fix(heartbeat): share automation-first Goal execution contract - #4201
Conversation
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
复审绑定 exact head:5605159a76f79dac455fcf9bf1f4cc77afe0610a。
动机
这组改动要解决的核心问题是真实的:native Goal 不应在持久 prompt 里复制一份会过期的 refresh/spend 配方,而应先取得稳定的 Turn identity,再消费当前 interaction_contract 和 typed settlement plan。Todo acceptance 与 Turn settlement 分离、失败后按同一 identity 恢复,也都是正确方向。
关于这次暴露出的 turn-instance-id 摩擦,需要把两件事分开:当前 Codex App heartbeat prompt 已经明确写了 LOOPX_TURN=<current_time_iso>; reuse,quota guard 也已经带 --turn-instance-id。我此前第一次执行仍漏传,是代理遵循 prompt 的失误,不是 #4201 缺少这条说明。#4201 真正修复的是另一条路径:codex_cli / managed native Goal 没有 App 外部注入的 Turn id;base 会直接暴露未绑定的 refresh/spend,head 会先投影带稳定占位符的 quota re-entry。这个 exact-head 行为我用真实 CLI fixture 验证通过。
改动思路
整体架构方向成立:quota 继续拥有 selection、Turn re-entry 和 settlement 顺序;host prompt 只负责长期不变量;MCP 负责 validate/complete/writeback/spend 的同一事务,并用 receipt readback 做 lost-response recovery。successor_todo_ids 复用现有 Todo 语义,没有引入第二套状态机。
不过,“移走会变化的命令”不能连同静态安全边界一起移走;“新增 v2 wrapper”也必须在真实 Codex automation 存储形态上可采用;release-only live runner 则必须把模型子进程限制在最小环境授权内。当前 head 在这三处还没有闭环。
具体改动
确认有效的部分:
- native Goal 首次 quota read 在缺少 Turn identity 时,只返回一次 re-entry;重入后 identity 绑定为当前 Goal/agent/Todo/Turn,并投影
validation -> durable_writeback -> quota_spend -> terminal_closeout。 - Goal Mode MCP 先验证并接受 Todo,再完成 writeback/spend;丢失 lifecycle、writeback 或 spend 响应后,同一意图重试不会重复扣 quota。
- release runner 默认不开模型;独立 ledger oracle、成功 transaction 校验和 timeout 清理均有覆盖。
需要修复的阻塞项:
-
[P1] native Goal prompt 丢失静态安全与修复路由。
loopx/control_plane/heartbeat/task_body.py:550-576把动态 settlement 配方移出后,也移除了 credential、destructive git、unauthorized production、repo rules,以及 lifecycle/registry 与 projection drift 的 owner 路由。相同输入下,base 有这些约束,head 没有;我又读取了 head 的真实 quota packet,动态 contract 也没有补回。Continue allowed work within authority不是这些具体边界的语义等价替代。请只把 volatile selection/settlement 移到interaction_contract,保留静态 safety/routing,并增加 base/head semantic-ledger + live quota packet 回归。 -
[P1] v2 prompt upgrade 无法作用于当前受支持的 Codex heartbeat。
loopx/control_plane/heartbeat/automation_upgrade.py:158-179要求 manifest 与 SQLite backing row 的kind都逐字等于heartbeat。真实 Codex App heartbeat 的逻辑 manifest 是heartbeat,底层 scheduler row 是cron;只读automation-prompts plan因而直接返回only existing heartbeat automations are supported,连desired_prompt都生成不了。也就是说,这个 PR 虽提供了 v2 wrapper,当前 thin-trial automation 仍无法 preview/adopt,用户感知到的摩擦仍在。请把“逻辑 heartbeat -> backing cron”建模为经过验证的 host mapping,同时继续拒绝真正的 standalone cron;用真实 schema 形状补回归。 -
[P1] release-live runner 把无关宿主凭据与过宽能力带进模型子进程。
scripts/qualify-claude-goal-release.py:65-80复制几乎全部os.environ,映射 provider key 后仍保留原始ARK_API_KEY和任意无关 token;随后又给 ClaudeBash。scripts/qualify-native-goal-release.py:164-168还显式使用shell_environment_policy.inherit="all"、完整环境和 network。使用纯合成 sentinel 的安全探针已确认原始 source key 与无关 secret 都会进入 child;未读取或输出真实凭据。请改成严格 allowlist,映射后删除 raw source key,隔离 HOME/config/runtime,去掉inherit="all",并用 negative sentinel tests 证明无关 TOKEN/AUTH/SOCK 不会下传。
对主干的风险
这三个问题都会在“单元测试全绿”的情况下穿过:prompt 测试当前甚至显式断言旧修复路由不存在;upgrade 测试只构造 heartbeat/heartbeat,而非真实 heartbeat/cron;runner 测试只排除了 Anthropic/Claude 前缀,没有排除任意宿主秘密。前两项会让实际 automation 仍然摩擦或以更弱边界运行,第三项涉及 live model child 的 credential/authority 扩散。
此外,GitHub 上 21 项检查成功,但 SonarCloud Code Analysis 仍失败(new-code coverage 6.9%,security rating C)。我的三个阻塞项都由独立本地反例复现,不依赖 Sonar 推断。
我的整体评价
结论是 REQUEST CHANGES。我完整阅读了 31 个文件、+1287/-215 的 patch,并在该 exact head 上跑过 prompt、quota、MCP、host、release-runner 相关测试:231 passed;Ruff 与 git diff --check 通过。没有运行付费/真实模型调用。
这不是要推翻该 PR 的架构:Turn-id re-entry 和 typed settlement owner 复用是正确且已验证的。范围虽然大,但四个 commit 仍围绕同一 host-contract/release-qualification 原因,修复上述三个相邻边界即可在当前 PR 内保持可审阅;不需要再引入新的通用框架。修复后请用新 exact head 重新跑:静态 prompt/动态 packet 语义对照、真实 automation plan、child-env negative sentinel,以及现有 231 项回归。
English verdict: REQUEST_CHANGES — the native Turn re-entry and typed settlement design are sound, but static safety semantics, real Codex heartbeat adoption, and live-runner credential isolation must be fixed on a new exact head.
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
复审绑定 exact head:5605159a76f79dac455fcf9bf1f4cc77afe0610a。
动机
这个 PR 解决的主问题成立:native Goal 不应长期保存一份会随控制面演进而过期的 refresh/spend 配方,而应进入当前 interaction_contract,让 quota 继续拥有 selection、Turn re-entry、settlement 顺序和 receipt recovery。Todo acceptance 与 Turn settlement 分离、MCP 复用既有 successor,以及 release-only 真实 host 回归,方向也都合理。
但我需要更正上一次评审里对 Turn ID 摩擦的判断。我之前说“prompt 已明确给出 LOOPX_TURN=<current_time_iso>,第一次漏传主要是 agent 执行失误”,这不够准确。信息虽然存在,却没有形成可直接执行且被真实 shell 回归约束的 bootstrap;这正是 capability/host contract 应该吸收、而不是继续交给模型临场拼装的摩擦。
改动思路
整体架构仍应保留:heartbeat envelope 提供本次 current_time_iso,quota 把它绑定成 exact Turn identity,并在成功 re-entry 后投影完整的 settlement_plan.ordered_steps;host prompt 只保留一条可靠入口和不会随控制面漂移的安全边界。Codex App heartbeat、native Goal 与 Claude /loop 可以共享这套 decision owner,但不能混同 scheduler ownership、host completion 或 child-process authority。
当前 exact head 已正确修复 native Codex CLI/Ark 的 unbound settlement:先返回一个 --turn-instance-id re-entry,绑定后才暴露 validation → writeback → spend → terminal closeout。问题是当前 Codex App thin path仍停在“给模型一段半结构化 shell recipe”,同时另三个已确认的边界问题也仍存在。
具体改动
关键代码讲解
visible_goal_turn_reentry_action把 native Goal 的无 Turn 状态从“错误地暴露 refresh/spend”改成一次 typed re-entry;真实 CLI fixture 证明绑定后 Goal/Agent/Todo/Turn 与 settlement 顺序正确,这是本 PR 的核心正向价值。GoalModeMCPControlPlane.complete_task新增successor_todo_ids,复用现有 Todo 关系;普通 Todo 可先被验证/接受,MCP 再按同一 identity 完成 writeback/spend,lost response 走 receipt readback,而不是重复记账。_render_goal_task_body删除静态 refresh/spend 是正确的,但同时删掉了 credentials、destructive git、unauthorized production、repo rules,以及loopx-project/loopx-self-repair路由;这些不是动态 quota contract 的重复知识。automation_upgrade._read能识别 v1/v2 wrapper 文本,但仍要求 manifest 和 backing row 的kind都等于heartbeat;当前受支持的 Codex 形态是逻辑 manifest=heartbeat、scheduler row=cron,所以 v2 连 preview 都进不去。host_environment与 native release runner 的inherit="all"把真实 host 环境带给 Bash/network-capable model child;合成 sentinel 已证明 raw source key 和无关 token 都会下传。
新增的 Turn ID 阻塞项是:render_thin_heartbeat_task_body 在 base 与 head 都输出 LOOPX_TURN=<current_time_iso>; reuse.,下一行 guard 再读取 ${LOOPX_TURN:?}。如果 agent 很自然地合并成 LOOPX_TURN=<iso> loopx ... "${LOOPX_TURN:?}",zsh 会在 command-prefix assignment 生效前展开参数,稳定退出 LOOPX_TURN: parameter not set。先独立赋值再执行才成功。现有测试只断言两个字符串存在,因此 81 个 focused tests 全绿也捕获不了这个真实失败。
对主干的风险
当前有四个 P1 阻塞:
- thin heartbeat 的 Turn bootstrap 仍不可直接执行。 首次 quota guard 可能在 LoopX 收到请求前失败,无 guard receipt、无 typed recovery,心跳会白跑。最小修复是生成明确的两步赋值/导出,或直接把 trigger ISO 作为 literal 绑定;测试必须替换固定 ISO 后在支持的 shell 中真正执行,并用 command-prefix mutation 证明会失败。
- native Goal 丢失静态安全/修复路由。 只迁移 volatile selection/settlement,不应迁移或删除 repo/user authority 与 credential/destructive-operation 边界;需要 base/head semantic ledger 加真实 quota packet 对照。
- v2 upgrade 不支持真实 heartbeat→cron backing mapping。 应显式建模这一 host mapping,同时继续拒绝真正 standalone cron;fixture 不能再只造 heartbeat/heartbeat。
- release-live child 环境授权过宽。 改为严格 allowlist,映射 provider key 后删除 raw source key,隔离 HOME/config/runtime,移除
inherit="all";用 TOKEN/AUTH/SOCK 合成负例验证。
此外 exact head 当前落后于 main;GitHub 21 项检查成功,但 SonarCloud Code Analysis 仍失败。我的验证包括:81 个 prompt/upgrade/native-release/Claude/MCP focused tests 通过,Ruff 与 git diff --check 通过;base/head prompt 对照、真实 zsh 反例、真实 supported automation kind mapping 和合成 child-env sentinel 均复现上述问题。没有运行付费模型。
我的整体评价
结论仍是 REQUEST CHANGES,并新增 Turn bootstrap 这一独立阻塞。我不是否定 automation-first / typed settlement 的架构;相反,native Goal re-entry 与 acceptance/settlement 分离已经证明有价值。问题在于当前 PR 宣称共享 thin automation dispatch,却仍把最先发生、最容易阻断整个 contract 的 Turn 绑定留给模型自行正确拼 shell。
这四项都属于本 PR 已触及的最近 owner:task body、automation adapter、release runner;可在现有范围内修复,不需要再加新框架。修复后请用新 exact head 重新跑四类 mutation-sensitive 证据:Turn recipe 真执行、静态 safety ledger、heartbeat/cron upgrade、child env allowlist,然后再复审整个 PR。
English verdict: REQUEST_CHANGES — exact head 5605159a76f79dac455fcf9bf1f4cc77afe0610a has a sound typed re-entry/settlement direction, but the thin App Turn bootstrap is still shell-fragile, and static safety, real heartbeat adoption, and release-child credential isolation remain blocking.
|
Re-evaluated the findings against both the automation baseline and the native Goal path. A local refinement is prepared; it has not been pushed yet, so this is not a resolution claim for the current head.
Validation of the local follow-up: 274 focused Python tests passed; final overlapping prompt/host and runner-isolation reruns passed 138 and 23 tests respectively; 60 TypeScript interaction/settlement tests passed; full heartbeat-prompt smoke and diff hygiene passed. Coverage includes real CLI guards, real SQLite migration/recovery, real stdio MCP, Bash/zsh mutation controls, subprocess environment sentinels and a no-model real Codex configuration/features probe. No live-model qualification was claimed or performed for this refinement. No active Goal, automation or installed runtime was changed. Product/architecture judgment: preserve static authority while keeping changing execution decisions in the live contract. The related refactor consolidates safety/repair text and removes duplicated or ambiguous instructions; it adds no new capability, provider or permission. The separate vision-closeout qualification remains necessary before claiming release readiness. |
Signed-off-by: Green hats <183933879+Green-hats@users.noreply.github.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
5605159 to
258d380
Compare
|
The refinement described above is now pushed as The static-semantics review exposed a real regression: native Goal still needs authority/privacy safeguards and conditional lifecycle/repair routing. These now share the automation rules, without restoring ambiguous project-branch bans, executor-facing prompt-maintenance advice, or duplicate static refresh/spend recipes. Independent work must remain admitted by the current contract; this does not authorize bypassing a global gate. The shell bootstrap now uses separate assignment and guarded-command statements with stable retry identity. Release runners isolate configuration and allowlist child environments. I did not accept blanket heartbeat/cron equivalence: inconsistent stores still require App reconciliation rather than inferred thread binding or scheduler conversion. Validation on the rebased head: 274 Python tests passed, 60 TS tests passed without skips, full heartbeat-prompt smoke, focused Ruff and diff hygiene. Coverage includes real CLI re-entry/settlement, SQLite adoption/recovery, stdio MCP, Bash/zsh guard execution, response-loss handling and child-environment sentinels. Every commit has DCO sign-off. No active Goal, automation, installed runtime or credentials were modified. Architecture judgment: consolidate invariant safety and current-contract dispatch, while preserving host-specific scheduling and settlement ownership. Todo acceptance and Turn settlement remain distinct; neither an empty Todo list nor a successful spend proves terminal vision closure. Ready for renewed review, not merged or release-qualified. Hosted checks must rerun on this head. No new live-model run was performed; the prior Claude/Doubao whole-Goal timeout remains a failure, with vision recovery tracked separately in #4208. The updated PR body retains these limitations. |
Signed-off-by: Green hats <183933879+Green-hats@users.noreply.github.com>
Signed-off-by: Green hats <183933879+Green-hats@users.noreply.github.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Co-authored-by: Green hats <183933879+Green-hats@users.noreply.github.com> Signed-off-by: huangruiteng <huangrt01@163.com>
…rades Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
|
The blocking I opened #4219 as a stacked fix against this branch. It compresses duplicate static prompt wording without raising the global allowances, while retaining the complete quota guard, separate Validation on #4201 head
Once #4219 is merged into this branch, the previously failed Python workflow should be rerun. This branch is also behind current |
258d380 to
55c0e0e
Compare
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
|
Update pushed: The update command now captures old-generator evidence before installation and invokes reconciliation through the upgraded runtime afterward (including the owning pip/pipx interpreter, not an unrelated PATH executable). Exact managed prompts may migrate automatically. Custom policy, mismatched bindings, unverified cron rows and unsupported hosts remain explicit per-task follow-up items. The qualified macOS adapter was exercised on one owner-authorized heartbeat with the App running, through the real CLI sync path. Immediate SQLite/TOML readback changed only the prompt; delayed readback across a scheduler interval retained the new prompt. Scheduling progress was independently visible and configuration/binding remained unchanged. This validates the selected host/version, not every App cache implementation or the agent's eventual compliance. No raw host records, identities, prompts or backups are published. Ordinary regression evidence: 195 focused Python tests passed (one native-Windows test skipped on macOS), 50 additional completion/settlement/host regressions passed, 38 TS interaction/settlement tests passed. After rebase, 66 loader/migration/runner tests passed; the final pip/pipx follow-up has 35 migration tests passing. The safety-transition differential has 40 passing tests and the actual base/head CLI budget smoke passes. Heartbeat prompt/error, Claude lifecycle/hook-policy, onboarding activation and installation smokes pass. Ruff and diff hygiene pass. All commits are signed off; #4216's remaining tests retain contributor attribution. Failure coverage includes SQLite writer contention through mirror delivery, rollback after mirror failure, explicit journal recovery, concurrent manifest changes, changed snapshots, custom prompts and foreign homes. SQLite and TOML are not one atomic transaction; detected conflicts retain recovery evidence rather than reporting success. Recovery remains an explicit operation with the App closed. Hosted checks are still running/queued on this final head; this is not a merge or all-green claim. Sonar's advisory report is not being represented as resolved, and the prior live Claude/Doubao full-Goal timeout remains a release-qualification failure tracked in #4208. This iteration adds no default paid model calls and does not waive vision replan or settlement authority. |
…rap loading Signed-off-by: huangruiteng <huangrt01@163.com>
test(hosts): align qualification regressions with updated #4201
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
复审绑定 exact head:e8a5867ae1f0f25642c9954ff5509d344d8f9d10。
动机
这个 PR 解决的是我在 thin automation 上真实遇到的摩擦:第一次执行 quota guard 时,我并不是不知道需要一个 Turn identity,而是不知道应该怎样把 prompt 里的 LOOPX_TURN=<current_time_iso>; reuse 可靠地变成可执行 shell。若自然地写成命令前缀赋值再在同一命令中展开 ${LOOPX_TURN:?},zsh 会在赋值生效前展开参数并直接失败,LoopX 根本收不到请求。
因此,这不是一句“记得传 Turn id”就足够的问题。host contract 应直接给出可执行、可测试的两步 bootstrap,并明确同一 Turn 在 guard、writeback 和 spend 中复用。当前 head 已经把这个摩擦吸收到 capability,而不是继续要求模型临场拼装。
改动思路
架构方向正确:heartbeat envelope 提供当前 ISO;prompt 先独立赋值/导出 LOOPX_TURN,再执行带参数守卫的 quota guard;quota 与 TypeScript effect runtime 继续拥有 selection、Turn 绑定、settlement 顺序和 receipt recovery。静态 authority/privacy/repair 规则留在 host prompt,易变的执行步骤由最新 interaction_contract 投影。
我也更正了此前的一个判断:我一度用旧的 .codex 存储形态推断当前 App heartbeat 是 heartbeat→cron。当前会话实际归属 .codex-gpt,是 thread-bound heartbeat/heartbeat;PR 对缺 thread 的 legacy cron 形态 fail closed 是合理的。现有 v1 automation 不会被静默改写,仍需显式采用 v2。
具体改动
关键代码讲解
render_thin_heartbeat_task_body现在输出真正的两条 shell 语句。Bash/zsh 正向执行通过,命令前缀 mutation 稳定失败,直接覆盖了我最初的 Turn-id 摩擦。- native Goal 在缺 Turn 时先投影一次 re-entry,绑定后才暴露 validation → durable writeback → quota spend → terminal closeout;Todo acceptance 与 Turn settlement 不再互相循环依赖。
- v2 wrapper 只对完整、绑定一致的 store 提供 adoption;unsupported legacy shape 交回 App reconciliation,不猜 scheduler/thread authority。
- release runner 使用隔离 profile 和 allowlist child environment;pip 与 pipx 更新后通过实际升级的 interpreter 执行 prompt reconciliation,不再回落到旧 PATH binary。
- 原先约 500 字符的 base/head output differential 已用精确的
none -> host_prompt_static_safety_v1一次性语义迁移处理:仅限 heartbeat thin/brief/compact 对应行,受 512 chars、640 bytes、5 lines 和 512 compact payload 约束;v1 -> v1、marker mutation 与非 heartbeat 行仍拒绝,绝对上限继续独立生效。
当前 exact head 仍有一个需要修复的合并阻塞:
- [P1] 绝对 brief-output 门禁仍会失败,并且当前 merge commit 缺 DCO。 在同一 Python 3.11 环境中,
tests/control_plane/test_cli_output_budget.py::test_explicit_compact_and_detail_modes_are_characterized在该 head 连续两次输出10634字符,超过heartbeat_prompt_brief/json的10500上限;切到当前origin/main后同一测试通过。这说明一次性 differential allowance 是有边界的,但最终 exact head 仍未满足另一条独立的绝对预算。GitHub DCO 同时明确指出 merge commite8a5867...缺少Signed-off-by。请在新 exact head 上恢复 DCO,并让长临时路径下的 absolute variant characterization 与 differential 同时通过,不要用更宽的全局豁免掩盖。
对主干的风险
Turn bootstrap、静态安全、真实 wrapper adoption、child-env 隔离和 pipx reconciliation 的核心语义已经闭环;我没有发现需要推翻现有 ownership 的新架构问题。剩余风险很具体:当前 head 仍能在正常本机测试路径触发 recurring prompt 的绝对预算失败,而且提交历史不满足仓库 DCO。Release Artifacts 的 403 发生在 artifact finalize,我把它视为独立基础设施问题,没有借此扩大代码结论。
验证证据包括:此前完整 exact head 上 286 个 focused Python、61 个 TypeScript settlement/effect 测试通过;当前 head 新增 qualification assertion 后,fresh output/qualification 批次为 73 passed、1 failed,失败可重复且 main 对照通过;changed file Ruff 与 git diff --check 通过。没有运行付费/真实模型,whole-Goal live qualification 仍是发布 hold。
我的整体评价
结论是 REQUEST CHANGES,但这次结论与最初四个语义问题不同:两步 Turn bootstrap 已经准确修复了“我一开始不知道怎样传 Turn id”的 capability 摩擦;automation-first / typed settlement 设计也成立。现在只需在最近 owner 内修正 absolute brief-output qualification 和 DCO,不需要再引入新框架。修复后请用新 exact head 重跑长路径 absolute variant、base/head differential、DCO 与最终 merge gate。
未来向前看,我认为当前的一次性语义迁移归因已经把预算例外限制在最小边界;不应再抽象出通用 exception framework。v1→v2 adoption 继续保持显式,且未授权任何 scheduler、permission 或 paid-model 行为。
English verdict: REQUEST_CHANGES — exact head e8a5867ae1f0f25642c9954ff5509d344d8f9d10 correctly fixes the executable Turn-ID bootstrap and the earlier host-contract friction, but it still fails the absolute brief-output ceiling on a reproducible path and contains an unsigned merge commit.
test(hosts): align qualification regressions with updated #4201 Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
e8a5867 to
b572baf
Compare
|
Addressed the latest exact-head review in
Validation on the final diff: 158 Python tests passed, no skips, full heartbeat-prompt smoke passed, real CLI absolute-budget and base/head differential smoke passed, changed-file Ruff and diff hygiene passed. The old-renderer negative control fails as expected. No model calls, active host-store writes or runtime installation were performed for this follow-up. Architecture judgment: a bounded renderer/qualification correction, not new execution authority. The automatic migration contract was already implemented; this follow-up makes its end-to-end evidence and documentation unambiguous. No scheduler/thread/permission migration is inferred for customized or inconsistent stores. Hosted checks must rerun on this head; prior artifact-finalization failure is not claimed resolved, and full-Goal live release qualification remains tracked separately in #4208. Ready for renewed review, not an all-green or merge claim. |
huangruiteng
left a comment
There was a problem hiding this comment.
Request changes conclusion (author-owned PR; GitHub blocks formal self-review)
动机
这个 PR 想把 heartbeat 从“安装时冻结的一段提示词”改成由当前运行时动态生成,并让 Codex App、原生 Goal、CLI/SSH 等宿主各自拿到与其生命周期匹配的启动与结算协议。这个方向是对的,也直接触及了真实摩擦:旧版 thin 提示把 LOOPX_TURN=<current_time_iso> 和 quota 命令拆成两个行内片段,代理容易不知道应当先绑定 Turn id、在同一 shell 中复用它。
当前 exact head 已经实质修复了这点:thin/brief 都给出可执行的同一 shell 代码块,先赋值 LOOPX_TURN,再通过 ${LOOPX_TURN:?} 调用 quota;Bash、zsh 的回归也从未预置该变量的环境执行生成结果。持久 Goal 同时明确拒绝 --turn-instance-id,避免把 heartbeat Turn 生命周期带进长驻运行。
改动思路
整体设计把职责拆得比较合理:TypeScript quota/settlement 继续掌握状态机与 effect 权威,Python prompt renderer 只负责宿主适配;goal_bootstrap 每次加载当前 registry/runtime contract,而不是复用安装时快照;原生 Goal 通过 typed re-entry action 续跑,SSH 仍走 --begin-turn;安装更新只自动替换 exact-managed prompt,自定义、canary、foreign 或发生竞态的 prompt 进入 review-only。
此外,Todo 的“接受当前工作”与 Turn 的“结算当前工作”被区分开来,方向上能避免未绑定 settlement。更新期先记录旧 prompt 的 exact-managed 身份,再在新 runtime 下协调 adoption,也比把 prompt 迁移混进二进制安装成功状态更清晰。
具体改动
这次改动覆盖动态 prompt 生成、host-loop activation、安装期 prompt adoption、registry-derived agent scope、quota/spend re-entry、CLI 文档与较完整的回归集。
关键代码讲解
loopx/control_plane/heartbeat/task_body.py::render_thin_heartbeat_task_body现在生成同一 fenced shell block,Turn id 的生成与消费不再靠读者自行拼接。loopx/control_plane/heartbeat/bootstrap_prompt.py::goal_bootstrap保留显式 caller policy,但重新读取 registry-derived runtime state,并拒绝持久化 Turn id/递归 bootstrap。loopx/control_plane/heartbeat/installed_prompt_update.py::update_with_prompts把 exact-managed prompt 的判定与新运行时下的 adoption 分开处理。loopx/control_plane/quota/spend_sources.py::visible_goal_turn_reentry_action给原生 Goal 一个带唯一 iteration identity 的 typed 续跑入口。
不过 brief 变体还有两个会阻断合并的语义问题:
render_brief_heartbeat_task_body插入的是HEARTBEAT_NOTIFICATION_RULE_THIN。它只写裸字段agent_must_attempt/must_attempt_work,没有保留权威对象路径heartbeat_recommendation.agent_must_attempt与execution_obligation.must_attempt_work。这会让低上下文代理重新混淆“是否通知用户”和“是否必须执行工作”,而仓库已有的 durable invariant 正是为了防止这种回归;当前 hostedtest-shard (1)、fallbackpytest和merge-gate都因此失败。- 用当前 exact head、真实
loopx-metaregistry scope 与--brief --codex-app生成提示时,budget_char_count=3792,超过 brief 声明的max_chars=3500,within_budget=false。现有 long-path 测试使用较短的合成 agent scope,且没有覆盖 Codex App 的真实 preflight/scope 增量,所以没有验证 PR 描述中声称的生产长路径预算。
最低修复是:brief 输出恢复两个 fully qualified authority locator;同时压缩或正确约束真实 App brief,使 representative registry-derived scope/preflight 下 within_budget=true,并新增 heartbeat-prompt --brief --codex-app 的生产形态预算回归。这里不需要再造新框架,复用 shared exact notification rule,并把预算 fixture 调整到真实宿主形态即可。
对主干的风险
本地在当前 head 上跑 tests/test_host_loop_activation.py tests/control_plane/test_heartbeat_notification_rule.py 得到 84 passed、1 failed,失败就是 brief 丢失 execution_obligation.must_attempt_work 的语义门禁;定向复跑同样稳定复现。Ruff 和 git diff --check 通过。远端 test shard 报 3851 passed、19 skipped、1 failed,随后 fallback 与 merge gate 失败,与本地证据一致。
当前分支相对最新 origin/main 落后 8 个提交;合成 merge tree 无冲突,但 main 已触及 3 个同路径文件,因此修复后复审前仍需重新确认 exact head、merge tree 和真实 App 预算。PR 没有声称新增 live-model qualification,这个非目标本身可以接受;当前 blocker 是已声明接口在真实 prompt 上没有满足,而不是缺少额外模型实验。
我的整体评价
核心架构方向和默认 thin 路径的 Turn-id 修复值得保留,尤其是把 ${LOOPX_TURN:?} 放进可执行同 shell block,确实修到了这次观察到的真实摩擦。但 brief 是低上下文 fallback,恰恰不能丢失执行权威路径,也不能在真实 Codex App 配置下超出自己的接口预算。请在新 head 上补齐上述两点;届时我会按 exact head 重新验证并复审。
English verdict: REQUEST_CHANGES at exact head b572baf3817c005edde04e507168d0c73c2ece74; the default thin path now binds LOOPX_TURN correctly in an executable same-shell block, but brief mode drops the fully qualified execution-obligation locator, fails the required hosted test/merge gate, and renders 3792 budget chars against its 3500 limit for the active Codex App profile.
…mpt-contract Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
Signed-off-by: huangruiteng <huangrt01@163.com>
|
Addressed the latest review at Both findings were valid:
The regression now calls the real Model regression: added This is decision-level evidence only, not actual host tool execution, scheduler/cache behavior, migration delivery or whole-Goal qualification. It does not erase the earlier Claude/Doubao whole-Goal closeout failure tracked in #4208. No live automation migration or installation was performed in this follow-up. Validation: 252 Python tests passed without skips on the final head; full heartbeat prompt smoke, real CLI absolute-budget plus base/head differential smoke, changed-file Ruff and diff hygiene passed. All 30 PR-range commits have DCO sign-off. Hosted checks must complete on this head; prior CI results are not reused as current passes. Architecture/refactor judgment: retain one current TS execution/settlement authority and one shared notification rule; remove duplicated static instructions rather than adding a new framework. Default remains thin; full/compact behavior and automatic exact-managed v1 adoption are unchanged by this correction. Ready for renewed review, not an all-green/merge claim. |
|
Post-merge audit(绑定 exact head 动机这个 PR 解决的是一组真实且会按每次唤醒累积的 host-contract 摩擦:保存的 heartbeat/Goal 提示会冻结旧执行步骤;旧 thin 文本虽然提到 我重新检查了最终合并 head。此前关于 Turn id、brief authority locator、真实 App budget、DCO 和 prompt adoption 的 blocker 均已修复;但合并时失败的外部 Sonar 门禁包含一个此前评审遗漏、且可独立复现的凭据边界问题,仍需要 post-merge 修复。 改动思路整体架构仍然成立: release-only qualification 也被设计为显式 具体改动关键代码讲解
复现使用的只是 synthetic key:把一个本地假程序传给 对主干的风险heartbeat 主路径的语义风险已经明显下降:base/head 真实输出对比确认旧 inline Turn hint 被可执行两步 bootstrap 替代;Bash/zsh mutation regression、当前安装回读和预算回读均通过。304 个 focused Python 行为测试通过;control-plane typecheck 通过,TypeScript 全套为 1096 passed、1 intentional skip。GitHub 的 DCO、dependency、build、Python、Node compatibility 和 merge gate 均通过。 剩余风险只在显式 live release qualification 开启时出现,但影响是 provider credential exposure,不应因为 default-off 就忽略。最低修复是:从 credential-bearing public live path 移除任意 binary override,改由 owner-controlled trusted configuration/allowlist 解析 executable;测试需要替换 binary 时使用内部 dependency injection。新增两个负向回归:分别给 Codex/Claude 传假 executable 与 synthetic key,必须在 spawn 前拒绝,且假程序不能观察到 key。修复后让外部 security gate 变绿;new-code coverage 当前为 43.7%,也应补齐或对真正不可执行的 release-only 分支做经过评审的精确排除,而不是继续整体 bypass。 我的整体评价Turn-id 摩擦已经被准确修到:现在不是“提醒代理记得传 id”,而是给出可执行、可回归、同一 wake 重试复用的 shell contract;brief 的 notification/work authority、动态 prompt adoption、native settlement re-entry 和 host 边界也形成了一个可解释的整体。这个结论不会因为 post-merge finding 被推翻。 但最终 head 不应被视为完全审净:release qualifier 新增的 arbitrary executable override 把“允许一次 live qualification”扩大成了“任意 caller-selected program 可接收 provider key”。请拆一个最小 follow-up 修复 trusted-executable boundary 和对应回归;不需要重新设计 heartbeat 或 settlement。 English verdict: POST-MERGE ACTION REQUIRED at exact head |
* fix(cli): restore module size and manpage classification budgets Two required public smokes fail on current `main`. `cli-command-module-size-ownership-command-modularization-smoke.py` reports `project_lifecycle.py has 1007 lines, above budget 1000`. The file crossed the budget when #4169 added the mutually exclusive external-sink delivery flags. Extract the three typed inline input codecs into `project_lifecycle_inputs.py`, which returns the owner to 925 lines without changing any public invocation. `cli-help-manpage-smoke.py` reports `unclassified: ['agent-context']`. The command shipped in #4244 without a manpage class. Add it to the existing `MANPAGE_COMMAND_HELP_ONLY` set, which is where comparable read-only lifecycle helpers already live. Extraction keeps the existing ownership contract: the registration and dispatch markers asserted by `cli-project-lifecycle-command-modularization-smoke.py` stay in the module, and `PROJECT_LIFECYCLE_COMMANDS` still covers all four commands. Validation: - `python3 examples/cli-command-module-size-ownership-command-modularization-smoke.py` -> ok - `python3 examples/cli-help-manpage-smoke.py` -> ok - `python3 examples/cli-project-lifecycle-command-modularization-smoke.py` -> ok - `python3 regression/cli-command-module-contract.py` -> ok - `python -m pytest tests/cli_commands/ tests/control_plane/test_cli_output_budget.py` -> 94 passed Signed-off-by: song <liusongstep@gmail.com> * test(smokes): realign stale contracts with shipped behavior Four required public smokes assert contracts that have since moved. Each is reproducible on a clean `main@fa57253`, so this aligns the checks with the shipped behavior rather than changing any product path. - `blocker-push-runtime-smoke.py` asserted the retired per-shell phrasing `` `LOOPX_TURN=<current_time_iso>`; reuse. ``. #4201 moved the bootstrap rule into the shared `HEARTBEAT_TURN_BOOTSTRAP_RULE`, whose current sentence ends with `reuse the value on retries`. Assert that sentence. - `install-local-smoke.py` required the accountable refresh and spend commands inside the `--brief` prompt, but brief mode renders exactly one bounded guard block by design; those commands belong to the full and compact modes. #4201 already realigned the adjacent thin-mode assertions and missed this one. Assert the brief contract, including that the pair stays out. - `github-actions-runtime-smoke.py` rejected the `22.14` SQLite runtime and the Node 26 forward job, and required the pre-#4241 `merge-gate` needs order. Record `SQLITE_NODE_VERSION` with its finalization rationale, extend the `python-tests.yml` expectation, and match the current needs list. - `repository-hygiene-smoke.py` fails because the `v1.0.3` tag exists without a timeline entry. Add the entry, following the existing format. Validation (each command exits 0): - `python3 examples/blocker-push-runtime-smoke.py` - `python3 examples/install-local-smoke.py` - `python3 examples/github-actions-runtime-smoke.py` - `python3 examples/repository-hygiene-smoke.py` - `python3 examples/release/release-readiness-doc-smoke.py` - `python -m pytest tests/control_plane/test_heartbeat_notification_rule.py tests/control_plane/test_heartbeat_prompt_support.py tests/control_plane/test_heartbeat_receipt.py tests/control_plane/test_heartbeat_recommendation_rules.py` -> 48 passed Signed-off-by: song <liusongstep@gmail.com> * test(ci): qualify runtime pins per workflow lane Signed-off-by: song <liusongstep@gmail.com> * test(ci): ignore comments when checking qualified runtime pins Signed-off-by: song <liusongstep@gmail.com> --------- Signed-off-by: song <liusongstep@gmail.com>
Summary
host_prompt. Explicit caller policy is retained, registry-derived state is refreshed, and loaders cannot recursively load themselves or pin one persistent Turn id.loopx update --applycaptures old-template evidence and invokes prompt reconciliation in the new runtime. Exact managed prompts can migrate automatically; custom/ambiguous/foreign-home or canary bindings remain review-only. Qualified macOS heartbeat stores support prompt-only SQLite/TOML migration while the App remains running, with revision checks, a writer lock, private journals and readback.Deliberate behavior changes and boundaries
The default remains thin. Static safety and the executable standalone Turn assignment justify explicit thin/compact ceilings of 2,500/6,500 characters; the output differential has a bounded one-time safety transition, not a permanent growth allowance. Selection, claim, vision replan and settlement authority remain in current contracts, not the saved prompt.
Brief now shares the fully qualified notification/execution rule with thin and follows current settlement steps rather than an independent static refresh/spend recipe. Its 3,500-character ceiling is unchanged; real App preflight and registry-derived scopes are retained.
The running-App writer is a qualified local compatibility adapter, not an official Codex storage API. SQLite and TOML are not one atomic transaction: detected external edits or crashes retain a recovery journal, and pending tasks are reported separately from binary installation success. Scheduler kind, thread, status, schedule, model, notifications and history are not rewritten. Unverified cron/heartbeat mappings remain rejected. Existing native Goal objectives are not imported or rewritten between homes. TraeX retains its separate capability projection. Existing MCP processes must restart after a runtime upgrade.
Validation
1beb54ef04fa0a8dbb3168901312d2e8b3281eaf. Final follow-up: 252 Python tests passed without skips, full heartbeat-prompt smoke, real long-path absolute budget and base/head differential passed; local DCO checks all 30 PR-range commits. Updated main is integrated without dropping contributor ancestry. Earlier broader evidence below retains its original scope.real_entrypointpassedreal_backendpassedmanualpassedregression_paritypassedintegrationrunningintegrationpassedintegrationfailed/looptimer. The prior Claude/Doubao whole-Goal timeout remains a failure; vision recovery is tracked separately in fix(host): recover vision settlement and preserve scoped replanning #4208. New prompt-decision probes do not replace it.Contributor follow-up
Refined #4216 on @Green-hats' original fork branch and merged it into this PR, retaining original contributor commits and the merged PR record. Its child-environment isolation and install-smoke corrections remain, with an additional one-bootstrap-load assertion. The integration merge now carries DCO sign-off without dropping contributor ancestry. No blanket cron-to-heartbeat conversion or everyday credential import was adopted.
Review judgment
The owner is the existing heartbeat/host-update boundary, not a new capability. The companion refactor consolidates stable bootstrap rendering and update-time adoption evidence while leaving scheduling and typed work/settlement ownership intact. Public fixtures use synthetic identities; private automation plans, journals, prompts, sessions and model credentials are excluded.