Files
Gitea-Tools/docs/architecture/mcp-stable-control-runtime-policy-adr.md
T
sysadmin a0fffae576 docs: ADR for stable MCP control runtime vs dev runtime
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
2026-07-09 20:16:50 -04:00

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)

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):

  1. Normal PR / review / merge / issue-mutation work must stop.
  2. Do not improvise by switching to a dev worktree MCP for production mutations.
  3. 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:

  1. Session preflight that refuses mutations if workspace root equals a branches/ feature worktree configured as “dev only.”
  2. Explicit runtime_kind=stable|dev in MCP config and gitea_whoami profile metadata.
  3. Promotion checklist script that emits the durable promotion marker fields.
  4. Operator Guide wiki cross-link to this ADR.

6. Acceptance for this ADR

  1. Document merged under docs/architecture/.
  2. Issue #615 references this path.
  3. LLM/operator runbooks treat kill/restart/relaunch-from-worktree as violations.
  4. 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