@rune-kit/rune 2.18.1 → 2.21.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/README.md +31 -12
- package/compiler/__tests__/comprehension.test.js +916 -0
- package/compiler/__tests__/governance-collector.test.js +376 -0
- package/compiler/__tests__/setup.test.js +5 -0
- package/compiler/analytics.js +5 -0
- package/compiler/bin/rune.js +165 -1
- package/compiler/comprehension-client.js +2348 -0
- package/compiler/comprehension.js +1254 -0
- package/compiler/governance-collector.js +382 -0
- package/compiler/schemas/comprehension.schema.json +87 -0
- package/compiler/schemas/governance.schema.json +78 -0
- package/compiler/transforms/branding.js +1 -1
- package/hooks/context-watch/index.cjs +24 -13
- package/hooks/hooks.json +2 -2
- package/hooks/lib/context-key.cjs +37 -0
- package/hooks/metrics-collector/index.cjs +37 -8
- package/hooks/pre-tool-guard/index.cjs +44 -0
- package/hooks/session-start/index.cjs +4 -10
- package/package.json +1 -1
- package/skills/adversary/SKILL.md +36 -3
- package/skills/adversary/references/cross-model-escalation.md +85 -0
- package/skills/adversary/references/reasoning-modes.md +95 -0
- package/skills/autopsy/SKILL.md +41 -0
- package/skills/ba/SKILL.md +106 -27
- package/skills/ba/references/ears-format.md +91 -0
- package/skills/brainstorm/SKILL.md +32 -7
- package/skills/completion-gate/SKILL.md +21 -10
- package/skills/converge/SKILL.md +178 -0
- package/skills/converge/references/eval-fixtures.md +59 -0
- package/skills/cook/SKILL.md +41 -6
- package/skills/debug/SKILL.md +4 -2
- package/skills/deploy/SKILL.md +23 -2
- package/skills/deploy/references/observability.md +146 -0
- package/skills/design/SKILL.md +15 -1
- package/skills/graft/SKILL.md +24 -8
- package/skills/onboard/SKILL.md +45 -0
- package/skills/perf/SKILL.md +4 -1
- package/skills/plan/SKILL.md +70 -7
- package/skills/plan/references/boundary-artifacts.md +127 -0
- package/skills/plan/references/plan-templates.md +28 -9
- package/skills/plan/references/vertical-slice.md +8 -6
- package/skills/preflight/SKILL.md +9 -3
- package/skills/review/SKILL.md +4 -2
- package/skills/skill-router/SKILL.md +2 -0
- package/skills/test/SKILL.md +15 -8
- package/skills/verification/SKILL.md +39 -7
package/skills/graft/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: graft
|
|
|
3
3
|
description: "Clone, port, or convert features from any GitHub repo into your project. Use when stealing patterns from external repos or porting proven code. Understand before copy, challenge before implement. 4 modes: port (rewrite), compare (analysis), copy (transplant), improve (copy + optimize)."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.3.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: creation
|
|
@@ -25,9 +25,10 @@ When you clone a repo you see hundreds of files. **That tree is a menu — optio
|
|
|
25
25
|
- Read the README + the **2-5 files that implement the target feature**. Skip the rest.
|
|
26
26
|
- If you cannot name the specific files you need before reading, you do not know what you want yet — go back to Step 0 and narrow scope.
|
|
27
27
|
- `WebFetch` on raw GitHub URLs beats `git clone` whenever you know the exact files. Use clone only when discovery is genuinely needed.
|
|
28
|
-
- A graft that reads >10 source files is almost always a scoping failure, not a thorough one.
|
|
29
28
|
|
|
30
|
-
|
|
29
|
+
**Reading to understand is not grafting.** The discipline above caps the **graft scope** — the files you actually transplant, port, or improve into your codebase (2-5, hard-cap 10). It does NOT cap how many files you may *read to learn a pattern*. Studying a 24-skill library to extract one convention legitimately reads dozens of files but grafts almost none. Keep the two counts separate: a wide read with a narrow graft is thorough; a wide graft is the failure mode.
|
|
30
|
+
|
|
31
|
+
This menu discipline applies to the **transplant modes** (port, copy, improve). Copy mode is not an excuse to import a directory wholesale — you still select files deliberately. **Compare mode and survey scope (`--deep`)** are exempt from the read cap by design: their job is breadth of understanding, not transplant. They still must NOT import code wholesale — wide reading, narrow (or zero) graft.
|
|
31
32
|
|
|
32
33
|
<HARD-GATE>
|
|
33
34
|
Challenge gate (Step 4) MUST complete before adaptation planning (Step 5).
|
|
@@ -67,6 +68,17 @@ Copy the feature, then refactor and optimize. Fix anti-patterns, add missing tes
|
|
|
67
68
|
|
|
68
69
|
**`--fast` warning**: Skipping challenge gate means no license check, no quality assessment. User accepts full responsibility. Announce: "Fast mode: skipping challenge gate. You are responsible for license and quality review."
|
|
69
70
|
|
|
71
|
+
## Scope Depth
|
|
72
|
+
|
|
73
|
+
Orthogonal to mode and speed. Controls how widely you may read.
|
|
74
|
+
|
|
75
|
+
| Scope | Read budget | Graft scope | When |
|
|
76
|
+
|-------|-------------|-------------|------|
|
|
77
|
+
| (default) | 2-5 files, hard-cap 10 | the feature's files | Transplant one feature/module |
|
|
78
|
+
| `--deep` (survey) | unbounded reads, full clone OK | narrow — patterns extracted, not files copied | Study a whole repo/library to learn architecture or compare many components |
|
|
79
|
+
|
|
80
|
+
**`--deep` is for understanding, not importing.** Use it when the goal is "what can I learn from this repo" rather than "port this function." Pairs naturally with `compare` mode. It relaxes the read cap and the scope-guard warning — but the transplant discipline still holds: extract the *pattern*, then graft narrowly (often into multiple existing skills/files rather than copying source files 1:1).
|
|
81
|
+
|
|
70
82
|
## Smart Intent Detection
|
|
71
83
|
|
|
72
84
|
| Input Pattern | Detected Mode |
|
|
@@ -76,6 +88,7 @@ Copy the feature, then refactor and optimize. Fix anti-patterns, add missing tes
|
|
|
76
88
|
| Contains "improve", "better", "adapt", "upgrade" | improve |
|
|
77
89
|
| Contains "port", "convert", "rewrite", "migrate" | port |
|
|
78
90
|
| URL points to specific file/dir (not repo root) | Auto-scope to that path |
|
|
91
|
+
| Contains "survey", "study", "learn from", "what can I take", "deep dive" | compare + `--deep` |
|
|
79
92
|
| (default — no keyword match) | port |
|
|
80
93
|
|
|
81
94
|
## Triggers
|
|
@@ -140,9 +153,9 @@ For specific files or small repos: use `WebFetch` on raw GitHub URLs instead of
|
|
|
140
153
|
3. package.json / pyproject.toml / Cargo.toml — dependencies and stack
|
|
141
154
|
4. Tests for target feature — understand expected behavior
|
|
142
155
|
|
|
143
|
-
**Scope guard**: If target feature spans >15 files or >2000 LOC → WARN user: "Feature is large. Suggest narrowing to [specific module]. Continue anyway?"
|
|
156
|
+
**Scope guard**: If target feature spans >15 files or >2000 LOC → WARN user: "Feature is large. Suggest narrowing to [specific module]. Continue anyway?" (Suppressed under `--deep`/compare — breadth is the point there.)
|
|
144
157
|
|
|
145
|
-
**Menu discipline
|
|
158
|
+
**Menu discipline** (transplant modes): Before reading file #6, pause and ask "do I actually need this *to graft it*, or am I eating the menu?" If the answer isn't a concrete reason tied to the target feature, stop reading and move to Step 2. Under `--deep`/survey scope this gate is lifted — read as widely as understanding requires, but keep the graft scope narrow (Step 5).
|
|
146
159
|
|
|
147
160
|
### Step 2 — Analyze Source
|
|
148
161
|
|
|
@@ -204,6 +217,8 @@ Wait for user approval (unless `--auto`).
|
|
|
204
217
|
|
|
205
218
|
### Step 5 — Plan Adaptation
|
|
206
219
|
|
|
220
|
+
**Graft scope stays narrow regardless of how widely you read.** If this run used `--deep`/survey to study a library, the read cap was lifted — but the adaptation plan below still selects a small set of files/patterns to actually transplant. A wide survey legitimately feeds a `copy`/`improve` plan that grafts only the 2-5 best files; it does not license importing the surveyed tree.
|
|
221
|
+
|
|
207
222
|
Based on mode, produce adaptation plan:
|
|
208
223
|
|
|
209
224
|
**Compare mode** → skip to output. Write comparison report and STOP.
|
|
@@ -302,7 +317,7 @@ graft.complete:
|
|
|
302
317
|
5. MUST respect local conventions — grafted code should look native, not foreign
|
|
303
318
|
6. MUST NOT modify the source repository — read-only access only
|
|
304
319
|
7. MUST NOT graft without scoping — always narrow to specific feature/module
|
|
305
|
-
8. MUST treat the source file tree as a menu, not a meal —
|
|
320
|
+
8. MUST treat the source file tree as a menu, not a meal for **transplant** — graft the 2-5 files the feature actually needs, not every file you can see. Reading widely to understand (esp. under `--deep`/compare) is allowed; grafting widely is not
|
|
306
321
|
|
|
307
322
|
## Mesh Gates
|
|
308
323
|
|
|
@@ -319,7 +334,8 @@ graft.complete:
|
|
|
319
334
|
| Grafting GPL code into MIT project | CRITICAL | Challenge gate checks license — blocks incompatible |
|
|
320
335
|
| Blindly copying code without understanding | CRITICAL | HARD-GATE: challenge before implement |
|
|
321
336
|
| Context overflow from large source files | HIGH | Scope guard: >15 files or >2000 LOC triggers warning |
|
|
322
|
-
| Reading the whole repo instead of the feature | HIGH | "Tree is a menu" rule — pause before file #6, justify each read |
|
|
337
|
+
| Reading the whole repo instead of the feature | HIGH | "Tree is a menu" rule — pause before file #6, justify each read (transplant modes only) |
|
|
338
|
+
| Forcing a pattern-study graft into the 10-file feature cap | MEDIUM | Use `--deep`/survey scope — wide read, narrow graft; cap counts grafted files, not reads |
|
|
323
339
|
| Grafted code doesn't match local conventions | HIGH | Step 3 scans local patterns, Step 5 plans adaptation |
|
|
324
340
|
| Stale source (abandoned repo) | MEDIUM | Maintenance dimension in challenge gate |
|
|
325
341
|
| Private repo URL fails | MEDIUM | Fallback to WebFetch raw URLs or manual paste |
|
|
@@ -335,7 +351,7 @@ SELF-VALIDATION (run before emitting graft.complete):
|
|
|
335
351
|
- [ ] License compatibility confirmed (or user override documented)
|
|
336
352
|
- [ ] Temp clone directory cleaned up
|
|
337
353
|
- [ ] Grafted code compiles/lints without new errors
|
|
338
|
-
- [ ]
|
|
354
|
+
- [ ] **Graft scope** ≤10 files (files actually transplanted/ported/improved) — if >10, document why. This is NOT the read count: under `--deep`/compare you may read far more to understand, but the files you graft stay narrow.
|
|
339
355
|
IF ANY check fails → fix before reporting done. Do NOT defer to completion-gate.
|
|
340
356
|
```
|
|
341
357
|
|
package/skills/onboard/SKILL.md
CHANGED
|
@@ -306,6 +306,49 @@ Suggest switching to interview mode (but don't force it) when:
|
|
|
306
306
|
|
|
307
307
|
Output: `"ℹ️ This project is hard to auto-detect. Run /rune onboard --interview for guided setup."`
|
|
308
308
|
|
|
309
|
+
### Step 6f — Emit comprehension.json
|
|
310
|
+
|
|
311
|
+
Write `.rune/comprehension.json` conforming to `compiler/schemas/comprehension.schema.json`.
|
|
312
|
+
This is ADDITIVE — do not touch any of the Markdown files created above.
|
|
313
|
+
|
|
314
|
+
Populate from the scan data already collected in Steps 2–3:
|
|
315
|
+
|
|
316
|
+
```json
|
|
317
|
+
{
|
|
318
|
+
"project": "<project name from Step 2>",
|
|
319
|
+
"generated_at": "<ISO 8601 timestamp>",
|
|
320
|
+
"source": "onboard",
|
|
321
|
+
"health_score": null,
|
|
322
|
+
"layers": [
|
|
323
|
+
{ "id": "api", "name": "API / Routes", "color": "service" },
|
|
324
|
+
{ "id": "service", "name": "Business Logic", "color": "service" },
|
|
325
|
+
{ "id": "data", "name": "Data / Storage", "color": "data" },
|
|
326
|
+
{ "id": "ui", "name": "UI / Views", "color": "code" },
|
|
327
|
+
{ "id": "util", "name": "Utilities", "color": "code" }
|
|
328
|
+
],
|
|
329
|
+
"domains": [],
|
|
330
|
+
"modules": [
|
|
331
|
+
{
|
|
332
|
+
"id": "<relative file path or module id>",
|
|
333
|
+
"name": "<file or module name>",
|
|
334
|
+
"layer": "<id from layers — best-guess from file path>",
|
|
335
|
+
"type": "file",
|
|
336
|
+
"complexity": "simple",
|
|
337
|
+
"files": 1,
|
|
338
|
+
"summary": "<one-line description>"
|
|
339
|
+
}
|
|
340
|
+
],
|
|
341
|
+
"edges": []
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
Rules:
|
|
346
|
+
- `modules[]` — include only the entry points and config files read in Steps 1–3 (5–15 items max). Do not enumerate all project files.
|
|
347
|
+
- `layers[]` — include only layers actually detected; omit unused ones.
|
|
348
|
+
- `edges[]` — leave empty; onboard does not trace cross-file dependencies.
|
|
349
|
+
- `health_score` — set to null; health scoring requires autopsy.
|
|
350
|
+
- If `.rune/comprehension.json` already exists, overwrite it (generated output, not human-written).
|
|
351
|
+
|
|
309
352
|
### Step 7 — Commit
|
|
310
353
|
Use `Bash` to stage and commit the generated files:
|
|
311
354
|
```bash
|
|
@@ -413,6 +456,7 @@ Known failure modes for this skill. Check these before declaring done.
|
|
|
413
456
|
- .rune/ directory initialized with conventions, decisions, progress, session-log, instincts
|
|
414
457
|
- .rune/DEVELOPER-GUIDE.md written with setup commands from actual scan
|
|
415
458
|
- All generated commands verified to exist in package.json/Makefile/etc.
|
|
459
|
+
- .rune/comprehension.json written conforming to comprehension.schema.json (project, generated_at, source:"onboard", modules[], edges[])
|
|
416
460
|
- Onboard Report emitted with Generated + Skipped + Observations sections
|
|
417
461
|
|
|
418
462
|
## Returns
|
|
@@ -424,6 +468,7 @@ Known failure modes for this skill. Check these before declaring done.
|
|
|
424
468
|
| Decision log (initialized) | Markdown | `.rune/decisions.md` |
|
|
425
469
|
| Developer onboarding guide | Markdown | `.rune/DEVELOPER-GUIDE.md` |
|
|
426
470
|
| Session/progress files | Markdown | `.rune/progress.md`, `.rune/session-log.md` |
|
|
471
|
+
| Comprehension graph | JSON | `.rune/comprehension.json` |
|
|
427
472
|
|
|
428
473
|
## Cost Profile
|
|
429
474
|
|
package/skills/perf/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: perf
|
|
|
3
3
|
description: "Performance regression gate. Detects N+1 queries, sync-in-async, missing indexes, memory leaks, and bundle bloat before they reach production. Ranks findings by Cost Impact Hierarchy (architecture > data transfer > compute > DB > caching) so fix priority maps to actual unit-cost reduction."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.5.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: quality
|
|
@@ -43,6 +43,9 @@ Performance regression gate. Analyzes code changes for patterns that cause measu
|
|
|
43
43
|
|
|
44
44
|
- `references/cost-reference.md` — Cost priority hierarchy, quick wins checklist, instance right-sizing, data transfer traps, serverless optimization, observability cost control, managed vs self-hosted matrix, unit economics tracking. Load when cost analysis or FinOps context detected.
|
|
45
45
|
- `references/scalability-reference.md` — Bottleneck identification flow, performance thresholds, API patterns (cursor pagination, rate limiting, circuit breaker, graceful shutdown), caching strategies, queue-based load leveling, concurrency patterns, K8s HPA, CDN headers, load testing. Load when scaling or infrastructure optimization context detected.
|
|
46
|
+
- `../deploy/references/observability.md` — Instrumentation discipline (RED/USE metrics, percentiles-not-averages, cardinality bounds, structured logs, correlation IDs). Load when establishing the *measurement basis* for an optimization — you cannot optimize what you do not measure.
|
|
47
|
+
|
|
48
|
+
**Measure before optimizing.** A perf finding without a metric behind it is a guess. Before recommending a fix, confirm the hotpath actually emits the signal that proves it is slow: RED latency as a **histogram** (read p95/p99 — averages hide the slow tail), bounded label cardinality, and a correlation ID to tie a slow trace to its logs. If the instrumentation does not exist yet, that absence is itself a finding (`UNMEASURED_HOTPATH`). See `../deploy/references/observability.md` for the instrumentation contract.
|
|
46
49
|
|
|
47
50
|
## Executable Steps
|
|
48
51
|
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan
|
|
3
|
-
description: "Create structured implementation plans from requirements. Produces master plan + phase files for enterprise-scale project management. Master plan = overview (<80 lines). Phase files = execution detail (<
|
|
3
|
+
description: "Create structured implementation plans from requirements. Produces master plan + phase files for enterprise-scale project management. Master plan = overview (<80 lines). Phase files = execution detail (<200 lines each). Each session handles 1 phase. Uses opus for deep reasoning."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.7.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: opus
|
|
9
9
|
group: creation
|
|
@@ -16,7 +16,7 @@ metadata:
|
|
|
16
16
|
|
|
17
17
|
## Purpose
|
|
18
18
|
|
|
19
|
-
Strategic planning engine for the Rune ecosystem. Produces a **master plan + phase files** architecture — NOT a single monolithic plan. The master plan is a concise overview (<80 lines) that references separate phase files, each containing enough detail (<
|
|
19
|
+
Strategic planning engine for the Rune ecosystem. Produces a **master plan + phase files** architecture — NOT a single monolithic plan. The master plan is a concise overview (<80 lines) that references separate phase files, each containing enough detail (<200 lines) that ANY model can execute with high accuracy.
|
|
20
20
|
|
|
21
21
|
**Design principle: Plan for the weakest coder.** Phase files are designed so that even an Amateur-level model (Haiku) can execute them with minimal errors. When the plan satisfies the Amateur's needs, every model benefits — Junior (Sonnet) executes near-perfectly, Senior (Opus) executes flawlessly.
|
|
22
22
|
|
|
@@ -34,7 +34,7 @@ For trivial tasks (1-2 phases, < 5 files): inline plan is acceptable.
|
|
|
34
34
|
```
|
|
35
35
|
.rune/
|
|
36
36
|
plan-<feature>.md ← Master plan: phases overview, goals, status tracker (<80 lines)
|
|
37
|
-
plan-<feature>-phase1.md ← Phase 1 detail: tasks, acceptance criteria, files to touch (<
|
|
37
|
+
plan-<feature>-phase1.md ← Phase 1 detail: tasks, acceptance criteria, files to touch (<200 lines)
|
|
38
38
|
plan-<feature>-phase2.md ← Phase 2 detail
|
|
39
39
|
...
|
|
40
40
|
```
|
|
@@ -162,14 +162,35 @@ Phase files are SELF-CONTAINED execution instructions — designed for the weake
|
|
|
162
162
|
</HARD-GATE>
|
|
163
163
|
|
|
164
164
|
Phase decomposition rules:
|
|
165
|
-
- **Foundation first**: types, schemas, core engine
|
|
165
|
+
- **Foundation first**: types, schemas, core engine. A Foundational phase holds ONLY what 2+ stories share — it BLOCKS story phases but stays minimal
|
|
166
166
|
- **Dependencies before consumers**: create what's imported before the importer
|
|
167
|
+
- **Ordering law WITHIN each slice**: Data → Logic → Endpoints/Services → UI → Integration. UI is structurally LAST — a UI task whose slice has no upstream data/logic/endpoint task (and doesn't consume Foundational or a prior slice's contract) is an INVALID plan, not a style choice. The button and the endpoint it calls are one slice's tasks, never split across slices
|
|
167
168
|
- **Test alongside**: each phase includes its own test tasks
|
|
168
169
|
- **Max 5-7 tasks per phase**: if more, split the phase
|
|
169
170
|
- **Vertical slices over horizontal layers**: prefer "auth end-to-end" over "all models → all APIs → all UI" (see `references/vertical-slice.md` for tracer-bullet template, AFK/HITL labels, granularity rules)
|
|
171
|
+
- **Story-grouped backbone from BA**: if `.rune/features/<name>/tasks.md` exists, its `## US-n` sections map to slices — refine them, do NOT flatten back into layer groups
|
|
170
172
|
|
|
171
173
|
Tasks within each phase MUST be organized into waves (parallel-safe groupings). See `references/wave-planning.md`.
|
|
172
174
|
|
|
175
|
+
### Step 3.7 — Boundary Artifacts (Contracts-First)
|
|
176
|
+
<MUST-READ path="references/boundary-artifacts.md" trigger="when the feature crosses a UI↔data boundary — templates for data-model.md, contracts/, quickstart.md"/>
|
|
177
|
+
|
|
178
|
+
**Detect the boundary**: requirements.md has a `## Key Entities` section AND any user story renders a UI surface (page/screen/form/component) — OR the task description implies user interaction with persisted data (submit, save, login, search, checkout).
|
|
179
|
+
|
|
180
|
+
**If the boundary exists, plan MUST emit — BEFORE writing phase files:**
|
|
181
|
+
|
|
182
|
+
| Artifact | Location | Content |
|
|
183
|
+
|----------|----------|---------|
|
|
184
|
+
| `data-model.md` | `.rune/features/<name>/` | Key Entities expanded: fields, types, validation rules, state transitions |
|
|
185
|
+
| `contracts/` | `.rune/features/<name>/contracts/` | One file per interface: endpoint/function, request/response shape, error cases — each mapped to the `US-n` it serves |
|
|
186
|
+
| `quickstart.md` | `.rune/features/<name>/` | Runnable end-to-end validation: prerequisites, setup commands, per-story Independent Test steps, expected outcomes |
|
|
187
|
+
|
|
188
|
+
Rules:
|
|
189
|
+
- Tasks are then DERIVED from contracts: every contract file → ≥1 implementation task + ≥1 test task inside the story it serves. A UI task referencing no contract (and no prior slice's contract) is orphaned — fix the plan
|
|
190
|
+
- A story that touches data but maps to no entity in data-model.md = spec gap → bounce to `ba` (Upstream Inconsistency)
|
|
191
|
+
- quickstart.md is the feature's executable end-to-end validation — write commands that actually run, not prose. Task derivation adds a "run quickstart validation" task to the final phase, so the plan itself guarantees it gets executed
|
|
192
|
+
- **Skip** when no boundary: pure-UI features (styling, layout), pure-backend (cron, migration), libraries. Announce the skip: "No UI↔data boundary — skipping boundary artifacts"
|
|
193
|
+
|
|
173
194
|
### Step 4 — Write Master Plan File
|
|
174
195
|
<MUST-READ path="references/plan-templates.md" trigger="when writing the master plan file"/>
|
|
175
196
|
|
|
@@ -208,9 +229,35 @@ Performance Constraints section is optional (only when NFRs apply).
|
|
|
208
229
|
|
|
209
230
|
When presenting alternatives (from brainstorm or Step 3), rate each **Completeness X/10**. Always recommend the higher-completeness option — with AI, the marginal cost of completeness is near-zero.
|
|
210
231
|
|
|
232
|
+
### Step 5.7 — Coverage Gate (after phase files, before presenting)
|
|
233
|
+
|
|
234
|
+
**Task ID scheme**: every task in a phase file carries the ID `P<phase>-T<seq>` — phase number + sequential position within that phase (`P2-T3` = phase 2, task 3). Phase file task labels use this ID (see `references/plan-templates.md`). Coverage Summary, Traceability Matrix, and Change Stacking `depends_on` all reference tasks by this ID.
|
|
235
|
+
|
|
236
|
+
When BA requirements exist, build the **Coverage Summary** — every `FR-n` and `US-n` mapped to the task IDs that implement it:
|
|
237
|
+
|
|
238
|
+
```markdown
|
|
239
|
+
## Coverage Summary
|
|
240
|
+
| Key | Priority | Tasks | Covered |
|
|
241
|
+
|-----|----------|-------|---------|
|
|
242
|
+
| US-1 | P1 | P1-T2, P1-T3, P2-T1 | ✅ |
|
|
243
|
+
| FR-3 | — | P2-T4 | ✅ |
|
|
244
|
+
| US-3 | P2 | — | ❌ deferred to v2 (explicit) |
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
<HARD-GATE>
|
|
248
|
+
A P1 story or its FRs with ZERO tasks = the plan is INCOMPLETE — do NOT present it for approval. Fix the plan first.
|
|
249
|
+
P2/P3 zero-coverage is allowed ONLY with an explicit deferral line in the master plan ("US-3 deferred to v2 — user-visible in Coverage Summary"), never silently.
|
|
250
|
+
</HARD-GATE>
|
|
251
|
+
|
|
252
|
+
**Sequencing note**: task IDs exist only AFTER Step 5 writes the phase files — so this step runs after Step 5, and you MUST go back and `Edit` the already-written master plan file (`.rune/plan-<feature>.md`) to insert the `## Coverage Summary` section (before `## Architecture`). Present the UPDATED master plan at Step 6. A master plan presented without its Coverage Summary is a Step 5.7 violation, not an oversight.
|
|
253
|
+
|
|
254
|
+
**Size spillover**: if the table exceeds ~15 rows, write the full table to `.rune/plan-<feature>-coverage.md` instead, and put a one-line pointer + the ❌/deferred rows only in the master plan (the 80-line cap stays intact; zero-coverage rows are never hidden in the spillover file).
|
|
255
|
+
|
|
256
|
+
Skip when no requirements.md exists (ad-hoc tasks).
|
|
257
|
+
|
|
211
258
|
### Step 6 — Present and Get Approval
|
|
212
259
|
|
|
213
|
-
Present the **master plan** to user (NOT all phase files). User reviews: phase breakdown, key decisions, risks, completeness scores
|
|
260
|
+
Present the **master plan** to user (NOT all phase files). User reviews: phase breakdown, key decisions, risks, completeness scores, **coverage summary**. Wait for explicit approval ("go", "proceed", "yes") before writing phase files.
|
|
214
261
|
|
|
215
262
|
### Step 6.5 — Update Feature Map (Always)
|
|
216
263
|
<MUST-READ path="references/feature-map.md" trigger="every plan invocation"/>
|
|
@@ -330,6 +377,9 @@ When producing phase files with wave-based task grouping, every task MUST declar
|
|
|
330
377
|
12. MUST include rejection criteria — explicit "DO NOT" anti-patterns to prevent common mistakes
|
|
331
378
|
13. MUST include cross-phase context — what's assumed from prior phases, what's exported for future
|
|
332
379
|
14. MUST update `.rune/features.md` after every non-trivial plan — feature map is a living artifact
|
|
380
|
+
15. MUST emit boundary artifacts (data-model.md, contracts/, quickstart.md) when the feature crosses a UI↔data boundary — tasks derive from contracts, not the reverse
|
|
381
|
+
16. MUST order layers within each slice Data → Logic → Endpoint → UI — a UI task with no upstream chain in its slice is an invalid plan
|
|
382
|
+
17. MUST NOT present a plan where a P1 story has zero task coverage — Coverage Summary is part of the master plan
|
|
333
383
|
|
|
334
384
|
## Returns
|
|
335
385
|
|
|
@@ -338,6 +388,9 @@ When producing phase files with wave-based task grouping, every task MUST declar
|
|
|
338
388
|
| Master plan | Markdown | `.rune/plan-<feature>.md` |
|
|
339
389
|
| Phase files | Markdown | `.rune/plan-<feature>-phase<N>.md` (one per phase) |
|
|
340
390
|
| Feature spec | Markdown | `.rune/features/<name>/spec.md` (Feature Spec Mode only) |
|
|
391
|
+
| Data model | Markdown | `.rune/features/<name>/data-model.md` (Step 3.7 — UI↔data boundary only) |
|
|
392
|
+
| Interface contracts | Markdown (one per interface) | `.rune/features/<name>/contracts/` (Step 3.7) |
|
|
393
|
+
| Quickstart validation | Markdown (executable steps) | `.rune/features/<name>/quickstart.md` (Step 3.7) |
|
|
341
394
|
| Roadmap | Markdown | `.rune/roadmap.md` (Roadmap Mode only) |
|
|
342
395
|
| Feature map | Markdown | `.rune/features.md` (auto-maintained) |
|
|
343
396
|
| Inline plan | Markdown (inline) | Emitted directly for trivial tasks |
|
|
@@ -349,7 +402,7 @@ Append to plan output when invoked standalone. Suppress when called as sub-skill
|
|
|
349
402
|
```yaml
|
|
350
403
|
chain_metadata:
|
|
351
404
|
skill: "rune:plan"
|
|
352
|
-
version: "1.
|
|
405
|
+
version: "1.7.0"
|
|
353
406
|
status: "[DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED]"
|
|
354
407
|
domain: "[area planned]"
|
|
355
408
|
files_changed:
|
|
@@ -401,6 +454,11 @@ chain_metadata:
|
|
|
401
454
|
| Missing dependency between tasks that share artifacts | HIGH | Every task declares `provides[]` and `requires[]` — cycle detection + missing dep check before dispatch |
|
|
402
455
|
| New feature planned without checking existing feature map | HIGH | Step 1 reads `.rune/features.md` — catches overlaps, conflicts, and missing dependencies before planning begins |
|
|
403
456
|
| Feature map never created — gaps accumulate silently | MEDIUM | Step 6.5 always runs (create or update) — feature map grows organically with each plan invocation |
|
|
457
|
+
| UI task planned with no endpoint/contract behind it (dead button at plan time) | CRITICAL | Step 3.7: contracts/ emitted before phase files; every UI task cites its contract; ordering law makes UI structurally last in its slice |
|
|
458
|
+
| P1 story silently missing from tasks (frontend-only plan) | CRITICAL | Step 5.7 Coverage Gate: P1 zero-coverage = plan not presentable; Coverage Summary visible in master plan at approval |
|
|
459
|
+
| Boundary artifacts skipped because "the feature is simple" | HIGH | Detection is mechanical (Key Entities + UI surface), not judgment. Skips are announced, never silent |
|
|
460
|
+
| quickstart.md written as prose instead of runnable commands | MEDIUM | Every step needs an **Expect** with observable outcome — cook executes this file at VERIFY |
|
|
461
|
+
| BA's story-grouped tasks.md flattened back into layer groups | HIGH | Step 3 rule: `## US-n` sections map to slices — refine, don't flatten |
|
|
404
462
|
|
|
405
463
|
## Self-Validation
|
|
406
464
|
|
|
@@ -412,6 +470,9 @@ SELF-VALIDATION (run before presenting plan to user):
|
|
|
412
470
|
- [ ] Phase files have ALL Amateur-Proof sections (data flow, code contracts, failure scenarios, rejection criteria)
|
|
413
471
|
- [ ] Locked decisions from BA are reflected in plan — none contradicted or ignored
|
|
414
472
|
- [ ] Every BA requirement has a corresponding Req ID in at least one phase's Traceability Matrix
|
|
473
|
+
- [ ] Coverage Summary built (Step 5.7) — no P1 story/FR with zero tasks; P2/P3 gaps have explicit deferral lines
|
|
474
|
+
- [ ] Boundary artifacts emitted if UI↔data boundary detected — every contract has a consumer, every UI task cites its contract (or justifies Contract: none)
|
|
475
|
+
- [ ] Layer order within every slice: no UI task precedes its slice's data/logic/endpoint tasks
|
|
415
476
|
- [ ] `.rune/features.md` updated with current feature (or created if first run)
|
|
416
477
|
- [ ] No cross-feature conflicts detected (or flagged to user if found)
|
|
417
478
|
```
|
|
@@ -427,6 +488,8 @@ SELF-VALIDATION (run before presenting plan to user):
|
|
|
427
488
|
- Failure scenarios table, rejection criteria (DO NOTs)
|
|
428
489
|
- Cross-phase context (assumes/exports), acceptance criteria
|
|
429
490
|
- Every code-producing phase has test tasks
|
|
491
|
+
- Boundary artifacts emitted (data-model.md + contracts/ + quickstart.md) when UI↔data boundary detected — or skip announced
|
|
492
|
+
- Coverage Summary in master plan — every P1 story/FR covered, P2/P3 gaps explicitly deferred
|
|
430
493
|
- Master plan presented to user with "Awaiting Approval"
|
|
431
494
|
- User has explicitly approved
|
|
432
495
|
- Self-Validation: all checks passed
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Boundary Artifacts (Contracts-First)
|
|
2
|
+
|
|
3
|
+
> Reference for `plan` skill — Step 3.7.
|
|
4
|
+
> Load when the feature crosses a UI↔data boundary.
|
|
5
|
+
|
|
6
|
+
The single most common incomplete-implementation failure is a UI element wired to nothing —
|
|
7
|
+
the button renders, the endpoint doesn't exist. Boundary artifacts make the interface surface
|
|
8
|
+
a REVIEWABLE ARTIFACT at plan time, so a missing backend is visible before any code is written.
|
|
9
|
+
|
|
10
|
+
## Detection
|
|
11
|
+
|
|
12
|
+
Emit boundary artifacts when BOTH are true:
|
|
13
|
+
1. `requirements.md` has a `## Key Entities` section (feature involves data)
|
|
14
|
+
2. Any user story renders a UI surface — page, screen, form, component — OR the task
|
|
15
|
+
implies user interaction with persisted data (submit, save, login, search, checkout)
|
|
16
|
+
|
|
17
|
+
Skip (and announce the skip) for: pure-UI features (styling, layout, static content),
|
|
18
|
+
pure-backend (cron jobs, migrations, CLI), libraries with no UI.
|
|
19
|
+
|
|
20
|
+
## Artifact 1: data-model.md
|
|
21
|
+
|
|
22
|
+
Save to `.rune/features/<name>/data-model.md`. Expand each Key Entity from the spec:
|
|
23
|
+
|
|
24
|
+
```markdown
|
|
25
|
+
# Data Model: [Feature Name]
|
|
26
|
+
|
|
27
|
+
## Order
|
|
28
|
+
| Field | Type | Validation | Notes |
|
|
29
|
+
|-------|------|-----------|-------|
|
|
30
|
+
| id | uuid | generated | PK |
|
|
31
|
+
| userId | uuid | must reference existing User | FK → User |
|
|
32
|
+
| status | enum | draft \| submitted \| fulfilled | state machine below |
|
|
33
|
+
| items | OrderItem[] | min 1 item | |
|
|
34
|
+
|
|
35
|
+
**State transitions**: draft → submitted (on user submit, validates items) → fulfilled
|
|
36
|
+
(on admin action). No transition skips submitted. Invalid transition = 409.
|
|
37
|
+
|
|
38
|
+
**Relationships**: User 1—N Order. Order 1—N OrderItem.
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Rules: every entity from the spec's Key Entities appears here. Every state named in the
|
|
42
|
+
spec has an explicit transition trigger. Validation rules come from AC error cases.
|
|
43
|
+
|
|
44
|
+
## Artifact 2: contracts/
|
|
45
|
+
|
|
46
|
+
Save one file per interface to `.rune/features/<name>/contracts/`. Filename: `<verb>-<resource>.md`
|
|
47
|
+
(e.g., `create-order.md`, `list-orders.md`).
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
# Contract: POST /api/orders
|
|
51
|
+
|
|
52
|
+
**Serves**: US-1 (AC-1.1, AC-1.2)
|
|
53
|
+
|
|
54
|
+
## Request
|
|
55
|
+
```json
|
|
56
|
+
{ "items": [{ "productId": "uuid", "quantity": 1 }] }
|
|
57
|
+
```
|
|
58
|
+
Validation: items non-empty; quantity ≥ 1; productId exists.
|
|
59
|
+
|
|
60
|
+
## Response 201
|
|
61
|
+
```json
|
|
62
|
+
{ "id": "uuid", "status": "submitted", "items": [...] }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Errors
|
|
66
|
+
| Case | Status | Body |
|
|
67
|
+
|------|--------|------|
|
|
68
|
+
| empty items (AC-1.2) | 422 | `{ "error": "items must not be empty" }` |
|
|
69
|
+
| unknown productId | 404 | `{ "error": "product not found" }` |
|
|
70
|
+
| unauthenticated | 401 | — |
|
|
71
|
+
|
|
72
|
+
## Consumers
|
|
73
|
+
- `OrderForm` component (US-1 UI task) — submit handler calls this endpoint
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Rules:
|
|
77
|
+
- Every contract names the `US-n` it serves and the AC cases its errors cover
|
|
78
|
+
- Every contract names its **Consumers** — the UI component or caller that will invoke it.
|
|
79
|
+
A contract with no consumer, or a UI task with no contract, is an orphan → fix the plan
|
|
80
|
+
- Non-HTTP interfaces (IPC, function boundary, event) use the same shape: input, output, errors, consumers
|
|
81
|
+
|
|
82
|
+
## Artifact 3: quickstart.md
|
|
83
|
+
|
|
84
|
+
Save to `.rune/features/<name>/quickstart.md`. This is EXECUTABLE, not prose — the
|
|
85
|
+
final phase carries a "run quickstart validation" task (see Task derivation below),
|
|
86
|
+
and `converge` traces each story's acceptance scenarios against these steps, so the
|
|
87
|
+
feature cannot be declared done without them passing.
|
|
88
|
+
|
|
89
|
+
```markdown
|
|
90
|
+
# Quickstart: [Feature Name]
|
|
91
|
+
|
|
92
|
+
## Prerequisites
|
|
93
|
+
- `npm install` done, DB running (`docker compose up -d db`)
|
|
94
|
+
- Migrations applied: `npm run db:migrate`
|
|
95
|
+
|
|
96
|
+
## Validate US-1 (P1): submit an order
|
|
97
|
+
1. `npm run dev`
|
|
98
|
+
2. `curl -s -X POST localhost:3000/api/orders -H 'content-type: application/json' \
|
|
99
|
+
-d '{"items":[{"productId":"<seed-id>","quantity":1}]}'`
|
|
100
|
+
**Expect**: 201, body contains `"status":"submitted"`
|
|
101
|
+
3. `curl -s localhost:3000/api/orders` — **Expect**: list contains the new order
|
|
102
|
+
4. UI path: open /orders/new → add item → Submit → **Expect**: redirect to /orders,
|
|
103
|
+
new order visible in list
|
|
104
|
+
|
|
105
|
+
## Validate US-1 error path (AC-1.2)
|
|
106
|
+
1. Submit with empty items → **Expect**: 422, form shows "items must not be empty"
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Rules:
|
|
110
|
+
- One validation block per P1 story (P2/P3 optional), derived from the story's Independent Test
|
|
111
|
+
- Every step has an **Expect** with an observable outcome — status code, body content, visible UI state
|
|
112
|
+
- Commands must actually run in the project's environment; if the env can't run them
|
|
113
|
+
(no browser, no DB), say so in Prerequisites and give the closest executable check
|
|
114
|
+
|
|
115
|
+
## Task derivation
|
|
116
|
+
|
|
117
|
+
After emitting the three artifacts, derive tasks:
|
|
118
|
+
|
|
119
|
+
| Source | Derived tasks |
|
|
120
|
+
|--------|---------------|
|
|
121
|
+
| Each entity in data-model.md | 1 schema/model task (in Foundational if shared by 2+ stories, else in its story) |
|
|
122
|
+
| Each contract file | 1 contract test task + 1 implementation task, inside the story it serves, BEFORE that story's UI task |
|
|
123
|
+
| Each contract's Consumers line | the UI task's Logic field references the contract file |
|
|
124
|
+
| quickstart.md | 1 "run quickstart validation" task in the final phase |
|
|
125
|
+
|
|
126
|
+
Cross-check before Coverage Gate (Step 5.7): every contract implemented, every consumer wired,
|
|
127
|
+
every quickstart block runnable. An unimplemented contract = the dead button, caught at plan time.
|
|
@@ -29,6 +29,16 @@ Save to `.rune/plan-<feature>.md`. Max 80 lines.
|
|
|
29
29
|
- Discretion (agent): [list — agent chose X because Y]
|
|
30
30
|
- Deferred: [list — explicitly excluded from this feature]
|
|
31
31
|
|
|
32
|
+
## Coverage Summary
|
|
33
|
+
<!-- Step 5.7 — only when BA requirements exist. P1 zero-coverage = plan not presentable.
|
|
34
|
+
Inserted AFTER phase files exist (task IDs come from them). If >15 rows, move the full
|
|
35
|
+
table to .rune/plan-<feature>-coverage.md and keep only a pointer + ❌/deferred rows here. -->
|
|
36
|
+
| Key | Priority | Tasks | Covered |
|
|
37
|
+
|-----|----------|-------|---------|
|
|
38
|
+
| US-1 | P1 | P1-T2, P1-T3 | ✅ |
|
|
39
|
+
| FR-3 | — | P2-T4 | ✅ |
|
|
40
|
+
| US-3 | P2 | — | ❌ deferred to v2 (explicit) |
|
|
41
|
+
|
|
32
42
|
## Architecture
|
|
33
43
|
<brief system diagram or component list — NOT implementation detail>
|
|
34
44
|
|
|
@@ -89,23 +99,32 @@ function validateInput(raw: unknown): TradeEntry[]; // throws ValidationError
|
|
|
89
99
|
|
|
90
100
|
Each task MUST include: **File** (exact path), **Test** (test file or N/A), **Verify** (shell command), **Commit** (semantic message). Granularity: 2-5 min per task. If >10min, decompose.
|
|
91
101
|
|
|
92
|
-
|
|
93
|
-
|
|
102
|
+
**Task IDs**: label every task `P<phase>-T<seq>` (phase number + position within phase). Coverage Summary, Traceability Matrix, and `depends_on` reference these IDs.
|
|
103
|
+
|
|
104
|
+
**Req IDs**: when BA produced `FR-n`/`US-n` IDs, use THOSE IDs in the Req field and Traceability Matrix — do NOT renumber as REQ-n. The `REQ-n` format is only for ad-hoc plans with no BA spec.
|
|
105
|
+
|
|
106
|
+
When BA requirements exist, each task also carries **Story** (`US-n` it serves) — and UI tasks carry **Contract** (the `contracts/` file whose endpoint the UI invokes; see `references/boundary-artifacts.md`). A UI task with `Contract: none` MUST justify why (static UI, consumes prior slice's contract).
|
|
107
|
+
|
|
108
|
+
- [ ] P2-T1 — Create calculateProfit function
|
|
109
|
+
- Req: FR-1 (P&L calculation)
|
|
110
|
+
- Story: US-1
|
|
94
111
|
- File: `src/foo/bar.ts` (new)
|
|
95
112
|
- Test: `tests/foo/bar.test.ts` (new)
|
|
96
113
|
- Verify: `npm test -- --grep "calculateProfit"`
|
|
97
114
|
- Commit: `feat(trading): add calculateProfit with fee calculation`
|
|
98
115
|
- Logic: sum entries by side, apply fees (0.1% per trade), return net P&L
|
|
99
116
|
- Edge: empty array → return { netPnL: 0, totalFees: 0, winRate: 0 }
|
|
100
|
-
- [ ]
|
|
101
|
-
- Req:
|
|
117
|
+
- [ ] P2-T2 — Add input validation
|
|
118
|
+
- Req: FR-2 (input validation)
|
|
119
|
+
- Story: US-1
|
|
102
120
|
- File: `src/foo/baz.ts` (modify)
|
|
103
121
|
- Test: `tests/foo/baz.test.ts` (new)
|
|
104
122
|
- Verify: `npm test -- --grep "validateInput"`
|
|
105
123
|
- Commit: `feat(trading): add input validation for trade entries`
|
|
106
124
|
- Logic: check side is 'long'|'short', prices > 0, quantity > 0
|
|
107
|
-
- [ ]
|
|
108
|
-
- Req:
|
|
125
|
+
- [ ] P2-T3 — Write integration tests
|
|
126
|
+
- Req: FR-1, FR-2 (integration coverage)
|
|
127
|
+
- Story: US-1
|
|
109
128
|
- File: `tests/foo/bar.test.ts` (modify)
|
|
110
129
|
- Test: N/A — this IS the test task
|
|
111
130
|
- Verify: `npm test -- --grep "trading" && npx tsc --noEmit`
|
|
@@ -157,10 +176,10 @@ Each task MUST include: **File** (exact path), **Test** (test file or N/A), **Ve
|
|
|
157
176
|
## Traceability Matrix
|
|
158
177
|
| Req ID | Requirement | Task(s) | Test(s) | Status |
|
|
159
178
|
|--------|-------------|---------|---------|--------|
|
|
160
|
-
|
|
|
161
|
-
|
|
|
179
|
+
| FR-1 | P&L calculation with fees | P2-T1 | `tests/foo/bar.test.ts` | ⬚ |
|
|
180
|
+
| FR-2 | Input validation | P2-T2 | `tests/foo/baz.test.ts` | ⬚ |
|
|
162
181
|
|
|
163
|
-
Every requirement from BA's Requirements Document MUST appear in this matrix. Missing requirement = incomplete phase. `completion-gate` checks this matrix during verification.
|
|
182
|
+
Every requirement from BA's Requirements Document MUST appear in this matrix, using BA's own IDs (`FR-n`/`US-n` — REQ-n only when no BA spec exists). Missing requirement = incomplete phase. `completion-gate` checks this matrix during verification.
|
|
164
183
|
|
|
165
184
|
## Files Touched
|
|
166
185
|
- `src/foo/bar.ts` — new
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
2. **Demoable on its own** — when the slice is merged, you can demo it (or run a single command to verify). If demoing requires "and now switch to the other PR", the slices were drawn wrong.
|
|
11
11
|
3. **Narrow but complete** — one user story, one happy path, minimal error handling. Edge cases are *separate slices*, not bigger versions of the same slice.
|
|
12
12
|
4. **Independently grabbable** — any developer or agent should be able to pick up Slice N without reading Slice N+1. Dependencies declared explicitly, not implicit.
|
|
13
|
+
5. **Layer order WITHIN the slice: Data → Logic → Endpoint/Service → UI → Integration.** UI is structurally last. The button and the endpoint it calls are ONE slice's tasks — a slice whose UI task has no upstream endpoint task (and consumes no prior slice's contract) ships a dead button. If the slice has a contract file (`references/boundary-artifacts.md`), the contract test task precedes the implementation task.
|
|
13
14
|
|
|
14
15
|
## Slice types
|
|
15
16
|
|
|
@@ -25,13 +26,14 @@
|
|
|
25
26
|
```markdown
|
|
26
27
|
### Slice: [verb-led title]
|
|
27
28
|
- **Type**: AFK | HITL
|
|
28
|
-
- **Story**: As a [persona], I want to [action] so that [benefit]
|
|
29
|
-
- **Path through layers
|
|
29
|
+
- **Story**: US-n — As a [persona], I want to [action] so that [benefit]
|
|
30
|
+
- **Path through layers** (this is also the BUILD ORDER — top to bottom):
|
|
30
31
|
- Schema: [migration / type addition]
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
-
|
|
32
|
+
- Logic: [business rule / validation]
|
|
33
|
+
- API: [endpoint or function signature — cite `contracts/<file>.md` if one exists]
|
|
34
|
+
- UI: [component or surface — names the API line above as its call target]
|
|
35
|
+
- Test: [verification approach — must cross UI→API, not mock the whole chain]
|
|
36
|
+
- **Demoable**: [exact command or click-path that shows it works — reuse the story's Independent Test]
|
|
35
37
|
- **Blocked by**: [slice IDs] | None — can start immediately
|
|
36
38
|
- **Out of scope** (explicit): [what this slice does NOT cover]
|
|
37
39
|
```
|
|
@@ -3,7 +3,7 @@ name: preflight
|
|
|
3
3
|
description: "Pre-commit quality gate that catches 'almost right' code. Use when about to commit — auto-fires before commit to validate logic correctness, error handling, regressions, and completeness. Goes beyond linting."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.2.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: quality
|
|
@@ -150,6 +150,7 @@ Verify that new code ships complete:
|
|
|
150
150
|
- New feature → has at least one test file
|
|
151
151
|
- New configuration option → has documentation (inline comment or docs file)
|
|
152
152
|
- New database query → has corresponding migration file if schema changed
|
|
153
|
+
- **Cross-layer pairing**: new interactive component (button/form/action) → its handler chain reaches a REAL endpoint/service that exists in the codebase — OR the plan explicitly scopes it UI-only with a mock (stated, not assumed). Unexcused missing pair = **BLOCK**, not WARN: a dead interactive element is incomplete work presented as complete. (Mirror check: new endpoint this diff → ≥1 consumer or a NAMED future task consuming it)
|
|
153
154
|
|
|
154
155
|
**Framework-specific completeness (apply only if detected):**
|
|
155
156
|
- React component with async data → must have `loading` state AND `error` state
|
|
@@ -238,6 +239,7 @@ When UI/Frontend hook is triggered, run these checks on all `.tsx`/`.jsx`/`.svel
|
|
|
238
239
|
| **Scale Minimum — hero display** | `<h1>` with `text-3xl` or smaller (30px) when the heading is in a hero/landing section | WARN: "Hero heading below 48px at {file}:{line} — insufficient visual hierarchy" |
|
|
239
240
|
| **Hand-rolled SVG for standard icons** | Inline `<svg viewBox=` in JSX when the surrounding comment/class names indicate standard iconography (dashboard, menu, close, chevron, arrow, search, home, user, settings, bell, trash) | WARN: "Hand-rolled SVG at {file}:{line} — use @phosphor-icons/react or huge-icons, or ship boxed placeholder" |
|
|
240
241
|
| **Manual hex accent shading** | CSS/Tailwind config defining 2+ sibling `--accent-hover` / `--accent-pressed` / `--accent-active` with hex literals (no `oklch(from ...)` or design-token chain) | WARN: "Manual hex shade at {file}:{line} — derive via oklch(from var(--accent) calc(l - 0.08) c h)" |
|
|
242
|
+
| **Dead interactive element** | `<button>`/`<form>`/action element with no bound handler (any framework syntax: `onClick=`, `on:click=`, `@click`, `v-on:`), `onClick={() => {}}`, `href="#"` on an action link (not navigation/scroll anchors), or `preventDefault()`-only submit — in files of THIS diff (skip elements listed in `.rune/ui-spec.md` `## Unwired Elements`; prop-origin handlers like `onClick={props.onSave}` count as bound) | BLOCK: "Dead interactive at {file}:{line} — element renders but does nothing" |
|
|
241
243
|
| **Missing states** | Components fetching data without loading/error/empty states | WARN: "Async component at {file} missing [loading|error|empty] state" |
|
|
242
244
|
| **Icon accessibility** | Decorative icons without `aria-hidden="true"`, functional icons without `aria-label` | WARN: "Icon at {file}:{line} missing aria attribute" |
|
|
243
245
|
| **Inline styles** | `style={{` or `style=` attribute usage instead of classes/tokens | WARN: "Inline style at {file}:{line} — use CSS class or Tailwind" |
|
|
@@ -336,8 +338,8 @@ Invoke `rune:sentinel` on the changed files. Attach sentinel's output verbatim u
|
|
|
336
338
|
|
|
337
339
|
### Step 6 — Generate Verdict
|
|
338
340
|
Aggregate all findings:
|
|
339
|
-
- Any BLOCK from sentinel OR a logic issue that would cause data corruption or security bypass → overall **BLOCK**
|
|
340
|
-
- Any missing error handling, regression risk with no tests, or incomplete feature → **WARN**
|
|
341
|
+
- Any BLOCK from sentinel OR a logic issue that would cause data corruption or security bypass OR a dead interactive element (Step 4 cross-layer pairing / Step 4.5 dead-interactive check) OR a BLOCK from any domain hook → overall **BLOCK**
|
|
342
|
+
- Any missing error handling, regression risk with no tests, or incomplete feature (other than the BLOCK cases above) → **WARN**
|
|
341
343
|
- Only style or best-practice suggestions → **PASS**
|
|
342
344
|
|
|
343
345
|
Report PASS, WARN, or BLOCK. For WARN, list each item the developer must acknowledge. For BLOCK, list each item that must be fixed before proceeding.
|
|
@@ -410,6 +412,8 @@ WARN — 3 issues found (0 blocking, 3 must-acknowledge). Resolve before commit
|
|
|
410
412
|
| Domain hooks not triggered when pack is installed | HIGH | Step 4.5 auto-detects file patterns — if pack is installed but hooks don't fire, check file pattern matching |
|
|
411
413
|
| Domain hooks overriding generic checks | HIGH | HARD-GATE: domain hooks are ADDITIVE — they never replace Steps 1-4 |
|
|
412
414
|
| Pack Hard-Stop Thresholds ignored in preflight | MEDIUM | Step 4.5 Pack Integration must read installed pack thresholds — test with each new pack |
|
|
415
|
+
| Dead interactive element downgraded to WARN ("just a loading-state issue") | CRITICAL | Step 4 cross-layer pairing + Step 4.5 dead-interactive check are BLOCK — a button wired to nothing is incomplete work, not a style nit |
|
|
416
|
+
| Flagging design's declared placeholders as dead interactives | MEDIUM | Elements listed in `.rune/ui-spec.md` `## Unwired Elements` are design debt tracked by converge — skip, don't BLOCK |
|
|
413
417
|
|
|
414
418
|
## Done When
|
|
415
419
|
|
|
@@ -417,6 +421,8 @@ WARN — 3 issues found (0 blocking, 3 must-acknowledge). Resolve before commit
|
|
|
417
421
|
- Error handling verified on all async functions and HTTP calls
|
|
418
422
|
- Regression impact assessed — dependent files identified via scout
|
|
419
423
|
- Completeness checklist passed (validation schema, loading/error states, test file)
|
|
424
|
+
- Cross-layer pairing checked (Step 4): every new interactive component's handler chain reaches a real endpoint/service or has an explicit UI-only scope
|
|
425
|
+
- Dead-interactive scan done (Step 4.5 UI hook) on all UI files in the diff
|
|
420
426
|
- Sentinel invoked and its output attached in Security section
|
|
421
427
|
- Structured report emitted with PASS / WARN / BLOCK verdict and file:line for every finding
|
|
422
428
|
|