Review 632 F4. Every prior reference to `gitea_recover_incomplete_bootstrap_lock`
and `gitea_inspect_issue_lock_contract` under `tests/` was a string literal — a
`tool=` argument, an assertion on returned prose, or a docs substring check —
and the suite reconstructed the recovery sequence by hand from
`assess_bootstrap_lock_recovery`, `build_canonical_issue_lock`,
`build_recovery_record`, and `bind_session_lock`. A hand-written sequence
validates the decision layer but cannot see a divergence between itself and
the tool body, which is exactly how F1 and F2 — both call-site defects —
survived 61 passing cases.
The new cases drive the registered functions against a real `git init`
repository, a real durable lock file, and config-backed profiles:
* `NamespaceMutationWallOnRecovery` — the gate is reached with this task and
`author_role_exclusive=True`; its return value aborts the tool rather than
being computed and discarded; the author namespace succeeds and produces a
canonical lock; a reviewer namespace is refused with `namespace_block` even
when the claimant data would otherwise match, and emits the standard BLOCKED
audit record; merger is refused; a mismatched claimant profile is refused by
the exact-owner layer with the namespace wall explicitly clear; a mismatched
head is refused; every refusal leaves the lock bytes, generation, branch,
worktree, and an unrelated lock untouched. A subtest matrix asserts the
role-kind wall admits `author` and refuses reviewer, merger, limited, and
mixed.
* `InspectionToolExecutes` — the registered read-only tool reports the contract
and the recovery preview while leaving lock bytes, mtime, HEAD, and porcelain
status unchanged, and reports an absent lock without creating one.
* `Ac7PostCompensationGuidance` — drives the real bootstrap to its AC7 refusal
with a forced partial lock and asserts the returned action against the state
the rollback actually left: complete cleanup directs to a bootstrap retry and
that retry is then executed and succeeds, leaving exactly one canonical lock
and one branch; partial cleanup with a surviving lock, and with a surviving
branch and worktree, each get their own executable action; a rollback that
never completed is distinguished from both; no recommendation names a deleted
artifact; unrelated locks are byte-identical afterwards. Two cases cover
`release_session_lock` directly — that the rollback now really removes the
lock, and that it refuses a lock owned by another session.
* `NativeEndToEndBootstrapToCreatePr` — bootstrap, inspect, heartbeat,
legitimate divergence (commit and push), pre-mutation ownership re-check, and
the unchanged #447 create-PR provenance guard, in one sequence against a real
origin. `gitea_lock_issue` is patched to fail the test if anything reaches for
it, so the bootstrap lock is proved to carry the whole cycle unrepaired.
* `DeadProvenanceConstantRemoved` — the removed constant stays removed and the
sanctioned source set stays unwidened.
`_NativeToolBase` clears `role_session_router` route state per test: the sticky
reviewer-stop marker is process-global and, now that this task is registered in
`AUTHOR_TASKS`, an earlier suite leaving it set would make the first gate refuse
before the namespace gate under test is reached.
Also documents both new tools in `docs/mcp-tool-inventory.md`, so this branch
adds no drift to `test_documented_inventory_equals_registered_tools`; the
failure reason there is now identical to the pinned base's.
Suite: 61 -> 92 cases.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>