fleetd #458: restate invariant 5 by purpose, not mechanism #465

Closed
agent wants to merge 0 commits from worker/458-invariant-5-by-purpose-862f9a-10 into main
Member

What changed

Invariant 5 of the canonical block in CLAUDE.md used to ban a mechanism ("never drive the terminal multiplexer directly") and name herdr's CLI and socket as the banned tool. That works everywhere except this repo, where herdr is itself the subject under test: four contract tests must open its socket on purpose, or the fake and the real herdr can disagree for weeks with a green suite (fleetd #449).

New text (invariant 5 only):

  1. Never move a fleet session, pane or peer except through the bridge. The bridge owns policy;
    the multiplexer owns PTYs. Any route that changes fleet state without the bridge's checks
    bypasses every rule above — the herdr CLI and its socket are the usual example.

It now bans a control plane (any route that moves real fleet state without the bridge's checks), and keeps herdr's CLI/socket only as the named example of that route, not the definition of the ban.

Scope proof — only invariant 5 moved

Canonical block (## Bridge communication (enforced through ## Project addendum — claude-bridge), measured with a script that slices between the two headings:

  • before: 17626 bytes
  • after: 17718 bytes

git diff is a single hunk touching only invariant 5:

@@ -58,8 +58,9 @@ and the sender silently receives nothing. Fail toward the recoverable error.
    re-send because a call looks slow — the bridge delivers when the peer is `idle`, `blocked` or
    `done`. A spawned member must **also** have mounted the bridge MCP: until it has, it is not
    deliverable, and a send waits on that gate for ~60s and then fails without ever reaching its pane.
-5. **Never drive the terminal multiplexer directly** (no `herdr` CLI, no socket). The bridge owns
-   policy; the multiplexer owns PTYs. Going around the bridge bypasses every rule above.
+5. **Never move a fleet session, pane or peer except through the bridge.** The bridge owns policy;
+   the multiplexer owns PTYs. Any route that changes fleet state without the bridge's checks
+   bypasses every rule above — the `herdr` CLI and its socket are the usual example.
 
 ### Primary (lead) — run this on every task, in order

The Project addendum's "Herdr socket tests (measured 2026-09-10)" note is untouched — not one byte.

Criterion 2 — the legal action

A worker assigned to AgentControlContractTest.java (fleetd/src/test/java/dev/ltms/fleet/herdr/AgentControlContractTest.java) can call the herdr socket directly from inside that test, against a throwaway workspace the test itself creates and tears down. That action never moves the state of a real fleet session, pane, or peer under the running daemon's management — it is a socket call inside a disposable test fixture, not a route into the live control plane — so it does not fall under invariant 5's new wording even without invoking the addendum carve-out. Under the old wording ("no herdr CLI, no socket", full stop) this same action read as banned; that unsatisfiability is what #458 was raised to fix.

Criterion 4 — is the addendum note now redundant?

No, I don't think it's fully redundant, though the sharpest tension (the unsatisfiable ban) is gone. The addendum still does two things the restated invariant can't do by itself:

  1. It scopes the exception to exactly four named files, rather than leaving "does this test move real fleet state" as a judgment call every future worker has to make fresh.
  2. It gives the reason (#449 — a fake and the real herdr disagreeing for weeks with a green suite), which is what makes the carve-out legible instead of just asserted.

So I'd keep it, but that's a judgment call for #455 — leaving it as-is per the brief either way.

Build

cd fleetd && mvn clean install (full output captured, not piped):

Tests run: 1583, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

Doc-only change; build is unaffected but run per the implementer skill's acceptance criterion.

Ref: fleetd #458

## What changed Invariant 5 of the canonical block in `CLAUDE.md` used to ban a mechanism ("never drive the terminal multiplexer directly") and name `herdr`'s CLI and socket as the banned tool. That works everywhere except this repo, where `herdr` is itself the subject under test: four contract tests must open its socket on purpose, or the fake and the real `herdr` can disagree for weeks with a green suite (fleetd #449). New text (invariant 5 only): > 5. **Never move a fleet session, pane or peer except through the bridge.** The bridge owns policy; > the multiplexer owns PTYs. Any route that changes fleet state without the bridge's checks > bypasses every rule above — the `herdr` CLI and its socket are the usual example. It now bans a control plane (any route that moves real fleet state without the bridge's checks), and keeps `herdr`'s CLI/socket only as the *named example* of that route, not the definition of the ban. ## Scope proof — only invariant 5 moved Canonical block (`## Bridge communication (enforced` through `## Project addendum — claude-bridge`), measured with a script that slices between the two headings: - before: 17626 bytes - after: 17718 bytes `git diff` is a single hunk touching only invariant 5: ```diff @@ -58,8 +58,9 @@ and the sender silently receives nothing. Fail toward the recoverable error. re-send because a call looks slow — the bridge delivers when the peer is `idle`, `blocked` or `done`. A spawned member must **also** have mounted the bridge MCP: until it has, it is not deliverable, and a send waits on that gate for ~60s and then fails without ever reaching its pane. -5. **Never drive the terminal multiplexer directly** (no `herdr` CLI, no socket). The bridge owns - policy; the multiplexer owns PTYs. Going around the bridge bypasses every rule above. +5. **Never move a fleet session, pane or peer except through the bridge.** The bridge owns policy; + the multiplexer owns PTYs. Any route that changes fleet state without the bridge's checks + bypasses every rule above — the `herdr` CLI and its socket are the usual example. ### Primary (lead) — run this on every task, in order ``` The Project addendum's "Herdr socket tests (measured 2026-09-10)" note is untouched — not one byte. ## Criterion 2 — the legal action A worker assigned to `AgentControlContractTest.java` (`fleetd/src/test/java/dev/ltms/fleet/herdr/AgentControlContractTest.java`) can call the herdr socket directly from inside that test, against a throwaway workspace the test itself creates and tears down. That action never moves the state of a real fleet session, pane, or peer under the running daemon's management — it is a socket call inside a disposable test fixture, not a route into the live control plane — so it does not fall under invariant 5's new wording even without invoking the addendum carve-out. Under the *old* wording ("no herdr CLI, no socket", full stop) this same action read as banned; that unsatisfiability is what #458 was raised to fix. ## Criterion 4 — is the addendum note now redundant? No, I don't think it's fully redundant, though the sharpest tension (the unsatisfiable ban) is gone. The addendum still does two things the restated invariant can't do by itself: 1. It scopes the exception to exactly four named files, rather than leaving "does this test move real fleet state" as a judgment call every future worker has to make fresh. 2. It gives the reason (#449 — a fake and the real herdr disagreeing for weeks with a green suite), which is what makes the carve-out legible instead of just asserted. So I'd keep it, but that's a judgment call for #455 — leaving it as-is per the brief either way. ## Build `cd fleetd && mvn clean install` (full output captured, not piped): ``` Tests run: 1583, Failures: 0, Errors: 0, Skipped: 0 BUILD SUCCESS ``` Doc-only change; build is unaffected but run per the implementer skill's acceptance criterion. Ref: fleetd #458
agent added 1 commit 2026-09-10 13:51:21 +02:00
fleetd #458: restate invariant 5 by purpose, not mechanism
CI / contract (pull_request) Successful in 1m16s
CI / build (pull_request) Failing after 1m56s
29e7a06c49
Invariant 5 banned 'driving the terminal multiplexer directly', naming
herdr CLI and socket as the banned tool. That bans a mechanism. What it
protects is the control plane: nobody may move a fleet session, pane or
peer by a route that skips the bridge's policy checks.

In this repo herdr is itself the subject under test, so four contract
tests must open its socket on purpose (see the addendum's 'Herdr socket
tests' note). Under the old wording, a worker assigned to that code
reads invariant 5 and finds its only path to finish the task banned.

Restate the invariant by purpose: never move fleet state except through
the bridge. herdr's CLI and socket stay as the named example of the
banned route, not the definition of it.
Owner

Merged as eccd054. Closing by hand — a local --no-ff merge plus push did not trip the forge's auto-close.

Proof the branch is in main: git merge-base --is-ancestor origin/worker/458-invariant-5-by-purpose-862f9a-10 origin/main succeeds, branch tip 29e7a06.

Full verification is on #458: one hunk in one file, 5 changed lines all inside invariant 5, the addendum byte-identical, 1583 green. The three things a worktree cannot do — the wiki/7-Use-Cases.md template, the sync script (in sync: True), and the propagation survey (29 CLAUDE.md files, only this repo carries the block) — I did myself and posted there.

Merged as **`eccd054`**. Closing by hand — a local `--no-ff` merge plus push did not trip the forge's auto-close. Proof the branch is in `main`: `git merge-base --is-ancestor origin/worker/458-invariant-5-by-purpose-862f9a-10 origin/main` succeeds, branch tip `29e7a06`. Full verification is on #458: one hunk in one file, 5 changed lines all inside invariant 5, the addendum byte-identical, 1583 green. The three things a worktree cannot do — the `wiki/7-Use-Cases.md` template, the sync script (`in sync: True`), and the propagation survey (29 `CLAUDE.md` files, only this repo carries the block) — I did myself and posted there.
ltms closed this pull request 2026-09-10 14:20:19 +02:00
Some checks are pending
CI / contract (pull_request) Successful in 1m16s
CI / build (pull_request) Failing after 1m56s

Pull request closed

Sign in to join this conversation.