Spec Studio

One sidecar per Claude session owns the session's harness turns

spec:cc-agents.sidecarUse Case / Behavior · featureready floor ready

Packs: none

Design: 5 design entries · 5 pinned declarations · no decisions

Findings: no errors, no warnings

specs/runner/sidecar.sdp.md

2 open questions and no blocking questions; implementation binding present, verifier binding present, and expected-outcome oracle none.

The sidecar is plugin/sidecar/server.mjs, started detached by plugin/sidecar/launch.mjs the first time the mod needs it. It is a small HTTP server on a Unix socket, and it is the only part that knows turns and neutral events; each harness sits behind its adapter. The harness processes are separate from it and from the Claude Code process: their lifetime is tied to the host, they are not inside it.

Intent
actor
The mod of one Claude session.
problem
A harness turn outlives any single step or hook call, and its capacity, events and cleanup must not depend on a Claude Code process that can reload its mods or die.
outcome
A process per session keeps each agent's turn and its events until the mod reads them, runs the turn through the adapter, and ends everything it started when its owner is gone.
value
A mod reload or crash does not lose a running turn, and no turn outlives the session that started it.

Open questions

  • non-blocking · question.idleExit line 29 · specs/runner/sidecar.sdp.md:29 · The sidecar also exits two minutes after its last turn and its last waiting spawn, refuses a second concurrent turn for the same agent, and fails a turn whose preparation fails without running it; no test pins any of the three.Decider: delegatedProvisional: Both are as built.
  • non-blocking · question.insideTheProcess line 32 · specs/runner/sidecar.sdp.md:32 · The README says the agents run inside the Claude Code process, while the code runs them in a detached sidecar and separate harness processes whose lifetime is tied to the host.Decider: ownerProvisional: The code is the truth; the README sentence needs a correction in the documents.
Behavior
rule.privateSocket line 38 · specs/runner/sidecar.sdp.md:38
The sidecar listens only on a Unix socket mode 0600 in a directory mode 0700 that belongs to the user, and refuses to start in a directory that others can enter.

no example exercises it

rule.exitsWithOwner line 39 · specs/runner/sidecar.sdp.md:39
The sidecar exits when its owner, the Claude Code process that started it, is gone, and a sidecar that stops mid-turn takes the harness and its commands with it.

no example exercises it

rule.knowsNoHarness line 40 · specs/runner/sidecar.sdp.md:40
The sidecar loads an adapter by the harness's name from its adapters folder, accepts only names of lowercase letters, digits and hyphens, and refuses a harness with no adapter.

no example exercises it

rule.checkBeforeStart line 41 · specs/runner/sidecar.sdp.md:41
A check resolves the model and effort the turn will run with, refuses what the harness cannot do with the values that would work, and answers with the turn's cap key and cap.

no example exercises it

rule.eventsKept line 42 · specs/runner/sidecar.sdp.md:42
The sidecar keeps an agent's events and serves them by a cursor, as a long poll that answers at once when events are past the cursor.

no example exercises it

rule.oneAttempt line 43 · specs/runner/sidecar.sdp.md:43
A turn runs once: a failure the harness reports ends the turn as it comes and is never replayed, because the harness retries on its own.

no example exercises it

rule.preparedBeforeRun line 44 · specs/runner/sidecar.sdp.md:44
The adapter prepares the turn and its work is recorded in the turn's slot before anything is submitted.

no example exercises it

rule.leaseInterrupts line 45 · specs/runner/sidecar.sdp.md:45
A turn whose events nobody has read within the lease is interrupted.

no example exercises it

rule.waitsVisibly line 46 · specs/runner/sidecar.sdp.md:46
A turn over its cap, or refused by the machine guard, waits and says why once as a status line, and starts when a slot frees or the machine eases.

no example exercises it

rule.statusForViews line 47 · specs/runner/sidecar.sdp.md:47
A status answer gives the session's agents, every cap key's use counted machine-wide, the spawns waiting for a slot, and the machine's sample.

no example exercises it

rule.remembersAgents line 48 · specs/runner/sidecar.sdp.md:48
The sidecar writes each agent's settings to a file in its run directory, so a reloaded mod can ask for them, and remembers Workflow roles by run id and position across sessions.

no example exercises it

0 unkeyed rules.

Design
startCommand line 52 · specs/runner/sidecar.sdp.md:52
node launch.mjs --dir <run dir> --sock <socket> --state <state dir>; the sidecar's owner is the launcher's parent.

no citation recorded

endpoints line 53 · specs/runner/sidecar.sdp.md:53
GET /health, POST /check, POST /reserve, POST /release, POST /register, POST /start, GET /events, POST /steer, POST /interrupt, GET /status, GET /agent, POST /resume-lookup.

no citation recorded

turnStates line 54 · specs/runner/sidecar.sdp.md:54
waiting, preparing, submitted, running, stopping, confirmed-ended.

no citation recorded

environment line 55 · specs/runner/sidecar.sdp.md:55
CC_AGENTS_STATE names the state directory, CC_AGENTS_LEASE_MS the lease, CC_AGENTS_MACHINE another machine-guard module, for tests.

no citation recorded

runDirectory line 56 · specs/runner/sidecar.sdp.md:56
<state>/run/<first 12 characters of the session id>, holding the socket, the log and the agents file.

no citation recorded

Verification

Verifier bindings

  • test:cc-agents.sidecar-suite · the sidecar, the Codex adapter, the slots and the guard against a fake Codex app-server · anchored · test anchor binding present · tests/sidecar.test.mjs:4
Design view

Requirement drawing

  • Declared verifying examples: no declared verifying example.
Requirement drawing for spec:cc-agents.sidecar
The diagram as text
  • spec:cc-agents.sidecar: One sidecar per Claude session owns the session's harness turns · declared Spec
  • spec:cc-agents.runner: Other model families run as real Claude Code agents · declared Spec
  • impl:cc-agents.launch: starts the sidecar detached and returns once it answers on its socket · anchored code · plugin/sidecar/launch.mjs:7
  • impl:cc-agents.sidecar: the per-session sidecar: owns each harness turn, its events and its slot, and drives every adapter through the contract · anchored code · plugin/sidecar/server.mjs:12
  • test:cc-agents.sidecar-suite: the sidecar, the Codex adapter, the slots and the guard against a fake Codex app-server · anchored test binding · binding present · tests/sidecar.test.mjs:4
  • spec:cc-agents.sidecar refines spec:cc-agents.runner · declared
  • impl:cc-agents.launch satisfies spec:cc-agents.sidecar · anchored
  • impl:cc-agents.sidecar satisfies spec:cc-agents.sidecar · anchored
  • test:cc-agents.sidecar-suite verifies spec:cc-agents.sidecar · anchored
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred and chosen syntax: requirementDiagram; exact refines, satisfies and verifies, with claim words in nodes and per-edge comments.

Decisions

No decision record named.

Runtime
  • impl:cc-agents.launch · starts the sidecar detached and returns once it answers on its socket · plugin/sidecar/launch.mjs:7

    Uses

    None.

  • impl:cc-agents.sidecar · the per-session sidecar: owns each harness turn, its events and its slot, and drives every adapter through the contract · plugin/sidecar/server.mjs:12

    Uses

    None.

Runtime observation: not tracked.

Evidence

Runtime observation: not tracked.

Build attestations: not tracked.

Deployments: not tracked.

Bills of materials: not tracked.

Impact
Relations of spec:cc-agents.sidecar
The diagram as text
  • spec:cc-agents.adapter-contract: One adapter module per harness, behind one contract
  • spec:cc-agents.cross-session-slots: A cap on concurrent turns holds across every Claude session on the machine
  • spec:cc-agents.machine-guard: A critically loaded machine refuses new agents and stops none
  • spec:cc-agents.mod-layer: The mod answers an agent's steps from the sidecar and never calls a model
  • spec:cc-agents.pane: The session's agents, their caps and the machine are always in view
  • spec:cc-agents.relay-job-type: The job agent takes Relay's header and returns Relay's state block
  • spec:cc-agents.runner: Other model families run as real Claude Code agents
  • spec:cc-agents.sidecar: One sidecar per Claude session owns the session's harness turns
  • spec:cc-agents.steering-and-stop: A message reaches the running turn at once, and a stop ends the harness turn
  • spec:cc-agents.sidecar dependsOn spec:cc-agents.adapter-contract · declared — the sidecar drives every harness only through the adapter contract
  • spec:cc-agents.sidecar dependsOn spec:cc-agents.cross-session-slots · declared — a turn starts only with a slot of its cap key
  • spec:cc-agents.sidecar dependsOn spec:cc-agents.machine-guard · declared — a start waits while the machine refuses it
  • spec:cc-agents.sidecar refines spec:cc-agents.runner · declared
  • spec:cc-agents.mod-layer dependsOn spec:cc-agents.sidecar · declared — every decision of the mod is a request to the session's sidecar
  • spec:cc-agents.pane dependsOn spec:cc-agents.sidecar · declared — the pane and the /harnesses text read the sidecar's status answer
  • spec:cc-agents.relay-job-type dependsOn spec:cc-agents.sidecar · declared — the header is translated, the report kept and the role remembered by the sidecar
  • spec:cc-agents.runner dependsOn spec:cc-agents.sidecar · declared — the per-session process that owns every harness turn
  • spec:cc-agents.steering-and-stop dependsOn spec:cc-agents.sidecar · declared — the sidecar holds the running turn that a message reaches
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: flowchart. Chosen syntax: labelled flowchart, preserving exact relations, claims and folds.

Rests on

Rested on by

Distance 1

  • spec:cc-agents.mod-layer

    Implementing units

    • impl:cc-agents.mod · plugin/hooks/register.js:9

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.mod-suite

    Packs: None

  • spec:cc-agents.pane

    Implementing units

    • impl:cc-agents.harness-options · plugin/hooks/harnesses.js:5
    • impl:cc-agents.pane · plugin/hooks/pane.js:13

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.mod-suite, test:cc-agents.pane-suite

    Packs: None

  • spec:cc-agents.relay-job-type

    Implementing units

    • impl:cc-agents.mod · plugin/hooks/register.js:9
    • impl:cc-agents.relay-header · plugin/sidecar/relay-header.mjs:9
    • impl:cc-agents.sidecar · plugin/sidecar/server.mjs:12

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.mod-suite, test:cc-agents.sidecar-suite

    Packs: None

  • spec:cc-agents.runner

    Implementing units

    None.

    Referencing units

    None.

    Enabled verifiers: None

    Packs: None

  • spec:cc-agents.steering-and-stop

    Implementing units

    • impl:cc-agents.mod · plugin/hooks/register.js:9
    • impl:cc-agents.sidecar · plugin/sidecar/server.mjs:12

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.mod-suite, test:cc-agents.sidecar-suite

    Packs: None

Distance 2

  • spec:cc-agents.adapter-contract

    Implementing units

    • impl:cc-agents.codex · plugin/sidecar/adapters/codex.mjs:15
    • impl:cc-agents.opencode · plugin/sidecar/adapters/opencode.mjs:26
    • impl:cc-agents.sidecar · plugin/sidecar/server.mjs:12

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.opencode-suite, test:cc-agents.sidecar-suite

    Packs: None

  • spec:cc-agents.codex-adapter

    Implementing units

    • impl:cc-agents.codex · plugin/sidecar/adapters/codex.mjs:15

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.sidecar-suite

    Packs: None

  • spec:cc-agents.cross-session-slots

    Implementing units

    • impl:cc-agents.sidecar · plugin/sidecar/server.mjs:12
    • impl:cc-agents.slots · plugin/sidecar/slots.mjs:16

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.sidecar-suite

    Packs: None

  • spec:cc-agents.exact-answer

    Implementing units

    • impl:cc-agents.mod · plugin/hooks/register.js:9

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.mod-suite

    Packs: None

  • spec:cc-agents.hq-links

    Implementing units

    None.

    Referencing units

    None.

    Enabled verifiers: None

    Packs: None

  • spec:cc-agents.installation

    Implementing units

    None.

    Referencing units

    • impl:cc-agents.harness-options · plugin/hooks/harnesses.js:5

    Enabled verifiers: None

    Packs: None

  • spec:cc-agents.machine-guard

    Implementing units

    • impl:cc-agents.machine · plugin/sidecar/machine.mjs:20

    Referencing units

    • impl:cc-agents.sidecar · plugin/sidecar/server.mjs:12

    Enabled verifiers: test:cc-agents.machine-suite, test:cc-agents.sidecar-suite

    Packs: None

  • spec:cc-agents.model-templates

    Implementing units

    • impl:cc-agents.harness-options · plugin/hooks/harnesses.js:5
    • impl:cc-agents.mod · plugin/hooks/register.js:9

    Referencing units

    • impl:cc-agents.sync-templates · scripts/sync-templates.mjs:10

    Enabled verifiers: test:cc-agents.mod-suite

    Packs: None

  • spec:cc-agents.opencode-adapter

    Implementing units

    • impl:cc-agents.opencode · plugin/sidecar/adapters/opencode.mjs:26

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.opencode-suite

    Packs: None

  • spec:cc-agents.work-containment

    Implementing units

    • impl:cc-agents.groups · plugin/sidecar/groups.mjs:13
    • impl:cc-agents.guard · plugin/sidecar/guard.mjs:16

    Referencing units

    None.

    Enabled verifiers: test:cc-agents.sidecar-suite

    Packs: None

Relations

Relation and directionOther endClaimReasonExercised keys
dependsOn · outgoingOne adapter module per harness, behind one contract
spec:cc-agents.adapter-contract · resolves
declaredthe sidecar drives every harness only through the adapter contractNone
dependsOn · outgoingA cap on concurrent turns holds across every Claude session on the machine
spec:cc-agents.cross-session-slots · resolves
declareda turn starts only with a slot of its cap keyNone
dependsOn · outgoingA critically loaded machine refuses new agents and stops none
spec:cc-agents.machine-guard · resolves
declareda start waits while the machine refuses itNone
refines · outgoingOther model families run as real Claude Code agents
spec:cc-agents.runner · resolves
declaredNoneNone
dependsOn · incomingThe mod answers an agent's steps from the sidecar and never calls a model
spec:cc-agents.mod-layer · resolves
declaredevery decision of the mod is a request to the session's sidecarNone
dependsOn · incomingThe session's agents, their caps and the machine are always in view
spec:cc-agents.pane · resolves
declaredthe pane and the /harnesses text read the sidecar's status answerNone
dependsOn · incomingThe job agent takes Relay's header and returns Relay's state block
spec:cc-agents.relay-job-type · resolves
declaredthe header is translated, the report kept and the role remembered by the sidecarNone
dependsOn · incomingOther model families run as real Claude Code agents
spec:cc-agents.runner · resolves
declaredthe per-session process that owns every harness turnNone
dependsOn · incomingA message reaches the running turn at once, and a stop ends the harness turn
spec:cc-agents.steering-and-stop · resolves
declaredthe sidecar holds the running turn that a message reachesNone

Bindings

Implementation binding: present

  • impl:cc-agents.launch · starts the sidecar detached and returns once it answers on its socket · plugin/sidecar/launch.mjs:7
  • impl:cc-agents.sidecar · the per-session sidecar: owns each harness turn, its events and its slot, and drives every adapter through the contract · plugin/sidecar/server.mjs:12

Design reference: none

Verifier binding: present

  • test:cc-agents.sidecar-suite · the sidecar, the Codex adapter, the slots and the guard against a fake Codex app-server · anchored · tests/sidecar.test.mjs:4 · test anchor

Expected-outcome oracle: none

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.