shapeup-sdlc 1.7.0 → 3.0.1
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.
- package/.claude/settings.local.example.json +5 -5
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +17 -3
- package/README.md +124 -103
- package/SECURITY.md +37 -30
- package/bin/init.mjs +77 -47
- package/bin/lib/grant.mjs +145 -0
- package/commands/build.md +7 -6
- package/commands/ship.md +29 -16
- package/commands/wire.md +1 -1
- package/hooks/dispatch-receipt.mjs +195 -0
- package/hooks/gate-intake.mjs +3 -3
- package/hooks/gate-zerowork.mjs +25 -24
- package/hooks/hooks.json +9 -48
- package/hooks/lib/decision.mjs +19 -8
- package/hooks/safety-spine.mjs +3 -3
- package/hooks/sandbox-guard.mjs +84 -40
- package/{skills/tech-lead/scripts/compile-order.mjs → kernel/compile.mjs} +283 -41
- package/{skills/tech-lead/scripts/gate-answers.mjs → kernel/gate.mjs} +58 -14
- package/kernel/harness.mjs +134 -0
- package/{skills/tech-lead/scripts/fit-check.mjs → kernel/init/fit.mjs} +15 -12
- package/{skills/tech-lead/scripts/init-run.mjs → kernel/init/run.mjs} +152 -31
- package/{skills/tech-lead/scripts → kernel}/lib/argv.mjs +52 -31
- package/{skills/tech-lead/scripts/lib/contract-md.mjs → kernel/lib/contract.mjs} +251 -7
- package/kernel/lib/paths.mjs +491 -0
- package/kernel/probe/concurrency.mjs +510 -0
- package/{skills/tech-lead/scripts/aegis-digest.mjs → kernel/probe/digest.mjs} +9 -10
- package/kernel/probe/eval.mjs +77 -0
- package/kernel/probe/leg.mjs +125 -0
- package/{skills/tech-lead/scripts/resume-state.mjs → kernel/probe/resume.mjs} +204 -63
- package/{skills/tech-lead/scripts → kernel/probe}/stats.mjs +14 -9
- package/kernel/probe/t0.mjs +66 -0
- package/{skills/ba-pitch-analyzer/scripts/board-derive.mjs → kernel/reduce/board.mjs} +99 -23
- package/kernel/reduce/graph.mjs +437 -0
- package/{skills/tech-lead/scripts/hill-derive.mjs → kernel/reduce/hill.mjs} +28 -9
- package/kernel/reduce/ingest.mjs +633 -0
- package/{hooks/slop-cleaner.mjs → kernel/reduce/leftovers.mjs} +40 -57
- package/{skills/tech-lead/scripts/ship-report.mjs → kernel/reduce/ship.mjs} +61 -13
- package/{skills/tech-lead/scripts/run-snapshot.mjs → kernel/reduce/snapshot.mjs} +21 -15
- package/{skills/spec-evaluator/scripts/verdict-ledger.mjs → kernel/reduce/verdict.mjs} +13 -7
- package/kernel/report/export.mjs +321 -0
- package/kernel/report/facts.mjs +209 -0
- package/{skills/tech-lead/scripts/budget-check.mjs → kernel/verify/budget.mjs} +15 -12
- package/kernel/verify/dispatch.mjs +114 -0
- package/{skills/tech-lead/scripts/validate-envelope.mjs → kernel/verify/envelope.mjs} +20 -15
- package/{skills/tech-lead/scripts/lib → kernel/verify}/ratchet-tree.mjs +36 -14
- package/kernel/verify/skills.mjs +125 -0
- package/kernel/verify/spec.mjs +559 -0
- package/{skills/tech-lead/scripts/t0-verify.mjs → kernel/verify/t0.mjs} +134 -24
- package/{skills/tech-lead/scripts/trace-lint.mjs → kernel/verify/trace.mjs} +26 -11
- package/oracles/http-oracle.mjs +1 -1
- package/oracles/process-oracle.mjs +1 -1
- package/oracles/snapshot-oracle.mjs +1 -1
- package/oracles/test-oracle.mjs +1 -1
- package/package.json +11 -9
- package/skills/ba-pitch-analyzer/SKILL.md +5 -5
- package/skills/ba-pitch-analyzer/assets/templates/_index.tmpl.md +1 -1
- package/skills/ba-pitch-analyzer/assets/templates/api-feasibility.tmpl.md +12 -7
- package/skills/ba-pitch-analyzer/assets/templates/contracts/third-party-api.contract.tmpl.md +6 -3
- package/skills/ba-pitch-analyzer/assets/templates/cross-context/migration-plan.tmpl.md +5 -4
- package/skills/ba-pitch-analyzer/assets/templates/cross-context/team-handoff.tmpl.md +23 -13
- package/skills/ba-pitch-analyzer/assets/templates/scope-summary.tmpl.md +17 -12
- package/skills/ba-pitch-analyzer/assets/templates/synthesis.tmpl.md +17 -38
- package/skills/ba-pitch-analyzer/assets/templates/task.tmpl.md +3 -0
- package/skills/ba-pitch-analyzer/references/contract-patterns.md +8 -4
- package/skills/ba-pitch-analyzer/references/doc-schemas.md +2 -0
- package/skills/ba-pitch-analyzer/references/task-generation.md +2 -2
- package/skills/qa-edge-hunter/SKILL.md +7 -3
- package/skills/scope-architect/SKILL.md +40 -6
- package/skills/solution-architect/SKILL.md +19 -4
- package/skills/spec-evaluator/SKILL.md +12 -2
- package/skills/task-executor/SKILL.md +7 -6
- package/skills/tech-lead/SKILL.md +50 -38
- package/skills/tech-lead/references/gates.md +71 -20
- package/skills/tech-lead/references/protocol.md +832 -0
- package/skills/tech-lead/schemas/domain.schema.json +341 -66
- package/skills/tech-lead/schemas/work-order.schema.json +11 -2
- package/skills/tech-lead/schemas/work-result.schema.json +1 -1
- package/skills/tech-lead/workflows/shapeup-run.js +1327 -750
- package/hooks/anti-rationalization.mjs +0 -238
- package/hooks/compact-snapshot.mjs +0 -47
- package/hooks/gate-deadline.mjs +0 -147
- package/hooks/gate-l2.mjs +0 -161
- package/hooks/session-rehydrate.mjs +0 -108
- package/skills/ba-pitch-analyzer/scripts/spec-lint.mjs +0 -239
- package/skills/spec-evaluator/README.md +0 -93
- package/skills/tech-lead/README.md +0 -71
- package/skills/tech-lead/references/delegation.md +0 -261
- package/skills/tech-lead/references/hard-rules.md +0 -34
- package/skills/tech-lead/references/invocation.md +0 -45
- package/skills/tech-lead/references/ledger-schema.md +0 -213
- package/skills/tech-lead/references/round-protocol.md +0 -234
- package/skills/tech-lead/references/state-model.md +0 -66
- package/skills/tech-lead/scripts/ingest-result.mjs +0 -258
- package/skills/tech-lead/scripts/lib/is-main.mjs +0 -81
- package/skills/tech-lead/scripts/lib/paths.mjs +0 -280
- package/skills/tech-lead/scripts/run-workflow.mjs +0 -381
- 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
|
-
|
|
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
|
-
|
|
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
|
|
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 |
|
|
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
|
|
175
|
+
## S-03 — Dependency Shape
|
|
176
176
|
|
|
177
|
-
> Open this section when **Dependency** is 🟡 or
|
|
177
|
+
> Open this section when **Dependency** is 🟡 or 🔴.
|
|
178
178
|
|
|
179
|
-
Derived from: `depends_on`
|
|
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
|
-
|
|
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
|
-
|
|
185
|
-
|
|
186
|
-
|
|
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 |
|
|
121
|
-
|
|
122
|
-
| [[FramerPageRepository]] | third-party-api | Framer REST API | ⚠️ speculative |
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)
|
|
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:
|
|
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
|
-
|
|
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
|
|
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
|
|
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}/
|
|
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
|
|
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
|
|
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):
|
|
74
|
-
entry_point (echo of the profile), entries[]
|
|
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}/
|
|
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}/
|
|
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}/
|
|
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
|
-
| `
|
|
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
|
|
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}/
|
|
197
|
-
# node "${CLAUDE_PLUGIN_ROOT}/
|
|
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
|
|
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}/
|
|
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
|
|
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}/
|
|
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}` —
|
|
49
|
-
|
|
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/
|
|
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):
|
|
57
|
-
(`domain.schema.json` `$defs/RunArgs` — `{slug, autoLevel, answers,
|
|
58
|
-
budgets:{maxRounds,attemptBudget,wallClockS}, pluginRoot, startedAt}
|
|
59
|
-
|
|
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
|
-
```
|
|
62
|
-
|
|
63
|
-
"${CLAUDE_PLUGIN_ROOT}/skills/tech-lead/workflows/shapeup-run.js"
|
|
64
|
-
|
|
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
|
|
69
|
-
exit code, in code, not by this skill's own reading of a paragraph. The `RunReturn`
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
**
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/
|
|
123
|
-
> **The round loop, stop conditions, three-level breaker rationale** → `references/
|
|
124
|
-
> **Run ledger format + Hill report** → `references/
|
|
125
|
-
> **State ownership, the central domain registry, two-ledger split** → `references/
|
|
126
|
-
> **Hard rules this design enforces, and why** → `references/
|
|
127
|
-
> **Full invocation examples + the complete flag table** →
|
|
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
|
|
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.
|