# Autonomy P0 — Chaos Scaffold Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use /ship (recommended) or /executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Build the `test/chaos/` fault-injection harness + chaos adapter so every later autonomy phase has an executable acceptance gate.

**Architecture:** A fault-injecting wrapper (`chaos.sh`) implements `spec/WRAPPER-CONTRACT.md` and misbehaves on command via env vars; a scenario runner builds throwaway fixture repos, launches `runplan` against them, and asserts journal outcomes. Canonical spec: `spec/CHAOS-SUITE.md` — implement per spec; this doc only sequences it.

**Tech Stack:** bash, Node (existing engine), git fixture repos.

**Sequencing:** First plan of the autonomy epic (`docs/plans/2026-07-07-design-gap-handoff.md` PART IV P0). Nothing merges after this phase without chaos green for the features it claims. Read `spec/IMPLEMENTER-NOTES.md` FIRST.

---

## Wave Plan

| Wave | Tasks | Files touched | Safe to parallelize? |
|------|-------|---------------|----------------------|
| 1 | Task 1, Task 2 | test/chaos/wrappers/chaos.sh · test/chaos/run.sh, test/chaos/lib.sh | ✅ no overlap |
| 2 | Task 3, Task 4 | presets/adapters.json · test/chaos/scenarios/ | ✅ no overlap |
| 3 | Task 5 | run-tests.sh | single task |

---

### Task 1: Chaos wrapper (fault-injecting adapter)

**Wave:** 1 · **Blocks:** Task 3, Task 4 · **Blocked by:** —

**Files:**
- Create: `test/chaos/wrappers/chaos.sh` — wrapper-contract-conformant adapter whose behavior is driven by `CHAOS_*` env vars.

**Contract:** `spec/CHAOS-SUITE.md` § chaos-wrapper vocabulary is canonical (fault vocabulary, env var names, event emission). Output MUST validate against `spec/events.schema.json`. Honors exit-code contract in `spec/WRAPPER-CONTRACT.md` (incl. exit 75, timeout semantics).

**Behavior:** No `CHAOS_*` vars set → behaves as a trivially-succeeding agent (makes a real commit in the task worktree, emits valid events, exits 0). Each vocabulary entry (hang, orphan-forker, garbage-json, giant-output, exit-0-no-commit, gate-red diff, crash mid-events, quota error, …) reproducible deterministically from env.

**Acceptance (one executable check):**
- Run: `bash test/chaos/wrappers/chaos.sh </dev/null` inside a fixture worktree with no fault vars
- Expected: exit 0, schema-valid event stream, one commit created

- [ ] Write conformance test (schema-validate emitted events per fault mode)
- [ ] Implement per spec vocabulary
- [ ] Run acceptance → expected output above
- [ ] Commit

### Task 2: Scenario runner + fixture builder

**Wave:** 1 · **Blocks:** Task 4 · **Blocked by:** —

**Files:**
- Create: `test/chaos/run.sh` — CLI: `run.sh <scenario>|--all`; builds fixture repo, launches `runplan`, evaluates assertions, prints PASS/FAIL per assertion.
- Create: `test/chaos/lib.sh` — fixture-repo builder (init git repo, seed plan jsonl, runstate dirs) + journal assertion helpers.

**Contract:** `spec/CHAOS-SUITE.md` § scenario format + § assertions is canonical. Scenario = declarative file under `test/chaos/scenarios/`. Assertions read the slug journal + git state ONLY (no engine internals). Feature-gated assertions (phase map in spec) must be skippable via an env/flag so P0 can run the suite before later features exist — skipped ≠ passed; runner prints the skip reason.

**Behavior:** Fixture repos under a temp dir, cleaned on success, preserved + path printed on failure. Non-zero exit iff any non-skipped assertion fails. Fail-closed: unknown scenario key → error, never ignore.

**Acceptance:**
- Run: `bash test/chaos/run.sh --list`
- Expected: lists scenarios with their gating phase, exit 0

- [ ] Write runner self-test (malformed scenario file → error; fixture builder produces valid git repo)
- [ ] Implement
- [ ] Run acceptance
- [ ] Commit

### Task 3: Register `chaos` preset

**Wave:** 2 · **Blocks:** Task 4 · **Blocked by:** Task 1

**Files:**
- Modify: `presets/adapters.json` — add `chaos` adapter entry pointing at `test/chaos/wrappers/chaos.sh`.

**Contract:** Entry shape per existing adapters in `presets/adapters.json`; dialect value must exist in `spec/events.schema.json` enum (I7). `presets/_validate.mjs` green.

**Behavior:** Per `spec/IMPLEMENTER-NOTES.md` working protocol: chaos doubles as the token-free dev adapter — any plan dry-exercisable end-to-end via `--preset chaos`.

**Acceptance:**
- Run: `node presets/_validate.mjs`
- Expected: exit 0 including new entry

- [ ] Add entry, validate, commit

### Task 4: P0-runnable scenarios (existing-engine coverage)

**Wave:** 2 · **Blocks:** Task 5 · **Blocked by:** Task 1, Task 2

**Files:**
- Create: `test/chaos/scenarios/` — ALL scenario files C1–C15 authored per `spec/CHAOS-SUITE.md` (complete list in spec — no subset), with phase-gated assertions marked per the spec's phase gate map.

**Contract:** Scenario IDs, faults, and assertion sets verbatim from `spec/CHAOS-SUITE.md`. Scenarios whose asserted features already exist in the engine (quarantine ladder, crash-resume, lock refusal, exit-4 semantics) MUST pass now; later-phase assertions marked gated.

**Acceptance:**
- Run: `bash test/chaos/run.sh --all`
- Expected: every currently-ungated assertion PASS; gated ones reported SKIP with phase label; exit 0

- [ ] Author all scenario files from spec (spec is the test source — never derive from engine behavior)
- [ ] Run acceptance
- [ ] Commit

### Task 5: Wire into test suite

**Wave:** 3 · **Blocks:** — · **Blocked by:** Task 4

**Files:**
- Modify: `run-tests.sh` — append chaos suite invocation (`test/chaos/run.sh --all`).

**Acceptance:**
- Run: `bash run-tests.sh`
- Expected: full suite green incl. chaos section, zero unexplained warnings

- [ ] Wire, run full suite, commit
