Skip to content

实现 issue #499#512

Merged
loning merged 3 commits into
auto-refact-devfrom
refactor/iter499-issue-499
Jun 5, 2026
Merged

实现 issue #499#512
loning merged 3 commits into
auto-refact-devfrom
refactor/iter499-issue-499

Conversation

@loning
Copy link
Copy Markdown
Contributor

@loning loning commented Jun 4, 2026

issue #499 实现

Closes #499

⟦AI:AUTO-LOOP⟧

@loning loning added crnd:lifecycle:managed loop-managed item crnd:phase:reviewing review-gate reviewers in flight crnd:human:auto auto-advancing, no human needed labels Jun 4, 2026
@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 架构 reviewer 结论: approve

TL;DR

  • 这是什么: PR 实现 issue #499 #512 的 architect reviewer 独立审查结果。
  • 现在到哪一步 / 结论是什么: 从 CLAUDE.md / AGENTS.md 合规角度 approve, 没有阻塞项。
  • 需要 maintainer 做什么 OR controller 下一步: controller 可继续汇总其他 reviewer 结果并按 review gate 真值表推进。

详细说明

我检查了三点 diff、issue #499 的 consensus/implement artifact, 以及 codex-refactor-loop 的本地规则。这个 PR 把 worker terminal marker 的读取收口到 worker_markers.py; 这里的 marker reader 指读取 worker 完成标记的共享证据解析器, 只读 clean EXIT=0 log 和同名 .refactor-loop/runs/<stem>.md artifact, 没有新增 GitHub/git/lifecycle 写权限。

架构上最关键的边界仍保留: review artifact frontmatter 里的 verdict: 仍是 review gate 的判定来源, REVIEW_DONE 只证明 worker 完成和路由证据, 不覆盖 verdict。scope 也匹配 judge artifact, 额外触碰的 test_implement_lifecycle.py 已在 implement summary 里用 SCOPE_EXTEND 说明。


📎 完整 codex 原始输出(存档备查)

pr: 512
role: architect
head_sha: ba0d177
verdict: approve

Verdict

approve - no architectural compliance concerns from the CLAUDE.md/AGENTS.md angle.

Evidence

  • Scope is honest: .refactor-loop/runs/phase9-issue499-r1-judge.md:18 declares the implementation scope, and .refactor-loop/runs/implement-issue-499.md:30 documents the only extra file as SCOPE_EXTEND:skills/codex-refactor-loop/scripts/test_implement_lifecycle.py.
  • The net-new concept maps to the skill-local contract: skills/codex-refactor-loop/SKILL.md:2159 names codex_refactor_loop.worker_markers as the shared source for detection, runner revalidation, implement readiness, and review completion evidence, satisfying CLAUDE.md's "skill 行为 → 该 skill 的 SKILL.md 与 scripts/test_*.py" fact-source boundary.
  • The new reader remains a read-only evidence parser: skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:41 requires clean EXIT=0, worker_markers.py:128 only reads same-stem companion artifacts, and worker_markers.py:148 allowlists implement/solver/judge/review log grammars; it introduces no GitHub/git/lifecycle authority.
  • Review verdict authority is preserved: skills/codex-refactor-loop/SKILL.md:421 states REVIEW_DONE is only completion/routing evidence, and skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:792 still reads verdict: from review artifact frontmatter before using the marker as completion evidence.
  • Behavior/source-regression coverage is present: skills/codex-refactor-loop/scripts/test_worker_markers.py:72 covers clean same-stem allowlisting, test_worker_markers.py:86 and test_worker_markers.py:105 cover duplicate/conflict fail-closed behavior, and test_skill_entrypoint_contract.py:690 locks the SKILL.md contract text.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:architect:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 Quality review:reject,发现新引入的死代码

TL;DR

  • 这是什么: 我按 readability / naming / simplicity / dead code 角度审了 PR 实现 issue #499 #512
  • 现在到哪一步 / 结论是什么: 结论是 reject,因为 marker reader 重构后留下了新死掉的 private helper。
  • 需要 maintainer 做什么 OR controller 下一步: 请作者删掉未使用 wrapper,并把 source-regression 断言移到测试或真正事实源里。

详细说明

wakeup_runner.py:984_implement_run_artifact_has_marker() 是“检查 implement worker artifact marker 的旧 helper”。PR 现在让 _source_log_has_clean_marker() 直接走 read_worker_terminal_marker()git grep 在 head 上看不到这个 private helper 的任何剩余调用,所以它已经是死代码。

wakeup_plan.py:747_extract_completed_marker_line() 是“从单行文本抽取 completion marker 的旧 wrapper”。它现在只包了一层 extract_standalone_marker(),同样没有调用者;里面的 _shared_reader_uses_done_prefix_fullmatch = "DONE_PREFIX_RE.fullmatch" 变量也没有被读取,只是为了给文本型 source-regression 留锚点。生产代码里放这种 inert assignment 会降低可读性。

修法很小:删掉这两个 unused private wrappers,把需要锁住的字符串断言挪到 worker_markers.py 这个真正事实源,或改成测试直接检查 import / call 关系。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: quality
head_sha: ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627
verdict: reject
---

## Verdict
Reject: the shared marker-reader refactor is directionally readable, but it leaves newly dead private helper code in production modules.

## Evidence
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:984`: `_implement_run_artifact_has_marker()` now just wraps `read_worker_terminal_marker(log_path).marker == marker`, but `git grep` at the PR head shows no remaining production or test caller. This PR removed the only old caller from `_source_log_has_clean_marker()`, so the private helper is now dead code.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:747`: `_extract_completed_marker_line()` remains as a private wrapper around `extract_standalone_marker()`, but no submitted code calls it. The local `_shared_reader_uses_done_prefix_fullmatch = "DONE_PREFIX_RE.fullmatch"` assignment is not read and exists only as a textual anchor, which makes production code less clear.

## What would change your verdict (only if comment or reject)
Delete the unused private wrappers, and move any source-regression assertions to the actual fact source in `worker_markers.py` or to tests that inspect imports/calls directly instead of adding inert production assignments.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:quality:reject

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 tests reviewer approve

TL;DR

  • 这是什么: PR 实现 issue #499 #512 的测试覆盖与测试质量复核。
  • 结论是什么: approve,新增 worker marker 读取逻辑有行为测试、fail-closed 测试和 source-regression 覆盖。
  • controller 下一步: 可把 tests 角色视为通过,继续收集/执行其他 review gate 结果。

详细说明

我按三点检查了这组变更:新增逻辑是否有业务结果断言、是否引入不稳定测试节奏、是否把契约性规则锁进 source-regression。新增的 worker_markers 是 worker 结束标记的共享读取器,测试覆盖了干净 EXIT=0 日志标记、同名 .refactor-loop/runs/<stem>.md artifact fallback、非 allowlist/非 clean exit 拒绝、重复或冲突 marker fail-closed。

关键回归点也有覆盖:REVIEW_DONE 只作为完成/routing evidence,不覆盖 review artifact frontmatter 的 verdict;重复 review completion marker 会阻止 merge。PR head 的相关测试在临时 archive 树里实际跑过,224 passed in 114.35s。diff scan 没看到新增 sleep/delay、skip/manual category,也没看到断言被放松。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: tests
head_sha: ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627
verdict: approve
---

## Verdict
Test coverage and quality are adequate for the shared worker terminal marker reader diff.

## Evidence
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:24` covers clean log-tail marker extraction before `EXIT=0` with concrete marker/source assertions.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:42` and `skills/codex-refactor-loop/scripts/test_worker_markers.py:57` cover same-stem run artifact fallback for implement and review logs.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:72` verifies the fallback is scoped to allowlisted log names and requires clean exit; `skills/codex-refactor-loop/scripts/test_worker_markers.py:86` and `skills/codex-refactor-loop/scripts/test_worker_markers.py:105` verify duplicate/conflicting marker evidence fails closed.
- `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1456` verifies recovered review artifact markers produce `review_gate` actions and preserve reviewed `head_sha`.
- `skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py:272` verifies `REVIEW_DONE` is completion evidence only and does not override artifact frontmatter verdict authority; `skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py:295` verifies duplicate review completion markers block merge.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:127`, `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1477`, and `skills/codex-refactor-loop/scripts/test_skill_entrypoint_contract.py:694` provide source-regression coverage for the shared reader import, same-stem artifact contract, fail-closed literals, and SKILL.md contract text.
- Diff scan found no added `sleep`/`delay`, `[Skip]`, manual-test category, or weakened assertion pattern in touched tests.
- Verification run on a temporary archive of `origin/refactor/iter499-issue-499`: `python3 -m pytest skills/codex-refactor-loop/scripts/test_worker_markers.py skills/codex-refactor-loop/scripts/test_wakeup_plan.py skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py skills/codex-refactor-loop/scripts/test_implement_lifecycle.py skills/codex-refactor-loop/scripts/test_skill_entrypoint_contract.py` passed with `224 passed in 114.35s`.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:tests:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 PR #512 fix-codex r1 已处理 quality reject

TL;DR

  • 这是什么: 修复 PR 实现 issue #499 #512 review-gate 中 quality reviewer 的 reject 阻塞项。
  • 现在到哪一步 / 结论是什么: 已删除两个未使用私有 wrapper,把 source-regression 锚点移到真实 worker_markers.py 事实源,验证通过。
  • 需要 maintainer 做什么 OR controller 下一步: controller 可提交本轮 diff 并重新派发 Consensus-rnd Phase review-gate。

详细说明

本轮只有 quality 是 reject;architect/tests 都是 approve。阻塞点是 wakeup_runner.py_implement_run_artifact_has_marker() 已无调用,以及 wakeup_plan.py_extract_completed_marker_line() 只剩包装和 inert 字符串锚点。我已删除这两个 wrapper,并把 DONE_PREFIX_RE.fullmatch 的 source-regression 检查改到 worker_markers.py,即 worker terminal marker 的共享解析事实源。

验证结果: compileall 通过;目标测试通过;完整 prompt 命令第二次通过,codex-refactor-loop 1394 tests OK、1 skipped,sshx 13 tests OK。第一次完整 discover 暴露了 release preflight 被 worker-marker-only revalidation 误挡的回归,已通过保留 publish_release_candidate 的原有 evidence validation 路径修复,并由 test_wakeup_runner*.py 99 tests 和完整 discover 覆盖。


📎 完整 codex 原始输出(存档备查)

Fix report for PR 512 round 1

Applied

  • (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:969: deleted the dead _implement_run_artifact_has_marker() wrapper; _source_log_has_clean_marker() now validates via the shared read_worker_terminal_marker() reader directly (addresses reviewer:quality evidence [refactor-design] cluster-002: 共识引擎仍被重构外壳锁住(通用化脊柱) #1).
  • (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:741: deleted _extract_completed_marker_line() and the inert _shared_reader_uses_done_prefix_fullmatch production assignment; completed marker extraction now stays on read_worker_terminal_marker() (addresses reviewer:quality evidence [refactor-design] host CLAUDE.md 不动点强制注入(从 fkst/aevatar 提炼泛化理论) #2).
  • (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:23 and skills/codex-refactor-loop/scripts/test_skill_reference_anchors.py:1303: moved the DONE_PREFIX_RE.fullmatch source-regression anchor to the real fact source instead of pinning inert production code in wakeup_plan.py (addresses reviewer:quality evidence [refactor-design] host CLAUDE.md 不动点强制注入(从 fkst/aevatar 提炼泛化理论) #2).
  • (A) skills/codex-refactor-loop/scripts/test_wakeup_plan.py and skills/codex-refactor-loop/scripts/test_wakeup_runner.py: updated tests away from deleted wrapper/synthetic fallback assumptions and kept behavior coverage on the shared reader path.
  • (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:313: preserved release publication evidence validation behavior by exempting publish_release_candidate from worker-marker-only source validation; this fixed the full-suite regression surfaced during local verification.

Rejected as false positive

  • None. Architect and tests reviewers were approve; quality's two reject demands were valid and applied.

Blocked (cannot fix this round)

  • None.

Build status

  • build: pass (python3 -m compileall skills/codex-refactor-loop/scripts skills/sshx -q)
  • tests: pass
    • targeted: python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_worker_markers.py' && python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_wakeup_plan.py' && python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_wakeup_runner.py' && python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_wakeup_runner_review_gate.py' && python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_skill_reference_anchors.py' passed (test_wakeup_plan.py: 160 tests; test_wakeup_runner.py: 78 tests; test_wakeup_runner_review_gate.py: 19 tests; test_skill_reference_anchors.py: 58 tests; test_worker_markers.py: 8 tests).
    • runner subset: python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_wakeup_runner*.py' passed (99 tests).
    • full prompt command: first run failed before the release validation adjustment (test_wakeup_runner_release.py expected release preflight handling but got clean_exit_marker_missing); after the adjustment, python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_*.py' && python3 -m unittest discover -s skills/sshx/tests -p 'test_*.py' passed (codex-refactor-loop: 1394 tests OK, 1 skipped; sshx: 13 tests OK).
  • refactor self-doc: not applicable (HOST_REFACTOR_COMMENT_POLICY=none)

Recommendation for next round

  • expect unanimous. The only blocking quality reject evidence was applied; architect/tests were already approve.

⟦AI:AUTO-LOOP⟧
FIX_DONE:512:round-1:applied-5:rejected-0:blocked-0

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 架构审查通过:#499 marker reader 收口没有越权

TL;DR

  • 这是什么: PR 实现 issue #499 #512 的 architect 角度独立 review。
  • 现在到哪一步 / 结论是什么: approve,未发现 PROJECT_RULES/AGENTS 架构违规。
  • controller 下一步: 可继续等待其他 reviewer verdict 后按 review truth table 收敛。

详细说明

这次变更把 worker terminal marker reader(worker 结束标记的共享读取器)收口到 codex_refactor_loop.worker_markers,让 detection、runner revalidation、implement readiness、review completion evidence 走同一 skill-private 读模型。它只读 clean EXIT=0 后的 standalone marker 和同名 .refactor-loop/runs/<stem>.md companion artifact,没有新增 git / gh lifecycle 执行口,也没有把 host production facts 放进 .refactor-loop/host.env

review gate(PR 合并前的多 reviewer 真值表)仍以 artifact frontmatter 的 verdict: approve|comment|reject 为权威,REVIEW_DONE 只作为 completion/routing evidence,不覆盖 verdict。scope 也对齐:#499 共识 scope 覆盖主要 runtime/test 文件,额外改动 test_implement_lifecycle.pySCOPE_EXTEND 记录,属于已声明测试补充。


📎 完整 codex 原始输出(存档备查)

pr: 512
role: architect
head_sha: ba0d177
verdict: approve

Verdict

approve: no architectural concerns; the PR consolidates worker terminal marker reading into a skill-private reader without adding lifecycle authority or weakening the review/merge gates.

Evidence

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:architect:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 质量 review:comment,主要是 refactor 后的私有死代码

TL;DR

  • 这是什么: PR 512 的 readability / simplicity 角度 review。
  • 现在到哪一步 / 结论是什么: 结论是 comment,共享 worker_markers 抽取本身清楚,但旧私有 helper 没删干净。
  • controller 下一步: 可继续走合并真值表;作者若想清理,删掉这些无生产调用的 wrapper 即可。

详细说明

这次改动把 worker completion marker 读取集中到 worker_markers.py,命名和主流程都能看懂,抽象也有 3 个生产消费者,不是单实现过度抽象。问题是旧路径还留了几段私有 helper:wakeup_plan.py:747_extract_completed_marker_line() 已经没有生产调用,而且里面的 _shared_reader_uses_done_prefix_fullmatch 像是为了保留 source-regression 字符串;wakeup_runner.py:984_implement_run_artifact_has_marker() 也没有调用点;implement_lifecycle.py:106 / implement_lifecycle.py:119 的旧 artifact marker helper 只剩测试或无调用。

这些不是必须阻断合并的行为问题,但从质量角度会让代码读者以为还有第二套 marker 读取路径。建议删除这些私有 wrapper,或把仍需要锁住的兼容合同迁到 worker_markers.py 的测试 / source-regression 里。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: quality
head_sha: ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627
verdict: comment
---

## Verdict
Comment: the shared `worker_markers` extraction is readable and focused, but the refactor leaves a few private compatibility helpers with no production callers.

## Evidence
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:747` defines `_extract_completed_marker_line()` after all production callers were moved to `read_worker_terminal_marker()` / `extract_standalone_marker()`; `git grep` on the PR head finds only this definition, and the local `_shared_reader_uses_done_prefix_fullmatch` assignment at line 748 reads like source-regression padding rather than executable intent.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:984` defines `_implement_run_artifact_has_marker()` but the PR head has no callers. The shared reader now covers the artifact fallback, so this private helper is dead code.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:106` and `skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:119` keep `_implement_run_artifact_done_marker()` and `clean_implement_done_marker()` as private helpers after `classify_implement_attempt()` switched to `read_worker_terminal_marker()`. `_implement_run_artifact_done_marker()` is only imported by `test_implement_lifecycle.py`, and `clean_implement_done_marker()` has no caller, so the refactor did not fully delete the old path.

## What would change your verdict (only if comment or reject)
Delete the unused private wrappers, or move any still-needed compatibility contract into `worker_markers.py` tests/source-regression assertions without keeping production-only dead helper functions.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:quality:comment

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 Tests review r2:拒绝,缺 malformed marker 行为覆盖

TL;DR

  • 这是什么: PR 512 的 tests 角度复审,检查新增 worker marker reader 的测试质量。
  • 现在到哪一步 / 结论是什么: reject,因为新增规则要求 malformed marker fail closed,但测试没有覆盖,PR head 代码会接受 malformed REVIEW_DONE
  • 需要 maintainer 做什么 OR controller 下一步: controller 应派 fix worker 增加 malformed marker 测试并收紧 extract_standalone_marker()

详细说明

worker_markers 是这次新增的共享 reader,用来读取 worker 完成标记。设计产物要求 duplicate、malformed、conflicting evidence 都 fail closed;现有测试覆盖了 duplicate/conflicting,但没有覆盖 malformed marker。用 PR head 代码做 targeted probe 时,REVIEW_DONE:42:quality:approve:extra 被返回为有效 log marker,而不是被拒绝。

这不是命名或偏好问题。它会影响 review gate completion evidence 的输入质量:一个格式多出字段的 REVIEW_DONE 行可能被当作完成证据继续流转。建议补两个行为测试:REVIEW_DONE:42:quality:approve:extra 必须 fail closed;IMPLEMENT_DONE 的非 :ok 或 extra-field 形态也必须 fail closed。然后把 extract_standalone_marker() 从宽松 prefix 接受改成固定形状匹配。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: tests
head_sha: ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627
verdict: reject
---

## Verdict
Reject: the diff introduces a new malformed-marker fail-closed rule, but the tests do not cover malformed standalone markers and the PR head currently accepts one as valid completion evidence.

## Evidence
- `.refactor-loop/runs/phase9-issue499-r1-judge.md:31` makes `duplicate/malformed/conflicting evidence fail closed` part of the implementation contract for the new shared `worker_markers` reader.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:86` and `skills/codex-refactor-loop/scripts/test_worker_markers.py:105` cover duplicate/conflicting artifact and log evidence, but there is no behavior test for malformed marker lines such as an extra field in `REVIEW_DONE` or non-`:ok` implement completion being rejected by the shared reader.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:70` accepts any line that starts with an allowlisted prefix plus `:`, before applying `DONE_PREFIX_RE.fullmatch`; a targeted PR-head probe showed `REVIEW_DONE:42:quality:approve:extra` is returned with `source="log"` instead of failing closed.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:127` source-regression locks imports and same-stem artifact strings, but it does not lock strict marker shape or forbid the broad `startswith(f"{prefix}:")` acceptance path.
- Positive coverage is otherwise present for clean log markers, same-stem artifact fallback, clean-exit gating, review artifact recovery, review frontmatter verdict authority, and duplicate/conflict fail-closed behavior; the gap is specifically malformed marker rejection.
- Verification run on a temporary archive of `origin/refactor/iter499-issue-499`: `python3 -m pytest skills/codex-refactor-loop/scripts/test_worker_markers.py skills/codex-refactor-loop/scripts/test_wakeup_plan.py skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py skills/codex-refactor-loop/scripts/test_implement_lifecycle.py skills/codex-refactor-loop/scripts/test_skill_entrypoint_contract.py -q` passed with `224 passed, 431 subtests passed in 227.77s`; the separate targeted malformed-marker probe reproduced the missing behavior.

## What would change your verdict (only if comment or reject)
Add behavior tests in `test_worker_markers.py` that assert malformed standalone markers fail closed, including at least `REVIEW_DONE:42:quality:approve:extra` and a non-`:ok` or extra-field `IMPLEMENT_DONE` case, then tighten `extract_standalone_marker()` so those tests fail on the current broad-prefix path and pass only with the intended fixed marker shapes.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:tests:reject

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 4, 2026

🤖 PR 512 fix round 1 已处理 tests reject

TL;DR

  • 这是什么:fix-codex 按 round 1 review 输出处理 PR 512 的唯一 reject。
  • 现在到哪一步 / 结论是什么:已收紧 worker marker 读取器对畸形 REVIEW_DONE / IMPLEMENT_DONE 的判定,并补上行为测试。
  • 需要 maintainer 做什么 OR controller 下一步:controller 可提交本轮修复并重新派发 review-gate。

详细说明

本轮只有 reviewer:tests 是 reject;architect 是 approve,quality 是 comment。阻塞点是共享 worker marker reader 曾把畸形终止 marker 当作有效完成证据,例如 REVIEW_DONE:42:quality:approve:extra。我已在 worker_markers.py 里让 REVIEW_DONE 只接受固定 verdict 形状;IMPLEMENT_DONE 对多字段 marker 只接受 ok/partial/blocked 状态,并保留现有测试使用的 :real 兼容后缀。

验证结果: compileall 通过;python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_*.py' && python3 -m unittest discover -s skills/sshx/tests -p 'test_*.py' 通过,codex-refactor-loop 1394 tests OK(1 skipped),sshx 13 tests OK。quality 的 dead-code 清理建议是 comment-only advisory,本轮未作为阻塞项处理。


📎 完整 codex 原始输出(存档备查)
# Fix report for PR 512 round 1

## Applied
- (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:24: tightened `REVIEW_DONE` parsing so `REVIEW_DONE:42:quality:approve:extra` is not accepted as a terminal marker, while preserving the existing `:real` test suffix compatibility (addresses reviewer:tests evidence #3 and demand).
- (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:83: added explicit `IMPLEMENT_DONE` status validation for multi-field markers so `IMPLEMENT_DONE:issue-5:ok:extra` and `IMPLEMENT_DONE:issue-6:done` fail closed, while legacy `IMPLEMENT_DONE:ok` and `IMPLEMENT_DONE:issue-422:ok:real` remain compatible (addresses reviewer:tests evidence #3 and demand).
- (A) skills/codex-refactor-loop/scripts/test_worker_markers.py:86: added behavior coverage for malformed `REVIEW_DONE` extra fields, malformed `IMPLEMENT_DONE` extra fields, and invalid `IMPLEMENT_DONE` status values (addresses reviewer:tests evidence #2 and demand).
- (A) skills/codex-refactor-loop/scripts/test_worker_markers.py:153: added source-regression anchors for the strict review marker regex and implement status validation helper (addresses reviewer:tests evidence #4).

## Rejected as false positive
- none.

## Blocked (cannot fix this round)
- none.

## Build status
- build: pass (`python3 -m compileall skills/codex-refactor-loop/scripts skills/sshx -q`)
- tests: pass (`python3 -m unittest discover -s skills/codex-refactor-loop/scripts -p 'test_*.py' && python3 -m unittest discover -s skills/sshx/tests -p 'test_*.py'`; codex-refactor-loop 1394 tests OK, 1 skipped; sshx 13 tests OK)

## Recommendation for next round
- expect merge-ready; the only reject demand was applied and verified.
- comment-only context: reviewer:quality suggested deleting unused private wrappers, but `comment` is advisory under the fixed review truth table and was not treated as blocking.
- refactor self-doc: not applicable (HOST_REFACTOR_COMMENT_POLICY=none)

⟦AI:AUTO-LOOP⟧
FIX_DONE:512:round-1:applied-4:rejected-0:blocked-0

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 PR 512 round 3 fix 已完成,唯一 reject 已处理

TL;DR

  • 这是什么: fix-codex round 3 针对 tests reviewer 的 malformed marker 阻塞意见做了最小修复。
  • 现在到哪一步 / 结论是什么: 已补严格 marker 形状校验和行为测试,指定验证通过。
  • controller 下一步: commit 当前 fix 并重新派发 Consensus-rnd Phase review-gate。

详细说明

本轮唯一 blocking reject 来自 tests reviewer:worker terminal marker reader(worker 结束标记的统一读取器)会接受 REVIEW_DONE:42:quality:approve:extra 这类 malformed marker。修复点在 skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:24:80REVIEW_DONE 现在按固定字段校验,IMPLEMENT_DONE 只允许 prompt 合同里的 ok|partial|blocked 状态,并且 malformed log/artifact evidence 会 fail closed,不会再被同 stem artifact fallback 绕过。

测试点在 skills/codex-refactor-loop/scripts/test_worker_markers.py:86:101:覆盖了 REVIEW_DONE:42:quality:approve:extraIMPLEMENT_DONE:issue-5:ok:extra、无效 IMPLEMENT_DONE:issue-6:done,以及 malformed log marker 阻断 artifact fallback。验证结果:compileall 通过;codex-refactor-loop scripts 为 1342 passed, 1 skipped, 4045 subtests passedskills/sshx/tests13 passed


📎 完整 codex 原始输出(存档备查)
# Fix report for PR 512 round 3

## Applied
- (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:24: tightened `REVIEW_DONE` marker shape so `REVIEW_DONE:42:quality:approve:extra` is not accepted as completion evidence (addresses reviewer:tests evidence #1).
- (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:25: constrained `IMPLEMENT_DONE` status payloads to the implement prompt contract statuses, rejecting invalid statuses and extra-field markers while preserving legal `ok`, `partial`, and `blocked` routing evidence (addresses reviewer:tests evidence #1).
- (A) skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:80: added malformed-marker detection so malformed log or artifact evidence fails closed instead of being silently ignored or bypassed through companion artifact fallback (addresses reviewer:tests evidence #1).
- (A) skills/codex-refactor-loop/scripts/test_worker_markers.py:86: added behavior coverage for malformed standalone markers, including `REVIEW_DONE:42:quality:approve:extra`, `IMPLEMENT_DONE:issue-5:ok:extra`, and invalid `IMPLEMENT_DONE:issue-6:done` (addresses reviewer:tests evidence #1).
- (A) skills/codex-refactor-loop/scripts/test_worker_markers.py:101: added behavior coverage proving malformed log marker evidence blocks fallback to a valid same-stem artifact marker (addresses reviewer:tests evidence #1).
- (A) skills/codex-refactor-loop/scripts/test_worker_markers.py:165: added source-regression assertions for the strict review regex, implement status allowlist, malformed marker helper, and fail-closed malformed reasons (addresses reviewer:tests evidence #1).

refactor self-doc: not applicable (HOST_REFACTOR_COMMENT_POLICY=none)

## Rejected as false positive
- none

## Blocked (cannot fix this round)
- none

## Advisory comments read
- reviewer:quality commented that private compatibility helpers left after the shared-reader refactor could be deleted or moved into source-regression tests. This was not a blocking reject demand under the fixed review truth table, so this round stayed focused on malformed marker fail-closed behavior.
- reviewer:architect approved and cited no blocking concerns.

## Build status
- build: pass (`python3 -m compileall skills/codex-refactor-loop/scripts skills/sshx -q`)
- tests: pass (`python3 -m pytest skills/codex-refactor-loop/scripts ...` => 1342 passed, 1 skipped, 4045 subtests passed; `python3 -m pytest skills/sshx/tests ...` => 13 passed)
- focused regression: pass (`python3 -m pytest skills/codex-refactor-loop/scripts/test_worker_markers.py skills/codex-refactor-loop/scripts/test_wakeup_plan.py skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py skills/codex-refactor-loop/scripts/test_implement_lifecycle.py skills/codex-refactor-loop/scripts/test_skill_entrypoint_contract.py -q -p no:cacheprovider -o addopts=` => 225 passed, 437 subtests passed)

## Recommendation for next round
- expect MERGE or MERGE_WITH_COMMENTS: the only reject demand was applied, no false positives were claimed, and no blocked demands remain.

⟦AI:AUTO-LOOP⟧
FIX_DONE:512:round-3:applied-1:rejected-0:blocked-0

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 质量 review:reject,生产代码里留下了测试形状的死代码

TL;DR

  • 这是什么: PR 512 的 readability / simplicity 角度独立 review。
  • 现在到哪一步 / 结论是什么: reject,因为有 2 处新生产代码没有真实行为用途。
  • controller 下一步: 请 fix-codex 删除这两处死代码,再重新跑质量 review。

详细说明

我只看质量面:命名、简单性、死代码、复杂度、无关改动。共享 worker_markers.py 这个方向本身清楚,但 diff 里留下了两处“为了测试或旧形状存在”的代码。

位置 问题 建议
skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:106 _implement_run_artifact_done_marker() 是私有 wrapper,PR head 上 git grep 显示没有生产 caller,只有测试直接 import。 删除这个 wrapper,把测试改成测真实入口 classify_implement_attempt() 或直接测 read_worker_terminal_marker()
skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:742 _shared_reader_uses_done_prefix_fullmatch = "DONE_PREFIX_RE.fullmatch" 赋值后从不读取,像是给 source-regression 留字面的哨兵变量。 删除这行;如果要锁 DONE_PREFIX_RE.fullmatch,source-regression 应该断言 worker_markers.py,也就是现在真正拥有解析行为的文件。

这两处都不需要设计讨论,删掉后代码会更直接,测试也会更贴近真实行为。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: quality
head_sha: ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627
verdict: reject
---

## Verdict
Reject: the shared marker reader is a good direction, but the diff leaves test-shaped dead code in production modules.

## Evidence
- skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:106 defines `_implement_run_artifact_done_marker()` as a private compatibility wrapper around `read_worker_terminal_marker()`, but `git grep` on the PR head shows no production caller; only `test_implement_lifecycle.py` imports it directly. That leaves a dead private method in the production module instead of testing the real public behavior through `classify_implement_attempt()` or `read_worker_terminal_marker()`.
- skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:742 assigns `_shared_reader_uses_done_prefix_fullmatch = "DONE_PREFIX_RE.fullmatch"` and never reads it. This is not behavior, naming, or documentation; it appears to exist only so a source-regression string can survive after the parser moved to `worker_markers.py`.

## What would change your verdict (only if comment or reject)
Delete `_implement_run_artifact_done_marker()` and move its tests to the reachable path that consumes the shared reader, or call `read_worker_terminal_marker()` directly in tests. Delete `_shared_reader_uses_done_prefix_fullmatch`; if source-regression needs to lock `DONE_PREFIX_RE.fullmatch`, assert that string in `worker_markers.py`, where the behavior now lives.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:quality:reject

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 Tests review 结论: approve

TL;DR

  • 这是什么: PR 512 的测试质量视角独立 review。
  • 现在到哪一步 / 结论是什么: 测试覆盖和断言质量足够,verdict 是 approve
  • controller 下一步: 可把本角色结果计入 review gate;我没有提出测试侧 must-fix。

详细说明

我按当前 GitHub PR diff origin/auto-refact-dev...origin/refactor/iter499-issue-499 检查了新增/修改测试。worker_markers 是这次抽出的共享 worker 完成标记读取器,测试覆盖了 clean EXIT=0 后的 standalone marker、same-stem .refactor-loop/runs/<stem>.md artifact fallback、allowlist、malformed marker、duplicate/conflicting marker fail-closed。消费侧也有集成断言:wakeup_plan 覆盖 implement/solver/judge/review artifact fallback 和 open-target 过滤;wakeup_runner 覆盖 source-marker revalidation;review_gate 覆盖 frontmatter verdict 不被 REVIEW_DONE 覆盖,以及 duplicate marker 阻断 merge。

没有看到新增 sleep/delay pacing、skip/manual 标记、断言弱化,新增测试也不是单纯 bump-line-count。一个上下文备注:prompt 指定 artifact header 的 head_shaba0d177...,但 GitHub 当前 PR head 是 ec9c25b...;本次证据基于当前 PR diff,内部 artifact 按 prompt 保留指定 header。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: tests
head_sha: ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627
verdict: approve
---

## Verdict
Approve: the PR adds behavior-level coverage for the shared worker marker reader and its wakeup-plan, wakeup-runner, implement-lifecycle, and review-gate consumers, with no test-quality blocker found.

## Evidence
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:24` covers standalone clean-exit log marker extraction and asserts the exact recovered marker plus `source == "log"`.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:42`, `:57`, and `:72` cover same-stem companion artifact fallback for implement/review logs and the clean-exit plus allowlisted-log-name guards.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:86`, `:101`, `:113`, and `:132` cover malformed marker and duplicate/conflicting evidence fail-closed paths instead of merely asserting no exception.
- `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1206`, `:1243`, `:1257`, `:1285`, `:1324`, `:1337`, and `:1348` cover net-new planner behavior for artifact-recovered implement/solver/judge/review completion markers, markerless publish suppression, open-target filtering, and review head propagation.
- `skills/codex-refactor-loop/scripts/test_wakeup_runner.py:38` and `:62` cover runner source-marker revalidation through the shared reader and rejection of raw embedded marker prose.
- `skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py:272` and `:295` cover the review-gate behavior that frontmatter verdict remains authoritative while duplicate completion marker evidence blocks merge.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:154`, `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1316`, `:1397`, and `skills/codex-refactor-loop/scripts/test_skill_entrypoint_contract.py:87` provide source-regression locks for the new shared marker fact source and the removed synthetic markerless implement path.
- Diff scan found no added `sleep`/delay pacing, no added skip/manual markers, and no assertion-loosening pattern in the touched tests.
- Review note: GitHub currently reports PR head `ec9c25bf34147e0b0dee0829b3d880a091b421de`, while the prompt requested artifact head `ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627`; this review inspected the current PR diff `origin/auto-refact-dev...origin/refactor/iter499-issue-499`.

## What would change your verdict (only if comment or reject)
N/A

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:tests:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 架构 reviewer r3: approve

TL;DR

  • 这是什么: PR 实现 issue #499 #512 的架构合规复审,只看 CLAUDE.md / AGENTS.md 边界。
  • 现在到哪一步 / 结论是什么: approve,当前远端 head ec9c25bf34147e0b0dee0829b3d880a091b421de 没看到新增架构违规。
  • controller 下一步: 可继续汇总其他 reviewer 结论;提示里的 ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627 是当前 head 的祖先。

详细说明

worker_markers.py 是统一读取 worker 完成标记的 skill-private 模块;这次 PR 把 wakeup_plan.pywakeup_runner.pyimplement_lifecycle.py 里分散的 marker 读取收口到它。它仍要求 clean EXIT=0,同名 .refactor-loop/runs/<stem>.md companion artifact,以及 allowlisted log basename,没有把 .refactor-loop/ 提升成 host production SSOT,也没有新增 generic lifecycle actor。

从架构角度,这符合 CLAUDE.md 的 事实源唯一边界清晰,职责分层删除优先。review gate 仍由 artifact frontmatter 的 verdict 决定,REVIEW_DONE 只作为 clean worker completion / routing evidence,没有放宽 merge truth table。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: architect
head_sha: ec9c25bf34147e0b0dee0829b3d880a091b421de
verdict: approve
---

## Verdict
approve: no architecture-compliance concerns in the current PR head; the diff consolidates marker reading into a bounded skill-private helper without adding lifecycle authority or a parallel path.

## Evidence
- No blocking findings. Reviewed current remote head `ec9c25bf34147e0b0dee0829b3d880a091b421de`; prompt head `ba0d177ed2fb15d9a3691d74de9fcc73d1aa5627` is an ancestor of the current PR head.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:43` centralizes clean `EXIT=0` worker marker reading, and `:164` restricts companion artifact fallback to same-stem `.refactor-loop/runs/<stem>.md` with allowlisted log-name families. This matches CLAUDE.md: `事实源唯一` and `边界清晰,职责分层`.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:741` and `:757` consume `read_worker_terminal_marker(...)` for completed-marker detection instead of maintaining local fallback logic. This removes a duplicated pathway and aligns with CLAUDE.md: `删除优先` and `skill 行为 → 该 skill 的 SKILL.md 与 scripts/test_*.py`.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:313` and `:1055` revalidate `clean_exit_source_marker` through the shared reader before helper dispatch. The runner still rejects missing evidence and keeps the #396 controller-action allowlist, so I do not see a new lifecycle authority or generic command surface.
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:57` uses the shared reader for readiness while `:69` still requires exact `IMPLEMENT_DONE:*:ok` before publish-ready classification. This preserves the implement lifecycle policy boundary.
- Scope matches `.refactor-loop/runs/phase9-issue499-r1-judge.md` `scope_paths`; the one extra changed test file is documented by `.refactor-loop/runs/scope-extend-issue-499.log` as `SCOPE_EXTEND:skills/codex-refactor-loop/scripts/test_implement_lifecycle.py`.
- Old/New pattern policy is compliant: `HOST_REFACTOR_COMMENT_POLICY`/prompt policy normalize to `none`, and `git diff --unified=0 ... | rg '^\\+.*(Old pattern|New principle|Refactor \\()'` found no newly added refactor-history comments.
- Verification note: I could not rerun the focused pytest set from the active checkout because the PR-only files are not present in the current worktree; the implement artifact reports 305 focused tests passed and full codex-refactor-loop unittest discovery passed.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:architect:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 架构 reviewer r4:approve

TL;DR

  • 这是什么: PR 512 的 architect 角度复核,检查 CLAUDE.md / AGENTS.md 架构合规。
  • 现在到哪一步 / 结论是什么: approve,未发现会阻塞合并的架构回归。
  • 需要 maintainer 做什么 OR controller 下一步: controller 可把这个 reviewer 结果纳入 review-gate 真值表。

详细说明

这次改动把 worker terminal marker reader,也就是 worker 完成标记的统一读取入口,收敛到 codex_refactor_loop.worker_markers。我核对了实际 diff:它要求 clean EXIT=0 后才接受 marker,只允许同 stem 的 .refactor-loop/runs/<stem>.md companion artifact 作为 fallback,并且 duplicate / malformed / conflicting marker 都 fail closed。这和 CLAUDE.md 的「事实源唯一」「变更必须可验证」「.refactor-loop/ 不能成为 host production SSOT」方向一致。

我也看了 runner / planner 的消费侧:wakeup_plan.pywakeup_runner.pyimplement_lifecycle.py 都改为走共享 reader;旧的 synthetic markerless implement inference 被删除,没有新增 generic command surface、host config/branch topology 写入、外部 repo reference、*WriteActor / *ReadActor / *Store 拆分,或 compat shim。scope drift 方面,额外触碰 test_implement_lifecycle.py.refactor-loop/runs/scope-extend-issue-499.log 记录。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: architect
head_sha: ec9c25bf34147e0b0dee0829b3d880a091b421de
verdict: approve
---

## Verdict
approve: no architectural concerns from the CLAUDE.md / AGENTS.md compliance angle.

## Evidence
- `skills/codex-refactor-loop/SKILL.md:421` preserves artifact-frontmatter verdict authority and narrows `REVIEW_DONE` to completion/routing evidence through `codex_refactor_loop.worker_markers`, matching CLAUDE.md: "事实源唯一:同一约束禁止在多处平行声明。"
- `skills/codex-refactor-loop/SKILL.md:2159` records the shared marker-reader contract, clean `EXIT=0` gate, same-stem artifact fallback, and fail-closed duplicate/malformed handling, matching CLAUDE.md: "变更必须可验证:行为约束必须落到机械验证手段(behavior test / source-regression test / 段落 lint)" and "新增后台脚本或 runtime surface 必须显式说明:允许做什么 / 不允许做什么 / 事实源在哪里 / 如何验证".
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:43` makes `read_worker_terminal_marker` the shared reader and requires a terminal `EXIT=0` before log or artifact marker acceptance, matching CLAUDE.md FI-006: "变更必须可验证且基于 evidence;失败、缺口和越界承诺要显式暴露,禁止用静默假设或禁用测试换取通过。"
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/worker_markers.py:164` limits artifact fallback to same-stem `.refactor-loop/runs/<stem>.md` and allowlisted worker log names, so `.refactor-loop/` remains runtime/cache evidence rather than host production SSOT, matching CLAUDE.md FI-002: "skill-private runtime directories such as `.refactor-loop/` must not become host production configuration or ledger SSOT."
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_plan.py:758` and `skills/codex-refactor-loop/scripts/codex_refactor_loop/wakeup_runner.py:972` now consume the shared reader instead of maintaining separate marker parsers or synthetic markerless-implement inference, matching CLAUDE.md: "单一主干,插件扩展:每个 skill 一条权威主链路;新能力以子模块/脚本挂载,禁止平行第二系统。"
- Scope is honest: the diff is inside `skills/codex-refactor-loop/`, and `.refactor-loop/runs/scope-extend-issue-499.log` documents the only extra touched test path `skills/codex-refactor-loop/scripts/test_implement_lifecycle.py`.
- Old/New pattern policy is compliant for this diff: no newly added Old/New/iteration refactor-history source comments were introduced by PR 512.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:architect:approve

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 质量审查:通过方向正确,但有一个私有 helper 残留

TL;DR

  • 这是什么: PR 实现 issue #499 #512 的 readability / simplicity 质量审查。
  • 现在到哪一步 / 结论是什么: verdict 是 comment,共享 marker reader 本身可读,但 implement_lifecycle.py 留下了冗余私有 helper。
  • controller 下一步: 可继续汇总 review;作者可顺手删掉这两个旧解析入口,降低后续维护歧义。

详细说明

worker_markers.py 把 worker 终止 marker 解析收敛成共享入口,这个方向更简单,生产侧也确实有 wakeup_plan.pywakeup_runner.pyimplement_lifecycle.py 三个调用点,不是无用抽象。

我只看到一个小质量问题:skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:106_implement_run_artifact_done_marker()classify_implement_attempt() 改为直接调用 read_worker_terminal_marker() 后,不再被生产代码调用;它现在只是包装共享 reader。它旁边的 clean_implement_done_marker() 也只剩这个旧 helper 间接需要。建议删除 _implement_run_artifact_done_marker()clean_implement_done_marker(),把仍有价值的测试迁到 test_worker_markers.py 或改成通过 classify_implement_attempt() 断言。


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: quality
head_sha: ec9c25bf34147e0b0dee0829b3d880a091b421de
verdict: comment
---

## Verdict
Comment: the shared marker reader is a readable simplification, but the diff leaves one old implement-marker helper path as now-redundant private surface.

## Evidence
- `skills/codex-refactor-loop/scripts/codex_refactor_loop/implement_lifecycle.py:106`: `_implement_run_artifact_done_marker()` is no longer called by production code after `classify_implement_attempt()` switched to `read_worker_terminal_marker()` at line 57; it now just wraps the shared reader, and `clean_implement_done_marker()` at line 119 is also unused outside this leftover helper. Keeping these private helpers creates two apparent marker parsing entry points in a file whose new intent is to delegate marker parsing to `worker_markers.py`.

## What would change your verdict (only if comment or reject)
Delete `_implement_run_artifact_done_marker()` and `clean_implement_done_marker()` from `implement_lifecycle.py`, and move any remaining direct tests for that private helper to `test_worker_markers.py` or through `classify_implement_attempt()`.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:quality:comment

⟦AI:AUTO-LOOP⟧

@loning
Copy link
Copy Markdown
Contributor Author

loning commented Jun 5, 2026

🤖 tests review 通过

TL;DR

  • 这是什么:PR 实现 issue #499 #512 的 tests 维度独立审查,重点看新增测试是否覆盖真实行为。
  • 现在到哪一步 / 结论是什么:结论是 approve,没有发现阻断合并的测试质量或覆盖缺口。
  • controller 下一步:可以把这个 tests verdict 纳入 review gate 汇总。

详细说明

我检查了三点 diff、实际新增/修改测试文件,以及相关生产代码入口。worker_markers 是这次把 worker 完成标记解析集中到一个共享 reader 的模块;测试覆盖了 clean EXIT=0 log marker、同 stem run artifact fallback、allowlist 范围、malformed marker、duplicate/conflicting evidence fail-closed。wakeup_plan projection、wakeup_runner revalidation、review gate、implement readiness 也都有对应行为测试和 source-regression 断言。

没有发现新增 sleep/delay、skip/manual 标记、polling allowlist 变更或断言放松。用 PR head 导出到临时目录跑了相关测试子集:303 passed, 495 subtests passed in 147.83s


📎 完整 codex 原始输出(存档备查)
---
pr: 512
role: tests
head_sha: ec9c25bf34147e0b0dee0829b3d880a091b421de
verdict: approve
---

## Verdict
Approve: test coverage and quality are adequate for the marker-reader consolidation diff.

## Evidence
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:24` covers standalone clean-exit log marker parsing, and `:42`, `:57`, `:72`, `:86`, `:101`, `:113`, `:132` cover same-stem artifact fallback, allowlist/clean-exit scoping, malformed marker rejection, and duplicate/conflicting evidence fail-closed behavior.
- `skills/codex-refactor-loop/scripts/test_worker_markers.py:154` adds source-regression coverage that `wakeup_plan.py`, `wakeup_runner.py`, and `implement_lifecycle.py` import the shared reader and that strict marker-contract literals remain present.
- `skills/codex-refactor-loop/scripts/test_wakeup_plan.py:1211` and `:1243` cover markerless clean implement logs with and without companion artifacts; `:1257` keeps existing log-marker paths working, and `:1285` keeps artifact fallback gated by open target state.
- `skills/codex-refactor-loop/scripts/test_wakeup_runner_review_gate.py:272` verifies review artifact frontmatter remains verdict authority even when the `REVIEW_DONE` completion marker disagrees; `:295` verifies duplicate review completion markers fail closed without merge.
- `skills/codex-refactor-loop/scripts/test_implement_lifecycle.py:25` and `:37` cover implement readiness recovery for `IMPLEMENT_DONE:*:ok` and redispatch behavior for partial, missing, and non-implement cases.
- Diff scan found no added `sleep/delay`, skip/manual markers, polling allowlist entries, or assertion loosening. The related PR-head test subset passed: `303 passed, 495 subtests passed in 147.83s`.

⟦AI:AUTO-LOOP⟧
REVIEW_DONE:512:tests:approve

⟦AI:AUTO-LOOP⟧

@loning loning marked this pull request as ready for review June 5, 2026 03:52
@loning loning merged commit a5944e1 into auto-refact-dev Jun 5, 2026
4 checks passed
@loning loning deleted the refactor/iter499-issue-499 branch June 5, 2026 03:52
@loning loning added crnd:phase:merged merged and removed crnd:phase:reviewing review-gate reviewers in flight labels Jun 5, 2026
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 patrol_inspector daemon 启动崩溃:DaemonHeartbeatLease 用构造函数非 from_env

#551 patrol.py daemon 分支调 DaemonHeartbeatLease.from_env()(不存在的方法)→
AttributeError 启动即崩,daemon 从未成功跑起来。改为 DaemonHeartbeatLease(
"patrol_inspector_daemon", ctx.repo_root),与 closed_label_reconciler/wakeup_runner
一致,心跳文件名匹配 restart 助手期待的 patrol_inspector_daemon.ts。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap 残留层:duplicate-marker log 读 companion artifact + 取代 superseded spawn intent

层2 残留:implement worker 把 IMPLEMENT_DONE:issue-N:ok 在 log 里 echo 多次→
worker_markers 返回 duplicate_or_conflicting_log_marker fail-closed→classifier 当
markerless 且不查 companion artifact→无 completed-marker action→无 publish→stale
harness-spawn-intent:dispatch-consensus-implementation:N 残留致 pending_implement_intent。

修:(1) classify_implement_attempt / completed_marker_actions 遇 duplicate marker 时
narrow 读 companion .refactor-loop/runs/implement-*.md(仅 implement log,仅末 30 行恰好
1 个 IMPLEMENT_DONE:ok 才接受);(2) suppress_publish_superseded_implementation_spawn_intents:
仅当某 issue 已有 executable publish_implementation_output 才把对应 dispatch-consensus-
implementation spawn intent 抑制为 status_only(implementation_ready_to_publish)。
不重蹈 #507 死锁:只在 publish 已 ready 后抑制 spawn(不漏派)、publish 仍全验证(不提前/
重复)、wakeup-runner/publish 授权口径不变。live 验证 #553 现投影 executable publish。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #555 (#557)

* 修复 publish-gap 第3层:wakeup_runner clean_exit revalidation 对 duplicate-marker log 复用 artifact-fallback

pubgap2 修了 plan 侧 duplicate-marker artifact-fallback,但 wakeup_runner 的
_source_log_has_clean_marker(clean_exit_source_marker 预条件 revalidation)仍用严格
reader,对 #553 duplicate IMPLEMENT_DONE echo 返回 clean_exit_marker_missing→阻 publish。
改为严格 reader 优先,仅当 duplicate_or_conflicting_log_marker + is_implement_log +
_implement_run_artifact_done_marker 精确匹配 projected marker 才 fallback。复用 plan 侧
同一 helper,不弱化安全门(reviewer/release/rebase/非 implement/其它 fail reason 保持严格)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 接 dispatch_remote_ci_fix 进 wakeup_runner:pipeline 自主修 ci-red(#396 内)

children review 通过但 contract-tests 红(改 restart/supervisor daemon 却没同步本地
TEST_CMD 屏蔽的 daemon-count 测试),wakeup_runner 缺 dispatch_remote_ci_fix 实现致
ci-red 永 status_only 不自主修。镜像既有 dispatch_reviewers + review-fix commit-push:
每失败 check 派一个 remote-ci-fix.md worker(无 commit 权),REMOTE_CI_FIX_DONE:<check>:ok
后 controller safe_push 推,:infra/:blocked 留 maintainer。durable retry cap=2 per
pr:head_sha:check(state/remote-ci-fix-attempts.json),超限 RETRY_CAP 停。在 #396
'dispatch remote-ci worker' 口径内,worker 无 lifecycle/commit 权,无新授权。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 wakeup_runner 单 helper 失败饿死全 tick:仅直接 spawn launch 失败才 break

run_once 对任何 spawn-budget blocked 且 reason 含 helper_exit:* 就 break 整 tick。rollup
PR #560(head rollup/<sha> 无 worktree)的 review-fix helper_exit:3(WORKTREE_MISSING)→
break → 饿死 #558/#561 的独立 ci-red 派发,致 runner ~30min noop 0 派发(0 codex)。
改为:仅直接 spawn_codex_harness_background launch 失败(is_spawn_action + _spawn_launch_failure)
才停扫描;blocked named helper(review_gate FIX / dispatch_remote_ci_fix)记录后 continue,
让同 tick 后面独立 PR 的 action 仍被处理。单 PR helper 失败不再阻塞全局派发。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 收紧无人唤醒与大 issue 分解授权测试 (#559)

* 实现 issue #556

* 实现 issue #556

* PR #559 review-fix output

* 修复 identical-duplicate terminal marker 被误判 conflicting:reader 容忍相同重复

remote-ci-fix worker echo REMOTE_CI_FIX_DONE:check:ok 两次→read_worker_terminal_marker
返回 duplicate_or_conflicting→runner 读不到→不 commit worker fix→撞 retry cap,#558 卡。
根因修(worker_markers._sentinel_adjacent_marker):无 sentinel-adjacent 但 tail 有 2+
standalone marker 全 identical 时返回该 marker。一次修 implement/ci-fix/未来所有 marker。
不弱化 conflicting:不同 marker 仍 fail,malformed 仍 fail,单非终止 marker 仍不终止。
不扩 #396;wakeup_runner 仍 revalidate clean_exit_source_marker 才 commit/push。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* rollup PR 自主化(maintainer-directive 2026-06-06):singleton + CI-only + 详细 body + auto-squash-merge

实现 maintainer 指令「rollup 只要ci过了就可以,不用review...绿了自动squash...默认自动,在env可配,只开一个rollup」:
- Singleton:已有 open rollup(head rollup/ + base review-base)时 force-with-lease 更新其 head 到当前
  integration SHA + 刷新 title/body;无则才新建,不增殖。
- CI-only:rollup PR 排除出 reviewer/review-fix/remote-ci-fix dispatch(不走 cluster 3-reviewer gate)。
- 详细 title/body:integration 领先 review-base 的 commit 数 + 范围 + commit 摘要(中文经 hex 编码守 source-EN-only)。
- Auto-squash-merge:host.env ROLLUP_AUTO_MERGE(默认 auto;manual 则等人工)。owner-gated + 仅 rollup PR
  narrow allowlist + exact-SHA required checks 全绿硬 gate(ReleaseRequiredChecksProjection)→ gh pr merge
  --squash --delete-branch;分支保护/host-policy 失败→WAIT 留人工不 force。所有失败写诊断 pending event。
- 授权双锚定:runtime-exceptions.md#rollup-autonomous-merge-2026-06-06 + SKILL.md + host.env surface matrix;
  durable artifact = maintainer-directives/2026-06-06。source-regression + behavior test 全覆盖。回归 1619 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #552

* PR #558 remote-ci-fix output

* 移除 #552 越界加的孤立 flaky phase9-router 测试

fb2f461(#552 实现)给未改动的 phase9 router 加了 test_phase9_router_tick_summary_is_
router_local_diagnostic,与 #552「收窄 restart daemon 权威」scope 无关,且该测试 call
self.router.tick() 不 mock managed-work-snapshot fetch → CI 无 GitHub 时 fetch-failed
诊断行污染输出致 anchored regex 不匹配(flaky),挡 CI。main 从无此测试。按删除优先+scope
收口移除;若 router 诊断测试有价值应在 phase9-focused PR 以 hermetic 形式正式加。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。



* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。



* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。



* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。



* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。



* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。



* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。



* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。



* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。



* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。



* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。



* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。



* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。



* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。



* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。



* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。



* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。



* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。



* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。



* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。



* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。



* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。



* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。



* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。



* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。



* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。



* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。



* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。



* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。



* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。



* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。



* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。



* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。



* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge



* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)



* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)



---------



* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。



* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。



* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。



---------



* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。



* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。



* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。



* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。



* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。



* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。



* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。



* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。



* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。



* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。



---------



* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。



* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。



* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。



* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。



---------



* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。



* 实现 issue #552

* PR #558 remote-ci-fix output

* 移除 #552 越界加的孤立 flaky phase9-router 测试

fb2f461(#552 实现)给未改动的 phase9 router 加了 test_phase9_router_tick_summary_is_
router_local_diagnostic,与 #552「收窄 restart daemon 权威」scope 无关,且该测试 call
self.router.tick() 不 mock managed-work-snapshot fetch → CI 无 GitHub 时 fetch-failed
诊断行污染输出致 anchored regex 不匹配(flaky),挡 CI。main 从无此测试。按删除优先+scope
收口移除;若 router 诊断测试有价值应在 phase9-focused PR 以 hermetic 形式正式加。



---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402、#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 patrol_inspector daemon 启动崩溃:DaemonHeartbeatLease 用构造函数非 from_env

#551 patrol.py daemon 分支调 DaemonHeartbeatLease.from_env()(不存在的方法)→
AttributeError 启动即崩,daemon 从未成功跑起来。改为 DaemonHeartbeatLease(
"patrol_inspector_daemon", ctx.repo_root),与 closed_label_reconciler/wakeup_runner
一致,心跳文件名匹配 restart 助手期待的 patrol_inspector_daemon.ts。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 修复 publish-gap 残留层:duplicate-marker log 读 companion artifact + 取代 superseded spawn intent

层2 残留:implement worker 把 IMPLEMENT_DONE:issue-N:ok 在 log 里 echo 多次→
worker_markers 返回 duplicate_or_conflicting_log_marker fail-closed→classifier 当
markerless 且不查 companion artifact→无 completed-marker action→无 publish→stale
harness-spawn-intent:dispatch-consensus-implementation:N 残留致 pending_implement_intent。

修:(1) classify_implement_attempt / completed_marker_actions 遇 duplicate marker 时
narrow 读 companion .refactor-loop/runs/implement-*.md(仅 implement log,仅末 30 行恰好
1 个 IMPLEMENT_DONE:ok 才接受);(2) suppress_publish_superseded_implementation_spawn_intents:
仅当某 issue 已有 executable publish_implementation_output 才把对应 dispatch-consensus-
implementation spawn intent 抑制为 status_only(implementation_ready_to_publish)。
不重蹈 #507 死锁:只在 publish 已 ready 后抑制 spawn(不漏派)、publish 仍全验证(不提前/
重复)、wakeup-runner/publish 授权口径不变。live 验证 #553 现投影 executable publish。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #555 (#557)

* 修复 publish-gap 第3层:wakeup_runner clean_exit revalidation 对 duplicate-marker log 复用 artifact-fallback

pubgap2 修了 plan 侧 duplicate-marker artifact-fallback,但 wakeup_runner 的
_source_log_has_clean_marker(clean_exit_source_marker 预条件 revalidation)仍用严格
reader,对 #553 duplicate IMPLEMENT_DONE echo 返回 clean_exit_marker_missing→阻 publish。
改为严格 reader 优先,仅当 duplicate_or_conflicting_log_marker + is_implement_log +
_implement_run_artifact_done_marker 精确匹配 projected marker 才 fallback。复用 plan 侧
同一 helper,不弱化安全门(reviewer/release/rebase/非 implement/其它 fail reason 保持严格)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* 实现 issue #553

* PR #561 review-fix output

* PR #561 remote-ci-fix output

* PR #561 review-fix output

* 收窄 restart daemon 权威到 owner-local 命令面 (#558)

* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+co…
loning added a commit that referenced this pull request Jun 6, 2026
* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。



* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。



* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。



* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。



* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。



* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions 309 通过。



* hotfix r12: run_once 不再让 spawn-batch starve drain-only lifecycle — ready PR headless merge,backlog 能 drain

根因(已核实):wakeup_plan 每 tick 把 SPAWN actions(implement intent + design-consensus #495/#496/#490/#491/#418,index 0-5)排在 lifecycle review_gate(#480/#473/#402,index 6-8)之前;run_once 旧逻辑 `if applied_spawns>0 and not is_spawn_action: break` → 只要派了任一 spawn,首个 lifecycle 即 break 整 tick。design-consensus 几乎总有 spawn 活 → review_gate/merge 永远 starve → #473(approve/approve/comment → MERGE_WITH_COMMENTS,MERGEABLE+CI 绿)永不 merge,active 数永不下降。

修法(最小,核心 dispatch loop):
- 引入 consumes_spawn_budget = is_spawn_action or _uses_spawn_budget(action);超 budget 时 `continue`(不 break)以便仍能抵达后续 drain-only lifecycle。
- _uses_spawn_budget:dispatch_reviewers=True、review_gate 仅当决策为 FIX(会派 fix worker)=True;否则 review_gate(MERGE/MERGE_WITH_COMMENTS)、close 等 drain-only=False → 不占 spawn budget、floor 填满后仍被评估执行。
- 保留 r6 的 spawn launch-failure break/retry 与 dispatch_design_consensus no-intents skip-and-continue;真值表/head-binding/CI-green/mergeable 安全语义不变。

结果:每 tick 既用 spawn 填满 floor,又评估 merge/close 等 drain-only lifecycle,backlog 能 drain。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+controller_actions+pr_checks 309 通过;新增 test_wakeup_runner_lifecycle_review_gate_not_starved_after_spawn_batch。



* hotfix r13: 修 WakeupRunner._run_command 把 --repo 注入到 gh 子命令前致全部 gh 调用 malformed — review→merge 根因

根因(实测确认):_run_command 对所有 gh 命令在 full[1:1] 插 --repo(子命令之前)。gh 不接受 --repo 作 pre-subcommand 全局 flag,且 gh api 根本不吃 --repo(repo 在 URL):`gh --repo O/R api repos/O/R/pulls/473` → rc=1 "unknown flag: --repo"。于是 wakeup-runner 的每个 gh 调用都 malformed:CI 读(PrChecksProjection(runner=_run_command) 的 gh api pulls/check-runs)→ ci_unavailable:pull_api_failure;mergeability(gh pr view)→ mergeability_unavailable;live-state 等同理。→ review gate 永远读不到 CI/mergeable → #473(approve/approve/comment=MERGE_WITH_COMMENTS,绿)、#402#480 永不 headless 落地。r11 的 retry 只是重复同一 malformed 命令。直连 PrChecksProjection()/直连 gh 用的是 plain default runner(无注入)所以正常,掩盖了 bug。

最小修法:_run_command 仅对 `gh pr`/`gh issue` 注入 --repo,且放在子命令(及其 verb)之后的合法位置;`gh api` 完全不动;绝不 pre-subcommand 注入;已存在 --repo 则不重复。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+pr_checks+wakeup_plan+controller_actions 312 通过;新增 argv-shape 测试 + e2e(stub subprocess.run 拒绝 malformed `gh --repo ... api`,ready PR 仍 merge)。



* hotfix r14: managed draft PR ready-then-merge — review gate 不再硬挡 pr_draft

根因(r13 修好 gh 调用后浮现):review_gate 的 _review_gate_mergeability_error 把 isDraft=True 当 WAIT_OR_REDISPATCH:pr_draft 硬挡。但本 loop draft-until-consensus:PR 开为 draft 直到 review 共识,merge_pr 在决策 MERGE/MERGE_WITH_COMMENTS 时 ready-then-merge。于是绿 gate 的 managed draft(如 #473 approve/approve/comment)永远卡 pr_draft、永不 headless 落地。

最小修法:
- wakeup_runner:删除 mergeability 检查里的 isDraft→pr_draft 硬挡(仍挡 mergeable!=MERGEABLE,即 CONFLICTING/DIRTY)。
- controller_actions.merge_pr:对 live draft PR 先校验 crnd:lifecycle:managed 再 gh pr ready(非 managed draft 不 ready,写 CONTROLLER_ACTION_BLOCKED:target-not-managed 并返回 2);保留既有 ready-then-merge。
- 真值表/head-binding/CI-green/conflicting-blocks 安全语义不变;readying 仅限 managed PR。

验证:controller 独立重跑 test_wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan+pr_checks 316 通过;新增 managed-draft merge + 真实 plan→runner→controller ready-then-merge e2e + conflicting/非managed 安全用例。



* #409: 移除 .refactor-loop/host.env runtime fallback,CONSENSUS_RND_HOST_ENV 为唯一 host fact locator(缺失 fail-closed);迁移依赖 legacy fallback 的 test fixture (#473)

* hotfix r15 (sshx 共识 B 之一): 统一 gh argv 构造到单一 build_gh_argv helper — 防 r13 类 --repo bug 复发

sshx 一致共识 B 的硬化第1步:把分散重复的 gh --repo 处理收口到 codex_refactor_loop/gh_invoke.py 的 build_gh_argv(slug, argv):gh api 永不加 --repo(repo 在 URL);gh pr/issue 仅在 subcommand 之后、缺失时加 --repo <slug>;绝不 pre-subcommand。wakeup_runner._run_command / ControllerActions.gh / PrChecksProjection 三处 API 调用全部改走该 helper,删除各自的内联 --repo 启发式。行为保持不变(含 r13 修复)。

验证:characterization + source-regression 锁在 test_gh_invoke.py(9 测试);controller 独立重跑 test_gh_invoke+pr_checks+wakeup_runner+review_gate+review_gate_e2e+controller_actions+wakeup_plan 326 通过;pr_checks 直跑 --help 兼容。

注:这是硬化(防复发),不直接提升并发;并发瓶颈在上游 implement→publish 阶段,接下来单独处理。



* hotfix r16 (sshx 共识): 打通 implement→publish 解锁并发瓶颈 — markerless/stale implement 重派 + 安全门控发布

sshx codex-cli triplet 共识(minimal/structural/delete + meta-judge):10 个 design-solving issue 已达成共识但卡在 implement→publish(implement 早跑过却 markerless/未提交/过期 base/没 PR;dispatch_consensus_implementation 被 local_iter_branch 抑制、publish 被 verified_pr_head_unavailable 抑制)→ 无新可派工作 → 并发 ~1。

修法(wakeup_plan/wakeup_runner/controller_actions/git.py):
- success-aware 重派:implement 分支/worktree 存在但无 valid clean IMPLEMENT_DONE:ok marker(markerless/failed)或 base 过期 → 重派;fresh_safe_worktree 把 canonical worktree reset/recreate 到当前 origin/$INTEGRATION_BRANCH;仅 genuine in-flight / 已有干净 PR / 待发布 clean marker 才抑制。
- 发布门控(严防误发 stale/wrong-scope):publish_implementation_output 仅在 canonical identity(refactor/iter<issue>-<candidate> + worktree 实际分支匹配)+ fresh integration base(merge-base==origin/integration,过期 base block)+ managed open issue + 无重复 PR + 非空 scoped diff 时,commit→push→open PR→派 reviewers;否则 block。
- wakeup_plan 用 canonical_implementation_identity/single_linked_managed_issue/clean_scoped_diff 替代 verified_pr_head 抑制。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 330 通过。

已知待修(follow-up):worker 把 PR title/body/commit 文案改成英文,违反「GitHub artifact 中文」策略,下一 commit 恢复中文。



* hotfix r17: fresh consensus-implement 重派前清除 terminal 非可发布 implement log — 让卡住的 implement 真正启动

承接 r16:r16 让 markerless/stale implement 重派(reset worktree),但旧的 EXIT=1/markerless implement log 仍占 spawn 的 target_log_absent 前置 → fresh implement 不启动(同一类「按存在抑制」,implement-spawn-log 层)。

修法(controller_actions,success-aware):fresh consensus-implementation dispatch 写 spawn intent 前,仅清除 terminal 非可发布 implement log(EXIT!=0 失败 / EXIT=0 无 IMPLEMENT_DONE:ok marker);保留 genuinely in-flight(无 EXIT)与 clean publish-ready(EXIT=0 + 干净 marker)log 不动。于是卡住的 markerless/failed implement 重派后能真正 launch、跑在 fresh base、产出干净 marker → r16 门控发布。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 333 通过。

设计说明:并发瓶颈用确定性逻辑修对(ready=clean EXIT=0+marker;parallel=scope_paths 不相交),不引入 LLM-in-loop 分发判断(daemon-first;sshx codex 三人组一致 revise:LLM 最多 shadow-mode,不入决策回路)。



* hotfix r18: implement-lifecycle 收敛为单一 success-aware 谓词 + runner 路径自清陈旧 log — headless 自愈,不再需手动清 log

承接 r16/r17(r17 把清 log 放进被抑制的 dispatch 路径,从没执行)。新增 implement_lifecycle.py 单一事实源 classify_implement_attempt → in_flight | publish_ready | redispatch,plan/runner/controller 共用:
- runner spawn-apply 路径 _spawn_log_suppresses_retry 仅在 in_flight|publish_ready 时抑制;redispatch(EXIT!=0/markerless/stale-base) 不抑制且 _clear_redispatchable_spawn_log 在 spawn 实际应用处清掉陈旧终态 log → fresh implement 真启动(修 r17 misplacement,免手动清)。
- publish 仅 publish_ready(clean IMPLEMENT_DONE:ok + canonical identity + fresh base + 非空 scoped diff);clean-marker 但 stale-base 改 redispatch 而非死锁(#421 edge)。
- 确定性逻辑(非 LLM-in-loop;daemon-first);merge-gate/#191/#322/#396 安全语义不变。

验证:controller 独立重跑 wakeup_plan+wakeup_runner+review_gate+review_gate_e2e+controller_actions+pr_checks+gh_invoke 339 通过。



* 修复 phase9-router triplet-evidence-invalid 误判致 headless design-consensus wedge

solver prompt 注入的 issue source snapshot 含上一轮 design-consensus 的
audit-trail(peer solver log 路径)时,_peer_solver_reference_violation
扫描整个 prompt 误判为 peer-isolation 违规,fail-closed 拒派 meta-judge,
使所有 body 含历史 consensus 记录的 issue 永久 wedge。

修复:peer-isolation 扫描只覆盖 router-controlled 区域,剥离
'## Issue source snapshot' 到 '## Full solver template' 之间的 issue
作者内容;router header / solver template 注入的真实 peer 引用仍拦截。
加两个 behavior test 覆盖 snapshot-排除 与 router-区域-仍拦截。

dogfood headless 实测:reload 后 418/437/474/490/491/493/494/495 全部
恢复 solver→judge→consensus 自驱,#494 已自驱到 implement。



* CLAUDE.md: 加 consensus-rnd:foundational-invariants sentinel block

dogfood bootstrap 的 check-project-rules probe 要求 PROJECT_RULES 含此
fixed-point block;缺失时 probe fail-closed 阻断 headless restart。内容
为 probe 生成的 canonical FI-001~007,镜像既有设计哲学,不引入新约束。



* 修复 markerless implement 致 publish 卡死的 headless gap

implement worker 干净退出(EXIT=0)但把 IMPLEMENT_DONE marker 只写进 run
artifact(runs/implement-issue-<id>.md)而非 log 末尾时(codex stdout marker
落点不可靠),completed_marker_actions 只扫 log marker → markerless → 不生成
publish action → design→implement→PR 链卡在 implement 后。实测 #421:EXIT=0
+ artifact 有 IMPLEMENT_DONE:issue-421:ok + 9 文件 staged,却无 PR、label 仍
停在 design-solving。

修复:对 clean-exit 的 implement-issue log,log markerless 时 fallback 读取
run artifact 末尾的 IMPLEMENT_DONE marker,复用 review verdict 已有的
artifact-first 模式。窄作用域(仅 implement-issue + clean-exit),配 2 个
behavior test;全套 wakeup_plan 138 tests green。



* 补全 markerless implement publish:revalidation 也读 run artifact marker

8aeea89 修了 wakeup_plan detection 端,但 wakeup-runner 的 source-marker
revalidation(_source_log_has_clean_marker)仍只扫 log,markerless implement
publish 仍被 reject(clean_exit_marker_missing)。补全:revalidation 对
clean-exit implement-issue log 在 log markerless 时 fallback 读
runs/implement-issue-<id>.md 的 marker,与 detection 端一致;配 behavior test,
全套 wakeup_runner 76 tests green。

注:dogfood 实测确认 markerless 是系统性病根(还影响 readiness 重派、review
verdict 等多处),应走系统性统一(见 #491 日志/observability 与后续 marker-reading
收口);本 commit 只补 implement publish 这条链。



* 日志详细化:wakeup-runner tick 显示全状态计数 + 被掩盖的 blocked/skipped 详情

旧 _wakeup_tick_action 只看 results[0],一个 tick 处理多 action 时 blocked(如
publish 失败)被成功的 spawn 掩盖、完全不可见;graphql-backoff 固定显示误导的
'remaining=unknown'。dogfood 调试时这逼得每次翻 ledger 才知道真实发生了什么。

改:tick log 显示 [applied=N,blocked=M,...] 全状态计数 + 被掩盖的 blocked/skipped
具体 reason+action(graphql-backoff 作整-tick 门控单独报、去掉 unknown);dispatched
headline 保留。更新 test 反映可见性提升,全套 wakeup_runner 76 tests green。



* 补全 markerless implement 第三环:readiness 谓词读 run artifact marker

classify_implement_attempt(r18 单一 success-aware 谓词)只扫 log 找
IMPLEMENT_DONE:ok,markerless log(marker 落 artifact)→ redispatch:markerless →
readiness 不 suppress → 重派覆盖已完成工作(dogfood 实测 #421 重派 4 次、#493
IMPLEMENT_DONE:ok→重派→:partial 工作丢失)。

补全:markerless log 时 fallback 读 runs/implement-<cluster>.md 的
IMPLEMENT_DONE:ok,与 detection(8aeea89)/revalidation(dfacc64)一致。窄作用域 +
r17/r18 兼容:只接受 :ok,partial/失败/真 markerless(无 artifact)仍 redispatch
recovery — 现有 markerless-redispatch test(wakeup_plan/wakeup_runner/
controller_actions 共 304 tests)全绿,新增 2 behavior test。

至此 implement→PR 的 markerless 三环(detection/revalidation/readiness)打通;
review 链 markerless 与系统性统一抽象交 #499 共识。



* #500: design-consensus 编排重设计 — phase9-router 唯一派发 owner,删 wakeup-runner 双重派发

落地 #500 r4 consensus(structural framing,no-new-schema):
- phase9-router 成为唯一 design-consensus worker intent owner,新增
  META_RESOLVED:re-design → marker.round+1 三路 solver route
- 删除 wakeup-runner 的 dispatch_design_consensus(消除双重派发 helper_exit:3)
- wakeup-runner 只保留 closed action apply(drop→close、consensus→implement)
- dispatch_consensus_implementation readiness 后转 crnd:phase:implementing
- 无新增 schema(复用 HARNESS_SPAWN_INTENT)

修复 headless P0:reflector META_RESOLVED 无 consumer + phase9-router/wakeup-runner
双重派发致 0-codex 死锁。14 文件 +207/-282;verification 471 tests 全绿。

共识由 controller 手动驱动 design-consensus r1→r4 达成(daemon 停止期间)。



* #501 fix r1: 补 dispatch_consensus_implementation label-transition failure-branch test

tests reviewer reject:新增 label transition(gh issue edit→implementing)只测 success
path,缺 gh issue edit 返回 nonzero 时 dispatch stop before worktree/render/intent 的
failure-branch test。本 fix 补该测试。



* 修复 headless 死锁:label 移除集只留 canonical crnd:*,删除历史 alias

gh issue/pr edit --remove-label 会因仓库不存在的 label 整条 rc=1 失败。
ISSUE_LABELS_REMOVE/PR_LABELS_REMOVE 含 cleanup_aliases(emoji/legacy 名),
仓库未维护这些历史 label,导致 _move_issue_to_implementing_phase 永久失败,
consensus→implement 派发卡死、wakeup_runner 0 codex 自驱死锁。

按 maintainer 指令删除历史 label 兼容(不再管历史标签):移除集只列
canonical crnd:* phase/human/stuck label。新增 source-regression 锁定
两集 canonical-only、无 alias。



* 修复 #500 回归:phase9-router 生产 ctx 丢失 GH_REPO_SLUG 致 design-consensus intake 全死

#500(e733b1a)把 Phase9Router.__init__ 的 ctx 构造从
`LoopContext.load(repo_root=repo_root)` 改成
`LoopContext.load(repo_root=repo_root, env={"REPO_ROOT": str(repo_root)})`。
受限 env 不读 os.environ,使 daemon(经 source host.env 启动)的 ctx
gh_repo_slug=None → `_open_design_consensus_issues` 第一行 fail-closed 返回 []
→ DesignConsensusIssueIntake 静默永不派 → headless 无法为任何 issue 启动
design-consensus;`_require_open_source_issue` 也因无 slug 失败(marker route
如 #490 redesign 卡在 phase9-source-state-unavailable)。

修复:revert 为 `LoopContext.load(repo_root=repo_root)`,读进程环境解析 host facts。
测试一律用 `Phase9Router(ctx=...)` 显式 ctx,不依赖受限 env;新增回归测试锁定
生产 repo_root 构造路径解析 GH_REPO_SLUG。



* 加 STALE_REVIVAL_HOURS:>阈值未推进的 stuck implement 自动 re-trigger(env 可配,默认 3h)

headless 下 partial/failed/markerless 的 implement log 会让已排队的
dispatch-consensus-implementation spawn intent 永久卡在 runner 的
target_log_absent 前置(清 log 的 dispatch_consensus_implementation 又被
pending_implement_intent 抑制)→ stuck implement 不会自愈(如 #421/494/493/474/498
的 10h partial-wedge)。

新增 host-tunable STALE_REVIVAL_HOURS(默认 3,非正/非法回落 3h)。wakeup_plan
投影 implement spawn intent 时,若目标 implement log 是 redispatchable
(partial/failed/markerless/stale-base)且 mtime 已超阈值,清掉它 →
target_log_absent 通过 → implement 自动重派。安全闸:in-flight(无终止 EXIT)永不清、
publish-ready(:ok+diff)不清、age-gate 防误清刚跑完的。

env 已登记进 SKILL.md host env surface matrix + host.env.example;5 个 behavior
test + matrix↔example 对称测试覆盖。



* 扩展 stale-revival 覆盖死 codex:in_flight 无 EXIT 且 >阈值 + 不在存活清单 也 re-trigger

最常见的 headless wedge 是 codex/supervisor 中途死亡(如 daemon 被 kill 截断),
log 永远停在 in_flight(无终止 EXIT)→ classify 永判 in_flight → 永不 redispatch。
之前只清 redispatchable(partial/failed/markerless)log,漏了这半边。

现在 _revive_stale_redispatchable_implement_log 在 log mtime 超阈值时,先按
redispatchable 清;否则若 classify 为 in_flight 且 monitor 存活清单里无该 log 的
活进程,则判定为死 worker 清掉。安全性:spawn-codex 的 no-output stall 窗口远小于
默认 3h,故 >阈值仍 in_flight 的 log 必是死 supervisor;再加 monitor 存活校验
双保险,绝不杀活 codex。新增 3 个 behavior test(死 codex revive / fresh 不碰 /
活进程不碰)。



* 加手动 trigger:consensus-rnd-cli revive-implements(立即 re-trigger 卡住的 implement,不等阈值)

_revive_stale_redispatchable_implement_log 加 force 参数:跳过 stale_revival_seconds()
age gate,但 in_flight log 在 force 下必须经 monitor 存活校验证明无活进程才清(绝不杀
正在跑的 codex)。新增 force_revive_stuck_implements() 扫所有 implement-issue-*.log
强制 revive,和新 CLI 命令 revive-implements(authority delete-log)。auto 路径
force=False 不变。新增 4 个 behavior test。



* 修 env 泄漏:测试套件 import 时隔离 ambient host.env(worktree 里跑 TEST_CMD 不再假失败)

daemon spawn 的 implement worker 在 worktree 里跑完整 TEST_CMD 时,继承的相对
CONSENSUS_RND_HOST_ENV=.config/consensus-rnd/host.env 泄漏进 temp-repo
LoopContext.load(repo_root=tmp) → 解析成 tmp/.config/... 不存在 → 假
LoopContextError(实测 concurrency_monitor 48 + restart_daemons 23 + … ≈151 errors)
→ 全套永不绿 → implement 永远 :partial → 进不了 PR。

unittest discover 在 collection 阶段先 import 所有 test_*.py 再跑;新增
test_aaa_host_env_isolation.py(字母序最先)在 import 时 pop 掉 host 注入变量,
全套在任何测试 run 前即隔离。验证:full discover 设 locator 跑 → exit 0 全绿
(此前 同条件 151 errors);targeted before/after 证 48/23/1 errors → OK。
纯测试模块,不碰 production/daemon。



* 修 markerless keystone:solver/judge marker 加 companion-artifact fallback

solver/judge codex 有时 EXIT=0 但 SOLVER_DONE/META_JUDGE_DONE marker 只落 run
artifact、没在 log 末尾,导致 phase9-router 判 triplet 不完整、永不派 judge,
design-consensus 轮卡死(实测 #505 r1 structural 214 次嵌入、0 次行首)。

把已有的 implement artifact-marker fallback 扩到 solver/judge:clean-exit log
末尾无独立 marker 时,从 companion run artifact runs/<log-stem>.md 兜底读。纯
additive(log 有 marker 时行为不变)、prefix-scoped、精确 filename regex、复用
安全的独立 marker 提取(不信嵌入/echo)。不削弱共识(仍要 3 marked solver +
judge,只让 marker 来源更稳健)。phase9/router.py + wakeup_plan.py + behavior +
source-regression tests;full suite 1367 green。



* 修 publish stale-base 无恢复 + 停 :ok churn:让 implementing 能发出 draft PR

implement :ok 但 worktree base 落后 origin/$INTEGRATION_BRANCH 时,publish 原本硬
block(publish_implementation_stale_base)且永不恢复;stale-revival 又把 stale-base
的 :ok implement 当 redispatchable 反复重派同一 stale worktree → 无限 churn 占满
floor、长时间零正式 PR(implement→首个 PR 永远开不出)。

改为:publish 前在 worktree merge origin/$INTEGRATION_BRANCH 恢复 base(冲突则
merge --abort + 明确 reason 交既有 resolver/re-dispatch);clean `:ok` 不再被
stale-revival churn(终态成功走 publish-with-recovery,不重跑);无 open PR 的 :ok
创建 draft PR(per #300 共识前 draft)+ Closes #N。controller 仍拥有 git topology,
worker 不 commit/push,不绕 review-gate/merge 真值表。controller_actions.py +
wakeup_plan.py + wakeup_runner.py + behavior/source-regression tests;full suite
1374 green。



* 修 markerless implement:EXIT=0+真diff 无干净 marker 时合成 publish 候选,止 stale-revival 空重派死循环

publish build/test 闸做安全网。



* 修 publish 顺序 bug + merge 失败派 codex 兜底 resolver:先 commit worker diff 再 merge fresh base,真冲突不 wedge 改派 resolver,幂等续跑

空判据改 git diff HEAD;顺带修 wakeup_plan stale-suppression 同类 git diff 问题。



* 实现 issue #504 (#519)

* 修 headless review-fix prompt 渲染不全:绑定全部 placeholder(PR_NUMBER/标题/轮次/分支/REVIEW_*_PATH 等),解锁 reject PR 的 fix→merge

之前 headless _dispatch_review_fix 只绑 FIX_OUTPUT_PATH,其余 ${} 未解析致 fix codex 读不到 reject 证据。



* 实现 issue #496 (#520)

* 修 review-fix codex 派到 main 的 cd bug:改在 PR worktree 跑,worktree 缺失 fail-closed

之前 _dispatch_review_fix cd=repo_root → fix 改 main(污染 daemon checkout)且不落 PR 分支(reject PR 永不 merge)。



* 实现 issue #508 (#523)

* 修 wakeup-plan action 排序:review_gate/publish 排到新工作 spawn 前,解 spawn-budget 饿死→reject PR 可被 fix→merge



* CLAUDE.md 加宪法工程规则:异常必抛出+记可诊断日志严禁吞掉/静默;测试必断言真实行为禁无意义测试(maintainer 指令)



* 实现 issue #503 (#521)

* 增加通用工程基本规则,明确面向对象设计要求及实现细则

* 实现 issue #514 (#524)

* 完善通用面向对象设计准则,增加核心原则与实现层细则

* 实现 issue #494 (#526)

* 实现 issue #517 (#528)

* 实现 issue #505 (#510)

* 实现 issue #505

* #510 fix r1:补 phase9-router 行为测试覆盖(应对 tests reviewer reject)



---------



* 修复 headless FIX_DONE 不提交 fix 输出 gap:wakeup-runner 在 FIX_DONE re-review 前先 commit+push fix worktree

headless 下 fix codex 产出 FIX_DONE 但 worker 从不 commit,FIX_DONE 直接路由 dispatch_reviewers,
fix 输出永远留在 worktree 未提交,reviewers 永远审旧 head,reject 不收敛,阻断所有需 fix 轮的 PR
review→merge。镜像 interactive controller:FIX_DONE 源的 dispatch_reviewers 前,若 fix worktree
dirty 则 git add+commit+safe_push,clean 则 no-op。附 2 个 behavior test(dirty 提交/clean 跳过)。



* 实现 issue #491 (#531)

* 实现 issue #490 (#529)

* 实现 issue #490

* 实现 issue #490

* PR #529 review-fix output

* 实现 issue #499 (#512)

* 实现 issue #499

* PR #512 review-fix output

* 实现 issue #474 (#532)

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* 实现 issue #474

* PR #532 review-fix output

* 实现 issue #476 (#518)

* 实现 issue #476

* PR #518 review-fix output

* 实现 issue #509 (#527)

* 实现 issue #509

* 实现 issue #509

* spawn-claim recycle 改用 artifact-aware terminal marker:companion log 被 24h retention 删除后,已完成任务的 claim 仍可回收(读 runs/ artifact),不再永久阻断重派;running 任务无终止 marker 仍不回收(防 double-spawn)

* 实现 issue #421:发行前 clean-room 集成测试制度 (#534)

* 实现 issue #421

* rebase #421 onto fresh integration:解决 test_cli_command_router 冲突 + 校验

* 实现 issue #493:测试纪律修宪(behavior-first) (#535)

* 实现 issue #493

* rebase #493 onto fresh integration:解决冲突 + 校验

* PR #535 review-fix r1:addressed tests+quality reject(behavior-first test 调整)

* 实现 issue #506 (#536)

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* 实现 issue #506

* PR #536 review-fix output

* churn 根治:wakeup-plan 给 consensus-impl spawn-intent 套 open_closing_pr/terminal/in-flight 抑制(对齐 dispatch_consensus_implementation),已有 PR 的 issue 不再被重派 implement

* 实现 issue #507 (#525)

* 实现 issue #507

* 实现 issue #507

* PR #525 review-fix output

* 实现 issue #516 (#530)

* 实现 issue #516

* 实现 issue #516

* #530 fix r1:补 ManagedWorkSnapshot fetch-failure stale-cache fallback 行为测试(应对 tests reviewer reject)

* PR #530 review-fix output

* PR #530 review-fix r2:typed ManagedWorkItem projection(addresses architect 类型边界 reject + tests + contract-tests)

* PR #530 review-fix r3:anchor ManagedWorkSnapshot read surface in authorization mirror + cross-artifact source-regression(addresses architect governance reject)

* PR #530 review-fix r4:add canonical+legacy managed-label discovery regression test(addresses tests reject)

* 修复 worker marker reader 误判相同重复 marker 为冲突

codex 常把终止 marker 回显 2-3 次(含 diff + 前缀行),导致
read_worker_terminal_marker 返回 duplicate_or_conflicting,review 真值表
永不收敛、所有 headless review→merge 卡死。改为:相同重复 marker 折叠为
有效,仅当存在 2+ 个不同 marker 值才判 duplicate_or_conflicting。
覆盖 _last_final_marker / _sentinel_adjacent_marker /
_marker_from_companion_artifact,保留 malformed 与 foreign-prefix 检测。



* Reserve implementation PR for issue #537 (#540)

⟦AI:AUTO-LOOP⟧

* 实现 issue #511 (#522)

* 实现 issue #511

* PR #522 review-fix output

* PR #522 review-fix output

* 移除误入 PR 的 .refactor-loop 运行 artifact(architect r8 reject)

resolve-pr522-merge.md 是一次性合并解决 summary,属生成物,不应进 durable diff
(CLAUDE.md「生成物不当事实源」)。解决说明保留在 commit message / PR body。



---------



* 修复早期 PR reservation 崩溃(#511 回归,阻断所有 implement 派发)

_reserve_implementation_pr 用 worker 富正文路径开 reservation PR,但该文件在
reservation 时尚不存在 → FileNotFoundError(未被 except RuntimeError 捕获)→
wakeup-runner tick 崩溃 → 任何 consensus issue 无法 implement → loop P0 wedge。
修复:reservation 前若 body 缺失则写占位正文(## issue #N 实现 + Closes + sentinel,
publish 会拒占位逼 worker 产真正文);reservation 幂等(已有 open PR 直接返回;
已有 remote head 则 reset 到 integration + force-with-lease push);捕获 OSError。



* Reserve implementation PR for issue #543 (#544)

⟦AI:AUTO-LOOP⟧

* Reserve implementation PR for issue #541 (#546)

⟦AI:AUTO-LOOP⟧

* revert early-PR reservation(#507):不再开空占位 PR,publish 出真内容才开 PR

dispatch_consensus_implementation 不再 reserve/开 PR;publish_implementation_output
恢复 pre-#507 行为——implement 出非空 diff 才 commit+push+open_pr_with_label(用 worker
真 title/body,验证非占位);空 diff 不开 PR、不 merge、不关 issue。删除占位机制
(_reserve_implementation_pr / _placeholder_*),改 wakeup_plan/runner 的 early_pr_missing 投影。
根因:空占位 PR 被 reviewer 在 implement publish 前空合,假性关闭 #537/#541/#543。
全量套件 1496 passed。



* 实现 issue #542:删除 redispatch payload 冗余 head_sha (#547)

移除 review redispatch 的重复 head_sha payload

* hotfix: stale consensus-implement intent 指向已删 worktree 不再 suppress fresh re-dispatch

consensus_implementation_suppressed_reason 的 pending_implement_intent 分支增加 worktree 存在性
守卫(接入既有 _canonical_consensus_worktree_exists):仅当 stale pending intent 的 canonical
worktree 仍存在时才 suppress。revert early-PR reservation(#507)后,#537/#541/#543 的 pending
implement intent 指向已删除 worktree,旧逻辑 suppress fresh re-dispatch,而 wakeup-runner 不断把
stale intent spawn 进死 cd 致 os error 2 / EXIT=1 死循环,阻断 consensus→implement 自主链路。
现 worktree 缺失即放行 fresh dispatch 重建 worktree。

补 test_wakeup_plan(worktree 缺失不 suppress / worktree 存在仍 suppress)+ 更新
test_controller_actions 锁旧行为的 subTest(pending case 建 canonical worktree 以保留
reject-before-fresh_safe_worktree 意图)。全套件 1557 passed。



* hotfix: spawn-claim lock 持有者 pid 已死即可回收(自愈,防 cleared-log 永久 HELD)

_existing_claim_is_recyclable 增加 pid-liveness 回退:当 lock 记录的持有者 pid 已死(os.kill
pid 0 抛 ProcessLookupError)时即可回收,保留既有 terminal-marker 回收与 live-spawn 保护
(pid 存活+无 marker 仍不回收)+ metadata-mismatch fail-closed。根因:implement 失败(EXIT=1)
留 stale lock,dispatch_consensus_implementation 重派时清掉 log → #490 spawn-claim 只在 log 有
EXIT= 时回收 → cleared log 无 marker → 死进程 lock 无法回收 → SPAWN_CLAIM_HELD 永久死锁,
阻断 consensus→implement 重派(#537/#541/#543)。补 7 个 behavior test。全套件 1560 passed。



* hotfix: publish_implementation_output 接受 worker 已 commit 的实现 diff

_require_publish_implementation_diff 之前只看 git diff HEAD --quiet(未提交改动),
worker 一旦自己 commit(在自己分支上,隔离无害)工作区就 clean → 误判 no_diff → 不开 PR。
现改为:有未提交改动 OR HEAD 相对 integration base 有 committed delta(merge-base..HEAD 非空)
即视为有 diff 可发;_commit_publish_implementation_diff 在工作区已 clean(worker 已 commit)时
跳过提交返回成功,不再误报 publish_commit_failed。修 #541 类 worker-commit→no_diff→无 PR+
daemon 重复 dispatch。补 behavior test。codex 全套件 DISCOVER_STATUS:0 通过。



* 实现 issue #437: .refactor-loop 历史生成物与陈旧 worktree 的有界清理机制 (#548)

* #437: 新增 canonical RuntimeRetention owner,log-retention 降为一版 alias;清理覆盖 generated files+pending-events compaction+stale worktree;CLAUDE.md 加 #437 narrow carveout

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* PR #548 review-fix output

* hotfix: CONFLICTING managed review PR 的 stale-base 冲突自主 resolve

接线既有但孤儿的 prompts/rebase-resolve.md 进 headless 路径:managed review PR
mergeable=CONFLICTING(base 落后)时,controller 在 PR worktree 起 git merge
--no-commit --no-ff origin/<integration>——干净则直接 commit+push,有冲突则派
rebase-resolve codex(隔离 worktree 内解+stage,禁 commit/push),收到
REBASE_RESOLVE_DONE 后 controller commit + safe_push 仅推 PR head。结果再过 CI+
review-gate 把关。新增 dispatch_pr_rebase_resolve / commit_push_resolved_pr_rebase
(controller_actions)+ wakeup_plan 投影 + wakeup_runner 应用。

安全:只动 refactor/iter<N>-* PR 分支,显式 guard 拒碰 integration/review_base,
diff-filter=U 验未解冲突才 commit,任何 abort 路径 git merge --abort 留干净 worktree,
幂等(已含 base / 解析在飞则 NOOP)。修 stale-base churn 致 loop 永久停滞(一个 PR
合了其它全 CONFLICTING 无人解)的根因。codex 全套件 1589 passed。



* hotfix: rebase_resolve_actions 投影前 enrich live mergeability(修生产 gap)

自主-resolve 投影读 item.mergeable 前未 enrich,但生产 GhItem 来自 snapshot
mergeable 为空 → 永远 skip → CONFLICTING PR 不投影 dispatch_pr_rebase_resolve →
loop 仍停滞。复用同文件 _with_live_mergeability(review_evidence_redispatch_actions
已用同模式)。补 mergeable-为空-需-live-fetch 的回归测试(原测试 mock 了 mergeable
未覆盖此生产路径)。



* hotfix: dispatch_pr_rebase_resolve kind 进 EXECUTABLE_ACTION_KINDS(end-to-end 可执行)

_close_projection_action 的 else 分支默认 status_only=True;rebase action 的 kind
stale-base-conflicting-pr 不在 EXECUTABLE_ACTION_KINDS → 永远 status_only,runner 不
apply,CONFLICTING PR 永不自主 resolve。加该 kind(+ commit_push completion kind 如需)
进集合;controller_action 已在 RUNNER_NAMED_HELPER_ACTIONS 故随即保持 executable。补
端到端 wakeup-plan pipeline 测试(原测试只测 rebase_resolve_actions 单函数,漏了 closed-
action-projection 的 status_only 关卡)。codex 全套件 1593 passed。



* hotfix: rebase-resolve commit/dispatch 投影 gate 在实际 worktree merge 态(止 stale-marker 噪音)

commit_push_resolved_pr_rebase 之前只凭持久 REBASE_RESOLVE_DONE marker 投影,worktree
已 commit+push(#549)或 abort(#550/#551)后 marker 仍在 → 每 tick fail-closed 噪音 +
反复 0-codex(zero_streak 触警)+ stale marker 挡 #550/#551 fresh resolve。现 gate:仅当
worktree 真有 merge-in-progress(MERGE_HEAD)且无 unmerged 才投 executable commit_push;
否则不投。并让 worktree clean + 仍 CONFLICTING 的 PR 重新拿 executable dispatch_pr_rebase_resolve
(stale DONE marker 不再永久压制)。补端到端测试。codex 全套件通过。



* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec  (#549)

* 实现 issue #502: 删除遗留 label 兼容层:purge emoji/legacy alias 全套(cleanup_aliases / per-spec

* 修复 PR #549 review r3:#502 label-purge 适配当前 label 代码(contract-tests + architect/tests reject)

fix codex round-3 applied-4:对齐 #502 遗留 label 兼容层 purge 与近期新增 label 代码,
修 contract-tests 失败 + architect/tests reject。改 labels.py + SKILL.md + test_wakeup_plan.py。



---------



* 修复 headless review_gate ci_failed 死锁:reject→FIX 移到 ci/mergeability 检查前

_review_gate_decision 之前 ci_error/mergeability 检查在 reject>0→FIX 之前 → CI 红的 PR
即使 reviewer reject 也返回 WAIT_OR_REDISPATCH:ci_failed 干等,而 CI 不修不会绿 → 死锁
(#548/#549 都中,需手动派 fix 破解)。把 reject>0→FIX 移到 ci/mergeability 检查前
(仍在 reviewer-validity/head 检查之后)→ reject 时即使 CI 红也自主派 fix(fix 同解 reject+CI)。
MERGE/MERGE_WITH_COMMENTS 判定完全不变(仍需 ci-green + mergeable + reject=0 + approve>=1),
无误合并风险。补 test_wakeup_runner 端到端测试(reject+ci-red→FIX;reject=0+ci-red 仍 WAIT;
happy path MERGE 不变;stale-head+reject 仍 WAIT)。full suite 1600 passed。



* 修正 review_gate 顺序:mergeability 检查移到 reject→FIX 之前(CONFLICTING 不并发 review/fix)

上一修复(a125d19)把 reject→FIX 移到 ci+mergeability 前,破了 ci_failed 死锁但也让
CONFLICTING+reject 的 PR 路由到 FIX → 与独立的 dispatch_pr_rebase_resolve 并发跑同一
worktree(#550 出现 98-file mid-merge + reviewer 并发)。把 mergeability_error 检查移到
reject→FIX 之前:CONFLICTING→WAIT(先 rebase-resolve,不并发 review/fix);MERGEABLE+
CI红+reject→FIX(死锁修复保留);ci_error 仍在 reject→FIX 后(纯 CI 红无 reject 才 WAIT)。
MERGE 判定不变。test_wakeup_runner 90 OK(+conflicting 用例)。



* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es (#550)

* 实现 issue #498

* 实现 issue #498: headless daemon fail-closed 点的 codex 兜底裁决/生成机制(narrow allowlist,非通用 es

* PR #550 review-fix output

* 新增 patrol-inspector 巡检 issue intake (#551)

* 实现 issue #541

* PR #551 review-fix output

* PR #551 review-fix output

* 修复 PR #551 contract-tests:对齐 patrol 第8 daemon + safe_push/sync_dev 测试 host.env

#551 patrol 新增 patrol_inspector_daemon(第8 daemon)→ test_anti_stop_restart 期望 7→8;
test_controller_lib_safe_push / test_sync_dev 补 CONSENSUS_RND_HOST_ENV host.env 设置
(代码按 host-config contract 需 host.env locator,rebase-resolve 丢了 base 新测试版本)。
断言未削弱(daemon 数断言强化为8)。full discovery 1634 OK + sshx 13 OK。



* 修复 PR #551 contract-tests(clean-env):e2e fixture 设 META_ESCALATION_STUCK_HOURS 隔离 de-dup 测试

test_batch_and_per_task_lock_do_not_duplicate_spawn 在 clean env(CI)下失败:#506 meta-
escalation 因 fixture mock 态被判 stuck 而 fire,产出 repository-stalled RunnerResult 污染
de-dup 断言(expected [] got [RunnerResult])。fixture host.env+env 设 META_ESCALATION_STUCK_
HOURS=999999 禁该测试的 meta-escalation,聚焦 de-dup 行为。断言未削弱。clean discovery 全过。



---------



* 修复 publish-gap:implement readiness 用 git status --porcelain 判 staged diff

原 classify_implement_attempt / wakeup_runner publish 前用 git diff --quiet 只检测 unstaged
改动;worker 正确 git add -A 后 staged diff 被误判 empty_scoped_diff,导致完成的 implement
(如 #553 干净 EXIT=0 + 885 行真实 staged diff + 有效 title/body artifacts)永远出不了 PR,
wakeup_runner 对 children 反复空转 re-dispatch。改为先 git status --porcelain 判 staged/
unstaged/untracked 任一即 publish-ready,只有真干净才 fallback git diff。publish-time 建 PR
路径不变(不重蹈 #507 early-PR 空 commit/placeholder 死锁)。



* 修复 patrol_inspector daemon 启动崩溃:DaemonHeartbeatLease 用构造函数非 from_env

#551 patrol.py daemon 分支调 DaemonHeartbeatLease.from_env()(不存在的方法)→
AttributeError 启动即崩,daemon 从未成功跑起来。改为 DaemonHeartbeatLease(
"patrol_inspector_daemon", ctx.repo_root),与 closed_label_reconciler/wakeup_runner
一致,心跳文件名匹配 restart 助手期待的 patrol_inspector_daemon.ts。



* 修复 publish-gap 残留层:duplicate-marker log 读 companion artifact + 取代 superseded spawn intent

层2 残留:implement worker 把 IMPLEMENT_DONE:issue-N:ok 在 log 里 echo 多次→
worker_markers 返回 duplicate_or_conflicting_log_marker fail-closed→classifier 当
markerless 且不查 companion artifact→无 completed-marker action→无 publish→stale
harness-spawn-intent:dispatch-consensus-implementation:N 残留致 pending_implement_intent。

修:(1) classify_implement_attempt / completed_marker_actions 遇 duplicate marker 时
narrow 读 companion .refactor-loop/runs/implement-*.md(仅 implement log,仅末 30 行恰好
1 个 IMPLEMENT_DONE:ok 才接受);(2) suppress_publish_superseded_implementation_spawn_intents:
仅当某 issue 已有 executable publish_implementation_output 才把对应 dispatch-consensus-
implementation spawn intent 抑制为 status_only(implementation_ready_to_publish)。
不重蹈 #507 死锁:只在 publish 已 ready 后抑制 spawn(不漏派)、publish 仍全验证(不提前/
重复)、wakeup-runner/publish 授权口径不变。live 验证 #553 现投影 executable publish。



* 实现 issue #555 (#557)

* 修复 publish-gap 第3层:wakeup_runner clean_exit revalidation 对 duplicate-marker log 复用 artifact-fallback

pubgap2 修了 plan 侧 duplicate-marker artifact-fallback,但 wakeup_runner 的
_source_log_has_clean_marker(clean_exit_source_marker 预条件 revalidation)仍用严格
reader,对 #553 duplicate IMPLEMENT_DONE echo 返回 clean_exit_marker_missing→阻 publish。
改为严格 reader 优先,仅当 duplicate_or_conflicting_log_marker + is_implement_log +
_implement_run_artifact_done_marker 精确匹配 projected marker 才 fallback。复用 plan 侧
同一 helper,不弱化安全门(reviewer/release/rebase/非 implement/其它 fail reason 保持严格)。



* 实现 issue #553

* PR #561 review-fix output

* PR #561 remote-ci-fix output

* PR #561 review-fix output

* 收窄 restart daemon 权威到 owner-local 命令面 (#558)

* #471 hotfix: wakeup_plan completed-marker 投影按 open-managed 集过滤,closed/merged target 不投影(止血 graphql:消除 wakeup_runner 对已终结 target 的逐条重校验)

* #410: SKILL/prompt 注释改引 durable contract anchor,不引用一次性 .refactor-loop/runs/*;新增 test_generated_artifacts_not_authority 窄 source-regression (#472)

* #471 hotfix2: wakeup-plan 同一 target 只投影最新有效 marker,旧轮次不再投影 dispatchable action(止 graphql backoff 最后一刀)

* skill: 强化 no-gap 规则 — 0 codex + active work 无观察模式豁免,必须当 turn 立即介入派 codex(+source-regression)

* #470: direct-post prompt 渲染时 fixed-token 内联 _github-post-rules,host worktree cwd 可达(避免裸相对路径) (#479)

* #478 hotfix: daemon spawn 改 launch-and-forget 独立 supervisor(start_new_session 不 wait),daemon reload 不丢 in-flight worker;daemon 每 tick 清晰状态行

* #471: wakeup-plan latest-open-fresh 投影 — completed-marker open-target/latest + release-rollup 仅 latest-per-sha 且 ahead>0 本地 ref 验证(止 stale 投影/graphql) (#482)

* #481: consensus->implement readiness-dedup gate(止 daemon 重派 closed/has-PR/in-flight) (#486)

* #481: consensus->implement readiness-dedup gate, closed/closing-PR/remote-branch/in-flight target 不投影 dispatchable, 止重复/race

* #481 fix r1: dedup gate 复用 concurrency monitor owner surface 测量 in-flight,不重实现 daemon 算法(addr architect)

* #481 fix r2: 补 controller helper guard behavior test(addr tests)

* #485: consensus->implement 按 scope_paths 冲突分组串行(同组一个 executable,其余 status_only),复用 batching-heuristics,防并行冲突 PR (#489)

* #475: wakeup-runner WakeupApplyBudget — spawn-worker action 按 hard_gate.dispatch_required 批量到 floor deficit(lifecycle action 仍 1/tick),修 1/tick 线性恢复 (#492)

* hotfix(#475 ext): batch budget 纳入 dispatch_design_consensus —— solver triplet 一 tick 派齐(非 lifecycle,worker 派发),修 design-consensus 仍 1/tick 低并发

* hotfix: headless spawn-intent launch — skipped duplicate 不再 break 整批 spawn,stale applied ledger(log 缺失)可重试,helper_exit:3 加来源诊断事件;修 248 intent 堆积/0 并发

* hotfix r2: blocked lifecycle action 不再 dead-stop 整 tick — 跳过/抑制 stale blocked(close-drop target OPEN / publish 无 verified head)继续 launch 后续 spawn-batch,使 headless 并发拉到 floor

* hotfix r3: 根治 headless 0 并发 — detached spawn-codex launch 显式传 env_for_subprocess(修 #478 decouple 丢 env 致 EXIT=127);失败 log(非0 EXIT)可重试 launch,EXIT=0/未完成仍抑制重复;tick 状态汇总后续 launch 不被首个 blocked 掩盖

* hotfix r4: run_once 通用 blocked-not-dead-stop — 任何 blocked/skipped non-spawn action 不再 dead-stop 整 tick,继续 launch 后续 spawn-batch;wakeup-plan 抑制 precondition 注定失败的 stale action;根治 headless 并发=0

* hotfix r5: wakeup-plan 投影侧 suppress stale close_managed_drop(target 实际 OPEN 的 drop-close 注定失败)为 status_only,不再占 tick 挡住后续 design-consensus spawn launch

* hotfix r6: wakeup-runner run_once 不再把 no-intents 的 dispatch_design_consensus(helper_exit:3)误判为 codex launch failure dead-stop 整 tick

根因:dispatch_design_consensus 是 spawn-batch action;当 solver triplet 不完整(如 #496 minimal/structural EXIT=0 但未 emit SOLVER_DONE marker)时 helper 返回 exit 3(NO_INTENTS),_spawn_launch_failure 命中 "helper_exit:" 前缀判 True → run_once break,整 tick dead-stop,后续 reviewers/其他 design-consensus/implement 全部不派 → headless 并发=0。

修法:run_once 中 blocked 的 spawn-batch action 若 controller_action != spawn_codex_harness_background(即 dispatch_design_consensus),按 routing no-op skip-and-continue,继续 launch 后续 spawn-batch;仅真正 spawn_codex_harness_background launch failure 才走既有 retry/break。延续 r4 blocked-not-dead-stop 不变量到 design-consensus spawn-batch action。

behavior test: test_wakeup_runner_design_consensus_no_intents_does_not_dead_stop_later_spawn_batch(无修复时 later spawn 不 launch 而 FAIL)。



* hotfix r7: review head_sha binding — 打通 headless review→merge 自驱

根因:reviewer artifact frontmatter 不带 head_sha,_review_evidence_from_artifact 取不到所审 head SHA → 所有 reviewing PR(#480/#473/#402)恒判 WAIT_OR_REDISPATCH:invalid_reviewer_evidence:missing_reviewed_head_sha,且 wakeup-plan 不自动重派 reviewer → review→merge headless 永久卡死(挡住发版)。

修法(codex hotfix worker 实现,controller 验证后提交):
- controller_actions 派 reviewer 时取 headRefOid,缺则 fail-closed,注入权威 HEAD_SHA 进 rendered prompt。
- reviewer-{architect,tests,quality}.md frontmatter 写 head_sha: ${HEAD_SHA}。
- wakeup_runner._review_head_sha_for:artifact 缺 head_sha 时从 controller-rendered prompt/log 回收(不依赖 worker 自报,避免 markerless 覆辙);live-head 陈旧判定与 merge 真值表语义不变。
- wakeup_plan 为 missing/stale reviewer head 的 OPEN reviewing PR 投射可执行 dispatch_reviewers 自愈动作。

验证:controller 独立重跑 test_wakeup_runner+review_gate+wakeup_plan+controller_actions 293 通过、marker/prompt 合同 30 通过;review-gate 安全语义(stale head 仍不 merge)由 13 项 review-gate 测试锁住。



* hotfix r8: 让 review-evidence-redispatch 自愈动作可执行 — 打通 headless review→merge 闭环

承接 r7:r7 让 reviewer 证据绑定 head_sha,但 wakeup_plan 投射的 review-evidence-redispatch 自愈动作被 closed-action-projection finalizer 强制 status_only(其 kind 不在 EXECUTABLE_ACTION_KINDS),runner 永不应用 → #480/#473/#402 缺 head 的 review 证据无法自动重派 → review_gate 恒 WAIT_OR_REDISPATCH → 并发耗干到 0。

修法(codex hotfix worker 实现,controller 验证后提交):
- wakeup_plan EXECUTABLE_ACTION_KINDS 加 review-evidence-redispatch,finalizer 保留 runner authority 不再强制 status_only。
- controller_actions.dispatch_reviewers 读 stale_review_roles 只重派陈旧角色,且 _pending_review_spawn_exists 跳过已有在飞 dispatch-reviewers:<pr>:<role>:r1 intent(幂等不双派);仍走 r7 的 HEAD_SHA 注入,使重派 reviewer 的新证据 head-bound。
- merge-gate 真值表不变,仅让既有自愈动作可执行 + 定向到陈旧角色。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 295 通过。



* hotfix r9: reviewer 重派 bump 到下一轮 + 绝对 cd + latest-evidence-per-role — 真正打通 headless review→merge

根因(同一类:按"产物存在"而非"成功+区分维度"抑制):reviewer 重派硬编码回 r1,撞上旧 head 早先成功(EXIT=0)的 r1 log → _harness_spawn_intent_log_suppresses_retry 判"做过了"抑制 → 当前 head 该重跑的 review 永不跑 → review_gate 恒 WAIT_OR_REDISPATCH → 并发 0。且 intent cd 是相对 "." → headless 启动层不投射。

最小修法(按 maintainer directive:文件名即唯一 id,不加 wrapper --id,留在现有 r<R> 命名约定内不改公开命名):
- controller_actions.dispatch_reviewers:_next_review_round 取该 PR/role 现有最大轮 +1,渲染 r<N+1> 的 prompt/log/output/intent;pending-spawn 幂等 guard 按真实轮号;_append_harness_spawn_intent 的 cd 改 str(cd.resolve()) 绝对路径,使 headless 投射+启动成立。
- wakeup_plan.latest_reviewer_heads / wakeup_runner._latest_review_evidence_by_role:改为"每 role 取各自最新轮证据"(而非全局最新单轮),使只重派陈旧 role 时不丢其它 role 已 head-bound 的有效证据;merge 仍要求每 role 证据绑定 live head,安全语义不变。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions 299 通过。



* hotfix r10: review_gate action 带上 reviewed head_sha + e2e 锁死 headless review→decision 全路

根因(review path head_sha 串接的第 5 处):wakeup_plan 投影 REVIEW_DONE 的 review_gate action 时只读 log 的 head(log 无 head)→ action.head_sha 空 → wakeup_runner._review_gate 卡 WAIT_OR_REDISPATCH:missing_action_reviewed_head_sha,证据虽已 head-bound 但 gate 连比都没法比。

修法(最小、按文件名即 id 思路):
- wakeup_plan.completed_marker_actions:REVIEW_DONE action 的 head_sha 改由 _review_done_action_head_sha 从权威证据面解析(latest_reviewer_heads 含 r7 prompt 注入的 head;或全 role head-bound 时取 live PR head;否则回落 log)。只从真实来源填充,不绕过 gate 的 head 比对,merge 安全语义不变。
- 新增 test_review_gate_e2e.py:从真实 wakeup_plan 投影 → WakeupRunner apply,断言 FIX(有 reject)与 MERGE(全 approve+CI 绿)两条具体决策落地——端到端锁死整条 review→decision,杜绝再冒隐藏层。
- test_wakeup_plan.py:加 prompt-bound reviewed head 的 planner 回归。

验证:controller 独立重跑 test_wakeup_plan+wakeup_runner+review_gate+controller_actions+review_gate_e2e 302 通过。



* hotfix r11: PrChecksProjection 对瞬时 gh-api 失败加 bounded retry — ready PR headless 走到 review_gate 决策

根因:review_gate 的 CI 读 PrChecksProjection.check_pr 对 gh api pulls/<n> 与 commits/<sha>/check-runs 的单次非零返回立即 fail-closed(ci_unavailable:pull_api_failure),无重试;rate limit 健康,实为瞬时 blip → 让 #473/#402(MERGEABLE+CI 绿)每 tick 被瞬时失败挡住、never reach MERGE/FIX。

修法(最小,只动 PrChecksProjection;不碰 #322 ReleaseRequiredChecksProjection):
- _run_api_read:对两处 api read 最多 3 次确定性重试(无 sleep),成功即停,持续失败仍 fail-closed(安全)。happy path 无行为变化。
- starvation 结论(worker 核实):review_gate 本就被 apply,blocked ci_unavailable 行可重评估(非 terminal duplicate-suppressed),无需改 run_once。
- e2e:test_review_gate_e2e 加「首次 pulls 读瞬时失败仍 merge」用例;test_pr_checks 加 retry 覆盖。

验证:controller 独立重跑 test_pr_checks+wakeup_runner+review_gate+review_gate_e2e+wakeup_plan+co…

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

crnd:human:auto auto-advancing, no human needed crnd:lifecycle:managed loop-managed item crnd:phase:merged merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant