@rune-kit/rune 2.8.0 → 2.10.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 +66 -34
- package/agents/adversary.md +27 -0
- package/agents/architect.md +19 -29
- package/agents/asset-creator.md +18 -4
- package/agents/audit.md +25 -4
- package/agents/autopsy.md +19 -4
- package/agents/ba.md +35 -0
- package/agents/brainstorm.md +31 -4
- package/agents/browser-pilot.md +21 -4
- package/agents/coder.md +21 -29
- package/agents/completion-gate.md +20 -4
- package/agents/constraint-check.md +18 -4
- package/agents/context-engine.md +22 -4
- package/agents/context-pack.md +32 -0
- package/agents/cook.md +41 -4
- package/agents/db.md +19 -4
- package/agents/debug.md +33 -4
- package/agents/dependency-doctor.md +20 -4
- package/agents/deploy.md +27 -4
- package/agents/design.md +22 -4
- package/agents/doc-processor.md +27 -0
- package/agents/docs-seeker.md +19 -4
- package/agents/docs.md +31 -0
- package/agents/fix.md +37 -4
- package/agents/git.md +29 -0
- package/agents/hallucination-guard.md +20 -4
- package/agents/incident.md +21 -4
- package/agents/integrity-check.md +18 -4
- package/agents/journal.md +19 -4
- package/agents/launch.md +32 -4
- package/agents/logic-guardian.md +26 -11
- package/agents/marketing.md +23 -4
- package/agents/mcp-builder.md +26 -0
- package/agents/neural-memory.md +30 -0
- package/agents/onboard.md +22 -4
- package/agents/perf.md +21 -4
- package/agents/plan.md +29 -4
- package/agents/preflight.md +22 -4
- package/agents/problem-solver.md +20 -4
- package/agents/rescue.md +23 -4
- package/agents/research.md +19 -4
- package/agents/researcher.md +19 -29
- package/agents/retro.md +32 -0
- package/agents/review-intake.md +20 -4
- package/agents/review.md +32 -4
- package/agents/reviewer.md +20 -28
- package/agents/safeguard.md +19 -4
- package/agents/sast.md +18 -4
- package/agents/scaffold.md +41 -0
- package/agents/scanner.md +19 -28
- package/agents/scope-guard.md +18 -4
- package/agents/scout.md +23 -4
- package/agents/sentinel-env.md +26 -0
- package/agents/sentinel.md +33 -4
- package/agents/sequential-thinking.md +20 -4
- package/agents/session-bridge.md +24 -4
- package/agents/skill-forge.md +22 -4
- package/agents/skill-router.md +26 -4
- package/agents/slides.md +24 -0
- package/agents/surgeon.md +19 -4
- package/agents/team.md +30 -4
- package/agents/test.md +36 -4
- package/agents/trend-scout.md +17 -4
- package/agents/verification.md +20 -4
- package/agents/video-creator.md +20 -4
- package/agents/watchdog.md +19 -4
- package/agents/worktree.md +17 -4
- package/compiler/__tests__/analytics.test.js +370 -0
- package/compiler/adapters/openclaw.js +2 -2
- package/compiler/analytics.js +385 -0
- package/compiler/bin/rune.js +68 -2
- package/compiler/dashboard.js +883 -0
- package/compiler/transforms/branding.js +1 -1
- package/extensions/ui/skills/animation-patterns.md +21 -0
- package/extensions/ui/skills/component-patterns.md +25 -0
- package/extensions/ui/skills/landing-patterns.md +1 -1
- package/hooks/context-watch/index.cjs +95 -68
- package/hooks/metrics-collector/index.cjs +86 -42
- package/hooks/post-session-reflect/index.cjs +41 -5
- package/hooks/session-start/index.cjs +8 -2
- package/package.json +2 -2
- package/skills/audit/SKILL.md +1 -0
- package/skills/autopsy/SKILL.md +78 -2
- package/skills/autopsy/references/repo-analysis-patterns.md +113 -0
- package/skills/ba/SKILL.md +72 -2
- package/skills/brainstorm/SKILL.md +1 -0
- package/skills/cook/SKILL.md +32 -3
- package/skills/cook/references/output-format.md +33 -0
- package/skills/db/SKILL.md +1 -0
- package/skills/debug/SKILL.md +23 -1
- package/skills/deploy/SKILL.md +1 -1
- package/skills/design/SKILL.md +110 -3
- package/skills/docs/SKILL.md +2 -1
- package/skills/fix/SKILL.md +23 -1
- package/skills/graft/SKILL.md +352 -0
- package/skills/graft/references/challenge-framework.md +98 -0
- package/skills/graft/references/mode-decision.md +44 -0
- package/skills/incident/SKILL.md +2 -0
- package/skills/journal/SKILL.md +2 -0
- package/skills/launch/SKILL.md +2 -0
- package/skills/marketing/SKILL.md +46 -2
- package/skills/mcp-builder/SKILL.md +3 -1
- package/skills/mcp-builder/references/auto-discovery-pattern.md +169 -0
- package/skills/plan/SKILL.md +60 -2
- package/skills/plan/references/feature-map.md +84 -0
- package/skills/preflight/SKILL.md +20 -1
- package/skills/rescue/SKILL.md +25 -1
- package/skills/retro/SKILL.md +2 -0
- package/skills/review/SKILL.md +55 -2
- package/skills/scaffold/SKILL.md +1 -0
- package/skills/scope-guard/SKILL.md +35 -17
- package/skills/sentinel/SKILL.md +29 -1
- package/skills/session-bridge/SKILL.md +155 -9
- package/skills/skill-forge/SKILL.md +43 -1
- package/skills/skill-router/{skill.md → SKILL.md} +27 -2
- package/skills/team/SKILL.md +24 -1
- package/skills/test/SKILL.md +29 -2
- package/skills/verification/SKILL.md +1 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# Auto-Discovery Tool Registry Pattern
|
|
2
|
+
|
|
3
|
+
Reference architecture for MCP servers that support partial deployment — tools register automatically at startup, gracefully skipping those with missing API keys.
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
MCP servers with 10+ tools often require 5+ API keys. Requiring ALL keys before the server starts means users can't use any tools until every key is configured. This kills adoption.
|
|
8
|
+
|
|
9
|
+
## Pattern: Scan → Validate → Register
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
tools/
|
|
13
|
+
├── web-search/
|
|
14
|
+
│ └── index.ts # exports: definition, handler, requiredEnvVars
|
|
15
|
+
├── reddit-search/
|
|
16
|
+
│ └── index.ts
|
|
17
|
+
├── youtube-search/
|
|
18
|
+
│ └── index.ts
|
|
19
|
+
└── content-scorer/
|
|
20
|
+
└── index.ts # no requiredEnvVars → always available
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Startup Flow
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// lib/tool-registry.ts
|
|
27
|
+
import { glob } from 'fs';
|
|
28
|
+
|
|
29
|
+
interface ToolModule {
|
|
30
|
+
definition: ToolDefinition;
|
|
31
|
+
handler: (params: unknown) => Promise<unknown>;
|
|
32
|
+
requiredEnvVars?: string[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function discoverTools(toolsDir: string): Promise<Map<string, ToolModule>> {
|
|
36
|
+
const registered = new Map<string, ToolModule>();
|
|
37
|
+
const skipped: string[] = [];
|
|
38
|
+
|
|
39
|
+
const toolDirs = await glob(`${toolsDir}/*/index.ts`);
|
|
40
|
+
|
|
41
|
+
for (const toolPath of toolDirs) {
|
|
42
|
+
const mod: ToolModule = await import(toolPath);
|
|
43
|
+
|
|
44
|
+
// Check env vars — skip if missing
|
|
45
|
+
const missing = (mod.requiredEnvVars ?? [])
|
|
46
|
+
.filter(key => !process.env[key]);
|
|
47
|
+
|
|
48
|
+
if (missing.length > 0) {
|
|
49
|
+
skipped.push(`${mod.definition.name} (missing: ${missing.join(', ')})`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
registered.set(mod.definition.name, mod);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (skipped.length > 0) {
|
|
57
|
+
console.error(`[registry] Skipped ${skipped.length} tools: ${skipped.join('; ')}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.error(`[registry] Registered ${registered.size} tools`);
|
|
61
|
+
return registered;
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Per-Tool Module Contract
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// tools/reddit-search/index.ts
|
|
69
|
+
import { z } from 'zod';
|
|
70
|
+
|
|
71
|
+
export const requiredEnvVars = ['RAPIDAPI_KEY'];
|
|
72
|
+
|
|
73
|
+
export const definition = {
|
|
74
|
+
name: 'reddit_search',
|
|
75
|
+
description: 'Search Reddit posts and comments. Use when researching community sentiment, finding discussions about a topic, or gathering user feedback.',
|
|
76
|
+
inputSchema: z.object({
|
|
77
|
+
query: z.string().describe('Search query'),
|
|
78
|
+
subreddit: z.string().optional().describe('Limit to specific subreddit'),
|
|
79
|
+
sort: z.enum(['hot', 'top', 'new', 'relevance']).default('relevance'),
|
|
80
|
+
time_filter: z.enum(['hour', 'day', 'week', 'month', 'year', 'all']).default('month'),
|
|
81
|
+
limit: z.number().min(1).max(25).default(10),
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export async function handler(params: z.infer<typeof definition.inputSchema>) {
|
|
86
|
+
// Implementation...
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Tools Without API Keys (Always Available)
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// tools/content-scorer/index.ts — no external dependencies
|
|
94
|
+
export const requiredEnvVars = []; // or omit entirely
|
|
95
|
+
|
|
96
|
+
export const definition = {
|
|
97
|
+
name: 'content_scorer',
|
|
98
|
+
description: 'Score content items by engagement with time-decay. Pure computation, no API calls.',
|
|
99
|
+
inputSchema: z.object({
|
|
100
|
+
items: z.array(ContentItemSchema),
|
|
101
|
+
recency_weight: z.number().default(0.1),
|
|
102
|
+
}),
|
|
103
|
+
};
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Key Design Rules
|
|
107
|
+
|
|
108
|
+
### 1. Graceful Degradation (Non-Negotiable)
|
|
109
|
+
- Missing API keys = tool is skipped, NOT a server crash
|
|
110
|
+
- Server MUST boot with 0 API keys configured (local-only tools still work)
|
|
111
|
+
- Log skipped tools to stderr (not stdout — MCP uses stdout for protocol)
|
|
112
|
+
|
|
113
|
+
### 2. Adding New Tools = Zero Core Changes
|
|
114
|
+
- Create `tools/<name>/index.ts` with the module contract
|
|
115
|
+
- Export `definition`, `handler`, and optionally `requiredEnvVars`
|
|
116
|
+
- Registry auto-discovers at next startup
|
|
117
|
+
|
|
118
|
+
### 3. Provider Fallback (Optional, Recommended)
|
|
119
|
+
For tools with multiple data sources, support tiered fallback:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
export const requiredEnvVars = []; // none required — has fallback chain
|
|
123
|
+
|
|
124
|
+
export async function handler(params) {
|
|
125
|
+
// Tier 1: Dedicated API (best quality)
|
|
126
|
+
if (process.env.GETX_API_KEY) {
|
|
127
|
+
return await fetchFromGetXAPI(params);
|
|
128
|
+
}
|
|
129
|
+
// Tier 2: RapidAPI (good quality, shared key)
|
|
130
|
+
if (process.env.RAPIDAPI_KEY) {
|
|
131
|
+
return await fetchFromRapidAPI(params);
|
|
132
|
+
}
|
|
133
|
+
// Tier 3: Web search fallback (approximate)
|
|
134
|
+
return await fetchViaWebSearch(params);
|
|
135
|
+
}
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
Mark output with `data_source: "api" | "web_search" | "mixed"` so downstream consumers know the reliability level.
|
|
139
|
+
|
|
140
|
+
### 4. Status Endpoint
|
|
141
|
+
Expose a `server_status` tool (or MCP resource) that reports which tools are active, which are skipped, and why:
|
|
142
|
+
|
|
143
|
+
```json
|
|
144
|
+
{
|
|
145
|
+
"registered": ["web_search", "content_scorer", "reddit_search"],
|
|
146
|
+
"skipped": [
|
|
147
|
+
{ "tool": "youtube_search", "reason": "Missing YOUTUBE_API_KEY" },
|
|
148
|
+
{ "tool": "linkedin_search", "reason": "Missing RAPIDAPI_KEY" }
|
|
149
|
+
],
|
|
150
|
+
"total": 5,
|
|
151
|
+
"active": 3
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## When to Use This Pattern
|
|
156
|
+
|
|
157
|
+
| Server Type | Use Auto-Discovery? |
|
|
158
|
+
|-------------|-------------------|
|
|
159
|
+
| Single-API wrapper (1-3 tools) | NO — overkill, just require the key |
|
|
160
|
+
| Multi-source aggregator (5+ tools, 3+ APIs) | YES — users rarely have ALL keys |
|
|
161
|
+
| Internal tools (no external APIs) | NO — no env vars to gate on |
|
|
162
|
+
| Plugin system (user adds custom tools) | YES — extensibility is the point |
|
|
163
|
+
|
|
164
|
+
## Anti-Patterns
|
|
165
|
+
|
|
166
|
+
- **Crashing on missing keys** — kills adoption for users who only need 2 of 10 tools
|
|
167
|
+
- **Requiring all keys in .env** — users give up during setup
|
|
168
|
+
- **Silent skip without logging** — users don't know why a tool isn't available
|
|
169
|
+
- **Dynamic import without validation** — malformed tool modules crash the entire server
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -3,13 +3,13 @@ name: plan
|
|
|
3
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 (<150 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.4.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: opus
|
|
9
9
|
group: creation
|
|
10
10
|
tools: "Read, Write, Edit, Glob, Grep"
|
|
11
11
|
emit: plan.ready
|
|
12
|
-
listen: codebase.scanned
|
|
12
|
+
listen: codebase.scanned, project.onboarded, security.blocked
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# plan
|
|
@@ -111,6 +111,7 @@ High-level multi-feature planning — organize features into milestones.
|
|
|
111
111
|
- `ba` (L2): Requirements Document → plan's primary input (locked decisions, user stories)
|
|
112
112
|
- `scout` (L2): codebase analysis → plan's convention/pattern awareness
|
|
113
113
|
- `neural-memory` (external): past architectural decisions → plan's precedent context
|
|
114
|
+
- `sentinel` (L2): repeated security blocks → plan's constraint awareness for future features
|
|
114
115
|
|
|
115
116
|
### Feedback Loops ↻
|
|
116
117
|
|
|
@@ -123,8 +124,12 @@ High-level multi-feature planning — organize features into milestones.
|
|
|
123
124
|
|
|
124
125
|
Check for `.rune/features/*/requirements.md` via `Glob`. If a Requirements Document exists (from `rune:ba`), read it — it contains user stories, acceptance criteria, scope, constraints. Do NOT re-gather what BA already elicited.
|
|
125
126
|
|
|
127
|
+
If `project.onboarded` signal was received, scout output is already available in session context — skip re-invoking scout.
|
|
128
|
+
|
|
126
129
|
Invoke `rune:scout` if not already done — plans without context produce wrong file paths. Call `neural-memory` (Recall Mode) to surface past architecture decisions before making new ones.
|
|
127
130
|
|
|
131
|
+
**Feature Map**: Check for `.rune/features.md` via `Glob`. If it exists, read it — understand the existing feature landscape, dependencies, and known gaps BEFORE planning. Cross-reference: does the new feature overlap, conflict with, or depend on existing features? If `.rune/features.md` does not exist, note this — Step 6.5 will create it.
|
|
132
|
+
|
|
128
133
|
### Step 2 — Classify Complexity
|
|
129
134
|
|
|
130
135
|
Determine inline plan vs master + phase files:
|
|
@@ -201,6 +206,25 @@ When presenting alternatives (from brainstorm or Step 3), rate each **Completene
|
|
|
201
206
|
|
|
202
207
|
Present the **master plan** to user (NOT all phase files). User reviews: phase breakdown, key decisions, risks, completeness scores. Wait for explicit approval ("go", "proceed", "yes") before writing phase files.
|
|
203
208
|
|
|
209
|
+
### Step 6.5 — Update Feature Map (Always)
|
|
210
|
+
<MUST-READ path="references/feature-map.md" trigger="every plan invocation"/>
|
|
211
|
+
|
|
212
|
+
After plan approval, update `.rune/features.md`:
|
|
213
|
+
|
|
214
|
+
**If `.rune/features.md` does NOT exist** (first run):
|
|
215
|
+
1. Reverse-engineer features from scout output — each top-level module = 1 feature
|
|
216
|
+
2. Map inter-feature dependencies from imports and shared types
|
|
217
|
+
3. Assess status per feature (complete, partial, planned)
|
|
218
|
+
4. Generate `.rune/features.md` with Features table, Dependency Graph, Detected Gaps
|
|
219
|
+
|
|
220
|
+
**If `.rune/features.md` exists** (subsequent runs):
|
|
221
|
+
1. Add or update the current feature's row (status, deps, key files)
|
|
222
|
+
2. Cross-reference: new feature resolves existing gaps? Creates new ones?
|
|
223
|
+
3. Validate dependency graph — flag missing features, orphans, circular deps, dead signals
|
|
224
|
+
4. Write updated `.rune/features.md`
|
|
225
|
+
|
|
226
|
+
**Skip if**: Inline plan for trivial task (no feature-level impact).
|
|
227
|
+
|
|
204
228
|
### Step 7 — Execution Handoff
|
|
205
229
|
|
|
206
230
|
```
|
|
@@ -299,6 +323,7 @@ When producing phase files with wave-based task grouping, every task MUST declar
|
|
|
299
323
|
11. MUST include failure scenarios table — what happens when things go wrong
|
|
300
324
|
12. MUST include rejection criteria — explicit "DO NOT" anti-patterns to prevent common mistakes
|
|
301
325
|
13. MUST include cross-phase context — what's assumed from prior phases, what's exported for future
|
|
326
|
+
14. MUST update `.rune/features.md` after every non-trivial plan — feature map is a living artifact
|
|
302
327
|
|
|
303
328
|
## Returns
|
|
304
329
|
|
|
@@ -308,8 +333,35 @@ When producing phase files with wave-based task grouping, every task MUST declar
|
|
|
308
333
|
| Phase files | Markdown | `.rune/plan-<feature>-phase<N>.md` (one per phase) |
|
|
309
334
|
| Feature spec | Markdown | `.rune/features/<name>/spec.md` (Feature Spec Mode only) |
|
|
310
335
|
| Roadmap | Markdown | `.rune/roadmap.md` (Roadmap Mode only) |
|
|
336
|
+
| Feature map | Markdown | `.rune/features.md` (auto-maintained) |
|
|
311
337
|
| Inline plan | Markdown (inline) | Emitted directly for trivial tasks |
|
|
312
338
|
|
|
339
|
+
## Chain Metadata
|
|
340
|
+
|
|
341
|
+
Append to plan output when invoked standalone. Suppress when called as sub-skill inside an L1 orchestrator (cook, team, etc.) — the orchestrator emits a consolidated block. See `docs/references/chain-metadata.md`.
|
|
342
|
+
|
|
343
|
+
```yaml
|
|
344
|
+
chain_metadata:
|
|
345
|
+
skill: "rune:plan"
|
|
346
|
+
version: "1.4.0"
|
|
347
|
+
status: "[DONE | DONE_WITH_CONCERNS | NEEDS_CONTEXT | BLOCKED]"
|
|
348
|
+
domain: "[area planned]"
|
|
349
|
+
files_changed:
|
|
350
|
+
- "[.rune/plan-*.md files created]"
|
|
351
|
+
exports:
|
|
352
|
+
plan_file: "[.rune/plan-<feature>.md path]"
|
|
353
|
+
phase_count: [N]
|
|
354
|
+
estimated_complexity: "[low | medium | high]"
|
|
355
|
+
risk_areas: ["[domains with identified risks]"]
|
|
356
|
+
suggested_next:
|
|
357
|
+
- skill: "rune:adversary"
|
|
358
|
+
reason: "[grounded in plan — e.g., 'Plan touches auth + payments — stress-test assumptions']"
|
|
359
|
+
consumes: ["plan_file", "risk_areas"]
|
|
360
|
+
- skill: "rune:cook"
|
|
361
|
+
reason: "Plan ready for execution"
|
|
362
|
+
consumes: ["plan_file", "phase_count"]
|
|
363
|
+
```
|
|
364
|
+
|
|
313
365
|
## Sharp Edges
|
|
314
366
|
|
|
315
367
|
| Failure Mode | Severity | Mitigation |
|
|
@@ -335,6 +387,8 @@ When producing phase files with wave-based task grouping, every task MUST declar
|
|
|
335
387
|
| Outcome Block "Next Action" is a list, not one action | LOW | One action only — ambiguity about where to start causes re-analysis and lost context |
|
|
336
388
|
| Overlapping file ownership across parallel phases/streams | HIGH | Change Stacking: every task declares `touches[]` — overlap detection flags same file in 2+ tasks before execution |
|
|
337
389
|
| Missing dependency between tasks that share artifacts | HIGH | Every task declares `provides[]` and `requires[]` — cycle detection + missing dep check before dispatch |
|
|
390
|
+
| New feature planned without checking existing feature map | HIGH | Step 1 reads `.rune/features.md` — catches overlaps, conflicts, and missing dependencies before planning begins |
|
|
391
|
+
| Feature map never created — gaps accumulate silently | MEDIUM | Step 6.5 always runs (create or update) — feature map grows organically with each plan invocation |
|
|
338
392
|
|
|
339
393
|
## Self-Validation
|
|
340
394
|
|
|
@@ -346,6 +400,8 @@ SELF-VALIDATION (run before presenting plan to user):
|
|
|
346
400
|
- [ ] Phase files have ALL Amateur-Proof sections (data flow, code contracts, failure scenarios, rejection criteria)
|
|
347
401
|
- [ ] Locked decisions from BA are reflected in plan — none contradicted or ignored
|
|
348
402
|
- [ ] Every BA requirement has a corresponding Req ID in at least one phase's Traceability Matrix
|
|
403
|
+
- [ ] `.rune/features.md` updated with current feature (or created if first run)
|
|
404
|
+
- [ ] No cross-feature conflicts detected (or flagged to user if found)
|
|
349
405
|
```
|
|
350
406
|
|
|
351
407
|
## Done When
|
|
@@ -364,6 +420,8 @@ SELF-VALIDATION (run before presenting plan to user):
|
|
|
364
420
|
- Self-Validation: all checks passed
|
|
365
421
|
- Outcome Block present in every plan output (master plan, phase files, inline plan)
|
|
366
422
|
- Outcome Block contains: What Was Planned + Immediate Next Action (single action) + How to Measure table
|
|
423
|
+
- `.rune/features.md` created (first run) or updated (subsequent) with current feature
|
|
424
|
+
- Cross-feature dependencies validated — no conflicts or orphans left unaddressed
|
|
367
425
|
|
|
368
426
|
## Cost Profile
|
|
369
427
|
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Feature Map
|
|
2
|
+
|
|
3
|
+
Living document that grows with each plan invocation. Provides bird's-eye view of all features, their dependencies, and detected gaps.
|
|
4
|
+
|
|
5
|
+
## Location
|
|
6
|
+
|
|
7
|
+
`.rune/features.md` — auto-created on first plan run, updated on every subsequent run.
|
|
8
|
+
|
|
9
|
+
## Format
|
|
10
|
+
|
|
11
|
+
```markdown
|
|
12
|
+
# Feature Map
|
|
13
|
+
<!-- Auto-maintained by rune:plan. Do not edit manually. -->
|
|
14
|
+
<!-- Last updated: YYYY-MM-DD -->
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
| Feature | Status | Depends On | Consumed By | Key Files | Gaps |
|
|
19
|
+
|---------|--------|-----------|-------------|-----------|------|
|
|
20
|
+
| Auth | ✅ | Database, Email | Dashboard, API | src/auth/* | No 2FA |
|
|
21
|
+
| Dashboard | 🔄 70% | Auth, Analytics | — | src/dashboard/* | No export |
|
|
22
|
+
|
|
23
|
+
## Dependency Graph
|
|
24
|
+
|
|
25
|
+
<!-- ASCII or mermaid — keep under 20 lines -->
|
|
26
|
+
Auth ──→ Dashboard
|
|
27
|
+
│ ↑
|
|
28
|
+
└──→ API ─┘
|
|
29
|
+
Database ──→ Auth
|
|
30
|
+
|
|
31
|
+
## Detected Gaps
|
|
32
|
+
|
|
33
|
+
- [ ] Auth → Payments: dependency missing (payments needs auth but not wired)
|
|
34
|
+
- [ ] Dashboard depends on Analytics but Analytics not in feature map
|
|
35
|
+
- [ ] Email: single consumer — fragile if auth changes notification strategy
|
|
36
|
+
|
|
37
|
+
## Signals
|
|
38
|
+
|
|
39
|
+
- [ ] Feature X emits event.Y but no feature listens
|
|
40
|
+
- [ ] Feature Z listens for event.W but no feature emits it
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Feature Detection (First Run)
|
|
44
|
+
|
|
45
|
+
When `.rune/features.md` does not exist, reverse-engineer from codebase:
|
|
46
|
+
|
|
47
|
+
1. **Read scout output** — directory structure, modules, entry points
|
|
48
|
+
2. **Identify features** — each top-level module or bounded context = 1 feature
|
|
49
|
+
3. **Map dependencies** — imports between modules, shared types, API calls
|
|
50
|
+
4. **Assess status** — has tests? has docs? complete or partial?
|
|
51
|
+
5. **Write `.rune/features.md`** with detected features
|
|
52
|
+
|
|
53
|
+
Detection heuristics:
|
|
54
|
+
- `src/<name>/` or `app/<name>/` directories → likely features
|
|
55
|
+
- Route files (pages/, routes/, api/) → user-facing features
|
|
56
|
+
- Shared directories (utils/, lib/, shared/) → NOT features, but dependencies
|
|
57
|
+
- Package.json workspaces → monorepo features
|
|
58
|
+
|
|
59
|
+
## Feature Update (Subsequent Runs)
|
|
60
|
+
|
|
61
|
+
When `.rune/features.md` exists, update incrementally:
|
|
62
|
+
|
|
63
|
+
1. **Read existing map** — current features, deps, gaps
|
|
64
|
+
2. **Check new feature** — does the feature being planned already exist in map?
|
|
65
|
+
- Yes → update status, deps, gaps
|
|
66
|
+
- No → add new row
|
|
67
|
+
3. **Cross-reference** — does new feature create/resolve any gaps?
|
|
68
|
+
- New dependency on existing feature → add to Depends On
|
|
69
|
+
- New feature fills a gap → mark gap resolved
|
|
70
|
+
- New feature creates orphan → add to Detected Gaps
|
|
71
|
+
4. **Write updated `.rune/features.md`**
|
|
72
|
+
|
|
73
|
+
## Gap Detection Rules
|
|
74
|
+
|
|
75
|
+
| Pattern | Gap Type | Severity |
|
|
76
|
+
|---------|----------|----------|
|
|
77
|
+
| Feature A depends on B, but B not in map | Missing feature | HIGH |
|
|
78
|
+
| Feature A has no consumers (nothing depends on it) | Orphan feature | MEDIUM |
|
|
79
|
+
| Feature A emits signal but nothing listens | Dead signal | MEDIUM |
|
|
80
|
+
| Feature A listens for signal but nothing emits | Missing producer | HIGH |
|
|
81
|
+
| Two features both write to same data store | Write conflict | HIGH |
|
|
82
|
+
| Feature has no tests | Quality gap | MEDIUM |
|
|
83
|
+
| Feature depends on deprecated module | Tech debt | LOW |
|
|
84
|
+
| Circular dependency: A → B → A | Coupling issue | HIGH |
|
|
@@ -3,7 +3,7 @@ name: preflight
|
|
|
3
3
|
description: Pre-commit quality gate that catches "almost right" code. Goes beyond linting — checks logic correctness, error handling, regressions, and completeness.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.8.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: quality
|
|
@@ -208,6 +208,7 @@ If a domain hook flags BLOCK, the overall preflight verdict is BLOCK regardless
|
|
|
208
208
|
| `openapi.*`, `*.graphql`, `*.proto` | API Contract | Breaking changes flagged, version bumped, deprecated fields documented |
|
|
209
209
|
| `docs/policies/*`, `PRIVACY*`, `TERMS*` | Legal/Compliance | No placeholder text, review date current, practice matches policy |
|
|
210
210
|
| `**/billing*`, `**/payment*`, `**/invoice*` | Financial | Decimal precision correct, currency locale-aware, no hardcoded rates |
|
|
211
|
+
| `*.tsx`, `*.jsx`, `*.svelte`, `*.vue`, `components/*` | UI/Frontend | Design token compliance, animation a11y, touch targets, visual hierarchy |
|
|
211
212
|
| `skills/*/SKILL.md`, `extensions/*/PACK.md` | Rune Skill | Frontmatter valid, all required sections present, word count within layer budget |
|
|
212
213
|
| `*.test.*`, `*.spec.*`, `__tests__/*` | Test Quality | No `.skip`/`.only` left in, assertions present (not empty tests), no hardcoded timeouts |
|
|
213
214
|
|
|
@@ -221,6 +222,24 @@ For each detected domain, run its checks on the relevant files in the diff:
|
|
|
221
222
|
4. **Classify** findings: BLOCK (data loss risk, breaking contract) or WARN (best practice, incomplete)
|
|
222
223
|
5. **Append** to preflight report under `### Domain Quality` section
|
|
223
224
|
|
|
225
|
+
#### UI/Frontend Domain Checks
|
|
226
|
+
|
|
227
|
+
When UI/Frontend hook is triggered, run these checks on all `.tsx`/`.jsx`/`.svelte`/`.vue` files in the diff:
|
|
228
|
+
|
|
229
|
+
| Check | What to Scan | Severity |
|
|
230
|
+
|-------|-------------|----------|
|
|
231
|
+
| **Design token compliance** | Hardcoded colors (`#fff`, `rgb(`, `hsl(`) instead of CSS variables or Tailwind tokens | WARN: "Hardcoded color at {file}:{line} — use design token" |
|
|
232
|
+
| **UI-SPEC drift** | If `.rune/ui-spec.md` exists, compare component decisions (card style, form layout, nav type) against spec | BLOCK: "Component at {file} uses bordered cards but UI-SPEC locks elevated cards" |
|
|
233
|
+
| **Animation accessibility** | Animations/transitions without `prefers-reduced-motion` guard | WARN: "Animation at {file}:{line} missing reduced-motion check" |
|
|
234
|
+
| **Touch target size** | Interactive elements with explicit small sizing (`w-5 h-5`, `p-0.5` on buttons/links) < 44×44px | WARN: "Touch target too small at {file}:{line}" |
|
|
235
|
+
| **Missing states** | Components fetching data without loading/error/empty states | WARN: "Async component at {file} missing [loading|error|empty] state" |
|
|
236
|
+
| **Icon accessibility** | Decorative icons without `aria-hidden="true"`, functional icons without `aria-label` | WARN: "Icon at {file}:{line} missing aria attribute" |
|
|
237
|
+
| **Inline styles** | `style={{` or `style=` attribute usage instead of classes/tokens | WARN: "Inline style at {file}:{line} — use CSS class or Tailwind" |
|
|
238
|
+
| **Font loading** | Custom font imports without `font-display: swap` or Next.js font optimization | WARN: "Font at {file} may cause layout shift — add font-display: swap" |
|
|
239
|
+
| **Placeholder content** | Strings like "Lorem ipsum", "TODO", "placeholder", "test text" in JSX/template | BLOCK: "Placeholder content at {file}:{line} — replace before shipping" |
|
|
240
|
+
|
|
241
|
+
**Skip if**: Diff contains only test files, config files, or non-UI code (detected by absence of JSX/template syntax).
|
|
242
|
+
|
|
224
243
|
#### Pack Integration
|
|
225
244
|
|
|
226
245
|
When a domain pack is installed (e.g., `@rune-pro/finance`, `@rune-pro/legal`), preflight checks the pack's **Hard-Stop Thresholds** table and applies matching rules to staged files. This means:
|
package/skills/rescue/SKILL.md
CHANGED
|
@@ -5,7 +5,7 @@ context: fork
|
|
|
5
5
|
agent: general-purpose
|
|
6
6
|
metadata:
|
|
7
7
|
author: runedev
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.4.0"
|
|
9
9
|
layer: L1
|
|
10
10
|
model: sonnet
|
|
11
11
|
group: orchestrator
|
|
@@ -34,6 +34,7 @@ Legacy refactoring orchestrator for safely modernizing messy codebases. Rescue r
|
|
|
34
34
|
- `autopsy` (L2): Phase 0 RECON — full codebase health assessment
|
|
35
35
|
- `safeguard` (L2): Phase 1 SAFETY NET — characterization tests and protective measures
|
|
36
36
|
- `surgeon` (L2): Phase 2-N SURGERY — incremental refactoring (1 module per session)
|
|
37
|
+
- `retro` (L2): post-rescue retrospective — capture lessons learned
|
|
37
38
|
- `journal` (L3): state tracking across rescue sessions
|
|
38
39
|
- `plan` (L2): create refactoring plan based on autopsy findings
|
|
39
40
|
- `review` (L2): verify each surgery phase
|
|
@@ -424,6 +425,29 @@ Rollback point: git tag rune-rescue-baseline (set in Phase 0)
|
|
|
424
425
|
| Health score comparison | Inline (Rescue Report) | Baseline vs final autopsy scores |
|
|
425
426
|
| Rescue Report | Markdown (inline) | Emitted at session end (per module and final) |
|
|
426
427
|
|
|
428
|
+
## Document Ownership
|
|
429
|
+
|
|
430
|
+
| Scope | Access | Files |
|
|
431
|
+
|-------|--------|-------|
|
|
432
|
+
| **Owns** (read + write) | `RESCUE-STATE.md`, `.rune/rescue-*.md`, git tags (`rune-rescue-*`), refactored source files (one module per session) |
|
|
433
|
+
| **Reads** (never writes) | `CLAUDE.md`, autopsy reports, safeguard test files, `.rune/contract.md` |
|
|
434
|
+
| **Never modifies** | Test files written by `safeguard` (characterization tests are the safety net — rescue reads them, never edits), `compiler/**`, `SKILL.md` files |
|
|
435
|
+
|
|
436
|
+
Rescue delegates to `surgeon` for actual code changes and `safeguard` for test creation. Rescue owns the orchestration state, not the artifacts.
|
|
437
|
+
|
|
438
|
+
## Anti-Patterns
|
|
439
|
+
|
|
440
|
+
Common legacy refactoring failures. These turn "rescue" into "make it worse."
|
|
441
|
+
|
|
442
|
+
| Anti-Pattern | Why It Fails | Correct Approach |
|
|
443
|
+
|---|---|---|
|
|
444
|
+
| **Big bang refactor** — rewriting everything at once | No rollback path. One bug = entire refactor is broken | One module per session. Commit + verify after each module |
|
|
445
|
+
| **Surgery without safety net** — refactoring before characterization tests exist | No way to verify behavior is preserved. "It compiles" ≠ "it works" | HARD-GATE: safeguard tests must pass BEFORE any surgery begins |
|
|
446
|
+
| **Coupled module surgery** — refactoring two interdependent modules simultaneously | Changes in module A break module B mid-surgery. Neither is stable | One module per session. Stabilize A completely before touching B |
|
|
447
|
+
| **Ignoring the autopsy** — starting refactoring without understanding current health | Fixes symptoms not causes. Wastes effort on low-impact modules | Phase 0 autopsy is mandatory. Surgery queue ordered by impact, not convenience |
|
|
448
|
+
| **Prototype patterns in production** — replacing legacy code with quick-and-dirty rewrites | Creates new legacy. The "rescue" becomes the next rescue target | Apply proven refactoring patterns from autopsy recommendations. Clean code, not fast code |
|
|
449
|
+
| **No rollback point** — surgery without a tagged baseline | If surgery goes wrong, no safe state to return to | `git tag rune-rescue-baseline` before ANY code changes |
|
|
450
|
+
|
|
427
451
|
## Sharp Edges
|
|
428
452
|
|
|
429
453
|
Known failure modes for this skill. Check these before declaring done.
|
package/skills/retro/SKILL.md
CHANGED
|
@@ -41,6 +41,8 @@ Retro is ENCOURAGING but CANDID. Every critique is anchored in specific commits,
|
|
|
41
41
|
|
|
42
42
|
- `audit` (L2): engineering velocity and health dimension
|
|
43
43
|
- `cook` (L1): optional — after completing a multi-phase feature, suggest retro
|
|
44
|
+
- `rescue` (L1): post-rescue retrospective
|
|
45
|
+
- `launch` (L1): post-launch retrospective
|
|
44
46
|
- User: `/rune retro` direct invocation
|
|
45
47
|
|
|
46
48
|
## Data Flow
|
package/skills/review/SKILL.md
CHANGED
|
@@ -3,13 +3,13 @@ name: review
|
|
|
3
3
|
description: Code quality review — patterns, security, performance, correctness. Finds bugs, suggests improvements, triggers fix for issues found. Escalates to opus for security-critical code.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.8.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: development
|
|
10
10
|
tools: "Read, Glob, Grep"
|
|
11
11
|
emit: review.complete, review.issues
|
|
12
|
-
listen: code.changed
|
|
12
|
+
listen: code.changed, docs.updated
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
# review
|
|
@@ -204,6 +204,36 @@ Identify gaps in test coverage.
|
|
|
204
204
|
- If untested code found: call `rune:test` with specific instructions on what to test
|
|
205
205
|
- Flag as HIGH if business logic is untested, MEDIUM if utility code is untested
|
|
206
206
|
|
|
207
|
+
#### Per-Function Test Gap Analysis
|
|
208
|
+
|
|
209
|
+
Go beyond "test file exists" — check coverage at function granularity:
|
|
210
|
+
|
|
211
|
+
1. **Extract changed functions** — from the diff, list every function/method that was added or modified (name + file:line)
|
|
212
|
+
2. **Map to test assertions** — for each changed function, Grep the test file for its name. Count distinct test cases (look for `it(`, `test(`, `describe(` blocks that reference the function)
|
|
213
|
+
3. **Classify gap severity**:
|
|
214
|
+
|
|
215
|
+
| Function Type | 0 tests | 1 test | 2+ tests |
|
|
216
|
+
|--------------|---------|--------|----------|
|
|
217
|
+
| Business logic (money, auth, state) | BLOCK | WARN: "only happy path" | PASS |
|
|
218
|
+
| Data transform (parse, format, map) | HIGH | PASS | PASS |
|
|
219
|
+
| Event handler (onClick, onSubmit) | MEDIUM | PASS | PASS |
|
|
220
|
+
| Pure utility (string, math, date) | MEDIUM | PASS | PASS |
|
|
221
|
+
|
|
222
|
+
4. **Output per-function table** in review report:
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
### Test Gap Analysis
|
|
226
|
+
| Function | File | Tests Found | Verdict |
|
|
227
|
+
|----------|------|-------------|---------|
|
|
228
|
+
| calculateTotal | src/billing.ts:42 | 3 (happy, zero, overflow) | PASS |
|
|
229
|
+
| processRefund | src/billing.ts:89 | 0 | BLOCK — business logic untested |
|
|
230
|
+
| formatCurrency | src/utils.ts:12 | 1 | PASS |
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
5. **Flag untested edge cases** — for functions with only 1 test, check if the test covers: empty/null input, boundary values, error path. If only happy path → WARN: "only happy path tested for {function}"
|
|
234
|
+
|
|
235
|
+
**Skip if**: Diff only touches config, docs, styles, or test files themselves.
|
|
236
|
+
|
|
207
237
|
### Step 5.5: Two-Stage Review Gate
|
|
208
238
|
|
|
209
239
|
Separate spec compliance from code quality. Most reviews conflate both — this gate forces the distinction.
|
|
@@ -503,6 +533,29 @@ When `cook` or `ship` checks review status: compare review commit hash with curr
|
|
|
503
533
|
| Composite quality score | Markdown table | inline (when `mode: "scored"`) |
|
|
504
534
|
| Blast radius assessment | Markdown table | inline |
|
|
505
535
|
|
|
536
|
+
## Chain Metadata
|
|
537
|
+
|
|
538
|
+
Append to Code Review Report when invoked standalone. Suppress when called as sub-skill inside an L1 orchestrator (cook, team, etc.) — the orchestrator emits a consolidated block. See `docs/references/chain-metadata.md`.
|
|
539
|
+
|
|
540
|
+
```yaml
|
|
541
|
+
chain_metadata:
|
|
542
|
+
skill: "rune:review"
|
|
543
|
+
version: "0.8.0"
|
|
544
|
+
status: "[DONE | DONE_WITH_CONCERNS]"
|
|
545
|
+
domain: "[area reviewed]"
|
|
546
|
+
files_changed: [] # review doesn't change files
|
|
547
|
+
exports:
|
|
548
|
+
findings_count: { critical: [N], high: [N], medium: [N], low: [N] }
|
|
549
|
+
findings:
|
|
550
|
+
- { severity: "[level]", file: "[path]", line: [N], message: "[issue]" }
|
|
551
|
+
verdict: "[APPROVE | REQUEST_CHANGES | NEEDS_DISCUSSION]"
|
|
552
|
+
quality_score: [0-100] # when mode: "scored"
|
|
553
|
+
suggested_next:
|
|
554
|
+
- skill: "rune:fix"
|
|
555
|
+
reason: "[grounded in findings — e.g., '2 HIGH findings in api/users.ts need remediation']"
|
|
556
|
+
consumes: ["findings"]
|
|
557
|
+
```
|
|
558
|
+
|
|
506
559
|
## Sharp Edges
|
|
507
560
|
|
|
508
561
|
| Failure Mode | Severity | Mitigation |
|
package/skills/scaffold/SKILL.md
CHANGED
|
@@ -33,6 +33,7 @@ Generated projects MUST build and pass tests. A scaffold that produces broken co
|
|
|
33
33
|
- `research` (L3): Phase 2 — best practices, starter templates, library comparison
|
|
34
34
|
- `plan` (L2): Phase 3 — architecture and implementation plan
|
|
35
35
|
- `design` (L2): Phase 4 — design system (frontend projects only)
|
|
36
|
+
- `skill-forge` (L2): when scaffolded project includes custom skills or plugin structure
|
|
36
37
|
- `fix` (L2): Phase 5 — code generation (implements the plan)
|
|
37
38
|
- `team` (L1): Phase 5 — parallel implementation when 3+ independent modules
|
|
38
39
|
- `test` (L2): Phase 6 — test suite generation
|