refactor(todos): preserve complete work counts across bounded projections - #4713
Conversation
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewed head: 2a1094a5be2671c5d895343f8e58466849511654.
动机
本次评审结论为 APPROVE,无未解决的阻塞发现。对应 #4574 的 R5/S2、TS T3 与 shared-authority L5,是完整计数消费者的合理增量,不是默认 SQLite 或 D1–D3 完成声明。
旧实现把展示列表长度当成工作数量:21 条可执行任务在 backlog 中变成 8,quota 压缩后又变成 2。另一条旧路径反向猜测隐藏任务全部可执行:通过真实 todo list --thin,完整合成图的 37 条 advancement 被报成全部 80 条未终结任务。最终 File/SQLite 均回读 37。提高展示上限不能解决来源完整性,继续只改 Python 则保留两套 lane 规则。
改动思路
调用链保持在已有 Todo 领域:完整来源及同版本 acceptance/resume 事实 → TS 批量 lane 分类 → 原有 Agent 归属/排除/能力筛选 → 作用域内计数 → 展示裁剪。work_counts 是每次读取推导的结果,不是新的持久状态、手写声明或执行权限。它不能替代 claim、lease、writer fence 或 acceptance admission。
复用已有 quota selector、Unicode comparator 和 managed effect runtime。Python 保留旧格式、时间及展示坐标适配;返回的 ordinal 只指向同一批输入,回读检查范围。新 Python codec 只有一个调用方,因此收回原摘要模块,未新增长期同名 Python/TS 模块。原 Python lane 分类和隐藏任务推断被删除。
具体改动
共 24 个文件,+576/-192;其中生产代码 +226/-189,生产 Python +89/-188,净减少 99 行。其余是有界回归、类型检查纳入、读取契约、预算说明和双语 RFC checkpoint。
关键代码讲解
projectTodoSummaryLanes:先解码完整输入,拒绝 status/done 矛盾和缺失的完整 resume 求值。一次观察时间决定 Monitor due/expiry;satisfies Record<TodoSummaryLane, ...>检查 lane 表完整性,再返回原输入坐标。排序、稳定平局及 deferred/done 旧约定保留。countTodoWork:分类已观察到的行,不猜未取得的行。hidden表示来源缺失而非分页隐藏;complete=false时分类数量只是下界。已观察行数由open - hidden推导,避免重复字段。projectQuotaSelection:在原作用域筛选之后复用计数 owner;来源不完整时,重复投影即使缩小到一屏也不能升级为完整。全 Goal 计数不会冒充某 Agent 的计数。todo_summary_open_task_counts:现代摘要直接校验并消费计数,旧片段交给 typed projector 去重。错作用域和非法算术关系显式失败。Monitor-only 与 future-Monitor-only 两条消费路径都要求完整证据;完整的未来 Monitor 情况仍保持原判断。
list/status/thin/quota compactors保留该计数;canonical todo list 同时携带已有 acceptance guard,受阻记录可见但不能进入可执行集合。相关 CLI、原有 Chat HTTP 和安装包读取均已验证;无新的设置、布局或前端操作。
对主干的风险
最强反例是“摘要字段正确,但另一个消费者仍把缺失内容当作不存在”。审查实际找到了 future-Monitor helper 的漏项,先记录失败,再修复并覆盖重复投影及完整来源正例。另一个实际 canary 失败是 quota 输出增长:最初 14,014 字符超过原 14,000 上限。检查输出后删除冗余 observed-row 字段,保留有用的 scope/completeness;经 owner 明确要求按信息价值权衡,预算同步为 14,500 字符/360 嵌套键,最终样例为 13,988/351,顶层上限仍为 52。不同 lane 中相同 Todo 的重复有既有消费者,未用删字段的方式伪造兼容。
验证包括:551 项 File/SQLite/隔离 PostgreSQL 16.15 及相关规则测试,零 skip;完整 synthetic legacy/native 图和授权只读冻结图的 baseline/File/SQLite/PostgreSQL 对照;最终修复后的 49 项 Python Monitor/work-lane 回归,再加最终 codec/count 调整的 18 项 Python、13 项 TS;真实 CLI 缺失展示、安装 wheel 的 CLI/真实 Chat HTTP;Ruff、mypy、TS typecheck、文档、语义词汇及预算检查。最终 risk canary 19 项全部通过;初次预算和同名模块计数失败已修复并完整重跑。较早 provider suite 的 storage/transaction 源码未变,最终来源比较和安装读取已重跑。
性能:最终 head 上 64 组交错 CLI 对照,baseline/candidate p50 为 854.93/833.70 ms,p95 为 1390.54/1407.09 ms(+16.55 ms、+1.19%),在当前门槛内。完整暖摘要 p50 为 46.14/65.26 ms,增加约 19 ms;128 次暖 TS 批量请求 p95 为 1.50 ms,8 次隔离冷启动 p95 为 364.72 ms。常驻测试 daemon 短 burst RSS 约 237→232 MB,不能当作稳态内存或长期 soak 证明。这里不宣称性能提升。
语义与 CI 对齐
本次复用既有 task/status/Monitor 词汇,并明确增加派生计数读取合同;不是新 actor lifecycle。没有引入 prose/substring 分类规则,错误和义务仍为通用 Todo/source/scope 语义。完整性是机器执行的判定条件,不是建议。Acceptance 的 on/off 配对回归及全来源比较证明关闭时保留原选择行为;新增计数和其纠错效果是所有 provider 的显式变更。
评审 packet 为 policy revision 6,wait_for_ci=false:未查询、轮询或等待远端 CI。结论基于本地必需验证,不声明 CI 绿色。PR 创建后 main 新增的两条提交仅修改站点发布文案和其测试,未改变本 PR 的 runtime、依赖或调用方;本地验证绑定固定 merge-base,未混入无关提交。
我的整体评价
这是一条可独立验收、回滚的读取语义链,规模与复现问题相称;不是为了增加 TS 文件而搬运代码。完整角色/Agent 摘要在显式新增计数和动态观察时间之外保持语义一致;更正的计数、未知来源和 acceptance 行为分别有独立反例。所有 provider 的原 Todo/lease/head 及独立展示保持不变。
未来演进检查已应用:删除重复规则、收回单调用方模块、去掉可推导字段;跨 lane payload 去重留给有实际消费者迁移的后续边界。永久投影恢复、其余 event/executor caller、D2 容量/至少十天实际 soak、D3 整 Goal 切换、默认 onboarding 及旧 writer 退出仍由现有迁移计划承担。没有修改活跃 Goal 或启动 soak。本评审不授权合并,运行时 PR 留给维护者。
English verdict: APPROVE - 2a1094a. Complete scoped work counts replace clipped/guessed counts; canonical acceptance and incomplete-source consumers are aligned. Real File/SQLite/PostgreSQL, installed CLI/HTTP, baseline-sensitive regressions and all 19 final canaries pass. Remote CI was not consulted under the resolved policy; default cutover and soak remain separate.
2a1094a to
dfc359b
Compare
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
Signed-off-by: huangruiteng <14976749+huangruiteng@users.noreply.github.com>
dfc359b to
de272e1
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
Reviewed head: de272e102f9bad2f59afece37a87ccfd9618f13b.
动机
本次评审结论为 APPROVE,无未解决的阻塞发现。该改动落实 #4574 的 R5/S2、TS T3 与 shared-authority L5:让 Todo 执行语义使用完整来源的计数,而不是把展示裁剪结果当成工作总量。它不是 SQLite 默认切换、D1–D3 完成或长期 soak 声明。
旧路径会双向失真:21 条可执行任务经 backlog/quota 展示裁剪后可变成 8/2;另一条 legacy fallback 又会把完整合成图中实际 37 条 advancement 猜成全部 80 条未终结记录。提高展示上限不能证明来源完整,Python-only 修补也会继续保留第二套 lane 规则。
改动思路
调用链保持在现有 Todo 边界:完整来源和同版本 acceptance/resume 事实 → TS 批量 lane 分类 → 现有 Agent 归属、排除和能力筛选 → 作用域内计数 → 展示裁剪。work_counts 是读取时推导的结果,不是持久状态、手写声明或执行权限;它不替代 claim、lease、writer fence 或 acceptance admission。
实现复用已有 quota selector、Unicode comparator 和 managed effect runtime。TS 成为 lane/count 的单一规则 owner;Python 只保留旧格式、时间和展示坐标适配。返回 ordinal 只引用同一批输入并做范围校验;原 Python lane 分类、隐藏任务推断和单调用方适配模块被删除或收回现有 owner。
具体改动
全量 diff 为 29 个文件、+702/-216:生产代码 +226/-189,测试/fixture/验证辅助 +333/-26,文档 +143/-1。
projectTodoSummaryLanes一次解码完整输入,拒绝 status/done 矛盾和缺失的完整 resume 求值,以一次观察时间计算 Monitor due/expiry,并保持稳定顺序。countTodoWork只分类已观察行;complete=false时结果是下界,不猜未取得的行。projectQuotaSelection在既有 Agent scope 筛选后复用同一计数 owner;重复投影不能把不完整来源升级为完整,全 Goal 计数也不能冒充 Agent 计数。todo_summary_open_task_counts校验现代计数并适配 legacy fragments;错误 scope 和非法算术显式失败。Monitor-only 与 future-Monitor-only 消费者都要求完整证据。- list/status/thin/quota compactors 保留计数;canonical
todo list携带已有 acceptance guard,因此受阻记录仍可见但不会进入可执行集合。读取契约、双语 RFC checkpoint 和 interface budget 同步更新。
相对上一轮 review 的三个修复也已纳入当前 exact-head 审查:fixture 改用真实的 work_counts scope;CLI differential 只允许一次性的 none -> todo_work_counts_v0 加法 schema migration;_schema_migration_growth_allowance 从 _compare_row 抽离,使其从 96 降至 84 statements 并满足 maintainability ratchet。
对主干的风险
最强反例是“摘要字段正确,但某个消费者仍把缺失内容当作不存在”。此前审查实际发现 future-Monitor helper 漏项并补入负例;当前 head 又用 legacy/native/frozen 三套语料,对 File、SQLite 和隔离 PostgreSQL 与当前 main 基线进行比较,除新增计数和动态观察时间外,Todo 字段、排序、归属、lease、archive 与 provider head 均保持一致。
Exact-head 验证结果:Python focused 542 passed;TS control-plane 共 2057 项,2039 passed、0 failed、18 个条件性 skip;TS typecheck、16 个变更 Python 路径的 Ruff、22 个 source files 的 mypy、61 项 CLI differential、docs governance、semantic vocabulary、hot-path budget 和 maintainability 均通过。premerge 为 19/19 passed、0 failure、0 manual hold;change-quality receipt cqr_4887bb129ff5958d3767 为 valid/pass。新 wheel 的 File/SQLite CLI 与 Chat HTTP 均回读 advancement=37,且未改写状态。首次裸跑 npm test 使用系统 Python 3.9,因不支持 dataclass(slots=...) 失败;切换到 worktree Python 3.13 后完整套件通过,因此这是环境误跑而非产品失败。
接口预算实测为 13,988/14,500 字符、351/360 嵌套键、49/52 顶层键。性能作为非阻塞 advisory:TS batch p95 3.90 ms;CLI candidate p95 917.01 ms,对应当前 main 基线 857.49 ms;cold-start p95 307.74 ms。不宣称性能提升、稳态内存结果或长期 soak。
评审 packet 为 policy revision 7,wait_for_ci=false,因此按能力合同未轮询或等待远端 CI;本结论基于上述本地必需验证,不宣称 CI 绿色。语义使用既有 Todo/source/scope 词汇,不引入 substring/prose 分类;完整性是机器执行条件而非“建议”。新增计数是所有 provider 的明确行为修正,但不扩大 authority。
我的整体评价
这是一个完整、可回滚且与问题规模相称的读取语义切片。它把计数和 lane 决策收敛到 typed owner,删除重复 Python 规则,并通过真实入口、三类 provider、baseline-sensitive 反例和打包产物证明用户可观察结果。没有发现需要阻止合入的问题。
未来演进检查已应用:删除重复规则、收回单调用方模块、移除可推导字段,并抽取 differential migration helper。跨 lane payload 去重、永久投影恢复、其余 event/executor caller、D2 容量与至少十天实际 soak、D3 整 Goal 切换、默认 onboarding 和旧 writer 退出仍属于现有迁移计划,不应扩大本 PR。由于该 PR 修改 loopx/** 控制面/runtime 行为,仓库规则要求由另一位 maintainer 执行合并;本 review 不授予作者自合并权限。
English verdict: APPROVE - de272e1. Complete scoped work counts replace clipped or guessed counts, and the final fixes align fixture scope, permit only the declared additive output migration, and satisfy the maintainability ratchet. Exact-head Python, TypeScript, CLI differential, real-provider, installed-wheel, quality, and 19/19 premerge validation pass; remote CI was not consulted under the resolved policy. No blocking findings; merge remains on the non-author maintainer path.
huangruiteng
left a comment
There was a problem hiding this comment.
Approval conclusion (author-owned PR; GitHub blocks formal self-approval)
审阅对象:PR #4713(开放中,未合并),exact head dfc359b6afe3efbae165d97e621773f7f1dc6430(作者 huangruiteng)。本文是该 exact head 的评审记录。
动机
Todo 的"有多少活"这件事此前每个消费者各算一遍,而且算的是展示后的数据:一个完整来源里 21 个可执行推进任务,在 backlog 被裁到 8 条后报成 8,经过 quota payload compaction 再变成 2。更糟的是旧回退逻辑把"没看见的行"直接算成 advancement(advancement = 可见数 + hidden),于是不完整来源会被当成"还有很多可执行任务";反过来,monitor_only_schedule 与 scoped_monitor_watch_without_advancement 又可能凭一份残缺摘要认证"只剩 Monitor 工作",而这两个判断直接决定本回合要不要真正干活。根因很清楚:计数是展示预算的函数,且未知被当成已知。
改动思路
把 lane 选择与计数收到已有的 typed control-plane 边界里(todos/summary_lanes.ts):Python 只负责旧字段归一化、时间戳与展示适配,然后一次性把整批行交给 TS owner,拿回数组下标(而不是把同一条 Todo body 在每个 lane 里重复一遍)以及 todo_work_counts_v0。计数在裁剪之前产生,并带两个新事实:hidden(声明存在但没拿到、无法分类的行)与 complete(现有来源是否覆盖声明范围)。同时删掉 Python 里那两段重复的 lane 选择与"隐藏即 executable"的推断,让消费方(list / status / quota / work_lane / external evidence)共用同一份结果;complete=false 只能表达下界,不能再认证"只剩 Monitor"。之所以不选"把展示上限调大",是因为那根本治不了病:数字仍然是上限的函数。
具体改动
29 个文件、+684/-192。生产运行时 14 个文件:新增 127 行 typed owner,注册 todo.summary_lanes.project / todo.work_counts.project 两个 handler,todo_summary.py 里 161 行的 lane 选择与 resume 强制检查被替换成 37 行适配器,todo_semantics.todo_summary_open_task_counts 改为消费预裁剪计数(旧摘要走 todo.work_counts.project 得下界),并把 work_counts 作为保留字段穿过 thin / agent-lane / explicit-limit / quota payload 四个压缩器。测试与示例 6 个文件、公开文档 8 个(新增 docs/reference/todo-work-counts.md、TS 迁移账本、双语 RFC、以及 interface-budget 合约的预算调整说明)。
我做的验证:pytest tests/control_plane/test_todo_work_counts.py test_cli_output_differential.py test_goal_acceptance_runtime.py -q → 73 passed(其中直接断言 21 不会被裁成 8、也不会被压缩成 2;旧摘要给 advancement=0 且 complete=false);另外 13 个 summary/status/quota/work-lane 模块 → 92 passed;node --test tests/control_plane_ts/todo_summary_lanes.test.ts → 7 passed;全套 control-plane TS 在 head 为 2057 tests / 12 fail,在 PR base(42620170d)为 1990 / 17 fail,head 没有任何 base 上不存在的失败(那 12 个都靠 python3 子进程,本机 PATH 的 python3 是 3.9,tests/control_plane/test_fine_grained_turn_mode.py 的 CLI 用例在 base 同样失败,我复现过)。examples/control_plane/hot-path-interface-budget-smoke.py 通过。此外我逐条比对了新旧 lane 语义(due = actionable monitor 且未过期且 next_due_at <= now;schedule gap 再排除 watch-only 与已排期;blocker/resume-blocked/claimed 一致),并确认排序键仍是同一四元组、TS 用的 authorityUnicodeCompare 就是码点比较,与 Python 元组比较一致。
对主干的风险
这不是展示层微调:它改的是决定本回合要不要干活的那组数字,所以判断错会既安静又有后果。逐条评估后我认为风险已被覆盖:
- 语义面:新 owner 复现了全部 19 个 lane 的旧代数,删除的是重复实现而不是并行实现;
has_resume && !resume_evaluated仍然硬失败(原来的 Python 抛错被搬到 owner 里),status与done不一致、ordinal 越界都会 fail closed。 - 消费面:两个真正用计数做门禁的调用方(
work_lane.monitor_only_schedule、scoped_monitor_watch_without_advancement)都加了complete is True前置,方向只会更保守(只能拒绝"安静地不动",不会放行),这与 AGENTS.md 对机器强制语义的要求一致。 - 预算面:quota 的 JSON 上限从 14000 提到 14500 字符、嵌套键 350→360,理由是新增的完整性与作用域事实。我实测 base 为 13838/343、head 为 13988/351——即旧键上限 350 会被 head 的 351 打破,因此这次上调是被实测需要的;但字符余量只剩 512、键余量 9,属于"贴顶"位置,值得后续在别处膨胀时优先压重复 body 而不是继续抬上限(文档也已写明重复 lane body 需要配套调用方迁移才能删)。
- 一条边界观察,非阻塞:
_project_summary_lanes把status(以及resume_ready)原样送进只接受四个规范字面量的解码器,而旧 Python 路径是先normalize_todo_status的。仓内两个生产者(compact_todo_group经_structured_todo_group_items、goal_todo_projection经已归一化摘要)都会先归一化,且compact_evaluated_todo_group的 docstring 明确限定调用方来源,所以我按"绕过内部契约的调用方会响亮失败"记录,而不是按缺陷处理;若要加厚,按task_class的既有做法在适配器里归一化即可,不要放宽 TS 的字面量集合。 - 证据边界:账本里声明的隔离 PostgreSQL/已安装 wheel(CLI、Chat HTTP)读回与冻结全图快照,本轮没有复现;我验证的是 file/SQLite 投影路径、typed owner、公开预算与消费方测试面。
我的整体评价
结论 APPROVE。这是一次把"计数到底是什么"从展示实现里拿出来、放进类型边界并说清完整性语义的重构:净减 Python 代码(删掉两段重复推断),新增的是一个可单测、返回下标的批量 owner;旧摘要不会崩,只是降级为"下界"(complete=false),新字段不落盘、回滚无需迁移。既有的公开预算调整是同 diff 披露并带实测理由的,CLI 差异差分器也只给 none→v0 这个一次性迁移留了有界额度(320 字符 / 192 compact 字符 / 10 行),v0→v0 仍走普通预算——这是正确的收紧方式。合并仍归维护者;建议合并时顺手评估是否把适配器的 status 归一化补上,并在下一次其他字段膨胀时优先压缩重复 lane body。
语义与 CI 对齐
按契约记一条对齐结论:判定 extend_vocabulary(扩展既有词表/边界,而非新建并行分类)。受影响契约是 effect_runtime_handlers.ts 的两个新 handler、todos/summary_lanes.ts 新 owner、todo_summary.py/todo_semantics.py 的适配与计数消费、新增公开读契约 docs/reference/todo-work-counts.md(todo_work_counts_v0:open/advancement/monitor/hidden/complete/agent_id,并明确计数不授予任何权限),以及 interface-budget-contract.md 里 quota 上限的变更。CI 侧该 head 为 8 pass / 3 pending / 4 skipped、无失败;本轮的本地验证见上(Python 73+92、TS 7 及全套对比 base 无新增失败、hot-path 预算 smoke 通过)。需要转给后续的边界已由 PR 自己在账本里写明:T1/T2 调用方闭包、D1 投影恢复、D2 容量与长时间 soak、D3 受栅栏保护的整体切换。
English verdict: APPROVE - Review of open PR #4713 at exact head dfc359b (author-owned; recorded as a COMMENTED approval because GitHub blocks formal self-approval). The change fixes a real defect: Todo work counts were computed from display-limited fragments, so a complete source with 21 actionable advancement Todos was reported as 8 after backlog clipping and 2 after quota payload compaction, and a legacy fallback classified unseen rows as executable. Lane selection and counting now happen once in the typed control-plane owner (todos/summary_lanes.ts), which returns ordinals into the single input array plus a todo_work_counts_v0 envelope with hidden and complete; Python keeps normalization/timestamp/presentation adaptation, and the duplicated Python lane-selection and hidden-work inference loops are deleted. Consumers that gate scheduling (work_lane monitor_only_schedule, scoped_monitor_watch_without_advancement) now require complete=true, so an incomplete source can no longer certify monitor-only work. I verified 73 targeted Python tests and 92 consumer-module tests pass at the head, the new TS owner passes 7 tests, the full control-plane TS suite has zero failures that are absent at the PR base (the 12 remaining ones reproduce on main and are caused by this machine's PATH python3 being 3.9), the hot-path interface-budget smoke passes, and the lane algebra plus ordering match the removed Python implementation predicate by predicate. The disclosed quota interface-budget increase (14000 to 14500 chars, 350 to 360 nested keys) is justified by the measured growth (13838/343 at base to 13988/351 at head). Residual risk, non-blocking: the adapter forwards status and resume_ready unnormalized into a decoder that accepts only canonical literals, so a caller bypassing the canonical builder would fail loudly rather than degrade; and the ledger's isolated PostgreSQL and installed-wheel readbacks were not reproduced in this audit. No blocking finding. Merges remain with the maintainer.
Summary
A complete Todo source with 21 actionable advancement tasks was reported as 8 after backlog clipping, then 2 after quota payload compaction. A legacy fallback also guessed that unseen rows were executable. This PR moves summary lane selection into the existing typed Todo boundary and preserves source-complete, Agent-scoped work counts through list/status/quota consumers.
Related: #4574 (R5/S2), TS T3 and shared-authority L5. This is a justified read-consumer increment: permanent projection freshness/recovery, remaining event/executor callers, D2 capacity/elapsed soak, integrated D3 cutover and default onboarding remain with the existing migration program. No provider default or persisted Todo schema changes.
Changes
work_countsis derived before display limits and recalculated after Agent selection. Incomplete knowledge survives repeated projection and cannot certify Monitor-only or future-Monitor-only work. Legacy fragments deduplicate identity; conflicting fragments cannot prove completeness.todo listnow receives acceptance guards from the same read revision as its Todos, so held work remains visible but is not executable. Acceptance-off selection, deferred/completed conventions and claimant visibility are preserved.open - hidden) and keep the single-caller Python codec in the existing summary module. After inspecting repeated lane payloads, qualify quota headroom at 14,500 characters / 360 nested keys; final fixture is 13,988 / 351. No semantic fields were discarded to meet the former ceiling.Validation
96d98f3d4versus candidate on identical full graphs; role/scoped summaries preserve all existing fields except declared count changes and observation time. The old baseline fails 21→8, 21→2 and unknown→advancement counterexamples. Through realtodo list --thin, the old count consumer reports 80 instead of 37 for the synthetic graph; final File/SQLite consumers correctly report 37.The chosen summary contract is read-only; no live Goal promotion, writer fence changes, lease mutation or scheduled soak was performed. PostgreSQL deployment/tenant/restore qualification and the >=10-day elapsed soak are not established by these tests. The review policy disables remote CI consultation; local evidence is reported independently.
Frontend / visual evidence
UI impact: none. Existing frontend/Lark display rows and ordering are preserved; the added field serves count consumers. Installed package and actual HTTP readback cover the affected delivery path; no settings or layout changed.
Shared-authority RFC fixture impact
Reuse
coordination_production_scale_v0and its legacy/native generators: existing mixed roles, claims, Monitor schedules, blocked/completed/deferred/archive records already exercise this classification boundary. New assertions cover limits, scoped completeness and contradictory/missing input rather than introducing a second fixture. File/SQLite/real PostgreSQL arms plus the immutable baseline were exercised.Rollback and boundary
Revert this cohesive PR; no data migration is needed because
work_countsis not persisted. Older readers ignore the additive field and retain their former undercount limitation. This runtime PR is left for maintainer merge.