actorA guard ends the groups a harness turn started and it has seen, even when the sidecar is killed
spec:cc-agents.work-containmentPacks: none
Design: 3 design entries · 3 pinned declarations · no decisions
Findings: no errors, no warnings
specs/runner/work-containment.sdp.md
1 open question and no blocking questions; implementation binding present, verifier binding present, and expected-outcome oracle none.
The guard is plugin/sidecar/guard.mjs, with the process-group records in plugin/sidecar/groups.mjs. It runs one harness process in a process group it leads, sharing its stdio with the sidecar, so the group's id stays unique while anything of the work runs.
Intent
- The sidecar and the slot that records a turn's work.
problem- A harness runs commands in process groups of its own, and a sidecar killed outright cannot clean up after itself.
outcome- When the harness process exits or the sidecar is gone, the guard's own group and every other group the guard has seen are ended, and the work is known to have ended only when those groups no longer exist.
value- A stopped or crashed agent leaves nothing running in a group the guard knew, and capacity is not handed back while any such group still exists.
Open questions
- non-blocking ·
question.detachedBeforeScanline 22 · specs/runner/work-containment.sdp.md:22· A process that leaves the guard's group and is reparented to the system between two scans is in no record, so the guard neither ends it nor counts it. Should the guarantee grow to cover it?Decider: ownerProvisional: No. The guarantee covers the guard's group and the groups a scan recorded; a descendant that detaches and is orphaned within one scan interval, two seconds by default, escapes cleanup and accounting. Covering it needs a code change, such as a process-tree watcher or an operating-system containment feature, and none is made here.
Behavior
rule.guardEndsWorkline 28 ·specs/runner/work-containment.sdp.md:28- When the command exits or the sidecar that started the guard is gone, even after a SIGKILL, the guard sends SIGTERM, then SIGKILL to what ignores it, ends its own group and the groups it has recorded, the own group last, and exits only once those groups are gone.
no example exercises it
rule.nestedGroupsline 29 ·specs/runner/work-containment.sdp.md:29- The guard looks at its process tree every few seconds and records each other process group that a descendant is in, so commands a harness runs in groups of their own are ended too. A descendant that leaves the tree before a scan reaches it is not recorded (see #detachedBeforeScan).
no example exercises it
rule.recordsOutliveGuardline 30 ·specs/runner/work-containment.sdp.md:30- The record of those groups lives in a file named for the guard, with each group's leader start time, so a guard killed with its sidecar leaves the groups counted as running and the reaper ends them.
no example exercises it
rule.stoppedFirstline 31 ·specs/runner/work-containment.sdp.md:31- An interrupt the harness does not confirm ends the turn only once the processes of its group and of the groups recorded are gone.
no example exercises it
rule.liveSidecarFinishesTheJobline 32 ·specs/runner/work-containment.sdp.md:32- A guard killed under a live sidecar frees the turn's slot only once the sidecar has ended the commands the guard had recorded.
no example exercises it
0 unkeyed rules.
Design
invocationline 36 ·specs/runner/work-containment.sdp.md:36node guard.mjs <command> [args...]no citation recorded
recordFileline 37 ·specs/runner/work-containment.sdp.md:37<state>/guards/<guard pid>.json, holding the guard's pid and start and each recorded group's id and leader start.no citation recorded
environmentline 38 ·specs/runner/work-containment.sdp.md:38CC_AGENTS_GUARD_DIRnames the records' folder,CC_AGENTS_GUARD_GRACE_MSandCC_AGENTS_GUARD_SCAN_MSset the grace and the scan interval.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.work-containment: A guard ends the groups a harness turn started and it has seen, even when the sidecar is killed · declared Spec
- spec:cc-agents.runner: Other model families run as real Claude Code agents · declared Spec
- impl:cc-agents.groups: records the process groups of a guarded turn and tells whether its work still runs · anchored code ·
plugin/sidecar/groups.mjs:13 - impl:cc-agents.guard: runs one harness process in a group it leads and ends everything the turn started · anchored code ·
plugin/sidecar/guard.mjs:16 - 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.work-containment refines spec:cc-agents.runner · declared
- impl:cc-agents.groups satisfies spec:cc-agents.work-containment · anchored
- impl:cc-agents.guard satisfies spec:cc-agents.work-containment · anchored
- test:cc-agents.sidecar-suite verifies spec:cc-agents.work-containment · 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.groups· records the process groups of a guarded turn and tells whether its work still runs ·plugin/sidecar/groups.mjs:13Uses
None.
impl:cc-agents.guard· runs one harness process in a group it leads and ends everything the turn started ·plugin/sidecar/guard.mjs:16Uses
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.codex-adapter: GPT runs through the user's Codex, one app-server per turn
- spec:cc-agents.cross-session-slots: A cap on concurrent turns holds across every Claude session on the machine
- spec:cc-agents.runner: Other model families run as real Claude Code agents
- spec:cc-agents.steering-and-stop: A message reaches the running turn at once, and a stop ends the harness turn
- spec:cc-agents.work-containment: A guard ends the groups a harness turn started and it has seen, even when the sidecar is killed
- spec:cc-agents.work-containment refines spec:cc-agents.runner · declared
- spec:cc-agents.codex-adapter dependsOn spec:cc-agents.work-containment · declared — the Codex app-server runs under the guard, and its process group is the turn's work
- spec:cc-agents.cross-session-slots dependsOn spec:cc-agents.work-containment · declared — a slot is free only once the work recorded in it has ended
- spec:cc-agents.steering-and-stop dependsOn spec:cc-agents.work-containment · declared — what an interrupted turn leaves running is bounded by the groups the guard recorded
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
Rested on by
Distance 1
- 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.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.hq-links
Implementing units
None.
Referencing units
None.
Enabled verifiers: None
Packs: None
- spec:cc-agents.sidecar
Implementing units
impl:cc-agents.launch·plugin/sidecar/launch.mjs:7impl:cc-agents.sidecar·plugin/sidecar/server.mjs:12
Referencing units
None.
Enabled verifiers: test:cc-agents.sidecar-suite
Packs: None
Distance 3
- 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
Distance 4
- 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.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.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
Relations
| Relation and direction | Other end | Claim | Reason | Exercised keys |
|---|---|---|---|---|
| refines · outgoing | Other model families run as real Claude Code agentsspec:cc-agents.runner · resolves | declared | None | None |
| dependsOn · incoming | GPT runs through the user's Codex, one app-server per turnspec:cc-agents.codex-adapter · resolves | declared | the Codex app-server runs under the guard, and its process group is the turn's work | None |
| dependsOn · incoming | A cap on concurrent turns holds across every Claude session on the machinespec:cc-agents.cross-session-slots · resolves | declared | a slot is free only once the work recorded in it has ended | 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 | what an interrupted turn leaves running is bounded by the groups the guard recorded | None |
Bindings
Implementation binding: present
impl:cc-agents.groups· records the process groups of a guarded turn and tells whether its work still runs ·plugin/sidecar/groups.mjs:13impl:cc-agents.guard· runs one harness process in a group it leads and ends everything the turn started ·plugin/sidecar/guard.mjs:16
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.