I1502 — A server serving code that no longer exists stops calling itself ready
Make a running server's own root and health documents carry the identity of the code it is serving, so that a stale server is detectable by the client reading it rather than only by an outside reader holding a newer executable.
DONE wave 0 · p0 · implementation profile · parallel safe
Part of development-runtime — The runtime has a development surface.
Objective
Make a running server's own root and health documents carry the identity of the code it is serving, so that a stale server is detectable by the client reading it rather than only by an outside reader holding a newer executable.
Why
F1 of the audit's failure table, and the audit names it the single most dangerous class it found, because every measurement anyone takes through such a server is quietly wrong — including measurements of what a development surface lacks. It was measured from both sides in one sitting: `serve status` in a fresh executable reported the primary checkout's server as outdated, with the reason that the executable it was started from has been replaced since, while the same server asked directly at /api/v1/server returned HTTP 200 and standing `ready`, with peers attached to it throughout. The asymmetry is structural: the lease reader in a fresh executable can tell, and the running server's own root document carries no identity to check against.
Current state
Four of the five servers running during the audit were outdated. A server reports `ready` from its own endpoint regardless of whether its executable still exists on disk, and its root document carries no HEAD, no build identity and no executable fingerprint for a reader to compare. This is the ghost-server class: a server that answers is not a server that is current.
Desired state
A client that reads a server's own documents can decide whether that server is current, without holding a second executable. A stale server says so where it is asked, in the same place it says it is ready.
Scope
- apps/majordomus-cli/src/server
- apps/majordomus-cli/src/capability/builtin/server.rs
- apps/majordomus-cli/src/capability/builtin/health.rs
- docs/COCKPIT.md
- test/cases
Out of scope
- Reaping the server register. The fleet listing enumerates every checkout it has ever seen, including long-gone scratch trees under /private/tmp, and nothing reaps it; that is a separate finding and not this issue.
- Killing or restarting another checkout's server. Several live sessions share this machine.
Dependencies
None. This issue is a root of the graph.
Acceptance criteria
- A server whose executable has been replaced reports that fact on the endpoint a client asks for its standing
- The check is answerable by a client holding no second executable
- A current server is not reported stale, proved by a fresh start
Validation
- bin/majordomus-cli serve status
- bash test/run.sh
Evidence required
- stale_server_says_so
- current_server_is_not_flagged
Evidence
| covers | type | command | result | at commit |
|---|---|---|---|---|
| stale_server_says_so | test | bash test/run.sh 885_a_replaced_server_stops_calling_itself_ready | ok at 4090b2b8ae: a server whose executable was replaced answers ready false with stale naming the replacement, on /api/v1/ready and the root document; the change is 8c29f1f3a6 (PR #747, landed in #815) | 4090b2b |
| current_server_is_not_flagged | test | bash test/run.sh 885_a_replaced_server_stops_calling_itself_ready | ok at 4090b2b8ae: the same case restarts the server and reads ready true with no stale field | 4090b2b |
Risk
Low in mechanism, high in value. The risk worth naming is the opposite one: a check that flags a current server as stale would make every worker ignore the signal, which is worse than not having it.
Timeline
- started
- 2026-10-08T10:33:49Z
- verified
- 2026-10-08T10:34:14Z
- completed
- 2026-10-08T10:34:20Z
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I1502.yaml. Read it back with majordomus plan show I1502.