fix: clarify capability preflight lifetime across safe reads (Closes #470)

Add preflight_contract helpers with explicit re-resolve error messages,
document the read-only tool set and consumption rules, and extend tests
for close_pr sequencing and task replacement.

Validation: ./venv/bin/python -m pytest tests/test_preflight_read_survival.py tests/test_mcp_server.py::TestPreflightVerification -q

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
2026-07-08 02:28:07 -04:00
co-authored by Claude Opus 4.8
parent 2d4ab4e54e
commit a8bcbdbcf2
4 changed files with 147 additions and 6 deletions
+19
View File
@@ -459,6 +459,25 @@ Root-level matches are listed in `.gitignore` so they never get committed.
`gitea_get_runtime_context` and `gitea_lock_issue` surface **warnings** (not
hard blocks) when these artifacts are still present.
## Capability preflight lifetime (#470)
After `gitea_resolve_task_capability(task=…)` proves the mutation is allowed,
interleaved **read-only** calls preserve that proof until a gated mutation
consumes it:
- Safe reads: `gitea_whoami`, `gitea_view_pr`, `gitea_view_issue`, `gitea_list_*`,
`gitea_get_runtime_context`, `gitea_check_pr_eligibility`, and related
read-only inventory/eligibility tools (see `preflight_contract.py`).
- Each mutation consumes the proof once; call `gitea_resolve_task_capability`
again immediately before the next mutation on the same task.
- Resolving capability for a **different** task replaces the prior task binding.
- Workspace edits before resolve, profile switches, or a dirty whoami baseline
invalidate proof (fail closed).
If a mutation fails with “capability has not been resolved” or “task mismatch”,
re-run `gitea_resolve_task_capability(task="<mutation>")` immediately before
retrying — do not guess or skip the resolve step.
Implementation work and review work must use separate branch folders. For
example, an implementation branch might live under
`branches/fix-issue-123-example`, while a review branch for the resulting PR