Repository navigation
test(semantics): point the stale turn_route fixtures at their current owners - #7621
Conversation
5d0aa92 to
905d68b
Compare
905d68b to
0147721
Compare
Two turn_route fixtures in tests/architecture/test_semantic_production.py still named sites that no longer exist. The parametrized return-producer case named 'return LoopXTurnRoute.CONTRACT_ERROR' in driver.py. The driver now assigns the route to a local and returns a call, so the Python producer has no literal left to mutate and the test failed on its own precondition. The route vocabulary's owner is the TypeScript producer, so the case now mutates turn_envelope.ts::turnEnvelopeRoute, whose resolved returns are the route values themselves. The mutation still replaces one returned value with an unregistered one and still expects the scan to reject it, so the invariant the test proves is unchanged; only the fixture that had gone stale moves. The one-hop re-export case named loop_controller.py::_envelope_route. PR loopx-project#7523 moved that decision into loop_controller.ts and dropped the site from the turn_route producers, so the assertion collected nothing. driver.py still re-exports LoopXTurnRoute from the generated owner and _typed_route is still a registered return producer, so the case now resolves through that hop. No production code, schema, wire or default change. Validation: tests/architecture/test_semantic_production.py 42 passed on origin/main 0a9a3a3. The remaining failures in tests/architecture are pre-existing on that base: the lark import boundary (PR loopx-project#7631) and two package/vocabulary ratchets this change does not touch. Signed-off-by: xiaoan17 <anbc1224@gmail.com>
0147721 to
6a767a5
Compare
loopx-agent
left a comment
There was a problem hiding this comment.
Reviewer: model_agent; gpt-6.1-sol; OpenAI; runtime_reported; reasoning_effort=max.
动机 / Motivation
维护者检查实际生产代码是否写出未注册的路由值时,会先被过期的测试目标阻断。旧用例寻找已移除的 Python return 和 controller 函数,尚未验证扫描器就失败;新用例指向现行 TypeScript return 与 Python 导入绑定,重新执行未注册值的拒绝检查。精确 head 的生产扫描模块 42 项通过,Python 扫描模块另有 76 项通过;未注册值仍被拒绝。本 PR 只修测试目标,不改生产扫描器、路由、注册表或检查门槛。继续保留旧目标会在语义检查开始前失败,删除测试又会丢失真实源 mutation,因此原位改正目标是有价值的完整修复。
改动思路 / Approach
vocabulary_v0.json 仍是 producer 注册依据,collect_production 与 validate_production 仍拥有扫描和拒绝判断。把 TypeScript turnEnvelopeRoute 的实际 return 在内存替换为 unknown_action,再验证拒绝;另用已注册的 driver.py::_typed_route 检查现行 owner 导入绑定。没有恢复旧 Python 决策 owner,也没有改扫描规则。
具体改动 / Changes
精确 head 6a767a5cac310edb88fba3dd2521901fc8442da3,整个 PR 仅 tests/architecture/test_semantic_production.py 的 +4/-4。规范为 docs/architecture/rfcs/semantic-vocabulary-convergence-v0.md,spec_revision 2a2323756089aaaa8f414f6dc84a30fb6ed00556;采用已交付的 I11(owner 与 producer 角色)和 I13(未注册输出 fail-closed),两项均 implemented。新目标存在于原注册表,未注册返回值仍触发既有拒绝断言。未新增词汇、注册项、协议或兼容分支。
有一项非阻断命名建议:test_real_reexported_turn_owner_is_attributed_through_one_hop 现在验证的是 直接 owner 导入绑定。内存禁用 _reexported 后,该用例仍通过;既有 test_one_unrenamed_reexport_hop_binds_the_owner 则会失败。建议将前者及注释改名,避免把它解释成一跳 re-export 的集成证据;真实 re-export 正反例仍由独立测试保护。
对主干的风险 / Risks
无阻断发现。重点检查了“测试全绿但覆盖变弱”的反例,并以上述故障注入分清直接导入与 re-export 的范围。PASS:本 head 生产扫描模块 42 项、Python production 模块 76 项,Ruff 通过;标准 premerge 5 项直接检查及 maintainability-ratchet、semantic-vocabulary-drift 两项 smoke 通过。按策略未查询 CI。其他架构与全量发布失败未在这里重标为通过。
现有 synthetic 测试不能替代真实 tracked-source mutation,二者保留有实际价值;有界检查同作者最近 8 项 PR 未发现本 mutation 修复的重复提案。
我的整体评价 / Verdict
此 PR 的 fixture 修复达到 goal_achieved;运行时无 diff,long_horizon 为 preserved,user_experience 为 not_applicable。视觉检查不适用:仅测试目标变动,未验证渲染范围为 none。相邻扫描器重构无必要,命名可以进一步澄清;没有需要阻断合并的行为问题。完整发布验收与合并权限仍须单独满足。
English verdict: APPROVE — 6a767a5; no blocking finding. 42 production tests, 76 Python production tests, Ruff and seven premerge checks pass. Rename the direct-import test for clarity; full release qualification remains separate.
Scope
Two stale
turn_routefixtures intests/architecture/test_semantic_production.py, and the main-branch breakagethey were hiding.
Both are red on
main(2a2323756), so they fail the pytest lane of every openpull request, including this repository's own.
1.
test_real_return_producer_rejects_an_unregistered_result[turn_route]This case mutates a registered return producer so that its value becomes
unregistered, and asserts the production scan rejects it. Its
turn_routecasestill named
return LoopXTurnRoute.CONTRACT_ERRORindriver.py— a literalthat no longer exists there. The driver now assigns the route to a local and
returns a call, so the Python producer has no literal left to mutate and the
test failed on its own precondition:
2.
test_real_reexported_turn_owner_is_attributed_through_one_hopThis case asserted that the registered
turn_routereturn producer resolvesthrough the driver's one-hop re-export. It named
loopx/control_plane/turn_driver/loop_controller.py::_envelope_route, a sitethat PR #7523 removed when it moved the decision into
loop_controller.tsanddropped the site from the
turn_routeproducers. The assertion thereforecollected nothing and failed:
Fix
Both cases are retargeted at the sites that own the values today. The
invariant each test proves is unchanged — only the fixture that had gone stale
moves.
The route vocabulary's owner is the TypeScript producer, so the case now
mutates
turn_envelope.ts::turnEnvelopeRoute, whose resolved returns arethe route values themselves. The mutation still replaces one returned value
with an unregistered one and still expects the scan to reject it.
driver.pystill re-exportsLoopXTurnRoutefrom the generated owner, and_typed_routeis still a registered return producer, so the one-hop case nowresolves through that hop and still asserts the route value is observed.
No production code, schema, wire or default change.
Validation
On
origin/main2a2323756:tests/architecture/test_semantic_production.py— 42 passedruff check tests/architecture/test_semantic_production.py— cleanThe remaining
tests/architecture/failures on that base are pre-existing andnot touched by this change:
test_lark_projection_sinks_are_owned_by_the_extension_layer— aproduction-code import boundary, fixed separately in fix(chat): keep the provider reply projection in the composition root #7631.
test_packages_import_exactly_the_pinned_loopx_modulesandtest_explicit_output_evidence_cannot_be_removed_or_redirected[call_producers-loop_disposition]— refactor(turn): qualify receipts and continuation in the typed owner #7523 fallout on the package-import ratchet and the vocabulary drift
check, tracked separately.
Signed-off-by: xiaoan17 anbc1224@gmail.com
Rebase and re-validation (2026-10-29)
mainat9dcdc0bacd455a8cf6f6146f052ffc4df0f5d04a6a767a5cac310edb88fba3dd2521901fc8442da3This is one of six pull requests that together restore
mainto green. Onmainat9dcdc0bacd455a8cf6f6146f052ffc4df0f5d04athe repository is red in exactly eight places, and this one owns two of them:tests/architecture/test_semantic_production.py::test_real_return_producer_rejects_an_unregistered_result[turn_route-loopx/control_plane/turn_driver/driver.py-...]tests/architecture/test_semantic_production.py::test_real_reexported_turn_owner_is_attributed_through_one_hopThe other six are owned by #7631, #7632, #7640, #7642 and #7646. None of the eight is caused by a pull request in this set.
All nine pull requests in this set were rebased onto
mainat9dcdc0bacd455a8cf6f6146f052ffc4df0f5d04aand merged together in a local worktree. The merged state passestests/architecture/,tests/canary/,tests/test_manager_context_roundtrip.py,tests/test_lark_native_reply_context.py,tests/control_plane/test_host_adapter_settlement_step_vocabulary.pyandtests/control_plane/test_host_adapter_settlement_partial_steps.py— 1805 passed, 0 failed.python scripts/generate_rfc_status_index.py --checkis clean.