Skip to content

<objective> Build the AgentOS supervisor behind its port and the hardening profile verifier. No concrete driver binding in this plan.

Purpose: Deliver RT-04 supervision with bounded crash policy and the RT-01 conformance check that gates container use. Output: Supervisor module, profile verifier, one fake, and two test files. </objective>

<execution_context> @~/.claude/gsd-core/workflows/execute-plan.md @~/.claude/gsd-core/templates/summary.md </execution_context>

<context> @.planning/PROJECT.md @.planning/ROADMAP.md @.planning/phases/03-container-runtime-and-bridges/03-CONTEXT.md @.planning/phases/03-container-runtime-and-bridges/03-PATTERNS.md </context>

<tasks>

<task type="tdd"> <name>Task 1: AgentOsDriver port and crash-loop supervisor</name> <files>src/runtime/agentos.ts, test/support/fake-agentos.ts, test/runtime/agentos-supervisor.test.ts</files> <read_first> - src/core/ports.ts (from plan 03-01; port style: interface only, no environment field) - src/core/backoff.ts (from plan 03-01; base 500 ms, cap 8000 ms, full jitter with injected random and sleep) - src/core/timeout.ts (every driver call raced against a timeout per D-59 and QUAL-01) - test/support/fake-execution.ts (scripted outcomes plus per-call recording to mirror) </read_first> <behavior> - Test: crash (alive false or start reject) restarts after a backoff from the shared schedule - Test: fifth consecutive failure throws AGENTOS_CRASH_LOOP (retryable); counter resets after 60000 ms of continuous alive (injected clock) - Test: hung driver call times out instead of hanging the supervisor - Test titles cite RT-04 </behavior> <action>Write the failing tests first per behavior, then implement per D-59 and D-60 in src/runtime/agentos.ts: AgentOsDriver port with start(), alive(), stop(); the supervisor owns restart policy with maximum 5 consecutive attempts, the fifth holding and throwing AGENTOS_CRASH_LOOP, the counter resetting after 60000 ms of continuous alive, and every driver call raced against a timeout. AgentOS lifecycle goes only through the supervisor and its port; nothing else starts or stops the process. The concrete driver is not written: the library registry entry is unverified (OQ-P3-06 default: no dependency added; an npm view read would precede any add) and the in-sandbox channel is undocumented (OQ-P3-05 default: port only, binding not written, reported as blocked). Hosted mode is not implemented (S-11); native sidecar stays open (OQ-P3-07). Then implement test/support/fake-agentos.ts with scripted start, alive, and stop outcomes and per-call recording.</action> <acceptance_criteria> - test/runtime/agentos-supervisor.test.ts asserts bounded restart, AGENTOS_CRASH_LOOP on the fifth consecutive failure, counter reset after the stable window, and timeout on a hung driver - No file in this plan imports or names an AgentOS package </acceptance_criteria> <verify> <automated>npx tsc -p tsconfig.json && node --test dist/test/runtime/agentos-supervisor.test.js</automated> <fails_when>non-zero exit, or the summary shows 0 passed</fails_when> </verify> <done>Supervisor green with bounded crash policy and an explicit unbound driver gap.</done> </task>

<task type="tdd"> <name>Task 2: Hardening profile and fail-closed verifier</name> <files>src/runtime/hardening.ts, test/runtime/hardening.test.ts</files> <read_first> - src/core/states.ts (freeze plus as const pattern for the frozen HARDENING_PROFILE) - src/core/policy.ts checkExecPolicy (decision-on-shape style to mirror for verifyInspect) - docs/integration/podman.md Q1 and Q2 (hardening flags and limits sourced from the man pages; OQ-P3-14 defaults to fail-closed verification) </read_first> <behavior> - Test: one failing case per D-51 property (privileged, rootless, CapDrop/CapAdd, no-new-privileges, read-only root, tmpfs /tmp and /run, PID 512, memory 1 GiB, CPU 2, network none, digest, mount set, socket path) - Test: conforming inspect yields an empty list; missing or unknown field fails closed - Test titles cite RT-01 </behavior> <action>Write the failing tests first per behavior, then implement HARDENING_PROFILE and verifyInspect(profile, inspect) in src/runtime/hardening.ts per D-51: not privileged; rootless from info; CapDrop exactly ["ALL"] with empty CapAdd; no-new-privileges set; read-only root with tmpfs at /tmp and /run; PID 512, memory 1 GiB, CPU 2 (Claude-discretion defaults held in this one constant); network none; image digest equals the pinned digest; mount set exactly the canonical workspace root and the realm state dir with no mount path being or containing docker.sock or podman.sock. Returns the failed property names, empty on conformance; any unknown or missing field counts as a failure. Freeze the profile.</action> <acceptance_criteria> - test/runtime/hardening.test.ts covers every D-51 property plus the conforming-empty and missing-fails-closed cases - No capability beyond the ALL drop is verified (per the D-51 no-capability-verified rule) </acceptance_criteria> <verify> <automated>npx tsc -p tsconfig.json && node --test dist/test/runtime/hardening.test.js</automated> <fails_when>non-zero exit, or the summary shows 0 passed</fails_when> </verify> <done>Verifier green with fail-closed semantics on every property.</done> </task>

</tasks>

<threat_model>

Trust Boundaries ​

BoundaryDescription
driver -> supervisorUntrusted liveness answers cross into restart policy; a lying alive cannot suppress the timeout race
libpod inspect -> verifierUntrusted container description crosses into the conformance decision; missing fields must fail, never default to safe

STRIDE Threat Register ​

Threat IDCategoryComponentSeverityDispositionMitigation Plan
T-03-16D (Denial of Service)src/runtime/agentos.tsmediummitigateBounded backoff with 5-attempt cap then AGENTOS_CRASH_LOOP; every driver call raced against a timeout so a hung driver cannot hang supervision (QUAL-01)
T-03-17T (Tampering)src/runtime/hardening.tshighmitigateverifyInspect fails closed on any unknown or missing field; digest must equal the pinned digest; socket-bearing mounts rejected by path rule
T-03-18E (Elevation of Privilege)src/runtime/hardening.tshighmitigatePrivileged, capability, no-new-privileges, read-only, and user checks all enforced; network none so no egress path exists
</threat_model>

<verification> npx tsc -p tsconfig.json && node --test dist/test/runtime/agentos-supervisor.test.js dist/test/runtime/hardening.test.js; grep both test files for RT-04 and RT-01. </verification>

<success_criteria> Crash loop bounded with stable-window reset, and every hardening property verified fail-closed. </success_criteria>

<output> Create .planning/phases/03-container-runtime-and-bridges/03-07-SUMMARY.md when done </output>

AGPL-3.0-only. Copyright (C) 2026 Spectrum Web Co/swcstudiospace.