Skip to content

refactor(goals): converge Vision wait projection in TypeScript - #7298

Open
hhyykk wants to merge 1 commit into
mainfrom
codex/control-plane-semantics-ts-20261025
Open

hhyykk wants to merge 1 commit into
mainfrom
codex/control-plane-semantics-ts-20261025

Conversation

@hhyykk

@hhyykk hhyykk commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Move Goal Vision wait-state assembly, blocker eligibility, causal Todo lineage, and resume-planning composition into one TypeScript effect: goal.vision_wait.project.
  • Keep Python as the source-snapshot codec, effect transport, result validator, and historical wait-state decoder.
  • Remove reason text from blocker eligibility. Typed task class, status, claim, exclusion, and causal lineage determine the wait state; reason text only appears in display output.
  • Update the TypeScript migration RFC in English and Chinese.

Measured results

  • Controlled build_quota_should_run path, 200 runs per arm: median 67.39 → 65.80 ms; P95 94.66 → 87.61 ms. Runtime crossings: 4 → 3.
  • Canonical File-backed CLI fixture, five repetitions: final quota should-run median 275.87 → 270.19 ms. The whole fixture flow held crossings at 4 → 4; the eligible wait projection uses one combined effect.
  • Final CLI JSON size: 25,729 bytes in both arms, about 6,433 estimated tokens. No payload growth.
  • Production loopx/ diff: +224 / −289 lines, net −65.

Validation

  • Exact-head npm run test:control-plane: 5,559 tests; 5,483 passed, 0 failed, 76 skipped because they require an isolated PostgreSQL server.
  • Vision wait and resume-planning TypeScript tests: 16 passed.
  • Vision wait and blocked-successor Python tests, including File-backed CLI cases: 82 passed.
  • Semantic architecture tests: 674 passed; semantic-vocabulary drift smoke passed.
  • npm run typecheck:control-plane, targeted ruff check, and the RFC bilingual diff check passed.
  • Diff scan found no secrets, tokens, or local absolute paths.

An earlier exact-head full run hit one Host heartbeat timing assertion. The isolated test passed on retry, and the subsequent full exact-head run passed with zero failures.

No PostgreSQL authority-store code changed. The 76 PostgreSQL-dependent cases remain skipped under their existing isolation requirement.

Signed-off-by: aihop <4408344+hhyykk@users.noreply.github.com>

@loopx-agent loopx-agent left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

结论:REQUEST_CHANGES。发现一个 P2:合法 blocker 的 selected_todo_priority 在新传输边界丢失;真实 CLI、wheel 和 sdist 均复现。

Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · reasoning_effort=max

审查版本:d8daa76e604f856efccdaf7b7887edc97ec8178d;完整 PR 基线:af68b0ff180ca8309b5d63d7ee326c77848521bb。以下结论来自本次独立本地验证,未查询、轮询或等待 GitHub CI。

动机

使用 Goal 持续推进任务的 Agent 和维护者,需要从等待状态判断当前阻塞项及其优先级。

同一名 Agent 的 P0 阻塞任务解释了当前目标缺口时,旧版等待投影保留 P0;新版仍识别该阻塞,却丢失输出中的优先级。

合并决策所有者的方向成立,但本次迁移尚未保住调用方可见字段,不能按语义等价交付。

本 PR 不负责重写存储后端、完成整体 TypeScript 迁移,或证明长期任务效率提升。

剩余缺口是把 blocker 的 priority 传过 Python→TypeScript 边界,并用真实 CLI 及安装包回归固定该字段。

原来 Python 决定哪些任务可以构成等待,再分别调用 TypeScript 的恢复规划和因果覆盖。后续改规则需要同时维护两处判断,重复读取也需要两次传输。这是一个真实维护边界,值得收敛;但迁移的价值需要保住原有输出,不能只用删除代码或测试数量证明。

改动思路

等待资格、因果覆盖和 payload 组装应复用现有 TypeScript 决策所有者;Python 只保留数据编解码和历史收据读取。

保留本次合并决策路径的边界;先修复 priority 丢失,不扩展到无关存储迁移或新增配置界面。

最强的反对理由是:旧实现已经携带完整优先级,换所有者会引入字段遗漏,而减少一次内部调用并不自动带来实际提速。更小的 Python 辅助函数仍保留分裂的决策所有者;新增服务或状态表则没有必要。当前设计复用 projectTodoResumePlanning 和 projectVisionWaitCoverage,生产代码净减 65 行,方向和规模相称。这里要求修正传输遗漏,不要求扩大重构。

真实入口的输入 基线 本 head
本 Agent 的 P0 blocker,带 reason 等待投影保留 P0 blocker 仍被识别,优先级键消失
同一合法 blocker,不写 reason 不形成 blocker 等待 按 canonical typed state 识别,属已披露修正
未来时间恢复的 deferred Todo 自动等待,保留恢复条件 相同
其他 Agent、无关因果 ID、独立可执行任务 不应继承当前等待 对照保持

表格说明的是已执行的输入对照。没有使用未渲染的图作为证据,也没有从一条等待收据推断长期效率提升。

具体改动

build_goal_vision_wait_state 现在只准备完整事实并发出 goal.vision_wait.project;handler 把它交给 projectGoalVisionWaitState。后者先检查缺口都是普通 Vision gap、没有独立可执行推进,再复用恢复规划、因果图和 witness 选择,最终在 waitStatePayload 中构造原有 schema。历史 exact-wait 解码器仍供收据读回使用,不构成第二个决策所有者。

[P2] 保留 blocker 的 priority。 loopx/control_plane/goals/goal_vision_wait.py:15 的字段白名单包含 id/class/status/claim/exclusion/reason,却没有 priority。下游 waitStatePayload 仍读取 selectedTodo.priority;读到 undefined 后转换成 null,再被输出过滤掉。因此同一 canonical P0 blocker 在基线有 selected_todo_priority: "P0",head 中该键不存在。最小修复是在白名单传递 priority,并添加真正经过 quota/status CLI 的字段存在性和值断言。不要只在 TS helper 中手填 priority 测试。

接受依据是 docs/architecture/rfcs/typescript-control-plane-migration-v0.md,固定于 af68b0ff180ca8309b5d63d7ee326c77848521bb,在阅读实现前检查。逐项判断:2.1 One TypeScript kernel、2.4 Replacement, not production dual-running、2.7 Legal domain values and deterministic decisions、2.8 Change locality as migration payoff 的本次边界有代码及调用证据;Caller-observable semantic parity is a promotion gate 未满足,缺口就是 priority 丢失。PR 自己修改的 ledger 不能替代旧合同。

语义与 CI:这是现有 effect vocabulary 的内部方法扩展,沿用既有 Todo/Goal 等待 schema;新增字段名白名单属于模块内 codec。没有用 reason 子串识别状态,也没有新增领域特定硬义务。默认行为确实改变:缺少 reason 的合法 blocker 现在按 typed state 生效,测试和双语 ledger 已披露。priority 丢失则不是这项修正的必要代价。must_attempt_work 等强制结果仍是机器语义,不能把它们称为可忽略建议。

对主干的风险

本次在不可变 base/head 上用同一 synthetic fixture 运行真实 canonical File、SQLite 和真实 effect runtime,七类输入共 14 个观察。除 evaluated_at 时钟外不归一化业务字段。带 reason 的 blocker 仍在两边得到 normal_run、must_attempt_work=true;因此这里只报告输出丢失,没有证明调度优先级改变或饥饿。未来 deferred 等待仍是 agent_scope_wait、不要求尝试执行;peer、无关因果和 runnable 对照未出现误覆盖。

两个焦点 Python 文件 82 项通过;完整 TS 套件 5559 项中 5484 通过、75 跳过、0 失败,不能把跳过算作执行通过。类型检查通过。标准 native premerge 的 6 项直接检查和 15 项选择检查全部通过,包含双语 RFC、语义 vocabulary 和公共边界。工作流范围 Ruff 有 5 个 E701/E702,逐条与基线核对均位于未修改的 tests/presentation/test_codex_attached_conversation.py;更宽的可选根扫描有 114 条相同诊断,二者范围不同,不混为一个结果。

正常构建最初因缺少生成的 Chat 资源失败;尝试复用资源时完整 source-input 校验正确拒绝了已变更的 TS kernel。我随后为精确 head 重新构建 Chat,再构建并隔离安装 wheel、sdist;没有改 manifest 或绕过校验。安装后的真实 CLI 在两种后端仍丢 priority,未来等待和 completed-reference 对照保持。所有测试都使用 disposable synthetic 状态,未改活动 Goal。

有限成本样本里,真实调用轨迹由两个传输方法变成一个,100 次 warm pure-call 中位数约 0.366→0.207ms;12 组交替的完整 SQLite CLI 中位数为 364.35→370.83ms、p95 为 594.42→548.31ms。共享主机样本没有显示明确端到端提速,也不证明冷启动、内存、File 性能、安装后的长期收益或模型采用。当前修复不改变存储权威,未据此声称 PostgreSQL 写路径资格。

我的整体评价

同意复用现有 TypeScript 所有者并删除 Python 重复决策,边界清楚、回退也可控。当前公开输出发生确定回归,所以需要先完成上面的最小修复再批准;不要求为这个修复新建框架、改存储或补齐整个路线图。typed-state 的 reason 修正可以保留,但应与意外 priority 丢失分开验收。

已检查 quota/status 的投影调用和本次全部 diff;没有修改渲染页面、布局或可见组件,视觉截图不适用。

未验证范围:Live installed host rendering was not exercised; this PR changes no rendered presentation. 未运行 live 模型、多主机长期任务或持续成本实验。没有新增用户确认轮次;真实可见读回仍需保持完整。评审、premerge 和字段修复都不构成合并授权。

English verdict: REQUEST_CHANGES for d8daa76e604f856efccdaf7b7887edc97ec8178d. The new Python blocker-row codec drops priority, so the existing selected_todo_priority field disappears from real File/SQLite CLI output and installed wheel/sdist builds. Preserve the field and add a public-entrypoint regression. The typed-state reason correction and consolidation into the existing TypeScript owner are otherwise justified; no scheduling starvation or sustained performance benefit is claimed.



def _vision_wait_blocker_rows(items: list[dict[str, Any]]) -> list[dict[str, Any]]:
fields = ("todo_id", "task_class", "status", "claimed_by", "excluded_agents", "reason")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

[P2] 保留 blocker 的 priority

当同一 Agent 的 canonical blocker 为 P0、带非空 reason 并覆盖当前 Vision gap 时,这个白名单丢弃了 priority。下游 waitStatePayload 仍读取 selectedTodo.priority,再把 null 字段移除,因此公开 quota/status 等待投影由 selected_todo_priority: P0 变为缺键。已在不可变 base/head 的真实 File、SQLite CLI,以及隔离 wheel、sdist 中复现;没有把 reason 的已披露 typed-state 修正当成问题。请传递 priority,并通过真实 CLI 断言字段存在及值。

The new blocker-row codec drops a canonical priority required by the existing public wait payload; preserve it and cover the ordinary CLI path.

This branch has not been deployed

No deployments
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.

2 participants