Skip to content

refactor(todo): migrate declarative decision metadata - #4292

Merged
huangruiteng merged 7 commits into
mainfrom
codex/todo-decision-scope-update
Sep 13, 2026
Merged

huangruiteng merged 7 commits into
mainfrom
codex/todo-decision-scope-update

Conversation

@huangruiteng

@huangruiteng huangruiteng commented Sep 12, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

This stacked follow-up closes the declarative decision-metadata part of the TypeScript control-plane migration. It is based on #4289 (codex/ts-authority-update) and keeps terminal/effect ownership and presentation/provider conformance in their existing RFC slices.

Semantic changes

  • Route decision_scope and required_decision_scopes through the typed native planning transaction.
  • Normalize compact and object forms to decision_scope_v0, preserve first-seen order, and deduplicate required scopes.
  • Enforce ownership: decision_scope is only for user_gate Todos; required scopes are only for Agent Todos.
  • Reject malformed, wrong-role, terminal-outcome, and scope-outcome writes atomically before any provider write or receipt.
  • Treat an explicit empty required-scope list as a clear.
  • Preserve omitted scope fields at the authoring boundary; an unrelated metadata correction no longer materializes null and erases a retained gate scope.
  • Preserve the existing scope_key grammar when compact keys contain : and keep legacy aggregate validation text for CLI callers.

Scope boundaries

  • No approval, lease, completion, promotion, or monitoring authority is added.
  • decision_outcome and decision_scope_outcomes remain effect-owned terminal state.
  • No frontend surface changed: the existing CLI/backend contract is the affected entry point, and no configuration editor owns these Todo fields.

Validation

  • Control-plane TypeScript typecheck: passed.
  • Full TypeScript control-plane suite with a real isolated PostgreSQL authority provider: 1,493/1,493 passed, 0 skipped.
  • Focused Python Todo/planning/projection/mutation/CLI-validation suite: 147 passed.
  • mypy for the changed canonical update-intent module: passed.
  • Shared-goal authority mutation suite: 54/54 killed, including role-guard and deduplication mutants.
  • Public/private boundary scan: 0 errors across all 14 changed files.
  • Read-only local loopx-meta status and two real dry-run Todo updates: normalized decision metadata, state unchanged, contract errors 0.
  • Change-quality receipt cqr_1ac69c15d5a66e52f009 is valid for the exact base and diff.
  • loopx canary premerge --from-git-diff: 18/18 checks passed, 0 failures, 0 manual holds.

Commits

  • ac4898b46 refactor(todo): centralize decision metadata planning
  • be443a96d test(todo): expand decision metadata conformance
  • ae76b81c0 docs(rfc): record decision metadata migration checkpoint
  • 9b7e5ff95 fix(todo): preserve aggregate scope validation errors
  • 4f53fba4a fix(todo): preserve scoped decision-key syntax

@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

Reviewed exact head 4f53fba4ab52d7fce6729715dc2e975b25190359 (base codex/ts-authority-update, exact base head b8345f13b0d81158d836fed5dc371cd08171f39b).

动机

本 PR 闭合 TypeScript control-plane migration 中声明式 decision metadata 的一段:将 decision_scope 与 required_decision_scopes 纳入 typed Todo planning transaction,同时保持 decision_outcome、decision_scope_outcomes 等 terminal/effect-owned 状态不越界。它还修复了 public authoring planner 把省略的 scope 物化为 null、从而擦除 retained user-gate scope 的问题。

改动思路

新增 decision_metadata.ts 作为唯一的归一化与角色校验 owner:compact kind:granularity:scope_key 和 object 形式统一为 decision_scope_v0,验证安全 key、schema、可选 decision id,并对 Agent 的 required scopes 按首次出现顺序去重。public_update.ts 与 native_update_plan.ts 复用这个 codec,再交给既有的 authoring/field planner 和 provider CAS;decision_scope.ts 改为复用同一套 kind/granularity/key grammar。scope intent 仅在字段显式出现时进入 authoring boundary,因此 omission 与 explicit clear 保持不同语义。

具体改动

  • loopx/control_plane/todos/decision_metadata.ts:增加 typed scope schema、compact/object parser、safe-key/id 校验、required-scope dedup,以及 user-gate/Agent role guard。
  • native_update_plan.ts:把两个声明式字段加入 planning allowlist 和 normalization;terminal decision fields 仍被拒绝。
  • public_update.ts:保留 scope 字段的省略语义,避免无关 metadata edit 清除 retained gate scope;继续复用既有 wait、authoring 和 field rules。
  • decision_scope.ts:删除重复的 scope kind/key 常量,改用共享 codec 常量,保持 read-only coverage/relation 行为。
  • 测试、production-scale fixture、两个 targeted mutants 以及中英文 RFC checkpoint 覆盖正向、错误 role、非法 token、重复、显式空 clear、omission preservation 和 effect boundary。

对主干的风险

我未发现阻塞性问题。精确 head 上,3 个 Python intent 测试、37 个 Python scope/lifecycle/CLI-validation 测试和 36 个 TypeScript focused/provider 测试均通过;control-plane TypeScript typecheck 通过;两个 decision-metadata mutants 均由断言击杀。基线 b8345f13b0d81158d836fed5dc371cd08171f39b 的既有 planning/provider 测试也保持通过。远端检查为 23 个成功、4 个跳过,唯一失败是 packet 标记为 non-blocking 的 SonarCloud Code Analysis。

本次没有 frontend、CLI installer、quota 或 scheduler surface 变化,也没有新增 approval、lease、completion、promotion 或 monitor authority。剩余风险是未来新增 metadata 字段时 Python canonical-intent allowlist、TypeScript codec 和 read-only consumer 可能不同步;当前 shared codec、conformance fixture 与 mutation controls 已把这个边界显式化。

我的整体评价

这是一个边界清晰、规模合适的迁移切片:新增模块只承载 decision metadata 的共享类型规则,事务、回执、生命周期和 effect ownership 仍由原 owner 负责。显式空值、字段省略和错误角色均有独立验证,RFC 也明确记录了不授予的权限。建议按该精确 head 合入;后续添加决策元数据时继续同步三处 allowlist/consumer 并保留负向 mutation 覆盖。

English verdict: APPROVE — no blocking finding on exact head 4f53fba4ab52d7fce6729715dc2e975b25190359; focused tests, typecheck, and remote required checks are green (SonarCloud is non-blocking).

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

审阅对象:PR #4292,exact head 4f53fba4ab52d7fce6729715dc2e975b25190359(stacked base b8345f13b0d81158d836fed5dc371cd08171f39b)。本次仅对该 exact head 相对其 base 的完整增量做独立 policy-v3 review,不继承旧 head 结论。

动机

本 PR 闭合 Todo TypeScript control-plane migration 中的 declarative decision metadata seam:让 user_gate 的 decision_scope 与 Agent Todo 的 required_decision_scopes 进入同一个 typed planning transaction,同时保持终态 decision_outcome、​decision_scope_outcomes 的 effect-owned 边界。此前 promoted canonical caller 没有这一组 native planning 字段,Python contract、TypeScript planner 与只读 scope relation 之间容易发生漂移;无关 note 修正还可能把省略字段物化成 null。当前改动新增 decision_metadata codec、planner 组合、production-scale conformance fixture、双语 RFC 说明与 focused tests,目标和范围匹配。

改动思路

update_goal_todo 先把 CLI 输入送入现有 build_canonical_update_intent,promoted Todo 再经过 normalizeNativePlanningIntent、planNativeTodoUpdate、planPublicTodoUpdate 与 planTodoFieldUpdate。新增 decision_metadata.ts 负责统一 scope kind/granularity/key 语法、compact token 解码、对象字段白名单、列表去重和 role ownership 检查;public planner 只把显式 scope 字段送入 authoring-scope plan,省略值保持 omitted。这样 decision metadata 与已有 work/ownership fields 一起在一次 provider CAS/receipt 事务中落盘,但没有把 approval、lease、completion 或 standing authority 搬入 planning。

正向路径是 user_gate 写入一个归一化 scope,或 agent Todo 写入 deduplicated required scopes;负向路径是 malformed key、错误 role、terminal outcome 或 scope field 注入,在 provider commit 前失败。现有 decision_scope.ts/contract.py 仍是读取和兼容边界,PR 没有创建第二套 relation 规则。

具体改动

关键代码讲解

  1. loopx/control_plane/todos/decision_metadata.ts:46 新增 normalizeTodoDecisionScope,接受 compact kind:granularity:scope_key 或对象形式,统一小写、限制公开 kind/granularity/key,并只保留 v0 支持字段。
  2. decision_metadata.ts:84 的 normalizeTodoRequiredDecisionScopes 支持分隔列表,按 kind/granularity/scope_key identity 保持首次出现顺序并去重;显式空数组保留为 clear。
  3. loopx/control_plane/todos/public_update.ts:55 将 decision metadata 归一化后再走 public/field planner,并改为 presence-based scopeIntent,因此 unrelated metadata edit 不会擦除 retained scope。
  4. loopx/control_plane/todos/native_update_plan.ts:26 扩展 FIELDS 但仍显式拒绝 decision_outcome 与 decision_scope_outcomes;​tests/control_plane_ts/decision_metadata.test.ts、production-scale fixture 和 RFC 中英文段落覆盖正负路径、角色约束、重复项、清除与边界说明。

对主干的风险

总体没有发现阻塞该增量的 P0/P1 问题。新增 codec 在 exact head 上由 86 个 focused Python tests、77 个 native TypeScript tests、ruff、diff-check 与 clean stacked merge-tree 支撑;remote checks 为 23 success、4 skipped,另一个 non-blocking Sonar workflow 通过。GitHub 的 SonarCloud Code Analysis 汇总项仍为 failure,建议合入前确认其质量门含义,但 merge-gate 已通过且该项未表现为此次增量的运行时失败。

[P2] task_class 降级时应校验 effective record(非阻塞建议)

新增 validateTodoDecisionMetadata 只在 intent 显式包含 decision_scope 时检查 role/task_class。如果一个已有 decision_scope 的 user_gate 同时把 task_class 改成 user_action(例如显式 global_gate:false)却省略 decision_scope,planner 会保留旧 scope,形成非 gate record 带 gate metadata 的状态。当前只读 standing/gate consumer 仍按 task_class 过滤,因此影响主要是投影一致性和未来消费者;建议在 task_class 离开 user_gate 时原子清除 retained scope,或要求显式 clear,并补一个 transition regression test。

此外,PR 的 stacked base #4289 当前有一个独立的 single-agent ownership admission blocker;本次结论仅针对 #4292 相对该 base 的增量,待 base 修复后应按 exact head 重新确认整条栈。

我的整体评价

该增量把 decision_scope 的规范化、role ownership、列表去重与 omitted/explicit-clear 语义放回现有 typed planning owner,复用了 Python compatibility contract、public/field planner 和只读 relation/standing consumers,代码量合理且测试覆盖完整。P2 的 effective-state 清理建议不影响本增量当前 APPROVE,但在后续 task-class transition 扩展前应补齐,以避免新的 role contract 只验证 requested intent 而未验证最终记录。

English verdict: APPROVE — exact head 4f53fba4ab52d7fce6729715dc2e975b25190359 correctly adds typed decision_scope/required_decision_scopes planning, preserves omission and explicit clears, deduplicates scopes, and keeps terminal outcomes effect-owned. Focused Python (86) and TypeScript (77) tests plus remote build/test checks pass; SonarCloud Code Analysis remains a non-blocking CI failure. One non-blocking P2 follow-up is to clear or reject retained decision_scope when task_class leaves user_gate.

@huangruiteng
huangruiteng force-pushed the codex/ts-authority-update branch 2 times, most recently from f3936c3 to bebab16 Compare September 13, 2026 12:10
Base automatically changed from codex/ts-authority-update to main September 13, 2026 12:23
@huangruiteng
huangruiteng force-pushed the codex/todo-decision-scope-update branch from 4f53fba to ce6c2e4 Compare September 13, 2026 13:40

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

审阅对象:PR #4292,exact head ce6c2e4e122484a3d71d406bec244c267d9d67e0,base main,base head df5e014b4777ad4def79c5970d15e60e140d7fa2。本轮先将原 stacked branch rebase 到当前主干,解决了与已合入 journal/presentation 变更的冲突,再对 rebase 后完整 14-file 增量重新审阅;旧 head 的结论不继承。

动机

本 PR 闭合 TypeScript control-plane migration 中声明式 decision metadata 的 typed seam:让 user gate 的 decision_scope 与 Agent Todo 的 required_decision_scopes 进入既有 planning transaction,同时把 decision_outcome、decision_scope_outcomes 留在 terminal/effect-owned 路径。此前 promoted caller 没有统一的字段 owner,public planner 的 scope omission 可能被物化为 null,scope grammar、角色约束和只读 consumer 也容易漂移。

旧 review 指出的 P2 也已在本轮 refine:已有 user_gate 带非空 scope 时,如果把 task_class 改成 user_action 却省略 scope,旧实现会保留一个对最终记录无效的治理字段。现在要求显式 decision_scope: null,既不改变“省略即保留”的通用协议,也不允许无声携带失效 scope。

改动思路

入口仍是 loopx.todos.update_goal_todo:Python compatibility builder 只把显式请求送入 native planning;todo_update.ts 从完整 canonical head 读取 Todo,调用 normalizeNativePlanningIntent 与 planNativeTodoUpdate,后者复用 planPublicTodoUpdate 和现有 field/authoring planners,最后由 AuthorityStore 的 CAS/receipt 事务落盘。public effect-runtime 入口同样复用 public planner。

decision_metadata.ts 是唯一的 scope schema/normalization owner:compact kind:granularity:scope_key 和 object 形式归一化为 decision_scope_v0,校验公开 kind、granularity、safe key 和可选 Todo id,并按 kind/granularity/key identity 对 required scopes 保持首次出现顺序去重。validateTodoDecisionMetadata 只做 role/effective-task-class 校验,不发放权限。字段省略只在显式出现时进入 authoring boundary;显式空列表或 null 才是 clear。terminal outcome、lease、completion、monitor effect、scheduler/quota 和 provider retry 仍由原 owner 负责。

正向路径是 user gate 写入规范化 scope,或 Agent Todo 写入去重后的 required scopes,随后一次 provider CAS 产生可 replay 的 receipt。负向路径是 malformed key/schema、错误 role、terminal outcome 注入,或 retained scope 跨 task-class 的隐式迁移;这些都在 provider write 前 fail closed。

具体改动

关键代码讲解

  1. loopx/control_plane/todos/decision_metadata.ts:46 的 normalizeTodoDecisionScope 接受 compact/object 两种输入,统一大小写和空白,限制 schema 字段与安全 key,并保留 : 作为 scope-key 的合法字符;:117 的 validateTodoDecisionMetadata 同时验证 role ownership 与最终 task-class 组合。
  2. decision_metadata.ts:84 的 normalizeTodoRequiredDecisionScopes 以稳定 identity 去重而不改首次出现顺序;空数组保留为显式清除,而不是被当作 omission。该模块是纯规则,无 storage、lease 或 effect side effect。
  3. loopx/control_plane/todos/public_update.ts:58-74 将两类 scope 送入共享 codec,并以 presence-based scopeIntent 调用既有 authoring scope;因此 unrelated note/text edit 不会擦掉 retained gate scope。native_update_plan.ts:28-75 扩展 typed allowlist,但仍拒绝 terminal outcome 和 monitor/completion effects。
  4. decision_scope.ts:6-28 改为复用同一 kind/granularity/key 常量;Python update_intent.py 只作为兼容边界 allowlist。测试/fixture/RFC 覆盖 compact/object、重复、非法输入、错误角色、explicit clear、omission preservation、provider replay 和本轮 task-class transition regression。

对主干的风险

我未发现阻塞性问题。rebase 后 exact diff 为 14 files、+389/-15,merge-base 与当前 origin/main 一致;新增模块有真实 production callers(CLI promoted update、effect-runtime public planner、coordination transaction 和 read-only relation consumer),不是 test-only scaffolding。变化集中在 Todo planning metadata,未扩大到前端、安装器、scheduler、quota 或 release policy。

验证结果:npm run typecheck:control-plane 通过;本地 npm run test:control-plane 为 1462 tests、1461 passed、0 failed、1 个明确的 PostgreSQL placeholder skip;隔离 PostgreSQL 16.15 实例的 npm run test:postgresql-authority-store 为 90/90 passed;focused Python update-intent 为 3 passed;ruff、py_compile 与 git diff --check 通过。远端 DCO、dependency-review、build、kernel-static-checks、四个 test shard、Stage2C(含 mutants/correctness)、Windows、Node minimum/forward、dashboard acceptance、pytest、checks 和 merge-gate 均为 pass;presentation、release upload/deploy 为路径性 skip;Sonar 使用仓库标记的 non-blocking workflow,仍在收尾。

最重要的负向验证是新回归:若 retained user-gate scope 随 task_class 降为 user_action 而未显式 clear,typed planner 现在在 CAS 前拒绝;若显式传 decision_scope:null,同一 metadata update 才会通过。旧 review 的 P2 因此已修复。全局 loopx check 的 public-boundary 子扫描为 clean,但该命令同时报告了 registry 中与本 PR 无关的既有错误/警告;它们不构成此次代码 finding,也未被写入仓库。

我的整体评价

这是一个边界清晰且与 migration 目标匹配的切片:共享 codec 解决跨语言/跨入口漂移,public/native planner 复用现有状态规则,provider CAS/receipt 和 terminal ownership 没有被复制。rebase 删除了已在主干的 stacked 内容,最终 14-file scope 可审阅;本轮只增加一个 11-line effective-state guard 和 focused regression,直接闭合旧 P2。唯一兼容注意点是调用方在离开带 scope 的 user gate 时必须明确清除,这属于可诊断、可回滚的显式协议要求。change-quality receipt cqr_c804d37ad6a47d287c8b 已记录并验证为 valid/pass,覆盖 exact fingerprint c804d37ad6a47d287c8b2ce250ec44159d934327fc69df163d324503c7992e7f。

English verdict: APPROVE — exact head ce6c2e4e122484a3d71d406bec244c267d9d67e0 is rebased onto main, the prior retained-scope P2 is fixed with an explicit-clear regression, required CI and real PostgreSQL validation pass, and no blocking finding remains.

@huangruiteng
huangruiteng force-pushed the codex/todo-decision-scope-update branch from ce6c2e4 to fe5903a Compare September 13, 2026 13:56

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

审阅对象:PR #4292,exact head fe5903a0e20b37e4049deb6e3a052cfaab6d4750,base main,base head f4d7c9dd906994a1adc96a6cf6ed3e8fc7a95d90。本轮先将原 stacked branch rebase 到当前主干,解决了与已合入 journal/presentation 变更的冲突;主干随后又前进一次,因此再次 rebase 并对最新完整 14-file 增量重新审阅,旧 head 的结论不继承。

动机

本 PR 闭合 TypeScript control-plane migration 中声明式 decision metadata 的 typed seam:让 user gate 的 decision_scope 与 Agent Todo 的 required_decision_scopes 进入既有 planning transaction,同时把 decision_outcome、decision_scope_outcomes 留在 terminal/effect-owned 路径。此前 promoted caller 没有统一的字段 owner,public planner 的 scope omission 可能被物化为 null,scope grammar、角色约束和只读 consumer 也容易漂移。

旧 review 指出的 P2 也已在本轮 refine:已有 user_gate 带非空 scope 时,如果把 task_class 改成 user_action 却省略 scope,旧实现会保留一个对最终记录无效的治理字段。现在要求显式 decision_scope: null,既不改变“省略即保留”的通用协议,也不允许无声携带失效 scope。

改动思路

入口仍是 loopx.todos.update_goal_todo:Python compatibility builder 只把显式请求送入 native planning;todo_update.ts 从完整 canonical head 读取 Todo,调用 normalizeNativePlanningIntent 与 planNativeTodoUpdate,后者复用 planPublicTodoUpdate 和现有 field/authoring planners,最后由 AuthorityStore 的 CAS/receipt 事务落盘。public effect-runtime 入口同样复用 public planner。

decision_metadata.ts 是唯一的 scope schema/normalization owner:compact kind:granularity:scope_key 和 object 形式归一化为 decision_scope_v0,校验公开 kind、granularity、safe key 和可选 Todo id,并按 kind/granularity/key identity 对 required scopes 保持首次出现顺序去重。validateTodoDecisionMetadata 只做 role/effective-task-class 校验,不发放权限。字段省略只在显式出现时进入 authoring boundary;显式空列表或 null 才是 clear。terminal outcome、lease、completion、monitor effect、scheduler/quota 和 provider retry 仍由原 owner 负责。

正向路径是 user gate 写入规范化 scope,或 Agent Todo 写入去重后的 required scopes,随后一次 provider CAS 产生可 replay 的 receipt。负向路径是 malformed key/schema、错误 role、terminal outcome 注入,或 retained scope 跨 task-class 的隐式迁移;这些都在 provider write 前 fail closed。

具体改动

关键代码讲解

  1. loopx/control_plane/todos/decision_metadata.ts:46 的 normalizeTodoDecisionScope 接受 compact/object 两种输入,统一大小写和空白,限制 schema 字段与安全 key,并保留 : 作为 scope-key 的合法字符;:117 的 validateTodoDecisionMetadata 同时验证 role ownership 与最终 task-class 组合。
  2. decision_metadata.ts:84 的 normalizeTodoRequiredDecisionScopes 以稳定 identity 去重而不改首次出现顺序;空数组保留为显式清除,而不是被当作 omission。该模块是纯规则,无 storage、lease 或 effect side effect。
  3. loopx/control_plane/todos/public_update.ts:58-74 将两类 scope 送入共享 codec,并以 presence-based scopeIntent 调用既有 authoring scope;因此 unrelated note/text edit 不会擦掉 retained gate scope。native_update_plan.ts:28-75 扩展 typed allowlist,但仍拒绝 terminal outcome 和 monitor/completion effects。
  4. decision_scope.ts:6-28 改为复用同一 kind/granularity/key 常量;Python update_intent.py 只作为兼容边界 allowlist。测试/fixture/RFC 覆盖 compact/object、重复、非法输入、错误角色、explicit clear、omission preservation、provider replay 和本轮 task-class transition regression。

对主干的风险

我未发现阻塞性问题。rebase 后 exact diff 为 14 files、+389/-15,merge-base 与当前 origin/main 一致;新增模块有真实 production callers(CLI promoted update、effect-runtime public planner、coordination transaction 和 read-only relation consumer),不是 test-only scaffolding。变化集中在 Todo planning metadata,未扩大到前端、安装器、scheduler、quota 或 release policy。

验证结果:npm run typecheck:control-plane 通过;本地 npm run test:control-plane 为 1462 tests、1461 passed、0 failed、1 个明确的 PostgreSQL placeholder skip;隔离 PostgreSQL 16.15 实例的 npm run test:postgresql-authority-store 为 90/90 passed;focused Python update-intent 为 3 passed;ruff、py_compile 与 git diff --check 通过。远端 DCO、dependency-review、build、kernel-static-checks、四个 test shard、Stage2C(含 mutants/correctness)、Windows、Node minimum/forward、dashboard acceptance、pytest、checks 和 merge-gate 均为 pass;presentation、release upload/deploy 为路径性 skip;Sonar 使用仓库标记的 non-blocking workflow,仍在收尾。

最重要的负向验证是新回归:若 retained user-gate scope 随 task_class 降为 user_action 而未显式 clear,typed planner 现在在 CAS 前拒绝;若显式传 decision_scope:null,同一 metadata update 才会通过。旧 review 的 P2 因此已修复。全局 loopx check 的 public-boundary 子扫描为 clean,但该命令同时报告了 registry 中与本 PR 无关的既有错误/警告;它们不构成此次代码 finding,也未被写入仓库。

我的整体评价

这是一个边界清晰且与 migration 目标匹配的切片:共享 codec 解决跨语言/跨入口漂移,public/native planner 复用现有状态规则,provider CAS/receipt 和 terminal ownership 没有被复制。两次 rebase 都删除了已在主干的 stacked 内容,最新 14-file scope 可审阅;本轮只增加一个 11-line effective-state guard 和 focused regression,直接闭合旧 P2。唯一兼容注意点是调用方在离开带 scope 的 user gate 时必须明确清除,这属于可诊断、可回滚的显式协议要求。change-quality receipt cqr_30007239b5ac3f15c761 已记录并验证为 valid/pass,覆盖 exact fingerprint 30007239b5ac3f15c761010079566c027e163f40d16180bf4ba6dd44cd6ef8e0。

English verdict: APPROVE — exact head fe5903a0e20b37e4049deb6e3a052cfaab6d4750 is rebased onto the latest main, the prior retained-scope P2 is fixed with an explicit-clear regression, required CI and real PostgreSQL validation pass, and no blocking finding remains.

@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Pre-merge validation update for exact head fe5903a0e20b37e4049deb6e3a052cfaab6d4750 (base f4d7c9dd906994a1adc96a6cf6ed3e8fc7a95d90).

  • Changed surfaces: TypeScript todo decision metadata/scope planning and public update projection, the Python update-intent bridge, conformance tests/fixture, and the bilingual migration RFC.
  • Focused loopx canary premerge --tier quick passed: diff hygiene, changed-Python compile, maintainability ratchet, scoped user-gate, and operator-gate resume smokes; no manual holds or tracked side effects.
  • The standard canary also ran 18 selected checks. 16 passed. Two catalog checks failed on the existing main-tree loopx.capabilities.cross_runtime legacy-module assertion (the same failure in the bounded-context namespace smoke and its catalog-run wrapper); neither changed surface imports or modifies that namespace. The focused gate is green and the PR-specific full validations remain green.
  • PR-specific validation: TypeScript typecheck; 1,462 control-plane tests (1,461 passed, 1 intentional placeholder skipped, 0 failed); PostgreSQL authority-store integration 90/90 against disposable PostgreSQL 16.15; Python intent tests 3/3; Ruff, py_compile, and diff checks passed. Required GitHub checks are still running; release/presentation/deploy checks are path-based skips. No private-boundary findings in changed files.
  • Change-quality receipt cqr_30007239b5ac3f15c761 is valid for this exact base/head and scope fingerprint 30007239b5ac3f15c761010079566c027e163f40d16180bf4ba6dd44cd6ef8e0.

Decision remains conditional on the required GitHub checks completing successfully and exact-head merge readiness.

@huangruiteng

Copy link
Copy Markdown
Collaborator Author

Pre-merge validation update for exact head fe5903a0e20b37e4049deb6e3a052cfaab6d4750 (base f4d7c9dd906994a1adc96a6cf6ed3e8fc7a95d90).

  • Changed surfaces: TypeScript todo decision metadata/scope planning and public update projection, the Python update-intent bridge, conformance tests/fixture, and the bilingual migration RFC.
  • Focused loopx canary premerge --tier quick passed: diff hygiene, changed-Python compile, maintainability ratchet, scoped user-gate, and operator-gate resume smokes; no manual holds or tracked side effects.
  • The standard canary also ran 18 selected checks. 16 passed. Two catalog checks failed on the existing main-tree loopx.capabilities.cross_runtime legacy-module assertion (the same failure in the bounded-context namespace smoke and its catalog-run wrapper); neither changed surface imports or modifies that namespace. The focused gate is green and the PR-specific full validations remain green.
  • PR-specific validation: TypeScript typecheck; 1,462 control-plane tests (1,461 passed, 1 intentional placeholder skipped, 0 failed); PostgreSQL authority-store integration 90/90 against disposable PostgreSQL 16.15; Python intent tests 3/3; Ruff, py_compile, and diff checks passed. All required GitHub checks and merge-gate passed; release/presentation/deploy checks are path-based skips. No private-boundary findings in changed files.
  • The separate SonarCloud Code Analysis app check is the only red status. Its non-blocking workflow job passed; the app quality gate reported D Reliability Rating on New Code and four warnings in the new TypeScript module (two false-positive Todo token detections plus two sort/localeCompare suggestions). This is advisory/non-blocking and is recorded rather than hidden.
  • Change-quality receipt cqr_30007239b5ac3f15c761 is valid for this exact base/head and scope fingerprint 30007239b5ac3f15c761010079566c027e163f40d16180bf4ba6dd44cd6ef8e0.

Decision: required CI, focused canary, quality receipt, and exact-head review are complete; admin-bypass squash merge is authorized with the advisory SonarCloud result explicitly disclosed above.

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>
@huangruiteng
huangruiteng force-pushed the codex/todo-decision-scope-update branch from 790ec4b to 97c6770 Compare September 13, 2026 14:21

@huangruiteng huangruiteng left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approval conclusion (author-owned PR; GitHub blocks formal self-approval)

审阅对象:PR #4292,exact head 97c67707db27fc2f2b8ca481cc6d001bbd6d8af6,base main,base head 6d3377ae28975293102a1996c9a893c929926b5e。本轮先将原 stacked branch rebase 到当前主干,解决了与已合入 journal/presentation 变更的冲突;主干随后又前进,因此再次 rebase,并在最新完整 14-file 增量上完成 refine 与重新审阅,旧 head 的结论不继承。

动机

本 PR 闭合 TypeScript control-plane migration 中声明式 decision metadata 的 typed seam:让 user gate 的 decision_scope 与 Agent Todo 的 required_decision_scopes 进入既有 planning transaction,同时把 decision_outcome、decision_scope_outcomes 留在 terminal/effect-owned 路径。此前 promoted caller 没有统一的字段 owner,public planner 的 scope omission 可能被物化为 null,scope grammar、角色约束和只读 consumer 也容易漂移。

旧 review 指出的 P2 也已在本轮 refine:已有 user_gate 带非空 scope 时,如果把 task_class 改成 user_action 却省略 scope,旧实现会保留一个对最终记录无效的治理字段。现在要求显式 decision_scope: null,既不改变“省略即保留”的通用协议,也不允许无声携带失效 scope。

改动思路

入口仍是 loopx.todos.update_goal_todo:Python compatibility builder 只把显式请求送入 native planning;todo_update.ts 从完整 canonical head 读取 Todo,调用 normalizeNativePlanningIntent 与 planNativeTodoUpdate,后者复用 planPublicTodoUpdate 和现有 field/authoring planners,最后由 AuthorityStore 的 CAS/receipt 事务落盘。public effect-runtime 入口同样复用 public planner。

decision_metadata.ts 是唯一的 scope schema/normalization owner:compact kind:granularity:scope_key 和 object 形式归一化为 decision_scope_v0,校验公开 kind、granularity、safe key 和可选 Todo id,并按 kind/granularity/key identity 对 required scopes 保持首次出现顺序去重。validateTodoDecisionMetadata 只做 role/effective-task-class 校验,不发放权限。字段省略只在显式出现时进入 authoring boundary;显式空列表或 null 才是 clear。terminal outcome、lease、completion、monitor effect、scheduler/quota 和 provider retry 仍由原 owner 负责。

正向路径是 user gate 写入规范化 scope,或 Agent Todo 写入去重后的 required scopes,随后一次 provider CAS 产生可 replay 的 receipt。负向路径是 malformed key/schema、错误 role、terminal outcome 注入,或 retained scope 跨 task-class 的隐式迁移;这些都在 provider write 前 fail closed。

具体改动

关键代码讲解

  1. loopx/control_plane/todos/decision_metadata.ts:46 的 normalizeTodoDecisionScope 接受 compact/object 两种输入,统一大小写和空白,限制 schema 字段与安全 key,并保留 : 作为 scope-key 的合法字符;:117 的 validateTodoDecisionMetadata 同时验证 role ownership 与最终 task-class 组合。
  2. decision_metadata.ts:84 的 normalizeTodoRequiredDecisionScopes 以稳定 identity 去重而不改首次出现顺序;空数组保留为显式清除,而不是被当作 omission。该模块是纯规则,无 storage、lease 或 effect side effect。
  3. loopx/control_plane/todos/public_update.ts:58-74 将两类 scope 送入共享 codec,并以 presence-based scopeIntent 调用既有 authoring scope;因此 unrelated note/text edit 不会擦掉 retained gate scope。native_update_plan.ts:28-75 扩展 typed allowlist,但仍拒绝 terminal outcome 和 monitor/completion effects。
  4. decision_scope.ts:6-28 改为复用同一 kind/granularity/key 常量;Python update_intent.py 只作为兼容边界 allowlist。测试/fixture/RFC 覆盖 compact/object、重复、非法输入、错误角色、explicit clear、omission preservation、provider replay 和本轮 task-class transition regression。

对主干的风险

我未发现阻塞性问题。rebase 后 exact diff 为 14 files、+389/-15,merge-base 与当前 origin/main 一致;新增模块有真实 production callers(CLI promoted update、effect-runtime public planner、coordination transaction 和 read-only relation consumer),不是 test-only scaffolding。变化集中在 Todo planning metadata,未扩大到前端、安装器、scheduler、quota 或 release policy。

验证结果:npm run typecheck:control-plane 通过;本地 npm run test:control-plane 为 1462 tests、1461 passed、0 failed、1 个明确的 PostgreSQL placeholder skip;隔离 PostgreSQL 16.15 实例的 npm run test:postgresql-authority-store 为 90/90 passed;focused Python update-intent 为 3 passed;ruff、py_compile 与 git diff --check 通过。远端 DCO、dependency-review、build、kernel-static-checks、四个 test shard、Stage2C(含 mutants/correctness)、Windows、Node minimum/forward、dashboard acceptance、pytest、checks、merge-gate 和 SonarCloud Code Analysis 均为 pass;presentation、release upload/deploy 为路径性 skip。

最重要的负向验证是新回归:若 retained user-gate scope 随 task_class 降为 user_action 而未显式 clear,typed planner 现在在 CAS 前拒绝;若显式传 decision_scope:null,同一 metadata update 才会通过。旧 review 的 P2 因此已修复。全局 loopx check 的 public-boundary 子扫描为 clean,但该命令同时报告了 registry 中与本 PR 无关的既有错误/警告;它们不构成此次代码 finding,也未被写入仓库。

我的整体评价

这是一个边界清晰且与 migration 目标匹配的切片:共享 codec 解决跨语言/跨入口漂移,public/native planner 复用现有状态规则,provider CAS/receipt 和 terminal ownership 没有被复制。多次 rebase 都删除了已在主干的 stacked 内容,最新 14-file scope 可审阅;refine 增加一个 11-line effective-state guard 和 focused regression,并把未知字段排序改为明确的 localeCompare,同时消除 Sonar 对文案的误报,直接闭合旧 P2。唯一兼容注意点是调用方在离开带 scope 的 user gate 时必须明确清除,这属于可诊断、可回滚的显式协议要求。change-quality receipt cqr_d341d0c7c9122c2e2d03 已记录并验证为 valid/pass,覆盖 exact fingerprint d341d0c7c9122c2e2d035118e46d29dabab9c79161c3b317f52ded9870708856。

English verdict: APPROVE — exact head 97c67707db27fc2f2b8ca481cc6d001bbd6d8af6 is rebased onto the latest main, the prior retained-scope P2 and Sonar quality findings are addressed, required CI and real PostgreSQL validation pass, and no blocking finding remains.

@huangruiteng
huangruiteng merged commit ba6ba1b into main Sep 13, 2026
28 checks passed
@huangruiteng
huangruiteng deleted the codex/todo-decision-scope-update branch September 13, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant