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
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: scope-architect
3
- description: "Use this skill to map, remap, or split the vertical scopes of a feature — Shape Up's \"map the scopes\" (step 8) as committed, mechanically enforceable contracts. Triggers on: \"map the scopes\", \"write the scope contracts\", \"scope contract\", \"remap this scope\", \"split this stuck scope\", \"the discovered tasks don't fit any scope\", \"re-slice the substrate\", or a tech-lead --order dispatch (operations map-scopes | remap | split-scope). Writes the committed scopes/*.md contracts by import-graph slicing along business flow, with write-whitelist substrates and e2e fixtures. NOT for decomposing a pitch into tasks (ba-pitch-analyzer) or cutting scope at ship time (scope-hammer)."
3
+ description: "Use this skill to map the vertical scopes of a feature — Shape Up's \"map the scopes\" (step 8) as committed, mechanically enforceable contracts. Triggers on: \"map the scopes\", \"write the scope contracts\", \"scope contract\", \"the discovered tasks don't fit any scope\", \"re-slice the substrate\" (operations map-scopes). Writes the committed scopes/*.md contracts by import-graph slicing along business flow, with write-whitelist substrates and e2e fixtures. NOT for decomposing a pitch into tasks (ba-pitch-analyzer) or cutting scope at ship time (scope-hammer)."
4
4
  ---
5
5
 
6
6
  # Scope Architect (pure worker v1.0)
@@ -13,17 +13,15 @@ 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
 
20
20
  | Field | What it is |
21
21
  |---|---|
22
- | `operation` | `map-scopes` (first slicing after the board exists) · `remap` (fold discovered items into scope contracts) · `split-scope` (re-slice one stuck scope) |
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 |
25
- | `payload.discovered_ledger` | (remap) items that fit no existing substrate |
26
- | `payload.scope_id` | (split-scope) the stuck scope (`rounds_at_position ≥ 3`, or an approved substrate-expansion) |
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 |
27
25
  | `substrate.allowed` | `scopes/*.md` + `scope-board.md` — your ONLY write surface |
28
26
 
29
27
  ## Core process
@@ -39,7 +37,23 @@ anti-rationalization table.
39
37
  scalars and [a, b] lists, a `## Affordances` table for affordance_manifest, and a
40
38
  short `## Why this slice` paragraph. A reviewer must be able to read the substrate
41
39
  in a PR; regeneration preserves prose under headings you do not own.
42
- 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
43
57
  allowed_file_substrate[] — exact globs; the sandbox hook's
44
58
  write-whitelist; wrong here =
45
59
  a legitimate ESCALATE later
@@ -59,17 +73,30 @@ anti-rationalization table.
59
73
  a fixture for unbuilt behavior
60
74
  hill_phase: "UPHILL_UNKNOWN" — ALWAYS; phase is derived from
61
75
  T0/T1/seesaw facts later,
62
- never authored (DD-10)
63
- 4 LINT node "${CLAUDE_PLUGIN_ROOT}/skills/ba-pitch-analyzer/scripts/spec-lint.mjs" --slug <slug>
64
- → PA1 (directory alignment), PA2 (>~15 files), DISJOINT (undeclared overlap).
76
+ never authored
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).
65
81
  Fix reds by re-slicing, not by silencing.
66
- 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.
67
94
  ```
68
95
 
69
- **remap:** a discovered item joins the nearest scope only if the flow matches (extend that
96
+ **Folding in a discovered item:** it joins the nearest scope only if the flow matches (extend that
70
97
  substrate minimally); otherwise propose a NEW scope — never silently widen an existing one.
71
- **split-scope:** re-run step 1 on just that scope's task+file set → N new contracts; mark the
72
- old one `superseded_by: [ids]` — never delete (branch and T0 history stay attributable).
98
+ **Re-slicing a stuck scope:** re-run step 1 on just that scope's task+file set → N new contracts;
99
+ mark the old one `superseded_by: [ids]` — never delete (branch and T0 history stay attributable).
73
100
 
74
101
  ## Anti-rationalization table
75
102
 
@@ -80,19 +107,31 @@ old one `superseded_by: [ids]` — never delete (branch and T0 history stay attr
80
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. |
81
108
  | "This scope looks downhill, I'll set the phase" | hill_phase is UPHILL_UNKNOWN at write, always. Facts move dots, not authors. |
82
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. |
83
113
  | "Fixtures can come later, leave the field empty" | Fixture at contract time or an explicit TBD flag — silence is how T0 goes blind. |
84
114
 
85
115
  ## Output contract — the WorkResult
86
116
 
117
+ **Escalation rule.** If you return `status: "escalated"`, the **first** entry in `deviations[]`
118
+ must be the blocker: one specific, answerable question plus the context needed to answer it.
119
+ Nothing else in the envelope carries it — there is no `escalates[]` field — so a vague entry, or
120
+ the question buried under other notes, reaches the human as "something went wrong" and costs a
121
+ round. Write it so someone without your context can answer it in one reply.
122
+
123
+
87
124
  `scopes/*.md` + `scope-board.md` in your substrate, then
88
125
  `.shapeup/<slug>/results/<order-suffix>.json`: `status`, `artifacts[]` (the contracts
89
- written/superseded), `escalates[]` (e.g. a discovered item implying a new UC — the planner's
90
- territory), `deviations[]` (any lint warn left standing and why). You never touch task files,
126
+ written/superseded), `deviations[]` (e.g. a discovered item implying a new UC — the planner's
127
+ territory and any lint warn left standing, with why). You never touch task files,
91
128
  `tasks/_index.md`, spec docs, or run-state.
92
129
 
93
130
  ## Verification checklist
94
131
 
95
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`
96
135
  - [ ] Substrates disjoint except declared shared_substrate (DISJOINT = 0 red)
97
136
  - [ ] Every interactive element in scope screens appears in exactly one affordance_manifest
98
137
  - [ ] Every scope has fixtures or an explicit TBD flag
@@ -102,10 +141,10 @@ territory), `deviations[]` (any lint warn left standing and why). You never touc
102
141
  ## Invocation
103
142
 
104
143
  ```bash
105
- # Orchestrated — compile-order --operation map-scopes|remap|split-scope --worker scope-architect …
144
+ # Orchestrated — compile-order --operation map-scopes --worker scope-architect …
106
145
  /scope-architect --order .shapeup/checkout-vnpay/orders/map-scopes.json
107
146
 
108
147
  # Standalone shims (compile the same envelope)
109
148
  /scope-architect --map shapeup/checkout-vnpay/
110
- /scope-architect --split cart-creation shapeup/checkout-vnpay/
149
+ /scope-architect --map --split cart-creation shapeup/checkout-vnpay/ # re-slice one scope
111
150
  ```
@@ -11,7 +11,7 @@ live with today — not to a hypothetical perfect version. "Better than the base
11
11
  enough to ship; "not as good as I imagined" is not a reason to keep building.
12
12
 
13
13
  **Why this is its own skill, not tech-lead prose.** GATE H census pulls from several sources
14
- that accumulate over a whole run (QA findings, discovered-task ledger, advisor-protocol budget
14
+ that accumulate over a whole run (QA findings, discovered-task ledger, attempt-budget
15
15
  overflows, per-scope inner-breaker trips) — a genuinely separate synthesis step from
16
16
  orchestration. Splitting it out keeps `tech-lead` thin (it dispatches, this skill decides what
17
17
  survives the hammer) and gives the census/cut-list/verdict logic one owner instead of being
@@ -22,10 +22,10 @@ re-derived inline at every SHIP.
22
22
  ## When this fires
23
23
 
24
24
  ```
25
- 1. All scopes reach FINISHED on the hill (design spec B2) → normal stop, post-QA-hunt.
25
+ 1. All scopes reach FINISHED on the hill → normal stop, post-QA-hunt.
26
26
  2. Outer circuit breaker trips: round_budget reaches 0 with scopes still uphill/downhill.
27
27
  3. Inner circuit breaker trips: a scope's attempt_budget (default 5) is exhausted without a
28
- T0-green result → queued as a hammer PROPOSAL (design spec Blueprint A `hammer_proposals`),
28
+ T0-green result → queued as a hammer PROPOSAL (`hammer_proposals`),
29
29
  judged here rather than immediately blocking the round.
30
30
  ```
31
31
  Any of the three routes to this skill; the difference is only what's in the census (case 1 has
@@ -63,7 +63,7 @@ H0.1 Unresolved scopes (breaker cases only):
63
63
  with the T0 failure that stalled them (from the last red t0/verdicts/*.json)
64
64
  H0.2 QA findings (qa-edge-hunter's hunt-report.md, when present) — all `~` by default.
65
65
  H0.3 Discovered-task ledger entries still open (discovery/ledger.md, `[+]`/`~` unresolved).
66
- H0.4 advisor-protocol budget-overflow flags (auto-resolved ESCALATEs logged for GATE H review).
66
+ H0.4 Attempt-budget hammer proposals (scopes that exhausted their T0 attempts during BUILD).
67
67
  H0.5 Classify every item: MUST-HAVE (the pitch's core problem is unsolved without it) vs
68
68
  NICE-TO-HAVE (`~`, improves but doesn't block the core promise). Default to NICE-TO-HAVE
69
69
  unless the item traces directly to a pitch boundary or a scope's business_goal — a
@@ -87,7 +87,7 @@ customer suffers through today), never to a perfect ideal.
87
87
 
88
88
  ```
89
89
  H1.1 Resolve the baseline: shapeup/<slug>/shaping/baseline.md if present (written at
90
- shaping time, design spec Blueprint F — first-class, not a pitch footnote). Absent →
90
+ shaping time — first-class, not a pitch footnote). Absent →
91
91
  degrade honestly: read the pitch's problem statement as the implicit baseline and flag
92
92
  "baseline not first-class — comparison is approximate" in the report. Do not invent one.
93
93
  H1.2 For each MUST-HAVE item from H0: "with this item cut/carried, is the shipped product
@@ -33,7 +33,7 @@ This skill lazily loads detail from resource files. **Read the relevant resource
33
33
  | `/shapeup breadboard-reflection` | `resources/breadboard-reflection.md` |
34
34
  | `/shapeup full` | Read `resources/shaping.md` first, then `resources/breadboarding.md` before B-phases, and `resources/context-compaction.md` for the run digest |
35
35
 
36
- > Resource paths are relative to this skill's directory. In Claude Code: `.claude/skills/shapeup/resources/`.
36
+ > Resource paths are relative to this skill's directory (`resources/` beside this SKILL.md, wherever the plugin is installed).
37
37
  > Multi-gate runs maintain a derived **decision digest** so each gate reads a compact slice instead of full prose — see `resources/context-compaction.md` and the "Run Workspace & Digest" section below.
38
38
 
39
39
  ---
@@ -374,8 +374,8 @@ Two roots, separated by artifact **nature** (full design →
374
374
  - **Shared** root `shapeup/[slug]/` = what the team contributes to
375
375
  (source + deliverable). **Local** root `.shapeup/[slug]/` = per-run scratch,
376
376
  hidden and fully gitignorable. Add **one** line to `.gitignore`: `.shapeup/`.
377
- No carve-out needed — the one committed report surface, the harvest feed
378
- `shapeup/metrics.jsonl`, lives in the shared root.
377
+ No carve-out needed — everything machine-written at run time, including the
378
+ harvest shards `.shapeup/metrics/*.jsonl`, lives under the local root.
379
379
  - `digest.md` is the run's derived decision context (the 4-field, two-zone read
380
380
  model the gates consume). It is **never** the source of truth and never crosses
381
381
  a skill boundary — `ba-pitch-analyzer` reads `pitch.md`/`shaping.md`, never the
@@ -182,9 +182,10 @@ Everything keys off the feature `<slug>`. Two roots, split by **who needs it**:
182
182
  - The **local** root `.shapeup/[slug]/` is per-run scratch + reports — hidden,
183
183
  fully gitignorable, dies with the run. It is derived from the same `<slug>`.
184
184
  - `.gitignore`: one line — `.shapeup/`. The whole local root is ignored; no
185
- carve-out is needed because the one committed report surface, the harvested
186
- signal feed `shapeup/metrics.jsonl` (written by the tech-lead at SHIP,
187
- fact-only; see the tech-lead skill's SHIP step), lives in the **shared** root.
185
+ carve-out is needed because everything machine-written at run time lives there,
186
+ including the harvested signal shards `.shapeup/metrics/*.jsonl` (written by
187
+ the tech-lead at SHIP, fact-only; see the tech-lead skill's SHIP step). The
188
+ committed report surface is the frozen `shapeup/[slug]/REPORT.md`.
188
189
  - All paths are **project-relative, resolved from the project root / cwd.** Never
189
190
  `/mnt/...` — that is the claude.ai authoring sandbox and dies in a user repo.
190
191
 
@@ -7,9 +7,9 @@ description: "Use this skill to design how each use-case's engine integrates int
7
7
 
8
8
  **Design the seam, or the engine ships orphaned.**
9
9
 
10
- The audit that motivated this skill found a 631-line asset pipeline with 26 passing tests and
11
- **zero call sites** in the app's composition root — built, green, and unreachable from the
12
- running application. Five more scopes had engines never wired to a player. This skill closes that
10
+ This skill exists because a sizeable engine module can be built, fully tested, and still have
11
+ **zero call sites** in the app's composition root — green, and unreachable from the
12
+ running application; observed across multiple scopes in one run, not theorized. It closes that
13
13
  hole at the front: before the scopes are sliced, it designs a committed **wiring map**
14
14
  (`shapeup/<slug>/wiring-map.md`) that names, for every use case, the chain from the
15
15
  engine module to a player-visible affordance — including **how** and **where** the engine attaches
@@ -23,13 +23,13 @@ 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.
30
30
  - **The slicer gets its integration seam up front.** Declaring each attachment *before*
31
31
  `scope-architect` runs supplies the missing input behind the round-1 substrate-expansion
32
- escalations — the four identical "declined by precedent" stalls. (This skill *front-loads* the
32
+ escalations — repeated identical "declined by precedent" stalls. (This skill *front-loads* the
33
33
  seam; it does not enforce the re-slice rule — that's a separate change.)
34
34
 
35
35
  You are the **sole writer** of the wiring map, written **directly** (the same authority
@@ -70,17 +70,32 @@ 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
- write the entry with the seam you INTEND and raise it in deviations[]/escalates[], so
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
78
93
  WorkResult. You do not run trace-lint — the orchestrator runs it advisory at L1b.
79
94
  ```
80
95
 
81
96
  **No use case is exempt.** If a UC's engine genuinely has no player-facing seam (a pure
82
97
  background job), say so in `wiring_seam` and name the boot/cron/init attachment that starts it — a
83
- cron registration, a boot hook. "It's internal" is how the asset pipeline stayed orphaned; there
98
+ cron registration, a boot hook. "It's internal" is how an engine stays orphaned; there
84
99
  is always an attachment to the entry point, or the code never runs.
85
100
 
86
101
  ## Anti-rationalization table
@@ -96,11 +111,18 @@ is always an attachment to the entry point, or the code never runs.
96
111
 
97
112
  ## Output contract — the WorkResult
98
113
 
114
+ **Escalation rule.** If you return `status: "escalated"`, the **first** entry in `deviations[]`
115
+ must be the blocker: one specific, answerable question plus the context needed to answer it.
116
+ Nothing else in the envelope carries it — there is no `escalates[]` field — so a vague entry, or
117
+ the question buried under other notes, reaches the human as "something went wrong" and costs a
118
+ round. Write it so someone without your context can answer it in one reply.
119
+
120
+
99
121
  `wiring-map.md` in your substrate, then `.shapeup/<slug>/results/<order-suffix>.json`:
100
- `status`, `artifacts[]` (the wiring map written), `escalates[]` (e.g. a missing profile, or a UC
101
- whose engine the spec never names the planner's territory), `assumptions[]` (engine paths
102
- inferred from the domain model where the spec was silent), `deviations[]` (any UC left with an
103
- uncertain seam, or an engine with no attachment path, and why). You never touch spec docs,
122
+ `status`, `artifacts[]` (the wiring map written), `assumptions[]` (engine paths
123
+ inferred from the domain model where the spec was silent), `deviations[]` (a missing profile, a
124
+ UC whose engine the spec never names the planner's territory a UC left with an uncertain
125
+ seam, or an engine with no attachment path, and why). You never touch spec docs,
104
126
  `scopes/*.md`, `project-profile.md`, task files, or run-state.
105
127
 
106
128
  ## Verification checklist
@@ -110,7 +132,7 @@ uncertain seam, or an engine with no attachment path, and why). You never touch
110
132
  - [ ] `entry_call_site` is a symbolic composition-root attachment resolved against the profile's `entry_point` — no invented line number, no guessed entry point
111
133
  - [ ] `entry_point` echoes the profile — no independently-chosen seam
112
134
  - [ ] The profile was READ, not guessed; a missing profile in orchestrated mode → ESCALATE, not an invented entry point
113
- - [ ] Any UC whose engine has no attachment path is raised in `deviations[]`/`escalates[]` (the wiring the build must close), never silently dropped
135
+ - [ ] Any UC whose engine has no attachment path is raised in `deviations[]` (the wiring the build must close), never silently dropped
114
136
  - [ ] The WorkResult validates against `work-result.schema.json`
115
137
 
116
138
  ## Invocation
@@ -125,5 +147,5 @@ uncertain seam, or an engine with no attachment path, and why). You never touch
125
147
  # The reachability oracle is the ORCHESTRATOR's, run advisory at L1b — not part of your craft.
126
148
  # Standalone, you MAY preview it after writing the map (it self-skips arms whose artifacts are
127
149
  # absent, and is near-vacuous pre-build since the engine code does not exist yet):
128
- # 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
129
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. |
@@ -116,6 +126,13 @@ Done-when statements; `_index.md` Non-Go list. Which UCs are in scope comes from
116
126
 
117
127
  ## Output contract — the WorkResult
118
128
 
129
+ **Escalation rule.** If you return `status: "escalated"`, the **first** entry in `deviations[]`
130
+ must be the blocker: one specific, answerable question plus the context needed to answer it.
131
+ Nothing else in the envelope carries it — there is no `escalates[]` field — so a vague entry, or
132
+ the question buried under other notes, reaches the human as "something went wrong" and costs a
133
+ round. Write it so someone without your context can answer it in one reply.
134
+
135
+
119
136
  1. Write the report `.shapeup/<slug>/evaluation/EVAL-FEATURE-<slug>.md` (or
120
137
  `EVAL-<task_id>.md` for a per-task run) per `references/report-schema.md`: verdict,
121
138
  per-dimension criteria table with confidence, stability block (flips), bug list (severity,
@@ -143,10 +160,10 @@ Done-when statements; `_index.md` Non-Go list. Which UCs are in scope comes from
143
160
  ```
144
161
 
145
162
  **Every FAIL criterion's `evidence` MUST carry a `file:line` locator** — schema-enforced, not
146
- advice: `validate-envelope` rejects the whole result before ingest sees it. A PASS may cite plain
147
- output. (Measured: a run returned a correct FAIL with `bugs: null` and no locator anywhere, which
148
- is unactionable without re-investigating. The rule used to be repeated five times in this prompt
149
- and enforced nowhere; it is now stated once and enforced by `domain.schema.json`.)
163
+ advice: the envelope is validated against `work-result.schema.json` at ingest and a locatorless
164
+ FAIL is rejected before any write. A PASS may cite plain output. (Observed, not theorized: a
165
+ correct FAIL verdict with no locator anywhere is unactionable without re-investigating the
166
+ rule used to live in prose and be enforced nowhere; it is now data in `domain.schema.json`.)
150
167
 
151
168
  The orchestrator's ingest appends the verdict ledger, un-ticks the `refuted` boxes, and sets
152
169
  `eval_verdict` frontmatter. You never touch a task file, a board, or run-state — and you
@@ -184,7 +201,7 @@ bug_template). Adding one (e.g. security) = write `references/dimensions/securit
184
201
  /spec-evaluator --order .shapeup/checkout-vnpay/orders/evaluate-r2.json
185
202
 
186
203
  # Standalone — the preamble shim compiles a minimal order, then the single code path runs:
187
- # 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> \
188
205
  # --worker spec-evaluator [--payload '{"dimensions": [...], "run_cmd": "..."}']
189
206
  /spec-evaluator --spec shapeup/checkout-vnpay/spec/ --task TASK-007
190
207
  /spec-evaluator --spec shapeup/checkout-vnpay/spec/ --feature checkout-vnpay --single-pass
@@ -192,7 +209,7 @@ bug_template). Adding one (e.g. security) = write `references/dimensions/securit
192
209
 
193
210
  Standalone keeps `--task` (per-task check, not round-gated) and `--single-pass` (feature-level)
194
211
  — the shim maps them onto the order's payload; missing run command → ask. After writing the
195
- 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
196
213
  summary — standalone has no orchestrator to ingest for you.
197
214
 
198
215
  ---
@@ -209,5 +226,5 @@ summary — standalone has no orchestrator to ingest for you.
209
226
  | Probe the RUNNING app, not the source alone | Apps that look right still break when used |
210
227
  | Re-probe every FAIL; flip ⇒ confidence low | A single snapshot lies; the ledger makes it visible |
211
228
  | Verdict-ledger lines are returned, appended by ingest, never rewritten | Verdict history is how a single-snapshot judge becomes measurable |
212
- | A verdict on a scoped spec without a T0 citation is structurally invalid | T0 is a machine fact the generator cannot fabricate (DD-7, PA4) |
229
+ | A verdict on a scoped spec without a T0 citation is structurally invalid | T0 is a machine fact the generator cannot fabricate |
213
230
  | UI assertions target affordances only (test_id/role/data-state) | Layer-3 styling is frozen; grading it resurrects the freeze through the judge |
@@ -9,9 +9,9 @@ command line overrides this table for a single run.
9
9
  |----|---------|------|----------------------|-------|
10
10
  | `spec-conformance` | ✅ true | `dimensions/spec-conformance.md` | all tasks | baseline correctness: AC + Done-when + contract shapes + non-go |
11
11
  | `tdd-surface` | ✅ true | `dimensions/tdd-surface.md` | all tasks | suite green + companion test files for new code; TDD-1/2 critical, TDD-3 advisory |
12
- | `integration` | ✅ true | `dimensions/integration.md` | `.be` and `.e2e` variants only | full-stack integration test + auth boundary + RLS-JWT pattern; runs only when variant matches |
12
+ | `integration` | ✅ true | `dimensions/integration.md` | `.be` and `.e2e` variants only | full-stack integration test + access boundary + enforcement-path integrity; stack read from the project profile, not hard-coded; runs only when variant matches |
13
13
  | `completeness` | ⚙️ auto | `dimensions/completeness.md` | all tasks (lens lite/standard) | auto-ON when spec has UC `## Invariants` (v2.8+); no-op on older specs |
14
- | `test-surface-conformance` | ⚙️ auto | `dimensions/test-surface-conformance.md` | all tasks (lens lite/standard) | auto-ON when spec has UC `## Test Surface` (v2.9+ or `--surface-only` retrofit); no-op otherwise. Report must list every TS row probed — qa-edge-hunter's negative-space input |
14
+ | `test-surface-conformance` | ⚙️ auto | `dimensions/test-surface-conformance.md` | all tasks (lens lite/standard) | auto-ON when spec has UC `## Test Surface` (v2.9+ or a retrofit-surface order); no-op otherwise. Report must list every TS row probed — qa-edge-hunter's negative-space input |
15
15
  | `security` | ⛔ false | `dimensions/security.md` | be / shared | stub — flip on when ready |
16
16
  | `performance` | ⛔ false | `dimensions/performance.md` | be / web | stub — flip on when ready |
17
17
 
@@ -25,7 +25,7 @@ criteria?"* — it grades the tasks that exist. It cannot see the task that was
25
25
  written. Shape Up's discovered-task philosophy says the real bulk of work is found while
26
26
  building; an invariant declared on a UC but never backed by a regression task is exactly
27
27
  that blind spot. This dimension converts "absence of a task" from invisible into a graded
28
- **GAP** — the judge surfaces it; the planner (a ba-pitch-analyzer reconcile/generate-board order) fills it.
28
+ **GAP** — the judge surfaces it; the planner (a ba-pitch-analyzer `reconcile` order) fills it.
29
29
  Judge never fills it itself.
30
30
 
31
31
  **Distinction held:** conformance = *the tasks that exist are correct*; completeness =