actorOne sidecar per Claude session owns the session's harness turns
spec:cc-agents.sidecarPacks: 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
- 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.idleExitline 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.insideTheProcessline 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.privateSocketline 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.exitsWithOwnerline 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.knowsNoHarnessline 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.checkBeforeStartline 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.eventsKeptline 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.oneAttemptline 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.preparedBeforeRunline 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.leaseInterruptsline 45 ·specs/runner/sidecar.sdp.md:45- A turn whose events nobody has read within the lease is interrupted.
no example exercises it
rule.waitsVisiblyline 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.statusForViewsline 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.remembersAgentsline 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
startCommandline 52 ·specs/runner/sidecar.sdp.md:52node launch.mjs --dir <run dir> --sock <socket> --state <state dir>; the sidecar's owner is the launcher's parent.no citation recorded
endpointsline 53 ·specs/runner/sidecar.sdp.md:53GET /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
turnStatesline 54 ·specs/runner/sidecar.sdp.md:54waiting,preparing,submitted,running,stopping,confirmed-ended.no citation recorded
environmentline 55 ·specs/runner/sidecar.sdp.md:55CC_AGENTS_STATEnames the state directory,CC_AGENTS_LEASE_MSthe lease,CC_AGENTS_MACHINEanother machine-guard module, for tests.no citation recorded
runDirectoryline 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.
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:7Uses
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:12Uses
None.
Runtime observation: not tracked.
Evidence
Runtime observation: not tracked.
Build attestations: not tracked.
Deployments: not tracked.
Bills of materials: not tracked.
Impact
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
- refines · spec:cc-agents.runner · stated defined, floor ready
- dependsOn · spec:cc-agents.adapter-contract · stated ready, floor ready
- dependsOn · spec:cc-agents.cross-session-slots · stated ready, floor ready
- dependsOn · spec:cc-agents.machine-guard · stated ready, floor ready
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:5impl: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:9impl:cc-agents.relay-header·plugin/sidecar/relay-header.mjs:9impl: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:9impl: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:15impl:cc-agents.opencode·plugin/sidecar/adapters/opencode.mjs:26impl: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:12impl: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:5impl: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:13impl:cc-agents.guard·plugin/sidecar/guard.mjs:16
Referencing units
None.
Enabled verifiers: test:cc-agents.sidecar-suite
Packs: None
Relations
| Relation and direction | Other end | Claim | Reason | Exercised keys |
|---|---|---|---|---|
| dependsOn · outgoing | One adapter module per harness, behind one contractspec:cc-agents.adapter-contract · resolves | declared | the sidecar drives every harness only through the adapter contract | None |
| dependsOn · outgoing | A cap on concurrent turns holds across every Claude session on the machinespec:cc-agents.cross-session-slots · resolves | declared | a turn starts only with a slot of its cap key | None |
| dependsOn · outgoing | A critically loaded machine refuses new agents and stops nonespec:cc-agents.machine-guard · resolves | declared | a start waits while the machine refuses it | None |
| refines · outgoing | Other model families run as real Claude Code agentsspec:cc-agents.runner · resolves | declared | None | None |
| dependsOn · incoming | The mod answers an agent's steps from the sidecar and never calls a modelspec:cc-agents.mod-layer · resolves | declared | every decision of the mod is a request to the session's sidecar | None |
| dependsOn · incoming | The session's agents, their caps and the machine are always in viewspec:cc-agents.pane · resolves | declared | the pane and the /harnesses text read the sidecar's status answer | None |
| dependsOn · incoming | The job agent takes Relay's header and returns Relay's state blockspec:cc-agents.relay-job-type · resolves | declared | the header is translated, the report kept and the role remembered by the sidecar | None |
| dependsOn · incoming | Other model families run as real Claude Code agentsspec:cc-agents.runner · resolves | declared | the per-session process that owns every harness turn | None |
| dependsOn · incoming | A message reaches the running turn at once, and a stop ends the harness turnspec:cc-agents.steering-and-stop · resolves | declared | the sidecar holds the running turn that a message reaches | None |
Bindings
Implementation binding: present
impl:cc-agents.launch· starts the sidecar detached and returns once it answers on its socket ·plugin/sidecar/launch.mjs:7impl: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.