Merged-PR source-branch cleanup is reconciler work (task_capability_map maps
cleanup_merged_pr_branch -> reconciler / gitea.branch.delete), but the
reconciler profile schema, execution-profile docs, and tests never covered
the permission, so no configured profile could run the guarded
gitea_cleanup_merged_pr_branch path.
- reconciler_profile.py: add gitea.branch.delete to
RECONCILER_RECOMMENDED_OPERATIONS (not required; not forbidden)
- docs/gitea-execution-profiles.md: document merged-branch cleanup
ownership, least-privilege constraints, and the no-alias caveat
- tests/test_reconciler_profile.py: reconciler profile with branch.delete
stays valid and classified reconciler; missing grant is reported as
missing-recommended
- tests/test_branch_cleanup_guard.py: author- and merger-shaped profiles
without gitea.branch.delete fail closed on gitea_cleanup_merged_pr_branch
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add orthogonal role:* (single-active owner) and hazard:* (additive warning)
lifecycle labels plus status:changes-requested, folding the #603 state:*
vocabulary into the canonical status:* set rather than a conflicting parallel
prefix.
- issue_workflow_labels.py: ROLE_/HAZARD_ specs + frozensets; role/hazard
transition maps and helpers (transition_role_labels, add/clear_hazard_label,
canonical_role_label, canonical_hazard_label, is_discussion,
is_implementation_candidate, requires_blocking_reason); state:* -> status:*
synonym transitions; assess_issue_labels surfaces role/hazard dims and flags
multiple active role labels
- docs/label-taxonomy.md: role, hazard, state->canonical migration, and
allocator cross-check sections
- tests: role/hazard/discussion/blocking-reason/state-synonym coverage
- manage_labels.py seeds the new labels automatically via CANONICAL_LABEL_SPECS
Labels remain advisory; control-plane leases (#601) and live PR state stay the
source of truth for mutations (#603 AC2).
Closes#603
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Add phase-1 observability bridge that turns provider observations into
normal Gitea issues and control-plane incident_links rows. Dry-run is
default; apply creates/links through sanctioned Gitea issue paths only.
Raw incidents remain non-assignable; the #600 allocator sees bridge work
only as ordinary Gitea issues. Builds on #613 substrate and #600 allocator.
Closes#612
Add gitea_allocate_next_work and allocator_service routing policy on top of
the #613 ControlPlaneDB substrate. Workers get atomic assign+lease results
(or wait/no_safe_work/terminal-path outcomes) without self-selecting work
via file locks or comment-only leases. #612 remains downstream.
Closes#600
Legacy NULL-scope dedupe only compared Gitea targets, so duplicate rows
with the same provider key and issue but different fingerprint/status/
event_count/etc. collapsed to the lowest link_id and silently dropped
observation data. Migration now compares all meaningful observation
fields and refuses to discard conflicts (#619 RC3 / #613).
Address REQUEST_CHANGES on PR #619:
- require_valid_assignment rejects terminal work states and head drift
- incident_links scope keys normalize NULL/blank to '' for UNIQUE
- remove trailing whitespace in control-plane-db-substrate.md
Add SQLite single-writer MVP control plane per the allocator ADR:
sessions, work_items (issue/pr only), atomic assign+lease, mutation
gates, terminal-lock index, and provider-neutral incident_links.
DB coordinates concurrency; Gitea remains assignable work; raw
Sentry/GlitchTip incidents are never work items. #600 and #612 build on
this substrate.
- Distinguish client_namespace vs offline_spawn probe sources; only IDE
client probes prove namespace health and feed mutation gates.
- Record assessments in session; gate gitea_submit_pr_review and
gitea_merge_pr when client-namespace health is unhealthy/non-proven.
- Mark test_mcp_conn.py offline-only; align recovery docs to client
reconnect (no PID-kill/config-touch as canonical recovery).
- Rebase onto current master so #590 ledger isolation keeps
TestMergePR.test_unknown_profile_blocks green.
Adds docs/mcp-namespace-eof-recovery.md documenting the correct recovery
path when a Gitea MCP namespace (gitea-author/reviewer/merger/tools)
returns `client is closing: EOF`.
Satisfies acceptance criterion 7 of #543: symptom, root cause (closed
client transport vs a live-but-stale process), the sanctioned
reconnect/relaunch sequence, diagnostics to capture, and how
test_mcp_conn.py reproduces the registered-vs-callable gap. Distinguishes
this transport-close failure from the ps-based stale-runtime family in
#531/#544 and reinforces the no-direct-import guard (#558).
Docs-only; no code or test behavior changed.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The namespace health check (05fdcee) classified a false-ready namespace but
only returned an advisory blocks_merge_workflow flag; nothing in the merge
gate consumed it. Wire it in so a broken live namespace hard-blocks merge.
- review_merge_state_machine.assess_workflow_blockers: add live_namespace_broken
blocker (registered-in-FastMCP but not callable-through-namespace).
- assess_state_advancement: forward **blocker_kwargs so can_approve/can_merge/
workflow_status honor the full blocker set (also fixes latent drop of
mcp_reconnect_failed/stale_capability_state through those paths).
- gitea_assess_review_merge_state_machine tool: accept live_namespace_broken and
thread it through all state-machine calls.
- Tests: prove can_merge/workflow_status/tool block on live_namespace_broken even
with every review state + pre-merge gate satisfied; bridge classify verdict.
- Docs: enforcement section wiring blocks_merge_workflow -> live_namespace_broken.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Durable review-decision locks (#559) can outlive the PR they protect.
When the last terminal mutation references a PR that is already
merged/closed, expose gitea_cleanup_stale_review_decision_lock so a
reviewer can clear the lock with identity/profile gates and a durable
audit trail — without weakening #332 for open PRs or deleting
session-state files by hand.
Also auto-clear same-profile locks after a successful merge of the
approved PR, and document allowed vs forbidden cleanup.
Closes#594
Add consolidated MVP route/read-only tests, path-filter helpers, and
scripts/test-webui plus scripts/ci-webui-check for Jenkins path-filtered
runs on PRs touching web UI surfaces.
Closes#436
Add bind-host assessment that refuses 0.0.0.0/:: without override,
warns on non-loopback binds, and documents internal-only MVP serving.
Health endpoint exposes deployment metadata; docs cover Access/VPN/WARP
and runtime env assumptions without embedding secrets in the client.
Closes#435
Add categorize-and-probe helpers for shell spawn failures, expose
gitea_diagnose_terminal, and fail closed on mutation capability resolve
when the terminal launcher is unhealthy (BLOCKED + DIAGNOSE). Document
the operator path in the workflow runbooks.