Context
Surfaced 2026-08-01 by @tobiu: "a harness restart refreshes NL and github workflow mcp servers. however, since KB and MC now live inside docker, restarts won't change anything. container updates do (and they might disconnect peers)."
.agents/skills/self-repair is turn-triggered substrate — it fires on "system degraded", "MCP infrastructure failure", "healthcheck". Its remediation model predates the Docker cut (#16167), so an agent following it during a real outage is directed at a surface that cannot fix the problem, and in one case is directed at an action that makes things worse.
Everything in The Problem is observed; The Fix is inference and marked as such.
Live latest-open sweep: latest 12 open issues at 2026-08-01T12:26:18Z. Duplicate sweep on self-repair, self-repair-protocol, and docker-restart-diagnostics returned no equivalent ticket, open or closed. No A2A [lane-claim] on skill substrate.
The Problem
Verified topology. ai/deploy/docker-compose.yml declares services chroma, kb-server, mc-server, orchestrator, ingress, local-model. There is no neural-link and no github-workflow service — the only occurrences of those names in any deploy compose are comments about config-leaf membership in docker-compose.dev.yml, not service definitions. So:
| MCP server |
Runs as |
Harness restart refreshes it? |
neural-link |
host process, harness-spawned |
yes |
github-workflow |
host process, harness-spawned |
yes |
knowledge-base |
container (kb-server) |
no |
memory-core |
container (mc-server) |
no |
The protocol never draws this line, and four passages are wrong or harmful because of it:
1. references/self-repair-protocol.md:21 — actively misleading.
"If the memory core is offline, refer back to Phase 1 and restart npm run ai:server on port 8000."
Memory Core offline is now a container condition. npm run ai:server starts a host stack that does not touch mc-server, so the prescribed remedy cannot succeed. Worse, it can start a second stack competing for port 8000 with the container's published 127.0.0.1:8000:8000 — turning a diagnosis step into a new fault.
2. :10 — half true, and the wrong half is the actionable one.
"Knowledge Base & Memory Core share a unified ChromaDB on port 8000 (script: npm run ai:server)"
Port 8000 is still correct (docker-compose.local-agent-os.yml:28 publishes 127.0.0.1:8000:8000). The script is the stale part, and it is the part an agent acts on.
3. :12 — a host remedy for a container fault.
"Search for and terminate zombie processes if ports are locked before attempting to restart the services."
Killing host processes never frees a containerised service and risks terminating unrelated host work. Under Docker the equivalent question is which container holds the port, which the protocol never asks.
4. :8 — path drift. test/playwright/unit/ai/McpServersHealth.spec.mjs now lives at test/playwright/unit/ai/mcp/client/McpServersHealth.spec.mjs.
The Architectural Reality
The protocol is missing the distinction that governs every container remedy, and it is not two-valued but three-valued. Measured on this machine today:
- Restart (
docker restart) — reduces code drift by zero. Container uptimes read 30h / 5h / 2h across the three services while all three images carried an identical build timestamp: those were restarts of one image.
- Recreate (
up -d --force-recreate) — applies compose-level change, not code. Today's sanctioned quiesce window recreated the stack: chroma correctly moved onto its mounted /data (#16252 applied), and yet /app/.neo-revision still reads c2304ea118… on both mc-server and orchestrator — 26 commits / 15 merged PRs behind dev at 247dbbc844, unchanged by the recreate.
- Rebuild (
up -d --build, or build --no-cache) — the only action that delivers merged code.
Two further facts the protocol has no place for:
/app/.neo-revision is the drift instrument. Baked by ai/deploy/Dockerfile, which states the discipline itself: "The label is an assertion, while /app/.neo-revision is measured artifact truth." Image timestamps are a proxy and undercount; I used them first and was wrong by one PR.
- Container actions disconnect peers. Recreating
mc-server drops every agent's live MCP session — during today's window the Memory Core was unreachable mid-write. A protocol that tells a degraded agent to act on containers without saying "announce first" invites one agent to sever the whole swarm's A2A spine while debugging its own symptom.
The Fix
(Prescription — inference, not observation.)
- Add a refresh matrix at the top of Phase 1: which surface each MCP server lives on, and what a harness restart does and does not reach. This is the single fact that makes the rest of the protocol correct.
- Replace the three host-remedy passages (
:10, :12, :21) with their container equivalents — inspect the container, read its logs, check /app/.neo-revision against origin/dev. Replace, not append: the wrong instruction must leave the file, or an agent under pressure will still find it.
- Name the restart / recreate / rebuild distinction and what each one actually changes.
- Add a peer-coordination precondition for any container-affecting action: announce over A2A first, because the action severs A2A.
- Fix the
McpServersHealth.spec.mjs path.
Substrate Accretion Defense. This must net-reduce or hold loaded bytes: items 2 and 5 are replacements, and item 1 is a table that lets several prose paragraphs go. If the result grows, the diff is wrong. Retirement trigger: if the harness ever spawns KB/MC as host processes again, or all four servers become containerised, the matrix collapses to one line and should.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
self-repair-protocol.md Phase 1 |
ai/deploy/docker-compose.yml service list |
remediation branches on whether the degraded server is containerised |
when the surface is unknown, inspect before acting — never restart blind |
the protocol itself |
no passage prescribes a host restart for a containerised server |
| Container-action preconditions |
today's quiesce-window plan-sync |
announce over A2A before any container-affecting action |
if A2A is already down, say so in the ticket rather than acting silently |
the protocol |
the protocol names the peer-disconnect consequence |
| Drift diagnosis |
ai/deploy/Dockerfile |
/app/.neo-revision compared to origin/dev is the staleness check |
if absent or local-build, treat drift as unknown, never as zero |
the protocol |
the protocol names the file, not image timestamps |
Decision Record impact
none. This aligns a skill with the topology #16167 already established; it decides nothing new.
Acceptance Criteria
Out of Scope
- The image-delivery gap itself — that merged code never reaches running containers is real (15 PRs outstanding as of this filing) but is a deployment-pipeline question with its own home; see Related. This ticket only teaches the protocol to diagnose drift, not to fix its cause.
- The backup-root location on this plane. Adjacent, separately observed, not a skill-substrate concern.
- Any other skill. Several likely carry the same pre-Docker assumption; a sweep is worth doing but bundling it here would make the diff unreviewable.
Avoided Traps
- Appending a Docker section and leaving the old text. The failure mode is an agent under pressure finding the wrong instruction first. Additive edits leave both instructions live and make the file longer, which is the accretion this substrate is supposed to resist.
- Assuming "containerised" means the whole Agent OS. It does not —
neural-link and github-workflow remain harness-spawned, and a rewrite that containerises all four in prose would be freshly wrong in the opposite direction.
- Treating restart and recreate as equivalent to rebuild. Verified today that both leave
/app/.neo-revision unchanged; a protocol that conflates them would report a drift fix that never happened.
- Trusting image build timestamps for drift. They undercount. The Dockerfile already says which artifact is truth.
Related
#16167 — the Docker hard cut this skill was never updated for
#16193 (Discussion) — deployment/IaC, where the "merged code never reaches containers" half belongs
#16208 / #16252 — the chroma persist-path work whose recreate produced the measurements above
#13652 — mechanical-enforcement epic; same philosophy, different layer
Origin Session ID: 713db0da-2239-44ea-ba5b-931be90d34fc
Retrieval Hint: query_raw_memories("self-repair protocol docker containerized KB MC harness restart refresh matrix"), or .agents/skills/self-repair/references/self-repair-protocol.md.
Context
Surfaced 2026-08-01 by @tobiu: "a harness restart refreshes NL and github workflow mcp servers. however, since KB and MC now live inside docker, restarts won't change anything. container updates do (and they might disconnect peers)."
.agents/skills/self-repairis turn-triggered substrate — it fires on "system degraded", "MCP infrastructure failure", "healthcheck". Its remediation model predates the Docker cut (#16167), so an agent following it during a real outage is directed at a surface that cannot fix the problem, and in one case is directed at an action that makes things worse.Everything in The Problem is observed; The Fix is inference and marked as such.
Live latest-open sweep: latest 12 open issues at 2026-08-01T12:26:18Z. Duplicate sweep on
self-repair,self-repair-protocol, and docker-restart-diagnostics returned no equivalent ticket, open or closed. No A2A[lane-claim]on skill substrate.The Problem
Verified topology.
ai/deploy/docker-compose.ymldeclares serviceschroma,kb-server,mc-server,orchestrator,ingress,local-model. There is noneural-linkand nogithub-workflowservice — the only occurrences of those names in any deploy compose are comments about config-leaf membership indocker-compose.dev.yml, not service definitions. So:neural-linkgithub-workflowknowledge-basekb-server)memory-coremc-server)The protocol never draws this line, and four passages are wrong or harmful because of it:
1.
references/self-repair-protocol.md:21— actively misleading.Memory Core offline is now a container condition.
npm run ai:serverstarts a host stack that does not touchmc-server, so the prescribed remedy cannot succeed. Worse, it can start a second stack competing for port 8000 with the container's published127.0.0.1:8000:8000— turning a diagnosis step into a new fault.2.
:10— half true, and the wrong half is the actionable one.Port 8000 is still correct (
docker-compose.local-agent-os.yml:28publishes127.0.0.1:8000:8000). The script is the stale part, and it is the part an agent acts on.3.
:12— a host remedy for a container fault.Killing host processes never frees a containerised service and risks terminating unrelated host work. Under Docker the equivalent question is which container holds the port, which the protocol never asks.
4.
:8— path drift.test/playwright/unit/ai/McpServersHealth.spec.mjsnow lives attest/playwright/unit/ai/mcp/client/McpServersHealth.spec.mjs.The Architectural Reality
The protocol is missing the distinction that governs every container remedy, and it is not two-valued but three-valued. Measured on this machine today:
docker restart) — reduces code drift by zero. Container uptimes read 30h / 5h / 2h across the three services while all three images carried an identical build timestamp: those were restarts of one image.up -d --force-recreate) — applies compose-level change, not code. Today's sanctioned quiesce window recreated the stack:chromacorrectly moved onto its mounted/data(#16252 applied), and yet/app/.neo-revisionstill readsc2304ea118…on bothmc-serverandorchestrator— 26 commits / 15 merged PRs behinddevat247dbbc844, unchanged by the recreate.up -d --build, orbuild --no-cache) — the only action that delivers merged code.Two further facts the protocol has no place for:
/app/.neo-revisionis the drift instrument. Baked byai/deploy/Dockerfile, which states the discipline itself: "The label is an assertion, while/app/.neo-revisionis measured artifact truth." Image timestamps are a proxy and undercount; I used them first and was wrong by one PR.mc-serverdrops every agent's live MCP session — during today's window the Memory Core was unreachable mid-write. A protocol that tells a degraded agent to act on containers without saying "announce first" invites one agent to sever the whole swarm's A2A spine while debugging its own symptom.The Fix
(Prescription — inference, not observation.)
:10,:12,:21) with their container equivalents — inspect the container, read its logs, check/app/.neo-revisionagainstorigin/dev. Replace, not append: the wrong instruction must leave the file, or an agent under pressure will still find it.McpServersHealth.spec.mjspath.Substrate Accretion Defense. This must net-reduce or hold loaded bytes: items 2 and 5 are replacements, and item 1 is a table that lets several prose paragraphs go. If the result grows, the diff is wrong. Retirement trigger: if the harness ever spawns KB/MC as host processes again, or all four servers become containerised, the matrix collapses to one line and should.
Contract Ledger Matrix
self-repair-protocol.mdPhase 1ai/deploy/docker-compose.ymlservice listai/deploy/Dockerfile/app/.neo-revisioncompared toorigin/devis the staleness checklocal-build, treat drift as unknown, never as zeroDecision Record impact
none. This aligns a skill with the topology #16167 already established; it decides nothing new.Acceptance Criteria
npm run ai:server(or any host restart) as the remedy for a degraded Memory Core or Knowledge Base./app/.neo-revisionis named as the drift instrument, compared againstorigin/dev.McpServersHealth.spec.mjspath resolves.Out of Scope
Avoided Traps
neural-linkandgithub-workflowremain harness-spawned, and a rewrite that containerises all four in prose would be freshly wrong in the opposite direction./app/.neo-revisionunchanged; a protocol that conflates them would report a drift fix that never happened.Related
#16167— the Docker hard cut this skill was never updated for#16193(Discussion) — deployment/IaC, where the "merged code never reaches containers" half belongs#16208/#16252— the chroma persist-path work whose recreate produced the measurements above#13652— mechanical-enforcement epic; same philosophy, different layerOrigin Session ID:
713db0da-2239-44ea-ba5b-931be90d34fcRetrieval Hint:
query_raw_memories("self-repair protocol docker containerized KB MC harness restart refresh matrix"), or.agents/skills/self-repair/references/self-repair-protocol.md.