Policy: real Gitea mutations use stable control runtime only; normal sessions must not kill/restart/relaunch from worktrees or edit the stable checkout. Promotion is operator-only with proof and rollback. Refs: #615
7.4 KiB
ADR: Stable control runtime vs dev runtime (Gitea MCP)
- Status: Accepted (policy effective immediately for LLM sessions; tooling may lag)
- Date: 2026-07-09
- Tracking issue: #615
- Related:
- #543 /
docs/mcp-namespace-health.md— client-namespace health docs/mcp-namespace-eof-recovery.md— reconnect-only EOF recovery (no PID kill)- #558 /
docs/mcp-daemon-import-guard.md— sanctioned daemon - #557 /
docs/bootstrap-review-path.md— controller bootstrap for self-hosted fixes - Allocator / control-plane ADR:
docs/architecture/mcp-allocator-control-plane-observability-adr.md(#613 / PR #614)
- #543 /
1. Context
The Gitea MCP server is the control plane for real issue/PR mutations (create, comment, lock, review, merge, etc.). When author/reviewer/merger/reconciler sessions kill or restart that process, relaunch it from a feature worktree, or edit the checkout that process loads, operators observe:
- Mid-session identity/preflight resets
- Stale-runtime vs master parity failures
- IDE transport EOF / “tool not found” while code on disk has changed
- Accidental production mutations from experimental code
This ADR separates stable control runtime from dev/test runtime and defines promotion proof.
2. Decision
2.1 Stable control runtime
The Gitea MCP server used for real workflow mutations is the stable control runtime.
Characteristics:
- Loads a known, promoted revision of Gitea-Tools (or the packaged release layout operators designate)
- Registered in the IDE/client as the production namespaces (
gitea-tools,gitea-reviewer,gitea-merger,gitea-reconciler, etc.) - Holds production profile credentials via sanctioned keychain/env paths only
2.2 Dev / test runtime
MCP server code development and testing:
- Happens in isolated
branches/worktrees (or other non-stable checkouts) - May use a separate dev/test MCP runtime/process when process-level testing is required
- Must not be used for real Gitea mutations on production issues/PRs
2.3 Forbidden actions (normal sessions)
Normal author, reviewer, merger, and reconciler sessions must not:
| Forbidden | Why |
|---|---|
| Kill the running MCP server process | Drops all concurrent sessions; loses preflight state |
| Restart the MCP server process | Same as kill; causes stale/identity churn mid-workflow |
| Relaunch MCP from a development worktree | Runs unpromoted code against production mutations |
| Edit files in the stable runtime checkout | Hot-mutates control plane under concurrent users |
| Use experimental/dev MCP for real Gitea mutations | Bypasses promotion proof and audit expectations |
EOF / transport recovery: client reconnect only (see docs/mcp-namespace-eof-recovery.md). Do not “fix” health by killing PIDs or bumping MCP config mtimes as a normal session procedure.
2.4 Promotion (operator / release-manager only)
Promotion of a new revision into the stable control runtime is an explicit operator/release-manager action, not an LLM self-service step.
A promotion must record (issue comment, release note, or promotion ledger):
| Field | Description |
|---|---|
| previous runtime SHA | Commit previously loaded by stable runtime |
| promoted runtime SHA | Commit after promotion |
| source branch/PR | Where the change was reviewed |
| restart/reload method | How the process was cycled (e.g. supervised restart, client reload) |
| health check proof | Client-namespace probe success (gitea_whoami / namespace health) |
| identity/profile proof | Expected profile(s) and username(s) after reload |
| workspace/root proof | Stable checkout path / root matches intended layout |
| mutation capability proof | Required permissions for the target role present; forbidden ops still forbidden |
| rollback instructions | How to restore previous SHA and re-verify health |
Suggested durable marker:
## MCP STABLE RUNTIME PROMOTION (#615)
Status: COMPLETED | ROLLED_BACK | ABORTED
Previous-SHA: <full sha>
Promoted-SHA: <full sha>
Source-PR: <number>
Source-Branch: <name>
Reload-Method: <text>
Health-Proof: client_namespace whoami OK / assess_mcp_namespace_health OK
Identity-Proof: profile=<name> user=<name>
Workspace-Proof: root=<path>
Mutation-Proof: allowed_ops include <…>; forbidden include <…>
Rollback: checkout <previous sha>; reload method <…>; re-run health/identity proofs
Operator: <username>
Timestamp: <ISO-8601>
2.5 Unhealthy stable runtime → stop work
If the stable MCP runtime is unhealthy (client-namespace probes fail, wrong identity, wrong root, missing mutation capability, persistent EOF after reconnect):
- Normal PR / review / merge / issue-mutation work must stop.
- Do not improvise by switching to a dev worktree MCP for production mutations.
- Resume only after:
- runtime is restored, or
- a controlled promotion/rollback completes with the promotion record above, or
- a controller invokes the narrow bootstrap review path (#557) when the defect is self-hosted and documented.
3. Relationship to other controls
| Doc / mechanism | Interaction |
|---|---|
| Namespace health (#543) | Proves IDE client can call tools; does not authorize restart |
| EOF recovery | Reconnect only; no process kill |
| Daemon import guard (#558) | Mutations require sanctioned daemon; not a bare shell import |
| Bootstrap path (#557) | Only controller-authorized exception when live runtime cannot review its own fix |
| Allocator / control-plane ADR | Coordination DB is separate; still depends on a healthy MCP surface for Gitea writes |
4. Consequences
Positive
- Predictable control plane for concurrent LLMs
- Clear operator-only promotion gate with rollback
- Aligns session behavior with health/EOF docs already landed
Costs
- LLM sessions must wait when runtime is sick (no DIY restart)
- Operators must maintain promotion discipline and dual-runtime config if they use a dev MCP
Non-goals
- Does not ban operator-supervised restarts during incidents
- Does not replace CI or code review for MCP changes
- Does not authorize editing stable checkout “because tests need a quick fix”
5. Implementation follow-ups (optional tooling)
These may land in later issues; the policy binds sessions now:
- Session preflight that refuses mutations if workspace root equals a
branches/feature worktree configured as “dev only.” - Explicit
runtime_kind=stable|devin MCP config andgitea_whoamiprofile metadata. - Promotion checklist script that emits the durable promotion marker fields.
- Operator Guide wiki cross-link to this ADR.
6. Acceptance for this ADR
- Document merged under
docs/architecture/. - Issue #615 references this path.
- LLM/operator runbooks treat kill/restart/relaunch-from-worktree as violations.
- Unhealthy runtime stops normal mutation work until restore/promotion/rollback/bootstrap.
7. Document history
| Date | Change |
|---|---|
| 2026-07-09 | Initial ADR: stable vs dev runtime, forbidden session actions, promotion proof fields, stop-work rule |