升级给维护者。 这条是 #9 挖出来的,涉及数据模型形状和一条已声明不变量的例外,所以不代裁。
一句话问题
按期率是这个产品的门面指标,而它在语义层里表达不出来。 判据是 completed_at <= due_date + duty.grace_days,需要「列 vs 列 + 日期加法」,而 $field 列比较被 driver-sql 拒(在内存求值器里却能过 —— 也就是开发环境能跑、生产 400),日期加法在过滤语法里根本不存在,且这里的偏移量本身还是一列。已报 objectstack#14104。
连带后果两个:
选项
| 方案 | 客户可感知的代价 |
|---|
| A | 完成时一次性盖章:hook 在任务转入 done 的那一刻,读 duty 的 grace_days,写一个 completed_late 布尔。指标读这个列。 | 宽限期真正生效。代价是核心对象上多一个字段,且看起来像违反规则 5 |
| B | v1 就承认没有宽限期:删掉 grace_days(两个对象 + #5 的抄写),「逾期」统一定义为过了到期日。 | 诚实、一致、更简单。但丢掉一个真实的合规概念,客户要问"能不能配宽限期" |
| C | 保留 grace_days 不动,数据集继续不出按期率,视图继续用近似值。 | 现状。两个界面含义不一致,且有一个填了没人读的字段 |
| D | 等平台修 #14104。 | M2 的验收门("管理者一屏回答什么迟了")卡住 |
四维分析
实际业务需求 — 宽限期在合规域是真实的:"5 号到期,10 号之前补报不算违规"是客户自己的制度。产品把这些人标成逾期,是在买方最在意的那个数字上和他的制度对着干。这条支持 A 或 B,反对 C。
长远合理性 — C 最差:一个填了没人读的字段一定会漂移,而且两个界面对同一个词给出不同答案,是那种没人会去查、直到审计时才炸的不一致。A 看起来违反规则 5("不要存能算出来的"),但规则 5 管的是需要持续维护的标志位——需要一个每天午夜跑的写入者,不跑的那天就说谎。completed_late 不是那种:它在完成的那一刻写一次,之后是不可变的历史事实,和旁边的 completed_at 同一类。visible_from(= 到期日 − 提前天数,派发时算一次存下来)已经是这个仓里的同款先例。
防 AI 写错 — A 要在规则 5 旁边写清楚例外的边界,否则下一个人会照着它去存一个真正会漂移的标志位。B 在这条上最干净:少一个概念就少一处能写错的地方。
创业阶段不扩散 — B 最省。A 是一个字段加 hook 的一条腿。D 不可控。
建议
A,并且在 AGENTS.md 规则 5 下面写明这条例外的判据:只在跃迁那一刻写一次、之后不可变的事实可以存;需要重算或需要定时写入者的一律不存。
如果你觉得宽限期在 v1 不值这个复杂度,B 也是干净的答案——但要连字段一起删掉,不能留着不读。C 是唯一不能选的:一个填了没人读的字段,加上两个界面对"逾期"给出不同答案。
本分析看不见什么:你的目标客户里真正会配非零宽限期的比例。如果试点客户基本都填 0,那 B 是对的,A 是为一个没人用的概念加字段。这一条我判断不了。
裁后执行
升级给维护者。 这条是 #9 挖出来的,涉及数据模型形状和一条已声明不变量的例外,所以不代裁。
一句话问题
按期率是这个产品的门面指标,而它在语义层里表达不出来。 判据是
completed_at <= due_date + duty.grace_days,需要「列 vs 列 + 日期加法」,而$field列比较被 driver-sql 拒(在内存求值器里却能过 —— 也就是开发环境能跑、生产 400),日期加法在过滤语法里根本不存在,且这里的偏移量本身还是一列。已报 objectstack#14104。连带后果两个:
grace_days现在是死元数据。 它在duly_catalog_item上被填写、被 Catalog instantiation — apply a position's duty catalog to a person #5 抄到duly_duty,然后没有任何东西读它——这个数据集是它唯一的预期消费者。grace_days— the view's definition of late disagrees with the product's #48)。数据集不出这个指标并写明原因;而「Late」列表视图静默用了due_date < 今天,忽略宽限期。客户配了 7 天宽限,第二天早上就被列成逾期。选项
done的那一刻,读 duty 的grace_days,写一个completed_late布尔。指标读这个列。grace_days(两个对象 + #5 的抄写),「逾期」统一定义为过了到期日。grace_days不动,数据集继续不出按期率,视图继续用近似值。四维分析
实际业务需求 — 宽限期在合规域是真实的:"5 号到期,10 号之前补报不算违规"是客户自己的制度。产品把这些人标成逾期,是在买方最在意的那个数字上和他的制度对着干。这条支持 A 或 B,反对 C。
长远合理性 — C 最差:一个填了没人读的字段一定会漂移,而且两个界面对同一个词给出不同答案,是那种没人会去查、直到审计时才炸的不一致。A 看起来违反规则 5("不要存能算出来的"),但规则 5 管的是需要持续维护的标志位——需要一个每天午夜跑的写入者,不跑的那天就说谎。
completed_late不是那种:它在完成的那一刻写一次,之后是不可变的历史事实,和旁边的completed_at同一类。visible_from(= 到期日 − 提前天数,派发时算一次存下来)已经是这个仓里的同款先例。防 AI 写错 — A 要在规则 5 旁边写清楚例外的边界,否则下一个人会照着它去存一个真正会漂移的标志位。B 在这条上最干净:少一个概念就少一处能写错的地方。
创业阶段不扩散 — B 最省。A 是一个字段加 hook 的一条腿。D 不可控。
建议
A,并且在
AGENTS.md规则 5 下面写明这条例外的判据:只在跃迁那一刻写一次、之后不可变的事实可以存;需要重算或需要定时写入者的一律不存。如果你觉得宽限期在 v1 不值这个复杂度,B 也是干净的答案——但要连字段一起删掉,不能留着不读。C 是唯一不能选的:一个填了没人读的字段,加上两个界面对"逾期"给出不同答案。
本分析看不见什么:你的目标客户里真正会配非零宽限期的比例。如果试点客户基本都填 0,那 B 是对的,A 是为一个没人用的概念加字段。这一条我判断不了。
裁后执行
src/objects/task.object.ts、src/hooks/task.hook.ts、src/datasets/duty-health.dataset.ts,并同批修 The "Late" task view marks late any task still open inside its duty'sgrace_days— the view's definition of late disagrees with the product's #48 的视图口径与AGENTS.md规则 5 的例外说明。grace_days— the view's definition of late disagrees with the product's #48 的视图口径统一。grace_days— the view's definition of late disagrees with the product's #48 都在同一批解决——两个界面对"逾期"必须给同一个答案。