shapeup-sdlc 3.18.2 → 4.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.
- package/.claude/settings.local.example.json +2 -3
- package/.claude-plugin/plugin.json +1 -1
- package/AGENTS.md +115 -56
- package/README.md +101 -143
- package/SECURITY.md +16 -25
- package/agents/orient.md +14 -0
- package/agents/qa-edge-hunter.md +13 -0
- package/agents/spec-evaluator.md +14 -0
- package/agents/task-executor.md +14 -0
- package/bin/init.mjs +13 -16
- package/bin/lib/grant.mjs +8 -19
- package/commands/build.md +9 -14
- package/commands/eval.md +3 -3
- package/commands/hammer.md +9 -5
- package/commands/retro.md +12 -11
- package/commands/scopes.md +1 -12
- package/commands/ship.md +45 -88
- package/commands/wire.md +1 -8
- package/hooks/dispatch-receipt.mjs +94 -8
- package/hooks/hooks.json +0 -41
- package/hooks/lib/decision.mjs +6 -9
- package/hooks/lib/tier.mjs +50 -0
- package/hooks/sandbox-guard.mjs +140 -64
- package/kernel/gate.mjs +203 -22
- package/kernel/harness.mjs +20 -67
- package/kernel/init/run.mjs +175 -523
- package/kernel/lib/contract.mjs +9 -93
- package/kernel/lib/floor.mjs +64 -0
- package/kernel/lib/paths.mjs +39 -112
- package/kernel/order.mjs +157 -0
- package/kernel/probe/digest.mjs +2 -38
- package/kernel/schemas/domain.schema.json +146 -1125
- package/kernel/schemas/work-order.schema.json +8 -4
- package/kernel/schemas/work-result.schema.json +1 -1
- package/kernel/verify/envelope.mjs +2 -2
- package/kernel/verify/skills.mjs +27 -8
- package/kernel/verify/t0.mjs +2 -2
- package/package.json +4 -2
- package/skills/building/SKILL.md +144 -0
- package/skills/building/resources/gates.md +76 -0
- package/skills/building/resources/guidance.md +23 -0
- package/skills/{translator/references/preservation-rules.md → building/resources/intake-preservation.md} +1 -1
- package/skills/building/resources/intake.md +157 -0
- package/skills/building/resources/orders.md +69 -0
- package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/doc-schemas.md +1 -1
- package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/task-generation.md +13 -13
- package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/test-surface.md +6 -7
- package/skills/building/resources/plan-scopes.md +95 -0
- package/skills/building/resources/plan-spec.md +102 -0
- package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/_index.tmpl.md +1 -1
- package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/assess-report.tmpl.md +10 -11
- package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/run-state.tmpl.md +4 -4
- package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/scope-summary.tmpl.md +2 -2
- package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/synthesis.tmpl.md +4 -4
- package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/usecase.tmpl.md +2 -2
- package/skills/building/resources/plan-wire.md +82 -0
- package/skills/building/resources/plan.md +98 -0
- package/skills/building/resources/retro-research.md +60 -0
- package/skills/building/resources/retro-scan.md +49 -0
- package/skills/building/resources/retro.md +225 -0
- package/skills/building/resources/rounds.md +78 -0
- package/skills/building/resources/stop.md +127 -0
- package/skills/orient/SKILL.md +37 -37
- package/skills/qa-edge-hunter/SKILL.md +29 -14
- package/skills/shapeup/SKILL.md +5 -5
- package/skills/shapeup/resources/breadboarding.md +1 -1
- package/skills/shapeup/resources/context-compaction.md +5 -5
- package/skills/shapeup/resources/shaping.md +1 -1
- package/skills/spec-evaluator/SKILL.md +17 -21
- package/skills/spec-evaluator/references/dimension-contract.md +1 -1
- package/skills/spec-evaluator/references/dimensions/completeness.md +3 -3
- package/skills/spec-evaluator/references/dimensions/spec-conformance.md +1 -1
- package/skills/spec-evaluator/references/dimensions/test-surface-conformance.md +5 -5
- package/skills/task-executor/SKILL.md +11 -15
- package/commands/hill.md +0 -10
- package/hooks/gate-intake.mjs +0 -109
- package/hooks/gate-zerowork.mjs +0 -349
- package/hooks/tier-guard.mjs +0 -162
- package/kernel/compile.mjs +0 -1419
- package/kernel/init/fit.mjs +0 -199
- package/kernel/init/run-args.mjs +0 -206
- package/kernel/lib/breadboard.mjs +0 -165
- package/kernel/probe/attempts.mjs +0 -161
- package/kernel/probe/concurrency.mjs +0 -535
- package/kernel/probe/eval.mjs +0 -405
- package/kernel/probe/hunt.mjs +0 -104
- package/kernel/probe/leg.mjs +0 -229
- package/kernel/probe/owner.mjs +0 -142
- package/kernel/probe/requirements.mjs +0 -328
- package/kernel/probe/resume.mjs +0 -1110
- package/kernel/probe/rounds.mjs +0 -115
- package/kernel/probe/staged.mjs +0 -83
- package/kernel/probe/stats.mjs +0 -477
- package/kernel/probe/t0.mjs +0 -115
- package/kernel/reduce/board.mjs +0 -350
- package/kernel/reduce/graph.mjs +0 -482
- package/kernel/reduce/hill.mjs +0 -322
- package/kernel/reduce/ingest.mjs +0 -767
- package/kernel/reduce/leftovers.mjs +0 -159
- package/kernel/reduce/ship.mjs +0 -529
- package/kernel/reduce/snapshot.mjs +0 -291
- package/kernel/reduce/verdict.mjs +0 -172
- package/kernel/report/export.mjs +0 -384
- package/kernel/report/facts.mjs +0 -234
- package/kernel/verify/budget.mjs +0 -153
- package/kernel/verify/build.mjs +0 -428
- package/kernel/verify/dispatch.mjs +0 -114
- package/kernel/verify/spec.mjs +0 -975
- package/kernel/verify/trace.mjs +0 -604
- package/skills/ba-pitch-analyzer/SKILL.md +0 -204
- package/skills/coach/SKILL.md +0 -397
- package/skills/hill-chart/SKILL.md +0 -154
- package/skills/hill-chart/assets/dashboard.template.html +0 -1432
- package/skills/scope-architect/SKILL.md +0 -174
- package/skills/scope-hammer/SKILL.md +0 -231
- package/skills/solution-architect/SKILL.md +0 -158
- package/skills/tech-lead/SKILL.md +0 -151
- package/skills/tech-lead/references/gates.md +0 -605
- package/skills/tech-lead/references/protocol.md +0 -889
- package/skills/tech-lead/references/tiny-lane.md +0 -53
- package/skills/tech-lead/workflows/shapeup-run.js +0 -2187
- package/skills/translator/SKILL.md +0 -258
- /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/contract-patterns.md +0 -0
- /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/ddd-patterns.md +0 -0
- /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/integration-analysis.md +0 -0
- /package/skills/{ba-pitch-analyzer/references → building/resources/plan-references}/ux-behavior-patterns.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/api-feasibility.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/contracts/be-service.contract.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/contracts/offline-storage.contract.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/contracts/third-party-api.contract.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/context-map.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/event-choreography.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/migration-plan.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/cross-context/team-handoff.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/domain-model.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/feedback.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/integration.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/task-board.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/task-spike.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/task.tmpl.md +0 -0
- /package/skills/{ba-pitch-analyzer/assets/templates → building/resources/plan-templates}/ux-behavior.tmpl.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-evaluator
|
|
3
|
-
description: "Use this skill whenever the user wants to evaluate, QA, or verify that an implemented task actually matches its spec and acceptance criteria — the judge in a planner→generator→evaluator harness. Trigger on: \"evaluate task TASK-NNN\", \"QA TASK-NNN\", \"verify against spec\", \"check acceptance criteria\", \"does this match the spec\", \"grade this build\", \"run evaluator\", or a
|
|
3
|
+
description: "Use this skill whenever the user wants to evaluate, QA, or verify that an implemented task actually matches its spec and acceptance criteria — the judge in a planner→generator→evaluator harness. Trigger on: \"evaluate task TASK-NNN\", \"QA TASK-NNN\", \"verify against spec\", \"check acceptance criteria\", \"does this match the spec\", \"grade this build\", \"run evaluator\", or a loop --order dispatch. Skeptical by default — absence of evidence is a FAIL; probes the running app and files file:line bugs."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Spec Evaluator (the single judge, pure worker v1.0)
|
|
@@ -9,7 +9,7 @@ description: "Use this skill whenever the user wants to evaluate, QA, or verify
|
|
|
9
9
|
|
|
10
10
|
The **judge** in a planner → generator → evaluator loop. It reads the committed spec, exercises
|
|
11
11
|
the **running** app, and returns a hard-threshold verdict plus a file:line bug list — as a
|
|
12
|
-
WorkResult envelope the orchestrator
|
|
12
|
+
WorkResult envelope the orchestrator applies. The generator fixes; the evaluator re-runs.
|
|
13
13
|
|
|
14
14
|
**Core guarantee — skeptical by default.** Out-of-the-box an LLM is a lenient QA: it finds a
|
|
15
15
|
real defect, then talks itself into approving anyway. This skill inverts that posture. A
|
|
@@ -20,7 +20,7 @@ criterion with no collected evidence is a **FAIL**, never a pass-by-assumption.
|
|
|
20
20
|
> **Dimension contract (injection interface)** → `references/dimension-contract.md`.
|
|
21
21
|
> Where any reference file describes *writing* shared state (task files, `.verdicts` ledger,
|
|
22
22
|
> run-state), the pure-worker contract overrides it: that data returns in the WorkResult and
|
|
23
|
-
> the orchestrator
|
|
23
|
+
> the orchestrator performs the write. Old gate names in reference files map
|
|
24
24
|
> 1:1 onto the core process below: GATE V0/V0.5 = input contract + dimension resolution,
|
|
25
25
|
> GATE V1 = CONTRACT, Phase A = PROBE, GATE V2 = VERDICT, Phase B = REPORT; GATE V3
|
|
26
26
|
> (sign-off) is retired — pausing is the caller's `interaction` policy.
|
|
@@ -42,7 +42,7 @@ Invoked as `--order <path>`. Fields you may rely on (absent = unknown, never inf
|
|
|
42
42
|
| `payload.launch_cmd` | The project profile's launch probe: installs the built artifact, starts it and asserts the first screen. This is how the app is brought up for `[ui]` probing. A non-zero exit is a finding to cite, not a reason to try another way. Absent → the profile declares none; fall back to `run_cmd` |
|
|
43
43
|
| `payload.build_gate` | This run's newest round build gate artifact — each step's exit code and output tail. It records that the build ran and whether the app launched, and the launch step's output names what it captured. Read it before grading any `[ui]` row NO EVIDENCE: a launch that succeeded is evidence the app can be probed, and the row is graded on the app, not on its absence. Absent → the gate never ran |
|
|
44
44
|
| `payload.revised_checks[]` | Rows that FAILed in one trial of this round and PASS in a later one whose own check file changed in between — a pass obtained by editing the check. Read each listed file against its row's Expect before you let its PASS count; a check that no longer asserts what the row asks makes that row a FAIL, and the bug names the check. Absent → no check was rewritten |
|
|
45
|
-
| `payload.t0_artifacts[]` | Per-scope T0 verdict paths for this round (scoped specs),
|
|
45
|
+
| `payload.t0_artifacts[]` | Per-scope T0 verdict paths for this round (scoped specs), listed by the orchestrator from each scope's latest verdict. An artifact listed but missing/red on disk, or a scoped spec with none listed → the round is NOT gradeable: return `status: failed` with the reason, naming the scope, as your FIRST deviation — a structural precondition, not a criterion |
|
|
46
46
|
| `payload.scopes_without_t0[]` | Scopes with no green T0 this round while others have one. The round IS gradeable: grade every row such a scope owns as FAIL, evidence "no green T0 for scope <id>" with the scope contract as its locator (`…/scopes/<id>.md:1`). Never refuse the round for them — a refusal ends the run before the next round or GATE H can act. Absent → every scope is green |
|
|
47
47
|
| `payload.browser` | `cli` (default, ~4x cheaper) \| `mcp` \| `none` |
|
|
48
48
|
| `payload.tasks[]` | Traceability only (which UCs a task claims): NEVER a grading source — the committed UC text is the criterion, a paraphrase mismatch is a finding |
|
|
@@ -101,15 +101,13 @@ Done-when statements; `_index.md` Non-Go list. Which UCs are in scope comes from
|
|
|
101
101
|
- Re-probe every FAIL once before finalizing: agree → confidence high; disagree → keep FAIL
|
|
102
102
|
(no stable pass = FAIL), confidence low, note flaky.
|
|
103
103
|
- Read any existing `.verdicts-*.jsonl` (read-only) to detect flips vs prior runs — a flip
|
|
104
|
-
forces confidence low and a stability note. The new lines return in your envelope;
|
|
104
|
+
forces confidence low and a stability note. The new lines return in your envelope; the loop
|
|
105
105
|
appends them (never rewrite history).
|
|
106
106
|
- Dimension threshold from its file (spec-conformance: 100% of [cmd]/[ui]/[data] criteria +
|
|
107
107
|
contract triplet + Non-Go). Overall PASS only if ALL active dimensions pass — the halo
|
|
108
108
|
effect is banned; a strong dimension never lifts a failing one.
|
|
109
109
|
- **T0 citation (scoped specs).** Recompute each cited artifact's sha256 from disk — never
|
|
110
|
-
trust a handed hash. Use any hasher you may run
|
|
111
|
-
`harness probe t0 --slug <slug> --scope <scope_id> --round <r>` prints the digest of that
|
|
112
|
-
scope's green verdict as the file is at that moment. A digest from any other place — a ledger
|
|
110
|
+
trust a handed hash. Use any hasher you may run (`shasum -a 256 <path>`, or `node -e` with `node:crypto`). A digest from any other place — a ledger
|
|
113
111
|
line, an earlier report, an error message — is a handed hash, however correct it looks. A verdict on a scoped spec without a T0 citation is structurally
|
|
114
112
|
invalid, regardless of how convincing your own probing looked; generator prose ("tests
|
|
115
113
|
pass", "verified locally") is never admissible evidence.
|
|
@@ -177,8 +175,8 @@ round. Write it so someone without your context can answer it in one reply.
|
|
|
177
175
|
```
|
|
178
176
|
|
|
179
177
|
**Every Test Surface row is its own criterion.** Name the row's id (`TS-05-05`) in `criterion`, one
|
|
180
|
-
row per entry — never a range (`TS-01-04/05`) and never a group ("device rows").
|
|
181
|
-
|
|
178
|
+
row per entry — never a range (`TS-01-04/05`) and never a group ("device rows"). A PASS that
|
|
179
|
+
leaves any row of the spec unnamed is incomplete, because the requirement matrix, the next round's bugs
|
|
182
180
|
and the rewritten-check list all read the verdict one row at a time.
|
|
183
181
|
|
|
184
182
|
**`traces_to` is copied, not invented.** Fill it from the `(covers: REQ-…)` clause of the
|
|
@@ -188,15 +186,15 @@ clause yields no anchor — leave the array empty rather than guessing, and neve
|
|
|
188
186
|
supply one. This changes nothing you grade: the anchor is a navigation path, never a grading input,
|
|
189
187
|
and a criterion passes or fails on its evidence exactly as before. It matters downstream because
|
|
190
188
|
the requirement matrix at GATE L4 and the census at GATE H are projected from these anchors; a
|
|
191
|
-
verdict that drops them grades the build and says nothing about what the pitch asked for.
|
|
189
|
+
verdict that drops them grades the build and says nothing about what the pitch asked for. A verdict that anchors no criterion at all while the board's ACs carry `covers:` clauses has dropped the link the loop reads.
|
|
192
190
|
|
|
193
191
|
**Every FAIL criterion's `evidence` MUST carry a `file:line` locator** — schema-enforced, not
|
|
194
|
-
advice: the envelope is validated against `work-result.schema.json`
|
|
192
|
+
advice: the envelope is validated against `work-result.schema.json` when the loop reads it and a locatorless
|
|
195
193
|
FAIL is rejected before any write. A PASS may cite plain output. (Observed, not theorized: a
|
|
196
194
|
correct FAIL verdict with no locator anywhere is unactionable without re-investigating — the
|
|
197
195
|
rule used to live in prose and be enforced nowhere; it is now data in `domain.schema.json`.)
|
|
198
196
|
|
|
199
|
-
The orchestrator's
|
|
197
|
+
The orchestrator's the loop appends the verdict ledger, un-ticks the `refuted` boxes, and sets
|
|
200
198
|
`eval_verdict` frontmatter. You never touch a task file, a board, or run-state — and you
|
|
201
199
|
NEVER set `status: done`: the judge issues verdicts; closure belongs elsewhere. That
|
|
202
200
|
separation is the whole point of the architecture.
|
|
@@ -212,7 +210,7 @@ separation is the whole point of the architecture.
|
|
|
212
210
|
- [ ] Every FAIL was re-probed once; confidence assigned per the ledger rule
|
|
213
211
|
- [ ] Scoped spec → T0 citations present with recomputed sha256 (else the run returned `failed`)
|
|
214
212
|
- [ ] Report written inside `evaluation/**` only; no other file touched
|
|
215
|
-
- [ ] `refuted[]` lists exactly the boxes your evidence disproves (un-ticking is
|
|
213
|
+
- [ ] `refuted[]` lists exactly the boxes your evidence disproves (un-ticking is the loop's act)
|
|
216
214
|
- [ ] The WorkResult validates against `work-result.schema.json`
|
|
217
215
|
|
|
218
216
|
---
|
|
@@ -233,17 +231,15 @@ bug_template). Adding one (e.g. security) = write `references/dimensions/securit
|
|
|
233
231
|
# Orchestrated (once per round, after GATE L2) — the canonical form
|
|
234
232
|
/spec-evaluator --order .shapeup/checkout-vnpay/orders/evaluate-r2.json
|
|
235
233
|
|
|
236
|
-
# Standalone — the preamble shim
|
|
237
|
-
# node "<kernel>" compile --operation evaluate --slug <slug> \
|
|
238
|
-
# --worker spec-evaluator [--payload '{"dimensions": [...], "run_cmd": "..."}']
|
|
234
|
+
# Standalone — the preamble shim writes a minimal order by hand, then the single code path runs:
|
|
239
235
|
/spec-evaluator --spec shapeup/checkout-vnpay/spec/ --task TASK-007
|
|
240
236
|
/spec-evaluator --spec shapeup/checkout-vnpay/spec/ --feature checkout-vnpay --single-pass
|
|
241
237
|
```
|
|
242
238
|
|
|
243
239
|
Standalone keeps `--task` (per-task check, not round-gated) and `--single-pass` (feature-level)
|
|
244
240
|
— the shim maps them onto the order's payload; missing run command → ask. After writing the
|
|
245
|
-
WorkResult,
|
|
246
|
-
summary — standalone has no orchestrator to
|
|
241
|
+
WorkResult, show the user its
|
|
242
|
+
summary — standalone has no orchestrator to apply it for you.
|
|
247
243
|
|
|
248
244
|
---
|
|
249
245
|
|
|
@@ -254,10 +250,10 @@ summary — standalone has no orchestrator to ingest for you.
|
|
|
254
250
|
| Absence of evidence = FAIL | Kills pass-by-assumption, the core QA failure mode |
|
|
255
251
|
| Halo effect banned | A strong dimension never lifts a failing one |
|
|
256
252
|
| Disabled dimensions are out of scope | No silent scope creep |
|
|
257
|
-
| Evaluator never sets `status: done`, never edits task files/boards | Judge ≠ doer; refuted boxes return as data,
|
|
253
|
+
| Evaluator never sets `status: done`, never edits task files/boards | Judge ≠ doer; refuted boxes return as data, the loop writes |
|
|
258
254
|
| Untestable AC blocks a clean PASS | Forces the spec to be verifiable, not vibes |
|
|
259
255
|
| Probe the RUNNING app, not the source alone | Apps that look right still break when used |
|
|
260
256
|
| Re-probe every FAIL; flip ⇒ confidence low | A single snapshot lies; the ledger makes it visible |
|
|
261
|
-
| Verdict-ledger lines are returned, appended by
|
|
257
|
+
| Verdict-ledger lines are returned, appended by the loop, never rewritten | Verdict history is how a single-snapshot judge becomes measurable |
|
|
262
258
|
| A verdict on a scoped spec without a T0 citation is structurally invalid | T0 is a machine fact the generator cannot fabricate |
|
|
263
259
|
| UI assertions target affordances only (test_id/role/data-state) | Layer-3 styling is frozen; grading it resurrects the freeze through the judge |
|
|
@@ -16,7 +16,7 @@ enabled: true # core loads it only if true (or named in --dime
|
|
|
16
16
|
weight: 1.0 # informational; thresholds are hard, not weighted averages
|
|
17
17
|
hard_threshold: all-pass # see "Threshold vocabulary" below
|
|
18
18
|
applies_to: # scoping — omit a key to mean "all"
|
|
19
|
-
lens: [lite, standard] # which
|
|
19
|
+
lens: [lite, standard] # which planning lenses
|
|
20
20
|
package: any # apps/api | apps/web | apps/mobile | packages/shared | any
|
|
21
21
|
variant: any # shared | be | web | mobile | e2e | any
|
|
22
22
|
requires_browser: true # does this dimension need the running app in a browser?
|
|
@@ -14,7 +14,7 @@ requires_browser: false
|
|
|
14
14
|
# Completeness Dimension
|
|
15
15
|
|
|
16
16
|
> **Auto-enable rule (read at GATE V0.5):** This dimension stays `enabled: false` by
|
|
17
|
-
> default so it is a no-op on every spec generated before
|
|
17
|
+
> default so it is a no-op on every spec generated before the planner wrote Invariants sections.
|
|
18
18
|
> The core flips it ON for a run **only when** the spec's `usecases/` contains at least
|
|
19
19
|
> one `## Invariants` section. A pre-v2.8 spec has no invariants → this dimension never
|
|
20
20
|
> activates → existing audit scores and verdicts are unchanged (non-regression guarantee).
|
|
@@ -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
|
|
28
|
+
**GAP** — the judge surfaces it; the planner (a plan spec step in `reconcile` mode) fills it.
|
|
29
29
|
Judge never fills it itself.
|
|
30
30
|
|
|
31
31
|
**Distinction held:** conformance = *the tasks that exist are correct*; completeness =
|
|
@@ -98,5 +98,5 @@ location: [usecases/UC-Name.md#Invariants INV-NN | usecases/UC-Name.md | discove
|
|
|
98
98
|
repro: <how the gap was detected — e.g. "grep use_case_refs across tasks/ found 0 backing TASK for INV-02">
|
|
99
99
|
expected: <e.g. "≥1 regression task referencing UC-ConnectObjects covering INV-02">
|
|
100
100
|
actual: <e.g. "no task references INV-02; invariant declared but unverified">
|
|
101
|
-
next: <handoff — e.g. "a
|
|
101
|
+
next: <handoff — e.g. "a plan spec step in reconcile mode over <ledger> to generate the missing regression task">
|
|
102
102
|
```
|
|
@@ -77,7 +77,7 @@ dimensions, off by default.
|
|
|
77
77
|
Inspect the diff / changed files. No file outside the feature's declared package/scope is
|
|
78
78
|
modified, and no item in _index.md's ## Non-Go list is touched. Any out-of-scope change
|
|
79
79
|
FAILS with file:line. (A local task file's own Non-Go section, when present, is consistent
|
|
80
|
-
with _index.md by construction —
|
|
80
|
+
with _index.md by construction — the plan activity derives it from the pitch — but the
|
|
81
81
|
committed _index.md is the grading source since the task file may not exist locally.)
|
|
82
82
|
source: index
|
|
83
83
|
|
|
@@ -14,9 +14,9 @@ requires_browser: true
|
|
|
14
14
|
# Test Surface Conformance Dimension
|
|
15
15
|
|
|
16
16
|
> **Auto-enable rule (read at GATE V0.5):** stays `enabled: false` by default — a no-op on
|
|
17
|
-
> every spec generated before
|
|
17
|
+
> every spec generated before the planner wrote a Test Surface. The core flips it ON for a run
|
|
18
18
|
> **only when** the spec's `usecases/` contains at least one `## Test Surface` section
|
|
19
|
-
> (fresh v2.9 spec, or a pre-v2.9 spec retrofitted
|
|
19
|
+
> (fresh v2.9 spec, or a pre-v2.9 spec retrofitted by a plan spec step in `retrofit-surface` mode). Pre-surface
|
|
20
20
|
> specs → never activates → existing verdicts unchanged (non-regression guarantee).
|
|
21
21
|
> Explicit `--dimensions ...,test-surface-conformance` always wins over the auto rule.
|
|
22
22
|
|
|
@@ -27,7 +27,7 @@ that the spec already implies. The BA now derives that matrix into each UC's
|
|
|
27
27
|
`## Test Surface` (D1 Invariants · D2 Error Cases · D3 Contract shapes · D4 No-gos,
|
|
28
28
|
mechanical-only); this dimension is the judge-side half: probe every derived row against
|
|
29
29
|
the running app. Judge probes; it never authors rows — a missing or thin Test Surface is
|
|
30
|
-
reported as a finding and routed back to the planner's retrofit-surface
|
|
30
|
+
reported as a finding and routed back to the planner's `retrofit-surface` spec mode, never filled in here.
|
|
31
31
|
|
|
32
32
|
**Distinctions held:**
|
|
33
33
|
- conformance = *the AC that were written pass* · test-surface = *the matrix the spec
|
|
@@ -63,7 +63,7 @@ reported as a finding and routed back to the planner's retrofit-surface operatio
|
|
|
63
63
|
pass_rule: >
|
|
64
64
|
Cross-check each UC: Invariants ↔ TS-INV rows, Error Cases codes ↔ TS-ERR rows, and
|
|
65
65
|
every row's Source cites D1–D4. A UC with `## Test Surface` whose own sources are
|
|
66
|
-
uncovered → FAIL at `major` with `next: retrofit-surface
|
|
66
|
+
uncovered → FAIL at `major` with `next: a plan spec step in retrofit-surface mode` (judge surfaces the gap;
|
|
67
67
|
generator fills it — this dimension NEVER authors rows). A UC carrying the explicit
|
|
68
68
|
empty-sources line passes TSC-2 vacuously. A v2.9+ spec UC with NO `## Test Surface`
|
|
69
69
|
section at all → FAIL at `major`, same routing.
|
|
@@ -90,7 +90,7 @@ ts_row: <the full row probed, verbatim>
|
|
|
90
90
|
repro: <probe executed — command / UI steps>
|
|
91
91
|
expected: <the Expect cell>
|
|
92
92
|
actual: <observed evidence — response, state, screenshot ref>
|
|
93
|
-
next: <TSC-1 → task-executor fix via
|
|
93
|
+
next: <TSC-1 → task-executor fix via the loop round r+1 | TSC-2 → retrofit-surface re-run>
|
|
94
94
|
```
|
|
95
95
|
|
|
96
96
|
## Report obligation (the QA handoff)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: task-executor
|
|
3
|
-
description: "Use this skill whenever a user wants to execute, implement, or run a specific task generated by the
|
|
3
|
+
description: "Use this skill whenever a user wants to execute, implement, or run a specific task generated by the plan activity (`/ship plan`). Triggers on: \"execute task TASK-NNN\", \"implement TASK-NNN\", \"run this task\", \"start working on TASK-NNN\", \"implement the task in [folder]\", \"run task from spec folder\", \"pick up the next task\", or a loop --order dispatch. Implements a task's acceptance criteria exactly — minimum code, surgical diffs, verified observable outcomes."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Task Executor (pure worker, v2.0)
|
|
@@ -23,8 +23,8 @@ rely on (anything absent = **unknown**; never invent it):
|
|
|
23
23
|
|
|
24
24
|
| Field | What it is |
|
|
25
25
|
|---|---|
|
|
26
|
-
| `payload.tasks[]` | The task(s) to implement: `id
|
|
27
|
-
| `payload.scope_contract` | The active scope: `affordance_manifest`, `e2e_verification_fixtures`, topology |
|
|
26
|
+
| `payload.tasks[]` | The task(s) to implement: `id` and `body_path` — read the file fully; its acceptance criteria are in it |
|
|
27
|
+
| `payload.scope_contract` | The path of the active scope's contract (`scopes/<id>.md`) — read it: `affordance_manifest`, `e2e_verification_fixtures`, topology |
|
|
28
28
|
| `substrate.allowed` / `substrate.shared` | The ONLY globs you may write. A needed file outside them → ESCALATE, never a write (a sandbox hook blocks it anyway) |
|
|
29
29
|
| `payload.decisions[]` | Adjudicated answers from prior escalations — binding precedent, apply them |
|
|
30
30
|
| `payload.digested_errors[]` | `{file, line, core_message}` triples from the previous attempt's failed verification (a test that failed by name with no file:line — `FAIL TS-05-05 step 4: …` — arrives with `file: null` and the whole line as its message) — your starting bug list |
|
|
@@ -165,13 +165,13 @@ suffix come from `order_id`) matching `work-result.schema.json`, and print its p
|
|
|
165
165
|
}
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
-
`ac` carries the checkbox text **verbatim** — the
|
|
168
|
+
`ac` carries the checkbox text **verbatim** — the loop ticks boxes by matching it.
|
|
169
169
|
Failing/skipped ACs are reported as such, never omitted. Discovered work is *reported*, never
|
|
170
170
|
self-planned: no new task files, no spec edits — one raw line per discovery.
|
|
171
171
|
|
|
172
172
|
You do NOT: tick AC boxes, edit `tasks/_index.md`, write `run-state.md`, touch the discovery
|
|
173
173
|
ledger, mark anything done outside your result, or update any other spec document. The
|
|
174
|
-
orchestrator's
|
|
174
|
+
orchestrator's loop does all of that from your envelope.
|
|
175
175
|
|
|
176
176
|
---
|
|
177
177
|
|
|
@@ -191,20 +191,16 @@ orchestrator's `harness reduce ingest` does all of that from your envelope.
|
|
|
191
191
|
## Invocation
|
|
192
192
|
|
|
193
193
|
```bash
|
|
194
|
-
# Orchestrated (
|
|
194
|
+
# Orchestrated (the loop's build step) — the canonical form
|
|
195
195
|
/task-executor --order .shapeup/checkout-vnpay/orders/r2-a3.json
|
|
196
196
|
|
|
197
|
-
# Standalone — the preamble shim
|
|
198
|
-
#
|
|
199
|
-
# node "<kernel>" compile --task TASK-003 --slug checkout-vnpay
|
|
200
|
-
# node "<kernel>" compile --next --slug checkout-vnpay
|
|
197
|
+
# Standalone — the preamble shim writes a minimal WorkOrder by hand from the flags (the loop's
|
|
198
|
+
# `resources/orders.md` has the shape), then the single code path above runs:
|
|
201
199
|
/task-executor --spec shapeup/checkout-vnpay/spec/ --task TASK-003
|
|
202
200
|
/task-executor --spec shapeup/checkout-vnpay/spec/ --next
|
|
203
201
|
```
|
|
204
202
|
|
|
205
|
-
Standalone shim: derive `<slug>` from the `--spec` path (`shapeup/<slug>/spec`),
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
`node "<kernel>" reduce ingest <result path>` yourself and show the user its
|
|
209
|
-
summary — standalone has no orchestrator to ingest for you. One code path inside; two entry
|
|
203
|
+
Standalone shim: derive `<slug>` from the `--spec` path (`shapeup/<slug>/spec`), write a minimal order
|
|
204
|
+
by hand with `"mode": "standalone"`, then proceed against it exactly as if dispatched. After writing the
|
|
205
|
+
WorkResult, show the user its summary — standalone has no orchestrator to apply it for you. One code path inside; two entry
|
|
210
206
|
points outside.
|
package/commands/hill.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Render the Hill Chart dashboard — a portfolio of pitches, or one pitch's detail
|
|
3
|
-
---
|
|
4
|
-
Use the **hill-chart** skill on $ARGUMENTS.
|
|
5
|
-
|
|
6
|
-
Renders a self-contained dashboard from committed hill shards (`shapeup/<slug>/hill/*.yml`) and
|
|
7
|
-
each pitch's local run graph (`.shapeup/<slug>/graph.jsonl`): a portfolio card per pitch, and
|
|
8
|
-
per-pitch detail with a mechanical Hill Chart, an attention list, a scope board, round history,
|
|
9
|
-
and the full run graph one click deeper. Give a slug to render one pitch only; no argument
|
|
10
|
-
renders the whole portfolio.
|
package/hooks/gate-intake.mjs
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// GATE L0.0 — intake precondition. PreToolUse hook.
|
|
3
|
-
//
|
|
4
|
-
// Denies a `tech-lead` dispatch that carries no pitch, no spec folder, and no requirement text.
|
|
5
|
-
//
|
|
6
|
-
// WHY THIS EXISTS (reproduced, not theorized). The orchestrator was reached as
|
|
7
|
-
//
|
|
8
|
-
// Skill(tech-lead, args: "--unattended")
|
|
9
|
-
//
|
|
10
|
-
// — the flag survived the hand-off, the requirement text did not. With nothing to orchestrate,
|
|
11
|
-
// the run printed the gate names, a confident plan, and wrote no code, while *looking* like a
|
|
12
|
-
// successful run. The same harness invoked with --pitch/--spec built the feature. Whether a model
|
|
13
|
-
// happens to inline the text and recover is a property of the model, not of the harness.
|
|
14
|
-
//
|
|
15
|
-
// That is the "agent claims done" failure this project exists to prevent, happening at the
|
|
16
|
-
// project's own front door. Every other invariant that matters here lives in the runtime; this one
|
|
17
|
-
// was living in a prompt, and a prompt is exactly what gets dropped on a hand-off. So it becomes a
|
|
18
|
-
// hook, like GATE L2.
|
|
19
|
-
//
|
|
20
|
-
// Design mirrors the GATE L2 block deliberately:
|
|
21
|
-
// • Scope — only `Skill` → tech-lead. Anything else defers instantly.
|
|
22
|
-
// • Fail-CLOSED only on a provably empty intake, with an actionable re-invocation in the reason.
|
|
23
|
-
// • Fail-OPEN on anything ambiguous (unparseable payload, unknown arg shape, an envelope
|
|
24
|
-
// --order). A gate that blocks legitimate runs gets disabled, and a disabled gate enforces
|
|
25
|
-
// nothing.
|
|
26
|
-
//
|
|
27
|
-
// Contract: PreToolUse stdin JSON { tool_name, tool_input:{skill_name|skill, skill_args|args}, ... }
|
|
28
|
-
// Deny via { hookSpecificOutput: { hookEventName, permissionDecision:"deny", permissionDecisionReason } }.
|
|
29
|
-
|
|
30
|
-
// RECEIPTS (v1.5). This gate has been scored `No effect` on a re-run where the acceptance rate did
|
|
31
|
-
// not move — because the hook CORRECTLY never fired and the cause was elsewhere. That distinction
|
|
32
|
-
// is unprovable from a hook that answers "inspected and permitted" and "never ran" with the same
|
|
33
|
-
// silence. Every decision below is now recorded (hooks/lib/decision.mjs).
|
|
34
|
-
|
|
35
|
-
import { runHook, readStdin, settle } from "./lib/decision.mjs";
|
|
36
|
-
|
|
37
|
-
await runHook("gate-intake", async () => {
|
|
38
|
-
/** Fail-open, with the reason on the record. */
|
|
39
|
-
const defer = (reason, rule) => settle({ verdict: "allow", event: "PreToolUse", tool: p?.tool_name ?? null, reason, rule });
|
|
40
|
-
|
|
41
|
-
const raw = await readStdin();
|
|
42
|
-
|
|
43
|
-
let p;
|
|
44
|
-
try { p = JSON.parse(raw || "{}"); }
|
|
45
|
-
catch (e) { settle({ verdict: "error", event: "PreToolUse", reason: `unparseable payload: ${e.message}` }); }
|
|
46
|
-
|
|
47
|
-
if (p.tool_name !== "Skill") defer(`not a Skill call (${p.tool_name ?? "no tool_name"}) — out of scope`);
|
|
48
|
-
|
|
49
|
-
// The Skill tool's field names differ by surface: `skill_name`/`skill_args` in the hook payload,
|
|
50
|
-
// `skill`/`args` in the model-facing stream. Accept both — assuming one was already wrong once.
|
|
51
|
-
const skillRaw = p.tool_input?.skill_name ?? p.tool_input?.skill ?? "";
|
|
52
|
-
const args = String(p.tool_input?.skill_args ?? p.tool_input?.args ?? "");
|
|
53
|
-
|
|
54
|
-
// Plugin skills arrive namespaced, e.g. "shapeup-sdlc-plugin:tech-lead".
|
|
55
|
-
const skill = String(skillRaw).split(":").pop();
|
|
56
|
-
if (skill !== "tech-lead") defer(`Skill(${skill}) is not the orchestrator — out of scope`);
|
|
57
|
-
|
|
58
|
-
// The envelope port supplies its own intake; `harness verify envelope` owns that path.
|
|
59
|
-
if (/--order\b/.test(args)) defer("envelope dispatch — validate-envelope owns this path", "--order");
|
|
60
|
-
|
|
61
|
-
// Intake is satisfied by ANY of: a pitch path, a spec folder, or free requirement text.
|
|
62
|
-
const hasPitch = /--pitch\s+\S/.test(args);
|
|
63
|
-
const hasSpec = /--spec\s+\S/.test(args);
|
|
64
|
-
const hasResume = /--from\s+\S/.test(args); // resuming an existing run has its state on disk
|
|
65
|
-
|
|
66
|
-
// Free text = anything left once flags and their values are removed.
|
|
67
|
-
// Every flag that TAKES A VALUE must be listed here. A flag whose value is not stripped reads as
|
|
68
|
-
// free requirement text, and the gate then defers on an empty intake — the exact dispatch it
|
|
69
|
-
// exists to deny. This is a live failure mode, not a hypothetical: adding `--gate-answers` and
|
|
70
|
-
// `--wall-clock-budget` without listing them here silently blinded the gate, and the very next run
|
|
71
|
-
// reached tech-lead as `args:"--unattended --gate-answers ci --wall-clock-budget 2400"` — no
|
|
72
|
-
// requirement text at all — and was waved straight through, because "ci" and "2400" counted as
|
|
73
|
-
// the spec.
|
|
74
|
-
// Adding a valued flag anywhere in the harness means adding it here, and structural test §39
|
|
75
|
-
// enforces exactly that against commands/ship.md.
|
|
76
|
-
const VALUED_FLAGS = /--(pitch|spec|from|lens|rounds|attempts|parallel-scopes|orch-model|exec-model|eval-model|qa-model|feature|task|gate-answers|wall-clock-budget|slug|auto-level|max-rounds|intake-file|intake-text|spec-folder|cwd|out|by|preset|file|order|breadboard)\s+\S+/g;
|
|
77
|
-
const BARE_FLAGS = /--[a-z0-9-]+/g;
|
|
78
|
-
const freeText = args.replace(VALUED_FLAGS, " ").replace(BARE_FLAGS, " ").trim();
|
|
79
|
-
|
|
80
|
-
if (hasPitch || hasSpec || hasResume || freeText.length > 0) {
|
|
81
|
-
const via = hasPitch ? "--pitch" : hasSpec ? "--spec" : hasResume ? "--from" : "free requirement text";
|
|
82
|
-
defer(`intake resolvable via ${via} — inspected and permitted`, via);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Provably empty intake → deny, and say exactly how to fix it.
|
|
86
|
-
const reason = [
|
|
87
|
-
"✋ GATE L0.0 — NO INTAKE. tech-lead was dispatched with no pitch, no spec folder, and no",
|
|
88
|
-
"requirement text; only flags survived the hand-off (args: " + JSON.stringify(args.slice(0, 80)) + ").",
|
|
89
|
-
"",
|
|
90
|
-
"An orchestrator with no spec has nothing to orchestrate. Proceeding would print the gate list",
|
|
91
|
-
"and build nothing — output that reads like a successful run and contains no work.",
|
|
92
|
-
"",
|
|
93
|
-
"Re-dispatch with the requirement text or an on-disk spec:",
|
|
94
|
-
" Skill(tech-lead, \"<the full requirement text>\")",
|
|
95
|
-
" Skill(tech-lead, \"--pitch <shaping.md> --spec <spec/>\")",
|
|
96
|
-
].join("\n");
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
verdict: "deny", event: "PreToolUse", tool: "Skill", subject: "tech-lead", rule: "empty-intake",
|
|
100
|
-
reason: "no pitch, no spec folder, and no requirement text survived the hand-off",
|
|
101
|
-
payload: {
|
|
102
|
-
hookSpecificOutput: {
|
|
103
|
-
hookEventName: "PreToolUse",
|
|
104
|
-
permissionDecision: "deny",
|
|
105
|
-
permissionDecisionReason: reason,
|
|
106
|
-
},
|
|
107
|
-
},
|
|
108
|
-
};
|
|
109
|
-
});
|