Repository navigation
refactor(work-items): retire Python primary-action instruction selection - #7462
Conversation
Select candidate precedence, exact mode instructions, replan fallbacks and orchestration lane counts in the existing typed interaction execution owner. Keep Python scalar/label compatibility views, resolution trace and final JSON serialization; preserve mode-only preflight and lazy selection recovery. Pin pre-change behavior, retain CLI/Host adapter coverage and record the bilingual retirement ledger, measured output/crossing parity and validation holds. No new RPC operation or persisted-format change. Bound primary-action list facts to the first selectable coerced row per source; TypeScript retains instruction predicates and source precedence. Pin 22,000-row backlog lane/recovery parity and all 182 bounded-codec instructions. Move goal_boundary budgets 30/2 -> 29/3 with RETIREMENT_ANCHOR in the same diff, per the anchor design. Same-source recount: 32 tokens total, migration surfaces 16/1, byte-identical prose, no new reader, writer or binder. Both architecture gates green again: 128 passed; retrodiction restored to unchanged baseline 12/15. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> Signed-off-by: hhyykk <4408344+hhyykk@users.noreply.github.com>
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent · gpt-6.1-sol · OpenAI · runtime_reported · max
动机 / Motivation
通过 quota、heartbeat 和既有上下文入口读取下一步工作的 Agent,以及维护这些指令规则的开发者。
原来同一次工作契约先由 TypeScript 选执行模式,再由 Python 选具体指令;本提案在原 typed 请求内同时选择模式和指令,减少后续规则修改时的双处维护。
194组完整production interaction contract在不可变base与精确head逐项相同;wheel/sdist各194组及File/SQLite真实CLI回读通过,原拒绝恢复和只读状态保留。这证明当前切片有真实调用方和功能增量;代码行数减少本身不证明持续运行更便宜。
本切片不完成整个T3/T4、controller统一、实际Host或模型长程采用,不改provider、权限、持久格式或执行费用授权。
改动思路 / Approach
审查完整 head 0331874 的 13 个文件。既有 interaction execution 请求足够承接指令选择,Python 兼容编码与后续恢复保留,没有新增 RPC 或状态 owner。本 PR 只收敛三项指令决定及必要传输;monitor、trace 和更广 T3/T4 留原 owner,当前切换的性能资格仍须补齐。
Python 把原 str/repr、真值、空白、按码点截断和标签视图送入既有 work_item.interaction_execution.project。TypeScript 先选模式并检查原 selection recovery,再产生 primary instruction;Python 原恢复命令、selection/capability gate、blocked-wait 覆盖和 resolution trace 保留。列表只传同语义下首个可选视图,避免把整份 backlog 搬入请求。当前不新增 provider IO、持久 store、配置或用户准备轮次。
具体改动 / Changes
先读的验收依据为 既有迁移 RFC,路径 docs/architecture/rfcs/typescript-control-plane-migration-v0.md,spec revision:be1dc37a008be7017b64b622f653b6707df5c544。
- Payoff-phase PR contract:确实删除三个 Python choice 函数,复用原 RPC,保留 codec/trace 的实际 caller 和退出条件,是有用且可回滚的迁移切片。
- Caller-observable semantic parity is a promotion gate:同脚本/同输入的 194 组完整 contract 全等,未归一化任何字段;源输入未变。另有实际 File/SQLite CLI、物理包读回及单条义务 mutation 的独立检错。
- Correctness:相关原生与 Python 检查、两种实际本地后端、wheel/sdist 深层执行已有正证;20 项旧 fixture 失败完整归因如下,不提升为通过。
- Performance:本次完整 quota CLI 样本未见物质回退,但原 §6 要求的 cold-start、warm typed request、代表性 transaction/full CLI p50/p95 和 idle/burst daemon memory 尚未完整资格化,判定 not_met。
关键代码讲解
- primary_action_instruction_facts 保留 Python coercion,按既有 Todo eligibility 生成首个可选视图,不再返回最终指令。182 个 fixture 已逐项读取,并补测有/无当前 lane、22,000 行 foreign/blocked 前缀、末尾合法项及 admitted/rejected/deferred。
- selectPrimaryActionInstruction 收敛原来源优先序和完整文案,包括当前 lane、到期 monitor、修调度、capability 候选、scoped fallback、Todo、backlog 和最后回退;空 child list 仍优先于 peer lanes。
- projectInteractionExecution 仅在 final facts 存在且原 selection 不需恢复时选择指令,mode-only preflight 不增字段。拒绝恢复保留原命令及 false 执行/交付标志。
- _build_interaction_contract_projection 是生产采用点,final 请求开启 primary action,再走原恢复或 agent channel;后续覆盖没有被此次迁移绕过。
生产 Python −185 行、TS +109 行,净 −76;总 diff +948/−278 包含双语 docs、测试和 fixture。保留 Python codec/monitor/trace 有具名消费者,是兼容编码和显示边界。沿原 action_selection_context 收敛而非新建 admission encoder 是合适的伴随整理;更广删除按原退出条件处理。
对主干的风险 / Risks
[P2] 补齐本切换的 §6 性能资格,再声明验证完成。 当前双语 RFC 新增 Validation is complete for this slice,依据是 canary、字节/crossing 和 25 次样本的 median。原有 §6 要求 cold/warm/完整 caller 的 p50/p95 及 idle/burst RSS;median 不能排除尾部或常驻内存问题。该事实 carrier 进入默认 final contract,功能等价和 RPC 数不变仍不能证明完整成本不退化。
本次独立固定 32 对、交错 AB/BA、相同物理 source/interpreter/单行 SQLite fixture 的完整 quota should-run:p50 278.89→277.99 ms,p95 325.09→317.33 ms。该样本未见物质回退;不把 −2.39% 认定为因果提速,也不将 3 次 warmup 当 cold-start 分布。当前仍缺原门中的 cold/warm/RSS 及其余代表 caller 尾延迟资格。最小修复是在同一切片补可重放回执、保留失败和未知,并同步双语完成边界;若测出回退,再在现有 owner 内修复。无需完成无关 parent roadmap 或新增模型实验。
语义与 CI 对齐
goal_boundary 原指令文字逐字迁移造成词法预算 Python/TS 30/2→29/3,总量仍 32,真正 reader/writer surface 16/1 未增。Registry 和 retirement anchor 同步、原义务未缩短,相关 smoke 与双语检查通过;这项有证据的预算调整本身不阻断。当前阻断来自已接受的 Performance 验收缺口,新的 complete 声明不能改写原标准。
| 独立检查 | 结果 |
|---|---|
| 4 个 TS 模块 | PASS:88,零 skip |
| 10 个 Python 模块 | 177 PASS / 20 FAIL;失败单独归因 |
| Base/head 完整 interaction contract | PASS:194,全字段相同,输入未改 |
| Wheel 与 sdist | 各 1,767 个产品文件与 source/安装字节一致;各 194 contract 通过,两后端各 5 条 CLI 均 exit 0,记录与 revision 不变 |
| 隔离 wheel 的单句语义 mutation | 原独立全契约 oracle 正确失败;随后恢复原字节 |
| Typecheck、Ruff、标准 premerge | PASS;6 直接 + 19 选中,零 manual hold |
20 项失败均在第一个 todo list 因 fixture 未初始化 canonical authority 拒绝;不可变 base 与 head 的 nodeid、exit code、完整诊断及恢复 payload 逐项相同,未进入迁移后的下游,不归为本 PR 新回归。首次 package build 因本地换头后 Chat bundle 陈旧被拒;沿原 build:chat 重建后两种物理包均通过,无 tracked source 改动。历史完整 Python 失败和未运行下游不标绿。本次不查询或等待远端 CI,未把其他 PR 的 PostgreSQL 结果冒作本头资格。
我的整体评价 / Verdict
REQUEST_CHANGES,原因是本切换既有性能资格尚未齐备。功能迁移、真实调用方采用、完整指令/恢复语义和打包均有独立正证,未发现当前语料内的功能差异;保留它们供后续复审复用。长期成本与收益仍未资格化,不能从行数、单次投影或一个 CLI 样本推断。
用户侧现有 CLI 指令和恢复路径保持,没有新增配置或确认轮次。13 文件无渲染组件、页面布局或按钮改动,因此视觉观察不适用;正式 App/Host、Windows、最低 Node、模型理解与持续收益未验。当前变更复用已注册 mode 与原 owner,无新共享持久词汇。补齐当前门后可复审,不以这次结论扩大 merge、安装或执行权限。
English verdict: REQUEST_CHANGES at 0331874. Full-contract parity, real File/SQLite callers and independently installed wheel/sdist pass. The default cutover still lacks the accepted cold/warm/p95 and daemon-memory qualification; median/crossing parity and the passing local canary do not establish completion.
| CLI outputs retain equal byte counts and normalized content; crossings remain | ||
| 1/3/3/75 for both binding counts. No latency improvement is claimed. | ||
| The slice moves one `goal_boundary` prose token Python → TypeScript; lexical budgets move 30/2 → 29/3 with migration surfaces unchanged at 16/1, as recorded in the ledger; registry and anchor move together. | ||
| Validation is complete for this slice: the final canary reports status: |
There was a problem hiding this comment.
[P2] 当前完成声明超出了本切换的已验边界。变更前同一RFC §6 Performance明确要求cold-start、warm typed request、transaction/full CLI的p50/p95及idle/burst daemon memory;ledger/PR当前只给25次median、字节和crossing parity。本次独立194完整contract、实际File/SQLite及物理wheel/sdist均通过,32对同条件完整quota CLI p95也未见回退(325.09→317.33ms),但它们仍不回答cold/warm/RSS与其余代表caller尾延迟。请沿原切片补可重放默认SQLite资格回执,保留原失败/未知,并同步中英文完成声明;若测出回退再有界修复,无需扩大到整个parent roadmap或模型实验。
Summary
selectPrimaryActionInstructioninloopx/control_plane/work_items/interaction_contract.ts, composed byprojectInteractionExecutioninside the existingwork_item.interaction_execution.projectrequest. It selects candidate-source precedence (agent lane, due monitors, schedule-metadata repair, capability-runnable count, scoped fallback, advancement Todos, backlog, advancement reason, work-lane text), the exact per-mode instructions, replan-packet fallbacks and child/peer lane counts, and runsactionSelectionNeedsRecoveryin process before reading instruction facts so rejected/deferred selections never build an executable instruction.work_items/primary_action.py(protocol_first_candidate_action,protocol_replan_action_packet_instruction,resolve_canonical_primary_action; 347 → 152 lines). Python keeps onlyprotocol_action_text/protocol_action_labelas compatibility codecs (Pythonstr/repr, whitespace,...truncation),protocol_monitor_action, the resolution trace and final JSON serialization, plus the facts/views carrierprimary_action_instruction_facts. The carrier transports at most the first selectable coerced row per list source, so the request size no longer depends on backlog/Todo list length; the typed owner applies the same predicates and precedence to whatever arrives.interaction_contract.py::_project_interaction_executionsendsprimary_action_factsplus the existingaction_selection_contextpacket only when the final contract builder asks for them (include_primary_action=True); mode-only preflight requests and theunadmitted_action_selectionresult shape are byte-identical to before. No new RPC operation, handler registration, runtime, provider, store or persisted-format change.goal_boundaryprose token. The retirement-ledger lexical budgets move 30/2 → 29/3 (Python tightened to its measured count; TypeScript increased with evidence: byte-identical relocated prose, cross-language total unchanged at 32, migration surfaces unchanged at 16/1 — no new field reader). Recorded in the bilingual ledger per the budget-failure decision guide.tests/control_plane_ts/fixtures/primary_action_instruction_selection.json(all modes, precedence, fallbacks, lane counts, empty/invalid shapes, Unicode/non-BMP, truncation), checked through the bounded codec and the real typed owner against independently pinned instructions; the 22,000-row oversized-backlog lane and rejected-selection recovery cases are pinned against the base outputs with a <16 KiB facts bound; existing CLI/Host adapter assertions retained.docs/architecture/rfcs/ledger/typescript-control-plane-migration-v0/2026-10-27-primary-action-instruction-selection.md+.zh-CN.mdand both migration RFC checkpoints. Deletion conditions: remove the trace/monitor facade when their consumers adopt a complete typed action/trace projection; remove the scalar/label codecs and facts carrier only after the last Python text/label consumer exits and a typed codec proves coercion/Unicode/truncation/trace parity.Measured results
Local bench harness, runs interleaved base → head → base → head; 25 timed runs / 3 warm-ups per command, N=1 and N=3 synthetic SQLite fixtures. Each median below is the minimum of that side's two interleaved medians. Crossings are Python→Node logical requests on the real CLI path; latency remains sensitive to host/launcher noise.
agent-context --phase before_planagent-context --phase after_delegate_result--turn-instance-idquota should-runagent-context --phase before_planagent-context --phase after_delegate_result--turn-instance-idquota should-runLatency deltas stay within the base-1 vs base-2 noise floor (agent-context ≤ +2.6%; quota −4.2% / −3.6%; launcher floor 38.45 → 39.16 ms).
*_attimestamps,context_id,event_id,staleness_seconds) is equal base vs head. Every emitted instruction literal is byte-equal to the retired Python string. Token consumption (bytes/4 estimate) is unchanged; crossings are unchanged (this slice removes a decision owner, not a request).git diff --numstat origin/main -- loopx/): Python −185 net, TypeScript +109 net, production total −76.git show --stat HEAD: 13 files, 914 insertions / 278 deletions.Validation
npm run typecheck:control-plane: pass.npm run test:control-plane: 5,528 passed / 0 failed / 75 PostgreSQL-isolated skipped (independent validator; Node 26.12.0, i.e. CI's forward-compatibility lane). Focused native tests re-verified on the final head: 37 passed.pytest -m "not stage2c_e2e"(head, 2:04:46): 908 failed / 27,169 passed / 234 skipped / 8 errors; 916 distinct failing IDs. Base replay of all 147 failing files: 913/916 also fail on base (inherited: canonical-authority fixtures Control-plane tests fail on main when scenario Goals lack canonical authority #7433, scheduler launcher Scheduler native launcher readback tests fail on main with "value must be strict JSON" #7434, quota-bound wait Quota-bound wait recovery test fails on main #7435, project registry Project registry pending-registration tests raise CanonicalAuthorityRequired on main #7436, plus guard-induced local artifacts). The 3 head-only IDs were: the two architecture checks this commit initially failed (goal_boundarylexical budget 3>2 and its downstream retrodiction signal 13/15) — resolved by the registry budget move recorded above, both tests now pass on the final head — and one frontend lifecycle test that only ran because dashboard dependencies were installed into the worktree during validation (skips on base; environment-induced, not a code regression).loopx canary premerge --from-git-diff --git-diff-base origin/main):status: passed,ok: true,merge_gate_passed: true, 0 failures, 0 manual holds. Bilingual RFC gate (scripts/check_rfc_bilingual.py --base origin/main --head HEAD): passed.git diff --check, public-boundary scan: clean. Semantic advisory: no new supported vocabulary carriers.origin/mainat the basebe1dc37a0already shows red Python test-shards 3 and 6, browser timeouts and Windows failures (tracked by Control-plane tests fail on main when scenario Goals lack canonical authority #7433–Project registry pending-registration tests raise CanonicalAuthorityRequired on main #7436 and CI: chat-bundle-browser and dashboard-browser shards time out on main #7389); those will appear on this PR as inherited and are not caused by this diff.