shapeup-sdlc 1.6.3 → 3.0.0

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 (118) hide show
  1. package/.claude/settings.local.example.json +5 -5
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +54 -107
  4. package/README.md +165 -151
  5. package/SECURITY.md +49 -27
  6. package/bin/init.mjs +93 -108
  7. package/bin/lib/grant.mjs +145 -0
  8. package/commands/build.md +20 -0
  9. package/commands/eval.md +5 -4
  10. package/commands/scopes.md +5 -4
  11. package/commands/shape.md +1 -1
  12. package/commands/ship.md +53 -7
  13. package/commands/wire.md +1 -1
  14. package/hooks/dispatch-receipt.mjs +195 -0
  15. package/hooks/gate-intake.mjs +16 -17
  16. package/hooks/gate-zerowork.mjs +107 -25
  17. package/hooks/hooks.json +9 -48
  18. package/hooks/lib/decision.mjs +38 -19
  19. package/hooks/safety-spine.mjs +4 -4
  20. package/hooks/sandbox-guard.mjs +130 -50
  21. package/{skills/tech-lead/scripts/compile-order.mjs → kernel/compile.mjs} +344 -55
  22. package/{skills/tech-lead/scripts/gate-answers.mjs → kernel/gate.mjs} +69 -26
  23. package/kernel/harness.mjs +134 -0
  24. package/{skills/tech-lead/scripts/fit-check.mjs → kernel/init/fit.mjs} +25 -22
  25. package/kernel/init/run.mjs +489 -0
  26. package/{skills/tech-lead/scripts → kernel}/lib/argv.mjs +52 -31
  27. package/{skills/tech-lead/scripts/lib/contract-md.mjs → kernel/lib/contract.mjs} +261 -17
  28. package/kernel/lib/paths.mjs +491 -0
  29. package/kernel/probe/concurrency.mjs +510 -0
  30. package/{skills/tech-lead/scripts/aegis-digest.mjs → kernel/probe/digest.mjs} +10 -11
  31. package/kernel/probe/eval.mjs +77 -0
  32. package/kernel/probe/leg.mjs +125 -0
  33. package/kernel/probe/resume.mjs +528 -0
  34. package/{skills/tech-lead/scripts → kernel/probe}/stats.mjs +102 -21
  35. package/kernel/probe/t0.mjs +66 -0
  36. package/{skills/ba-pitch-analyzer/scripts/board-derive.mjs → kernel/reduce/board.mjs} +104 -28
  37. package/kernel/reduce/graph.mjs +437 -0
  38. package/kernel/reduce/hill.mjs +152 -0
  39. package/kernel/reduce/ingest.mjs +633 -0
  40. package/{hooks/slop-cleaner.mjs → kernel/reduce/leftovers.mjs} +40 -57
  41. package/{skills/tech-lead/scripts/ship-report.mjs → kernel/reduce/ship.mjs} +93 -14
  42. package/{skills/tech-lead/scripts/run-snapshot.mjs → kernel/reduce/snapshot.mjs} +22 -21
  43. package/{skills/spec-evaluator/scripts/verdict-ledger.mjs → kernel/reduce/verdict.mjs} +14 -8
  44. package/kernel/report/export.mjs +325 -0
  45. package/kernel/report/facts.mjs +347 -0
  46. package/{skills/tech-lead/scripts/budget-check.mjs → kernel/verify/budget.mjs} +22 -25
  47. package/kernel/verify/dispatch.mjs +114 -0
  48. package/{skills/tech-lead/scripts/validate-envelope.mjs → kernel/verify/envelope.mjs} +20 -15
  49. package/{skills/tech-lead/scripts/lib → kernel/verify}/ratchet-tree.mjs +36 -14
  50. package/kernel/verify/skills.mjs +125 -0
  51. package/kernel/verify/spec.mjs +559 -0
  52. package/{skills/tech-lead/scripts/t0-verify.mjs → kernel/verify/t0.mjs} +138 -28
  53. package/{skills/tech-lead/scripts/trace-lint.mjs → kernel/verify/trace.mjs} +28 -13
  54. package/oracles/_shared.mjs +1 -1
  55. package/oracles/http-oracle.mjs +2 -2
  56. package/oracles/index.mjs +1 -1
  57. package/oracles/process-oracle.mjs +2 -2
  58. package/oracles/snapshot-oracle.mjs +2 -2
  59. package/oracles/test-oracle.mjs +2 -2
  60. package/package.json +11 -13
  61. package/skills/ba-pitch-analyzer/SKILL.md +24 -19
  62. package/skills/ba-pitch-analyzer/assets/templates/_index.tmpl.md +1 -1
  63. package/skills/ba-pitch-analyzer/assets/templates/api-feasibility.tmpl.md +12 -7
  64. package/skills/ba-pitch-analyzer/assets/templates/contracts/third-party-api.contract.tmpl.md +6 -3
  65. package/skills/ba-pitch-analyzer/assets/templates/cross-context/migration-plan.tmpl.md +5 -4
  66. package/skills/ba-pitch-analyzer/assets/templates/cross-context/team-handoff.tmpl.md +23 -13
  67. package/skills/ba-pitch-analyzer/assets/templates/scope-summary.tmpl.md +17 -12
  68. package/skills/ba-pitch-analyzer/assets/templates/synthesis.tmpl.md +17 -38
  69. package/skills/ba-pitch-analyzer/assets/templates/task.tmpl.md +3 -0
  70. package/skills/ba-pitch-analyzer/references/contract-patterns.md +8 -4
  71. package/skills/ba-pitch-analyzer/references/doc-schemas.md +3 -1
  72. package/skills/ba-pitch-analyzer/references/task-generation.md +8 -8
  73. package/skills/ba-pitch-analyzer/references/test-surface.md +1 -1
  74. package/skills/coach/SKILL.md +3 -3
  75. package/skills/orient/SKILL.md +2 -1
  76. package/skills/qa-edge-hunter/SKILL.md +15 -41
  77. package/skills/scope-architect/SKILL.md +57 -18
  78. package/skills/scope-hammer/SKILL.md +5 -5
  79. package/skills/shapeup/SKILL.md +3 -3
  80. package/skills/shapeup/resources/context-compaction.md +4 -3
  81. package/skills/solution-architect/SKILL.md +37 -15
  82. package/skills/spec-evaluator/SKILL.md +24 -7
  83. package/skills/spec-evaluator/references/dimensions/_registry.md +2 -2
  84. package/skills/spec-evaluator/references/dimensions/completeness.md +1 -1
  85. package/skills/spec-evaluator/references/dimensions/integration.md +98 -67
  86. package/skills/spec-evaluator/references/dimensions/spec-conformance.md +4 -4
  87. package/skills/spec-evaluator/references/dimensions/test-surface-conformance.md +1 -1
  88. package/skills/spec-evaluator/references/probing.md +42 -23
  89. package/skills/spec-evaluator/references/report-schema.md +2 -2
  90. package/skills/task-executor/SKILL.md +32 -18
  91. package/skills/tech-lead/SKILL.md +127 -438
  92. package/skills/tech-lead/references/gates.md +140 -49
  93. package/skills/tech-lead/references/protocol.md +832 -0
  94. package/skills/tech-lead/schemas/domain.schema.json +645 -198
  95. package/skills/tech-lead/schemas/gate-answers.schema.json +2 -2
  96. package/skills/tech-lead/schemas/work-order.schema.json +11 -2
  97. package/skills/tech-lead/schemas/work-result.schema.json +56 -18
  98. package/skills/tech-lead/workflows/shapeup-run.js +1474 -0
  99. package/skills/translator/SKILL.md +2 -2
  100. package/hooks/anti-rationalization.mjs +0 -244
  101. package/hooks/compact-snapshot.mjs +0 -47
  102. package/hooks/gate-deadline.mjs +0 -151
  103. package/hooks/gate-l2.mjs +0 -161
  104. package/hooks/session-rehydrate.mjs +0 -109
  105. package/skills/advisor-protocol/SKILL.md +0 -171
  106. package/skills/ba-pitch-analyzer/scripts/spec-lint.mjs +0 -239
  107. package/skills/spec-evaluator/README.md +0 -93
  108. package/skills/tech-lead/README.md +0 -71
  109. package/skills/tech-lead/references/delegation.md +0 -254
  110. package/skills/tech-lead/references/invocation.md +0 -45
  111. package/skills/tech-lead/references/ledger-schema.md +0 -214
  112. package/skills/tech-lead/references/round-protocol.md +0 -184
  113. package/skills/tech-lead/references/state-model.md +0 -66
  114. package/skills/tech-lead/scripts/ingest-result.mjs +0 -270
  115. package/skills/tech-lead/scripts/init-run.mjs +0 -326
  116. package/skills/tech-lead/scripts/lib/is-main.mjs +0 -82
  117. package/skills/tech-lead/scripts/lib/paths.mjs +0 -278
  118. package/skills/translator/README.md +0 -66
package/README.md CHANGED
@@ -15,11 +15,11 @@ The ceremony is right-sized: `/ship` runs the full gated pipeline for real featu
15
15
  fixes where the gates would have nothing to say.
16
16
 
17
17
  <p align="center">
18
- <img src="docs/assets/demo-gate.svg" alt="Terminal recording: the agent tries to run EVAL with two tasks unfinished, and a PreToolUse hook denies the tool call outright." width="700">
18
+ <img src="docs/assets/demo-gate.svg" alt="Terminal recording: a worker tries to edit a file outside the scope it was given, a PreToolUse hook denies the write and names the path, and the next edit inside the scope is permitted." width="700">
19
19
  </p>
20
20
 
21
21
  <p align="center"><sub>
22
- The denial text above is <b>verbatim stdout</b> from <code>hooks/gate-l2.mjs</code> —
22
+ The denial above is <b>verbatim stdout</b> from <code>hooks/sandbox-guard.mjs</code> —
23
23
  <a href="tools/demo/record-demo.mjs">the recorder runs the real hook</a> and fails rather than
24
24
  draw a picture. <a href="docs/assets/demo-gate.txt">Plain-text transcript.</a>
25
25
  </sub></p>
@@ -32,8 +32,8 @@ prompt-based harness:
32
32
 
33
33
  **1. A worker cannot act on an order nobody compiled.** Every dispatch carries a schema-validated
34
34
  WorkOrder, and a `PreToolUse` hook hard-denies the call when that order is missing or malformed —
35
- the tool call never reaches the worker. The same layer denies any write outside the active scope's
36
- file substrate, and blocks a session that dispatched the orchestrator and left no run receipt.
35
+ the tool call never reaches the worker. The same layer denies any write the order's own substrate
36
+ does not permit, and blocks a session that dispatched the orchestrator and left no run receipt.
37
37
  → *Prevents: an agent inventing its own brief, then reporting against it.*
38
38
 
39
39
  (GATE L2, the board-green check before evaluation, is advisory: it warns when a round's evaluation
@@ -54,52 +54,64 @@ Under the hood this rests on a typed worker envelope and a single-writer state l
54
54
  are load-bearing plumbing, and you should not have to think about them to use the harness —
55
55
  they are documented for [contributors](CONTRIBUTING.md), not for users.
56
56
 
57
- > ### Just want the gate?
58
- >
59
- > The enforcement layer ships separately as the **[Anti-Lying Kit](plugins/anti-lying-kit/)** —
60
- > three hooks, no methodology, installable *alongside* spec-kit, OpenSpec, or your own
61
- > `tasks.md`. You should not have to adopt Shape Up to stop your agent claiming done.
62
- >
63
- > ```
64
- > /plugin install anti-lying-kit@nvptuoc-marketplace
65
- > ```
66
-
67
57
  ## Quickstart
68
58
 
69
59
  ```
70
60
  /plugin marketplace add nguyenvanphituoc/shapeup-sdlc-plugin
71
61
  /plugin install shapeup-sdlc-plugin@nvptuoc-marketplace
72
- /ship "add dark mode to the settings screen"
62
+ /shapeup-sdlc-plugin:ship "add dark mode to the settings screen"
73
63
  ```
74
64
 
75
- `/ship` walks the whole lifecycle and pauses at each gate for you. That's the whole quickstart.
65
+ That last one walks the whole lifecycle and pauses at each gate for you. That's the whole
66
+ quickstart.
67
+
68
+ > **The `shapeup-sdlc-plugin:` prefix is not optional.** A plugin's commands are namespaced by the
69
+ > plugin that ships them, so the bare `/ship` is not a command and answers `Unknown command: /ship`
70
+ > — measured on both a marketplace install and a `--plugin-dir` checkout. Interactively you will
71
+ > normally pick the command off `/`-completion and never type the prefix yourself; it matters when
72
+ > you are writing the command down, which is exactly what a headless `claude -p` invocation or a CI
73
+ > step does. **Everything below writes commands in the short form for readability — prepend
74
+ > `shapeup-sdlc-plugin:` to any of them you actually type.**
75
+
76
+ > **Running unattended?** The plugin install grants no permissions — every pipeline step is a Node
77
+ > script that ships *with* the plugin and therefore lives outside your project, so it needs
78
+ > approval. You click once interactively; headless there is nobody to click. Scaffold instead, which
79
+ > writes the grant:
80
+ >
81
+ > ```bash
82
+ > npx shapeup-sdlc init -d . -y
83
+ > ```
84
+ >
85
+ > **And lift the print-mode background ceiling, or the run is killed at ten minutes.** `claude -p`
86
+ > terminates a session's background tasks after 600 s by default, and the whole pipeline runs as
87
+ > one background launch — so an unattended run dies mid-BUILD with the CLI reporting nothing worse
88
+ > than "background tasks still running after 600s; terminating". Measured, on a run that had
89
+ > reached WIRE:
90
+ >
91
+ > ```bash
92
+ > CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0 claude -p "/shapeup-sdlc-plugin:ship …" …
93
+ > ```
94
+ >
95
+ > Nothing is lost when it happens — resume state is on disk, so relaunching fast-forwards past the
96
+ > phases that finished. It costs a relaunch, not a run.
76
97
 
77
98
  Want to see a full run before installing anything? **[docs/quickstart.md](docs/quickstart.md)**
78
- walks one small feature end to end — including the hook denying a premature eval, a FAIL round
99
+ walks one small feature end to end — including what the hooks do to a premature eval, a FAIL round
79
100
  with real evaluator output, and the fix that turns it green.
80
101
 
81
102
  <sub>No prerequisites for non-UI work — a browser (`npx playwright install chromium`) is needed
82
103
  only when a run actually reaches a `[ui]` acceptance criterion. Team installs, the scaffolding
83
- installer (Claude Code / Antigravity / Codex), and troubleshooting are in
104
+ installer, and troubleshooting are in
84
105
  **[docs/install.md](docs/install.md)**; upgrading is **[docs/upgrading.md](docs/upgrading.md)**.</sub>
85
106
 
86
107
  ## Agent support
87
108
 
88
- The harness is written once and compiled to other agent CLIs (`npm run distribute` emits
89
- `dist/`; the [scaffolding installer](docs/install.md#local-scaffolding) wires targets in one
90
- run). The matrix is honestthe row that matters most does not travel:
91
-
92
- | | Claude Code | Cursor | Antigravity | Codex |
93
- |---|:---:|:---:|:---:|:---:|
94
- | The 13 skills | ✅ plugin | ✅ `.mdc` rules (references inlined) | ✅ subagent defs + skill files | ✅ skill files |
95
- | Slash commands | ✅ all 10 | ✅ VS Code/Cursor extension + rules | — | — |
96
- | Pipeline scripts (`t0-verify`, `trace-lint`, oracles) | ✅ | ✅ plain Node, run from any CLI | ✅ | ✅ |
97
- | **Hook-enforced gates** (deny on premature EVAL, substrate sandbox, safety spine) | ✅ | ❌ | ❌ | ❌ |
98
- | Advisory Stop hooks | ✅ | ❌ | ❌ | ❌ |
99
-
100
- Hooks are a per-CLI mechanism, so outside Claude Code the gates degrade from **enforced** to
101
- **instructed** — the same honor system every other framework runs on everywhere. If the deny
102
- hook is why you're here, that currently means Claude Code.
109
+ The harness targets **Claude Code only**. The reason is the row that never travelled when we
110
+ compiled to other CLIs: hooks. The 12 skills, 10 slash commands and the kernel are
111
+ portable prose and plain Nodebut hook-enforced gates (envelope validation, substrate
112
+ sandbox, safety spine, the zero-work block) are a per-CLI mechanism, and without them every gate degrades from
113
+ **enforced** to **instructed** the same honor system every other framework runs on
114
+ everywhere. If the deny hooks are why you're here, that means Claude Code.
103
115
 
104
116
  ## Glossary
105
117
 
@@ -108,15 +120,15 @@ rest of this README after this table and nothing will be a surprise.
108
120
 
109
121
  | Term | In plain English |
110
122
  |---|---|
111
- | **board** | The round's task list. "Green" means every task is done. The deny hook reads this. |
123
+ | **board** | The round's task list. "Green" means every task is done. GATE L2's hook reads this before an evaluation and warns if it is not green. |
112
124
  | **round** | One build → evaluate cycle. A FAIL verdict starts round *r+1*. |
113
125
  | **T0** | The smoke test a scope must pass before it counts as built: its fixtures + a DB probe + the seesaw. Writes an artifact to disk that the evaluator must cite. |
114
126
  | **seesaw** | The part of T0 that re-runs *other* scopes' fixtures — so a regression is never mistaken for progress. |
115
- | **substrate** | The exact list of files one scope is allowed to write. A hook blocks anything outside it. |
127
+ | **substrate** | The exact list of files one dispatch is allowed to write, stamped into its work order. A hook blocks anything outside it — and anything the order marks frozen. |
116
128
  | **scope contract** | The file defining one vertical slice: its substrate, its fixtures, its affordances. |
117
129
  | **affordance** | The thing a user can actually click, type or call. UI is graded on affordances, not on looks. |
118
130
  | **hill / hill phase** | How much of a scope is still *unknown* versus merely *unfinished*. Derived from T0 facts — never self-reported. |
119
- | **gate (L0–L4)** | A numbered checkpoint in a run. Most pause for you; GATE L2 is the one enforced by a hook. |
131
+ | **gate (L0–L4)** | A numbered checkpoint in a run. Most pause for you; GATE L2 is the one a hook observes and reports on. |
120
132
  | **covers-closure** | Every requirement clause has at least one task claiming to cover it. Nothing silently drops. |
121
133
  | **wiring reachability** | Every engine has a call site reachable from the app's real entry point. Catches "built, but never wired up". |
122
134
  | **discovery ledger** | The one file everything found mid-run gets written to, so nothing is lost between rounds. |
@@ -128,37 +140,24 @@ A longer version, including the internals, is in [docs/glossary.md](docs/glossar
128
140
  The harness walks a pitch from idea to ship. The full annotated pipeline — the build round,
129
141
  the gate walkthrough, the circuit breaker — is
130
142
  [`docs/design/04-functional-design.md`](docs/design/04-functional-design.md), and the design
131
- document as a whole starts at [`docs/design/`](docs/design/README.md). A simplified view:
132
-
133
- ```mermaid
134
- graph LR
135
- A([Raw Idea]) --> S["Shaping<br>/shapeup"]
136
- S --> P["Pitch"]
137
- P --> BET{"Betting<br>(PO)"}
138
- BET --> KO["Kick-off + Orient<br>/orient"]
139
- KO --> WIRE["Wire<br>/solution-architect"]
140
- WIRE --> MAP["Map Scopes<br>/ba-pitch-analyzer<br>+ /scope-architect"]
141
- MAP --> BUILD["Build Vertically<br>/task-executor"]
142
- BUILD --> EVAL["Evaluate<br>/spec-evaluator"]
143
- EVAL -- FAIL --> BUILD
144
- EVAL -- PASS --> QA["Edge Hunt<br>/qa-edge-hunter"]
145
- QA --> SHIP["Triage + Ship<br>/scope-hammer"]
146
- SHIP --> RETRO["Coach Retro<br>/coach"]
147
- TL["/tech-lead orchestrates Orient → Ship"] -.-> KO
148
-
149
- classDef plan fill:#e3f2fd,stroke:#1e88e5;
150
- classDef build fill:#e8f5e9,stroke:#43a047;
151
- classDef qa fill:#fce4ec,stroke:#c2185b;
152
- class S,WIRE,MAP plan;
153
- class KO,BUILD build;
154
- class QA,EVAL qa;
155
- ```
143
+ document as a whole starts at [`docs/design/`](docs/design/README.md). This diagram shows the
144
+ full phase and gate mechanism — simpler than that per-attempt detail, but the whole pipeline:
145
+
146
+ <p align="center">
147
+ <img src="docs/assets/workflow-mechanism.svg" alt="The shapeup-sdlc harness pipeline from raw idea to Coach Retro: Shaping produces a Pitch, the Betting Table bets into the tech-lead-orchestrated run or rejects back to raw idea, Kick-off through Ship Sign-off cross gates L0, L1a, L1a.5, L1b, advisory L2, L3, GATE H and L4, the Build/Evaluate round loops on FAIL, and a circuit breaker routes straight to GATE H — bypassing QA — when the round or wall-clock budget runs out." width="900">
148
+ </p>
149
+
150
+ <p align="center"><sub>
151
+ Plan-phase skills in blue, build-phase in green, QA-phase in pink; amber pills are gates —
152
+ the outlined <b>L2</b> is advisory, the rest block. The dashed region marks what
153
+ <code>/tech-lead</code> orchestrates end to end.
154
+ </sub></p>
156
155
 
157
156
  Since v1.3 the pipeline carries a **traceability spine**: `ba-pitch-analyzer`'s `coverage`
158
157
  operation writes a requirement registry (`requirements.md`), `solution-architect` commits a
159
158
  per-use-case wiring map (`wiring-map.md`, gate L1a.5) resolved against the L0
160
159
  `project-profile.md`, and the covers-closure + reachability oracle
161
- `skills/tech-lead/scripts/trace-lint.mjs` checks that no engine ships orphaned. It runs
160
+ `kernel/verify/trace.mjs` checks that no engine ships orphaned. It runs
162
161
  advisory (warn-only) and is promoted to a blocking gate only once `covers:` is populated;
163
162
  every arm is skipped when its artifact is absent, so older specs are unaffected.
164
163
 
@@ -171,13 +170,12 @@ every arm is skipped when its artifact is absent, so older specs are unaffected.
171
170
  | Shaping (1–4) | `shapeup` | — | Frame the problem, breadboard affordances, spike risks, write the pitch. Sub-commands: `full`, `shaping`, `spike`, `breadboarding`, `framing-doc`, `kickoff-doc`, `breadboard-reflection`. |
172
171
  | Intake (GATE L0) | `translator` | — | Normalizes non-English intake (pitch/PRD/transcript) to faithful English before planning. The harness is English-only downstream. |
173
172
  | Orient (7) | `orient` | — | Builder-led recon: reads the code, spikes the single riskiest area, emits a code-surface map, spike findings, discovered-task seed, and a hill signal. Writes no production code. |
174
- | Wire (GATE L1a.5) | `solution-architect` | v1.1 | Sole writer of the committed wiring map (`wiring-map.md`): per-UC engine → integration seam → entry-point call site → player-visible affordance, resolved against `project-profile.md`. Front-loads the integration seam so no engine ships orphaned; the reachability input `trace-lint.mjs` checks. Operation: wire. |
175
- | Map Scopes (8) | `ba-pitch-analyzer` | v4.0 | The spec-analyzer (pure worker). Decomposes a pitch into a linked DDD document tree (domain model → use cases → tasks) with BDD scenarios, a UC system flow, and a derived `## Test Surface`. One craft, five order-selected operations (analyze / generate-board / reconcile / retrofit-surface / coverage — the last writes the shared `requirements.md` registry for covers-closure); graph math + audits delegated to `board-derive.mjs`/`spec-lint.mjs`. |
176
- | Map Scopes (8) | `scope-architect` | v1.0 | Sole writer of committed, write-whitelisted scope contracts (`scopes/*.md`): import-graph slicing by flow, substrates, affordance manifests, fixtures. Operations: map-scopes / remap / split-scope. |
173
+ | Wire (GATE L1a.5) | `solution-architect` | v1.1 | Sole writer of the committed wiring map (`wiring-map.md`): per-UC engine → integration seam → entry-point call site → player-visible affordance, resolved against `project-profile.md`. Front-loads the integration seam so no engine ships orphaned; the reachability input `harness verify trace` checks. Operation: wire. |
174
+ | Map Scopes (8) | `ba-pitch-analyzer` | v4.0 | The spec-analyzer (pure worker). Decomposes a pitch into a linked DDD document tree (domain model → use cases → tasks) with BDD scenarios, a UC system flow, and a derived `## Test Surface`. One craft, four order-selected operations (analyze / reconcile / retrofit-surface / coverage — the last writes the shared `requirements.md` registry for covers-closure); graph math + audits delegated to `harness reduce board`/`harness verify spec`. |
175
+ | Map Scopes (8) | `scope-architect` | v1.0 | Sole writer of committed, write-whitelisted scope contracts (`scopes/*.md`): import-graph slicing by flow, substrates, affordance manifests, fixtures. Operation: map-scopes. |
177
176
  | Build (9) | `task-executor` | v2.0 | Pure worker: work order in → code out. Assumption scan, minimum-code/surgical-change discipline, Layer 1/2/3 UI rules, substrate-sandboxed, zero-memory. Never writes boards/ledgers/run-state. |
178
177
  | Evaluate (GATE L3) | `spec-evaluator` | v1.0 | The single judge (pure worker). Verifies spec-conformance, TDD surface, and integration against the running app — skeptical, files `file:line` bugs, runs exactly once per build round. Requires a T0 artifact citation, grades UI affordance-only; verdict + refuted boxes return as data. |
179
178
  | QA (post-PASS) | `qa-edge-hunter` | v1.1 | Exploratory edge hunt on the running app through six fixed lenses, charting edges *outside* what the evaluator probed. Findings go to the ledger as `~`; never blocks ship. |
180
- | Advisor (mid-build) | `advisor-protocol` | v0.1 | Adjudicates a worker's structured `ESCALATE` (design decision / spec ambiguity / substrate expansion) within a per-scope-per-round budget; persists answers to the committed round ledger so they survive a zero-memory reset. |
181
179
  | Stop (11) | `scope-hammer` | v0.1 | GATE H: must-have census → baseline comparison (never vs. the ideal) → cut list + ship verdict. Handles the normal stop and both circuit-breaker triggers. |
182
180
  | Retro (post-L4) | `coach` | — | RLHF for the harness: turns raw PO/TL feedback at Ship Sign-off into per-skill guidelines under committed `shapeup/knowledge-base/<skill>.md`, read back by `task-executor` / `ba-pitch-analyzer` / `qa-edge-hunter` on their next run. GATE COACH-1 asks the PO which skill owns each rule — never assumes; mechanism defects are filed to the harness-defect register instead. |
183
181
  | Orchestrator | `tech-lead` | v1.0 | Owns the run end-to-end: PLAN once → BUILD all tasks → EVAL once per round, looping on FAIL. Three-level circuit breaker (rounds / T0 attempts / wall clock), T0/seesaw-verified build rounds, mechanical hill derivation. Sole writer of run-state. |
@@ -185,7 +183,8 @@ every arm is skipped when its artifact is absent, so older specs are unaffected.
185
183
  ### Commands
186
184
 
187
185
  `/ship` runs the whole lifecycle; the phase commands run one step each, so the pipeline is
188
- learnable from `/`-completion alone.
186
+ learnable from `/`-completion alone. Names are written short here; the real name of each carries the
187
+ `shapeup-sdlc-plugin:` prefix, which `/`-completion fills in for you and a script must spell out.
189
188
 
190
189
  | Command | Phase | Description |
191
190
  |---------|-------|-------------|
@@ -200,58 +199,71 @@ learnable from `/`-completion alone.
200
199
  | `/hammer` | H | Must-have census, baseline comparison, cut list + ship verdict. |
201
200
  | `/retro` | post-L4 | File ship-gate feedback into the per-skill knowledge base. |
202
201
 
203
- ### Agents
204
-
205
- | Agent | Description |
206
- |-------|-------------|
207
- | `reviewer` | Independent correctness/security code reviewer (returns findings, never edits). |
208
-
209
- ### Hooks
210
-
211
- Nine Node hooks. What each one reads and what it can deny:
212
-
213
- - `SessionStart` — prints a load confirmation so you know the plugin is active; on
214
- `startup|compact|resume|clear`, `hooks/session-rehydrate.mjs` additionally injects the mid-run
215
- `RunSnapshot` hint ("trust the files, not the summary") when a harness run is in flight. On a
216
- cold `startup` it leads with the stronger sentence — *a run is already open; resume it, do not
217
- re-open it* because that is the failure a fresh session actually makes. Silent when no run is
218
- in flight, which is the ordinary case.
219
- - `PreToolUse` (matcher `Skill`) **`hooks/gate-l2.mjs` hard-blocks the once-per-round EVAL
220
- delegation while the task board isn't fully green.** This is the gate in the demo above.
221
- - `PreToolUse` (matcher `Skill`) **`hooks/gate-intake.mjs` denies a `tech-lead` dispatch that
222
- carries no pitch, no spec folder, and no requirement text.** Measured on the SDD harness
223
- benchmark: when the requirement text was dropped on the hand-off and only a flag survived, the
224
- run printed the gate list, built nothing, and scored 29% against a hidden acceptance suite while
225
- looking like a success (n=3, zero variance). An orchestrator with no spec now fails loudly
226
- instead of narrating.
227
- - `PreToolUse` (matcher `Skill`) **`hooks/gate-deadline.mjs` denies a `task-executor` dispatch
228
- once the run's opt-in wall-clock budget is spent**, routing to GATE H instead. `spec-evaluator`,
229
- `scope-hammer`, `qa-edge-hunter` and `advisor-protocol` stay reachable — a run past its deadline
230
- must still be able to judge, hammer and close. Off unless a budget is configured.
231
- - `PreToolUse` (matcher `Bash|Read|Write|Edit|MultiEdit`) `hooks/safety-spine.mjs` denies
232
- destructive commands (`rm -rf` on unrecoverable targets, force-push/push-to-main,
233
- `git reset --hard`, `DROP TABLE`) and secret-file reads. Machine guard, not pipeline guard;
234
- escape hatch is the human-authored `.shapeup/safety-overrides.json`.
235
- - `PreToolUse` (matcher `Edit|Write|MultiEdit`) `hooks/sandbox-guard.mjs` blocks writes
236
- outside the active scope's substrate whitelist (no-op unless scope contracts exist).
237
- - `PreToolUse` (matcher `Skill|Agent`) `skills/tech-lead/scripts/validate-envelope.mjs`
238
- denies any worker dispatch whose order file is missing or schema-invalid.
239
- - `Stop` **`hooks/gate-zerowork.mjs` blocks a session that dispatched the orchestrator and
240
- left no run receipt.** The one blocking `Stop` hook, and the narrowest: its predicate is
241
- mechanical orchestrator dispatched AND no `.shapeup/<slug>/receipt.json` so it never
242
- judges quality, it reports that no work exists to judge. It exists because the benchmark caught
243
- this harness describing its own pipeline instead of running it (Haiku 4.5, n=5, zero variance,
244
- 29% acceptance) while both existing guards structurally could not see it: one is scoped to an
245
- active run, and a run that never started leaves no files; the other matches past-tense
246
- completion claims, and narration is future-tense. Fails open on everything ambiguous, and
247
- `stop_hook_active` caps it at one block per stop chain.
248
- - `Stop` two **advisory, never-blocking** hooks (`hooks/anti-rationalization.mjs` flags
249
- completion claims the board/T0 facts contradict including a future-tense promise left as the
250
- session's last word; `hooks/slop-cleaner.mjs` flags TODO/`console.log`/commented-out-code
251
- leftovers in the session's diff). They emit at most a `systemMessage` "QA is a level-up, not
252
- a gate."
253
- - `PreCompact` — `hooks/compact-snapshot.mjs` persists the mid-run `RunSnapshot` to
254
- `.shapeup/<slug>/run-snapshot.json` before the conversation is compacted.
202
+ ### What is enforced, and by what
203
+
204
+ The honest version of this table matters more than a long one. A guarantee is only as strong as
205
+ the layer that carries it, and the three layers here fail differently:
206
+
207
+ | Layer | Works when | Fails how |
208
+ |---|---|---|
209
+ | **Wall** — a hook | Under every permission mode, including `bypassPermissions`. The CLI runs it; the model cannot decline it. | Fail-OPEN on anything ambiguous, and every evaluation writes a decision row, so "permitted" never looks like "never ran". |
210
+ | **Runtime** — the kernel and the run script | When the run goes through the harness. A schema rejection or a non-zero exit stops the step. | A lane that never calls the kernel is never checked — which is why the hooks below cover the doors, not the steps. |
211
+ | **Advisory** — a report section | When somebody reads the artifact. | Silently, if nobody does. It is a cleanup list, never a verdict. |
212
+
213
+ **Four walls.** These are hooks because nothing in the runtime can substitute for them:
214
+
215
+ - `PreToolUse` (`Skill`) **`hooks/gate-intake.mjs` denies a `tech-lead` dispatch that carries no
216
+ pitch, no spec folder, and no requirement text.** Observed, not theorized: when the requirement
217
+ text is dropped on the hand-off and only a flag survives, the run prints the gate list, builds
218
+ nothing, and reads like a success while leaving every defect in the deliverable.
219
+ - `PreToolUse` (`Skill|Agent`) **`harness verify envelope` denies any worker dispatch whose order
220
+ file is missing or fails the WorkOrder schema.** A malformed envelope never reaches a worker.
221
+ - `PreToolUse` (`Edit|Write|MultiEdit`) **`hooks/sandbox-guard.mjs` blocks a write that no LIVE
222
+ order's substrate permits.** It reads every compiled-but-not-yet-ingested order rather than a
223
+ pointer to one, so scopes building concurrently are each held to their own contract; `frozen`
224
+ outranks everything, across all of them.
225
+ - `PreToolUse` (`Bash|Read|Write|Edit|MultiEdit`) — **`hooks/safety-spine.mjs` denies destructive
226
+ commands** (`rm -rf` on unrecoverable targets, force-push/push-to-main, `git reset --hard`,
227
+ `DROP TABLE`) and secret-file reads. A machine guard, not a pipeline guard; the escape hatch is
228
+ the human-authored `.shapeup/safety-overrides.json`.
229
+
230
+ **One recorder**, which denies nothing and is what makes a wall possible one layer down:
231
+
232
+ - `PostToolUse` (`Skill|Agent`) **`hooks/dispatch-receipt.mjs` writes down which skill actually
233
+ ran.** Until it existed, a dispatch that failed — plugin absent, disabled, or a different version
234
+ loaded was indistinguishable from one that succeeded: the sub-agent would do the craft itself
235
+ from the prose in its own prompt, the artifacts landed in exactly the place the order permitted, so
236
+ the order gate and the sandbox guard both passed and the run advanced having applied none of the
237
+ shipped craft. A green run was consistent with zero worker craft. The hook appends
238
+ `{order_id, worker_declared, skill_invoked, dispatch_ok, at}` to `.shapeup/<slug>/receipts/`, and
239
+ `harness reduce ingest` refuses an orchestrated result with no matching receipt. A failed dispatch
240
+ never reaches `PostToolUse` at all, so the receipt's *existence* is the evidence. It has no deny
241
+ path, every write is guarded, and `--no-receipt-check` is the documented way through when the
242
+ channel itself fails.
243
+
244
+ **One blocking Stop hook**, and it is the narrowest thing in the repo:
245
+
246
+ - `Stop` **`hooks/gate-zerowork.mjs` blocks a session that dispatched the orchestrator and left
247
+ no run receipt.** Its predicate is mechanical orchestrator dispatched AND no
248
+ `.shapeup/<slug>/receipt.json` so it never judges quality; it reports that no work exists to
249
+ judge. It exists because this harness was repeatedly observed describing its own pipeline instead
250
+ of running it: a narrated run that reads like a clean success. Fails open on everything
251
+ ambiguous, and `stop_hook_active` caps it at one block per stop chain.
252
+
253
+ **What the runtime carries instead** (v2.0 retired six hooks whose work moved here):
254
+
255
+ | Was a hook | Is now | What changed |
256
+ |---|---|---|
257
+ | `gate-l2` (EVAL over an unfinished board) | The GATE L2 block, which names `green_scopes` and `hammer_proposals` | It was advisory either way; now the same facts reach the human who answers the gate rather than a warning line above it. |
258
+ | `gate-deadline` (deny builds past the wall clock) | `harness verify budget --strict`, checked at every round boundary | **A real coverage change, stated rather than hidden:** the round loop stops the run from opening ANOTHER round, but no longer interrupts a single build leg that runs long. `attempt_budget` bounds that leg by attempts instead. |
259
+ | `session-rehydrate` + `compact-snapshot` | `harness reduce graph --slug <slug> --subgraph run` | A hook fired at two moments the platform chose; a command answers whenever the question is asked, including the moments a hook never saw. |
260
+ | `anti-rationalization` (claims the facts contradict) | The ship report's census, derived from the board and the T0 artifacts | The facts are in an artifact a teammate finds on `git pull`, not in a transcript nobody re-reads. |
261
+ | `slop-cleaner` (TODO/`console.log` leftovers) | The ship report's **Leftovers** section | Same scan, same added-lines-only rule; it lands somewhere checkable. |
262
+
263
+ **Nothing load-bearing depends on permission mode.** The four walls plus the zero-work gate run
264
+ under every mode. The kernel needs a grant to be *invoked* — two Bash lines `npx shapeup-sdlc init`
265
+ writes — but a session that never gets that grant is a session that cannot run the pipeline at all,
266
+ not one that runs it unguarded.
255
267
 
256
268
  No hook makes a network request, none has dependencies, and all are plain, readable `.mjs`
257
269
  files. **[SECURITY.md](SECURITY.md)** states what each hook reads, what it can deny, and what
@@ -278,8 +290,8 @@ These hold across the harness and are the reason it stays predictable:
278
290
  - **Hill phase is mechanical, never self-reported** — derived only from T0/T1/seesaw facts, closing
279
291
  the self-reported-confidence risk outright.
280
292
  - **One writer per shared file** — every board/ledger/verdict write goes through
281
- `ingest-result.mjs`; workers return data and never touch shared state.
282
- - **Traceability is oracle-checked, opt-in** — `trace-lint.mjs` verifies covers-closure and
293
+ `harness reduce ingest`; workers return data and never touch shared state.
294
+ - **Traceability is oracle-checked, opt-in** — `harness verify trace` verifies covers-closure and
283
295
  wiring reachability from the committed spine artifacts; it ships advisory (warn-only) and every
284
296
  arm is skipped when its artifact is absent, so older specs are non-regressed.
285
297
 
@@ -289,14 +301,13 @@ Stated plainly, because you will hit them:
289
301
 
290
302
  - **The `--tiny` lane is young.** It right-sizes the ceremony (two gates instead of eight) but
291
303
  keeps the T0 verification floor; its fit-check heuristics will need tuning against real use.
292
- - **Only half the trigger-eval story is measured.** Skill *discrimination* is:
293
- **0 false activations across 75 cross-skill hard negatives** (Haiku 4.5, 2026-07-26 the
294
- thirteen descriptions do not steal each other's work). *Activation* rate is measured but
295
- confounded and deliberately not quoted as a headline: 38 of 74 positive cases point at a
296
- referent ("coach **this feedback**") the probe never supplies, so a model that names the right
297
- skill and asks for the missing input scores as a miss. Method, per-skill numbers, and the fix
298
- are in [evals/README.md](evals/README.md) the harness ships a CI test that *fails* if
299
- fabricated results appear, and three earlier baselines were discarded rather than published.
304
+ - **Nothing here measures skill quality or activation.** There is no number for whether a
305
+ skill's description makes it fire on the right request, no measured craft delta, and no CI
306
+ check enforcing the honesty invariant on such numbers. The structural suite is the coverage
307
+ that exists, and it is about mechanism rather than quality it proves a gate denies and an
308
+ oracle discriminates, never that a skill's output is good.
309
+ - **The gates are verified; the craft is not.** A hook that denies is proven by a test that
310
+ watches it deny. A skill that writes a good spec tree is, at present, taken on trust.
300
311
 
301
312
  Contributions to any of these are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md).
302
313
 
@@ -315,37 +326,40 @@ claude --plugin-dir . # load this working copy without installing
315
326
  .claude-plugin/
316
327
  plugin.json # plugin manifest
317
328
  marketplace.json # marketplace listing (points at this repo)
318
- skills/<name>/SKILL.md # the 13 harness skills (+ references/ and assets/)
319
- skills/tech-lead/scripts|schemas/ # orchestrator pipeline: init-run, gate-answers,
320
- # budget-check, compile-order, ingest-result, validate-envelope,
321
- # t0-verify, trace-lint, aegis-digest, run-snapshot,
322
- # stats + envelope and gate-answer schemas
323
- skills/ba-pitch-analyzer/scripts/ # planner mechanics: board-derive, spec-lint
324
- skills/spec-evaluator/scripts/ # verdict-ledger (reference impl of the flip/confidence grammar)
329
+ skills/<name>/SKILL.md # the 12 harness skills (+ references/ and assets/)
330
+ skills/tech-lead/schemas/ # the envelope port: WorkOrder, WorkResult, domain registry
331
+ skills/tech-lead/workflows/shapeup-run.js # the BUILD-phase pipeline, on the native Workflow runtime
332
+ kernel/harness.mjs # ONE entry point for every deterministic step; the whole permission grant
333
+ kernel/{verify,reduce,probe,init,report}/ # its subcommands, plus compile and gate at the root
334
+ kernel/lib/ # argv (the typed CLI boundary), paths (+ the run key), contract (shape)
325
335
  commands/*.md # slash commands (/ship + the 9 phase commands)
326
- agents/*.md # subagents (reviewer)
327
- hooks/ # hooks.json + safety-spine, gate-l2, gate-intake, gate-deadline,
328
- # sandbox-guard (PreToolUse),
329
- # gate-zerowork (Stop, blocking), anti-rationalization, slop-cleaner (Stop, advisory),
330
- # compact-snapshot (PreCompact), session-rehydrate (SessionStart)
336
+ hooks/ # hooks.json + the four walls: safety-spine, gate-intake, sandbox-guard
337
+ # (PreToolUse) + gate-zerowork (Stop, the one blocking hook)
338
+ # + dispatch-receipt (PostToolUse, denies nothing, attests which skill ran)
339
+ # + lib/decision.mjs (every hook records allow / deny / error)
340
+ oracles/ # the evaluation-contract oracle registry (test · snapshot · http · process)
341
+ bin/init.mjs # `npx shapeup-sdlc init` — scaffolds all three CLI targets
331
342
  scripts/install-harness.sh, migrate.sh # stable public entrypoints (fresh install / update)
332
- tools/demo/record-demo.mjs # regenerates docs/assets/demo-gate.svg
333
- scripts/shapeup-sdlc/ # dev/CI tooling: lib/, migrations/, oracles/,
334
- # trigger-eval.mjs, distribute.js
343
+ scripts/shapeup-sdlc/lib/ # shell libs both entrypoints source
344
+ tools/ # repo-only: demo/
345
+ # demo/record-demo.mjs (regenerates docs/assets/demo-gate.svg)
346
+ tests/structural.mjs, tests/structural/*.mjs # Tier 0 — 880+ checks, zero LLM calls
335
347
  docs/install.md, upgrading.md, glossary.md
336
- docs/design/ # the design document (pipeline, gates, circuit breaker, ERD)
337
- docs/internal/launch/ # directory-submission copy
338
- .github/workflows/ # CI + release
348
+ docs/design/ # the design document (pipeline, gates, circuit breaker, ERD) + adr/
349
+ docs/visualize/ # rendered views of the tree and the pipeline
350
+ .github/workflows/ # CI + release (release publishes to npm via OIDC)
339
351
  ```
340
352
 
341
353
  ## Release
342
354
 
343
- 1. Bump `version` in `.claude-plugin/plugin.json`.
355
+ 1. Bump `version` in **both** `.claude-plugin/plugin.json` and `package.json` — the release
356
+ workflow fails if either disagrees with the tag.
344
357
  2. Update `CHANGELOG.md`.
345
- 3. Tag and push: `git tag v1.3.1 && git push origin v1.3.1`.
358
+ 3. Tag and push: `git tag v1.7.0 && git push origin main --follow-tags`.
346
359
 
347
- The release workflow validates the plugin, checks the tag matches the manifest version,
348
- and publishes a GitHub release.
360
+ The workflow validates the plugin, checks the tag against both manifests, publishes a GitHub
361
+ release, and publishes to npm through **trusted publishing (OIDC)** — no `NPM_TOKEN`, no OTP, with
362
+ a SLSA provenance attestation attached automatically.
349
363
 
350
364
  ## Credits
351
365
 
package/SECURITY.md CHANGED
@@ -1,38 +1,61 @@
1
1
  # Security
2
2
 
3
- This plugin installs **eight hook entries (seven Node scripts + one `echo`)**, four of them in
4
- a `PreToolUse` position where they can deny tool calls. That is the product and it is also
5
- exactly the kind of surface a careful reviewer should want spelled out before installing.
6
- This page is that spelling-out.
3
+ This plugin installs **seven hook entries (six Node scripts + one `echo`)**: four in a
4
+ `PreToolUse` position, **all four of which can deny a tool call**, one `PostToolUse` hook that has no
5
+ deny path at all, and one `Stop`-position hook that can block a session from ending. That is the
6
+ product and it is also exactly the kind of surface a careful reviewer should want spelled out
7
+ before installing. This page is that spelling-out.
8
+
9
+ Count them yourself rather than taking the paragraph's word for it, because this paragraph has been
10
+ wrong before — it described a twelve-entry surface for the whole life of v2.0, after the hook diet cut
11
+ it to four walls and updated the table below without updating the sentence above it:
12
+
13
+ ```bash
14
+ node -e "const h=require('./hooks/hooks.json').hooks;
15
+ for (const [e,gs] of Object.entries(h)) for (const g of gs) for (const x of g.hooks)
16
+ console.log(e, g.matcher||'*', x.command.match(/[^/ ]+\.mjs/)?.[0] ?? '(echo)')"
17
+ ```
7
18
 
8
19
  ## Reporting a vulnerability
9
20
 
10
21
  Use [GitHub private vulnerability reporting](https://github.com/nguyenvanphituoc/shapeup-sdlc-plugin/security/advisories/new)
11
- for anything exploitable — especially anything that would let a run **escape a deny** (talk
12
- past GATE L2, write outside a substrate, widen its own safety overrides) or exfiltrate data.
22
+ for anything exploitable — especially anything that would let a run **escape a deny** (write
23
+ outside a substrate, dispatch on an uncompiled order, widen its own safety overrides) or
24
+ exfiltrate data.
13
25
  For non-sensitive hardening ideas, an ordinary issue is fine.
14
26
 
15
- In scope: the hooks, the pipeline scripts (`compile-order` / `ingest-result` /
16
- `validate-envelope` / `t0-verify`), the installer/migration shell scripts, and any prompt-
17
- injection path through skill files. Please do not test against machines you don't own.
27
+ In scope: the hooks, the kernel (`kernel/harness.mjs` and every subcommand beneath it), the
28
+ installer/migration shell scripts, and any prompt-injection path through skill files. Please do not
29
+ test against machines you don't own.
18
30
 
19
31
  ## The claims, stated so they can be falsified
20
32
 
21
- 1. **No hook or pipeline script makes a network request.** There is no `fetch`, no
33
+ 1. **No hook or kernel subcommand makes a network request.** There is no `fetch`, no
22
34
  `node:http(s)`, no `node:net`, no shelling out to `curl`/`wget` anywhere in `hooks/` or
23
- `skills/*/scripts/`. Verify: `grep -rnE "fetch|node:http|node:net|curl|wget" hooks/ skills/*/scripts/`.
35
+ `kernel/`. Verify: `grep -rnE "fetch|node:http|node:net|curl|wget" hooks/ kernel/`.
24
36
  2. **No hook has dependencies.** Plain `.mjs`, Node standard library only, no `node_modules`,
25
37
  no install-time scripts. What you read is what runs.
26
38
  3. **Every hook is fail-open by design.** Unparseable input, missing state files, or an
27
39
  unrecognized invocation shape → the hook defers and the normal permission flow proceeds. A
28
- hook denies only when it can positively prove its condition (a non-green board, a matched
29
- destructive command, a path outside a declared substrate, an invalid order file).
40
+ hook denies only when it can positively prove its condition (a matched destructive command, a
41
+ path no live order's substrate permits, an invalid order file, an empty intake).
30
42
  4. **The model cannot widen its own safety envelope.** The escape hatch
31
43
  (`.shapeup/safety-overrides.json`) is human-authored; `safety-spine` itself denies any
32
44
  write/move/delete touching that file, a malformed overrides file is treated as absent
33
- (override channel fails closed), and every exercised override is logged.
34
- 5. **Stop hooks never block.** The two Stop-position hooks are advisory: they emit at most a
35
- `systemMessage` and always exit 0.
45
+ (override channel fails closed), and every exercised override is logged. The same principle
46
+ covers `.shapeup/active-order`, which `sandbox-guard` reads to find the run whose orders fence
47
+ a worker's writes: it sits outside the run-trace carve-out, so a worker cannot repoint its own
48
+ sandbox.
49
+ 5. **Exactly one hook can block, and only on a mechanical absence.** `gate-zerowork` returns
50
+ `decision: "block"` in one state: the session dispatched the orchestrator and left no run
51
+ receipt on disk. It makes no judgement about quality — it reports that there is no work to
52
+ judge. `stop_hook_active` caps it at one block per stop chain. Every other check that used to
53
+ emit an advisory `systemMessage` at `Stop` now lands in the ship report instead, where it is a
54
+ section a person can read afterwards rather than a line in a transcript.
55
+ 6. **Every hook decision is recorded.** `hooks/lib/decision.mjs` is the only exit path a hook
56
+ has, so allow, deny, block and error each leave a row in `.shapeup/decisions.jsonl`. An
57
+ inert hook and a permitting hook are therefore distinguishable — which matters, because
58
+ "exit 0, no output" is what both used to look like.
36
59
 
37
60
  If you find any of these to be false, that is a vulnerability — report it as claim #ⁿ.
38
61
 
@@ -44,25 +67,24 @@ sitting, and reading them is the recommended review.
44
67
  | Hook | Event (matcher) | Reads | Can deny | Never does |
45
68
  |---|---|---|---|---|
46
69
  | [`safety-spine.mjs`](hooks/safety-spine.mjs) | PreToolUse (`Bash\|Read\|Write\|Edit\|MultiEdit`) | The proposed command/path; `.shapeup/safety-overrides.json` | Yes — provably destructive ops only: `rm -rf` on unrecoverable targets, `git push --force` / push to main, `git reset --hard`, `git clean -fdx`, `DROP TABLE`/`TRUNCATE`, reads of `.env`/keys/cloud credentials, and any write to its own overrides file | Never blocks an unmatched command; `--force-with-lease` stays allowed |
47
- | [`gate-l2.mjs`](hooks/gate-l2.mjs) | PreToolUse (`Skill`) | The round's task board (`.shapeup/<slug>/tasks/`) | Yes — the once-per-round EVAL dispatch while any task is unfinished | Never gates a single-task eval (`--task`); no board defers |
48
- | [`validate-envelope.mjs`](skills/tech-lead/scripts/validate-envelope.mjs) | PreToolUse (`Skill\|Agent`) | The `--order` file named in the dispatch; the JSON schemas | Yes — a worker dispatch whose order file is missing or schema-invalid | Never gates a dispatch that carries no `--order` (standalone skill use stays free) |
49
- | [`sandbox-guard.mjs`](hooks/sandbox-guard.mjs) | PreToolUse (`Edit\|Write\|MultiEdit`) | The target path; the active scope contract | Yes — writes outside the active scope's substrate whitelist | No-op unless a scope is active; the active feature's own `.shapeup/<slug>/` run-trace is always writable. Appends denials to the local pathology log |
50
- | [`anti-rationalization.mjs`](hooks/anti-rationalization.mjs) | Stop | Board/T0 facts vs. the reply's completion claims | **No**advisory `systemMessage` only | Never `decision:"block"`, never exit 2 |
51
- | [`slop-cleaner.mjs`](hooks/slop-cleaner.mjs) | Stop | The session's git diff (local `git diff`, via `spawnSync`) | **No**advisory `systemMessage` flagging TODO / `console.log` / commented-out leftovers | Same never blocks |
52
- | [`compact-snapshot.mjs`](hooks/compact-snapshot.mjs) | PreCompact | Run state | No — writes `.shapeup/<slug>/run-snapshot.json` before compaction | Touches nothing outside `.shapeup/` |
53
- | [`session-rehydrate.mjs`](hooks/session-rehydrate.mjs) | SessionStart (`compact\|resume`) | The saved run snapshot | No — injects the "trust the files, not the summary" hint when a run is in flight | Silent when no run is in flight |
70
+ | [`gate-intake.mjs`](hooks/gate-intake.mjs) | PreToolUse (`Skill`) | The `tech-lead` dispatch's own arguments | Yes — an orchestrator dispatch carrying no resolvable intake (no pitch, spec, resume or requirement text) | Fails open on `--order` and on any ambiguous arg shape |
71
+ | [`harness verify envelope`](kernel/verify/envelope.mjs) | PreToolUse (`Skill\|Agent`) | The `--order` file named in the dispatch; the JSON schemas | Yes — a worker dispatch whose order file is missing or schema-invalid | Never gates a dispatch that carries no `--order` (standalone skill use stays free) |
72
+ | [`sandbox-guard.mjs`](hooks/sandbox-guard.mjs) | PreToolUse (`Edit\|Write\|MultiEdit`) | The target path; the `substrate` block of every LIVE order (compiled, not yet ingested) | Yes — any write no live order permits: outside every `allowed`/`shared`, inside any `frozen`, or a `Write` to an `append_only` path | No-op unless an order is live; the active feature's own `.shapeup/<slug>/` run-trace is always writable. Appends denials to the local pathology log |
73
+ | [`dispatch-receipt.mjs`](hooks/dispatch-receipt.mjs) | PostToolUse (`Skill\|Agent`) | The `--order` file named in the dispatch; the tool result's own report of which skill ran | **No — it has no deny path at all.** It records that the shipped skill ran, so `harness reduce ingest` can refuse a result no dispatch produced | Never writes an attestation for a result that does not name a resolved skill; never fails the call it observes (every write is inside `try`/`catch`) |
74
+ | [`gate-zerowork.mjs`](hooks/gate-zerowork.mjs) | Stop | Run receipts on disk; the session transcript; the decision ledger | **Yesthe one blocking hook.** Returns `decision:"block"` when the session dispatched the orchestrator and produced no run receipt | Defers the moment any receipt exists; `stop_hook_active` caps it at one block per stop chain |
54
75
 
55
- (The eighth `hooks.json` entry is a plain `echo` on SessionStart confirming the plugin loaded.)
76
+ (The remaining `hooks.json` entry is a plain `echo` on SessionStart confirming the plugin loaded.)
56
77
 
57
78
  ## Data handling
58
79
 
59
80
  - **Nothing leaves the machine.** Run state lives in the gitignored `.shapeup/`; telemetry
60
- is a per-machine JSONL shard under `shapeup/metrics/` that travels only if you
61
- commit it. There is no phone-home of any kind.
81
+ is a per-machine JSONL shard under `.shapeup/metrics/`, inside that same gitignored root,
82
+ so it travels only if you deliberately un-ignore and commit it. There is no phone-home of
83
+ any kind.
62
84
  - **The safety-spine actively blocks secret reads** (`.env`, `*.pem`, `*.key`, ssh/cloud
63
85
  credentials) rather than merely not making them.
64
86
  - The installer (`scripts/install-harness.sh`) writes only into the target project
65
- (`.claude/`, `.agents/`, `.codex/`, `shapeup/`, `.gitignore`) and tells you what it
87
+ (`.claude/`, `shapeup/`, `.gitignore`) and tells you what it
66
88
  is going to do first; the `curl | bash` form requires an explicit `--yes` for exactly that
67
89
  reason.
68
90