shapeup-sdlc 1.7.0 → 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 (98) hide show
  1. package/.claude/settings.local.example.json +5 -5
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/AGENTS.md +17 -3
  4. package/README.md +124 -103
  5. package/SECURITY.md +37 -30
  6. package/bin/init.mjs +77 -47
  7. package/bin/lib/grant.mjs +145 -0
  8. package/commands/build.md +7 -6
  9. package/commands/ship.md +29 -16
  10. package/commands/wire.md +1 -1
  11. package/hooks/dispatch-receipt.mjs +195 -0
  12. package/hooks/gate-intake.mjs +3 -3
  13. package/hooks/gate-zerowork.mjs +25 -24
  14. package/hooks/hooks.json +9 -48
  15. package/hooks/lib/decision.mjs +19 -8
  16. package/hooks/safety-spine.mjs +3 -3
  17. package/hooks/sandbox-guard.mjs +84 -40
  18. package/{skills/tech-lead/scripts/compile-order.mjs → kernel/compile.mjs} +283 -41
  19. package/{skills/tech-lead/scripts/gate-answers.mjs → kernel/gate.mjs} +58 -14
  20. package/kernel/harness.mjs +134 -0
  21. package/{skills/tech-lead/scripts/fit-check.mjs → kernel/init/fit.mjs} +15 -12
  22. package/{skills/tech-lead/scripts/init-run.mjs → kernel/init/run.mjs} +152 -31
  23. package/{skills/tech-lead/scripts → kernel}/lib/argv.mjs +52 -31
  24. package/{skills/tech-lead/scripts/lib/contract-md.mjs → kernel/lib/contract.mjs} +251 -7
  25. package/kernel/lib/paths.mjs +491 -0
  26. package/kernel/probe/concurrency.mjs +510 -0
  27. package/{skills/tech-lead/scripts/aegis-digest.mjs → kernel/probe/digest.mjs} +9 -10
  28. package/kernel/probe/eval.mjs +77 -0
  29. package/kernel/probe/leg.mjs +125 -0
  30. package/{skills/tech-lead/scripts/resume-state.mjs → kernel/probe/resume.mjs} +204 -63
  31. package/{skills/tech-lead/scripts → kernel/probe}/stats.mjs +93 -11
  32. package/kernel/probe/t0.mjs +66 -0
  33. package/{skills/ba-pitch-analyzer/scripts/board-derive.mjs → kernel/reduce/board.mjs} +99 -23
  34. package/kernel/reduce/graph.mjs +437 -0
  35. package/{skills/tech-lead/scripts/hill-derive.mjs → kernel/reduce/hill.mjs} +28 -9
  36. package/kernel/reduce/ingest.mjs +633 -0
  37. package/{hooks/slop-cleaner.mjs → kernel/reduce/leftovers.mjs} +40 -57
  38. package/{skills/tech-lead/scripts/ship-report.mjs → kernel/reduce/ship.mjs} +61 -13
  39. package/{skills/tech-lead/scripts/run-snapshot.mjs → kernel/reduce/snapshot.mjs} +21 -15
  40. package/{skills/spec-evaluator/scripts/verdict-ledger.mjs → kernel/reduce/verdict.mjs} +13 -7
  41. package/kernel/report/export.mjs +325 -0
  42. package/kernel/report/facts.mjs +347 -0
  43. package/{skills/tech-lead/scripts/budget-check.mjs → kernel/verify/budget.mjs} +15 -12
  44. package/kernel/verify/dispatch.mjs +114 -0
  45. package/{skills/tech-lead/scripts/validate-envelope.mjs → kernel/verify/envelope.mjs} +20 -15
  46. package/{skills/tech-lead/scripts/lib → kernel/verify}/ratchet-tree.mjs +36 -14
  47. package/kernel/verify/skills.mjs +125 -0
  48. package/kernel/verify/spec.mjs +559 -0
  49. package/{skills/tech-lead/scripts/t0-verify.mjs → kernel/verify/t0.mjs} +134 -24
  50. package/{skills/tech-lead/scripts/trace-lint.mjs → kernel/verify/trace.mjs} +26 -11
  51. package/oracles/http-oracle.mjs +1 -1
  52. package/oracles/process-oracle.mjs +1 -1
  53. package/oracles/snapshot-oracle.mjs +1 -1
  54. package/oracles/test-oracle.mjs +1 -1
  55. package/package.json +11 -9
  56. package/skills/ba-pitch-analyzer/SKILL.md +5 -5
  57. package/skills/ba-pitch-analyzer/assets/templates/_index.tmpl.md +1 -1
  58. package/skills/ba-pitch-analyzer/assets/templates/api-feasibility.tmpl.md +12 -7
  59. package/skills/ba-pitch-analyzer/assets/templates/contracts/third-party-api.contract.tmpl.md +6 -3
  60. package/skills/ba-pitch-analyzer/assets/templates/cross-context/migration-plan.tmpl.md +5 -4
  61. package/skills/ba-pitch-analyzer/assets/templates/cross-context/team-handoff.tmpl.md +23 -13
  62. package/skills/ba-pitch-analyzer/assets/templates/scope-summary.tmpl.md +17 -12
  63. package/skills/ba-pitch-analyzer/assets/templates/synthesis.tmpl.md +17 -38
  64. package/skills/ba-pitch-analyzer/assets/templates/task.tmpl.md +3 -0
  65. package/skills/ba-pitch-analyzer/references/contract-patterns.md +8 -4
  66. package/skills/ba-pitch-analyzer/references/doc-schemas.md +2 -0
  67. package/skills/ba-pitch-analyzer/references/task-generation.md +2 -2
  68. package/skills/qa-edge-hunter/SKILL.md +7 -3
  69. package/skills/scope-architect/SKILL.md +40 -6
  70. package/skills/solution-architect/SKILL.md +19 -4
  71. package/skills/spec-evaluator/SKILL.md +12 -2
  72. package/skills/task-executor/SKILL.md +7 -6
  73. package/skills/tech-lead/SKILL.md +50 -38
  74. package/skills/tech-lead/references/gates.md +69 -20
  75. package/skills/tech-lead/references/protocol.md +832 -0
  76. package/skills/tech-lead/schemas/domain.schema.json +341 -66
  77. package/skills/tech-lead/schemas/work-order.schema.json +11 -2
  78. package/skills/tech-lead/schemas/work-result.schema.json +1 -1
  79. package/skills/tech-lead/workflows/shapeup-run.js +1313 -750
  80. package/hooks/anti-rationalization.mjs +0 -238
  81. package/hooks/compact-snapshot.mjs +0 -47
  82. package/hooks/gate-deadline.mjs +0 -147
  83. package/hooks/gate-l2.mjs +0 -161
  84. package/hooks/session-rehydrate.mjs +0 -108
  85. package/skills/ba-pitch-analyzer/scripts/spec-lint.mjs +0 -239
  86. package/skills/spec-evaluator/README.md +0 -93
  87. package/skills/tech-lead/README.md +0 -71
  88. package/skills/tech-lead/references/delegation.md +0 -261
  89. package/skills/tech-lead/references/hard-rules.md +0 -34
  90. package/skills/tech-lead/references/invocation.md +0 -45
  91. package/skills/tech-lead/references/ledger-schema.md +0 -213
  92. package/skills/tech-lead/references/round-protocol.md +0 -234
  93. package/skills/tech-lead/references/state-model.md +0 -66
  94. package/skills/tech-lead/scripts/ingest-result.mjs +0 -258
  95. package/skills/tech-lead/scripts/lib/is-main.mjs +0 -81
  96. package/skills/tech-lead/scripts/lib/paths.mjs +0 -280
  97. package/skills/tech-lead/scripts/run-workflow.mjs +0 -381
  98. package/skills/translator/README.md +0 -66
@@ -35,14 +35,15 @@ audit_score: 0
35
35
 
36
36
  The longest sequential chain — minimum time to complete if parallelized optimally.
37
37
 
38
- ```
39
- TASK-NNN → TASK-NNN → TASK-NNN → TASK-NNN
40
- Nh Nh Nh Nh
41
- ```
42
-
43
- **Critical path estimate:** Nh total
38
+ **Critical path estimate:** Nh total, N steps
44
39
  *(All other work can happen in parallel alongside this chain)*
45
40
 
41
+ <!-- Record the DERIVED numbers only — total hours and step count, both from
42
+ `harness reduce board`. The chain's task ids belong to the LOCAL board
43
+ (.shapeup/<slug>/tasks/), which is gitignored and renumbers per machine; this
44
+ document is committed, so an id written here dangles on every other clone
45
+ (spec-lint TIER-DIRECTION). Read the id-level chain off the board itself. -->
46
+
46
47
  ---
47
48
 
48
49
  ## Package Distribution
@@ -58,12 +59,16 @@ TASK-NNN → TASK-NNN → TASK-NNN → TASK-NNN
58
59
 
59
60
  ## Parallel Opportunities
60
61
 
61
- Tasks with no interdependency that can run simultaneously:
62
+ How much of the board can run simultaneously — **counts and use cases, never task ids.** This file
63
+ is COMMITTED; the board is not, and its ids renumber per machine (spec-lint TIER-DIRECTION).
64
+
65
+ | Group | Use cases | Tasks | Can start after |
66
+ |-------|-----------|-------|-----------------|
67
+ | Group A | UC-x, UC-y | N | nothing — no dependency |
68
+ | Group B | UC-z | N | Group A |
62
69
 
63
- | Group | Tasks | Can start after |
64
- |-------|-------|----------------|
65
- | Group A | TASK-NNN, TASK-NNN | TASK-NNN completes |
66
- | Group B | TASK-NNN | TASK-NNN completes |
70
+ The per-scope release order is `scope-board.md`'s, keyed on `scope_id`. Cite it rather than
71
+ restating it here.
67
72
 
68
73
  ---
69
74
 
@@ -94,7 +99,7 @@ Carried from [[_index#Rabbit-Holes]]:
94
99
 
95
100
  ## Execution Recommendation
96
101
 
97
- <!-- Filled from spec-lint.mjs output -->
102
+ <!-- Filled from harness verify spec output -->
98
103
 
99
104
  **Audit Score: N/100**
100
105
 
@@ -166,50 +166,29 @@ Derived from: `_index.md` rabbit holes + `api-feasibility.md` SPIKE blocks + `in
166
166
 
167
167
  | Cut | At | Reason | Traded for (if any) |
168
168
  |-----|-----|-------|---------------------|
169
- | ~~[cut capability]~~ | GATE-N | appetite overflow — saved for a later bet | TASK-NNN |
169
+ | ~~[cut capability]~~ | GATE-N | appetite overflow — saved for a later bet | [UC or scope it was traded for] |
170
170
 
171
171
  *A Cut is a healthy shaping signal, not debt. Revisit it at the betting table next cycle.*
172
172
 
173
173
  ---
174
174
 
175
- ## S-03 — Dependency Graph
175
+ ## S-03 — Dependency Shape
176
176
 
177
- > Open this section when **Dependency** is 🟡 or 🔴, or when planning parallel work.
177
+ > Open this section when **Dependency** is 🟡 or 🔴.
178
178
 
179
- Derived from: `depends_on` and `unlocks` in every task frontmatter + `estimated_hours`.
179
+ Derived from: `depends_on` in every task frontmatter. **Counts and shape only — no task ids.**
180
+ This document is COMMITTED and the board is not: ids live in the gitignored tier and renumber on
181
+ every regeneration, so an id written here resolves on the machine that wrote it and nowhere else.
182
+ spec-lint reds a `TASK-` id anywhere in the committed tree (TIER-DIRECTION).
180
183
 
181
- ### Critical Path
184
+ | Metric | Value |
185
+ |---|---|
186
+ | Critical path | N tasks · NN hours · NN% of total estimated hours |
187
+ | Widest parallel wave | N tasks |
188
+ | Tasks with no dependency | N |
189
+ | Single points of failure (block > 2 downstream) | N |
182
190
 
183
- ```
184
- Critical path: N tasks · NN hours · NN% of total estimated hours
185
-
186
- TASK-001 [SPIKE] spike-[api]-feasibility 2h
187
- └─ blocks ──► TASK-004, TASK-005, TASK-006
188
- TASK-002 [TASK] shared-schema 3h ← parallel (no dependency on 001)
189
- TASK-003 [TASK] contract-stub 2h ← parallel
190
- TASK-004 [FEAT] implement-[repo] ⏳ blocked by TASK-001 4h
191
- └─ blocks ──► TASK-005
192
- TASK-005 [FEAT] [use-case]-service ⏳ blocked by TASK-004 6h
193
- └─ blocks ──► TASK-006, TASK-007
194
- TASK-006 [FEAT] [feature]-ui ⏳ blocked by TASK-005 8h
195
- TASK-007 [FEAT] [feature]-ui-edge-cases ⏳ blocked by TASK-005 4h
196
- ```
197
-
198
- ### Parallel Opportunities
199
-
200
- Tasks at the same dependency depth with no interdependency — can be executed in parallel:
201
-
202
- | Wave | Tasks | Total Hours | Can Parallelize |
203
- |------|-------|-------------|-----------------|
204
- | Wave 1 (no deps) | TASK-001, TASK-002, TASK-003 | Nh | ✅ yes — 3 agents |
205
- | Wave 2 (after 001) | TASK-004 | Nh | — single task |
206
- | Wave 3 (after 004) | TASK-005 | Nh | — single task |
207
- | Wave 4 (after 005) | TASK-006, TASK-007 | Nh | ✅ yes — 2 agents |
208
-
209
- ### Single Points of Failure
210
-
211
- Tasks whose delay cascades to > 2 downstream tasks:
212
-
213
- | Task | Blocks | Cascaded Hours at Risk |
214
- |------|--------|----------------------|
215
- | TASK-NNN | TASK-NNN, TASK-NNN, TASK-NNN | Nh |
191
+ **The per-scope build order — which scopes go in which wave, and what each waits on — lives in
192
+ `scope-board.md`, not here.** `scope-architect` writes that board and is the only worker that knows
193
+ the scope ids; it runs after this document, so the ordering cannot be expressed here in a key that
194
+ survives a clone. Cite the board, never restate it.
@@ -9,6 +9,9 @@ priority: N
9
9
  depends_on: []
10
10
  unlocks: []
11
11
  use_case_refs: []
12
+ scope_id: "" # optional — set ONLY when several scopes share this task's use
13
+ # case and spec-lint SCOPE-PARTITION says the UC anchor cannot
14
+ # decide who builds it. Names a committed scope_id (LOCAL→SHARED).
12
15
  entities: []
13
16
  repositories: []
14
17
  linked_docs: []
@@ -117,11 +117,15 @@ Every contracts folder must have an `_index.md` registry:
117
117
  ```markdown
118
118
  # Contract Registry — [feature-slug]
119
119
 
120
- | Repository | Source Type | Service / Engine | Status | SPIKE Task |
121
- |-----------|------------|-----------------|--------|------------|
122
- | [[FramerPageRepository]] | third-party-api | Framer REST API | ⚠️ speculative | [[TASK-001]] |
120
+ | Repository | Source Type | Service / Engine | Status | Spike |
121
+ |-----------|------------|-----------------|--------|-------|
122
+ | [[FramerPageRepository]] | third-party-api | Framer REST API | ⚠️ speculative | open |
123
123
  | [[PageCacheRepository]] | offline-storage | SQLite/Drizzle | ✅ confirmed | — |
124
124
  | [[UserSessionRepository]] | be-service | apps/api /auth | ✅ confirmed | — |
125
+
126
+ The Spike column carries a STATUS, not a task id. The registry is committed; the board is
127
+ not, and its ids renumber on every regeneration — so a task id recorded here resolves on
128
+ the machine that wrote it and nowhere else (spec-lint TIER-DIRECTION).
125
129
  ```
126
130
 
127
131
  This registry is the entry point for the spec-lint structure checks.
@@ -147,6 +151,6 @@ Every implementation task that uses a repository MUST:
147
151
 
148
152
  3. If contract is still `speculative` at task-generation time:
149
153
  ```markdown
150
- > ⏳ BLOCKED by [[TASK-001-spike-framer-feasibility]]
154
+ > ⏳ BLOCKED spike open, see [[api-feasibility#API-01]]
151
155
  > Unblock condition: [[contracts/framer-page.contract.md]] has no remaining ⏳ TBD fields
152
156
  ```
@@ -217,6 +217,8 @@ depends_on: [] # other TASK IDs: [TASK-001, TASK-002] — the
217
217
  unlocks: [] # DERIVED — inverse of the board's depends_on graph, recomputed
218
218
  # on every board write; never hand-authored (v3.3)
219
219
  use_case_refs: [] # UC IDs this task implements: [UC-CreateOrder]
220
+ scope_id: "" # optional disambiguator — the scope that builds this task.
221
+ # Needed only when >1 scope shares a use case (SCOPE-PARTITION).
220
222
  entities: []
221
223
  repositories: []
222
224
  linked_docs: [] # [[usecase]], [[domain-model#section]]
@@ -362,7 +362,7 @@ Slug rules:
362
362
 
363
363
  **`depends_on` is the single authoritative edge; `unlocks` is derived, never hand-authored.**
364
364
  On EVERY board write — analyze, reconcile — recompute (via
365
- `board-derive.mjs --write`, never by hand) the `unlocks` field of every task on the board as the
365
+ `harness reduce board --write`, never by hand) the `unlocks` field of every task on the board as the
366
366
  exact inverse of the full board's `depends_on` graph, then write it. Adding one task that
367
367
  declares `depends_on: [TASK-007]` therefore rewrites `TASK-007.unlocks` in the same pass.
368
368
  "Write both sides when you remember" allows drift; a derived field cannot drift
@@ -563,7 +563,7 @@ tasks). Scope (Basecamp sense) maps onto a UC; an invariant lives *inside* the U
563
563
  task-executor / the tech lead; this mode only surfaces the disagreement.
564
564
  9. Regenerate ONLY the derived files: tasks/_index.md, scope-summary.md, synthesis.md
565
565
  (+ the unlocks frontmatter recompute from step 7).
566
- 10. Run board-derive.mjs (Appetite Guard arithmetic, below); report overflow as a discovery.
566
+ 10. Run harness reduce board (Appetite Guard arithmetic, below); report overflow as a discovery.
567
567
  ```
568
568
 
569
569
  **Appetite Guard (forcing function, not a report):**
@@ -33,14 +33,17 @@ tech-lead: ... GATE L2 → EVAL → GATE L3 PASS ──► QA EDGE HUNT (you)
33
33
  |------|----------|
34
34
  | Read EVAL-*.md to map covered territory — then hunt OUTSIDE it | Re-probe anything the evaluator already graded |
35
35
  | Charter edges via six fixed lenses, minus covered territory | Author or extend `## Test Surface` (that is the planner's retrofit-surface operation) |
36
- | Execute charters on the **running app** (session-based exploratory) | Read-only speculate from code ("this looks racy") — every finding needs a live repro |
36
+ | Execute charters against the **running deliverable** (session-based exploratory) | Read-only speculate from code ("this looks racy") — every finding needs a live repro |
37
37
  | Return each finding in the WorkResult's `discoveries[]`, **always `~`** | Promote `~` → must-have (PO/TL at SHIP S.0; severity-hint is advice, not a decision) |
38
38
  | Emit `qa/hunt-report.md` — charters run/cut, findings by lens | Render a verdict, score, or PASS/FAIL of any kind |
39
39
 
40
40
  Pure worker (harness rule: stateless workers, one stateful orchestrator). Its WorkOrder
41
41
  carries `payload.feature`, `payload.spec_folder`, `payload.eval_report`, `payload.app_url`,
42
42
  `payload.kb_rules_path`, and `payload.ledger` (the discovery ledger, READ-ONLY — covered-territory
43
- context so a hunt does not re-report what is already known); its write surface is
43
+ context so a hunt does not re-report what is already known). **`app_url` is null when the
44
+ deliverable is not served over HTTP** — a CLI, a library, a batch job. That is a normal order, not a
45
+ malformed one: drive the built entry point instead, exactly as the Test Surface's process rows do.
46
+ Do not refuse the hunt, and do not invent a URL. Its write surface is
44
47
  `.shapeup/<feature>/qa/**` only. The Hunter never touches the discovery ledger itself —
45
48
  ingest appends its `discoveries[]` under a `## Discovered` section, preserving single-writer
46
49
  mechanically.
@@ -50,7 +53,8 @@ mechanically.
50
53
  ## Workflow
51
54
 
52
55
  ```
53
- ⏸ GATE Q0 │ Preflight ────► hard: app running? EVAL verdict PASS? ledger exists?
56
+ ⏸ GATE Q0 │ Preflight ────► hard: deliverable reachable (one real request at `app_url`, or one
57
+ │ real invocation of the entry point when it is null)? EVAL PASS? ledger?
54
58
  │ soft: Test Surface present? absent → DEGRADED MODE offer
55
59
  Phase Q1 │ Charter Map ──► 6 lenses × UC tree − covered territory (EVAL-probed rows/AC)
56
60
  ⏸ GATE Q1 │ Charter Review► PO/TL hammer the charter list (QA's own appetite is fixed too)
@@ -13,7 +13,7 @@ harness enforces mechanically: the sandbox hook denies writes outside a substrat
13
13
  runs the fixtures, the evaluator asserts only against the affordance manifest. This skill is
14
14
  the **sole writer** of scope contracts — a distinct authority from the planner (task
15
15
  decomposition) and a distinct failure mode (directory-thinking, PA1) deserving its own
16
- anti-rationalization table.
16
+ the ship report's census table.
17
17
 
18
18
  ## Input contract — the WorkOrder
19
19
 
@@ -21,7 +21,7 @@ anti-rationalization table.
21
21
  |---|---|
22
22
  | `operation` | `map-scopes` — the only operation this skill has. It covers first slicing after the board exists, folding discovered items in, and re-slicing a stuck scope; the payload says which of those you are doing |
23
23
  | `payload.feature` / `payload.spec_folder` | Slug + committed spec (read ux-behavior.md for manifests; usecases for flows) |
24
- | `payload.tasks[]` | The board's tasks with their touched files — the slicing input |
24
+ | `payload.tasks[]` | The board's tasks with their touched files — the slicing INPUT only. Each carries `use_case_refs`; those UC ids are what you write into the contract. Never copy a task id into a contract |
25
25
  | `substrate.allowed` | `scopes/*.md` + `scope-board.md` — your ONLY write surface |
26
26
 
27
27
  ## Core process
@@ -37,7 +37,23 @@ anti-rationalization table.
37
37
  scalars and [a, b] lists, a `## Affordances` table for affordance_manifest, and a
38
38
  short `## Why this slice` paragraph. A reviewer must be able to read the substrate
39
39
  in a PR; regeneration preserves prose under headings you do not own.
40
- scope_id, topology_type, tasks[] — the stable join key is the scope
40
+ scope_id, topology_type — the stable join key is the scope
41
+ use_cases[] — the UC ids this scope implements.
42
+ THE ONLY LINK YOU WRITE TO THE
43
+ WORK: never task ids. The contract
44
+ is committed and the board is not,
45
+ so a TASK-NNN here dangles on
46
+ every other clone (spec-lint
47
+ TIER-DIRECTION reds it). The
48
+ scope's tasks are re-derived from
49
+ the board's own use_case_refs
50
+ covers[] — optional REQ-ids from
51
+ requirements.md this scope answers
52
+ for; stable, never renumbered
53
+ depends_on[] — scope_ids this scope builds AFTER.
54
+ This is the build ORDER — declare
55
+ it whenever one scope consumes
56
+ another's output, or the two race
41
57
  allowed_file_substrate[] — exact globs; the sandbox hook's
42
58
  write-whitelist; wrong here =
43
59
  a legitimate ESCALATE later
@@ -58,10 +74,23 @@ anti-rationalization table.
58
74
  hill_phase: "UPHILL_UNKNOWN" — ALWAYS; phase is derived from
59
75
  T0/T1/seesaw facts later,
60
76
  never authored
61
- 4 LINT node "${CLAUDE_PLUGIN_ROOT}/skills/ba-pitch-analyzer/scripts/spec-lint.mjs" --slug <slug>
62
- → PA1 (directory alignment), PA2 (>~15 files), DISJOINT (undeclared overlap).
77
+ 4 LINT node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" verify spec --slug <slug>
78
+ → PA1 (directory alignment), PA2 (>~15 files), DISJOINT (undeclared overlap),
79
+ SCOPE-ANCHOR (empty/unresolvable use_cases), TIER-DIRECTION (a task id in a
80
+ committed contract), SCOPE-DEPS (depends_on naming a scope that isn't here).
63
81
  Fix reds by re-slicing, not by silencing.
64
- 5 BOARD regenerate scope-board.md (scope_id, topology, task count, substrate size, lint)
82
+ 5 BOARD regenerate scope-board.md a VIEW of the contracts, nothing more:
83
+
84
+ | scope_id | topology | use_cases | depends_on | files | lint |
85
+
86
+ Every column restates a field the contract already declares, so the board can be thrown
87
+ away and rebuilt. Do NOT add a `wave` column: waves are Kahn levels of `depends_on` and
88
+ `probe resume` derives them at dispatch — a hand-written copy of a derived value drifts,
89
+ which is exactly why `unlocks` stopped being authored. The BUILD ORDER lives in each
90
+ contract's `depends_on`; the board only shows it.
91
+
92
+ A `TASK-` id anywhere in a contract or the board — a column, a cell, or a sentence in
93
+ the prose — is spec-lint TIER-DIRECTION red. The board is committed; ids are not.
65
94
  ```
66
95
 
67
96
  **Folding in a discovered item:** it joins the nearest scope only if the flow matches (extend that
@@ -78,6 +107,9 @@ mark the old one `superseded_by: [ids]` — never delete (branch and T0 history
78
107
  | "I'll widen the substrate a little so the doer stops escalating" | A wide substrate is no substrate. Split or add a shared_substrate entry, deliberately. |
79
108
  | "This scope looks downhill, I'll set the phase" | hill_phase is UPHILL_UNKNOWN at write, always. Facts move dots, not authors. |
80
109
  | "The old contract is superseded, delete it" | supersede-never-delete. History must stay attributable. |
110
+ | "Both scopes implement that UC, the tasks will sort themselves out" | They will not — both scopes get every task of that UC and three of four writes get denied. Give each scope its own use cases, or say so in deviations[] so the board can be stamped. |
111
+ | "I'll list the task ids so the contract says what it builds" | The board is gitignored and renumbers per machine; the contract is committed. Cite the UCs — the tasks are re-derived from them. |
112
+ | "Build order is obvious from the slice, I'll leave depends_on empty" | Nothing infers it any more. An undeclared edge means the two scopes are released into the same wave and race. |
81
113
  | "Fixtures can come later, leave the field empty" | Fixture at contract time or an explicit TBD flag — silence is how T0 goes blind. |
82
114
 
83
115
  ## Output contract — the WorkResult
@@ -98,6 +130,8 @@ territory — and any lint warn left standing, with why). You never touch task f
98
130
  ## Verification checklist
99
131
 
100
132
  - [ ] Every scope crosses layers or is declared CHOWDER; spec-lint PA1 = 0 red
133
+ - [ ] Every scope names ≥1 `use_cases` that resolves on disk, and NO contract carries a task id
134
+ - [ ] Every scope that consumes another's output declares it in `depends_on`
101
135
  - [ ] Substrates disjoint except declared shared_substrate (DISJOINT = 0 red)
102
136
  - [ ] Every interactive element in scope screens appears in exactly one affordance_manifest
103
137
  - [ ] Every scope has fixtures or an explicit TBD flag
@@ -23,7 +23,7 @@ orchestrator's `trace-lint` proves against real code at L1b. Your job is to make
23
23
 
24
24
  Two payoffs, one artifact:
25
25
  - **Reachability becomes checkable later.** Because you name each UC's `engine` (a real
26
- repo-relative module path) and the profile declares the `entry_point`, `trace-lint.mjs` can
26
+ repo-relative module path) and the profile declares the `entry_point`, `harness verify trace` can
27
27
  fold this map into its oracle *after the build*: a UC whose engine does not reach the
28
28
  `entry_point` via the import graph goes red. You supply the two anchors; the oracle does the
29
29
  proving.
@@ -70,8 +70,23 @@ guessed `main.js` would make the later oracle certify nothing.
70
70
  the import graph, it does not parse this field)
71
71
  affordance the player-visible thing this UC exposes once wired (the human
72
72
  end of the chain — what a user can DO, not an internal call)
73
- 3 WRITE shapeup/<slug>/wiring-map.md (WiringMap): {schema_version:1, feature,
74
- entry_point (echo of the profile), entries[]}. One entry per use case. A UC whose
73
+ 3 WRITE shapeup/<slug>/wiring-map.md (WiringMap): frontmatter for schema_version, feature
74
+ and entry_point (echo of the profile), then entries[] as ONE MARKDOWN TABLE under a
75
+ `## Wiring` heading — this exact shape, because it is the only one the reader parses:
76
+
77
+ ## Wiring
78
+
79
+ | use_case | engine | wiring_seam | entry_call_site | affordance |
80
+ |---|---|---|---|---|
81
+ | UC-01 | src/parsing.mjs | argv dispatch calls parseEnv | bin/envlint.mjs | envlint <file> |
82
+
83
+ One ROW per use case + engine pair — a UC carried by two engines gets two rows, never
84
+ one cell naming both. `engine` is a bare repo-relative path and nothing else: the
85
+ oracle resolves that cell against disk, and a cell like "`a.mjs` and `b.mjs` — two pure
86
+ modules" resolves to no file and is reported unverifiable. Put the explanation in the
87
+ `## Deviations` prose, never in the cell.
88
+
89
+ A UC whose
75
90
  engine has no attachment path is exactly the gap this artifact exists to surface —
76
91
  write the entry with the seam you INTEND and raise it in deviations[], so
77
92
  the build knows the wiring it must close. Your craft ends here: WRITE, then return the
@@ -132,5 +147,5 @@ seam, or an engine with no attachment path, and why). You never touch spec docs,
132
147
  # The reachability oracle is the ORCHESTRATOR's, run advisory at L1b — not part of your craft.
133
148
  # Standalone, you MAY preview it after writing the map (it self-skips arms whose artifacts are
134
149
  # absent, and is near-vacuous pre-build since the engine code does not exist yet):
135
- # node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/trace-lint.mjs" --slug checkout-vnpay
150
+ # node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" verify trace --slug checkout-vnpay
136
151
  ```
@@ -97,6 +97,15 @@ Done-when statements; `_index.md` Non-Go list. Which UCs are in scope comes from
97
97
  trust a handed hash. A verdict on a scoped spec without a T0 citation is structurally
98
98
  invalid, regardless of how convincing your own probing looked; generator prose ("tests
99
99
  pass", "verified locally") is never admissible evidence.
100
+ - **When a criterion names a command, run THAT command.** Not the one that works, not the
101
+ equivalent, not the underlying tool the named one wraps. If the named command fails, that is
102
+ the finding — cite it with its exit code and output, and grade the criterion on it. Measured:
103
+ a contract's verification clause named `npm test`, that exact invocation failed on the host's
104
+ Node version, `node --test` passed 45/45, and the report cited the second one. The verdict was
105
+ right about the deliverable and wrong about what it had verified, so a broken entry point
106
+ shipped under a PASS. Substituting a working command for the specified one is the same move as
107
+ accepting generator prose: it replaces the evidence the criterion asked for with evidence that
108
+ was easier to get.
100
109
 
101
110
  ---
102
111
 
@@ -107,6 +116,7 @@ Done-when statements; `_index.md` Non-Go list. Which UCs are in scope comes from
107
116
  | "The code clearly implements it, no need to run it" | Apps that look right still break when used. Probe the running app. |
108
117
  | "It failed, but the feature mostly works" | One FAIL fails the dimension. Thresholds are hard. |
109
118
  | "The generator says tests pass" | Generator prose is not evidence. Your probe or the T0 artifact is. |
119
+ | "`npm test` is broken but `node --test` passes, so the tests pass" | You graded a different criterion. Run the command the contract names; if it fails, that IS the finding. |
110
120
  | "This criterion isn't really testable, count it as pass" | Untestable AC = spec defect → surface it; it blocks a clean PASS unless explicitly waived. |
111
121
  | "The other dimensions are strong, round up" | Halo effect banned. Dimensions never average. |
112
122
  | "The task file's checklist says done" | The checklist is the generator's paraphrase. Grade the committed UC text. |
@@ -191,7 +201,7 @@ bug_template). Adding one (e.g. security) = write `references/dimensions/securit
191
201
  /spec-evaluator --order .shapeup/checkout-vnpay/orders/evaluate-r2.json
192
202
 
193
203
  # Standalone — the preamble shim compiles a minimal order, then the single code path runs:
194
- # node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/compile-order.mjs" --operation evaluate --slug <slug> \
204
+ # node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" compile --operation evaluate --slug <slug> \
195
205
  # --worker spec-evaluator [--payload '{"dimensions": [...], "run_cmd": "..."}']
196
206
  /spec-evaluator --spec shapeup/checkout-vnpay/spec/ --task TASK-007
197
207
  /spec-evaluator --spec shapeup/checkout-vnpay/spec/ --feature checkout-vnpay --single-pass
@@ -199,7 +209,7 @@ bug_template). Adding one (e.g. security) = write `references/dimensions/securit
199
209
 
200
210
  Standalone keeps `--task` (per-task check, not round-gated) and `--single-pass` (feature-level)
201
211
  — the shim maps them onto the order's payload; missing run command → ask. After writing the
202
- WorkResult, run `node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/ingest-result.mjs" <result path>` and show its
212
+ WorkResult, run `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" reduce ingest <result path>` and show its
203
213
  summary — standalone has no orchestrator to ingest for you.
204
214
 
205
215
  ---
@@ -30,7 +30,8 @@ rely on (anything absent = **unknown**; never invent it):
30
30
  | `payload.verify.test_cmd` | The command that verifies your work. No test_cmd → command-verifiable ACs still need *some* observable check; say what you used |
31
31
  | `payload.kb_rules_path` | Team guidelines (read if the file exists) — steering, never spec; conflict → the AC wins, note it in `deviations` |
32
32
  | `payload.constraints` | Non-Go items and freezes (e.g. `ui_layers.layer3_frozen`) |
33
- | `operation` | `execute` (fresh), `fix` (only the bugs in `payload.bugs` touch nothing else), `spike` (produce a decision doc, not code) |
33
+ | `payload.bugs[]` | The previous round's FAIL verdict, addressed to files inside YOUR substrate: `{severity, criterion, location, repro, expected, actual}`. Fix exactly these and touch nothing else. They are spec-conformance defects, so verification is ALREADY green and will stay green whether or not you fix them — a passing `test_cmd` is not evidence you are done this round, and re-running it cannot tell you. Read the cited lines against the committed spec instead. An entry marked `unowned` cites a file no scope owns: fix it only if it falls inside your substrate. Absent unless the previous round failed |
34
+ | `operation` | `execute` (fresh), `fix` (only the bugs in `payload.bugs` — touch nothing else), `spike` (produce a decision doc, not code). A build round whose predecessor returned FAIL arrives as `fix` with the same substrate as the `execute` that preceded it |
34
35
 
35
36
  **Zero-memory rule.** You have no memory of prior attempts or sessions. Decisions that
36
37
  mattered are in `payload.decisions`; errors that mattered are in `payload.digested_errors`.
@@ -168,7 +169,7 @@ self-planned: no new task files, no spec edits — one raw line per discovery.
168
169
 
169
170
  You do NOT: tick AC boxes, edit `tasks/_index.md`, write `run-state.md`, touch the discovery
170
171
  ledger, mark anything done outside your result, or update any other spec document. The
171
- orchestrator's `ingest-result.mjs` does all of that from your envelope.
172
+ orchestrator's `harness reduce ingest` does all of that from your envelope.
172
173
 
173
174
  ---
174
175
 
@@ -193,15 +194,15 @@ orchestrator's `ingest-result.mjs` does all of that from your envelope.
193
194
 
194
195
  # Standalone — the preamble shim compiles a minimal WorkOrder from the flags, then the
195
196
  # single code path above runs. Requires the harness scripts (plugin install):
196
- # node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/compile-order.mjs" --task TASK-003 --slug checkout-vnpay
197
- # node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/compile-order.mjs" --next --slug checkout-vnpay
197
+ # node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" compile --task TASK-003 --slug checkout-vnpay
198
+ # node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" compile --next --slug checkout-vnpay
198
199
  /task-executor --spec shapeup/checkout-vnpay/spec/ --task TASK-003
199
200
  /task-executor --spec shapeup/checkout-vnpay/spec/ --next
200
201
  ```
201
202
 
202
203
  Standalone shim: derive `<slug>` from the `--spec` path (`shapeup/<slug>/spec`),
203
- run `compile-order.mjs` with the matching flags (mode becomes `standalone`), then proceed
204
+ run `harness compile` with the matching flags (mode becomes `standalone`), then proceed
204
205
  against the compiled order exactly as if dispatched. After writing the WorkResult, run
205
- `node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/ingest-result.mjs" <result path>` yourself and show the user its
206
+ `node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" reduce ingest <result path>` yourself and show the user its
206
207
  summary — standalone has no orchestrator to ingest for you. One code path inside; two entry
207
208
  points outside.
@@ -12,7 +12,7 @@ call is narration, and a narrated run is a failed run — it reads like a clean
12
12
  escaped defects behind it. `hooks/gate-zerowork.mjs` (Stop) blocks a session
13
13
  that **reached the orchestrator and left no receipt** — where "reached the orchestrator" means
14
14
  dispatching this skill or launching a `shapeup-*` workflow by either surface, and the receipt is
15
- what `init-run.mjs` writes. Working around the harness is not an exemption: a busy session used to
15
+ what `harness init run` writes. Working around the harness is not an exemption: a busy session used to
16
16
  switch this gate off and no longer does. Loading these instructions is not running them.
17
17
 
18
18
  **Step 1 — open the run.** Write the requirement to a file first, then pass the path — a
@@ -20,12 +20,19 @@ multi-line requirement inlined into a shell argument is where this step goes wro
20
20
  turns fighting shell quoting):
21
21
 
22
22
  ```bash
23
- node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/init-run.mjs" \
23
+ node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" init run \
24
24
  --slug <slug-from-the-request> --intake-file <path/to/the/requirement.md> \
25
25
  --auto-level <interactive|auto|unattended> \
26
26
  [--dimensions <a,b>] [--gate-answers <ci|guarded|path.json>] [--wall-clock-budget <seconds>] [--max-rounds 3]
27
27
  ```
28
28
 
29
+ **After a compaction, or in a fresh session over an open run, re-derive before you act.** One
30
+ command answers where the run stands, from artifacts and never from memory:
31
+
32
+ ```bash
33
+ node "${CLAUDE_PLUGIN_ROOT}/kernel/harness.mjs" reduce graph --slug <slug> --subgraph run
34
+ ```
35
+
29
36
  **Exit 3 means a run is ALREADY OPEN.** Resume it; do not re-open it. The refusal prints the
30
37
  derived RESUME STATE (slug, status, round, board counts) — read it and go straight to Step 2;
31
38
  `shapeup-run.js`'s own fast-forward will re-derive exactly where to continue from disk, never from
@@ -45,58 +52,62 @@ translates itself.
45
52
  **Step 2 — pin GATE L0, then launch.** Collect the L0.1–L0.9 config (spec folder, lens, stack,
46
53
  eval dims, max_rounds, the model/budget matrix — see `references/gates.md` GATE L0 for the full
47
54
  collect-list), write the SHARED `project-profile.md` yourself (`{schema_version:1, archetype,
48
- entry_point}` — the only artifact this skill writes directly; `shapeup-run.js` has no filesystem
49
- of its own), emit the `⏸ GATE L0` block, then check the lane:
55
+ entry_point}` — `shapeup-run.js` has no filesystem of its own), emit the `⏸ GATE L0` block, then
56
+ check the lane:
50
57
 
51
58
  - **`--tiny`, or the spec has no committed `scopes/*.md` yet** (pre-v0.3.0 spec): `shapeup-run.js`
52
59
  is out of scope for this lane by design (it targets scope-contract specs). Run the unchanged
53
- legacy loop instead — `references/round-protocol.md` (BUILD(r)/EVAL) + `references/delegation.md`
60
+ legacy loop instead — `references/protocol.md` (BUILD(r)/EVAL) + `references/protocol.md`
54
61
  carry the full step-by-step for both the tiny lane and a scope-less BUILD loop, verbatim, non-
55
62
  regression. Stop reading this file here for that run.
56
- - **Otherwise** (the common case — a scoped spec, any auto level): write `RunArgs`
57
- (`domain.schema.json` `$defs/RunArgs` — `{slug, autoLevel, answers, models:{exec,eval,qa},
58
- budgets:{maxRounds,attemptBudget,wallClockS}, pluginRoot, startedAt}`) to
59
- `.shapeup/<slug>/run-args.json`, then launch it as a **background** Bash call:
63
+ - **Otherwise** (the common case — a scoped spec, any auto level): build `RunArgs`
64
+ (`domain.schema.json` `$defs/RunArgs` — `{slug, runId, autoLevel, answers, lane,
65
+ models:{exec,eval,qa}, budgets:{maxRounds,attemptBudget,wallClockS}, pluginRoot, startedAt}`,
66
+ plus every switch the operator typed `references/gates.md` GATE L0.9 has the flag→field table,
67
+ and a flag that stops here is a flag that was accepted and ignored). **Write that exact object to
68
+ `.shapeup/<slug>/run-args.json` before launching**, fresh on every launch and relaunch: the flags
69
+ reach the workflow as a value in memory, so it is the run's only evidence of what it was launched
70
+ with, and a run that cannot state its own configuration cannot have a claim about it checked.
71
+ Then launch the run script with the **`Workflow` tool**:
60
72
 
61
- ```bash
62
- node "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/scripts/run-workflow.mjs" \
63
- "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/workflows/shapeup-run.js" \
64
- --args-file .shapeup/<slug>/run-args.json --run-dir .shapeup/<slug>/workflow-run
73
+ ```
74
+ Workflow({
75
+ scriptPath: "${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/workflows/shapeup-run.js",
76
+ args: <the RunArgs object>
77
+ })
65
78
  ```
66
79
 
67
80
  `shapeup-run.js` (`domain.schema.json` `$defs/RunArgs`/`RunReturn`) owns everything from ORIENT
68
- through GATE H and ship-report — every gate inside that range resolves via `gate-answers.mjs`'s
69
- exit code, in code, not by this skill's own reading of a paragraph. The `RunReturn` arrives as
70
- `result` in `.shapeup/<slug>/workflow-run/result.json`, and on stdout.
71
-
72
- **Background, and by Bash both are load-bearing.** A real run outlives any foreground tool-call
73
- ceiling. And **do not launch this with the `Workflow` tool** unless the project has explicitly
74
- granted it: that call is denied by default in a headless session — the lane then executes zero
75
- times while the session improvises the feature by hand and the only grant that unblocks it is
76
- the unscoped token `"Workflow"`, which permits *every*
77
- dynamic workflow script in the project. `run-workflow.mjs` runs the same script under the
78
- path-scoped grant `npx shapeup-sdlc init` already writes. Headless runs also need
79
- `CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS=0`, or the wait is cut at 600 s and a truncated run is
80
- reported as a clean one. If the launch comes back "requires approval", stop
81
- and say so — do not hand-build the feature instead.
81
+ through GATE H and the ship report — every gate inside that range resolves via `harness gate`'s
82
+ exit code, in code, not by this skill's own reading of a paragraph. The `RunReturn` is the script's
83
+ return value, and it arrives as the workflow's result.
84
+
85
+ **Why the tool and not a Bash launcher.** The native runtime is what gives the run
86
+ resume-from-journal, worktree isolation, and sub-agents that share this session's prompt cache
87
+ instead of paying a cold start each. `npx shapeup-sdlc init` writes the `"Workflow"` grant the
88
+ launch needs. That grant is UNSCOPED it authorises every dynamic workflow script in the project,
89
+ not only this one — so an install may decline it with `--no-native-workflow`, in which case the
90
+ launch prompts for approval once per session and the unattended lane is unavailable. If the launch
91
+ comes back "requires approval" in a headless session, stop and say so — do not hand-build the
92
+ feature instead.
82
93
 
83
94
  ## Step 3 — the pause protocol: branch on `RunReturn.status`
84
95
 
85
96
  | `status` | What the workflow is telling you | What you do |
86
97
  |---|---|---|
87
- | `paused` | A gate resolved "ask" — `paused_at` names it, `block` is composed and ready | Emit `block` **verbatim** (never re-summarise it — that is the paraphrase channel this design exists to close). Put it to the PO, get a decision. Write it to `.shapeup/<slug>/gate-answers.json` (`{"version":1,"preset":"custom","answers":{"<paused_at>":{"decision":"<answer>"}}}`, merging with any prior gate's answer already there). **Relaunch the SAME command, same `--args-file`** — the fast-forward re-derives from disk and re-dispatches nothing already done (verify: `orders/` minus `results/` is empty before it proceeds) |
88
- | `aborted` | A gate resolved "abort", or a hard stop (spec-lint red, scope-hammer CANNOT SHIP) | Report `aborted_at` + `reason` to the PO. Do not relaunch without a human decision — `--force` on `init-run.mjs` if truly restarting |
98
+ | `paused` | A gate resolved "ask" — `paused_at` names it, `block` is composed and ready | Emit `block` **verbatim** (never re-summarise it — that is the paraphrase channel this design exists to close). Put it to the PO, get a decision. Write it to `.shapeup/<slug>/gate-answers.json` (`{"version":1,"preset":"custom","answers":{"<paused_at>":{"decision":"<answer>"}}}`, merging with any prior gate's answer already there). **Relaunch the SAME `Workflow` call, same `args`** — the fast-forward re-derives from disk and re-dispatches nothing already done (verify: `orders/` minus `results/` is empty before it proceeds) |
99
+ | `aborted` | A gate resolved "abort", or a hard stop (spec-lint red, scope-hammer CANNOT SHIP) | Report `aborted_at` + `reason` to the PO. Do not relaunch without a human decision — `--force` on `harness init run` if truly restarting |
89
100
  | `gate_h` | A circuit breaker tripped (`breaker`: outer \| inner \| deadline) — `green_scopes` shipped nothing, `hammer_proposals` needs a census | Dispatch a fresh Agent (model: exec): `Skill(shapeup-sdlc-plugin:scope-hammer) --slug <slug> --breaker <breaker> [--scope <id>]` for the census + cut list, put the PO's decision to `references/gates.md` GATE H, then close out via Step 4 below |
90
101
  | `shipped` | The board's final round passed EVAL, QA ran, GATE H accepted the cut list, `report` names the frozen `shapeup/<slug>/REPORT.md` | Go straight to Step 4 |
91
102
 
92
103
  **Never** treat a `paused` return as a stall to work around, and never invent an answer this skill
93
104
  did not actually receive from the PO — an unattended lane with no answer for a gate is meant to
94
- `abort` (see `gate-answers.mjs`'s `on_missing`), not silently proceed.
105
+ `abort` (see `harness gate`'s `on_missing`), not silently proceed.
95
106
 
96
107
  ## Step 4 — GATE L4 — Ship Sign-Off (this skill's own gate; the workflow never sees it)
97
108
 
98
109
  FIRST freeze the evidence — run state is gitignored, so `shapeup/<slug>/REPORT.md` (already
99
- written by `shapeup-run.js` via `ship-report.mjs`, or write it now on a `gate_h` close) is all a
110
+ written by `shapeup-run.js` via `harness reduce ship`, or write it now on a `gate_h` close) is all a
100
111
  teammate sees. Then emit:
101
112
 
102
113
  ```
@@ -119,18 +130,19 @@ never orients, plans, builds, or judges itself — `shapeup-run.js` **sequences*
119
130
  and returns to the PO at every gate.
120
131
 
121
132
  > **Gate collect-lists + output-block formats** → `references/gates.md`
122
- > **How each sub-skill is invoked + handoff files (the envelope port)** → `references/delegation.md`
123
- > **The round loop, stop conditions, three-level breaker rationale** → `references/round-protocol.md`
124
- > **Run ledger format + Hill report** → `references/ledger-schema.md`
125
- > **State ownership, the central domain registry, two-ledger split** → `references/state-model.md`
126
- > **Hard rules this design enforces, and why** → `references/hard-rules.md`
127
- > **Full invocation examples + the complete flag table** → `references/invocation.md`
133
+ > **How each sub-skill is invoked + handoff files (the envelope port)** → `references/protocol.md`
134
+ > **The round loop, stop conditions, three-level breaker rationale** → `references/protocol.md`
135
+ > **Run ledger format + Hill report** → `references/protocol.md` (Part 4 — State)
136
+ > **State ownership, the central domain registry, two-ledger split** → `references/protocol.md` (Part 4 — State)
137
+ > **Hard rules this design enforces, and why** → `references/protocol.md`
138
+ > **Full invocation examples + the complete flag table** →
128
139
  > **The small-change lane (`--tiny`)** → `references/tiny-lane.md`
129
140
 
130
141
  ## Invocation
131
142
 
132
143
  `/tech-lead --pitch <shaping.md> --spec <spec/> --lens standard` for an interactive run; `--auto`
133
144
  (pause only at L1a/L1b/L3/L4), `--unattended` (headless/CI), `--from build` (resume), `--no-eval`/
134
- `--no-qa` to skip passes. **`--tiny`** stays a prose-only lane (`references/tiny-lane.md`)
145
+ `--no-qa` to skip passes, `--parallel-scopes N` to set how many scopes build at once (default 4,
146
+ `1` = sequential), `--adversarial-verify` to refute each FAIL finding before it costs a fix round. **`--tiny`** stays a prose-only lane (`references/tiny-lane.md`) —
135
147
  `shapeup-run.js` targets specs with committed scope contracts; a tiny change or a pre-scope-
136
148
  contract spec runs the unchanged v0.2.6 flow this file's Hard Rules already describe.