Repository navigation
refactor(status): compose the status task graph in TypeScript #7904
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
c9f8d90
refactor(status): compose the status task graph in TypeScript
hhyykk 4fa58bf
fix(status): preserve delegated identities and large snapshots
huangruiteng 3dbf94a
Merge remote-tracking branch 'origin/main' into codex/repair-pr7904
hhyykk f78fe2d
fix(status): normalize approved handoff identities with the shared codec
hhyykk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
153 changes: 153 additions & 0 deletions
153
...cs/ledger/typescript-control-plane-migration-v0/2026-11-02-status-task-graph.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| # Status task-graph composition (2026-11-02) | ||
|
|
||
| ## Owner boundary | ||
|
|
||
| This checkpoint moves the complete optional status task-graph decision from Python | ||
| `work_items/task_graph.py` into the existing TypeScript `work_items/task_graph.ts`. | ||
| One `work_item.task_graph.status` operation owns selected work, claim display, | ||
| user-gate selection/count/cap/overflow, bounded predecessor traversal, run | ||
| selection and lineage joins, evidence, handoff, repair, deduplication, dangling | ||
| edge rejection, timestamps and completeness/limits. It calls existing topology, | ||
| Todo summary, classification and handoff owners in process. The standalone | ||
| `work_item.task_graph.topology` handler is retired; topology remains an internal | ||
| composition function used by status and its semantic tests. | ||
|
|
||
| Python supplies source-shaped status facts, latest-run facts and fallback time. | ||
| It retains public-text redaction/normalization facts. Status SHA-256 node/edge | ||
| identity materialization moves into the composer with byte-identical Unicode | ||
| and `None` encoding, so deduplication compares actual historical identities | ||
| rather than unevaluated descriptors. Goal-map uses the same native identity, | ||
| state and topology-row functions; the three Python rule helpers are deleted. | ||
| Source fields are restricted to existing Todo read fields and the consumed | ||
| status lanes. Derived display text uses the qualified composition-only | ||
| compaction boundary described below. There is no Python selection, traversal, gate, evidence, | ||
| handoff, lineage, repair or limit fallback. | ||
|
|
||
| `build_goal_task_map` retains its public signature and byte-identical output for | ||
| `chat_status_api.py`. It sends source/public-text facts to `projectGoalTaskMap`, | ||
| which now materializes node/edge identities, state and metadata. Native topology | ||
| fact requests retain their existing compatibility contract. Omitted opaque | ||
| metadata is not stringified; unsupported non-JSON public-text values are marked | ||
| unavailable at the codec edge and rejected only if consumed. Uncalled status | ||
| builders, attachers, source collectors, ref helpers and constants are deleted. | ||
| No new Python/TypeScript basename pair is added. | ||
|
|
||
| Physical product diff: +865/−1030, net −165 lines against the archived base. | ||
| `task_graph.py` falls from 1,044 to 255 lines: one module-level recursive public | ||
| text codec and two source/transport facades, with no graph decision rules. | ||
| Tests, fixtures and documentation are counted separately. | ||
|
|
||
| ## Public text and remaining duplication | ||
|
|
||
| Choice (a): there is no second TS redaction rule. Source strings must have | ||
| Python public-text facts; a missing fact throws. The local fallback only calls | ||
| `compactTodoReadText` on registered public fact outputs or explicitly composed | ||
| strings. Interpolated components are asserted to be registered public strings | ||
| or numeric counts. Native tests enumerate composed titles, identities, | ||
| references and reasons, and reject unqualified source text. Constructors are | ||
| claim/lease, evidence prefix and public evidence prefix-slice, handoff identity/ | ||
| title/reasons, missing-ID gate, gate overflow, latest-run title, repair defaults, | ||
| and joins of generated node identities. Fixed reason prose comes from native | ||
| graph construction; generated identities contain only ASCII identifier/hash | ||
| characters. Goal scope is already public-normalized by the status caller. | ||
| No `INTERNAL_STATE_SHAPE_PATTERNS` redaction copy remains in this module. | ||
|
|
||
| `rg` found no equivalent TS owner of Python `open_todo_items`: `read_codec.ts` | ||
| provides compaction/fields, `context_projection.ts` provides planning/display | ||
| sources, and `summary_lanes.ts` selects normalized summary lanes, not the | ||
| historical source-key, dedup-before-sort, bounded-open display selection. | ||
| Python still serves status attention/monitor projections, project-asset | ||
| readbacks and Todo summary renderers. `statusOpenItems` therefore retains that | ||
| bounded duplication. Exit: migrate those callers to one native Todo open-display | ||
| selection owner, qualify ordering/handoff/limit parity, then remove the Python | ||
| selection and delegate the graph to that owner. Do not substitute normalized | ||
| summary-lane selection with different admission semantics. | ||
|
|
||
| The codec caches repeated source strings and computes only field-used caps; | ||
| no source redaction facts are inferred from truncated text. Display caps and the | ||
| unsupported-text marker are local transport facts, not a new shared decision | ||
| vocabulary. Counts below include | ||
| the initial Goal public-text call; “before” means the reviewed encoder draft, | ||
| which called the public codec six times per source string (full safety plus | ||
| five display caps), not the original all-Python graph: | ||
|
|
||
| | Status case | Public-text calls before → after | | ||
| | --- | --- | | ||
| | `diamond_at_cap` | 127 → 32 | | ||
| | `cycle` | 79 → 22 | | ||
| | `missing_prerequisite` | 31 → 12 | | ||
| | `open_predecessor` | 79 → 24 | | ||
| | `condition_and_lineage` | 55 → 19 | | ||
| | `predecessor_overflow` | 193 → 47 | | ||
| | `duplicate_identity` | 97 → 19 | | ||
| | `long_public_text` | 61 → 21 | | ||
| | `redaction` | 61 → 21 | | ||
| | `handoff_evidence` | 73 → 21 | | ||
| | `unicode_ids` | 43 → 15 | | ||
| | `all_empty` | 1 → 1 | | ||
| | `gate_overflow` | 145 → 24 | | ||
| | `no_selected_run_gate` | 43 → 17 | | ||
| | `repair_evidence` | 79 → 29 | | ||
| | `stale_source_time` | 43 → 18 | | ||
| | `absent_goal` | 1 → 1 | | ||
| | `invalid_goal` | 1 → 1 | | ||
|
|
||
| Largest characterization request (`long_public_text`): compact JSON parameters | ||
| with the transport's ASCII escaping, 6,797 → 4,899 bytes (−27.9%); calls | ||
| 61 → 21 (−65.6%). These are parameter bytes, excluding RPC framing. The maximum | ||
| call case, predecessor overflow, falls from 193 to 47. This is codec/request | ||
| cost evidence, not an end-to-end latency or effectiveness claim. | ||
|
|
||
| ## Crossings and parity | ||
|
|
||
| Instrumentation counts every `effect_runtime_result` reached by the public | ||
| Python graph entrypoint, including Todo display/handoff helpers: | ||
|
|
||
| | Operation | Before → after | | ||
| | --- | --- | | ||
| | Selected work, including topology/error evidence cases | 4 → 1 | | ||
| | User-gate overflow | 7 → 1 | | ||
| | Run/gate nodes with no selected Todo | 4 → 1 | | ||
| | Valid Goal with all-empty facts and no graph | 0 → 1 | | ||
| | Absent or invalid Goal | 0 → 0 | | ||
| | Goal task map | 1 → 1 | | ||
|
|
||
| The empty valid snapshot is decided inside the native composer; only absent or | ||
| invalid Goals return before transport. A rejected native request has no Python | ||
| fallback. Large packets reuse the existing local snapshot transport. | ||
|
|
||
| The frozen synthetic characterization corpus was green on unchanged | ||
| `fb16c6cb1369efce52a673030c914b38e1dac166` (21 cases) before implementation; | ||
| expected JSON bytes remain unchanged. Independent native cases test semantics | ||
| rather than using that corpus as a specification. The status Markdown renderer | ||
| has no graph section. Real `status --include-task-graph` CLI output matches an | ||
| archived base byte-for-byte on isolated File and SQLite homes in JSON and | ||
| Markdown, with a fixed observation clock: respectively 33,417/33,445 and | ||
| 5,120/5,126 bytes. The actual chat `_goal_task_map` entrypoint, using the same | ||
| canonical File/SQLite sources, matches at 2,310 bytes on each provider. The three | ||
| already-pinned Goal-map cases were green on the archived base before refactoring; | ||
| the fixture expected outputs have not been edited. | ||
|
|
||
| ## Qualification and exit | ||
|
|
||
| Current rerun: Python 355 passed, 2 failed across the six requested suites and | ||
| all tests found by `rg build_goal_task_map / chat_status_api`; native graph/handler/ | ||
| loading tests 50 passed. Ruff (two changed Python files), control-plane typecheck, | ||
| task-graph fixture, attention queue, semantic vocabulary and maintainability | ||
| smokes, six CLI/chat parity comparisons and `git diff --check` passed. Earlier | ||
| interface-budget/integrated-canary evidence remains historical, not a new rerun. The quota planning-horizon suite retains two failures | ||
| (missing `planning_horizon`, File and SQLite), reproduced with the same tests | ||
| in an untouched `git archive HEAD` baseline copy; they are not reported as passes. | ||
| No gate, budget, vocabulary anchor or baseline is relaxed. | ||
|
|
||
| The Python status facade exits when status callers deliver the source/public | ||
| text facts directly to the native owner and the retained public-text codec has | ||
| an independently qualified native replacement. Remove its operation only when | ||
| those callers use an in-process owner. The same codec exit applies to | ||
| the Goal-map facade. The characterization corpus | ||
| can retire once facade removal has independent public-entrypoint coverage. | ||
|
|
||
| The adjacent cleanup removes the obsolete topology RPC and callback surface; | ||
| no unrelated refactor or product journey is introduced. Existing CLI, attention | ||
| queue, chat and review-packet consumers keep their public payloads. No end-to-end latency, | ||
| total resource-cost or long-horizon effectiveness/efficiency benefit is claimed. | ||
125 changes: 125 additions & 0 deletions
125
...ger/typescript-control-plane-migration-v0/2026-11-02-status-task-graph.zh-CN.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| # Status 任务图组合(2026-11-02) | ||
|
|
||
| ## Owner 边界 | ||
|
|
||
| 本检查点将可选 status 任务图的完整决策从 Python `work_items/task_graph.py` | ||
| 迁入现有 TypeScript `work_items/task_graph.ts`。单个 | ||
| `work_item.task_graph.status` 操作拥有所选工作、claim 展示、用户 gate | ||
| 选择/计数/上限/溢出、有界前驱遍历、run 选择与 lineage 连接、证据、handoff、 | ||
| repair、去重、悬空边拒绝、时间戳及完整性/限制。它在进程内组合现有 topology、 | ||
| Todo 摘要、分类和 handoff owner。独立的 `work_item.task_graph.topology` | ||
| handler 已退役;topology 作为内部组合函数保留,由 status 及其语义测试使用。 | ||
|
|
||
| Python 提供源形状的 status 事实、latest-run 事实和后备时间。它保留公开文本 | ||
| 脱敏/规范化事实。status 的 SHA-256 节点/边身份物化迁入组合器,Unicode 和 | ||
| `None` 编码逐字节一致,从而使用实际历史身份去重,而非尚未求值的 descriptor。 | ||
| Goal-map 也复用同一套原生身份、状态及 topology-row 函数;三个 Python 规则 helper 已删除。源字段限定为现有 Todo 读取字段及实际消费的 status lane。 | ||
| 派生展示文本使用下文限定的组合文本压缩边界。不存在 Python 的选择、遍历、 | ||
| gate、证据、handoff、lineage、repair 或限制后备决策。 | ||
|
|
||
| `build_goal_task_map` 保持公开签名及 `chat_status_api.py` 输出逐字节一致。 | ||
| 它向 `projectGoalTaskMap` 提交源数据/公开文本事实,由原生实现物化节点/边身份、 | ||
| 状态及元数据。现有原生 topology 事实请求保留兼容合同。被省略的 opaque 元数据 | ||
| 不会提前字符串化;非 JSON 公开文本值在 codec 边界标记为不可用,仅在消费时拒绝。 | ||
| 无调用方的 status builder、attacher、源收集器、ref helper 和常量已删除。 | ||
| 没有新增 Python/TypeScript 同名文件对。 | ||
|
|
||
| 相对归档基线,产品物理行差异为 +865/−1030,净 −165 行。 | ||
| `task_graph.py` 从 1,044 行降至 255 行:一个模块级递归公开文本 codec 和两个 | ||
| 源数据/传输 facade,不含任务图决策规则。测试、fixture 和文档单独计数。 | ||
|
|
||
| ## 公开文本与保留的重复规则 | ||
|
|
||
| 选择 (a):没有第二套 TS 脱敏规则。源字符串必须提供 Python 公开文本事实, | ||
| 缺少事实时抛错。本地 fallback 仅对已登记的公开事实输出或显式组合字符串调用 | ||
| `compactTodoReadText`。插值组件断言为已登记公开字符串或数字计数。原生测试枚举 | ||
| 组合标题、身份、引用及原因,并拒绝未限定的源字符串。构造器包括 claim/lease、 | ||
| evidence 前缀及公开证据的前缀切片、handoff 身份/标题/原因、缺失 ID 的 gate、 | ||
| gate 溢出、latest-run 标题、repair 默认文本和生成节点身份的连接。固定原因来自 | ||
| 原生图构造;生成身份仅含 ASCII 标识符/hash 字符。status 调用方已对 Goal scope | ||
| 做公开规范化。模块不再复制 `INTERNAL_STATE_SHAPE_PATTERNS` 脱敏规则。 | ||
|
|
||
| `rg` 未找到 Python `open_todo_items` 的等价 TS owner:`read_codec.ts` 提供 | ||
| 压缩/字段,`context_projection.ts` 提供规划/展示源,`summary_lanes.ts` 选择 | ||
| 规范化摘要 lane,不实现历史 source-key、先去重再排序、有界开放项展示选择。 | ||
| Python 仍服务 status attention/monitor、project-asset 读回及 Todo 摘要渲染。 | ||
| 因此 `statusOpenItems` 暂时保留这项有限重复。退出条件:这些调用方迁入统一的 | ||
| 原生 Todo open-display 选择 owner,验收排序/handoff/上限一致性,再删除 Python | ||
| 选择并让图委托同一 owner。不得用准入语义不同的摘要 lane 选择替代。 | ||
|
|
||
| codec 缓存重复源字符串,只计算字段实际使用的上限;不从截断文本推断源脱敏事实。展示上限和不支持文本标记仅是本地传输事实, | ||
| 不构成新的共享决策词汇。 | ||
| 下表包含初始 Goal 公开文本调用;“之前”指本次评审的 encoder 初稿,每个源字符串 | ||
| 调用六次(完整安全检查加五个展示上限),并非最初的全 Python 图: | ||
|
|
||
| | Status 用例 | 公开文本调用次数:之前 → 之后 | | ||
| | --- | --- | | ||
| | `diamond_at_cap` | 127 → 32 | | ||
| | `cycle` | 79 → 22 | | ||
| | `missing_prerequisite` | 31 → 12 | | ||
| | `open_predecessor` | 79 → 24 | | ||
| | `condition_and_lineage` | 55 → 19 | | ||
| | `predecessor_overflow` | 193 → 47 | | ||
| | `duplicate_identity` | 97 → 19 | | ||
| | `long_public_text` | 61 → 21 | | ||
| | `redaction` | 61 → 21 | | ||
| | `handoff_evidence` | 73 → 21 | | ||
| | `unicode_ids` | 43 → 15 | | ||
| | `all_empty` | 1 → 1 | | ||
| | `gate_overflow` | 145 → 24 | | ||
| | `no_selected_run_gate` | 43 → 17 | | ||
| | `repair_evidence` | 79 → 29 | | ||
| | `stale_source_time` | 43 → 18 | | ||
| | `absent_goal` | 1 → 1 | | ||
| | `invalid_goal` | 1 → 1 | | ||
|
|
||
| 最大刻画请求 `long_public_text` 使用传输层 ASCII 转义的紧凑 JSON 参数计量, | ||
| 6,797 → 4,899 字节(−27.9%),调用 61 → 21(−65.6%)。这些是参数字节, | ||
| 不含 RPC framing。最大调用用例 predecessor overflow 从 193 降至 47。 | ||
| 这是 codec/请求成本证据,不代表端到端延迟或效果收益。 | ||
|
|
||
| ## 跨运行时调用与一致性 | ||
|
|
||
| 插桩统计公开 Python 图入口触发的每次 `effect_runtime_result`,包括 Todo | ||
| 展示/handoff helper: | ||
|
|
||
| | 操作 | 迁移前 → 后 | | ||
| | --- | --- | | ||
| | 所选工作,包括 topology/错误证据情形 | 4 → 1 | | ||
| | 用户 gate 溢出 | 7 → 1 | | ||
| | 无所选 Todo、但有 run/gate 节点 | 4 → 1 | | ||
| | 有效 Goal、事实全空且无图 | 0 → 1 | | ||
| | 缺失或无效 Goal | 0 → 0 | | ||
| | Goal 任务地图 | 1 → 1 | | ||
|
|
||
| 有效空快照由原生组合器决策;只有缺失或无效 Goal 在传输前返回。原生请求拒绝后 | ||
| 没有 Python fallback。大请求复用现有本地快照传输。 | ||
|
|
||
| 冻结的合成刻画语料在实现前已于未修改的 | ||
| `fb16c6cb1369efce52a673030c914b38e1dac166` 通过(21 个用例);预期 JSON | ||
| 字节保持不变。独立原生用例验证语义,而不将刻画语料当作规范。status Markdown | ||
| 渲染器没有图专属章节。真实 `status --include-task-graph` CLI 在隔离的 File 和 | ||
| SQLite home 上,以固定观察时钟对比归档基线,JSON 和 Markdown 均逐字节相同: | ||
| 分别为 33,417/33,445 及 5,120/5,126 字节。实际 chat `_goal_task_map` | ||
| 入口使用相同的规范 File/SQLite 源,两者均逐字节一致,为 2,310 字节。三个已冻结的 | ||
| Goal-map 用例在重构前已于归档基线通过;fixture 预期输出未修改。 | ||
|
|
||
| ## 验收与退出 | ||
|
|
||
| 本次重跑:六个指定 Python 套件及 `rg build_goal_task_map / chat_status_api` | ||
| 找到的全部测试共 355 通过、2 失败;原生图/handler/loading 测试 50 通过。 | ||
| 两个变更 Python 文件的 Ruff、control-plane typecheck、任务图 fixture、attention | ||
| queue、语义词汇、可维护性 smoke、六项 CLI/chat 一致性和 `git diff --check` | ||
| 均通过。早先接口预算和集成 canary 证据仅保留为历史,不声称本次重跑。 | ||
| quota planning-horizon 套件仍有两项 | ||
| 失败(File 和 SQLite 缺少 `planning_horizon`),使用同样测试在未修改的 | ||
| `git archive HEAD` 基线副本中复现;不将其报告为通过。未放宽任何 gate、预算、 | ||
| 词汇锚点或基线。 | ||
|
|
||
| 当 status 调用方直接向原生 owner 提供源/公开文本事实,且保留的公开文本 codec | ||
| 已有独立验收的原生替代时,Python status facade 才可退出。只有这些调用方 | ||
| 改为进程内 owner 后,才移除其操作。Goal-map facade 使用相同的 codec 退出条件。facade 移除具备独立公开入口覆盖后,可退役刻画语料。 | ||
|
|
||
| 相邻清理移除了过时 topology RPC 和 callback 表面;没有引入无关重构或产品 | ||
| 旅程。现有 CLI、attention queue、chat 及 review-packet 消费方保持其公开 | ||
| payload。不声称端到端延迟、完整资源成本或长程效果/效率收益。 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[P2] TG-INSTALL / TG-COST:迁移前已接受的 RFC §6 对每个事务切换仍要求 fresh wheel/sdist 深层语义及匹配的默认 SQLite request/transaction/full-CLI p50/p95、idle/burst RSS。本 PR 明确排除安装/latency qualification;结构 crossing 数不能替代。在该 exact head 构建 wheel 与 sdist,分别装入全新隔离环境,从 packaged files 执行任务图正常、拒绝和恢复的深层语义探针并记录来源。按迁移前固定 base 与当前 head、同 fixture/环境,在默认 SQLite 测 cold/warm request、完整 transaction 与 CLI 的 p50/p95,以及 idle/burst daemon RSS;按既有阈值判定,File 单独披露。