Replace manual in-process _SESSION_LEASE seeding with an auditable
gitea_adopt_merger_pr_lease tool that posts durable adoption proof and
records sanctioned session provenance. Mutation gates now reject bare
record_session_lease calls without provenance from acquire/adopt/heartbeat.
Closes#536
Namespace-scoped workspace resolution prevents GITEA_AUTHOR_WORKTREE from
poisoning reviewer, merger, and reconciler purity checks. Each role uses
its own worktree env var with actionable binding-source errors and safe
reconnect guidance. Preserves #274/#475 author and control-checkout guards.
Introduce root_checkout_guard helper and enforce it in verify_preflight_purity
so author, reviewer, and merger mutations fail closed when the stable control
checkout is on the wrong branch, detached, dirty, or diverged from prgs/master.
Isolated branches/... worktrees and reconciler paths remain allowed.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Normal author work is unchanged: gitea_lock_issue still requires the worktree
to be base-equivalent to master/main/dev, and gitea_create_pr still targets a
normal base branch. A *stacked* PR (based on another unmerged PR's branch) is a
new explicit, proof-backed path — it never bypasses the issue lock.
- stacked_pr_support.py: pure policy. Approve a non-master base only when it is
declared AND owned by a live OPEN PR whose number matches; reject arbitrary,
mismatched, or stale (merged/closed) branches; require the PR body to document
the stack (base branch, stacked-on PR, merge ordering).
- issue_lock_worktree.py: read_worktree_git_state / _find_matching_base_ref gain
an opt-in extra_bases arg so an approved stacked base can anchor
base-equivalence in addition to master/main/dev (empty by default = unchanged).
- gitea_mcp_server.py:
- gitea_lock_issue gains stacked_base_branch + stacked_base_pr. When declared,
it verifies the open PR owns the branch, anchors base-equivalence to it, and
records approved_stacked_base = {branch, pr_number, verified_open} on the lock.
- gitea_create_pr validates a non-master base against the lock's approved
stacked base, re-checks the dependency PR is still open, and enforces the
stacked-PR body fields. Master-based path untouched.
- Docs: llm-workflow-runbooks.md and work-issue.md document when stacked PRs are
allowed and the required PR-body wording.
Tests: test_stacked_pr_support.py (18 policy cases), stacked base-equivalence in
test_issue_lock_worktree.py, approved_stacked_base persistence round-trip in
test_issue_lock_store.py. Existing lock/create_pr regressions still pass.
The #482 -> #479/#478 case motivates this: create_pr previously could not open a
stacked PR because the lock required a master-equivalent worktree.
Closes#484.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
When gitea_lock_issue adopts an existing own branch, the live tool
response now carries explicit, citable adoption-proof fields so #473-style
recovery sessions can quote the lock output directly instead of inferring
adoption from separate offline checks.
- issue_lock_adoption.py: add DECISION_LABELS + decision_label()/
safe_next_action() helpers; extend build_adoption_proof() with
adoption_decision, adopted, adopted_branch, adopted_branch_head,
matcher_summary (boundary-safe reason), competing_branch_check, and
safe_next_action for all outcomes; add build_non_adoption_lock_proof()
for adoption-free NO_MATCH metadata.
- gitea_mcp_server.py: attach adoption-free adoption_check block to normal
(non-adopt) lock responses so they cannot be misread as claiming adoption.
- docs/llm-workflow-runbooks.md: document the adoption/adoption_check
response blocks and instruct recovery reports to cite them directly.
- tests: explicit-field proof for ADOPT/BLOCK_COMPETING/NO_MATCH,
substring-collision boundary safety (issue-42 vs issue-420), non-adoption
proof, and MCP-level live-response assertions.
BLOCK_COMPETING lock attempts still fail closed (raise); no raw API
fallback, branch deletion, force-push, or manual lock seeding introduced.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add ./mcp-menu.sh for safe, read-only onboarding and workflow prompt
discovery. Includes root checkout health, role prompts, onboarding
checklist, Proxmox placeholders, and run-tests fallback. Document in
docs/mcp-menu.md with hermetic tests.
Closes#478.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Adds a canonical, discoverable full-validation entry point so sessions stop
guessing between pytest invocations.
- run-tests.sh: executable root runner; runs `venv/bin/python -m pytest "$@"`;
forwards args; fails closed with a clear setup message when the venv Python
is missing (no silent wrong-interpreter fallback); set -euo pipefail; no
network, no Gitea, no lock files.
- docs/developer-testing-guidelines.md: name ./run-tests.sh as the canonical
full/focused validation command.
- tests/test_run_tests_script.py: contract checks (exists, executable, strict
bash flags, venv pytest + arg forwarding, fail-closed guard, repo-local, and
the guide naming the runner).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Store per remote/org/repo/issue locks under GITEA_ISSUE_LOCK_DIR with
atomic writes and per-session binding. Integrate own-branch adoption for
lock recovery, update worktree-start and cleanup reconcile, and add tests
documenting the ban on manual global lock seeding.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add lock_provenance metadata on gitea_lock_issue writes and fail closed at
gitea_create_pr when provenance is missing. Final-report validation now
requires explicit External-state mutations disclosure for issue-lock
read/write/delete and blocks mixed author PR creation with reviewer approval.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Adds read-only /leases and /api/leases routes for issue claim inventory,
reviewer PR lease comments, duplicate PR/branch warnings, and local issue
lock visibility without acquire/release mutations.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Adds read-only /queue and /api/queue routes that load open PRs and issues
from the default registry project via gitea_auth, surface pagination proof,
and classify items with claimed/blocked/in-review/duplicate badges.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Expose short copy/paste operator prompts on /prompts derived from canonical
workflow files with workflow path and SHA-256 hash. Adds JSON export at
/api/prompts, copy buttons, and tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Starlette read-only MVP with shared layout, /health JSON liveness, and
route stubs for projects, prompts, runtime, audit, worktrees, and leases.
Includes scripts/run-webui, docs/webui-local-dev.md, and tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Merge prgs/master into feat/issue-304-reconciler-profile; keep both
reconciler_profile and review_merge_state_machine imports.
Closes conflict with master landing review_merge_state_machine (#389 stack).
Adds canonical pr-queue-cleanup workflow, report verifier, reviewer-only task
routing, and runbook guidance so operators can drain open PRs one canonical
review at a time with fail-closed boundaries on batching and unauthorized merges.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Introduce a dedicated reconciler role with gitea_reconcile_already_landed_pr,
which closes open PRs only after live fetch and ancestor proof against a fresh
target branch. Document the gitea-reconciler namespace and extend task routing.
Document default tool-call and wall-time budgets for deterministic MCP
work, forbid subagent commit delegation when gitea_commit_files is
available, and pin the rules in runbooks, portable skill, operator guide,
and doc-contract tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Document MCP-native gitea_commit_files as the only approved commit path when
gitea.repo.commit is allowed; ban WebFetch, Playwright, and manual base64
workarounds in runbooks and safety model. Add doc tests.
Closes#260.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add runbook section, root-level .gitignore patterns, and detection helper
for _encode_/_emit_/_inline_ throwaway scripts. Surface non-blocking
warnings from assess_preflight_status and gitea_lock_issue.
Closes#261
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add runbook guidance for deleting throwaway _encode/_emit/_inline commit
helpers after MCP commit attempts, ignore those patterns in .gitignore,
and cross-link the worktree-cleanup template.
Closes#261.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Require mutations only from branches/ worktrees after proving project
root, cwd, branch, stable main-checkout branch, and session worktree
path. Surface in portable skill, runbooks, wiki, operator guide, and
start-issue template.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Require lease verification (open PRs, branches, worktrees, leases,
merged completion) before any issue or PR work. Surface the rule in
the portable skill, Gitea runbooks, operator guide, and start-issue
template; add doc-contract tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Document that build triggers live on the gated jenkins-write-mcp server,
not the read-only jenkins-mcp surface. Add registration and safety-model
cross-links plus doc tests that fail if trigger tools reappear on the read
boundary.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Bootstrap repo-tracked wiki pages (10 required pages), the operator-
confirmed sync script, PR template publication gate, and safety tests so
Gitea-Tools can publish to the live Gitea Wiki per issue #224.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
PR closure had no first-class capability: agents could close PRs through
gitea_edit_pr(state=closed) with no close-specific capability proof, and
gitea_resolve_task_capability(close_pr) failed as unknown, leaving the
broad edit path as an untracked close fallback.
Add close_pr to the resolver TASK_MAP (gitea.pr.close, author-side) and
gate gitea_edit_pr(state=closed) on the same operation: without it the
close fails closed before any auth or API call, with reasons and a
structured permission_report; with it the close proceeds and is audited
as a distinct close_pr action carrying the required capability. Reject
invalid state values outright so case variants cannot bypass the gate.
Generalize the profile gate helper (_profile_operation_gate) and document
the PR comment / PR edit / PR close capability split.
Co-Authored-By: Claude Fable 5 <[email protected]>