Deliver exact change-relative sources and shared governance tiers to reviewers. Preserve received verdicts while recording read coverage as diagnostic evidence. Retire scope window authority and packed deep review.
A production-touching task edits the very files it was sent to edit, which
invalidates any advisory it ran earlier. On its first `commit_reviewed` it then
hits `ADVISORY_PRE_REVIEW_REQUIRED: No fresh advisory run found for this
snapshot`, has to leave the gate, call `preflight_review` by hand, and come back
— and any further edit (fixing a finding, a test) restarts the loop.
Long-running production tasks were observed spending 170-200 rounds in this
ping-pong; a tests-only change in the same batch that never needed a version
bump kept its single advisory fresh and landed in ~45.
`_advisory_and_tests_gate` now, when the block is a PURE freshness gap ("no run
matches this snapshot" or "last run could not be parsed") and no explicit
`skip_advisory_pre_review` was passed, runs `_handle_advisory_pre_review` inline
against the current snapshot and re-checks once. It is the same advisory the
agent would run — a real `AdvisoryRunRecord`, not a bypass — so the compensating
test-preflight coupling (`advisory_gate_unavailable()` -> mandatory hermetic
pytest) is unchanged. One attempt only: a SyntaxError preflight block, open
obligations, or a critical advisory finding survive the re-check and are
returned to the agent exactly as before.
Scope:
- In: `_advisory_and_tests_gate` freshness-gap self-recovery; two new helpers
`_ADVISORY_SELF_RECOVERABLE_MARKERS` / `_advisory_freshness_gap_is_self_recoverable`;
`_handle_advisory_pre_review` added to the existing `claude_advisory_review`
import.
- Out: the `open_debts` / stale-manifest block path, the `#123` bypass
detection, and the tests-preflight coupling are untouched.
Verification:
- tests/test_advisory_inline_freshness.py (new, 2 cases): freshness gap ->
inline advisory runs once + gate proceeds; syntax-preflight block -> no
inline retry, block returned. (Kept in a new file rather than growing the
banded tests/test_commit_gate.py.)
- python -m pytest tests/test_commit_gate.py tests/test_git_review_pipeline.py
tests/test_advisory_observability.py tests/test_review_cycles_dispatch.py -q
-> green
- python -m ruff check . --select F -> clean;
python scripts/regenerate_size_ratchet.py --check -> exit 0
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>