@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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: converge
|
|
3
|
+
description: "Spec↔code convergence scan. Use after implementation to verify the ACTUAL codebase matches the spec/plan — detects missing backends, dead buttons, partial wiring, scope creep. Classifies gaps (missing/partial/contradicts/unrequested), appends remediation tasks, loops until converged. The direct answer to 'the UI renders but nothing works' syndrome."
|
|
4
|
+
metadata:
|
|
5
|
+
author: runedev
|
|
6
|
+
version: "0.1.0"
|
|
7
|
+
layer: L3
|
|
8
|
+
model: sonnet
|
|
9
|
+
group: verification
|
|
10
|
+
tools: "Read, Glob, Grep"
|
|
11
|
+
emit: convergence.gaps, convergence.clean
|
|
12
|
+
listen: verification.complete
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# converge
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
|
|
19
|
+
Post-implementation gap detector. Re-reads the spec, plan, and tasks as the **sole source of intent**, inspects the ACTUAL codebase (present state, not the diff), and classifies every intent key as implemented or gapped. Where verification asks "does it build?", converge asks "**is everything the spec promised actually in the code?**"
|
|
20
|
+
|
|
21
|
+
This is the skill that catches the most expensive silent failure: a P1 story's UI exists, renders, passes lint/type/build — and its backend was never written.
|
|
22
|
+
|
|
23
|
+
<HARD-GATE>
|
|
24
|
+
Converge DETECTS — it never fixes. No Edit, no Write to source files.
|
|
25
|
+
Its ONLY write is APPENDING a `## Convergence` task section to the plan's task file.
|
|
26
|
+
Existing file content is never rewritten, reordered, or deleted. Zero gaps = zero writes.
|
|
27
|
+
</HARD-GATE>
|
|
28
|
+
|
|
29
|
+
## Called By (inbound)
|
|
30
|
+
|
|
31
|
+
- `cook` (L1): Phase 6.5 CONVERGE — after VERIFY, before COMMIT, for feature/greenfield chains with a requirements.md
|
|
32
|
+
- User: `/rune converge` — "did it fully implement the spec?", "check completeness", "does the code match the spec?"
|
|
33
|
+
|
|
34
|
+
## Calls (outbound)
|
|
35
|
+
|
|
36
|
+
None — pure L3 verification utility. Reports gaps; cook decides what to execute.
|
|
37
|
+
|
|
38
|
+
## Executable Steps
|
|
39
|
+
|
|
40
|
+
### Step 1 — Build the Intent Inventory
|
|
41
|
+
|
|
42
|
+
Load intent sources (all that exist; requirements.md is mandatory — without it, STOP and report `NO_SPEC`):
|
|
43
|
+
|
|
44
|
+
1. `.rune/features/<name>/requirements.md` — extract keys: every `FR-n`, every `US-n` with priority + Independent Test, every `AC-n.m` (as `US-n/AC-n.m`), every Key Entity
|
|
45
|
+
2. `.rune/plan-<feature>.md` + phase files — Key Decisions, Coverage Summary, task list with `P<phase>-T<seq>` IDs
|
|
46
|
+
3. `.rune/features/<name>/contracts/*.md` — each contract: its endpoint, its `Serves:` story, its `Consumers:` list
|
|
47
|
+
4. `.rune/features/<name>/data-model.md` — entities, state transitions
|
|
48
|
+
5. `.rune/features/<name>/quickstart.md` — per-story validation steps
|
|
49
|
+
6. `.rune/ui-spec.md` `## Unwired Elements` (if present) — designed placeholders that MUST NOT count as implemented
|
|
50
|
+
|
|
51
|
+
The inventory is a flat list of keys: `FR-3`, `US-1/AC-1.2`, `contract:create-order`, `entity:Order`, `decision:<slug>`.
|
|
52
|
+
|
|
53
|
+
### Step 2 — Build the Code-Scope Map
|
|
54
|
+
|
|
55
|
+
Map intent → code locations. NO full-repo read — targeted lookups only:
|
|
56
|
+
|
|
57
|
+
1. `Glob` every file path named in plan tasks — does it exist?
|
|
58
|
+
2. `Grep` entity names (from data-model.md) across schema/model directories
|
|
59
|
+
3. `Grep` each contract's endpoint path/route across the codebase — implementation AND callers
|
|
60
|
+
4. `Grep` component names from UI tasks — definition AND the handler symbols they bind
|
|
61
|
+
|
|
62
|
+
### Step 3 — Classify Gaps
|
|
63
|
+
|
|
64
|
+
For every intent key, assign exactly one verdict:
|
|
65
|
+
|
|
66
|
+
| Verdict | Meaning | Example |
|
|
67
|
+
|---------|---------|---------|
|
|
68
|
+
| `implemented` | Code fully realizes the key | Endpoint exists, has logic, has a caller |
|
|
69
|
+
| `missing` | Required work absent entirely | Contract file exists, no route implements it |
|
|
70
|
+
| `partial` | Started but a link in the chain is dead | Button + handler exist; handler's fetch targets a route that doesn't exist |
|
|
71
|
+
| `contradicts` | Code diverges from a locked decision or AC | Spec says soft-delete; code hard-deletes |
|
|
72
|
+
| `unrequested` | Code maps to NO intent key (scope creep — surfaced, not blocked) | New admin page no story asked for |
|
|
73
|
+
|
|
74
|
+
**Dead-interaction trace** (run for every UI element an AC references):
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
element → handler bound? → handler body non-trivial? → calls service/fetch?
|
|
78
|
+
→ target route/function EXISTS in codebase? → route touches the entity the AC names?
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
First broken link = `partial`, keyed to that element's `US-n/AC-n.m`. Elements listed in `## Unwired Elements` are automatically `missing` (designed placeholder, never wired). Heuristics: `onClick={() => {}}`, `href="#"` on action links, `console.log`-only handlers, `preventDefault()`-only submits, `fetch('/api/...')` where no route file matches — all break the chain.
|
|
82
|
+
|
|
83
|
+
### Step 4 — Assign Severity
|
|
84
|
+
|
|
85
|
+
| Severity | Condition |
|
|
86
|
+
|----------|-----------|
|
|
87
|
+
| CRITICAL | `missing` or `contradicts` gap that blocks a **P1 story's** acceptance scenario or Independent Test |
|
|
88
|
+
| HIGH | `partial` on a P1 story, or `missing`/`contradicts` on P2 |
|
|
89
|
+
| MEDIUM | Any gap on P3; `unrequested` code touching shared modules |
|
|
90
|
+
| LOW | `unrequested` isolated code; cosmetic divergence |
|
|
91
|
+
|
|
92
|
+
### Step 5 — Append Remediation Tasks (APPEND-ONLY)
|
|
93
|
+
|
|
94
|
+
If gaps exist, append to the ACTIVE phase file (or master plan task section if no phase file):
|
|
95
|
+
|
|
96
|
+
```markdown
|
|
97
|
+
## Convergence (round N)
|
|
98
|
+
> Appended by converge — spec↔code gaps found. Do not edit rows above this section.
|
|
99
|
+
- [ ] CV-N.1 [CRITICAL] Implement POST /api/orders route per contract:create-order (missing) — `src/api/orders.ts`
|
|
100
|
+
- [ ] CV-N.2 [HIGH] Wire OrderForm submit to POST /api/orders per US-1/AC-1.1 (partial: handler fetches nonexistent route) — `src/components/OrderForm.tsx`
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Task format: `CV-<round>.<seq> [severity] <imperative> per <intent-key> (<gap-type>) — <file path>`. Every task cites its intent key — a remediation task with no key is itself a converge violation.
|
|
104
|
+
|
|
105
|
+
**Deduplication**: when multiple intent keys trace to the SAME absent/broken artifact (e.g., `contract:create-order` missing AND `US-1/AC-1.1` partial, both resolved by implementing `src/api/orders.ts`), emit ONE combined CV task citing all keys — `CV-1.1 [CRITICAL] Implement POST /api/orders per contract:create-order + US-1/AC-1.1 (missing/partial) — src/api/orders.ts`. One target file = one task; the report table still lists every key's verdict separately.
|
|
106
|
+
|
|
107
|
+
If ZERO gaps: write nothing (task file stays byte-identical), emit `convergence.clean`.
|
|
108
|
+
|
|
109
|
+
### Step 6 — Emit Verdict
|
|
110
|
+
|
|
111
|
+
- Gaps found → emit `convergence.gaps` with `{feature, round, counts: {missing, partial, contradicts, unrequested}, critical: N}`
|
|
112
|
+
- Clean → emit `convergence.clean` with `{feature, round, keys_checked: N}`
|
|
113
|
+
|
|
114
|
+
The caller (cook Phase 6.5) executes appended tasks and re-invokes converge — loop until clean, max 2 remediation rounds before escalation.
|
|
115
|
+
|
|
116
|
+
## Output Format
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
## Convergence Report — <feature> (round N)
|
|
120
|
+
|
|
121
|
+
Intent keys checked: 23 | implemented: 19 | gaps: 4
|
|
122
|
+
|
|
123
|
+
| Key | Verdict | Severity | Evidence |
|
|
124
|
+
|-----|---------|----------|----------|
|
|
125
|
+
| contract:create-order | missing | CRITICAL | contracts/create-order.md exists; no route matches POST /api/orders (grep: 0 hits in src/) |
|
|
126
|
+
| US-1/AC-1.1 | partial | HIGH | OrderForm.tsx:42 fetch('/api/orders') → route absent |
|
|
127
|
+
| US-3/AC-3.1 | implemented | — | route src/api/list.ts:12, caller OrderList.tsx:8 |
|
|
128
|
+
| (none) | unrequested | LOW | src/pages/admin-stats.tsx maps to no story |
|
|
129
|
+
|
|
130
|
+
Verdict: 2 gaps blocking P1 → convergence.gaps emitted, 2 tasks appended (CV-1.1, CV-1.2)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Every row needs `file:line` evidence or a grep result count — verdicts without evidence are hallucinations.
|
|
134
|
+
|
|
135
|
+
## Constraints
|
|
136
|
+
|
|
137
|
+
1. MUST treat spec/plan/contracts as the sole source of intent — never infer intent from the code itself
|
|
138
|
+
2. MUST inspect present codebase state, not the git diff — earlier phases may have broken older work
|
|
139
|
+
3. MUST give every gap an intent key, a gap-type, a severity, and file-level evidence
|
|
140
|
+
4. MUST append remediation tasks — never rewrite, reorder, or delete existing task content
|
|
141
|
+
5. MUST NOT edit source code — converge detects, fix/cook remediate
|
|
142
|
+
6. MUST surface `unrequested` code as findings, never silently delete or block on it
|
|
143
|
+
7. MUST report `NO_SPEC` and stop when no requirements.md exists — converge without a spec is vibes
|
|
144
|
+
|
|
145
|
+
## Sharp Edges
|
|
146
|
+
|
|
147
|
+
| Failure Mode | Severity | Mitigation |
|
|
148
|
+
|---|---|---|
|
|
149
|
+
| Inferring intent from code ("this helper implies a story") | CRITICAL | Intent inventory comes ONLY from Step 1 artifacts — code is evidence, never intent |
|
|
150
|
+
| Verdict without file:line or grep evidence | CRITICAL | Output format requires Evidence column — no evidence, no verdict |
|
|
151
|
+
| Rewriting the task file instead of appending | CRITICAL | HARD-GATE: append-only; zero gaps = zero writes (byte-identical file) |
|
|
152
|
+
| Marking `implemented` because the file exists | HIGH | Existence ≠ implementation — run the dead-interaction trace; a route with `res.status(501)` is `partial` |
|
|
153
|
+
| Counting a designed placeholder as implemented | HIGH | `.rune/ui-spec.md` Unwired Elements are automatically `missing` |
|
|
154
|
+
| Infinite converge loop (gaps never reach zero) | HIGH | Caller caps at 2 remediation rounds → Structured Escalation Report; same gap surviving 2 rounds = approach is wrong, not effort |
|
|
155
|
+
| Fixing the gap itself "since it's small" | HIGH | Converge never edits source — emit the task, let fix own the change |
|
|
156
|
+
| Scanning the whole repo (context blowout) | MEDIUM | Step 2 is targeted Glob/Grep from intent keys — not a repo read |
|
|
157
|
+
| Treating `unrequested` as an error to delete | MEDIUM | Scope creep is surfaced for human decision — it may be wanted, undocumented work |
|
|
158
|
+
|
|
159
|
+
## Done When
|
|
160
|
+
|
|
161
|
+
- Intent inventory built from requirements.md + plan + contracts (or NO_SPEC reported)
|
|
162
|
+
- Every intent key has a verdict with file-level evidence
|
|
163
|
+
- Dead-interaction trace run for every AC-referenced UI element
|
|
164
|
+
- Gaps appended as `CV-*` tasks with intent keys (or task file byte-identical when clean)
|
|
165
|
+
- `convergence.gaps` or `convergence.clean` emitted with counts
|
|
166
|
+
- Convergence Report rendered with evidence column
|
|
167
|
+
|
|
168
|
+
## Returns
|
|
169
|
+
|
|
170
|
+
| Artifact | Format | Location |
|
|
171
|
+
|----------|--------|----------|
|
|
172
|
+
| Convergence Report | Markdown table with evidence | inline |
|
|
173
|
+
| Remediation tasks | `CV-<round>.<seq>` checklist (append-only) | active phase file / master plan |
|
|
174
|
+
| Signal | `convergence.gaps` \| `convergence.clean` with counts | mesh |
|
|
175
|
+
|
|
176
|
+
## Cost Profile
|
|
177
|
+
|
|
178
|
+
~2000-5000 tokens input (spec + plan + targeted greps), ~500-1500 tokens output. Sonnet — the dead-interaction trace needs code comprehension, not just pattern matching. Runs once per feature (plus ≤2 remediation rounds).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Converge Eval Fixtures
|
|
2
|
+
|
|
3
|
+
> Behavioral test scenarios for `converge`. Each fixture defines inputs (spec + code state)
|
|
4
|
+
> and the EXACT expected verdict. Use these to verify converge behaves correctly after any
|
|
5
|
+
> edit to its SKILL.md — and as seeds for a future automated eval harness.
|
|
6
|
+
|
|
7
|
+
## Fixture 1 — Dead button (the canonical failure)
|
|
8
|
+
|
|
9
|
+
**Spec**: `US-1 [P1]` "submit an order", `AC-1.1: GIVEN valid items WHEN user clicks Save THEN order persisted and visible in list`. Contract `contracts/create-order.md` → `POST /api/orders`, Consumers: `OrderForm`.
|
|
10
|
+
|
|
11
|
+
**Code state**: `OrderForm.tsx` exists, renders `<button onClick={handleSave}>Save</button>`; `handleSave` calls `fetch('/api/orders', {method:'POST'})`. NO route file implements `POST /api/orders`.
|
|
12
|
+
|
|
13
|
+
**Expected**: `contract:create-order` → `missing` CRITICAL (P1). `US-1/AC-1.1` → `partial` (chain breaks at route-exists). Two `CV-1.*` tasks appended citing those keys. `convergence.gaps` emitted. **FAIL IF**: verdict is `implemented` because OrderForm exists, or converge edits OrderForm itself.
|
|
14
|
+
|
|
15
|
+
## Fixture 2 — Fully wired (clean pass)
|
|
16
|
+
|
|
17
|
+
**Spec**: same as Fixture 1.
|
|
18
|
+
|
|
19
|
+
**Code state**: `OrderForm.tsx` handler → `fetch POST /api/orders`; `src/api/orders.ts` implements the route, validates items, persists via `Order` model; `OrderList.tsx` fetches and renders.
|
|
20
|
+
|
|
21
|
+
**Expected**: all keys `implemented` with file:line evidence. ZERO writes — task file byte-identical. `convergence.clean` emitted. **FAIL IF**: any "improvement" task is appended (converge is not a reviewer), or the task file is touched at all.
|
|
22
|
+
|
|
23
|
+
## Fixture 3 — Contradicts a locked decision
|
|
24
|
+
|
|
25
|
+
**Spec**: requirements.md Decision (locked): "soft-delete only — records marked `deletedAt`, never removed". Plan Key Decisions repeats it.
|
|
26
|
+
|
|
27
|
+
**Code state**: `src/api/orders.ts` delete handler runs `DELETE FROM orders WHERE id = ?`.
|
|
28
|
+
|
|
29
|
+
**Expected**: `decision:soft-delete` → `contradicts`, CRITICAL if a P1 AC covers deletion (else HIGH). Task: `CV-1.1 [CRITICAL] Replace hard delete with deletedAt flag per decision:soft-delete (contradicts) — src/api/orders.ts`. **FAIL IF**: classified `implemented` because "a delete exists".
|
|
30
|
+
|
|
31
|
+
## Fixture 4 — Unrequested code (scope creep surfaced, not blocked)
|
|
32
|
+
|
|
33
|
+
**Spec**: stories US-1..US-3 cover order CRUD only.
|
|
34
|
+
|
|
35
|
+
**Code state**: everything from Fixture 2 PLUS `src/pages/admin-stats.tsx` (a dashboard no story mentions).
|
|
36
|
+
|
|
37
|
+
**Expected**: all spec keys `implemented`; one `unrequested` finding (LOW — isolated) listing admin-stats.tsx. `convergence.gaps` emitted (unrequested counts as a gap for reporting) BUT no CV task demanding deletion — the finding is informational for the user. **FAIL IF**: converge deletes the file, appends a "remove admin-stats" task, or hides the finding.
|
|
38
|
+
|
|
39
|
+
## Fixture 5 — Placeholder counted honestly
|
|
40
|
+
|
|
41
|
+
**Spec**: `US-2 [P2]` "browse products", AC-2.1 names a product grid.
|
|
42
|
+
|
|
43
|
+
**Code state**: `ProductGrid.tsx` renders `[ PLACEHOLDER: product-grid ]` boxes; `.rune/ui-spec.md` lists `product-grid` under `## Unwired Elements`.
|
|
44
|
+
|
|
45
|
+
**Expected**: `US-2/AC-2.1` → `missing` HIGH (P2) — Unwired Elements are auto-missing regardless of how substantive the placeholder markup looks. **FAIL IF**: `implemented` or `partial` (a designed placeholder is not "started work").
|
|
46
|
+
|
|
47
|
+
## Fixture 6 — No spec (honest refusal)
|
|
48
|
+
|
|
49
|
+
**Spec**: no `.rune/features/*/requirements.md` exists.
|
|
50
|
+
|
|
51
|
+
**Expected**: converge reports `NO_SPEC` and stops. No inventory invented from the code, no tasks appended. **FAIL IF**: converge scans the code and fabricates intent keys from what it finds.
|
|
52
|
+
|
|
53
|
+
## Fixture 7 — Remediation survives round 1 (escalation path)
|
|
54
|
+
|
|
55
|
+
**Spec**: same as Fixture 1. **Round 1**: converge found `contract:create-order` missing, appended `CV-1.1`. Cook executed CV-1.1 but implemented a stub: `src/api/orders.ts` exists, handler returns `res.status(501)`.
|
|
56
|
+
|
|
57
|
+
**Code state at round 2**: route file exists, body is a 501 stub; OrderForm unchanged.
|
|
58
|
+
|
|
59
|
+
**Expected**: round 2 verdict for `contract:create-order` → `partial` (file exists but Level-2-style stub — a 501 is not an implementation), still CRITICAL (P1). `CV-2.1` appended. After round 2 the caller's cap is exhausted → cook produces a Structured Escalation Report with the surviving gap named. **FAIL IF**: classified `implemented` because the route file now exists, or converge silently allows a round 3.
|
package/skills/cook/SKILL.md
CHANGED
|
@@ -5,13 +5,13 @@ context: fork
|
|
|
5
5
|
agent: general-purpose
|
|
6
6
|
metadata:
|
|
7
7
|
author: runedev
|
|
8
|
-
version: "2.
|
|
8
|
+
version: "2.6.0"
|
|
9
9
|
layer: L1
|
|
10
10
|
model: sonnet
|
|
11
11
|
group: orchestrator
|
|
12
12
|
tools: "Read, Write, Edit, Bash, Glob, Grep"
|
|
13
13
|
emit: phase.complete, checkpoint.request
|
|
14
|
-
listen: plan.ready, review.complete, ideas.ready, preflight.passed, verification.complete
|
|
14
|
+
listen: plan.ready, review.complete, ideas.ready, preflight.passed, verification.complete, convergence.gaps, convergence.clean
|
|
15
15
|
---
|
|
16
16
|
|
|
17
17
|
# cook
|
|
@@ -110,8 +110,8 @@ Not every task needs every phase:
|
|
|
110
110
|
Nano task: DO → VERIFY → DONE (no phases, auto-detected)
|
|
111
111
|
Simple bug fix: Phase 1 → 4 → 6 → 7
|
|
112
112
|
Small refactor: Phase 1 → 4 → 5 → 6 → 7
|
|
113
|
-
New feature: Phase 1 → 1.5 → 2 → 3 → 4 → 5 → 6 → 7 → 8
|
|
114
|
-
Complex feature: All phases + brainstorm in Phase 2
|
|
113
|
+
New feature: Phase 1 → 1.5 → 2 → 3 → 4 → 5 → 6 → 6.5 → 7 → 8 (6.5: conditional — requires requirements.md)
|
|
114
|
+
Complex feature: All phases (incl. 6.5) + brainstorm in Phase 2
|
|
115
115
|
Security-sensitive: All phases + sentinel escalated to opus
|
|
116
116
|
Fast mode: Phase 1 → 4 → 6 → 7 (auto-detected, see below)
|
|
117
117
|
Multi-session: Phase 0 (resume) → 3 → 4 → 5 → 6 → 7 (one plan phase per session)
|
|
@@ -282,7 +282,12 @@ After scout completes, check if the detected tech stack or task description matc
|
|
|
282
282
|
**Step 0.5 — Cross-Project Recall**: Call `neural-memory` (Recall Mode) with 3-5 topics relevant to the current task. Always prefix queries with the project name (e.g., `"ProjectName auth pattern"` not `"auth pattern"`).
|
|
283
283
|
|
|
284
284
|
1. Use `Glob` to check for `.rune/plan-*.md` files
|
|
285
|
-
2. If a master plan exists matching the current task:
|
|
285
|
+
2. If a master plan exists matching the current task:
|
|
286
|
+
- **Step 0.55 — Spec-Backfill Gate (HARD-GATE)**: Before resuming, `Glob` `.rune/features/*/requirements.md`. If NO requirements doc exists AND the task is a **Feature / Integration / Greenfield** (same classification as the Phase 1 BA-gate — NOT a bug fix, refactor, or trivial change), the plan was produced without a spec (e.g., a `brainstorm → plan` bypass that skipped `ba`). Do NOT resume blindly:
|
|
287
|
+
1. Invoke `rune:ba` to backfill requirements (5-question elicitation, or Synthesis Mode if the plan + conversation already carry enough context) → produces `.rune/features/<name>/requirements.md`.
|
|
288
|
+
2. Re-invoke `rune:plan` to reconcile the existing plan against the new spec — if the plan contradicts a locked Decision or misses a requirement, revise the affected phase files and get user re-approval (Re-Planning protocol).
|
|
289
|
+
3. THEN resume. For Bug Fix / Refactor / trivial tasks, skip this gate — no spec is expected.
|
|
290
|
+
- Read the (reconciled) master plan → find first `⬚ Pending` or `🔄 Active` phase → load ONLY that phase file → announce "Resuming from Phase N" → skip to Phase 4
|
|
286
291
|
3. If no master plan exists → proceed to Phase 1 as normal
|
|
287
292
|
|
|
288
293
|
**Step 0.6 — Contract Load**: Use `Glob` to check for `.rune/contract.md`. If it exists:
|
|
@@ -502,12 +507,36 @@ Invoke `rune:session-bridge` after Phase 2, 4, and 5 to save intermediate state.
|
|
|
502
507
|
|
|
503
508
|
Before entering ANY Phase N+1, assert: Phase N `completed` in TodoWrite | gate condition met | no BLOCK from sub-skills | no unresolved CRITICAL findings. If any fails → STOP, log "BLOCKED at Phase N→N+1: [assertion]", fix, re-check.
|
|
504
509
|
|
|
505
|
-
**Key transitions:** 1→2: scout done | 2→3: plan approved | 3→4: failing tests exist | 4→5: all tests pass | 5→6: no CRITICAL findings | 6→
|
|
510
|
+
**Key transitions:** 1→2: scout done | 2→3: plan approved | 3→4: failing tests exist | 4→5: all tests pass | 5→6: no CRITICAL findings | 6→6.5: lint+types+build green | 6.5→7: convergence.clean or documented escalation (features with requirements.md; others pass through).
|
|
506
511
|
|
|
507
512
|
## Phase 6: VERIFY
|
|
508
513
|
|
|
509
514
|
**REQUIRED SUB-SKILL**: Use `rune:verification` — run lint, type check, full test suite, build. Then `rune:hallucination-guard` to verify imports and API signatures. ALL checks MUST pass before commit.
|
|
510
515
|
|
|
516
|
+
**Quickstart execution**: if `.rune/features/<name>/quickstart.md` exists (plan Step 3.7 boundary artifact), execute its validation blocks — run each command, compare against its **Expect** line. Any mismatch = verification FAIL (treat like a failing test). If the environment cannot run a block (no browser, no DB), SKIP it with the reason named in the Cook Report — a skipped quickstart is visible debt, never silent.
|
|
517
|
+
|
|
518
|
+
## Phase 6.5: CONVERGE (Spec↔Code Gap Scan)
|
|
519
|
+
|
|
520
|
+
**REQUIRED SUB-SKILL**: Use `rune:converge` — verify the ACTUAL codebase matches the spec before committing.
|
|
521
|
+
|
|
522
|
+
**Trigger**: feature/greenfield chains where `.rune/features/<name>/requirements.md` exists.
|
|
523
|
+
**Skip** (announce the skip): nano/fast/bugfix/refactor/hotfix chains, or no requirements.md (ad-hoc task — Phase 5 gates are the only protection).
|
|
524
|
+
|
|
525
|
+
1. Invoke `rune:converge` — it re-reads spec/plan/contracts as sole intent, scans present code state, classifies gaps (`missing` / `partial` / `contradicts` / `unrequested`)
|
|
526
|
+
2. **`convergence.clean`** → proceed to Phase 7
|
|
527
|
+
3. **`convergence.gaps`** → inspect the signal's `counts` payload first:
|
|
528
|
+
- **Unrequested-only** (`counts.missing`=0, `counts.partial`=0, `counts.contradicts`=0, `counts.unrequested`>0): no CV tasks were appended — surface the findings in the Cook Report and proceed to Phase 7. Do NOT enter the remediation loop for informational scope-creep findings
|
|
529
|
+
- **Otherwise**: converge appended `CV-*` remediation tasks to the active phase file:
|
|
530
|
+
- Execute the CV tasks (return to Phase 4 loop for them; CRITICAL/HIGH first)
|
|
531
|
+
- Re-run Phase 6 VERIFY on the remediated code, then re-invoke converge (round 2)
|
|
532
|
+
- **Max 2 remediation rounds.** Gaps still present after round 2 → produce a Structured Escalation Report (the same gap surviving 2 rounds means the approach is wrong, not the effort)
|
|
533
|
+
4. `unrequested` findings are surfaced to the user in the Cook Report — never silently deleted, never blocking
|
|
534
|
+
|
|
535
|
+
<HARD-GATE>
|
|
536
|
+
A P1 story with a CRITICAL convergence gap (missing/contradicts) MUST NOT be committed as "done."
|
|
537
|
+
Either remediate within the round cap, or escalate with the gap documented — never claim completion over a known dead path.
|
|
538
|
+
</HARD-GATE>
|
|
539
|
+
|
|
511
540
|
## Phase 7: COMMIT
|
|
512
541
|
|
|
513
542
|
**RECOMMENDED SUB-SKILL**: Use `rune:git` — stage specific files (`git add <files>`, NOT `git add .`), generate semantic commit message from diff. If working from master plan: update phase status `🔄 → ✅`, announce next phase or "All phases complete."
|
|
@@ -772,6 +801,7 @@ Mentally track tool call fingerprints. 3 identical calls → WARN. 5 identical c
|
|
|
772
801
|
| 5 | `constraint-check` | L3 | Audit HARD-GATE compliance across workflow |
|
|
773
802
|
| 6 | `verification` | L3 | Lint + types + tests + build |
|
|
774
803
|
| 6 | `hallucination-guard` | L3 | Verify imports and API calls are real |
|
|
804
|
+
| 6.5 | `converge` | L3 | Spec↔code gap scan for features with requirements.md — dead buttons, missing backends, contradicted decisions |
|
|
775
805
|
| 7 | `journal` | L3 | Record architectural decisions |
|
|
776
806
|
| 8 | `session-bridge` | L3 | Save context for future sessions |
|
|
777
807
|
| any | `context-pack` | L3 | create structured handoff briefings before spawning subagents |
|
|
@@ -802,6 +832,7 @@ Mentally track tool call fingerprints. 3 identical calls → WARN. 5 identical c
|
|
|
802
832
|
| Gate | Requires | If Missing |
|
|
803
833
|
|------|----------|------------|
|
|
804
834
|
| Resume Gate | Phase 0 checks for master plan before starting | Proceed to Phase 1 |
|
|
835
|
+
| Spec-Backfill Gate | Feature/greenfield resume requires `requirements.md` to exist alongside the plan | Plan without spec → invoke `rune:ba` to backfill, reconcile plan, THEN resume |
|
|
805
836
|
| Scout Gate | scout output before Phase 2 | Invoke rune:scout first |
|
|
806
837
|
| Plan Gate | User-approved plan before Phase 3 | Cannot proceed |
|
|
807
838
|
| Adversary Gate | adversary verdict before Phase 3 for features | Skip for bugfix/hotfix/refactor |
|
|
@@ -809,6 +840,7 @@ Mentally track tool call fingerprints. 3 identical calls → WARN. 5 identical c
|
|
|
809
840
|
| Test-First Gate | Failing tests before Phase 4 | Write tests or get explicit skip |
|
|
810
841
|
| Quality Gate | preflight + sentinel + review before Phase 7 | Fix findings, re-run |
|
|
811
842
|
| Verification Gate | lint + types + tests + build green before commit | Fix, re-run |
|
|
843
|
+
| Convergence Gate | `convergence.clean` (or documented escalation) before Phase 7 for features with requirements.md | Execute CV tasks, re-verify, re-converge (max 2 rounds) |
|
|
812
844
|
|
|
813
845
|
## Structured Output Contract (Prompt-as-API Pattern)
|
|
814
846
|
|
|
@@ -881,6 +913,7 @@ Common multi-agent failures to explicitly avoid. These are NOT edge cases — th
|
|
|
881
913
|
| Anti-Pattern | Why It Fails | Correct Approach |
|
|
882
914
|
|---|---|---|
|
|
883
915
|
| **Bypass hierarchy** — skipping scout/plan and jumping to Phase 4 code | Builds wrong thing. Most "wasted work" traces back to missing Phase 1-2 | Follow phase gates. Even "obvious" tasks benefit from 30s of scout |
|
|
916
|
+
| **Resume without spec** — a `brainstorm → plan` chain produced a plan file, so Phase 0 skips to Phase 4 and `ba` never runs | Plan exists but no requirements/acceptance criteria — a plan without a spec. Ships confident code for the wrong "what" | Spec-Backfill Gate (Step 0.55): feature/greenfield resume with no `requirements.md` → run `ba`, reconcile plan, THEN resume |
|
|
884
917
|
| **Shadow decisions** — making architectural choices without logging to decisions.md | Next session repeats the same debate. Team agents contradict each other | Log every non-trivial choice via `decisions.md` or `journal` |
|
|
885
918
|
| **Gold-plating** — adding "nice-to-have" features not in the approved plan | Scope creep, delayed delivery, untested code paths | Build ONLY what's in the plan. Log extras as follow-up tasks |
|
|
886
919
|
| **Test-after** — writing tests after implementation instead of before (TDD violation) | Tests validate implementation bugs, not requirements. Coverage looks good but misses edge cases | Phase 3 (RED) before Phase 4 (GREEN). Always |
|
|
@@ -903,6 +936,7 @@ SELF-VALIDATION (run before emitting Cook Report):
|
|
|
903
936
|
- [ ] Plan approval gate was not bypassed — user said "go" (check conversation history)
|
|
904
937
|
- [ ] No Phase 4 code was written before Phase 3 tests (TDD order preserved)
|
|
905
938
|
- [ ] All Phase 5 quality gates (preflight, sentinel, review) ran — not just claimed
|
|
939
|
+
- [ ] Phase 6.5 converge ran for features with requirements.md — or skip announced (no spec) / escalation documented
|
|
906
940
|
- [ ] No quality gate exceeded 3 remediation cycles without user escalation
|
|
907
941
|
- [ ] No upstream issue was fixed by code change alone — UPSTREAM findings re-invoked the source skill
|
|
908
942
|
- [ ] Cook Report contains actual commit hash, not placeholder
|
|
@@ -912,6 +946,7 @@ SELF-VALIDATION (run before emitting Cook Report):
|
|
|
912
946
|
|
|
913
947
|
All applicable phases complete + Self-Validation passed:
|
|
914
948
|
- User approved plan | All tests PASS (output shown) | preflight+sentinel+review PASS | build green
|
|
949
|
+
- Convergence: `convergence.clean` OR skip announced (no requirements.md) OR escalation documented — never silent
|
|
915
950
|
- Cook Report emitted with commit hash | Session state saved to .rune/ via session-bridge
|
|
916
951
|
|
|
917
952
|
## Cost Profile
|
package/skills/debug/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: debug
|
|
|
3
3
|
description: "Root cause analysis for bugs and unexpected behavior. Traces errors through code, uses structured reasoning, and hands off to fix when cause is found. Core of the debug↔fix mesh. When the diagnosed cause is a memory leak in a long-running process, escalates to perf for cost-impact framing (leaks drive OOM-restart → cold-start → autoscaler spend, often 20-40% bill inflation)."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.4.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: development
|
|
@@ -174,6 +174,8 @@ ALL diagnostic code added during debug MUST be wrapped in `#region agent-debug`
|
|
|
174
174
|
Unmarked instrumentation will be treated as stray code and removed prematurely.
|
|
175
175
|
</HARD-GATE>
|
|
176
176
|
|
|
177
|
+
**Observability gap as a finding.** If you had to add temporary `console.log` markers because the code emitted *nothing useful* about this path, that absence is itself a root-cause-adjacent signal: the bug was hard to diagnose because the system is blind here. When the fix lands, recommend converting the throwaway markers into **durable structured telemetry** (a stable event name + correlation ID, not prose) so the next occurrence is a query, not another archaeology session. This is advisory — note it in the report, don't block on it. Contract: `../deploy/references/observability.md`.
|
|
178
|
+
|
|
177
179
|
### Step 2c: Check Debug Knowledge Base
|
|
178
180
|
|
|
179
181
|
Before forming hypotheses, check `.rune/debug/knowledge-base.md`:
|
|
@@ -427,7 +429,7 @@ Append to Debug Report when invoked standalone. Suppress when called as sub-skil
|
|
|
427
429
|
```yaml
|
|
428
430
|
chain_metadata:
|
|
429
431
|
skill: "rune:debug"
|
|
430
|
-
version: "1.
|
|
432
|
+
version: "1.4.0"
|
|
431
433
|
status: "[DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED]"
|
|
432
434
|
domain: "[area debugged]"
|
|
433
435
|
files_changed: [] # debug never changes files
|
package/skills/deploy/SKILL.md
CHANGED
|
@@ -4,13 +4,13 @@ description: "Deploy application to target platform. Use when user explicitly sa
|
|
|
4
4
|
disable-model-invocation: true
|
|
5
5
|
metadata:
|
|
6
6
|
author: runedev
|
|
7
|
-
version: "0.
|
|
7
|
+
version: "0.8.0"
|
|
8
8
|
layer: L2
|
|
9
9
|
model: sonnet
|
|
10
10
|
group: delivery
|
|
11
11
|
tools: "Read, Write, Edit, Bash, Glob, Grep"
|
|
12
12
|
emit: deploy.complete
|
|
13
|
-
listen: security.passed, tests.passed, docs.updated, audit.complete, db.migrated
|
|
13
|
+
listen: security.passed, tests.passed, docs.updated, audit.complete, db.migrated, integration.verified, convergence.clean
|
|
14
14
|
---
|
|
15
15
|
|
|
16
16
|
# deploy
|
|
@@ -58,6 +58,8 @@ Call `rune:verification` to run the full test suite and build.
|
|
|
58
58
|
If verification fails → STOP. Do NOT proceed. Report failure with test output.
|
|
59
59
|
```
|
|
60
60
|
|
|
61
|
+
**Wiring evidence check (advisory)**: when deploying a FEATURE (not a hotfix — hotfix chain exempt) whose changes touch both UI and api/service/data files, look for cross-layer evidence: `integration.verified` (verification Level 3.5 passed) or `convergence.clean` (converge found zero gaps). Neither present → WARN the user explicitly — "Deploying UI+data changes with no cross-layer wiring evidence. Unit tests alone don't prove the buttons work. Proceed?" — and require confirmation. Advisory, not a block: the user can proceed, but never unknowingly.
|
|
62
|
+
|
|
61
63
|
Call `rune:sentinel` to run security scan.
|
|
62
64
|
|
|
63
65
|
```
|
|
@@ -290,6 +292,24 @@ Production observability (Datadog, Sentry, New Relic, Honeycomb, Logtail) bills
|
|
|
290
292
|
|
|
291
293
|
This overlaps with `perf` Step 8.6 (Observability Cost Control). `perf` finds the code patterns that emit overheavy telemetry; `deploy` ensures the platform-side ingestion + retention defaults are configured before the first prod release where the bill compounds.
|
|
292
294
|
|
|
295
|
+
## Instrumentation Readiness (pre-prod advisory gate)
|
|
296
|
+
|
|
297
|
+
> Two observability concerns, kept separate: the section *above* ("Observability Cost in Deploys") gates the telemetry **bill** (retention/sampling/cardinality config). This section gates whether the telemetry **exists and works** at all. Both run; neither replaces the other.
|
|
298
|
+
|
|
299
|
+
Cost config (above) answers "is the telemetry *affordable*". This answers "does the telemetry *exist and work*". A feature with retries, queues, external calls, or new endpoints that ships **zero new telemetry** is shipping blind — the first incident becomes archaeology.
|
|
300
|
+
|
|
301
|
+
<MUST-READ path="references/observability.md" trigger="first prod deploy of a feature that adds I/O, endpoints, jobs, or external integrations"/>
|
|
302
|
+
|
|
303
|
+
Before the first production deploy of such a feature, verify the **Instrumentation Readiness Checklist** in `references/observability.md`. This is **advisory** (WARN, not BLOCK) — do not stop a deploy over missing telemetry, but surface the gap:
|
|
304
|
+
|
|
305
|
+
```
|
|
306
|
+
INSTRUMENTATION_GAP — feature adds [endpoint/job/integration] with no new
|
|
307
|
+
structured logs / RED metrics / correlation ID. First incident will be blind.
|
|
308
|
+
→ See deploy/references/observability.md before shipping.
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Skip for: static sites, config-only changes, hotfixes (flag for follow-up), non-prod deploys.
|
|
312
|
+
|
|
293
313
|
## Output Format
|
|
294
314
|
|
|
295
315
|
Deploy Report with platform, status (success/failed/rollback), deployed URL, build time, and checks (tests, security, HTTP, visual, monitoring). See Step 6 Report above for full template.
|
|
@@ -328,6 +348,7 @@ Known failure modes for this skill. Check these before declaring done.
|
|
|
328
348
|
| Resources deployed without cost-allocation tags | HIGH | Step 1 pre-deploy MUST verify Environment/Team/Service tags. Untagged = unfalsifiable cost claims downstream |
|
|
329
349
|
| Self-host migration recommended on bill threshold alone | HIGH | Crossover rule requires ALL 3 conditions: bill + ops bandwidth + customization need. Single-criterion recommendations produce engineering-debt swap |
|
|
330
350
|
| Defaults shipped on observability stack | MEDIUM | Verify retention + sampling + cardinality config BEFORE first prod deploy; defaults often bleed > compute bill |
|
|
351
|
+
| Feature ships with zero telemetry (logs/metrics/traces) | MEDIUM | Instrumentation Readiness advisory gate — WARN `INSTRUMENTATION_GAP` (skip for static sites/config-only/hotfix per section); first incident is blind without it. See `references/observability.md` |
|
|
331
352
|
| Premature self-host (< 10K MAU) | MEDIUM | Flag `PREMATURE_SELFHOST` — managed equivalent at this scale is cheaper than engineering time spent operating |
|
|
332
353
|
|
|
333
354
|
## Done When
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Observability & Instrumentation Reference
|
|
2
|
+
|
|
3
|
+
Code you cannot observe is code you cannot operate. Instrumentation is written **alongside** the feature, like tests — not bolted on after the first incident. A feature that ships without telemetry turns its first user-reported bug into archaeology instead of a query.
|
|
4
|
+
|
|
5
|
+
This reference is the shared instrumentation discipline. `deploy` gates on it before prod, `perf` uses it as the measurement basis, `debug` leaves it behind so the next investigation is fast.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Define "working" before instrumenting
|
|
10
|
+
|
|
11
|
+
Telemetry without a question is noise. Before adding anything, write 2-4 questions an on-call engineer will ask about this feature:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
FEATURE: checkout payment retry
|
|
15
|
+
ON-CALL WILL ASK:
|
|
16
|
+
1. What fraction of payments succeed first-try vs after retry?
|
|
17
|
+
2. When a payment fails permanently, why? (provider error / timeout / validation?)
|
|
18
|
+
3. Is the payment provider slower than usual?
|
|
19
|
+
→ Every signal below must answer one of these.
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
If you cannot name the questions, you are not ready to instrument — you will log everything and learn nothing.
|
|
23
|
+
|
|
24
|
+
## 2. One signal per question
|
|
25
|
+
|
|
26
|
+
| Signal | Answers | Cost profile |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| **Structured log** | "What happened in this specific case?" | Per-event; grows with traffic |
|
|
29
|
+
| **Metric** | "How often / how fast, in aggregate?" | Fixed per series; cheap to query |
|
|
30
|
+
| **Trace** | "Where did time go across services?" | Per-request; usually sampled |
|
|
31
|
+
|
|
32
|
+
Rule of thumb: **metrics say *that* something is wrong, traces say *where*, logs say *why*.**
|
|
33
|
+
|
|
34
|
+
## 3. Structured logging
|
|
35
|
+
|
|
36
|
+
Log events, not prose. Every line is a JSON object with a stable event name and machine-readable fields:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// BAD: string interpolation — unqueryable, inconsistent
|
|
40
|
+
logger.info(`Payment ${id} failed for ${userId} after ${n} retries`);
|
|
41
|
+
|
|
42
|
+
// GOOD: stable event name + structured fields
|
|
43
|
+
logger.warn({ event: 'payment_failed', paymentId: id, provider: 'stripe', errorCode: err.code, attempt: n }, 'payment failed');
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Log levels — consistent meaning:**
|
|
47
|
+
|
|
48
|
+
| Level | Meaning | On-call action |
|
|
49
|
+
|---|---|---|
|
|
50
|
+
| `error` | Invariant broken; someone may need to act | Investigate |
|
|
51
|
+
| `warn` | Degraded but handled (retry succeeded, fallback used) | Watch trends |
|
|
52
|
+
| `info` | Significant business event (order placed, job finished) | None |
|
|
53
|
+
| `debug` | Diagnostic detail | Off in prod by default |
|
|
54
|
+
|
|
55
|
+
**Correlation IDs are mandatory.** Generate or accept a request ID at the system boundary; attach it to every log line, span, and outbound call. Without it you cannot reconstruct one request from interleaved logs:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
app.use((req, res, next) => {
|
|
59
|
+
req.id = req.headers['x-request-id'] ?? crypto.randomUUID();
|
|
60
|
+
req.log = logger.child({ requestId: req.id });
|
|
61
|
+
res.setHeader('x-request-id', req.id);
|
|
62
|
+
next();
|
|
63
|
+
});
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Never log secrets, tokens, passwords, or full PII.** Telemetry pipelines are a classic data-leak path (hard rule, shared with `sentinel`). Allowlist fields; never log whole request bodies.
|
|
67
|
+
|
|
68
|
+
## 4. Metrics — RED and USE
|
|
69
|
+
|
|
70
|
+
- **Request-driven services** (endpoints, external deps): instrument **RED** — **R**ate (req/s), **E**rrors (failure rate), **D**uration (latency *histogram*).
|
|
71
|
+
- **Resources** (queues, pools, hosts): instrument **USE** — **U**tilization, **S**aturation, **E**rrors.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const httpDuration = new Histogram({
|
|
75
|
+
name: 'http_request_duration_seconds',
|
|
76
|
+
labelNames: ['method', 'route', 'status_class'], // '2xx', not '200'
|
|
77
|
+
buckets: [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5],
|
|
78
|
+
});
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Cardinality is the failure mode.** Every unique label combination is a separate time series. Labels must come from small fixed sets (route template, status class, provider). Never use user IDs, raw URLs, request IDs, or error-message text as labels — that belongs in logs/traces.
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
OK as label: route="/api/tasks/:id" status_class="5xx" provider="stripe"
|
|
85
|
+
NEVER a label: user_id, email, request_id, full URL, error message text
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**Averages never, percentiles always.** An average hides the 1% of users having a terrible time. Use histograms; read p50/p95/p99.
|
|
89
|
+
|
|
90
|
+
## 5. Distributed tracing
|
|
91
|
+
|
|
92
|
+
Use OpenTelemetry (vendor-neutral). Auto-instrumentation covers HTTP/gRPC/common DB clients with near-zero code:
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
// tracing.ts — imported before anything else
|
|
96
|
+
const sdk = new NodeSDK({ serviceName: 'checkout-service', instrumentations: [getNodeAutoInstrumentations()] });
|
|
97
|
+
sdk.start();
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Add manual spans only around meaningful internal work (`applyDiscounts`, `chargeProvider`) with the attributes on-call filters by. Propagate context across every async boundary (HTTP headers, queue metadata) or the trace dies at the gap. Sample head-based at a low rate; keep 100% of errors if the backend supports tail sampling.
|
|
101
|
+
|
|
102
|
+
## 6. Alerting — symptoms, not causes
|
|
103
|
+
|
|
104
|
+
Alert on **what users feel**, not on internal causes:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
SYMPTOM (page-worthy): CAUSE (dashboard, not a page):
|
|
108
|
+
error rate > 1% for 5 min CPU at 85%
|
|
109
|
+
p99 latency > 2s one pod restarted
|
|
110
|
+
queue age > 10 min disk at 70%
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Cause-based alerts fire when nothing is wrong and miss failures you did not predict. Every alert must:
|
|
114
|
+
|
|
115
|
+
1. **Be actionable.** If the response is "ignore it, it self-heals" → delete it.
|
|
116
|
+
2. **Link to a runbook** — even three lines: what it means, first query to run, escalation path.
|
|
117
|
+
3. **Have a threshold + duration** justified by an SLO or historical data, not a guess.
|
|
118
|
+
4. **Use two severities only** — *page* (user-facing, act now) and *ticket* (degradation, act this week). A third tier trains people to ignore everything.
|
|
119
|
+
|
|
120
|
+
## 7. Verify the telemetry itself
|
|
121
|
+
|
|
122
|
+
Instrumentation is code; it can be wrong. Before calling it done, trigger the paths and look at the real output:
|
|
123
|
+
|
|
124
|
+
- Force an error in staging → find it by `requestId`, confirm fields are structured (not `[object Object]`).
|
|
125
|
+
- Send test traffic → metric series appear with expected labels and sane values.
|
|
126
|
+
- Follow one request end-to-end in the tracing UI → no broken spans.
|
|
127
|
+
- Fire each new alert once (lower the threshold temporarily) → it reaches the right channel and the runbook link works.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Instrumentation Readiness Checklist (gate)
|
|
132
|
+
|
|
133
|
+
A feature is observable-ready when:
|
|
134
|
+
|
|
135
|
+
- [ ] On-call questions written down; each signal maps to one
|
|
136
|
+
- [ ] All logs structured (JSON), stable event names, correlation ID on every line
|
|
137
|
+
- [ ] No secrets/tokens/PII in any log line (spot-check actual output)
|
|
138
|
+
- [ ] RED metrics on every new endpoint + external dependency, bounded labels
|
|
139
|
+
- [ ] Latency is a histogram; p95/p99 queryable
|
|
140
|
+
- [ ] One request followable end-to-end without broken spans
|
|
141
|
+
- [ ] Every new alert is symptom-based, has a runbook link, was test-fired once
|
|
142
|
+
- [ ] An induced staging failure was located via telemetry alone, without reading source
|
|
143
|
+
|
|
144
|
+
## Cost note
|
|
145
|
+
|
|
146
|
+
Instrumentation has a bill. Retention, sampling, and cardinality defaults bleed money (see `deploy` → "Observability Cost in Deploys" and `perf` Step 8.6). Instrument for the on-call questions — not for completeness. Three queryable events beat three hundred prose lines.
|
package/skills/design/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: design
|
|
|
3
3
|
description: "Design system reasoning. Maps product domain to style, palette, typography, and platform-specific patterns. Generates .rune/design-system.md as the shared design contract for all UI-generating skills."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.7.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: creation
|
|
@@ -183,6 +183,18 @@ If the design calls for an icon, illustration, or graphic that the agent cannot
|
|
|
183
183
|
- For illustrations, reference a placeholder string (e.g., `[ILLUSTRATION: empty-state-dashboard]`) that a human or asset-creator pass fills in later.
|
|
184
184
|
- Malformed SVG is the #1 AI tell. A clean labeled placeholder is honest and professional.
|
|
185
185
|
|
|
186
|
+
**Placeholder Ownership (MANDATORY)**: every placeholder or intentionally inert element the design ships — `[ ICON: ... ]`, `[ILLUSTRATION: ...]`, `[ PLACEHOLDER: ... ]`, and any button/link/form rendered as visual-only (no behavior designed yet) — MUST be listed in `.rune/ui-spec.md` under a `## Unwired Elements` section:
|
|
187
|
+
|
|
188
|
+
```markdown
|
|
189
|
+
## Unwired Elements
|
|
190
|
+
| Element | Location | Why unwired | Owner of wiring |
|
|
191
|
+
|---------|----------|-------------|-----------------|
|
|
192
|
+
| product-grid | ProductGrid.tsx | awaiting US-2 backend | US-2 Endpoint task |
|
|
193
|
+
| [ ICON: dashboard ] | Sidebar.tsx | asset pass pending | asset-creator |
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
This list is how downstream gates tell **declared debt** from **accidental dead UI**: `preflight` skips these elements, `verification` reports them as INFO (visible, non-failing), and `converge` counts them as `missing` until wired. A placeholder NOT on this list that reaches implementation = a dead element with no owner — that's the bug this section exists to prevent.
|
|
197
|
+
|
|
186
198
|
#### Rule 3 — Color Derivation via oklch(), not Manual Shading
|
|
187
199
|
|
|
188
200
|
When the design needs a darker hover, lighter surface, or tinted state, **derive from the accent via oklch()** — never eyeball a hex value.
|
|
@@ -655,6 +667,7 @@ Trading/Fintech — Data-Dense Dark — Web
|
|
|
655
667
|
11. MUST write measurable rules into design-system.md — never vague directives like "modern typography" or "tasteful spacing" (Step 2.9 Rule 4)
|
|
656
668
|
12. MUST NOT use pure `#000` / `#fff` for default text or background, MUST NOT ship lorem ipsum (Step 2.9 Rule 5)
|
|
657
669
|
13. MUST list CJK-capable font FIRST in stack if product targets Chinese/Japanese/Korean (Step 2.9 Rule 6)
|
|
670
|
+
14. MUST list every intentionally inert/placeholder element in `.rune/ui-spec.md` under `## Unwired Elements` (element, location, why unwired, wiring owner) — Placeholder Ownership (Step 2.9 Rule 2)
|
|
658
671
|
|
|
659
672
|
## Mesh Gates (L1/L2 only)
|
|
660
673
|
|
|
@@ -670,6 +683,7 @@ Trading/Fintech — Data-Dense Dark — Web
|
|
|
670
683
|
| oklch-Derivation Gate | All accent variants derived via `oklch(from ...)` | Rewrite manual hex shades as relative oklch |
|
|
671
684
|
| Measurable-Constraints Gate | Every rule in design-system.md is testable (concrete units, hex/oklch, ratios) | Rewrite vague directives as measurable specs (Step 2.9 Rule 4 table) |
|
|
672
685
|
| No-Pure-No-Lorem Gate | No `#000`/`#fff` in semantic tokens; no lorem ipsum in output | Swap to oklch neutrals; replace lorem with real data or labelled placeholder |
|
|
686
|
+
| Placeholder-Ownership Gate | Every inert/placeholder element shipped is listed in `.rune/ui-spec.md` `## Unwired Elements` (element, location, why, wiring owner) | Add the missing rows before reporting done — an unlisted placeholder is a dead element with no owner |
|
|
673
687
|
|
|
674
688
|
## Returns
|
|
675
689
|
|