@rune-kit/rune 2.21.0 → 2.22.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 +5 -1
- package/package.json +4 -3
- package/skills/converge/SKILL.md +33 -6
- package/skills/cook/SKILL.md +2 -1
- package/skills/verification/SKILL.md +7 -5
package/README.md
CHANGED
|
@@ -83,7 +83,11 @@ _Methodology: Claude Code CLI headless mode (`claude -p --output-format json`),
|
|
|
83
83
|
|
|
84
84
|
---
|
|
85
85
|
|
|
86
|
-
## What's New (v2.
|
|
86
|
+
## What's New (v2.22.0 — Convergence, Dogfooded)
|
|
87
|
+
|
|
88
|
+
> **v2.22.0 (2026-07-03):** The v2.21.0 gates went through a live-fire dogfood: fresh executor agents (zero author context) ran `converge` and `verification` Level 3.5 against a fixture with a dead Submit button, a handler-less Export button, a navigation-anchor decoy, and a declared placeholder. **Both gates caught the dead button with file:line evidence and zero false positives** — and the 16 ambiguities the executors reported became spec fixes: converge v0.2.0 adds a `deferred-debt` class (declared design debt can no longer force a false escalation), a `Plan Claims vs Reality` section (tasks marked `[x]` whose code doesn't exist — surfaced first-class), and derived story verdicts; verification v0.7.0 gets FAIL-dominates precedence, per-route reverse checks, and server/static entry-point exemptions. The dogfood fixture itself shipped as the seed of **`npm run eval`** — a behavioral eval harness that runs a fresh headless agent against fixture repos and asserts outcomes, because structural validation can't prove a skill makes an agent behave. Pro `autopilot` v1.6.0 now explicitly runs Phase 6.5 CONVERGE in autonomous mode.
|
|
89
|
+
|
|
90
|
+
### Previous (v2.21.0 — Convergence)
|
|
87
91
|
|
|
88
92
|
> **v2.21.0 (2026-07-03):** Kills the most expensive silent failure in AI-built apps: **the dead button** — UI renders, click does nothing, backend never existed. New `converge` skill (65th) re-reads your spec/plan/contracts as the sole source of intent and scans the ACTUAL code for `missing` / `partial` / `contradicts` / `unrequested` gaps, appending remediation tasks until spec and code converge (`cook` Phase 6.5, max 2 rounds then honest escalation). The whole chain got teeth: `ba` v1.2.0 emits story-sliced specs (P1/P2/P3 priorities, per-story **Independent Test**, **Key Entities**), `plan` v1.7.0 emits **contracts-first boundary artifacts** (`data-model.md` + `contracts/` + `quickstart.md`) with a P1 zero-coverage HARD-GATE and a Data→Logic→Endpoint→UI ordering law (UI is structurally last), `verification` v0.6.0 adds **Level 3.5 INTERACTION WIRED** (traces button → handler → route across React/Svelte/Vue syntax), `completion-gate` v1.9.0 makes the E2E flow trace mandatory for UI+data diffs (single-phase included), and `deploy` v0.8.0 warns before shipping UI+data changes with no wiring evidence. 3 new mesh signals (`convergence.gaps`, `convergence.clean`, `integration.verified`). Every gate is diff-scoped — legacy debt warns, new work fails.
|
|
89
93
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rune-kit/rune",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.22.0",
|
|
4
|
+
"description": "65-skill mesh for AI coding assistants — runtime auto-discipline via native hooks (Claude/Cursor/Windsurf/Antigravity), 5-layer architecture, 204 connections + 43 signals, multi-platform compiler. converge (L3) scans spec vs code so dead-button/frontend-only implementations can't ship.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"rune": "./compiler/bin/rune.js"
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"lint": "biome check .",
|
|
15
15
|
"lint:fix": "biome check --fix .",
|
|
16
16
|
"format": "biome format --write .",
|
|
17
|
-
"ci": "biome check . && node --test compiler/__tests__/*.test.js scripts/__tests__/*.test.js &&
|
|
17
|
+
"ci": "biome check . && node --test compiler/__tests__/*.test.js scripts/__tests__/*.test.js && npm run doctor",
|
|
18
|
+
"eval": "node scripts/run-evals.js",
|
|
18
19
|
"version-check": "node scripts/version-sync-check.js",
|
|
19
20
|
"version-bump": "node scripts/bump-version.js",
|
|
20
21
|
"prepublishOnly": "node scripts/version-sync-check.js"
|
package/skills/converge/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: converge
|
|
|
3
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
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.2.0"
|
|
7
7
|
layer: L3
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: verification
|
|
@@ -50,6 +50,11 @@ Load intent sources (all that exist; requirements.md is mandatory — without it
|
|
|
50
50
|
|
|
51
51
|
The inventory is a flat list of keys: `FR-3`, `US-1/AC-1.2`, `contract:create-order`, `entity:Order`, `decision:<slug>`.
|
|
52
52
|
|
|
53
|
+
Rules:
|
|
54
|
+
- **Task IDs (`P<phase>-T<seq>`) and quickstart.md are EVIDENCE, not verdict keys** — tasks feed the code-scope map (Step 2), quickstart steps feed pass/fail evidence for story rows. Neither gets its own verdict row
|
|
55
|
+
- **US-n verdict is DERIVED**: worst verdict among its `AC-n.m` rows (all ACs implemented → story implemented; any partial/missing → story inherits it). Don't independently re-assess the story
|
|
56
|
+
- **Plan Claims vs Reality**: while reading tasks, note every task marked `[x]` whose artifact is missing/partial in code — these go in a dedicated report section (informational; `completion-gate` owns claim enforcement, converge just surfaces the lie)
|
|
57
|
+
|
|
53
58
|
### Step 2 — Build the Code-Scope Map
|
|
54
59
|
|
|
55
60
|
Map intent → code locations. NO full-repo read — targeted lookups only:
|
|
@@ -78,7 +83,13 @@ element → handler bound? → handler body non-trivial? → calls service/fetch
|
|
|
78
83
|
→ target route/function EXISTS in codebase? → route touches the entity the AC names?
|
|
79
84
|
```
|
|
80
85
|
|
|
81
|
-
First broken link = `partial`, keyed to that element's `US-n/AC-n.m`.
|
|
86
|
+
First broken link = `partial`, keyed to that element's `US-n/AC-n.m`. Heuristics: `onClick={() => {}}`, `href="#"` on action links, `console.log`-only handlers, `preventDefault()`-only submits, `fetch('/api/...')` where no route file matches — all break the chain.
|
|
87
|
+
|
|
88
|
+
**Unwired Elements (declared debt)** — elements listed in `.rune/ui-spec.md` `## Unwired Elements`:
|
|
89
|
+
- Owner of wiring is a task/story IN THIS feature's plan → `missing`, keyed to that story (in-scope debt)
|
|
90
|
+
- Owner is external (asset-creator pass, future feature, human) → **`deferred-debt`**: report in a separate `### Deferred (declared debt)` section, do NOT append a CV task, do NOT count in gap counts, does NOT block `convergence.clean`. Declared debt with a named owner is tracked honesty, not a convergence failure
|
|
91
|
+
|
|
92
|
+
**Precedence**: an element that maps to NO intent key takes the `unrequested` path — the dead-interaction trace runs only for AC-referenced elements.
|
|
82
93
|
|
|
83
94
|
### Step 4 — Assign Severity
|
|
84
95
|
|
|
@@ -104,13 +115,17 @@ Task format: `CV-<round>.<seq> [severity] <imperative> per <intent-key> (<gap-ty
|
|
|
104
115
|
|
|
105
116
|
**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
117
|
|
|
107
|
-
|
|
118
|
+
**No CV tasks for `unrequested` findings** — they are surfaced for human decision (Constraint 6), never converted to work items. **No CV tasks for `deferred-debt`** — the named owner owns it.
|
|
119
|
+
|
|
120
|
+
If ZERO gaps (missing/partial/contradicts on spec keys — deferred-debt and unrequested don't count): write nothing (task file stays byte-identical), emit `convergence.clean`.
|
|
108
121
|
|
|
109
122
|
### Step 6 — Emit Verdict
|
|
110
123
|
|
|
111
|
-
- Gaps found → emit `convergence.gaps` with `{feature, round, counts: {missing, partial, contradicts, unrequested}, critical: N}`
|
|
124
|
+
- Gaps found → emit `convergence.gaps` with `{feature, round, counts: {missing, partial, contradicts, unrequested}, critical: N, cv_tasks: N}`
|
|
112
125
|
- Clean → emit `convergence.clean` with `{feature, round, keys_checked: N}`
|
|
113
126
|
|
|
127
|
+
Payload notes: `counts` are PER-KEY (one absent route can inflate several keys — that's fine for zero-checks, which is all cook needs); `cv_tasks` is the DEDUPED work-item count — consumers judging workload use `cv_tasks` + `critical`, not raw counts.
|
|
128
|
+
|
|
114
129
|
The caller (cook Phase 6.5) executes appended tasks and re-invokes converge — loop until clean, max 2 remediation rounds before escalation.
|
|
115
130
|
|
|
116
131
|
## Output Format
|
|
@@ -119,15 +134,24 @@ The caller (cook Phase 6.5) executes appended tasks and re-invokes converge —
|
|
|
119
134
|
## Convergence Report — <feature> (round N)
|
|
120
135
|
|
|
121
136
|
Intent keys checked: 23 | implemented: 19 | gaps: 4
|
|
137
|
+
(keys checked = spec keys only; unrequested and deferred-debt listed separately below)
|
|
122
138
|
|
|
123
139
|
| Key | Verdict | Severity | Evidence |
|
|
124
140
|
|-----|---------|----------|----------|
|
|
125
141
|
| contract:create-order | missing | CRITICAL | contracts/create-order.md exists; no route matches POST /api/orders (grep: 0 hits in src/) |
|
|
126
142
|
| US-1/AC-1.1 | partial | HIGH | OrderForm.tsx:42 fetch('/api/orders') → route absent |
|
|
127
143
|
| 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
144
|
|
|
130
|
-
|
|
145
|
+
### Unrequested (surfaced, no CV tasks)
|
|
146
|
+
- src/pages/admin-stats.tsx — maps to no story
|
|
147
|
+
|
|
148
|
+
### Deferred (declared debt, no CV tasks)
|
|
149
|
+
- [ ICON: sparkle ] (ui-spec Unwired Elements, owner: asset-creator)
|
|
150
|
+
|
|
151
|
+
### Plan Claims vs Reality
|
|
152
|
+
- P1-T2 marked [x] but POST /api/orders absent — see contract:create-order gap
|
|
153
|
+
|
|
154
|
+
Verdict: 2 gaps blocking P1 → convergence.gaps emitted, 1 task appended (CV-1.1, deduped)
|
|
131
155
|
```
|
|
132
156
|
|
|
133
157
|
Every row needs `file:line` evidence or a grep result count — verdicts without evidence are hallucinations.
|
|
@@ -155,6 +179,9 @@ Every row needs `file:line` evidence or a grep result count — verdicts without
|
|
|
155
179
|
| Fixing the gap itself "since it's small" | HIGH | Converge never edits source — emit the task, let fix own the change |
|
|
156
180
|
| Scanning the whole repo (context blowout) | MEDIUM | Step 2 is targeted Glob/Grep from intent keys — not a repo read |
|
|
157
181
|
| Treating `unrequested` as an error to delete | MEDIUM | Scope creep is surfaced for human decision — it may be wanted, undocumented work |
|
|
182
|
+
| Declared debt (Unwired Elements, external owner) blocks convergence.clean forever | HIGH | deferred-debt class: reported, never a CV task, never blocks clean — a decorative icon must not cause a round-cap escalation |
|
|
183
|
+
| Appending CV tasks for unrequested findings | MEDIUM | Step 5: unrequested = surfaced only; converting scope creep into work items without user decision IS scope creep |
|
|
184
|
+
| Double-assessing US-n independently of its ACs | LOW | Story verdict is derived — worst of its AC rows |
|
|
158
185
|
|
|
159
186
|
## Done When
|
|
160
187
|
|
package/skills/cook/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ context: fork
|
|
|
5
5
|
agent: general-purpose
|
|
6
6
|
metadata:
|
|
7
7
|
author: runedev
|
|
8
|
-
version: "2.6.
|
|
8
|
+
version: "2.6.1"
|
|
9
9
|
layer: L1
|
|
10
10
|
model: sonnet
|
|
11
11
|
group: orchestrator
|
|
@@ -531,6 +531,7 @@ Before entering ANY Phase N+1, assert: Phase N `completed` in TodoWrite | gate c
|
|
|
531
531
|
- Re-run Phase 6 VERIFY on the remediated code, then re-invoke converge (round 2)
|
|
532
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
533
|
4. `unrequested` findings are surfaced to the user in the Cook Report — never silently deleted, never blocking
|
|
534
|
+
5. **Stale CV tasks**: if converge reports clean but unchecked `CV-*` tasks remain from earlier rounds (e.g., rules changed between rounds), cook closes them as `[x] (resolved — superseded)` with a Cook Report note — converge's append-only contract means only cook may touch them
|
|
534
535
|
|
|
535
536
|
<HARD-GATE>
|
|
536
537
|
A P1 story with a CRITICAL convergence gap (missing/contradicts) MUST NOT be committed as "done."
|
|
@@ -3,7 +3,7 @@ name: verification
|
|
|
3
3
|
description: "Universal verification runner. Runs lint, type-check, tests, and build. Use after any code change to verify nothing is broken."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.7.0"
|
|
7
7
|
layer: L3
|
|
8
8
|
model: haiku
|
|
9
9
|
group: validation
|
|
@@ -139,18 +139,20 @@ If ANY stub pattern detected → mark file as STUB, Level 2 FAIL.
|
|
|
139
139
|
|
|
140
140
|
If file has 0 consumers → mark as UNWIRED, Level 3 FAIL.
|
|
141
141
|
|
|
142
|
-
**Exception**: Entry-point files
|
|
142
|
+
**Exception**: Entry-point files are exempt from Level 3 — they ARE the top-level consumers. Entry points include: main.ts/index.ts/App.tsx/routes config, server entrypoints referenced by package.json `main`/`start`/`bin`, and root pages served statically (e.g. `public/index.html` behind `express.static`).
|
|
143
|
+
|
|
144
|
+
**Config/manifest files** (package.json, tsconfig, *.yml, dotfiles): Level 2 = valid, non-empty, matches its schema's basic shape; Level 3 = exempt (consumed by tooling, not imports).
|
|
143
145
|
|
|
144
146
|
**Level 3.5 — INTERACTION WIRED** (UI files in this task's diff only — `.tsx/.jsx/.vue/.svelte/.html`):
|
|
145
147
|
|
|
146
148
|
Level 3 proves the component is *rendered*; Level 3.5 proves its interactive elements *do something*. For each UI file created or modified in this task:
|
|
147
149
|
|
|
148
|
-
1. `Grep` interactive elements in the file — framework-aware patterns: `<button`, `<form`, `type="submit"`, `action=`, plus binding syntax per framework: React `onClick=`/`onSubmit=`, Svelte `on:click=`/`on:submit=`, Vue `@click`/`@submit`/`v-on:`, plain HTML `addEventListener`
|
|
150
|
+
1. `Grep` interactive elements in the file — framework-aware patterns: `<button`, `<form`, `type="submit"`, `action=`, `<a ` with an action-style href (`href="#"`, `href=""`, `javascript:`) — pure-navigation anchors (`href="#section-id"` with a matching id, route paths) are exempt — plus binding syntax per framework: React `onClick=`/`onSubmit=`, Svelte `on:click=`/`on:submit=`, Vue `@click`/`@submit`/`v-on:`, plain HTML `addEventListener`
|
|
149
151
|
2. For each element, trace INWARD:
|
|
150
152
|
- **Handler bound?** Interactive element with NO binding in any framework syntax above and no enclosing form handler → `UNWIRED-INTERACTIVE`. **Prop-origin handlers PASS**: `onClick={props.onSave}`, `on:click={dispatch('save')}`, or a callback-library pattern (`onSubmit={handleSubmit(onSubmit)}` — react-hook-form et al.) count as bound; wiring the prop is the parent's/caller's responsibility, checked at the parent's own 3.5 pass
|
|
151
153
|
- **Handler resolves?** The bound symbol is locally defined OR imported (imported = resolves; do not demand the import's body) and its body is non-trivial (not caught by the Level 2 dead-handler patterns)
|
|
152
154
|
- **Target exists?** If the handler calls `fetch`/`axios`/a service function → the route path or service symbol EXISTS somewhere in the codebase (`Grep` the path/symbol). Handler → nonexistent target = `UNWIRED-INTERACTIVE`. Pure-navigation handlers (`router.push`, `navigate(...)`, framework `<Link>`) PASS — navigation is their target
|
|
153
|
-
3. **Reverse check**: every API route
|
|
155
|
+
3. **Reverse check**: every API route HANDLER created in this task (per-route, not per-file — a file with 3 routes gets 3 checks) has ≥1 caller (`Grep` each route's path across UI/service files). Route with 0 callers → `UNCALLED-ROUTE`
|
|
154
156
|
4. Pure-display elements (no user expectation of action: decorative buttons in mockups explicitly listed in `.rune/ui-spec.md` `## Unwired Elements`) are reported as INFO, not failures — they are design's declared debt, tracked by `converge`
|
|
155
157
|
5. **De-dup**: if preflight already flagged the same element as dead-interactive in this session, cite the cross-reference ("preflight Step 4.5 already flagged") instead of emitting a duplicate finding
|
|
156
158
|
|
|
@@ -327,7 +329,7 @@ When any skill calls verification and then reports results upstream:
|
|
|
327
329
|
3. MUST report specific failures with file:line references
|
|
328
330
|
4. MUST NOT skip checks because "changes are small"
|
|
329
331
|
5. MUST include stdout/stderr capture in every check result — empty output noted explicitly
|
|
330
|
-
6. MUST mark Overall as INCOMPLETE if any check was skipped without valid reason (tool not installed = valid, "changes are small" = invalid)
|
|
332
|
+
6. MUST mark Overall as INCOMPLETE if any check was skipped without valid reason (tool not installed = valid, "changes are small" = invalid). **Precedence**: a 3-Level or Level 3.5 FAIL dominates — Overall = FAIL even when command checks were validly skipped; INCOMPLETE applies only when nothing failed
|
|
331
333
|
7. MUST run the 3-Level Artifact Verification on every file created/modified this task, AND Level 3.5 INTERACTION WIRED on every UI file (`.tsx/.jsx/.vue/.svelte/.html`) in the diff — skip 3.5 only when the diff contains no UI files (note "L3.5: n/a — no UI files")
|
|
332
334
|
|
|
333
335
|
## Sharp Edges
|