# Architecture ## Layers ```text Natural-language requirement │ ▼ Codex / Agent Skill ── scenario + oracle + safety gates │ ▼ CLI machine API ── install, ephemeral patch, process capture, reports │ ▼ DSH bundle ├─ dsh-tool-chaos deterministic runtime adapter └─ dsh-tool-chaos/reporter JSONL evidence adapter │ ▼ DSH tool pipeline pre-execute → guard → execute → post-execute → finalizer → result ``` ## Package boundaries - `options.ts`: serializable public config and strict direct-call validation. - `core.ts`: stable stringify, glob matcher, hash sampling, schedule counters, decisions. - `engine.ts`: runtime-independent public subpath. - `runtime.ts`: three DSH event adapters and cooperative cancellation. - `events.ts`: shared Cordis event augmentation. - `reporter.ts`: prefixed JSONL projection. - `bin/`: process orchestration and report generation. - `plugins/`: Codex plugin and Agent Skill. ## Why the reporter is separate The main bundle remains silent and reusable. A dedicated reporter row can be disabled in normal profiles and enabled only by an experiment overlay. This gives the CLI stable evidence without coupling to a private DSH logging backend. ## Patch strategy The installed bundle inserts both rows with safe defaults. The CLI uses DSH `--patch` overlays for experiments, so the scenario is applied after profile/user layers and disappears with the process. It never permanently writes active rules into a profile. ## Cancellation strategy For `abort`: 1. capture upstream signal; 2. create a derived controller; 3. forward upstream cancellation; 4. arm deterministic deadline; 5. replace `exec.signal` only for delegated execution; 6. await the delegated promise; 7. map this plugin's deadline to `CHAOS_ABORTED`; 8. clear timer/listener and restore upstream signal in `finally`. The plugin cannot hard-kill same-process work that ignores `AbortSignal`; that is the documented cooperative boundary.