clean-room-skill 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +2 -3
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/README.md +96 -522
  5. package/agents/clean-implementer-verifier-shell.md +1 -1
  6. package/agents/clean-qa-editor.md +2 -2
  7. package/bin/install.js +786 -62
  8. package/bin/verify.sh +5 -0
  9. package/docs/ARCHITECTURE.md +4 -2
  10. package/docs/REFERENCE.md +318 -0
  11. package/examples/codex/.codex/agents/clean-qa-editor.toml +2 -2
  12. package/hooks/agent3-verification-runner.py +255 -5
  13. package/hooks/clean-room-hook.py +38 -7
  14. package/hooks/clean_room_paths.py +2 -0
  15. package/hooks/deny-clean-room-shell.py +5 -1
  16. package/hooks/validate-json-schema.py +2 -2
  17. package/lib/dir-lock.cjs +142 -0
  18. package/lib/doctor.cjs +109 -15
  19. package/lib/hooks.cjs +26 -0
  20. package/lib/preflight.cjs +49 -0
  21. package/lib/run.cjs +278 -36
  22. package/package.json +7 -1
  23. package/plugin.json +1 -1
  24. package/skills/clean-room/SKILL.md +3 -2
  25. package/skills/clean-room/assets/clean-run-context.schema.json +78 -0
  26. package/skills/clean-room/assets/implementation-plan.schema.json +33 -0
  27. package/skills/clean-room/assets/init-config.schema.json +78 -0
  28. package/skills/clean-room/assets/preflight-goal.schema.json +78 -0
  29. package/skills/clean-room/examples/contaminated-side/init-config.json +12 -0
  30. package/skills/clean-room/examples/contaminated-side/preflight-goal.json +12 -0
  31. package/skills/clean-room/examples/contaminated-side/task-manifest.json +2 -2
  32. package/skills/clean-room/examples/minimal-spec-package/clean-run-context.json +12 -0
  33. package/skills/clean-room/examples/minimal-spec-package/implementation-plan.json +12 -2
  34. package/skills/clean-room/references/PROCESS.md +3 -1
  35. package/skills/clean-room/references/SPEC-SCHEMA.md +5 -1
  36. package/skills/init/SKILL.md +3 -1
  37. package/templates/docker/README.md +25 -0
  38. package/templates/docker/compose.clean-room.yml +21 -0
  39. package/templates/docker/examples/go-test.json +18 -0
  40. package/templates/docker/examples/node-typescript.json +17 -0
  41. package/templates/docker/examples/python-pytest.json +18 -0
  42. package/templates/docker/examples/rust-cargo.json +17 -0
  43. package/templates/docker/profiles/go126.Dockerfile +3 -0
  44. package/templates/docker/profiles/node22.Dockerfile +3 -0
  45. package/templates/docker/profiles/python312.Dockerfile +3 -0
  46. package/templates/docker/profiles/rust-stable.Dockerfile +3 -0
package/README.md CHANGED
@@ -1,276 +1,87 @@
1
1
  # Clean Room
2
2
 
3
- Clean-room workflow for turning authorized source analysis into clean specs and clean implementation code.
3
+ Clean Room is an agent workflow for turning authorized source analysis into clean behavioral specs, clean implementation plans, and clean destination code.
4
4
 
5
- This is a POC based on the ideas presented here:
5
+ It is a POC based on ideas from [malus.sh](https://malus.sh/blog.html). It is an engineering risk-reduction workflow, not legal advice, and it does not create a legal safe harbor.
6
6
 
7
- https://malus.sh/blog.html
7
+ ## What This Is / Does
8
8
 
9
- This plugin packages the `clean-room`, `preflight`, `attended`, `unattended`, `resume`, `start-over`, and `refocus` skills, Claude role agents, Codex role-agent templates, JSON schemas, examples, and hook guardrails for separating contaminated source analysis from clean behavioral specification and clean implementation work.
9
+ Use this package when you need documented separation between source-reading work and clean implementation work.
10
10
 
11
- It is an engineering risk-reduction workflow. It is not legal advice and does not create a legal safe harbor.
11
+ It installs:
12
12
 
13
- ## Use This For
13
+ - Clean-room skills for Codex, Claude Code, and other agent runtime layouts.
14
+ - Role-agent prompts for contaminated analysis, clean planning, and clean implementation.
15
+ - JSON schemas and examples for durable workflow artifacts.
16
+ - Hook guardrails that help keep source material out of clean artifacts.
17
+ - A small CLI for runtime installation, bootstrap folders, preflight contracts, hook smoke tests, and the bounded inner clean-room runner.
14
18
 
15
- - Authorized source-to-implementation migration work.
16
- - Clean behavioral specifications for compatibility work.
17
- - Implementation plans, clean code changes, verification reports, QC reports, open questions, and test plans.
18
- - Documented separation between source-reading roles, clean planning roles, and clean implementation roles.
19
+ The workflow creates clean behavioral spec packages and clean implementation outputs. It does not generate replacement code directly from source.
19
20
 
20
- ## Threat Model And Non-Goals
21
+ Core boundary:
21
22
 
22
- This workflow protects against:
23
+ - Contaminated roles may read authorized source and write contaminated artifacts.
24
+ - Source-denied roles may read only clean artifacts, implementation roots, schemas, and approved public/reference roots.
25
+ - Clean implementation code is written only under the clean implementation root.
26
+ - Raw source, source paths, private identifiers, raw diffs, copied comments, and source-shaped pseudocode must not cross into clean handoff artifacts.
23
27
 
24
- - accidental source expression crossing into clean specs or clean implementation code
25
- - clean agents reading contaminated roots
26
- - contaminated agents writing clean artifacts
27
- - clean or contaminated agents writing outside their role artifact or implementation roots
28
- - unbounded unattended controller loops
28
+ For the full boundary model, see [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md). For CLI and troubleshooting details, see [docs/REFERENCE.md](docs/REFERENCE.md).
29
29
 
30
- It does not protect against:
30
+ ## How To Install
31
31
 
32
- - hostile local users
33
- - compromised host tooling
34
- - shared model context outside role isolation
35
- - legal conclusions
36
- - side channels through filenames, timing, or retained chat context
32
+ Requires Node.js `>=22`.
37
33
 
38
- ## Install
39
-
40
- ### Installation Model
41
-
42
- The `clean-room-skill` npm package has two separate layers:
43
-
44
- * **Agent/runtime install**: installs clean-room skills, agent prompts, and verification hooks *into* your local or global agent runtimes (e.g., Claude Code, Codex, or Cursor). This is the default command behavior.
45
- * **Run bootstrap**: `clean-room-skill init` creates neutral external output folders and a clean-safe repo stub for a specific clean-room run. It does not install hooks, does not write active run artifacts, and does not replace the runtime skill workflow.
46
-
47
- * **Global Installation (Recommended)**: Integrates the clean-room workflow globally into your agent configuration directories (e.g., `~/.claude/` or `~/.codex/`).
48
- * **Local Installation**: Places the plugin directly inside your current repository's workspace (e.g., `.claude/` or `.codex/`).
49
-
50
- Preferred direct installer:
34
+ Preferred interactive install:
51
35
 
52
36
  ```bash
53
37
  npx clean-room-skill@latest
54
38
  ```
55
39
 
56
- The installer prompts for runtime and scope when no flags are supplied. For non-interactive installs, pass the runtime and scope explicitly:
40
+ Non-interactive installs:
57
41
 
58
42
  ```bash
59
43
  npx clean-room-skill@latest --codex --global --yes
60
44
  npx clean-room-skill@latest --claude --global --yes
61
- npx clean-room-skill@latest --antigravity --global --yes
62
- npx clean-room-skill@latest --opencode --global --yes
63
- npx clean-room-skill@latest --cursor --global --yes
64
45
  npx clean-room-skill@latest --all --global --yes
65
46
  ```
66
47
 
67
- Runtime support tiers:
68
-
69
- - Verified: Codex and Claude Code. These installs have tested skill, agent, hook registration, and hook payload behavior.
70
- - Layout-only / experimental: Antigravity, Gemini, OpenCode, Kilo, Cursor, GitHub Copilot, Windsurf, Augment, Trae, Qwen Code, Hermes Agent, and CodeBuddy. The installer writes files to expected layout roots, but this repo does not verify that those hosts load the files or enforce clean-room behavior.
71
-
72
- Runtime install roots:
73
-
74
- - Codex global: `CODEX_HOME` or `~/.codex`
75
- - Claude Code global: `CLAUDE_CONFIG_DIR` or `~/.claude`
76
- - Antigravity CLI global plugin: `ANTIGRAVITY_PLUGIN_DIR`, `ANTIGRAVITY_CLI_PLUGIN_DIR`, `ANTIGRAVITY_CONFIG_DIR/plugins/clean-room`, or `~/.gemini/antigravity-cli/plugins/clean-room`
77
- - Gemini global legacy/enterprise: `GEMINI_CONFIG_DIR` or `~/.gemini`
78
- - OpenCode global: `OPENCODE_CONFIG_DIR`, `OPENCODE_CONFIG`, `XDG_CONFIG_HOME/opencode`, or `~/.config/opencode`
79
- - Kilo global: `KILO_CONFIG_DIR`, `KILO_CONFIG`, `XDG_CONFIG_HOME/kilo`, or `~/.config/kilo`
80
- - Cursor global: `CURSOR_CONFIG_DIR` or `~/.cursor`
81
- - GitHub Copilot global: `COPILOT_CONFIG_DIR` or `~/.copilot`
82
- - Windsurf global: `WINDSURF_CONFIG_DIR` or `~/.codeium/windsurf`
83
- - Augment global: `AUGMENT_CONFIG_DIR` or `~/.augment`
84
- - Trae global: `TRAE_CONFIG_DIR` or `~/.trae`
85
- - Qwen Code global: `QWEN_CONFIG_DIR` or `~/.qwen`
86
- - Hermes Agent global: `HERMES_HOME` or `~/.hermes`
87
- - CodeBuddy global: `CODEBUDDY_CONFIG_DIR` or `~/.codebuddy`
88
-
89
- Local installs are available through `--local` using each runtime's project config directory. Antigravity local installs write `.agents/plugins/clean-room/`. Claude local, Gemini, **OpenCode, and Kilo** receive generated command wrappers (e.g. `clean-room-clean-room.md`, `clean-room-init.md`); native skill runtimes receive `SKILL.md` directories. Gemini CLI support is legacy/enterprise compatibility because Google is transitioning consumer Gemini CLI users to Antigravity CLI on June 18, 2026. Cline is not included because it has no verified clean-room skill or command layout.
90
-
91
48
  Hook modes:
92
49
 
93
- - `--hooks=safe`: default. Copies hooks and registers a wrapper that no-ops unless `CLEAN_ROOM_HOOK_ENFORCE=1` or clean-room environment variables are present. This is compatibility-only; use `--hooks=strict` for dedicated Codex or Claude clean-room homes.
94
- - `--hooks=copy-only` or `--no-hooks`: copies hook files but does not register Codex or Claude hook config.
95
- - `--hooks=strict`: registers fail-closed hooks for dedicated clean-room homes. Strict mode is supported only for Codex and Claude Code because other runtime hook payloads are not verified. Antigravity receives hook scripts in the plugin directory, but the generated plugin manifest does not enable them until an Antigravity-specific hook payload adapter exists.
96
-
97
- ### Installer CLI Reference
98
-
99
- Execute the installer via `npx` with the following parameters:
100
-
101
- ```bash
102
- npx clean-room-skill@latest [runtimes] [scope] [options]
103
- ```
104
-
105
- | Parameter | Type | Description |
106
- | --- | --- | --- |
107
- | `--claude` / `--codex` | Runtime | Selects the target agent runtime. (Supports `--all` for all runtimes) |
108
- | `--global` / `--local` | Scope | Installs to the global user home config or the local project directory. |
109
- | `--hooks=<mode>` | Option | Sets hook mode: `safe` (default, opt-in), `strict` (fail-closed), or `copy-only`. |
110
- | `--no-hooks` | Option | Alias for `--hooks=copy-only`. Copies scripts without registering hooks. |
111
- | `--config-dir <path>` | Option | Overrides the target root directory (only for single-runtime installs). |
112
- | `--dry-run` | Option | Performs a trial run, logging actions without writing files. |
113
- | `--uninstall` | Option | Removes all manifest-managed files and hook registrations. |
114
- | `--yes` | Option | Non-interactive mode. Automatically accepts overwriting known files. |
115
-
116
- Useful maintenance commands:
117
-
118
- ```bash
119
- npx clean-room-skill@latest --dry-run --all --global
120
- npx clean-room-skill@latest --codex --global --uninstall --yes
121
- npx clean-room-skill@latest doctor --runtime codex --hooks=safe
122
- npx clean-room-skill@latest preflight --template --output ~/Documents/CleanRoom/task-1234abcd/contaminated/preflight-goal.json
123
- npx clean-room-skill@latest run --task-manifest ~/Documents/CleanRoom/task-1234abcd/contaminated/task-manifest.json --agent-commands ./agent-commands.json --dry-run
124
- ```
125
-
126
- The installer serializes install and uninstall per target root with `.clean-room-install.lock`. It writes `clean-room-install-manifest.json` into each target root, records `phase: "installing"` before hook config mutation, and switches to `phase: "complete"` only after hook config succeeds. Reinstalling replaces only manifest-managed files automatically. Before each write or removal, the installer rechecks the file state observed during planning; late managed-file changes are backed up under `clean-room-patches/<timestamp>/` before replacement or removal. Unknown existing files are not overwritten in non-interactive mode.
50
+ - `--hooks=safe`: default. Hooks are installed but enforce only during clean-room role sessions with the required environment.
51
+ - `--hooks=strict`: fail-closed hook mode for dedicated Codex or Claude clean-room homes.
52
+ - `--hooks=copy-only` or `--no-hooks`: copy hook files without registering runtime hook config.
127
53
 
128
- ### Bootstrap CLI Reference
54
+ Verified runtimes are Codex and Claude Code. Other runtime layouts are installed on a best-effort basis. See [docs/REFERENCE.md](docs/REFERENCE.md#runtime-support) for the full support table and install roots.
129
55
 
130
- Use `init` to prepare a clean implementation repository and external run folder before starting the agent workflow:
56
+ Marketplace install is also supported.
131
57
 
132
- ```bash
133
- npx clean-room-skill@latest init
134
- npx clean-room-skill@latest init --target-dir . --target-profile speckit-feature-folder
135
- npx clean-room-skill@latest init --artifact-base ~/Documents/CleanRoom --task-id task-1234abcd
136
- ```
137
-
138
- By default, `init` writes external run folders under `~/Documents/CleanRoom/<task-id>/` and creates:
139
-
140
- - `contaminated/`
141
- - `clean/`
142
- - `quarantine/`
143
- - `clean-room-bootstrap.json`
144
- - `.clean-room/README.md` in the target repository
145
-
146
- The repo-local `.clean-room/README.md` is clean-safe guidance only. Do not commit source roots, contaminated artifact paths, private identifiers, source-derived names, `preflight-goal.json`, `init-config.json`, `task-manifest.json`, or `clean-run-context.json` into the clean implementation repository.
147
-
148
- Without `--force`, bootstrap metadata and repo stub writes use atomic no-clobber creation. If another process creates the same task metadata or repo stub between the existence check and write, `init` aborts instead of overwriting it.
149
-
150
- `init` prints the output folder, repo stub path, safe hook install command, runtime start guidance, and uninstall command. It never registers strict hooks. For normal use, install safe hooks into your agent home:
151
-
152
- ```bash
153
- npx clean-room-skill@latest --codex --global --hooks=safe --yes
154
- npx clean-room-skill@latest --claude --global --hooks=safe --yes
155
- ```
156
-
157
- Use `--hooks=strict` only for dedicated clean-room Codex or Claude homes, not a daily agent profile.
158
-
159
- ### Preflight CLI Reference
160
-
161
- `clean-room-skill preflight` creates or validates the required Stage 0 goal contract. It is a small helper, not an interactive wizard.
162
-
163
- ```bash
164
- npx clean-room-skill@latest preflight --template --output ~/Documents/CleanRoom/task-1234abcd/contaminated/preflight-goal.json
165
- npx clean-room-skill@latest preflight --input ./preflight-goal.json --output ~/Documents/CleanRoom/task-1234abcd/contaminated/preflight-goal.json
166
- ```
167
-
168
- `--template` writes an attended draft with blocking `open_questions`. It rejects `--mode unattended`; unattended runs must use a completed input contract with `unattended_allowed_after_preflight: true`, finite `max_iterations`, and no `open_questions`.
169
-
170
- Keep `preflight-goal.json` in the contaminated/controller artifact root. Agent 2 and Agent 3 receive only clean-safe `goal_contract` fields and `code_hygiene_policy` through `clean-run-context.json`.
171
-
172
- ### Inner Loop Runner Reference
173
-
174
- `clean-room-skill run` executes the bounded inner clean-room loop for one approved spec slice. It is not the outer spec-development loop. The task manifest must already contain:
175
-
176
- - `preflight_goal_ref` and `preflight_goal_sha256`
177
- - the required `handoff_sequence`
178
- - `controller_policy.mode: "unattended"`
179
- - `controller_policy.max_iterations`
180
- - `controller_policy.max_units_per_iteration: 1`
181
- - `loop_context.child_loop_kind: "clean-room"`
182
- - `loop_context.approved_scope_refs` naming the selected unit or units
183
-
184
- The runner locks the contaminated artifact root with `.clean-room-run.lock`, reloads durable artifacts each iteration, validates schema/leakage/handoff state, selects at most one pending or gap unit inside `approved_scope_refs`, spawns configured role commands with `shell: false`, and writes:
185
-
186
- - `controller-run-ledger.json` in the contaminated artifact root
187
- - `clean-room-result.json` in the contaminated artifact root
188
-
189
- CLI:
190
-
191
- ```bash
192
- npx clean-room-skill@latest run \
193
- --task-manifest ~/Documents/CleanRoom/task-1234abcd/contaminated/task-manifest.json \
194
- --agent-commands ./agent-commands.json \
195
- --max-iterations 3
196
- ```
197
-
198
- Options:
199
-
200
- | Option | Description |
201
- | --- | --- |
202
- | `--task-manifest <path>` | Required path to `task-manifest.json`. |
203
- | `--agent-commands <path>` | Required role command adapter JSON unless `--dry-run` is set. |
204
- | `--max-iterations <n>` | May only lower the manifest and `loop_context` cap. |
205
- | `--once` | Runs at most one inner-loop iteration. |
206
- | `--dry-run` | Validates, selects, and prints the selected unit without writing state or spawning agents. |
207
- | `--schema-dir <path>` | Overrides bundled schema directory. |
208
- | `--python <path>` | Python executable for validation hooks. Defaults to `python3`. |
209
-
210
- Agent command adapter shape:
211
-
212
- ```json
213
- {
214
- "version": 1,
215
- "stages": [
216
- {
217
- "phase": "contaminated-analysis",
218
- "role": "contaminated-source-analyst",
219
- "cwd": "/absolute/contaminated/workspace",
220
- "argv": ["agent-cli", "--fresh-session", "--role", "source-analyst"],
221
- "timeout_ms": 600000
222
- },
223
- {
224
- "phase": "contaminated-coverage-verify",
225
- "role": "contaminated-manager-verifier",
226
- "cwd": "/absolute/contaminated/workspace",
227
- "argv": ["agent-cli", "--fresh-session", "--role", "manager"]
228
- }
229
- ]
230
- }
231
- ```
232
-
233
- Supported phases are `contaminated-analysis`, `sanitize-handoff`, `clean-plan`, `clean-implement-qc`, and `contaminated-coverage-verify`. The coverage verification phase is required because Agent 3's terminal report is not enough to return to the outer loop. Adapter `env` values may add non-clean-room variables, but must not override `CLEAN_ROOM_*`.
234
-
235
- Marketplace install remains available.
236
-
237
- From Codex marketplace:
58
+ Codex:
238
59
 
239
60
  ```bash
240
61
  codex plugin marketplace add https://github.com/whit3rabbit/clean-room-skill.git
241
62
  ```
242
63
 
243
- Then install or enable `clean-room` from the `clean-room-skill` marketplace. Enable plugin hooks in trusted Codex config before relying on guardrails:
244
-
245
- ```toml
246
- [features]
247
- plugin_hooks = true
248
- ```
249
-
250
- From Claude Code marketplace:
64
+ Claude Code:
251
65
 
252
66
  ```text
253
67
  /plugin marketplace add https://github.com/whit3rabbit/clean-room-skill.git
254
68
  /plugin install clean-room@clean-room-skill
255
69
  ```
256
70
 
257
- Manual Antigravity install:
71
+ ## How To Run
258
72
 
259
- Clone this repository into your local plugins directory:
73
+ Optionally create neutral external run folders and a clean-safe repository stub:
260
74
 
261
75
  ```bash
262
- git clone https://github.com/whit3rabbit/clean-room-skill.git ~/.gemini/config/plugins/clean-room-skill
76
+ npx clean-room-skill@latest init
263
77
  ```
264
78
 
265
- Reload or restart the host if the plugin is not visible immediately.
266
-
267
- ## Invocation
79
+ The default artifact base is `~/Documents/CleanRoom/<task-id>/`. Keep active contaminated artifacts, clean artifacts, and clean implementation roots separate.
268
80
 
269
- In Claude Code, use the plugin skill namespace:
81
+ In Claude Code, invoke skills with the plugin namespace:
270
82
 
271
83
  ```text
272
84
  /clean-room
273
- /clean-room:clean-room
274
85
  /clean-room:preflight
275
86
  /clean-room:init
276
87
  /clean-room:attended
@@ -280,352 +91,115 @@ In Claude Code, use the plugin skill namespace:
280
91
  /clean-room:refocus
281
92
  ```
282
93
 
283
- `/clean-room` and `/clean-room:clean-room` start the setup wizard. `/clean-room:preflight` creates or reviews the required goal contract. `/clean-room:init` records reusable setup preferences before a run starts or changes. `/clean-room:attended` starts the same wizard with attended review gates. `/clean-room:unattended` starts it with bounded unattended defaults: one unit per iteration, finite max iterations, and the configured safety stop conditions. `/clean-room:resume`, `/clean-room:start-over`, and `/clean-room:refocus` recover runs from durable artifacts. `clean-room-skill run` executes the bounded inner clean-room loop from a schema-valid `task-manifest.json` and a user-supplied agent command adapter.
284
-
285
- In Codex, invoke the `clean-room` plugin or one of its bundled skills explicitly with `@` or the skills UI. Do not rely on Claude-style `/clean-room:...` namespacing in Codex.
286
-
287
- ## Run Workflow
288
-
289
- Use this sequence for normal runs and recovery:
94
+ In Codex, invoke the `clean-room` plugin or bundled skills through `@` or the skills UI. Do not rely on Claude-style slash namespacing in Codex.
290
95
 
291
- | Situation | Claude command | Codex action | What the skill does |
292
- | --- | --- | --- | --- |
293
- | Record goal contract | `/clean-room:preflight` | Invoke `preflight` | Records end goal, target stack, dependency/license policy, exactness policy, feature policy, code hygiene, output policy, mode, and open questions. |
294
- | Initialize preferences | `/clean-room:init` | Invoke `init` | Records artifact roots, target profile, model preferences, clean-safe rules, and contaminated-only rules. Defaults artifacts to `~/Documents/CleanRoom/<task-id>/`. |
295
- | New run, default review gates | `/clean-room` or `/clean-room:attended` | Invoke `clean-room` or `attended` | Confirms authorization, separated roots, target profile, and starts the scope gate in attended mode. |
296
- | New bounded unattended run | `/clean-room:unattended` | Invoke `unattended` | Starts from the same scope gate, then records finite unattended bounds and stop conditions. |
297
- | Continue an interrupted run | `/clean-room:resume` | Invoke `resume` | Reloads `task-manifest.json`, the initialization snapshot, ledgers, `clean-run-context.json`, `qc-report.json`, handoff artifacts, and abstract delta tickets, then continues from the earliest incomplete gate. |
298
- | Restart a bad or obsolete run | `/clean-room:start-over` | Invoke `start-over` | Requires explicit confirmation, archives or quarantines current artifacts without deletion, then returns to the scope gate with a fresh `task_id`. |
299
- | Correct drift without changing scope | `/clean-room:refocus` | Invoke `refocus` | Audits current artifacts against declared scope and routes Agent 0 back to missed gates without expanding scope. |
300
-
301
- Before starting, prepare separate paths for source, contaminated artifacts, clean artifacts, optional clean reference docs, and quarantine. The default artifact base is `~/Documents/CleanRoom/<task-id>/`; if no explicitly approved neutral task ID is provided, use `task-` plus 8 lowercase hex characters. For recovery, provide the existing `task-manifest.json` or the artifact roots so the skill can reload durable state. Prior chat history is not task state.
302
-
303
- ## Quick Start: Onboarding your Codebase
304
-
305
- Once the skill package is installed in your runtime, follow these steps to initialize and execute a clean-room specification task.
306
-
307
- ### Optional: Bootstrap Run Folders
308
- Before invoking the runtime skill, you can create the external output folders and a clean-safe repository stub:
96
+ For unattended inner-loop execution from durable artifacts:
309
97
 
310
98
  ```bash
311
- npx clean-room-skill@latest init
312
- ```
313
-
314
- The command prints the output folder path to pass into the runtime skill. It does not write `preflight-goal.json`, `init-config.json`, `task-manifest.json`, or `clean-run-context.json`; those are still created or validated by the runtime workflow.
315
-
316
- ### Step 1: Record the Goal Contract
317
-
318
- Create or review `preflight-goal.json` before source discovery:
319
-
320
- ```text
321
- /clean-room:preflight
322
- ```
323
-
324
- The goal contract records what is being built, which target stack to use, what public behavior may be mirrored exactly, what must not be mirrored, feature add/remove policy, dependency/license policy, code hygiene, output roots, and attended/unattended mode. `preflight-goal.json` stays on the contaminated/controller side.
325
-
326
- ### Step 2: Initialize Workspace Preferences
327
- In your agent session (e.g., Claude Code), run the initialization subcommand:
328
-
329
- ```text
330
- /clean-room:init
331
- ```
332
-
333
- The agent will prompt you for setup choices and write an `init-config.json` file on the contaminated side (defaults to `~/Documents/CleanRoom/<task-id>/`). This file holds:
334
- * The paths to your **Authorized Source Roots** and **Clean Output Roots**.
335
- * Your output schema target profile (e.g., `speckit-feature-folder` or `openspec-delta`).
336
- * Model configurations and `clean_safe` or `contaminated_only` rules.
337
-
338
- *Note: For security, `init-config.json` should never be written to or committed within your clean workspace.*
339
-
340
- ### Step 3: Establish the Scope and Task Manifest
341
- Start the clean-room controller wizard:
342
-
343
- ```text
344
- /clean-room
345
- ```
346
-
347
- The agent (Agent 0) will:
348
- 1. Re-verify the path separation of your source, contaminated, and clean workspace roots.
349
- 2. Capture your authorization details and compile them into `task-manifest.json` with `preflight_goal_ref`, `preflight_goal_sha256`, and the required `handoff_sequence`.
350
- 3. Create `clean-run-context.json` with only clean-safe `goal_contract` fields and `code_hygiene_policy`.
351
- 4. If analyzing a complex scope, guide you to run the local source-index preflight to generate a `source-index.json` under your contaminated artifacts directory.
352
- 5. Decompose the workspace files into neutral, logical task units.
353
-
354
- ### Step 4: Run the Implementation Pipeline
355
- Choose either **Attended** (with explicit manual approval checkpoints) or **Unattended** mode to begin work on the logical units:
356
-
357
- ```text
358
- /clean-room:attended
359
- /clean-room:unattended
99
+ npx clean-room-skill@latest run \
100
+ --task-manifest ~/Documents/CleanRoom/task-1234abcd/contaminated/task-manifest.json \
101
+ --agent-commands ./agent-commands.json \
102
+ --max-iterations 3
360
103
  ```
361
104
 
362
- * **Agent 1** analyzes the source files mapped to the active unit and writes neutral draft specs under `CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS`.
363
- * **Agent 1.5** sanitizes the drafts, ensuring no private symbols, code snippets, or structure are leaked.
364
- * **Agent 2** reads sanitized specs plus the clean destination foundation and writes `implementation-plan.json`.
365
- * **Agent 3** implements the selected spec slice under `CLEAN_ROOM_IMPLEMENTATION_ROOTS`, records verification status, and writes `implementation-report.json` plus `qc-report.json`.
105
+ The `run` command executes one bounded inner clean-room loop for an already approved spec slice. It does not replace the outer spec-development workflow.
366
106
 
367
- The outer loop evolves specs and chooses one approved spec slice. The inner clean-room loop completes that slice through sanitized handoff, implementation, QC, and contaminated-side coverage verification, then writes `clean-room-result.json` before returning to the outer loop. Agent 3's terminal report alone is not an inner-loop return.
368
-
369
- ## Operating Model
370
-
371
- Use separate workspaces, worktrees, repositories, or profiles for contaminated and clean work:
372
-
373
- - Contaminated source workspace: source-readable, read-only where practical.
374
- - Contaminated artifact workspace: preflight goals, init configs, source indexes, task manifests, coverage ledgers, evidence ledgers, draft specs, and abstract delta tickets. Configure as `CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS`.
375
- - Clean artifact workspace: clean run contexts, approved behavior specs, handoff packages, skeleton manifests, implementation plans, implementation reports, QC reports, and test plans. Configure as `CLEAN_ROOM_CLEAN_ROOTS`.
376
- - Clean implementation workspace: clean destination code and tests. Configure as `CLEAN_ROOM_IMPLEMENTATION_ROOTS`.
377
- - Clean allowed reference workspace: public documentation or destination constraints explicitly approved for clean and source-denied role reads.
378
-
379
- ### Path Naming Guards
380
-
381
- Artifact paths must be neutral. Do not name task IDs, clean roots, implementation roots, or contaminated artifact roots after private source folders or private code identifiers.
382
-
383
- When no explicitly approved neutral task ID is provided, the controller should generate `task-` plus 8 lowercase hex characters under `~/Documents/CleanRoom/`. The initialization wizard and `require-clean-room-env.py` preflight reject clean, implementation, or contaminated artifact paths that contain source root basenames or meaningful non-generic tokens from those basenames. Guard errors avoid printing the private source name.
384
-
385
- Prompt instructions alone are not a boundary. Use path separation, role-specific sessions, hook checks, schema validation, and artifact quarantine.
386
-
387
- ## Separation Diagram
107
+ ## Typical Workflow
388
108
 
389
109
  ![Clean Room Architecture](assets/clean-room-arch.svg)
390
110
 
391
- For a detailed breakdown of the flowchart representation, agent responsibilities, environment boundaries, and guardrail scripts, see the [Clean Room Architecture Documentation](docs/ARCHITECTURE.md).
392
-
393
- ## Roles
111
+ 1. Record the goal contract.
112
+ Use `/clean-room:preflight` or `clean-room-skill preflight` before source discovery. This creates or validates `preflight-goal.json` on the contaminated/controller side.
394
113
 
395
- - Agent 0 / `contaminated-manager-verifier`: consumes contaminated source indexes, decomposes scope into logical batches, tracks coverage, verifies clean specs and terminal implementation reports against source, and influences Agent 2/3 only through durable sanitized artifacts.
396
- - Agent 1 / `contaminated-source-analyst`: reads authorized source and writes neutral draft task/spec material with evidence references, not code.
397
- - Agent 1.5 / `contaminated-handoff-sanitizer`: reviews Agent 1 drafts from a fresh source-denied contaminated context and approves only sanitized handoff candidates.
398
- - Agent 2 / `clean-architect`: reads clean artifacts and the clean implementation foundation, then writes `implementation-plan.json` with relative destination paths, tests, constraints, risks, and argv-array verification commands.
399
- - Agent 3 / `clean-qa-editor`: implements the selected spec-slice work under `CLEAN_ROOM_IMPLEMENTATION_ROOTS`, records verification status, maintains `qc-report.json`, and emits one terminal report for Agent 0 only when the assigned slice is complete, blocked, or quarantined.
114
+ 2. Initialize preferences.
115
+ Use `/clean-room:init` to record artifact roots, target profile, model preferences, clean-safe rules, and contaminated-only rules. The active `init-config.json` stays out of the clean implementation repository.
400
116
 
401
- Claude role agents are in `agents/`. Codex role-agent templates are in `examples/codex/.codex/agents/`.
117
+ 3. Start the controller.
118
+ Use `/clean-room` or `/clean-room:attended` for human review gates. Use `/clean-room:unattended` only after preflight allows bounded unattended work with finite iteration limits and no open questions.
402
119
 
403
- ## Required Environment
120
+ 4. Analyze and sanitize.
121
+ Source-reading roles produce neutral draft behavior specs. A source-denied sanitizer reviews handoff candidates before anything enters the clean domain.
404
122
 
405
- Set and pass this environment block into every clean-room role session before tool use:
123
+ 5. Plan and implement.
124
+ Clean roles read only approved clean artifacts and the clean destination foundation. Agent 2 writes `implementation-plan.json`; Agent 3 writes code/tests under the implementation root and reports under clean artifacts.
406
125
 
407
- ```text
408
- CLEAN_ROOM_ROLE
409
- CLEAN_ROOM_SOURCE_ROOTS
410
- CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS
411
- CLEAN_ROOM_CLEAN_ROOTS
412
- CLEAN_ROOM_IMPLEMENTATION_ROOTS
413
- CLEAN_ROOM_SCHEMA_DIR
414
- CLEAN_ROOM_ALLOWED_READ_ROOTS
415
- ```
126
+ 6. Verify and return.
127
+ Agent 0 performs contaminated-side coverage verification after Agent 3 reaches a terminal state, then writes `clean-room-result.json`.
416
128
 
417
- For clean roles, reads are deny-by-default. They may read only `CLEAN_ROOM_CLEAN_ROOTS`, `CLEAN_ROOM_IMPLEMENTATION_ROOTS`, `CLEAN_ROOM_SCHEMA_DIR`, and explicit public or destination constraint roots in `CLEAN_ROOM_ALLOWED_READ_ROOTS`. Agent 2 and Agent 3 receive `clean-run-context.json`, not the full `task-manifest.json` or `preflight-goal.json`. Agent 1.5 is also source-denied: it may read only assigned contaminated artifacts, `CLEAN_ROOM_SCHEMA_DIR`, and explicit public or destination constraint roots. Source roots in `CLEAN_ROOM_SOURCE_ROOTS` stay denied.
129
+ Use recovery skills instead of chat history:
418
130
 
419
- Agent 0 must not directly steer Agent 2 or Agent 3. Clean roles accept Agent 0 input only as schema-valid durable sanitized artifacts already present in the clean workspace. Direct chat instructions, progress feedback, priority changes, implementation hints, or corrective coaching from Agent 0 are out of bounds. Agent 3 reports back to Agent 0 only at the terminal report gate, never during an active implementation loop.
131
+ - `resume`: continue from durable artifacts.
132
+ - `start-over`: archive or quarantine current artifacts without deletion, then restart with a fresh neutral task id.
133
+ - `refocus`: audit current artifacts against declared scope without expanding scope.
420
134
 
421
- Writes are also deny-by-default. Agent 2 writes only clean artifacts under `CLEAN_ROOM_CLEAN_ROOTS`. Agent 3 writes reports under `CLEAN_ROOM_CLEAN_ROOTS` and code/tests only under `CLEAN_ROOM_IMPLEMENTATION_ROOTS`. Contaminated roles may write only under `CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS`. Source roots stay read-only for contaminated roles unless a separate, explicit process outside this plugin changes that policy.
135
+ ## Commands / Skills
422
136
 
423
- The environment preflight also audits root names. `CLEAN_ROOM_CLEAN_ROOTS`, `CLEAN_ROOM_IMPLEMENTATION_ROOTS`, and `CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS` must not contain source-derived project basenames or meaningful non-generic source-name tokens.
424
-
425
- Optional hook-only guardrail:
426
-
427
- ```text
428
- CLEAN_ROOM_PRIVATE_IDENTIFIER_DENYLIST
429
- ```
430
-
431
- Set it to path-separated, line-oriented files containing private source package, module, class, function, method, variable, constant, field, or other internal identifiers to reject from clean artifacts. Blank lines and `#` comments are ignored. Files are bounded to 1,000,000 bytes each, 20,000 total terms, and 512 characters per term. Keep those files outside clean/source-denied readable roots and do not paste their contents into model-visible artifacts.
137
+ | Command or skill | Use it for |
138
+ | --- | --- |
139
+ | `clean-room-skill init` | Create neutral external run folders and a clean-safe `.clean-room/README.md` stub. |
140
+ | `clean-room-skill preflight` | Create or validate the Stage 0 goal contract. |
141
+ | `clean-room-skill run` | Execute the bounded inner clean-room runner for one approved spec slice. |
142
+ | `clean-room-skill doctor` | Smoke test generated Codex or Claude hook registration. |
143
+ | `clean-room-skill status` | Report installed runtime version, drift, and hook state. |
144
+ | `clean-room-skill update` | Refresh installed runtime files without onboarding. |
145
+ | `clean-room` | Start the setup wizard for authorized clean-room work. |
146
+ | `preflight` | Record the required goal, policy, output, and controller-mode contract. |
147
+ | `init` | Record run preferences, separated roots, schema profile, and model policy. |
148
+ | `attended` | Start the wizard in attended mode with human review gates. |
149
+ | `unattended` | Start the wizard in bounded unattended mode with finite loop limits. |
150
+ | `resume` | Continue an existing run from durable artifacts. |
151
+ | `start-over` | Non-destructively archive or quarantine current artifacts and restart. |
152
+ | `refocus` | Audit a run and route it back to missed gates without adding scope. |
432
153
 
433
- Do not grant shell-style tools to Agent 0, Agent 1, Agent 1.5, Agent 2, or the default Agent 3 profile. If Agent 3 verification needs a terminal, use an isolated verification home with strict hooks and `CLEAN_ROOM_ALLOW_AGENT3_SHELL=1`, then invoke only the installed `agent3-verification-runner.py` from an implementation-root cwd. The runner reads argv-array verification commands from `implementation-plan.json`, applies a small allowlist, strips clean-room root env values, and executes with `shell=False`. Shell access still does not replace OS/profile isolation for untrusted test code.
154
+ Reference files:
434
155
 
435
- For multi-file scopes, run `skills/clean-room/scripts/build_source_index.py` as source-index controller preflight before clean-room role sessions. Store `source-index.json` under `CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS`, or pass `--contaminated-artifact-root` explicitly. The script refuses `--output` outside those roots. It is contaminated-only and must not be included in clean handoff packages or shown to Agent 1.5.
156
+ - [docs/REFERENCE.md](docs/REFERENCE.md): CLI flags, hook modes, troubleshooting, and local verification.
157
+ - [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md): operating model, roles, environment, guardrails, and flow details.
158
+ - [skills/clean-room/references/PROCESS.md](skills/clean-room/references/PROCESS.md): detailed clean-room process.
159
+ - [skills/clean-room/references/LEAKAGE-RULES.md](skills/clean-room/references/LEAKAGE-RULES.md): clean handoff rules.
436
160
 
437
- `source-index.json` includes bounded `skipped_entries` when the indexer intentionally or unavoidably omits input. Expected reasons include ignored directories, file count and byte caps, total byte caps, binary files, file stat/read errors, post-read size changes, files that changed during read, symlinks that resolve outside the source root, and directory traversal errors. After a global file or byte cap is reached, traversal is pruned and represented by an aggregate `remaining-files-skipped-after-limit:*` entry instead of enumerating the rest of a large tree. Treat skipped entries as coverage metadata: inspect them before deciding that a source index fully represents the authorized root.
161
+ ## Development
438
162
 
439
- Optional AST/indexing helpers are checked before the controller loop, not from clean-room role sessions:
163
+ Install dependencies:
440
164
 
441
165
  ```bash
442
- python3 skills/clean-room/scripts/clean_room_tool_manager.py --status
166
+ npm ci --ignore-scripts
443
167
  ```
444
168
 
445
- `--status` is stat-only by default. Use `--probe-tools` only when you want it to execute version commands for explicitly configured, cache-local, skill-local, system-path, or explicitly allowed project tools:
169
+ Run tests:
446
170
 
447
171
  ```bash
448
- python3 skills/clean-room/scripts/clean_room_tool_manager.py --status --probe-tools
172
+ npm test
449
173
  ```
450
174
 
451
- Tools discovered under `/opt/homebrew` or `/usr/local` remain stat-only during `--probe-tools` unless you also pass `--allow-user-toolchain-probes`.
452
-
453
- Local helper installs are explicit and strict SemVer version-pinned, and they write to `~/.cache/re-skills/clean-room-tools/`. Local npm-backed installs are serialized with a cache-local lock so concurrent setup processes do not mutate the shared npm prefix at the same time. Prefix creation failures, subprocess timeouts, and subprocess launch errors are reported as structured JSON error facts:
175
+ Run installer tests only:
454
176
 
455
177
  ```bash
456
- python3 skills/clean-room/scripts/clean_room_tool_manager.py --install-local ast-grep --version <exact-version>
178
+ npm run test:install
457
179
  ```
458
180
 
459
- Target-project `.local/bin`, `.bin`, and `node_modules/.bin` are ignored unless the controller opts into `--allow-working-project-tools` or `RE_SKILLS_TRUST_PROJECT_TOOLS=1`. Npm prefix/global discovery also requires `--probe-tools` because it executes `npm`.
460
-
461
- ## Controller Modes
462
-
463
- Missing `controller_policy` means `attended`.
464
-
465
- - `attended`: agent zero pauses for human review at scope gate, clean handoff, terminal implementation deltas, blocked units, and final coverage.
466
- - `unattended`: agent zero runs a bounded inner clean-room loop only after preflight allows unattended mode with no open questions. It reloads durable artifacts each iteration, selects at most one pending or gap unit inside the approved spec slice, starts each role from fresh context with the required environment block, validates before advancing state, and stops on any configured safety or ambiguity condition.
467
-
468
- `task-manifest.json` may include `run_state` with the generation, start timestamp, previous generation reference, and restart reason. It may also include `initialization_snapshot`, which is the per-run copy of `init-config.json` preferences. Use durable artifacts to recover or start over without relying on chat history.
469
-
470
- Agent zero generates the durable tasklist as neutral `task-manifest.json` `units`. For larger scopes, it may use `source-index.json` recommended batches and record `source_index_ref` plus per-unit `source_index_refs`. Progress is tracked in `coverage-ledger.json`, `evidence-ledger.json`, terminal `implementation-report.json`, `qc-report.json`, and abstract delta tickets, not in prior chat history or live clean-role feedback.
471
-
472
- ## Recovery Entry Points
473
-
474
- - `resume`: reload durable artifacts, including referenced preflight goal and implementation plan/report when present, validate schema and leakage state, compare reusable init config against the manifest snapshot when present, and continue from the earliest incomplete gate using the recorded `controller_policy`.
475
- - `start-over`: require explicit confirmation, archive or quarantine the current artifact set without deletion, and restart from the preflight gate with a fresh `task_id`.
476
- - `refocus`: audit current artifacts against declared scope and preflight goal, then steer Agent 0 back to missed gates without expanding scope.
477
-
478
- ## Artifacts
479
-
480
- The schema contract lives in `skills/clean-room/assets/`:
481
-
482
- - `task-manifest.schema.json`
483
- - `preflight-goal.schema.json`
484
- - `init-config.schema.json`
485
- - `clean-run-context.schema.json`
486
- - `source-index.schema.json`
487
- - `coverage-ledger.schema.json`
488
- - `evidence-ledger.schema.json`
489
- - `handoff-package.schema.json`
490
- - `behavior-spec.schema.json`
491
- - `skeleton-manifest.schema.json`
492
- - `implementation-plan.schema.json`
493
- - `implementation-report.schema.json`
494
- - `clean-room-result.schema.json`
495
- - `qc-report.schema.json`
496
- - `contamination-incident.schema.json`
497
-
498
- Clean-side example artifact shapes are in `skills/clean-room/examples/minimal-spec-package/`. Verification commands in clean plans and reports are argv arrays, not shell strings. Contaminated-side controller examples, including `source-index.json`, are in `skills/clean-room/examples/contaminated-side/`. They are examples only, not outputs from a real source review.
499
-
500
- ## Workflow
501
-
502
- 1. Create or validate `preflight-goal.json`.
503
- 2. Record reusable setup preferences in `init-config.json` when requested, then snapshot effective choices into `task-manifest.json`.
504
- 3. Record authorization, scope, prohibited actions, evidence handling, preflight goal ref/hash, role root paths, and the required `handoff_sequence` in `task-manifest.json`.
505
- 4. Record the user's selected target profile, model policy, `run_state`, Agent 0-3 pipeline, and required Agent 1.5 sanitizer role in `task-manifest.json`.
506
- 5. Create `clean-run-context.json` for Agent 2 and Agent 3. It must record artifact-only coordination, clean-safe `goal_contract` fields, and `code_hygiene_policy`, and must not contain source roots, contaminated roots, source index refs, ledger paths, or full preflight/task manifests.
507
- 6. Run source index preflight when the source scope needs relationship-aware batching.
508
- 7. Decompose the source scope into bounded, neutral `task-manifest.json` units. One unit may map to one source-index batch or, for large files, one preflight segment.
509
- 8. Write contaminated-side draft behavior specs from observed behavior, public contracts, states, errors, invariants, and test scenarios.
510
- 9. Sanitize specs through Agent 1.5 using `skills/clean-room/references/LEAKAGE-RULES.md`; Agent 1.5 gets only a neutral brief and assigned draft paths.
511
- 10. Move only Agent 1.5-approved structured artifacts and `clean-run-context.json` into the clean workspace through `handoff-package.json`. Do not include `task-manifest.json`, `preflight-goal.json`, or `source-index.json`.
512
- 11. Agent 2 writes `implementation-plan.json` from clean specs, clean run context, target constraints, preflight code hygiene policy, and the clean implementation foundation.
513
- 12. Agent 3 implements work items under `CLEAN_ROOM_IMPLEMENTATION_ROOTS`, records verification status, and writes `implementation-report.json` without Agent 0 guidance. Run terminal verification only through the installed Agent 3 verification runner.
514
- 13. Produce or update `qc-report.json` with schema status, leakage status, gaps, code hygiene findings, and testability notes.
515
- 14. After Agent 3 reaches complete, blocked, or quarantined, Agent 0 verifies coverage from the contaminated side.
516
- 15. Write `clean-room-result.json` with `spec-slice-complete`, `spec-slice-blocked`, `spec-delta-required`, `contamination-suspected`, `iteration-limit-reached`, or `no-progress-detected`.
517
- 16. Repeat only through updated durable clean artifacts and abstract delta tickets. Do not steer an in-progress Agent 2 or Agent 3 session.
518
-
519
- ## Hook Guardrails
520
-
521
- Agent/tool hook scaffolding lives in `hooks/`. Security enforcement uses installer-generated Codex or Claude hook configs with absolute wrapper paths. Runtime plugin manifests do not declare static package hooks because cwd-relative hook commands are fragile.
522
-
523
- The generated hook configs route through `hooks/clean-room-hook.py`. In safe mode, the wrapper exits successfully unless `CLEAN_ROOM_HOOK_ENFORCE=1` or clean-room environment variables are present. Safe mode is compatibility-only until enforcement is enabled. In strict mode, it runs the configured checks immediately and fails closed when required role or path configuration is missing. Prefer strict mode for dedicated Codex or Claude clean-room homes.
524
-
525
- After install, run a smoke check:
181
+ Run the full local verifier:
526
182
 
527
183
  ```bash
528
- clean-room-skill doctor --runtime codex --hooks=strict
529
- ```
530
-
531
- Use `--runtime claude` for Claude Code, and add `--config-dir <path>` when testing an alternate config root.
532
-
533
- Expanded matcher coverage applies only to tool events the host runtime actually emits; do not treat matcher names as proof that an unsupported host tool is guarded.
534
-
535
- ### What Doctor Verifies
536
-
537
- `doctor` verifies that Codex or Claude hook config exists, contains four generated clean-room hooks, uses absolute wrapper paths, uses the requested safe or strict mode, and that smoke payloads fail for missing environment, source reads, source writes, shell use, and malformed post-write JSON. It also verifies that safe hooks no-op without clean-room env.
538
-
539
- It does not verify every runtime tool event, every matcher name emitted by the host, host-side hook enablement outside the config file, legal clean-room sufficiency, or full JSON Schema conformance. Treat it as an install smoke test, not a complete enforcement proof.
540
-
541
- - `clean-room-hook.py`: safe/strict dispatch wrapper for the policy checks below.
542
- - `agent3-verification-runner.py`: runs Agent 3 argv-array verification commands with `shell=False`, a small allowlist, sanitized env, bounded output, timeout, and root traversal checks.
543
- - `require-clean-room-env.py`: fails closed when required role and root environment is missing.
544
- - `deny-clean-room-shell.py`: denies shell-style tools for clean-room role sessions except installed Agent 3 verification-runner invocations explicitly allowed under implementation roots.
545
- - `deny-clean-source-read.py`: denies clean and source-denied role reads from source roots and unapproved paths.
546
- - `deny-contaminated-clean-write.py`: enforces role write roots. Agent 2 writes clean artifacts only, Agent 3 may write clean reports and implementation-root files, and contaminated roles write only under contaminated artifact roots.
547
- - `check-artifact-leakage.py`: scans clean artifacts, plus Agent 1.5 staged contaminated artifacts, for high-risk leakage markers, source-like identifiers, and optional private identifier denylist matches.
548
- - `validate-json-schema.py`: checks JSON syntax and common bundled clean-room schema constraints, including the conditional and bounded fields used by these schemas. Under clean roots, unknown JSON artifacts are rejected unless explicitly allowlisted through `CLEAN_ROOM_AUXILIARY_JSON_ALLOWLIST`. It is a lightweight guardrail, not a full JSON Schema 2020-12 validator.
549
- - `validate-handoff-package.py`: verifies handoff artifact paths stay under clean roots, do not point into source or contaminated roots, do not include `task-manifest.json`, `preflight-goal.json`, or `source-index.json`, and match declared `sha256` values.
550
-
551
- These scripts are guardrail and audit support. They are not a substitute for separate workspaces and role isolation.
552
-
553
- For release-quality schema assurance, run a full JSON Schema validator in addition to the bundled lightweight hook.
554
-
555
- ## Troubleshooting
556
-
557
- | Symptom | Likely cause | Recovery |
558
- | --- | --- | --- |
559
- | `python3 is required to install clean-room hooks` | Python missing or not on `PATH` | Install Python 3 or use `--hooks=copy-only` |
560
- | `safe hooks are installed but not enforcing` | Safe mode default | Set `CLEAN_ROOM_HOOK_ENFORCE=1`, set clean-room env vars, or reinstall with `--hooks=strict` in a dedicated profile |
561
- | `install lock is held` | Another install or uninstall is mutating the same target root, or a prior process died while holding `.clean-room-install.lock` | Wait for the other process to finish; inspect and remove the lock only after confirming no installer is active |
562
- | Hook config write failed after files copied | Partial installer state; manifest records `hook_registration.status: "failed"` when possible | Fix the filesystem error, then re-run the same installer command to repair hook registration |
563
- | Install manifest write failed after files copied | Manifest may be absent or left at `phase: "installing"` | Re-run the same installer command before relying on uninstall tracking |
564
- | `phase` remains `installing` in `clean-room-install-manifest.json` | The previous install did not complete hook config or manifest finalization | Re-run the same installer command for that runtime and target root |
565
- | `clean-room run` rejects the manifest | The manifest is not unattended, lacks `loop_context`, raises `--max-iterations`, or has no approved unit | Fix `controller_policy`, `loop_context`, and `approved_scope_refs`, then retry `--dry-run` |
566
- | `clean-room run` reports no progress | The configured stages exited successfully but no tracked durable JSON artifact changed | Check role command cwd/argv, selected unit, and artifact write roots |
567
- | `clean-room run` reports repeated unit selection | The same unit was selected after a prior no-progress iteration | Resolve the blocker or update durable artifacts before retrying |
568
- | Hook reports `could not read` or `could not stat` | Artifact disappeared, permissions changed, or path was replaced during post-write validation | Restore readable artifact state and retry; hooks fail closed without printing private paths |
569
- | `source-index.json` is missing files | Limits, unreadable directories, ignored directories, binary files, changed-during-read files, or symlinks outside the source root | Inspect `skipped_entries` and adjust limits or permissions if the omissions matter |
570
-
571
- ## References
572
-
573
- - `skills/clean-room/SKILL.md`: main skill instructions.
574
- - `skills/clean-room/references/CONTROLLER-LOOP.md`: nested outer/inner loop contract.
575
- - `skills/clean-room/references/PREFLIGHT.md`: Stage 0 goal contract.
576
- - `skills/clean-room/references/PROCESS.md`: detailed process.
577
- - `skills/clean-room/references/LEAKAGE-RULES.md`: clean handoff rules.
578
- - `skills/clean-room/references/SPEC-SCHEMA.md`: artifact schema guidance.
579
- - `skills/clean-room/references/TARGET-LANGUAGE-GUIDE.md`: target constraint guidance.
580
-
581
- ## Dry Run
582
-
583
- From the repository root, run a minimal hook smoke test before relying on the workflow:
584
-
585
- ```bash
586
- export CLEAN_ROOM_ROLE=clean-qa-editor
587
- export CLEAN_ROOM_SOURCE_ROOTS="$PWD/source"
588
- export CLEAN_ROOM_CONTAMINATED_ARTIFACT_ROOTS="$PWD/contaminated-artifacts"
589
- export CLEAN_ROOM_CLEAN_ROOTS="$PWD/skills/clean-room/examples/minimal-spec-package"
590
- export CLEAN_ROOM_IMPLEMENTATION_ROOTS="$PWD/implementation"
591
- export CLEAN_ROOM_ALLOWED_READ_ROOTS=""
592
- export CLEAN_ROOM_SCHEMA_DIR="$PWD/skills/clean-room/assets"
593
-
594
- printf '{"tool_input":{"file_path":"%s"}}' "$PWD/skills/clean-room/examples/minimal-spec-package/behavior-spec.json" \
595
- | python3 hooks/check-artifact-leakage.py
596
-
597
- printf '{"tool_input":{"file_path":"%s"}}' "$PWD/skills/clean-room/examples/minimal-spec-package/behavior-spec.json" \
598
- | python3 hooks/validate-json-schema.py
599
-
600
- python3 hooks/clean-room-hook.py --mode safe --check require-clean-room-env.py </dev/null
184
+ npm run verify
601
185
  ```
602
186
 
603
- ## Local Verification
187
+ Documentation-only changes usually need review plus link/path checks, not the full test suite.
604
188
 
605
- After changing plugin metadata, hooks, schemas, or skill instructions, run the same local checks used for pull request CI:
189
+ Useful development checks:
606
190
 
607
191
  ```bash
608
- npm run verify
192
+ node --check bin/install.js
193
+ node --test tests/run.test.js
194
+ npm pack --dry-run
609
195
  ```
610
196
 
611
- Note: The unit test suite (`npm test`) utilizes the native Node.js test runner and requires Node.js >= 22 to execute successfully.
612
-
613
- The full JSON Schema validation requires Python `jsonschema` with format extras. On macOS with Homebrew Python, use a repo-local venv:
197
+ Python schema validation requires `jsonschema` with format extras:
614
198
 
615
199
  ```bash
616
200
  python3 -m venv .venv
617
201
  .venv/bin/python -m pip install "jsonschema[format]>=4.18,<5"
618
- npm run verify
202
+ .venv/bin/python tests/validate_jsonschema.py
619
203
  ```
620
204
 
621
- Optional, if an external skill-creator `quick_validate` command is installed on your machine:
622
-
623
- ```bash
624
- quick_validate skills/attended
625
- quick_validate skills/clean-room
626
- quick_validate skills/init
627
- quick_validate skills/refocus
628
- quick_validate skills/resume
629
- quick_validate skills/start-over
630
- quick_validate skills/unattended
631
- ```
205
+ Use `st` for repository search.