Repository navigation
fix(architecture): restore the top-level module budget gate after #6703 - #6734
Conversation
loopx-project#6703 added loopx/chat_turn_release.py as a new top-level module without lowering the pinned top-level count, so the required Python Tests pytest shard fails 146 against 145 for every PR based on main. Relocate the 30-line TurnReleaseWakeup helper into the existing loopx/capabilities/native_chat/ package, which chat_runtime.py already imports for its native-chat companions, and update its only importer. No behavior change; the top-level budget and the module-size ratchet both pass again. Closes loopx-project#6728. Signed-off-by: JasonBuildAI <jasonbuildai@gmail.com>
JasonBuildAI
left a comment
There was a problem hiding this comment.
Independent agent review of d37839b29b18c42120da1795961e4c070e7dfcdb (base f9bdae675). The reviewer was given only the issue text, the complete diff, and the reproduction/check commands; it verified them read-only and posted nothing else. This is an AI-agent review record, not a human approval.
Verdict: APPROVE WITH NOTES. No blocking findings.
What was verified
- Importance is real. At the base, the top-level count is 146 against the pinned 145 and
pytest -q tests/architecture/test_top_level_module_budget.pyfails1 failed, 5 passed; at the head it is 145 and6 passed.fdf03ec6had 145, #6703 (dc3feb5) moved parent 145 → child 146 by addingloopx/chat_turn_release.py, anda4483aae..f9bdae675added no other top-level module. - The gate is required.
CONTRIBUTING.mdnames onlySign-offandmerge-gateas merge-blocking;merge-gateneedspytest, whose six shards fail the job on one test failure. #6703's rollup showstest-shardandpytestCANCELLEDbefore merge, so this regression never ran the gate. - Scope is one problem. The diff is an
R100rename (identical blobeadccc2c…) plus one import line inloopx/chat_runtime.py; one commit, DCO trailer present,git diff --checkclean, no docs/tests/cleanup. - No logic or compatibility issue. No remaining reference to
loopx/chat_turn_release; no import cycle (stdlib-only module in an empty-__init__package, and no capability auto-discovery enumerates it); the module is a day-old private helper with one importer and no shipped import contract. - Checks reproduced. Architecture trio
35 passed in 38.41s;tests/test_lark_delivery_wakeup.py tests/test_chat_turn_wait.py2 failed, 7 passedidentically on base and head with the sameexecutable_not_foundfake-codexWindows stack;tests/test_chat_session_active_turn.py52 passed; maintainability ratchetok,unreviewed: 0; ruff clean. - The ratchet forced the placement.
loopx/chat_runtime.pyis 2209 lines, one line under its reviewed 2210 ceiling, so inlining would have failedcontrol-plane-maintainability-ratchet-smoke.py; moving below the package root was the smallest compliant repair.
Non-blocking notes
- Hosted CI on this exact head is still pending; merge readiness still needs the required checks.
- Pre-existing (not changed here): the budget test's diagnostic names the reverse-alphabetically last module (
workflow_skill_install.py), not the actually added one. loopx/capabilities/native_chat/is a defensible but loose semantic home for a generic wakeup helper;chat_runtimealready imports that package for its native-chat companions.- The direct
TurnReleaseWakeupregister/notify assertions sit inside a test that fails early on this Windows host, so those assertions execute on Linux CI rather than in the author's local run.
Reviewed head unchanged since: d37839b29b18c42120da1795961e4c070e7dfcdb.
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
动机
运行 Python 检查和聊天回复 worker 的维护者,需要默认检查可用且原来的唤醒行为保持。
同一预算测试在 base 的原始输入下因146超过145失败,迁移后保持预算145并通过,聊天 worker 仍能注册、唤醒和注销。
当前 head 恢复既有模块预算,移动的30行 helper 字节相同,打包后的 chat_runtime 导入和 Event 行为通过。
不认证原生 Windows、全部主干检查或长期稳定性,不扩大到整个分包迁移,也不执行合并或安装升级。
改动思路
没有发现阻断项,建议 APPROVE。模块数量预算是为了让顶层扩张可见,不是为了鼓励换个名字隐藏决策。这里确实把内部 helper 迁到已经使用的 native_chat 包,旧入口被删除,既有唯一调用者同步更新;没有重复一份逻辑。
复用既有 native_chat 包与同一个 Event helper,删除旧入口,仅改唯一 import;没有新增配置、状态或兼容桥。
当前 PR 边界是恢复 top-level 预算并保留既有 Turn-release 唤醒,不承诺完成后续分包里程碑。
不改会继续让无关提案继承预算红灯;把类内联回 chat_runtime 会触及其2210行维护性门;单纯把预算改成146也不解决这次独立模块的放置问题。当前迁移已有调用和归属,较小且可逆。它不完成整个包拆分,也不新增一层抽象或兼容入口。
具体改动
完整 head d37839b29b18c42120da1795961e4c070e7dfcdb,base f9bdae67596c185cebc81dc555dd6a3e0242e9c5。全 PR 是2条变更路径、一个100% rename及一行 import 替换;被移动的30行 helper 在两侧 Git blob 都是 eadccc2c159019dd56a4378a1716dbdb9bad34ba。
先于 diff 阅读的规范是 docs/architecture/rfcs/monorepo-distribution-split-v0.md 在完整提交 f9bdae67596c185cebc81dc555dd6a3e0242e9c5,以及 #6728 的 Expected behavior。适用的 M0 是预算测试通过且数量保持 pin;I3 明确内部移动应更新调用者并删除旧入口,只有已建立的公开 import 才需要兼容窗口。没有用这个 PR 自己的声明当规范。
chat_runtime.py:25 现在从 capabilities.native_chat.turn_release 导入 TurnReleaseWakeup。TurnReleaseWakeup.__call__ 继续在锁内登记 Event、拒绝重复登记,并在 finally 注销;notify:24 仍先取快照,再逐一 set,既不传 Session 或正文,也不调用 transport。完整 tracked 源搜索未发现旧 chat_turn_release 引用,包初始化没有新增 discovery 行为。
独立预算对照没有改 pin:base 对应输入为146、head为145。实际旧测试在另一个同 base 的 sibling checkout 跑出1 failed/5 passed;该 checkout 虽另有两条无关 finance新增文件,但被测试读取的整个 loopx 树、测试及 JSON fixture 与不可变 base 逐字节相同。这是相同旧输入的复现,不能冒称那个 sibling 的整个树就是 base。
当前 head 的预算、导入边界、package/kernel ratchet、Lark delivery wakeup、chat turn wait 和 active-turn 六个模块共96 passed。后面三套走真实本地 journal/worker,外部 runtime/transport 是合成 fixture;不是独立 Lark 或 Windows 资格。另正常构建 Chat bundle 与 wheel,把 wheel 解压到空临时目录,用 Python -S 从包内导入 chat_runtime;登记、notify、重复拒绝及注销后不再唤醒都通过,source checkout 和 site-packages 不在这条加载路径中。
对主干的风险
主要风险是模块移动导致打包漏文件或遗漏调用者;源码全量引用搜索、字节相等、实际 wheel 加载和 source 行为测试覆盖了这两个路径。旧 import 仅是前一修复新增的内部 helper,没有找到外部契约或持久化导入引用,保留壳反而会让预算继续溢出,因此当前不需要兼容桥。
Ruff、DCO、diff hygiene、advisory 后完整 semantic、两条公开候选路径扫描都通过。标准 premerge 为6 direct +10 selected,0失败、0 manual hold;这不是合并授权,也没有查询或等待 CI。公开扫描仍有隔离 HOME 缺 registry 的警告,0 error。
第一次 wheel 构建被旧的本地 Chat bundle fingerprint 拒绝,尚未产出可验证包;正常运行现有 build:chat 生成并验证 bundle 后,相同 wheel 路径通过。保留这个准备失败,没有关闭打包检查或改代码。作者的 Windows fake-codex/mypy 限制按作者证据保留,本次 macOS96测试通过不代表我独立认证了 Windows。
我的整体评价
APPROVE,准确 head d37839b29b18c42120da1795961e4c070e7dfcdb。M0 和 I3 的本次适用要求满足;helper 行为保持、预算恢复、包内路径可读,未发现当前范围的阻断项。
复用既有 native_chat 包与同一个 Event helper,删除旧入口,仅改唯一 import;没有新增配置、状态或兼容桥。
当前 PR 边界是恢复 top-level 预算并保留既有 Turn-release 唤醒,不承诺完成后续分包里程碑。
相邻未来改动检查已应用:这次去掉旧内部入口,复用已有 package 与唯一规则,下一次变更仍只改一处。更大规模 chat 分包属于另一个已存在的 RFC 阶段,无需为了本次修复增加新任务。原有用户操作零新增导航、抄写或确认轮次,没有新的 frontend/Lark 用户能力要增加界面;唤醒仍只是已有 journal 的读者提示,不能变成完成证据或执行权限。
English verdict: APPROVE - d37839b. The private R100 move restores the unchanged145-module pin and preserves the wakeup helper byte-for-byte.96 focused tests,6direct/10selected premerge checks, and a fresh wheel import/Event lifecycle pass. Native Windows and full-main health remain unqualified.
songoow
left a comment
There was a problem hiding this comment.
动机
这条改动要解决的是主干上一项必需的架构预算检查已经确定性失败的问题。触发场景很普通:一位维护者或贡献者提交一个会运行 Python 测试的 PR,本地的 pytest 分片和远端 Python Tests 任务都会执行 tests/architecture/test_top_level_module_budget.py。受影响的是维护者与贡献者:他们提交的 PR 会运行 Python Tests,而这条必需的架构检查在主干上确定性失败,使他们无法区分继承来的失败和自己改动引入的回归。改动前,在未修改的主干上运行该预算测试会报出顶层模块从 145 增至 146;改动后,同一个命令在受审查 head 上返回 6 passed,顶层模块数回到 145。可观测结果是架构预算测试在受审查 head 上通过、顶层模块数为 145,且 TurnReleaseWakeup 仍只被 loopx/chat_runtime.py 导入。本 PR 不改写预算上限、不做更宽的 loopx/chat_* 包重组,也不改变 TurnReleaseWakeup 的行为。不合并的代价是每条相关 PR 继续携带着无法归因的必需检查失败,评审和合并判断被持续污染。
改动思路
做法是把 30 行的进程内唤醒登记器从顶层搬到它唯一调用方已经依赖的子包里,并把那一行导入指向新位置,属于最小可行修复。控制流没有变化:调用方 loopx/chat_runtime.py 仍然在模块加载时导入同一个类,构造、__call__ 注册上下文、notify() 广播 threading.Event 的路径完全不变。所有权边界也没有变化:这个 helper 依旧只是 native_chat 相邻的本地实现,而不是新的控制面能力;之所以放进 loopx/capabilities/native_chat/,是因为 chat_runtime.py 已经为 codex_context、project_context 导入了同一个包,不需要发明新的顶层边界。真正的把关者仍是既有测试 tests/architecture/test_top_level_module_budget.py::_top_level_modules,它统计 loopx/*.py 数量并与 tests/architecture/top_level_module_budget.json 的 max_top_level_modules: 145 比较;每个机制都已经放在正确的边界上:预算不变量留在架构测试与固定夹具里,唤醒 helper 作为本地实现留在唯一调用方已经依赖的包内,因此现在不需要进一步简化。本 PR 的交付边界只是恢复 145 个顶层模块的预算;更宽的 loopx/chat_* 重组留给 issue 6728 记录的 M1 决策。本 PR 只是让这个既有的不变量重新成立,而不是新增一条规则。另一条更省事的路径是直接把上限改成 146,被否决的原因是该测试文件明确记录预算只能下调、新增顶层模块必须先有设计决策,改数字会把一条真实约束降级成摆设。
具体改动
改动面极小,只有两个文件:loopx/chat_turn_release.py → loopx/capabilities/native_chat/turn_release.py 的 100% 重命名(git diff 显示 similarity index 100%,没有任何行级变化),以及 loopx/chat_runtime.py 第 25 行的导入从 .chat_turn_release 改为 .capabilities.native_chat.turn_release。
关键符号映射如下。其一,loopx/capabilities/native_chat/turn_release.py:7 的 TurnReleaseWakeup 负责在本地维护一组 threading.Event:__call__ 在锁内拒绝重复登记并加入集合,退出时移除;notify() 在锁内取快照并在锁外 event.set(),注释明确说明事件不做 IO、不携带 Session/文本/完成权限,避免在模型 worker 或持锁状态下调用传输代码。其二,loopx/chat_runtime.py:25 的导入是该类的唯一调用入口,我用 grep -rn "turn_release import\|chat_turn_release" 在受审查 head 全仓检索,只有这一处命中,没有测试、示例、文档、序列化或外部配置引用旧路径。其三,tests/architecture/test_top_level_module_budget.py::_top_level_modules 是既有守卫,负责枚举 loopx/*.py 并与预算 JSON 比较,本 PR 没有修改它,这正是“不通过放宽门禁来变绿”的证据。
规格依据:issue https://github.com/loopx-project/loopx/issues/6728,审查修订 d37839b29b18c42120da1795961e4c070e7dfcdb。验收判据 6728-C1 要求顶层模块数等于固定值 145,由 top_level_module_budget.json 的 max_top_level_modules 与上述测试实现、并由本地运行证明;6728-C1 的验证是 python -m pytest -q tests/architecture/test_top_level_module_budget.py 在 head 上 6 passed。判据 6728-C2 要求 TurnReleaseWakeup 行为不变,落实为 100% 重命名加一行导入,并由导入冒烟与双重登记拒绝反例证明。
一个从输入到输出的例子:chat_runtime 在启动时导入 TurnReleaseWakeup,构造实例后在等待 Turn 的代码块里 with wakeup(event): 登记,另一个线程调用 wakeup.notify() 时该 event 被置位。我在受审查 head 上直接执行了这段路径:退出上下文后再 notify() 得到 notify_after_exit False(已注销不再被唤醒),而在同一个 event 上嵌套登记得到 ValueError: turn release wakeup is already registered,两条都与搬移前一致。
对主干的风险
整体风险低,但需要说明爆炸半径与验证边界。重命名属于机械搬移,gh pr diff 与本地 git diff 都显示文件内容零变化、仅新增一行导入并删除一行导入,因此不存在逻辑漂移;grep 证明没有第二处引用,也就不存在“旧路径仍被导入”导致的 ImportError 风险。若导入写错,失败模式是进程启动期 ImportError,属于立即失败而非静默降级,且被 33 个 architecture 测试覆盖,我没有观察到该路径残留。负向链路我实际走了一遍:在同一个 threading.Event 上嵌套登记会抛出 ValueError,说明搬移没有悄悄放宽登记唯一性;同时 notify() 在事件注销后不再置位,说明清理仍然生效。兼容性方面,该模块不是持久化契约、不是 CLI、不是公开协议,仓库内没有旧数据需要读回,因此不需要兼容垫片;作者声明“无兼容层”与我的检索一致。
需要保留的残余风险与缺口:我没有运行作者的完整 Windows 主机测试组合,也没有断言 tests/test_lark_delivery_wakeup.py 中两条 Windows-only fake shim 失败与本改动无关之外的更多细节——我在 macOS 环境下运行了 tests/architecture/test_control_plane_import_boundaries.py 与预算测试,共 33 passed,以及 ruff check 全绿,覆盖了本次真正变化的导入边界不变量。远端 CI 结果我没有作为评审证据,评审结论只依赖本地可复现的运行。
我的整体评价
没有阻塞性发现:改动正确地恢复了必需门禁,代价是一行导入加一次机械搬移,属于与问题规模相称的最小修复,且没有为了变绿去修改预算数字或弱化测试。交付判断是 goal_achieved:issue 6728 命名的目标(顶层模块回到 145、行为不变)在受审查 head 上已经可以独立验证,不需要虚构后续任务;长期看这条预算门禁重新具备约束力,用户体验维度不适用(无 UI/CLI 变化)但也没有回归。规格判据映射见上文 6728-C1 与 6728-C2,均已在 head 上实现并有对应验证。
我实际执行并观察到的验证:python -m pytest -q tests/architecture/test_top_level_module_budget.py → 6 passed;python -m pytest -q tests/architecture/test_control_plane_import_boundaries.py tests/architecture/test_top_level_module_budget.py → 33 passed;ruff check loopx/chat_runtime.py loopx/capabilities/native_chat/turn_release.py → All checks passed;基线复现 git checkout f9bdae67596c185cebc81dc555dd6a3e0242e9c5 后同一预算测试 → 1 failed(146 modules);全仓 grep 旧路径 → 无命中。审查 head:d37839b29b18c42120da1795961e4c070e7dfcdb。
Reviewer: model_agent, model DeepSeek Flash, provider DeepSeek, self_reported.
English verdict: APPROVE - d37839b: byte-identical move of TurnReleaseWakeup plus one import restores the 145-module budget gate; 6 passed budget test at head vs 1 failed at base, 33 architecture tests and ruff clean, no blockers.
Goal And Delivered Outcome
Impact: a required Python Tests merge-gate job is deterministically red on
main, so every PR whose Python Tests run (30 open PRs at the time of writing) inherits an unrelated failure and maintainers cannot separate it from a real regression; this PR restores the gate with a one-line import change and a byte-identical relocation.docs/architecture/rfcs/monorepo-distribution-split-v0.mdM0 / Section 9.maincarries 146 top-level modules whiletests/architecture/top_level_module_budget.jsonpins 145, because fix(lark): wake existing reply workers when durable work arrives #6703 addedloopx/chat_turn_release.pywithout moving another module below a package root. The required Python Testspytestshard therefore fails deterministically on unmodifiedmain, somerge-gateis red for every PR whose Python Tests run (30 open PRs at the time of writing; docs- or presentation-only PRs that skip the Python Tests workflow are unaffected) and maintainers cannot separate an inherited failure from a real regression in a PR.f9bdae67596c185cebc81dc555dd6a3e0242e9c5,python -m pytest -q tests/architecture/test_top_level_module_budget.py→1 failed, 5 passedwithloopx/ grew from 145 to 146 top-level modules. At this head the same command →6 passed, the top-level count is 145, andloopx canary premerge --from-git-diff --git-diff-base upstream/main→status: passed,manual_holds: 0.loopx-project/loopx:mainatf9bdae67596c185cebc81dc555dd6a3e0242e9c5.Author Declaration
Implemented against
tests/architecture/top_level_module_budget.json(max_top_level_modules: 145,baseline_commit: a4483aaece5bc74ec3f969fd067229487022401b) and the module metric ceiling forloopx/chat_runtime.pyinloopx/canary/module_metric_baseline.json, both atf9bdae67596c185cebc81dc555dd6a3e0242e9c5.loopx/*.pycount must equal the pinned 145loopx/capabilities/native_chat/turn_release.py;loopx/chat_turn_release.pyremovedpython -m pytest -q tests/architecture/test_top_level_module_budget.py→ 6 passedloopx/chat_runtime.pymust stay inside its reviewed module-size ceilingloopx/chat_runtime.py(import-only change)python examples/control_plane/control-plane-maintainability-ratchet-smoke.py→ ok,unreviewed: 0TurnReleaseWakeupmoved byte-identically; only the import line changedpython -m pytest -q tests/test_lark_delivery_wakeup.py tests/test_chat_turn_wait.py→ 7 passed, 2 pre-existing host failures disclosed belowpytest/mypyresults are reported with their Windows host limitations below.Scope And Continuation
Eventregistry whose only importer isloopx/chat_runtime.py; it has no code, test, example, doc or external reference other than that import. It moves into the existingloopx/capabilities/native_chat/package thatchat_runtime.pyalready imports for its native-chat companions. The class body and its comments are byte-identical, so there is no behavior change and no compatibility shim is needed. No product behavior, CLI surface, schema or vocabulary changes.loopx/chat_*→loopx/chat/M1 move), [Bug]: required Python Tests gate is red on main after #6703 added a 146th top-level module #6728 records that decision; this PR is the smallest change that restores the gate without weakening either ratchet.Validation
d37839b29b18c42120da1795961e4c070e7dfcdbregression_paritypython -m pytest -q tests/architecture/test_top_level_module_budget.py:1 failed, 5 passedon unmodifiedf9bdae675(146 against the 145 pin);6 passedat this head.git diff --statfor the change is a 100% rename plus one import line.unitpython -m pytest -q tests/architecture/test_top_level_module_budget.py tests/architecture/test_control_plane_import_boundaries.py tests/architecture/test_package_kernel_import_ratchet.py→35 passed in 37.22s.unitpython -m pytest -q tests/test_lark_delivery_wakeup.py tests/test_chat_turn_wait.py→7 passed, 2 failed. Both failures are the fake POSIXcodexshim on native Windows (CodexChatAgentError: executable_not_found); the same two tests fail identically on the unmodified basef9bdae675(2 failed, 4 passedfortests/test_lark_delivery_wakeup.pyalone), andtests/test_chat_session_active_turn.pypasses52 passed.staticpython -m ruff check loopx/chat_runtime.py loopx/capabilities/native_chat/turn_release.py→ clean.python -m mypyreports 6 pre-existing Windows-only errors aboutos.killpg/signal.SIGKILL/os.WNOHANGinloopx/extensions/process_runtime.pyandloopx/control_plane/effect_runtime.py, which this diff does not touch; hosted CI runs Linux.staticpython scripts/generate_semantic_inventory.py --changed-from HEAD→changed sources: 1 paths, 1 snapshots; supported candidates: 0;git diff --checkclean.integrationloopx canary premerge --from-git-diff --git-diff-base upstream/main→status: passed,merge_gate_passed: true, direct checks 5/5 passed, catalog canaries 10/10 passed,manual_holds: 0.self_merge_allowed: falseis the repository policy, not a check failure.mypyare not clean on this cp936 Windows host independently of this diff (the 4 remainingtests/architecturefailures aregbkcodec errors in test fixtures that do not import the changed module, and the mypy errors are POSIX-only attributes in untouched files). The changed behavior surface is the import graph only, which the 35 architecture tests plus the 7 passing wakeup/turn tests exercise; the two failing wakeup tests are host-only and reproduce on the base.Frontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
docs/architecture/rfcs/monorepo-distribution-split-v0.mdM0 / Section 9; related [Bug]: the pinned top-level module budget is already exceeded on main (150 measured against 147) #5685 (the earlier 150-vs-147 instance, no longer reproducible) and fix(lark): wake existing reply workers when durable work arrives #6703 (the introducing change).Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).AI disclosure: this change was drafted with AI assistance at JasonBuildAI's request, under their direction and constraints. An independent reviewer agent audits the exact head before handoff and records its verdict on this PR; maintainer review is requested.