Skip to content

Commit 0331874

Browse files
refactor(work-items): retire Python primary-action instruction selection
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>
1 parent be1dc37 commit 0331874

13 files changed

Lines changed: 948 additions & 278 deletions
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Primary-action instruction selection
2+
3+
[中文镜像](2026-10-27-primary-action-instruction-selection.zh-CN.md)
4+
5+
## Boundary and ownership
6+
7+
This Stage 2B slice removes the Python instruction decision owner while keeping
8+
caller-visible prose and rendering stable. `projectInteractionExecution` in
9+
`work_items/interaction_contract.ts` selects the existing mode and its primary
10+
instruction in the same `work_item.interaction_execution.project` request.
11+
There is no new operation, handler registration, runtime, provider or store.
12+
Qualification remains incomplete until the validation holds below are resolved.
13+
14+
Retired Python symbols in `work_items/primary_action.py`:
15+
16+
- `protocol_first_candidate_action`: source precedence, addressed labels,
17+
capability candidate count, scoped successor and advancement fallbacks.
18+
- `protocol_replan_action_packet_instruction`: settlement-only, successor and
19+
generic typed-outcome wording.
20+
- `resolve_canonical_primary_action`: exact mode prose, fallbacks and child/peer
21+
lane counts, including the empty-child-list precedence over peer lanes.
22+
23+
`interaction_contract.py::_project_interaction_execution` sends a single optional
24+
facts/views carrier and the existing `action_selection_context` projection.
25+
The final contract builder requests and threads the returned instruction through
26+
`_build_interaction_agent_channel` into `build_primary_action_projection`.
27+
`unadmitted_action_selection` retains its mode-only preflight and exact result
28+
shape. The TS owner composes `actionSelectionNeedsRecovery` before reading
29+
instruction facts; rejected/deferred recovery does not construct executable
30+
instructions. The existing Python recovery alternative, selection/capability
31+
channel overrides, blocked-successor override and blocked-wait override remain.
32+
33+
Python retains `protocol_action_text` and `protocol_action_label`: Python `str`
34+
and nested repr, truthiness, whitespace, label prefixes and code-point limits
35+
are compatibility codecs, including `...` rather than the trace codec's `…`.
36+
`primary_action_instruction_facts` transports those views and existing Todo
37+
eligibility/lifecycle source facts; it does not select an instruction or retry a
38+
Python fallback. Python transports at most the first selectable row per list
39+
source, evaluated from the same coerced views; the typed owner applies the same
40+
predicates and source precedence. Request size is independent of backlog/Todo
41+
list length. Registered effective actions and agent-scope values come from
42+
their generated TS exports. Other existing local rule strings keep their exact
43+
spellings; no shared vocabulary or persisted schema is added.
44+
45+
Python also retains `protocol_monitor_action` and the resolution trace through
46+
`state_projection.next_action_resolution_trace`. `primary_action` still precedes
47+
optional `resolution_trace`; channel insertion order and final Python JSON
48+
serialization are unchanged. Delete the trace/monitor facade only when their
49+
remaining consumers adopt a complete typed action/trace projection. Delete the
50+
scalar/label codecs and facts carrier only after the last Python text/label
51+
consumer exits and a complete typed compatibility codec proves Python coercion,
52+
Unicode, truncation and trace parity. This slice does not retire those owners.
53+
54+
## Vocabulary budget
55+
56+
The registry's `meaning` says "module_budget counts modules under loopx/ whose text carries the standalone field token" and "the token count stays until Q11 decides whether the syntactic metric replaces it"; this deliberately conservative lexical proxy protects against unexplained growth in potential field readers.
57+
On the same tracked-source workload, base `be1dc37a0` → `this commit` moves `goal_boundary` lexical counts from Python/TypeScript 30/2 → 29/3 (total 32 unchanged), originally failing `legacy field goal_boundary grew to 3 .ts modules; budget is 2` and retrodiction `(13, 15)` versus frozen `(12, 15)`.
58+
The moved sentence, `repair goal_boundary.write_scope projection before attempting the selected write`, is byte-identical agent-facing prose, adding no reader, writer or binder; the smoke's prose-versus-reader distinction keeps migration surfaces at Python 16 / TypeScript 1.
59+
Retaining that instruction, the registry tightens the Python token budget to its measured 29 and increases TypeScript 2 → 3, with zero lexical headroom; migration-surface budgets and their anchor remain unchanged at 16/1, while the registry and `RETIREMENT_ANCHOR` move together in this same commit, as the anchor mechanism requires; the retrodiction baseline is unchanged and the measured result returns to `(12, 15)` (`would_have_caught=12/15`, `caught_baseline=12/15`) once the budget accepts the measured counts.
60+
61+
## Economics and parity
62+
63+
Against the immutable base, the three retired function spans contain 267 physical
64+
lines (269 including separating lines). Production Python is 185 lines smaller;
65+
TS grows by 109; net production is 76 lines smaller. The primary-action module
66+
shrinks 347 → 152 lines. The new Python facts codec is 77 lines plus its
67+
separators; remaining Python changes are transport/result plumbing. The TS
68+
helper contains 14 lines of local view decoders (`facts`, `object`, `text`,
69+
`rows`, `count`), not another RPC surface. The bounded
70+
companion refactor reuses `action_selection_context` rather than a second
71+
admission-fact encoder. Broader admission, monitor and trace migration is deferred.
72+
73+
One untimed base/head execution and one logical-request trace per command,
74+
with isolated synthetic SQLite fixtures and one or three delegation bindings:
75+
76+
| Command | Bindings | Crossings base → head | Stdout bytes base → head |
77+
| --- | --- | --- | --- |
78+
| `agent-context --phase before_plan` | 1 | 1 → 1 | 1885 → 1885 |
79+
| `agent-context --phase after_delegate_result` | 1 | 3 → 3 | 1612 → 1612 |
80+
| Same result phase with a Turn instance | 1 | 3 → 3 | 2594 → 2594 |
81+
| `quota should-run` | 1 | 75 → 75 | 25520 → 25520 |
82+
| `agent-context --phase before_plan` | 3 | 1 → 1 | 2247 → 2247 |
83+
| `agent-context --phase after_delegate_result` | 3 | 3 → 3 | 1612 → 1612 |
84+
| Same result phase with a Turn instance | 3 | 3 → 3 | 2594 → 2594 |
85+
| `quota should-run` | 3 | 75 → 75 | 25904 → 25904 |
86+
87+
All eight normalized JSON outputs match after excluding timestamp keys ending
88+
in `_at`, `context_id`, `event_id` and `staleness_seconds`. This is equal byte
89+
count and normalized-content evidence, not literal equality of volatile fields
90+
or a latency improvement claim. No persisted-format change or data migration.
91+
92+
## Validation and remaining gates
93+
94+
A pre-change synthetic fixture pins 182 cases: all modes, candidate-source
95+
precedence, fallback and lane-count branches, empty/invalid source shapes,
96+
booleans, numbers, nested values, whitespace, Unicode/non-BMP and truncation.
97+
Native tests check those independently pinned instructions and the recovery
98+
getter sentinel; Python checks codec views, non-JSON `str` and projection order.
99+
Existing Python CLI/Host integration assertions are retained. Retire the pinned
100+
Python payload/view fixture when its last codec consumer exits and native
101+
invariant tests independently cover the same wording/source branches.
102+
103+
The oversized-backlog regression pins 22,000 rows through the public Python
104+
projection: the lane instruction matches BASE, and rejected selection preserves
105+
the BASE recovery command with `must_attempt` and `delivery_allowed` both false.
106+
Encoded instruction facts stay below 16 KiB.
107+
108+
<!-- validation-results -->
109+
Independent review's rule table found EQUIVALENT selection semantics with one
110+
DIVERGENT row for oversized eager transport; the bounded first-selectable-row
111+
carrier fixes it: facts for 22,000 rows shrink 2,354,852 → 959 bytes, with lane
112+
and rejected-selection recovery outputs byte-identical to base and pinned in
113+
tests. The fix passes 38 arbitration tests, 37 native tests and 309 Python
114+
adapter tests, including 182-case typed-instruction parity. The `goal_boundary`
115+
vocabulary budget decision moves Python/TypeScript 30/2 → 29/3 together with
116+
`RETIREMENT_ANCHOR` in this commit; the smoke reports
117+
`semantic-vocabulary-drift-smoke: ok`, architecture tests pass 128/128, and
118+
retrodiction returns to the unchanged 12/15 baseline. The full TS suite passes
119+
5,528 tests with 0 failures and 75 PostgreSQL skips. The original full Python
120+
suite records 27,169 passed, 908 failed, 234 skipped and 8 errors; base replay
121+
of its 147 failing files records 2,353 passed, 905 failed, 18 skipped and
122+
8 errors, reproducing 913/916 distinct failure/error IDs under the same guard,
123+
whose restrictions induced some failures. Of the three head-only failures,
124+
the two architecture failures are repaired above; the third is
125+
environment-induced because dashboard dependencies were installed mid-validation,
126+
while base skips that test. The final-code 44-module sweep has identical sets
127+
of 84 failures on base and head, zero new failures, 1,871 → 1,880 passes and
128+
20 skips on each; these scoped runs do not establish a green full Python suite.
129+
The final canary reports status: `passed`, ok: `true`, merge_gate_passed: `true`,
130+
manual_holds: `0`, with 0 failures. The four interleaved benchmark runs
131+
(25 timed runs and 3 warmups per command) retain equal bytes on all eight
132+
commands and unchanged 1/3/3/75 crossings for both binding counts; every median
133+
regression is within the stated 5% rule, so byte, crossing and median checks
134+
pass without a latency-improvement claim. CI-only limits remain a real
135+
PostgreSQL server, Node 22.22.3, Windows and browser lanes; PostgreSQL skips
136+
are not passes. Main's inherited failures remain tracked by #7433–#7436 and
137+
#7389; this validation does not resolve them.
138+
139+
Installed wheel, minimum Node, Windows, real PostgreSQL and full CI are not
140+
qualified locally; PostgreSQL skips are not passes. The committed-head bilingual
141+
check and premerge canary remain orchestrator/validation responsibilities. These
142+
holds do not authorize broader authority/provider changes or weaker acceptance.
143+
Rollback is a code-only revert; no state rewrite is needed.
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
# Primary-action 指令选择
2+
3+
[English mirror](2026-10-27-primary-action-instruction-selection.md)
4+
5+
## 边界与归属
6+
7+
本 Stage 2B 切片删除 Python 指令决策 owner,保持调用方可见文字和渲染。
8+
`work_items/interaction_contract.ts` 中的 `projectInteractionExecution` 在原有
9+
`work_item.interaction_execution.project` 请求内同时选择 mode 与 primary 指令。
10+
不新增 operation、handler 注册、runtime、provider 或 store。
11+
下述验证 hold 解决之前,资格仍未完成。
12+
13+
删除 `work_items/primary_action.py` 中的 Python 符号:
14+
15+
- `protocol_first_candidate_action`:来源优先序、带地址标签、capability 候选数量、
16+
scoped successor 与 advancement 回退。
17+
- `protocol_replan_action_packet_instruction`:仅结算、successor 和通用 typed-outcome 文字。
18+
- `resolve_canonical_primary_action`:各 mode 的精确文字、回退和 child/peer lane 数量,
19+
包括空 child 列表优先于 peer lanes 的规则。
20+
21+
`interaction_contract.py::_project_interaction_execution` 发送一个可选 facts/views
22+
carrier 和现有 `action_selection_context` 投影。最终 contract builder 请求并将返回
23+
指令经 `_build_interaction_agent_channel` 传入 `build_primary_action_projection`。
24+
`unadmitted_action_selection` 保留仅 mode 的 preflight 和精确结果形状。
25+
TS owner 在读取指令事实前组合 `actionSelectionNeedsRecovery`;rejected/deferred
26+
恢复不构建可执行指令。既有 Python 恢复分支、selection/capability channel 覆盖、
27+
blocked-successor 覆盖及 blocked-wait 覆盖均保留。
28+
29+
Python 保留 `protocol_action_text` 和 `protocol_action_label`:Python `str`、嵌套
30+
repr、真值、空白、标签前缀和按码点限制都是兼容 codec,包括 `...`,而非 trace
31+
codec 的 `…`。`primary_action_instruction_facts` 传递这些视图及现有 Todo 资格/
32+
lifecycle 来源事实,不选择指令,也无 Python 决策回退。Python 对每个列表来源至多
33+
传输从相同强制转换视图判定的首个可选行;typed owner 应用相同谓词和来源优先序。
34+
请求大小不随 backlog/Todo 列表长度增长。已注册 effective action 和
35+
agent-scope 值导入生成的 TS exports。其他现有局部规则字符串保持精确拼写;
36+
不新增共享词汇或持久化 schema。
37+
38+
Python 还保留 `protocol_monitor_action` 和经
39+
`state_projection.next_action_resolution_trace` 构建的 resolution trace。
40+
`primary_action` 仍先于可选 `resolution_trace`;channel 插入顺序和最终 Python JSON
41+
序列化不变。仅当剩余消费者采用完整 typed action/trace 投影时,才删除 trace/monitor
42+
facade。仅当最后一个 Python text/label 消费者退出,且完整 typed 兼容 codec 证明
43+
Python coercion、Unicode、截断及 trace 等价时,才删除 scalar/label codec 和 facts
44+
carrier。本切片不宣称这些 owner 已退役。
45+
46+
## 词汇预算
47+
48+
registry 的 `meaning` 写明 "module_budget counts modules under loopx/ whose text carries the standalone field token" 和 "the token count stays until Q11 decides whether the syntactic metric replaces it";这一刻意保守的词法代理用于防止潜在字段 reader 数量出现无解释增长。
49+
在相同 tracked-source 负载上,base `be1dc37a0` → `this commit` 的 `goal_boundary` 词法计数从 Python/TypeScript 30/2 → 29/3(总数仍为 32),原始失败为 `legacy field goal_boundary grew to 3 .ts modules; budget is 2`,以及 retrodiction `(13, 15)` 对比冻结值 `(12, 15)`。
50+
迁移的句子 `repair goal_boundary.write_scope projection before attempting the selected write` 是逐字节一致的 agent-facing 文字,未新增 reader、writer 或 binder;smoke 对文字与 reader 的区分使 migration surface 保持 Python 16 / TypeScript 1。
51+
保留该指令,registry 将 Python token 预算收紧至实测 29,并将 TypeScript 从 2 增至 3,词法余量为零;migration-surface 预算及其 anchor 维持 16/1 不变,而 registry 与 `RETIREMENT_ANCHOR` 按 anchor 机制要求在同一提交中一起调整;retrodiction 基线不变,预算接受实测计数后,实测结果恢复为 `(12, 15)`(`would_have_caught=12/15`、`caught_baseline=12/15`)。
52+
53+
## 经济性与等价
54+
55+
相对固定基线,三个删除函数跨度共 267 物理行(含间隔行则为 269)。生产 Python
56+
净减 185 行,TS 增 109 行,生产总代码净减 76 行。primary-action 模块从 347 行缩为
57+
152 行。新增 Python facts codec 为 77 行加间隔;其余 Python 变化为 transport/结果
58+
传递。TS helper 内有 14 行局部 view decoder(`facts`、`object`、`text`、`rows`、
59+
`count`),不另建 RPC surface。伴随的有界重构复用 `action_selection_context`,不另建 admission facts 编码器。
60+
更广的 admission、monitor 和 trace 迁移延后。
61+
62+
在隔离的合成 SQLite fixture 上,分别使用 1 或 3 个 delegation binding;每条命令
63+
各执行一次不计时的 base/head 输出和一次逻辑请求 trace:
64+
65+
| 命令 | Binding 数 | Crossings base → head | Stdout 字节 base → head |
66+
| --- | --- | --- | --- |
67+
| `agent-context --phase before_plan` | 1 | 1 → 1 | 1885 → 1885 |
68+
| `agent-context --phase after_delegate_result` | 1 | 3 → 3 | 1612 → 1612 |
69+
| 同一 result phase,带 Turn instance | 1 | 3 → 3 | 2594 → 2594 |
70+
| `quota should-run` | 1 | 75 → 75 | 25520 → 25520 |
71+
| `agent-context --phase before_plan` | 3 | 1 → 1 | 2247 → 2247 |
72+
| `agent-context --phase after_delegate_result` | 3 | 3 → 3 | 1612 → 1612 |
73+
| 同一 result phase,带 Turn instance | 3 | 3 → 3 | 2594 → 2594 |
74+
| `quota should-run` | 3 | 75 → 75 | 25904 → 25904 |
75+
76+
排除以 `_at` 结尾的时间字段、`context_id`、`event_id` 和 `staleness_seconds` 后,
77+
八组规范化 JSON 均一致。这证明字节数和规范化内容等价,不代表易变字段字面一致,
78+
也不宣称延迟提升。不改变持久化格式,无数据迁移。
79+
80+
## 验证与剩余门禁
81+
82+
修改前合成 fixture 固定 182 个案例:全部 mode、候选来源优先序、回退及 lane 数量
83+
分支、空/非法来源形状、布尔值、数值、嵌套值、空白、Unicode/非 BMP 和截断。
84+
原生测试核对独立固定的指令和 recovery getter sentinel;Python 核对 codec 视图、
85+
非 JSON `str` 及投影顺序。既有 Python CLI/Host 集成断言保留。仅当最后一个 codec 消费者退出,且原生
86+
invariant 测试独立覆盖相同文字/来源分支时,才删除固定的 Python payload/view fixture。
87+
88+
超大 backlog 回归通过公开 Python 投影固定 22,000 行:lane 指令与 BASE 一致,
89+
rejected selection 保留 BASE 恢复命令,且 `must_attempt` 和 `delivery_allowed` 均为 false。
90+
编码后的指令事实保持在 16 KiB 以下。
91+
92+
<!-- validation-results -->
93+
独立 review 的规则表判定选择语义为 EQUIVALENT,仅超大 eager transport 一行为
94+
DIVERGENT;有界首个可选行 carrier 修复该问题:22,000 行的 facts 从
95+
2,354,852 字节缩至 959 字节,lane 与 rejected-selection recovery 输出均与 base
96+
逐字节一致,并由测试固定。修复通过 38 项 arbitration、37 项原生及 309 项 Python
97+
adapter 测试,包含 182 案例 typed-instruction parity。`goal_boundary` 词汇预算决策
98+
将 Python/TypeScript 从 30/2 调整为 29/3,并在本提交中同步调整
99+
`RETIREMENT_ANCHOR`;smoke 报告 `semantic-vocabulary-drift-smoke: ok`,
100+
architecture 测试 128/128 通过,retrodiction 恢复至未变的 12/15 基线。
101+
完整 TS suite 为 5,528 项通过、0 项失败、75 项 PostgreSQL skip。原始完整 Python
102+
suite 记录 27,169 项通过、908 项失败、234 项 skip、8 项 error;base 重放其
103+
147 个失败文件,记录 2,353 项通过、905 项失败、18 项 skip、8 项 error,
104+
在相同 guard 下复现 913/916 个不同的 failure/error ID,其中部分失败由 guard
105+
限制引起。三个 head-only 失败中,两个 architecture 失败已由上述修复解决;第三个
106+
由环境引起,因为验证期间安装了 dashboard 依赖,而 base 跳过该测试。最终代码的
107+
44 模块 sweep 在 base 与 head 上具有完全相同的 84 个失败,新增失败为零,
108+
通过数为 1,871 → 1,880,两边各有 20 项 skip;这些限定范围的运行不能证明完整
109+
Python suite 全绿。最终 canary 报告 status: `passed`、ok: `true`、
110+
merge_gate_passed: `true`、manual_holds: `0`,失败数为 0。四轮交错 benchmark
111+
运行(每条命令 25 次计时、3 次 warmup)中,八条命令的字节数全部相等,两种 binding
112+
数量的 crossings 均维持 1/3/3/75;每项中位数回退均在既定 5% 规则内,因此字节数、
113+
crossing 和中位数检查通过,不宣称延迟提升。仅 CI 可验证的限制仍包括真实
114+
PostgreSQL server、Node 22.22.3、Windows 和 browser lanes;PostgreSQL skip
115+
不等于通过。main 的继承失败仍由 #7433–#7436 和 #7389 跟踪;本次验证未解决它们。
116+
117+
本地未验证 installed wheel、最低 Node、Windows、真实 PostgreSQL 及完整 CI;
118+
PostgreSQL skip 不等于通过。提交确切 head 后的双语检查和 premerge canary 由
119+
orchestrator/验证工程师负责。这些 hold 不授权更广的 authority/provider 修改或
120+
降低验收。回滚仅需撤销代码,无需改写状态。

0 commit comments

Comments
 (0)