Repository navigation
Conversation
Signed-off-by: duang777 <duangjl007@gmail.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; model=gpt-6.1-sol; provider=OpenAI; runtime_reported; reasoning_effort=max
完整评审 6679@0a1cbfde9b977df2b17a8d0dc5693ab0a51f9de5,实际合并基线 da7d0b9979d2e7a2651cdc95230de70549278bfb。结论 REQUEST_CHANGES:有一个已通过真实读取路径复现的 P2。
动机
运行 quota should-run、需要判断当前结果是否可信的自动化 Agent 与本地操作者。
此前 quota 的决定没有自己的来源与覆盖说明,调用者无法直接区分当前、陈旧或不完整的读数;本次增加统一说明,目的是让调用者先看来源告警再决定下一步。
正常来源、状态继承、覆盖与渲染已有可执行覆盖;但独立真实 CLI 和 wheel 均证明损坏的调度状态仍被标成 fresh,整体 alert 为 false,因此核心可信读数尚未成立。
不改变算力准入、任务排序、调度策略或写权限,不完成 review-packet / Decision Context 的后续接入,不证明实际宿主安装、模型采用或持续运行收益。
quota 来源读数需要修复下面的 P2;review-packet 与 Decision Context 仍按既有 RFC 顺序推进,不能将本次接入称为完整迁移。
改动思路
沿用现有 Python quota 投影及唯一 TypeScript envelope owner 是合适的有界接入;来源 IO 的真实结果必须由现有读取 owner 返回,不能在 Python 根据参数存在重新推断成功。
当前 PR 只交付 quota 的真实来源、继承、覆盖及告警;要求修复真实调度读取事实并补负例,不要求先迁移整个 quota 或完成后续投影。
生产入口仍是 quota should-run,先取得 status,再按原有 quota / interaction / scheduler owner 生成决定,最后把直接读取事实与 status 的所有上游来源交给 projection.envelope.seal。Python 不判断陈旧阈值、覆盖完整性和告警组合,既有 TypeScript owner 决定这些语义;Markdown 复用统一告警渲染器。没有新持久化状态、开关或设置动作,也不需要用户重复授权来读取原有响应。这里是既有读模型的元数据接入,前端配置器没有新增可操作能力;没有把 CLI 配置描述当成新 UI 交付。
最强的反对理由是每次 quota 都增加载荷和维护成本,却可能仍然隐藏坏来源。因此关键验收是“真实失败能否被看见”,不能只看 schema、测试数或 seal 的输出形状。当前框架选择可以保留,缺口在读取事实的生产者;采用另一次 Python 文件探测或第二套 freshness 规则会进一步复制知识。
| 同一读取状态 | 基线 | 当前头与 wheel |
|---|---|---|
| 两个调度键都不存在 | 原决定,未声明 quota 自身新鲜度 | 允许作为健康空读,符合声明 |
| 两个调度键都是损坏 JSON | 原决定,无 quota envelope | 仍声称 fresh,整体无告警,违反来源契约 |
| 两个调度路径是目录 | 原决定,无 quota envelope | IO 读取失败仍声称 fresh,无告警 |
| 清除隔离坏数据后重新读取 | 原决定 | 恢复健康空读,原有决定与指令保持 |
此表来自实际 CLI、真实 TypeScript 文件读取与正常 wheel,不是流程示意或模型采用证明。
具体改动
独立规范在读 diff 前固定为 docs/reference/contracts/projection-envelope-contract.md,spec_revision: da7d0b9979d2e7a2651cdc95230de70549278bfb;同时对照相同基线的 docs/architecture/rfcs/typescript-control-plane-migration-v0.md §2.6。规范的当前 rollout 编辑不能反过来充当自己实现的验收依据。
2.6 Projection envelope is a kernel read contract:implemented。quota 增加自己的 envelope,继承上游来源,保持 TypeScript 唯一判断 owner;paused、health、unknown 等返回也接入。Field semantics:not_met。不可读来源必须告警,但新 scheduler 来源仅据参数存在推断成功,真实错误没有进入来源事实。Consumer rule:not_met。渲染顺序本身正确,但调度来源出错时 envelope 告警为 false,调用者没有告警可披露,不能据此声称当前来源健康。Cache and replay:implemented。复用原 TS seal 与上游 envelope,保留旧 observation、重算 freshness;缓存与陈旧来源测试通过。后续 review-packet / Decision Context 接入仍保留在既有 RFC 边界。
关键代码讲解
_attach_quota_should_run_envelope:Assemble source facts and requested Goal coverage; call existing TS seal exactly once. No own envelope -> inherited status and direct source envelope。_record_app_scheduler_state_source:Records App scheduler source after real payload assembly. Infers read from parameters; currently falsefresh on actual read failure。_projection_envelope_migration:Qualify one-time none -> v0 migration for canonical status/quota surfaces including variants. Status-only row prefix -> canonical surface id includes quota。render_quota_should_run_markdown:Print envelope notice before quota decision. No quota notice -> common renderer。
其他差异也完整检查:双语 RFC 仅更新 quota rollout 及剩余入口;projection 文档描述实际来源;测试覆盖上游继承、未知 Goal、缺失 envelope、paused/health、cadence 失败、缓存与渲染,以及一次性输出迁移的反例。源码共 10 文件、+665/-59,主要增量是本地来源适配和 360 行聚焦测试,没有引入新框架或第二决策权威。
预算增加有同负载证据,不能因为旧上限而删去消费者需要的来源说明。独立 hot-path 对照是 quota JSON 15,419→18,636 字符、378→513 个嵌套键、52→53 个顶层键,新上限 20,500 / 525 / 54;原 heartbeat/status 形状没有改变。共享 differential 只为 canonical status / quota_should_run 的 none→v0 提供一次性余量,包括对应模式;同 v0 继续增长、其他 surface、逆向或未知版本不获豁免。实际完整 base/head 96/96 行通过,18 条 quota 迁移提示保留给审查者,没有新增行被隐藏。
对主干的风险
[P2] 调度状态读失败不能被标成 fresh
位置:loopx/control_plane/quota/should_run.py:208-212。有效 App context、runtime 和 Agent 并不能证明来源被成功读取。真实 _build_quota_should_run_payload 调用 scheduler loader;既有 state_store.ts::loadSchedulerState 将非 ENOENT / JSON 解析错误吞成 null,随后新 helper 仅检查两个参数是否非空,写入 read_status=read 和当前时间。seal 忠实处理这些错误的输入事实,于是输出 status=fresh、unreadable_count=0、alert=false。
我在一次性 runtime 中,通过 scheduler_state_path 找到当前键与 Codex 兼容键,分别放入损坏 JSON 和目录;独立物理读取分别得到 JSONDecodeError / IsADirectoryError。真实 API、生产 quota should-run --goal-id goal-a --agent-id reader-a --runtime-profile codex_app_heartbeat 和正常构建安装的 wheel 都复现上述错误健康标签,CLI 均退出 0。API 的 eligible 决定仍为 run;CLI 的已有 operator-gate 指令也保持原样。这里新增的错误是“失败来源被认证为新鲜”,没有声称这个 PR 新增了原有空状态 fallback 或授权绕过。
从实际 scheduler.state.load / load_app_automation_scheduler_state 读取边界带回成功、缺失与不可读事实,保留合法缺失为空的语义;将解析或 IO 失败映射为 unreadable 并由既有 TS seal 产生告警,不要仅由 runtime_root 与 agent_id 是否存在生成 read/fresh。
在隔离 runtime 内分别令当前与 Codex 兼容键的 scheduler_state_path 为不存在、有效状态、损坏 JSON、目录或读取失败;通过 quota should-run 的生产 CLI / 正常 wheel 验证损坏会告警、合法缺失不误报、修复后恢复,并重跑原 178 项测试与 CLI differential。
语义与 CI 对齐
本次复用既有 loopx_projection_envelope_v0 与 read/missing/unreadable/not_read 词汇,source id 是局部事实名;没有新共享生命周期或授权语义。开发期语义 advisory 没发现支持语法内的新载体,完整 semantic-vocabulary check 也通过,但这不能证明来源事实正确,当前 P2 直接违反既有 Field semantics / Consumer rule。回归应覆盖真实 TypeScript 读取错误,而不只用已归一化的正向 mock 替代读取结果。
独立验证:相关 pytest 基线 163、当前 178 项通过;native standard premerge 为 5 个直接检查及 19 个选择检查,failed=0、skip=0、manual hold=0,含真实 CLI 输出、quota 路由、scheduler、维护性与全部 10 文件 public-boundary 扫描。TS typecheck、mypy 17 文件、选定路径 Ruff、完整语义与 DCO/diff 均通过。初次 wheel 因复用工作区的旧 Chat 构建产物被正常校验拒绝,随后运行正常 build:chat 并重建 wheel,独立 site-packages 路径再次复现 P2;没有放松构建校验。未查询或等待远程 CI。
我的整体评价
整体方案与已接受的下一步一致,保留现有 TS owner、局部 Python facts adapter 和有证据的一次性预算调整是合理的。未来适配退出仍归原投影迁移;当前有界整理应把实际读事实从现有 IO owner 传回来,避免参数推断或重复探测,不要求无关的全量 TypeScript 重写。
long_horizon: preserved:四个真实对照场景中,除明确新增的 envelope、隔离路径拼写及生成时间,旧决定、完整指令和解压后的宿主 follow-up 事实逐字段相同;96 个 CLI 场景与原生路由验证没有发现调度或续行变化。这不证明长期收益。user_experience: regression:原先未知的新鲜度现在在坏来源上被错误标为健康,正是本次能力要消除的风险,因此当前头不能批准。
结论是 REQUEST_CHANGES,限于上述已复现的来源真实性缺口。修复后用同一真实 CLI / wheel 的缺失、坏数据与恢复对照重审新头;不以绿测试替代该观察,也不把这条评审视为合并、安装、宿主采用或后续迁移完成的资格。
English verdict: REQUEST_CHANGES - 0a1cbfd: actual corrupt/unreadable scheduler state is labeled fresh with no envelope alert; reproduced through the real source CLI and installed wheel despite 178 passing targeted tests, 96-row differential and 19 green native canaries. Preserve actual read outcomes at the existing IO boundary and test missing/error/recovery.
| if isinstance(identity, Mapping) | ||
| else "" | ||
| ) | ||
| read = bool(status_payload.get("runtime_root") and agent_id) |
There was a problem hiding this comment.
[P2] 调度状态读失败不能被标成 fresh。从实际 scheduler.state.load / load_app_automation_scheduler_state 读取边界带回成功、缺失与不可读事实,保留合法缺失为空的语义;将解析或 IO 失败映射为 unreadable 并由既有 TS seal 产生告警,不要仅由 runtime_root 与 agent_id 是否存在生成 read/fresh。 独立观察:真实 API、生产 CLI 与正常安装 wheel 均输出 app_scheduler_state.read_status=read、status=fresh、unreadable_count=0、envelope.alert=false;读取失败被误当成健康空状态,调用者看不到应该先披露的告警。 验证要求:在隔离 runtime 内分别令当前与 Codex 兼容键的 scheduler_state_path 为不存在、有效状态、损坏 JSON、目录或读取失败;通过 quota should-run 的生产 CLI / 正常 wheel 验证损坏会告警、合法缺失不误报、修复后恢复,并重跑原 178 项测试与 CLI differential。
There was a problem hiding this comment.
Fixed in a74b460d9, with regression coverage in 7f6c8c724 and 9ef61099a.
The TypeScript scheduler state store now reports the actual read result. Missing state is a successful empty read. Malformed JSON, directory reads, invalid state, and other I/O failures report unreadable. Python observes both the canonical and Codex compatibility-key reads; it no longer infers success from runtime_root and agent_id.
Validation on Node 22.22.3 / SQLite 3.51.3:
- scheduler state store: 16/16 passed, including malformed canonical and legacy JSON plus a directory path
- scheduler/projection Python suites: 59 passed
- quota and CLI differential suites: 171 passed
- exact-head premerge: 19/19 selected checks passed
- built and installed wheel: packaged CLI returned fresh for missing state, unreadable with alert for corrupt state, then fresh after recovery
- production CLI regression also covers directory-path I/O failure and recovery
Please re-review 6679@9ef61099af9ee83772020afb052e4d180feff6c3.
|
This pull request has merge conflicts with Choose the remote for the base repository, not an out-of-date fork. git fetch upstream
git rebase upstream/main
# Resolve each conflict, git add the resolved files, then git rebase --continue.
git push --force-with-lease origin HEADFor a same-repository clone whose Keep the DCO |
Signed-off-by: duang777 <duangjl007@gmail.com> # Conflicts: # docs/architecture/rfcs/typescript-control-plane-migration-v0.zh-CN.md
Signed-off-by: duang777 <duangjl007@gmail.com>
Signed-off-by: duang777 <duangjl007@gmail.com>
Signed-off-by: duang777 <duangjl007@gmail.com>
Goal And Delivered Outcome
quota should-runinherited status data but did not emit its own canonical freshness, completeness, source, and Goal-coverage envelope.KeyError: projection_envelope. After, every active, paused or stopped, health-blocked, and unknown-Goal result emitsloopx_projection_envelope_v0. The focused regression suite and the source and packaged CLI rows below prove the result.main. No separate issue.Author Declaration
Implemented against
docs/architecture/rfcs/typescript-control-plane-migration-v0.mdanddocs/reference/contracts/projection-envelope-contract.mdat baseda7d0b9979.build_quota_should_runtests/test_projection_envelope.py_tracked_read_callback,_record_app_scheduler_state_sourcetest_quota_should_run_records_live_workspace_inbox_and_scheduler_readsprojection.envelope.sealnpm run typecheck:control-planerender_quota_should_run_markdowntest_quota_should_run_alerts_when_the_status_envelope_is_missingScope And Continuation
quota should-runrollout slice. The RFC still listsreview-packetand Decision Context packets as later read-model adoptions.Validation
0a1cbfde9b977df2b17a8d0dc5693ab0a51f9de5regression_paritypassedprojection_envelopewas absent. After implementation and the final rebase, the related suite passed 228 tests.regression_paritypassedreal_entrypointpassedpython -m loopx.cli ... quota should-runfrom the source checkout and read backprojection=quota_should_run.real_entrypointpassedloopx quota should-runread back the Goal-scoped envelope.staticpassedregression_paritypassedintegrationpassedloopx canary premerge --from-git-diffpassed all 19 selected checks, including the public and private boundary and both interface-budget smokes.See validation disclosure guidance.
Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).