Feat/four contributor tasks - #3078
Conversation
Add read-only global risks command surfaced from status health items, global registry findings, and run history stale runs. Follows the same pattern as /loopx-global-gates and /loopx-global-todos: - loopx/global_risks.py: build_global_risks, error envelope, markdown renderer - CLI handler: global-risks subcommand registration and dispatch - Schema: global_manager_command_response_v0 with risk groups Validation: global_manager_command_protocol_smoke, CLI --help
…les (GH-C68) Move the stable pure rules from quota-scheduler-state-ack-smoke.py into independently derived decision-table tests so implementation output cannot become the oracle. Coverage: - Wait backoff progression: 10→20→30→60 then cap (5 parametrized rows) - Monitor-wait progression: 15→30→60 then cap (4 parametrized rows) - Stale ack tolerance window: ±2 minutes (5 parametrized rows) - Active work keeps 3-min cadence, repairs stale state - Monitor identity ignores recommended_action text noise - Ack plan validation: 6 failure modes + already_applied - Scheduler state scope: cross-agent rejection, corrupt state ignored - Negative/mutation: wrong identity triggers reset, target change resets
Public-safe walkthrough proving stable program identity, observed head snapshots, compact diff classification, review/CI transition lineage, and fail-closed unknown state. No provider payloads, review bodies, credentials, or merge authority. Exercises 8 scenarios from the pure diff rules in the PR program skill.
Public-safe walkthrough proving stable item identity, revision-bound approval invalidation, delivery/readback receipts, supersession, and idempotent event replay. No provider calls, draft bodies, credentials, private locators, or publish authority. Exercises 11 scenarios across the full content_ops_item_v0 lifecycle.
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3078 新 head 复核(head 9c77eb09d830cf9898f21096498145d3c34f55da)
详细中文评审
动机
该 PR 以 "four contributor tasks" 提交四块内容:content-ops item 生命周期 walkthrough smoke(GH-C78)、provider-neutral PR program snapshot walkthrough smoke(GH-C81)、补齐 main 已注册但未实现的 loopx global-risks 只读命令(global_risks.py + summary_all.py 接线)、以及 scheduler stateful-backoff 决策表测试(534 行,覆盖 10→20→30→60 分钟退避与 reset 规则)。
改动思路
五个文件均为独立、可验证的交付:两个 walkthrough smoke 只做合成数据、不触达 provider/凭据/发布权威;global_risks.py 从 status/registry/history 的公开安全投影聚合风险,全部经 redact_public_text 与 public_safe_boundary() 收敛;scheduler 测试把 smoke 文档化的进度规则提取成参数化决策表,避免以实现输出作为 oracle。方向正确、边界干净。
关键代码讲解
tests/control_plane/test_quota_scheduler_state_backoff.py把from __future__ import annotations放在模块 docstring 之前,导致 Ruff 把 docstring 视为普通表达式语句,后续 8 处 import 全部触发 E402(CI Lint test suite 23s 失败,含 16/18/19/20/24/27 等行)。修复:把模块 docstring 移到from __future__之前,或删除 docstring,恢复仓库惯例。loopx/global_risks.py的build_global_risks_error与 markdown renderer 均对错误文本脱敏;build_global_risks只消费 status/registry/history 的公开投影,omissions明确声明不记录原始日志、凭据、本地路径。summary_all.py新增global-risksparser 与 handler 分支,接入已有/loopx-global-risksslash-command 注册(main 已含slash_commands.py/slash_command_install.py/canary/planner.py引用),补齐命令面。
对主干的风险
- P1(阻塞):CI pytest(Lint test suite)失败——新测试文件 8 处 Ruff E402;这是本 PR 自带的 lint 回归,先修再合入。
- P2(非阻塞):PR 模板卫生——
Summary为-、Closes #为空、Validation/Boundary 复选框未勾选;下次提交补上并附实际验证输出。 - 未发现其他阻塞项:
build与dependency-review全绿;行为面本地验证全部通过。
验证
- exact head
9c77eb09:py_compile通过(global_risks.py / summary_all.py / 新测试文件)。 - 本地运行:两个 walkthrough smoke 均通过(content-ops 11 步、pr-program 8 步,exit 0);新测试文件 31 passed;
test_cli_output_budget.py/test_actual_default_model_behavior_portfolio.py/test_cli_argument_diagnostics.py/test_turn_envelope.py/test_quota_markdown_boundary.py/test_cli_entrypoint.py合计 149 passed。 - CI:pytest FAILURE(仅 E402 lint,23s 即失败)、build SUCCESS、dependency-review SUCCESS。
我的整体评价
四块内容职责清晰、边界处理到位,测试与 smoke 质量高;唯一阻塞是本 PR 引入的 lint 回归(docstring/__future__ 顺序),修复是单点小改。修复并让 pytest 全绿后即具备合并条件,结论 REQUEST_CHANGES。
Review: REQUEST_CHANGES
Head: 9c77eb09d830cf9898f21096498145d3c34f55da
Verdict: Request changes — the four deliverables are well-scoped and locally verified (both walkthrough smokes pass; new scheduler decision-table tests 31 passed; 149 related tests pass; build/dependency-review green), but CI pytest (Lint test suite) is red with 8 Ruff E402 errors in tests/control_plane/test_quota_scheduler_state_backoff.py: from __future__ import annotations precedes the module docstring, so every subsequent import is flagged as not-at-top. Move the module docstring above the future import (or drop it) and re-run the lint suite. Non-blocking: fill the PR template (Summary, Closes #, validation/boundary checkboxes).
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3078 新 head 复核(head ac50f76718b4e631c298e787410cd640a59b1e12)
详细中文评审
动机(本次 head 更新)
上一轮 REQUEST_CHANGES 指出的 P1 是 tests/control_plane/test_quota_scheduler_state_backoff.py 的 8 处 Ruff E402(from __future__ 放在模块 docstring 之前导致后续 import 全部被判为不在文件顶部)。作者本次仅提交一个 commit:把模块 docstring 移到 from __future__ import annotations 之上,diff 共 2 行增、2 行删,聚焦且无附带改动。
验证
- exact head
ac50f767:diff 仅限目标测试文件;本地py_compile通过。 - 本地测试:新决策表测试 31 passed,加上 output-budget / portfolio / 参数诊断 / turn-envelope / quota-markdown / CLI entrypoint 合计 180 passed。
- CI:pytest SUCCESS、build SUCCESS、dependency-review SUCCESS(此前 lint 失败已消除)。
对主干的风险
无阻塞项。上一轮 P2(PR 模板卫生:Summary 为 -、Closes # 为空、Validation/Boundary 复选框未勾选)仍存在,但不影响合入;建议作者下次提交补齐模板。
我的整体评价
修复精准命中上一轮唯一阻塞点,CI 全绿,达到合并条件,结论 APPROVE。
Review: APPROVE
Head: ac50f76718b4e631c298e787410cd640a59b1e12
Verdict: APPROVE — the new head is a focused 2-line/2-delete fix moving the module docstring above from __future__ import annotations, resolving all 8 Ruff E402 errors. Local validation passes (31 scheduler decision-table tests plus 149 adjacent tests = 180 passed) and CI pytest/build/dependency-review are all SUCCESS. Non-blocking follow-up: fill the PR template fields (Summary, Closes #, validation/boundary checkboxes).
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3078 新 head 复核(head 01ad9c33ed3258cd8b80147d20733ba876745cf4)
详细中文评审
动机(本次 head 更新)
上一轮 APPROVE 后,作者在同一个 PR 上追加新 commit feat(effect-program): extend typed settlement to task_lease acquire path (GH-C82)(+793 行,5 个文件):新增 loopx/control_plane/work_items/task_lease_settlement.py(343 行)以及 effect-program 的 conformance / fault-replay / incident-replay 三组测试。PR 标题仍是 "four contributor tasks",实际已并入第五个任务,作用域明显膨胀,但这是次要问题;主要问题在适配器语义。
改动思路
适配器把 task-lease acquire 建模为"validation → durable writeback"两段式 typed settlement:resolve_task_lease_validation 做 owner 资格、活动 lease、write-scope 冲突检查;commit_task_lease_acquire 用 build_lease + write_lease 直接写文件。测试覆盖 typed receipt 形状、fault short-circuit、effect_id 一致性。
关键代码讲解
- 模块 docstring 声明 "Wraps the existing task_lease acquire path",但
commit_task_lease_acquire实际绕过 owner 模块的acquire_task_lease,直接write_lease,没有获取exclusive_file_lock、没有expected_versionCAS、也没有 idempotency-key 参数匹配。 - 对比 owner 路径:
acquire_task_lease在exclusive_file_lock内完成 owner 约束复检、assert_expected_version(existing, expected_version)、同 owner+key 时校验 write_scopes/ttl 一致(不一致抛idempotency_key_reuse)、CAS 写回。这些语义在适配器里全部缺失。 - 后果:
- 并发竞态:两个不同 owner/key 的 acquire 可同时通过 validation,随后各自
write_lease,last-writer-wins 覆盖首个 lease,"todo already has an active lease with a different owner or key" 的不变量只在读检查瞬间成立,提交阶段不再成立; - 幂等参数漂移:同 owner+key 重放但 write_scopes/ttl 不同时,适配器会静默覆盖旧 lease,而 owner 路径应报
idempotency_key_reuse; - 无版本 CAS:旧实例可覆盖新 lease。
- 并发竞态:两个不同 owner/key 的 acquire 可同时通过 validation,随后各自
- 现有 56 项新测试全部通过,但均为串行、同参数场景,未覆盖上述三条语义;因此 conformance/fault-replay 覆盖的并不是真实 acquire 路径的语义,而是这个代理实现——与模块自称的 "wraps the existing task_lease acquire path" 不符。
对主干的风险
- P1(阻塞):
commit_task_lease_acquire必须复用 owner 模块的锁 + CAS + 幂等参数检查语义。推荐直接调用acquire_task_lease(...)并把其返回/异常映射为 typed receipt/failure(idempotency_key_reuse→ WRITEBACK_REJECTED,lease_cas_mismatch→ CAS failure),或至少在同一个exclusive_file_lock(task_lease_lock_path(...))内复刻expected_version与参数一致性校验后再写。 - P2(非阻塞):PR 作用域标题与实际内容不一致("four" vs 第五个 GH-C82 任务);建议后续把 effect-program adapter 拆成独立 PR,模板
Closes #/复选框仍未填。
验证
- exact head
01ad9c33:py_compile通过;本地 236 passed(180 既有 + 56 新增 effect-program 测试);build SUCCESS;pytest 运行时状态以 CI 终态为准。 - 未覆盖:并发 acquire 竞态、同 key 不同参数重放、expected_version CAS——建议补三条聚焦回归测试后再合入。
我的整体评价
typed settlement 的形状和测试质量不错,但 task-lease 适配器没有真正包装 owner 的 acquire 路径,丢掉了锁、CAS 与幂等参数语义,会让 conformance 覆盖产生"测了一个替身"的错觉。这是需要先修的核心问题,结论 REQUEST_CHANGES。
Review: REQUEST_CHANGES
Head: 01ad9c33ed3258cd8b80147d20733ba876745cf4
Verdict: Request changes — the new task-lease typed-settlement adapter claims to wrap the owning acquire_task_lease path but bypasses it in commit_task_lease_acquire: no per-goal exclusive_file_lock, no expected_version CAS, and no idempotency-key parameter matching. That allows concurrent last-writer-wins clobbering, silent overwrite on same-key/different-parameters replay, and stale writes over a newer lease, while the new tests only cover serial same-parameter scenarios. Route the commit through the owning acquire_task_lease (or replicate its lock+CAS+parameter checks inside the same lock) and add focused regression tests for the three missing semantics. Local validation passes (236 tests) and build is green; the scope/title drift (fifth task in a "four tasks" PR) is a non-blocking follow-up.
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3078 新 head 复核(head 46cd075c13a56a14c75dc131a170a30b5b5274c6)
详细中文评审
动机(本次 head 更新)
上一轮 REQUEST_CHANGES 指出 GH-C82 task-lease 适配器绕过 owner 路径的锁/CAS/幂等参数语义。作者本次并未修复该问题,而是在同一 PR 上再追加新 commit feat(control-plane): implement generic observable_artifact_handle_v0 protocol (GH-C50)(+1425 行:loopx/observable_artifact_handle.py 722 行、tests/test_observable_artifact_handle.py 521 行、examples/observable-artifact-handle-smoke.py 182 行)。PR 现在包含 6 个相互独立的任务,标题仍是 "Feat/four contributor tasks"。
改动思路(GH-C50)
新增默认 generic 的 observable-artifact-handle 协议:紧凑 token/text 校验器、frozen typed 模型、builder/validate/project/policy/fixture/markdown 六件套。校验器拒绝本地路径、URL/remote、私密标记与父目录标记;read_boundary 默认 compact-only(raw logs/command/env/artifacts/paths 全部 False);launch_actions_enabled 与 production_actions_enabled 恒为 False;validate 强制 raw_handle_payload_recorded=False。该模块本身边界干净、实现独立。
关键代码讲解
_compact_public_text/_public_or_redacted_ref:可公开文本走 alias,含路径/URL/凭据标记的内容降级为 sha256 前 16 位的redacted:…,不记录原文。ObservableArtifactHandle.as_dict:allowed_poll_command只输出command_label,argv_recorded/raw_command_recorded恒 False。validate_observable_artifact_handle:对 schema、handle_id、kind、state、poll command、read boundary、launch 开关做逐项校验,非法输入 fail-closed。
对主干的风险
- P1(仍阻塞):GH-C82
commit_task_lease_acquire依旧直接write_lease,未复用acquire_task_lease的exclusive_file_lock、expected_versionCAS 与 idempotency-key 参数一致性检查。并发竞态、同 key 不同参数重放静默覆盖、旧写覆盖新 lease 三个问题均未修复。 - P1(流程):同一 PR 在带阻塞评审的 head 上继续叠加第 5、6 个独立任务(GH-C82、GH-C50),评审与回滚难度显著上升。GH-C50 本身干净且独立,建议拆成单独 PR 先审;GH-C82 按上一轮意见修复;#3078 回到其名义上的四个任务再合并。
- P2(非阻塞):PR 模板
Summary/Closes #/复选框仍未填;标题与实际内容不一致。
验证
- exact head
46cd075c:py_compile通过;tests/test_observable_artifact_handle.py46 passed;examples/observable-artifact-handle-smoke.py18 checks 通过;此前 236 项(180 + 56 effect-program)在未变文件上仍通过;build SUCCESS;pytest 运行时状态以 CI 终态为准。
我的整体评价
GH-C50 单独看是一个高质量的独立交付,但本轮 head 没有解决 GH-C82 的阻塞问题,且作用域继续膨胀。正确路径是拆 PR:GH-C50 独立合入,GH-C82 修复锁/CAS 语义,原四任务保持聚焦。结论 REQUEST_CHANGES。
Review: REQUEST_CHANGES
Head: 46cd075c13a56a14c75dc131a170a30b5b5274c6
Verdict: Request changes — the new GH-C50 observable_artifact_handle_v0 module is clean, well-bounded, and locally verified (46 tests + 18-check smoke pass), but this head still carries the unresolved GH-C82 blocker from the previous review: commit_task_lease_acquire continues to bypass the owning acquire_task_lease lock/CAS/idempotency-parameter semantics (concurrent last-writer-wins, same-key/different-parameter silent overwrite, stale overwrite without version CAS). The PR has also grown to six independent tasks under a stale "four contributor tasks" title. Recommended path: split GH-C50 into its own PR (ready to review on its own), fix GH-C82 per the prior finding, and keep #3078 scoped to its original four tasks. PR template fields still need filling.
46cd075 to
9c77eb0
Compare
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3078 新 head 复核(head 9c77eb09d8)
详细中文评审
动机(本次 head 更新)
作者按上一轮建议把 GH-C82 与 GH-C50 拆出(分别进入 #3081/#3080),#3078 回到名义上的四个任务分支。但当前 head 是 9c77eb09——即 E402 lint 修复(ac50f767)之前的提交,tests/control_plane/test_quota_scheduler_state_backoff.py 的 docstring 仍在 from __future__ import annotations 之后,8 处 Ruff E402 回归。
对主干的风险
- P1(阻塞):CI pytest(Lint test suite)FAILURE,8 处 E402 与首轮评审一致。修复:把模块 docstring 移到
from __future__之前(即应用 ac50f76 的 2 行/2 删改动),或直接并入该 commit 后再推。 - P2(非阻塞):模板
Summary/Closes #/复选框仍未填。
验证
- exact head
9c77eb09:CI pytest FAILURE(lint),build/dependency-review SUCCESS;此前本地验证过该 head(除 lint 外 149+31 测试通过)。
我的整体评价
拆分动作正确,但当前 head 丢了 lint 修复,CI 红。补回 docstring 顺序修复后即可达到合并条件,结论 REQUEST_CHANGES。
Review: REQUEST_CHANGES
Head: 9c77eb09d8
Verdict: Request changes — the split is correct (GH-C82 → #3081, GH-C50 → #3080), but this head regressed to the pre-fix commit: the module docstring again sits below from __future__ import annotations, causing 8 Ruff E402 failures in CI pytest. Apply the ac50f76 docstring-order fix (or cherry-pick that commit) and re-run CI. Non-blocking: fill the PR template fields.
huangruiteng
left a comment
There was a problem hiding this comment.
PR #3078 新 head 复核(head 8240e3a1c0)
详细中文评审
动机(本次 head 更新)
作者在拆分 GH-C82/GH-C50 后补回 lint 修复 commit fix(lint): move module docstring above __future__ import to resolve E402(仅改 tests/control_plane/test_quota_scheduler_state_backoff.py,2 行增/2 行删),把模块 docstring 移到 from __future__ import annotations 之前,消除 8 处 Ruff E402。
验证
- exact head
8240e3a1:py_compile通过;本地 180 passed(含 31 项 scheduler 决策表 + 149 项相邻回归);build SUCCESS;pytest 运行时状态以 CI 终态为准。
我的整体评价
拆分与 lint 修复都已到位,#3078 回到干净的四任务作用域。达到合并条件,结论 APPROVE。
Review: APPROVE
Head: 8240e3a1c0
Verdict: APPROVE — the branch is back to its four-task scope with the docstring-order lint fix restored (2+/2- in the scheduler decision-table test file), resolving the 8 Ruff E402 failures. Local validation passes (180 tests), build is green, and CI pytest is running. The GH-C82 and GH-C50 work now live in #3081/#3080 respectively.
Summary
Issue Or Task
Validation
python3 -m py_compile loopx/*.pyloopx check --scan-root .Type of Change
LoopX Area
Boundary Checklist
.loopx/,.codex/goals/, liveACTIVE_GOAL_STATE.md, credentials, private benchmark traces, verifier output, raw agent sessions, internal document links, or local machine paths.