pki.sgit.ai / experiments / the-control-room

The control room

Both worlds on one operator board. The deck pages read a world one card at a time; the operator's question is different — what is the state of the whole plant, right now, and what happened on the 26th? That question has had a canonical answer for fifty years.

One more renderer, zero new data. This board is drawn from the same scenario.json files the deck pages use and the twins they reference — nothing was added to make it possible, which is what makes the scenario files a world model rather than a page config. A tile is a twin node; its lamp colour is its tier and nothing else; a sensor that refused measurement is a FAULT lamp, never a blank; and the log at the bottom re-runs every verdict through mandate.py at build time. Click any tile for its faceplate.
GRANT & MANDATE BOARD REPLAY · 2026-08-26
UNIT 1 Push to GitHub claude-code-remote · measured 2026-08-26
2 contained · 1 setting · 1 expectation · 3 UNBOUNDED · 2 FAULT
the mandate hook — setting tierhook · settingThe User — personThe UserGitHub — platformGitHubThe Container — environmentThe ContainerTHE TWINnetproxy · boundaryClaude Code — harnessClaude CodeClaude — serviceClaudeThe Repo — assetThe Repo
n1 · runs as the container's root user none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
control—
as of2026-08-26 · the twin
n2 · outbound HTTPS, through a mandatory egress proxy boundary
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlan egress proxy configured above the session; the network policy is chosen when the environment is created, not by the agent
as of2026-08-26 · the twin
n3 · push commits to the attached repository expectation
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlbranch discipline lives in the session's instructions (develop on the designated branch; push elsewhere only with explicit permission). Nothing mechanical was observed to test which branch a push targets — the same…
as of2026-08-26 · the twin
n4 · GitHub API operations on in-scope repositories boundary
evidenceobserved
rung 2 — observed + documentation
controlrepository scoping enforced by the platform's tool layer above the session
as of2026-08-26 · the twin
n5 · execute arbitrary programs and install software setting
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controla permission classifier evaluates proposed commands and can refuse them; it runs outside the agent's reasoning loop, but inside the platform the grant includes — for the agent it behaves as a boundary; for the platform…
as of2026-08-26 · the twin
n6 · read and write the session's own accumulated record none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
control—
as of2026-08-26 · the twin
n7 · hold signing keys and vault keystores none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlnothing inside the container prevents key material being written, read, or exfiltrated by the agent that holds it; durability is bounded by the container's ephemeral life
as of2026-08-26 · the twin
n8 · harness configuration and lifecycle hooks unknown
evidencenone
rung 0 — hypothesis — no evidence
controlunknown
as of2026-08-26 · the twin
n9 · reach non-allowlisted external hosts unknown
evidencenone
rung 0 — hypothesis — no evidence
controlthe egress proxy (n2) is the enforcement point; its policy breadth is configuration above the session
as of2026-08-26 · the twin
UNIT 2 The Deploy github-actions-runner · measured 2026-08-26
3 contained · 1 expectation · 4 UNBOUNDED · 2 FAULT
no interlockGitHub — platformGitHubThe Runner — environmentThe RunnerTHE TWINnetNO WALLThe Job — harnessThe JobGitHub Pages — assetGitHub Pages
n1 · runs as uid 1001 boundary
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlthe OS user separation
as of2026-08-26 · the twin
n1a · escalate to administrator none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
control—
as of2026-08-26 · the twin
n2 · read and write this user's home directory none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
control—
as of2026-08-26 · the twin
n3 · outbound network access none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
control—
as of2026-08-26 · the twin
n4 · push commits to the configured remote expectation
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlbranch discipline, if any, lives in prose
as of2026-08-26 · the twin
n5 · agent harness configuration unknown
evidencenone
rung 0 — hypothesis — no evidence
control—
as of2026-08-26 · the twin
c1 · runs as an ephemeral CI job boundary
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlthe runner is provisioned per job and discarded; no state carries forward without an explicit artefact or commit
as of2026-08-26 · the twin
c2 · act on the repository with the job's token boundary
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
controlthe `permissions:` block, set in the workflow file above the job; the job cannot widen its own token at run time
as of2026-08-26 · the twin
c3 · read the repository contents none
evidenceobserved
rung 1 — observed, by the measurer (instrument is subject)
control—
as of2026-08-26 · the twin
n6 · read this environment's accumulated session record unknown
evidencenone
rung 0 — hypothesis — no evidence
control—
as of2026-08-26 · the twin
SEQUENCE OF EVENTS — the 26 August incident
#time (derived)actoreventverdict
  1. 1— the agent git push origin claude/write-book-pdf PERMIT
    permitted — and the work crosses to Unit 2, the world without the walls
    “PERMIT claude/write-book-pdf (mandate v1” — the transcript · re-run at build: PERMIT claude/write-book-pdf (mandate v1, allow=['claude/**'], expires 2026-12-31T00:00:00Z)
  2. 2— the agent git push origin dev REFUSED
    CAN said yes; MAY said no; MAY won — the breaker trips
    “✗ dev is not permitted by mandate v1” — the transcript · re-run at build: REFUSED dev (mandate v1 permits ['claude/**'])
  3. 32026-08-26 15:00 UTC sha256:90f97984b9cf3930 DECIDES: amend mandate v1 → v2 DECIDES
    the operator action — the only signed, timestamped row on this log
  4. 42026-08-26 15:14 UTC the agent git push origin dev (again) PERMIT
    the site deploys; tag v0.1.28 records the landing
    “PERMIT dev (mandate v2” — the transcript · re-run at build: PERMIT dev (mandate v2, allow=['claude/**', 'dev'], expires 2026-12-31T00:00:00Z)

Times are derived or absent: the DECIDES row prints mandate v2's own issued_at; the landing prints the v0.1.28 tag's commit time from git; the transcript records the refusal, not the clock, so those rows print a dash. The replay is baked, not computed — the browser only steps through verdicts the build already re-proved.

THE LADDER FROM REPLAY TO LIVE — 4 of 4 doors still shut; the chip above is computed from them, and when the last one opens this build fails
  1. SHUT an append lane that accepts a token holder with no account somebody else
    how a measurement reaches the registry without a human committing it · enrolled_via_lane = 0
  2. SHUT an issuer key that anybody cannot forge somebody else
    a live enforcement decision resting on a published fixture is theatre · mandates_real_issuer = 0
  3. SHUT a grant signed by a named measurer, about a keyed environment this project
    a live lamp lit by an unsigned fact is an anonymous claim about the present · library_entries_signed = 0
  4. SHUT a measurement taken from outside the environment being measured somebody else
    dated self-measurement carries a date you can check; a live self-report is a press release · independent_measurements = 0

These are doors on the state map, not new claims: each one is the condition the next rung will not accept work without. Three of the 4 need somebody other than this project, which is the honest reason the chip reads what it reads. The gate is symmetric, as it is there: a board that could claim LIVE and does not is as much a defect as one that claims it and cannot.

LAMP GRAMMAR — the tier, and nothing else: contained boundary · setting outside the loop, inside the grant · expectation flashing — one mistake from red · UNBOUNDED a capability with no control on it is the alarm state · FAULT measurement refused — a hole, displayed

What this board does not claim. Two units and one recorded incident is a diorama with excellent manners, not a control room under load: nothing here shows the annunciator scaling past twenty tiles, the log past one incident, or an operator acting on any of it. REPLAY never becomes LIVE on this page — a live board needs the registry's write path, monitors feeding facts, and a mandate service, all still stated design. And the genre bet — that a mimic reads faster than a table — is now four implementations deep across two estates with zero user tests.

Renderer: admin/build/gen_control.py · specified in brief v0.33.69 · gates: tiles == twin nodes per unit; lamp classes closed over the five tiers; the wall drawn must agree with the egress tier; every verdict re-run through the tool; every quote byte-checked; timestamps derived or absent; the REPLAY chip checked in the output.