@rune-kit/rune 2.12.3 → 2.14.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 +41 -7
- package/compiler/__tests__/adr-scoring.test.js +91 -0
- package/compiler/__tests__/context-md-format.test.js +180 -0
- package/compiler/__tests__/context-pack-smell-tests.test.js +215 -0
- package/compiler/__tests__/diversity-score.test.js +117 -0
- package/compiler/__tests__/improve-architecture.test.js +171 -0
- package/compiler/__tests__/openclaw-adapter.test.js +31 -0
- package/compiler/__tests__/out-of-scope-format.test.js +303 -0
- package/compiler/__tests__/zoom-out-output.test.js +112 -0
- package/compiler/adapters/openclaw.js +43 -3
- package/package.json +2 -2
- package/skills/adversary/SKILL.md +1 -1
- package/skills/audit/SKILL.md +1 -0
- package/skills/autopsy/SKILL.md +1 -1
- package/skills/ba/SKILL.md +241 -82
- package/skills/ba/references/context-md-format.md +136 -0
- package/skills/ba/references/explore-first.md +107 -0
- package/skills/ba/references/out-of-scope-format.md +152 -0
- package/skills/brainstorm/SKILL.md +77 -1
- package/skills/brainstorm/references/design-it-twice.md +155 -0
- package/skills/context-pack/SKILL.md +69 -26
- package/skills/context-pack/evals.md +122 -0
- package/skills/context-pack/references/brief-template.md +121 -0
- package/skills/context-pack/references/durability-rules.md +109 -0
- package/skills/cook/SKILL.md +4 -4
- package/skills/debug/SKILL.md +2 -1
- package/skills/fix/SKILL.md +2 -1
- package/skills/graft/SKILL.md +1 -1
- package/skills/improve-architecture/SKILL.md +275 -0
- package/skills/improve-architecture/evals.md +145 -0
- package/skills/improve-architecture/references/deepening.md +87 -0
- package/skills/improve-architecture/references/interface-design.md +68 -0
- package/skills/improve-architecture/references/language.md +81 -0
- package/skills/improve-architecture/references/scoring.md +122 -0
- package/skills/journal/SKILL.md +34 -7
- package/skills/journal/references/adr-criteria.md +109 -0
- package/skills/marketing/SKILL.md +2 -1
- package/skills/review/SKILL.md +1 -0
- package/skills/review-intake/SKILL.md +25 -2
- package/skills/safeguard/SKILL.md +1 -1
- package/skills/scout/SKILL.md +33 -1
- package/skills/sentinel-env/SKILL.md +24 -13
- package/skills/skill-forge/SKILL.md +108 -1
- package/skills/surgeon/SKILL.md +17 -2
- package/skills/test/SKILL.md +48 -1
- package/skills/test/evals.md +137 -0
- package/skills/test/references/mocking-policy.md +121 -0
- package/skills/test/references/test-quality.md +124 -0
- package/skills/test/references/vertical-tdd.md +110 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# Language
|
|
2
|
+
|
|
3
|
+
Shared vocabulary every output of this skill uses. These eight terms are precise. Substitutes ("component", "service", "API", "boundary", "layer") are banned in skill output because they carry baggage from other paradigms (DDD, microservices, n-tier).
|
|
4
|
+
|
|
5
|
+
## Terms
|
|
6
|
+
|
|
7
|
+
### Module
|
|
8
|
+
Anything with an interface and an implementation. Scale-agnostic on purpose: a function, a class, a package, or a tier-spanning slice can each be a module.
|
|
9
|
+
*Avoid*: unit, component, service.
|
|
10
|
+
|
|
11
|
+
### Interface
|
|
12
|
+
Everything a caller must know to use the module correctly. Includes the type signature plus invariants, ordering constraints, error modes, required configuration, and performance characteristics.
|
|
13
|
+
*Avoid*: API, signature (those refer only to the type-level surface).
|
|
14
|
+
|
|
15
|
+
### Implementation
|
|
16
|
+
The body of code inside the module. Distinct from **adapter**: a thing can be a small adapter with a large implementation (a Postgres repo) or a large adapter with a small implementation (an in-memory fake).
|
|
17
|
+
|
|
18
|
+
### Depth
|
|
19
|
+
Leverage at the interface — how much behavior a caller can exercise per unit of interface they have to learn.
|
|
20
|
+
- **Deep**: large behavior, small interface.
|
|
21
|
+
- **Shallow**: interface nearly as complex as the implementation (often a wrapper or pass-through).
|
|
22
|
+
|
|
23
|
+
Numeric scoring rubric (1–5):
|
|
24
|
+
| Score | Interface Complexity vs Implementation |
|
|
25
|
+
|-------|----------------------------------------|
|
|
26
|
+
| 1 | Wrapper / pass-through (interface ≈ impl) |
|
|
27
|
+
| 2 | Thin (interface > 50% of impl) |
|
|
28
|
+
| 3 | Modest (interface ≈ 1/3 of impl) |
|
|
29
|
+
| 4 | Deep (interface ≈ 1/5 of impl) |
|
|
30
|
+
| 5 | Very deep (interface ≪ impl) |
|
|
31
|
+
|
|
32
|
+
### Seam *(from Michael Feathers)*
|
|
33
|
+
A place where you can alter behavior without editing in that place. The *location* of an interface. Choosing where to put the seam is its own design decision, distinct from what goes behind it.
|
|
34
|
+
*Avoid*: boundary (overloaded with DDD's bounded context).
|
|
35
|
+
|
|
36
|
+
### Adapter
|
|
37
|
+
A concrete thing that satisfies an interface at a seam. Describes role (what slot it fills), not substance (what's inside).
|
|
38
|
+
|
|
39
|
+
### Leverage
|
|
40
|
+
What callers get from depth. More capability per unit of interface they have to learn. One implementation pays back across N call sites and M tests.
|
|
41
|
+
|
|
42
|
+
### Locality
|
|
43
|
+
What maintainers get from depth. Change, bugs, knowledge, and verification concentrate at one place rather than spreading across callers. Fix once, fixed everywhere.
|
|
44
|
+
|
|
45
|
+
## Principles
|
|
46
|
+
|
|
47
|
+
### Depth is a property of the interface, not the implementation
|
|
48
|
+
A deep module can be internally composed of small, mockable, swappable parts — they just aren't part of the interface. A module can have **internal seams** (private to its implementation, used by its own tests) as well as the **external seam** at its public interface.
|
|
49
|
+
|
|
50
|
+
### The deletion test
|
|
51
|
+
Imagine deleting the module.
|
|
52
|
+
- If complexity vanishes, the module wasn't hiding anything — it was a pass-through. Verdict: `vanish`.
|
|
53
|
+
- If complexity reappears across N callers, the module was earning its keep. Verdict: `concentrate`.
|
|
54
|
+
- If complexity moves to some callers and dissolves at others — verdict: `redistribute`. Common case for partially-deepened modules.
|
|
55
|
+
|
|
56
|
+
### The interface is the test surface
|
|
57
|
+
Callers and tests cross the same seam. If you want to test *past* the interface (peek at internal state, count internal calls), the module is the wrong shape — not the test.
|
|
58
|
+
|
|
59
|
+
### One adapter is hypothetical, two are real
|
|
60
|
+
Don't introduce a port unless something actually varies across it (typically prod + test). A single-adapter seam is just indirection that costs comprehension without buying flexibility.
|
|
61
|
+
|
|
62
|
+
## Relationships
|
|
63
|
+
|
|
64
|
+
- A **Module** has exactly one **Interface** (its public surface).
|
|
65
|
+
- **Depth** is a property of a **Module**, measured against its **Interface**.
|
|
66
|
+
- A **Seam** is where a **Module**'s **Interface** lives.
|
|
67
|
+
- An **Adapter** sits at a **Seam** and satisfies the **Interface**.
|
|
68
|
+
- **Depth** produces **Leverage** for callers and **Locality** for maintainers.
|
|
69
|
+
|
|
70
|
+
## Banned framings (and why)
|
|
71
|
+
|
|
72
|
+
- **Depth as ratio of impl-lines to interface-lines** — rewards padding the implementation. Use depth-as-leverage instead.
|
|
73
|
+
- **"Interface" as the TypeScript `interface` keyword or a class's public methods** — too narrow. Interface here includes every fact a caller must know, including invariants and error modes.
|
|
74
|
+
- **"Boundary"** — overloaded with DDD's bounded context. Say *seam* or *interface* instead.
|
|
75
|
+
- **"Component"** — UI-centric. Use *module*.
|
|
76
|
+
- **"Service"** — microservice-centric. Use *module*.
|
|
77
|
+
- **"Layer"** — too generic, often confused with horizontal n-tier slicing. Use *module* + *seam*.
|
|
78
|
+
|
|
79
|
+
## Vocabulary discipline (mechanical check)
|
|
80
|
+
|
|
81
|
+
The compiler test `compiler/__tests__/vocabulary-discipline.test.js` greps this skill's body and references for the banned aliases. Any hit fails the build. Fix by substituting the precise term.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Scoring Rubric
|
|
2
|
+
|
|
3
|
+
Numeric scoring is the value-add. Soft prose ("this looks shallow") doesn't compose. Numeric scores let `surgeon`, `audit`, `review` gate decisions programmatically.
|
|
4
|
+
|
|
5
|
+
Three metrics + one verdict per candidate.
|
|
6
|
+
|
|
7
|
+
## Depth (1–5)
|
|
8
|
+
|
|
9
|
+
Measures how much behavior the interface hides.
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
depth = clamp_1_5( implementation_complexity / interface_complexity )
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Interface complexity** — count of unique entry points (functions / methods) × average parameter count. Plus penalty (+1) for each invariant or ordering rule a caller must remember.
|
|
16
|
+
|
|
17
|
+
**Implementation complexity** — total LOC inside the module + count of distinct branches + count of distinct internal collaborators.
|
|
18
|
+
|
|
19
|
+
| Score | Description | Example |
|
|
20
|
+
|-------|-------------|---------|
|
|
21
|
+
| 1 | Wrapper / pass-through; interface ≈ impl | `getUserName(u) => u.name` |
|
|
22
|
+
| 2 | Thin; interface > 50% of impl | Function that does light validation + delegates |
|
|
23
|
+
| 3 | Modest; interface ≈ 1/3 of impl | Module with 5 methods over 200 LOC of state-machine logic |
|
|
24
|
+
| 4 | Deep; interface ≈ 1/5 of impl | Port with 3 methods over 800 LOC of state machine |
|
|
25
|
+
| 5 | Very deep; interface ≪ impl | Single-method JIT compiler interface |
|
|
26
|
+
|
|
27
|
+
## Leverage (1–5)
|
|
28
|
+
|
|
29
|
+
Measures caller benefit — how much capability callers get per unit of interface they have to learn.
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
leverage = clamp_1_5( num_callers * unique_use_cases / interface_method_count )
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| Score | Description | Example |
|
|
36
|
+
|-------|-------------|---------|
|
|
37
|
+
| 1 | Few callers, many methods to learn | 1 caller, 8-method object |
|
|
38
|
+
| 2 | Modest reach per surface | 3 callers, 5 methods |
|
|
39
|
+
| 3 | Balanced | 10 callers, 4 methods |
|
|
40
|
+
| 4 | Strong leverage | 30 callers, 3 methods |
|
|
41
|
+
| 5 | Exceptional leverage | 100+ callers, 1-2 methods |
|
|
42
|
+
|
|
43
|
+
Edge cases:
|
|
44
|
+
- Internal-only modules (callers all in same package) — score capped at 4 unless used by multiple packages.
|
|
45
|
+
- External public API — leverage is per-consumer; cap at 5 because ecosystem reach is exponential.
|
|
46
|
+
|
|
47
|
+
## Locality (1–5)
|
|
48
|
+
|
|
49
|
+
Measures maintainer benefit — where change/bugs concentrate.
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
locality = clamp_1_5( code_concentration_index )
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`code_concentration_index` ≈ 5 - (entropy of where related logic lives). Pragmatic scoring:
|
|
56
|
+
|
|
57
|
+
| Score | Description |
|
|
58
|
+
|-------|-------------|
|
|
59
|
+
| 1 | Logic spread across N callers; "fix once, fix N times" |
|
|
60
|
+
| 2 | Logic in 2-3 modules; some duplication |
|
|
61
|
+
| 3 | Logic mostly in one module, some leakage |
|
|
62
|
+
| 4 | Logic concentrated in one module; clear single source |
|
|
63
|
+
| 5 | Logic in one module AND callers don't reimplement it |
|
|
64
|
+
|
|
65
|
+
## Deletion test (verdict, not score)
|
|
66
|
+
|
|
67
|
+
Imagine deleting the module. What happens to the codebase?
|
|
68
|
+
|
|
69
|
+
| Verdict | Meaning |
|
|
70
|
+
|---------|---------|
|
|
71
|
+
| `vanish` | Complexity disappears; module was a pass-through. Often accompanies depth ≤ 2. Action: delete entirely, inline at callers, OR deepen by absorbing more responsibility. |
|
|
72
|
+
| `concentrate` | Complexity reappears across N callers. Module was earning its keep. Action: KEEP. May still benefit from deepening if depth < 4. |
|
|
73
|
+
| `redistribute` | Complexity moves — some absorbed by callers, some dissolved. Common case for partially-shallow modules. Action: deepen (most likely target) OR refine into a smaller, more focused module. |
|
|
74
|
+
|
|
75
|
+
## Aggregate score (architecture sub-score)
|
|
76
|
+
|
|
77
|
+
For a target module, the aggregate is:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
candidate_score = depth + leverage + locality # 3-15
|
|
81
|
+
sub_score_contribution = (candidate_score / 15) * 100 # 0-100 normalized
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`audit` may aggregate across many candidates by averaging sub-score contributions weighted by callers (modules with more callers have more architectural impact).
|
|
85
|
+
|
|
86
|
+
## Score gating (used by other skills)
|
|
87
|
+
|
|
88
|
+
| Score Range | Interpretation | Suggested Action |
|
|
89
|
+
|-------------|----------------|------------------|
|
|
90
|
+
| 12-15 | Already deep; small gains possible | Skip deepening; tag as "healthy" |
|
|
91
|
+
| 8-11 | Modest; deepening yields measurable gain | Candidate for `surgeon` |
|
|
92
|
+
| 3-7 | Shallow; high-priority deepening target | Strong recommendation; flag in `audit` |
|
|
93
|
+
| 0-2 | Pass-through or wrapper; consider deletion | Verify with deletion test before delete |
|
|
94
|
+
|
|
95
|
+
## Worked scoring example
|
|
96
|
+
|
|
97
|
+
Module: `src/auth/login.ts`
|
|
98
|
+
- 1 function `login(email, password) → SessionToken | null`
|
|
99
|
+
- 30 LOC, 3 branches, calls `db.users.get` + `crypto.compare`
|
|
100
|
+
- Used by 4 routes
|
|
101
|
+
|
|
102
|
+
Calculate:
|
|
103
|
+
- Interface complexity: 1 entry × 2 params = 2; +0 invariants → 2
|
|
104
|
+
- Implementation complexity: 30 LOC + 3 branches + 2 collaborators = ~35
|
|
105
|
+
- Depth: clamp_1_5(35/2 ÷ 5) ≈ 3 (modest, not very deep)
|
|
106
|
+
- Leverage: clamp_1_5(4 callers × 1 use case / 1 method) = 4 (strong leverage already!)
|
|
107
|
+
- Locality: 5 (logic in one file)
|
|
108
|
+
- Deletion test: concentrate (deleting it scatters auth across 4 routes)
|
|
109
|
+
|
|
110
|
+
Aggregate: 3 + 4 + 5 = **12 / 15** = "healthy". Improvement effort better spent elsewhere.
|
|
111
|
+
|
|
112
|
+
The single-function "login" was actually fine. The shallowness signal might come from `login + refresh + logout` being three separate small modules — score them as a candidate cluster, not individually.
|
|
113
|
+
|
|
114
|
+
## Cluster scoring
|
|
115
|
+
|
|
116
|
+
When the friction is a cluster of related shallow modules (auth, session, refresh), score the *cluster as a single hypothetical deepened module*:
|
|
117
|
+
|
|
118
|
+
- Depth: what the deepened interface would be
|
|
119
|
+
- Leverage: callers across all current modules combined / new method count
|
|
120
|
+
- Locality: maintainer benefit if all logic concentrated
|
|
121
|
+
|
|
122
|
+
The current state's score is the *baseline*; the cluster score is the *target*. Delta = potential gain.
|
package/skills/journal/SKILL.md
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: journal
|
|
3
|
-
description: Persistent state tracking and Architecture Decision Records across sessions. Manages progress state, module health, dependency graphs, and ADRs for any workflow.
|
|
3
|
+
description: Persistent state tracking and Architecture Decision Records across sessions. Use when recording a decision, ADR, or progress that must survive session boundaries. Manages progress state, module health, dependency graphs, and ADRs for any workflow.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.4.0"
|
|
7
7
|
layer: L3
|
|
8
8
|
model: haiku
|
|
9
9
|
group: state
|
|
@@ -38,6 +38,7 @@ None — pure L3 state management utility.
|
|
|
38
38
|
- `skill-forge` (L2): record skill creation decisions and rationale
|
|
39
39
|
- `graft` (L2): auto-log graft operations — source URL, mode, challenge score, files changed
|
|
40
40
|
- `retro` (L2): record retrospective insights and decisions
|
|
41
|
+
- `improve-architecture` (L2): record an ADR when the user rejects a deepening candidate with a load-bearing reason
|
|
41
42
|
|
|
42
43
|
## Files Managed
|
|
43
44
|
|
|
@@ -82,11 +83,32 @@ Use `Write` to save the updated `module-status.json`.
|
|
|
82
83
|
|
|
83
84
|
Use `Edit` to update the relevant lines in `RESCUE-STATE.md` (current phase, current module, counts of completed vs pending).
|
|
84
85
|
|
|
85
|
-
### Step 3 — Record decisions
|
|
86
|
+
### Step 3 — Record decisions (gated by 3-criteria scoring)
|
|
86
87
|
|
|
87
88
|
For each architectural decision or trade-off made during this session (applies to any workflow — feature development, deploy, rescue, audit):
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
#### Step 3.0 — Score the decision
|
|
91
|
+
|
|
92
|
+
Compute three numeric scores (1–5 each) before opening any ADR file. See [references/adr-criteria.md](references/adr-criteria.md) for full rubric.
|
|
93
|
+
|
|
94
|
+
| Axis | What it measures |
|
|
95
|
+
|------|------------------|
|
|
96
|
+
| `reversibility` | 1 = next-sprint reversible; 5 = practically irreversible |
|
|
97
|
+
| `surprisingness` | 1 = obvious to any reader; 5 = future engineer would "fix" without context |
|
|
98
|
+
| `tradeoff_strength` | 1 = no real alternative; 5 = genuinely difficult choice |
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
score = reversibility + surprisingness + tradeoff_strength # range 3–15
|
|
102
|
+
open_adr = (score >= 11) AND (each axis >= 3)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Step 3.1 — Counter-test (anti-fake)
|
|
106
|
+
|
|
107
|
+
Before writing the ADR, fill in **at least one rejected alternative + why**. If no credible alternative was actually considered, the decision wasn't a real tradeoff — re-classify as a **convention** (record in CLAUDE.md or comment, not in `.rune/adr/`) and skip ADR creation.
|
|
108
|
+
|
|
109
|
+
#### Step 3.2 — Open the ADR (if gate passed)
|
|
110
|
+
|
|
111
|
+
1. Generate filename including the score: `.rune/adr/ADR-[NNN]-[slug]-s[score].md` where NNN is sequential and `score` is the 3–15 sum (e.g., `ADR-007-postgres-write-model-s13.md`)
|
|
90
112
|
2. Use `Write` to create the ADR file with this format:
|
|
91
113
|
|
|
92
114
|
```markdown
|
|
@@ -96,6 +118,7 @@ For each architectural decision or trade-off made during this session (applies t
|
|
|
96
118
|
**Status**: Accepted
|
|
97
119
|
**Workflow**: [rescue | cook | deploy | audit | other]
|
|
98
120
|
**Scope**: [affected module, feature, or system area]
|
|
121
|
+
**Score**: reversibility=[1-5] / surprisingness=[1-5] / tradeoff_strength=[1-5] / total=[3-15]
|
|
99
122
|
|
|
100
123
|
## Context
|
|
101
124
|
[Why this decision was needed — what problem or trade-off prompted it]
|
|
@@ -109,8 +132,8 @@ For each architectural decision or trade-off made during this session (applies t
|
|
|
109
132
|
## Consequences
|
|
110
133
|
[Impact on files/modules/future work — include rollback path if relevant]
|
|
111
134
|
|
|
112
|
-
## Rejected Alternatives
|
|
113
|
-
[List what was considered but NOT chosen, and why. This prevents future sessions from re-visiting dead ends.]
|
|
135
|
+
## Rejected Alternatives (counter-test — MUST have at least one)
|
|
136
|
+
[List what was considered but NOT chosen, and why. This prevents future sessions from re-visiting dead ends. If you cannot fill in this section, the decision wasn't a real tradeoff — DO NOT open this ADR.]
|
|
114
137
|
- **[Alternative A]**: Rejected because [specific reason — constraint, performance, complexity]
|
|
115
138
|
- **[Alternative B]**: Rejected because [specific reason]. May reconsider if [condition changes].
|
|
116
139
|
```
|
|
@@ -226,10 +249,14 @@ Known failure modes for this skill. Check these before declaring done.
|
|
|
226
249
|
| RESCUE-STATE.md initialized without content when called from non-rescue workflows | MEDIUM | If caller is not rescue/surgeon, skip RESCUE-STATE.md initialization — use progress.md instead |
|
|
227
250
|
| Overwriting human-written ADR content on re-run | CRITICAL | MUST check if ADR-[NNN].md exists before writing — never overwrite, increment NNN |
|
|
228
251
|
| Empty ADR Rationale field ("decided to use X") | MEDIUM | Constraint 1 blocks this — re-prompt for rationale before writing |
|
|
252
|
+
| Opening an ADR for a decision that scores below threshold (sum < 11 or any axis < 3) | HIGH | Step 3.0 gate — if score fails, classify as "convention" and record in CLAUDE.md instead |
|
|
253
|
+
| Score inflation to reach threshold | MEDIUM | Step 3.1 counter-test — must name a credible rejected alternative; cannot be faked |
|
|
254
|
+
| ADR for a deferral ("we'll do X later") | MEDIUM | Deferrals are not decisions; route to backlog or `.out-of-scope/` (if rejection) |
|
|
229
255
|
|
|
230
256
|
## Done When
|
|
231
257
|
|
|
232
|
-
- All decisions from the session recorded as ADR files
|
|
258
|
+
- All decisions from the session that pass the 3-criteria gate (sum >= 11, each axis >= 3, counter-test filled) recorded as ADR files
|
|
259
|
+
- Decisions failing the gate classified as conventions (logged in CLAUDE.md or code comment, NOT in `.rune/adr/`)
|
|
233
260
|
- All identified risks recorded as RISK files with severity, mitigation, and trigger conditions
|
|
234
261
|
- Progress state updated (module status, phase, or deploy event as appropriate)
|
|
235
262
|
- Dependency graph updated if module relationships changed
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# ADR Criteria — When to Open an ADR
|
|
2
|
+
|
|
3
|
+
ADRs (Architecture Decision Records) are durable. They survive sessions, codebases, and team turnover. That power has a cost: writing one for every minor pick fills the directory with noise, and the genuinely load-bearing decisions get lost.
|
|
4
|
+
|
|
5
|
+
The ADR gate ensures that every entry in `.rune/adr/` *earned* its place.
|
|
6
|
+
|
|
7
|
+
## The 3-criteria gate
|
|
8
|
+
|
|
9
|
+
An ADR is offered only if **all three** are true:
|
|
10
|
+
|
|
11
|
+
### 1. Hard to reverse (`reversibility`)
|
|
12
|
+
|
|
13
|
+
Score 1–5: how expensive is it to change your mind later?
|
|
14
|
+
|
|
15
|
+
| Score | Description |
|
|
16
|
+
|-------|-------------|
|
|
17
|
+
| 1 | Reversible next sprint (one PR, no migration) |
|
|
18
|
+
| 2 | Reversible this quarter (a few PRs, simple migration) |
|
|
19
|
+
| 3 | Significant cost (data migration, multi-PR rollout) |
|
|
20
|
+
| 4 | Quarter-or-more to reverse (schema change, integration rewrite) |
|
|
21
|
+
| 5 | Practically irreversible (architectural commitment, lock-in to vendor) |
|
|
22
|
+
|
|
23
|
+
### 2. Surprising without context (`surprisingness`)
|
|
24
|
+
|
|
25
|
+
Score 1–5: how likely is a future reader to wonder "why did they do it this way?"
|
|
26
|
+
|
|
27
|
+
| Score | Description |
|
|
28
|
+
|-------|-------------|
|
|
29
|
+
| 1 | Obvious — anyone would do it this way |
|
|
30
|
+
| 2 | Common, but with one minor detail |
|
|
31
|
+
| 3 | Mildly unusual — half of practitioners might pick differently |
|
|
32
|
+
| 4 | Strongly counter to common practice |
|
|
33
|
+
| 5 | Rare or counter-intuitive — without explanation, future engineer would "fix" it |
|
|
34
|
+
|
|
35
|
+
### 3. Real tradeoff (`tradeoff_strength`)
|
|
36
|
+
|
|
37
|
+
Score 1–5: how credible were the rejected alternatives?
|
|
38
|
+
|
|
39
|
+
| Score | Description |
|
|
40
|
+
|-------|-------------|
|
|
41
|
+
| 1 | No real alternative — the obvious thing |
|
|
42
|
+
| 2 | One alternative considered briefly |
|
|
43
|
+
| 3 | 2–3 alternatives evaluated; pick was clear |
|
|
44
|
+
| 4 | Multiple credible alternatives; pick required real analysis |
|
|
45
|
+
| 5 | Genuinely difficult choice; reasonable people disagreed |
|
|
46
|
+
|
|
47
|
+
### Threshold
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
score = reversibility + surprisingness + tradeoff_strength # range 3–15
|
|
51
|
+
open_adr = (score >= 11) AND (each axis >= 3)
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The "each axis >= 3" rule prevents single-axis cheating. A decision that's hard-to-reverse but obvious AND has no real alternatives (e.g., "we're using SQL for our SQL database") shouldn't be an ADR even if reversibility=5.
|
|
55
|
+
|
|
56
|
+
## Counter-test (anti-fake)
|
|
57
|
+
|
|
58
|
+
Before opening an ADR, the agent MUST be able to fill in **rejected alternatives + why**. If the agent can't name at least one credible alternative *that was actually considered*, the decision wasn't a real tradeoff. Re-classify as a "convention" — record it in CLAUDE.md or a comment, not in `.rune/adr/`.
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
Rejected alternative: PostgreSQL JSON columns
|
|
62
|
+
Why rejected: schema migrations harder; no JSON-path indexing in the version we use; team's tooling stack favors structured columns.
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If you can't write that section, don't open the ADR.
|
|
66
|
+
|
|
67
|
+
## ADR file naming
|
|
68
|
+
|
|
69
|
+
Filename includes the score, so future reviewers see at a glance why this one was kept:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
.rune/adr/ADR-007-postgres-write-model-s13.md
|
|
73
|
+
.rune/adr/ADR-008-event-sourced-orders-s14.md
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Format: `ADR-NNN-<slug>-s<score>.md` where `NNN` is the sequential number and `score` is the 3–15 sum.
|
|
77
|
+
|
|
78
|
+
## What qualifies (examples)
|
|
79
|
+
|
|
80
|
+
- **Architectural shape**: "We're using a monorepo." "The write model is event-sourced; the read model is projected into Postgres." (s ≈ 12–14)
|
|
81
|
+
- **Integration patterns between modules**: "Ordering and Billing communicate via domain events, not synchronous HTTP." (s ≈ 11–13)
|
|
82
|
+
- **Technology choices that carry lock-in**: database, message bus, auth provider, deployment target — only the ones that would take a quarter to swap out. (s ≈ 11–14)
|
|
83
|
+
- **Boundary-and-scope decisions**: "Customer data is owned by the Customer module; other modules reference it by ID only." The explicit no-s are as valuable as the yes-s. (s ≈ 10–12 — borderline, judge case-by-case)
|
|
84
|
+
- **Deliberate deviations from the obvious path**: "We're using manual SQL instead of an ORM because X." (s ≈ 11–13 — high surprisingness)
|
|
85
|
+
- **Constraints not visible in the code**: "We can't use AWS because of compliance requirements." (s ≈ 11–13)
|
|
86
|
+
- **Rejected alternatives when the rejection is non-obvious**: considered GraphQL, picked REST for subtle reasons. (s ≈ 10–12 — if rejection is documented elsewhere, may not need ADR)
|
|
87
|
+
|
|
88
|
+
## What does NOT qualify (examples)
|
|
89
|
+
|
|
90
|
+
- "We chose lodash over underscore." (reversibility ≤ 2; not surprising; weak tradeoff) — s ≈ 5
|
|
91
|
+
- "This function uses async/await instead of Promises." (reversibility 1; not surprising; convention) — s ≈ 3
|
|
92
|
+
- "We're using TypeScript." (reversibility 5; not surprising; obvious for the stack) — s ≈ 7
|
|
93
|
+
- "We deferred dark mode." (this is a deferral, not a decision — goes to backlog or `.out-of-scope/`) — N/A
|
|
94
|
+
|
|
95
|
+
## When score is 8–10 (borderline)
|
|
96
|
+
|
|
97
|
+
Don't auto-open. Ask the user: "This decision scores 9/15 — borderline. Do you want it as an ADR, or is a comment in the code sufficient?" Default to the lighter touch.
|
|
98
|
+
|
|
99
|
+
## Score gaming detection
|
|
100
|
+
|
|
101
|
+
The score can be inflated, but the counter-test (rejected alternative) cannot be faked without lying about history. If the agent fills out scores ≥ 4 on each axis but can't name a credible rejected alternative, the gate fails and no ADR is opened.
|
|
102
|
+
|
|
103
|
+
`audit` later cross-references ADR scores — if the average score across `.rune/adr/` files is < 11, it flags "ADR inflation" as a quality concern.
|
|
104
|
+
|
|
105
|
+
## Convention vs Decision
|
|
106
|
+
|
|
107
|
+
Decisions are tradeoffs at fork points. **Conventions are choices everyone makes the same way** — naming, formatting, simple defaults. Conventions go in CLAUDE.md or code style guides, not ADRs.
|
|
108
|
+
|
|
109
|
+
A test: if you can imagine the team coming back next quarter and saying "yeah obvious, of course we did it this way" — it's a convention. If they'd say "wait, why did we do *that*?" — it's a decision and probably qualifies.
|
|
@@ -3,11 +3,12 @@ name: marketing
|
|
|
3
3
|
description: Create marketing assets and execute launch strategy. Generates landing copy, social banners, SEO meta, blog posts, and video scripts.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: delivery
|
|
10
10
|
tools: "Read, Write, Edit, Glob, Grep, WebFetch, WebSearch"
|
|
11
|
+
emit: media.request
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
# marketing
|
package/skills/review/SKILL.md
CHANGED
|
@@ -60,6 +60,7 @@ Every review MUST cite at least one specific concern, suggestion, or explicit ap
|
|
|
60
60
|
- `review` → `test` — untested edge case found → test writes it
|
|
61
61
|
- `review` → `fix` — bug found during review → fix applies correction
|
|
62
62
|
- `review` → `scout` — needs more context → scout finds related code
|
|
63
|
+
- `review` → `improve-architecture` — when reviewer flag mentions "shallow", "wrapper", "indirection", or pass-through pattern
|
|
63
64
|
- `review` ← `fix` — complex fix requests self-review
|
|
64
65
|
- `review` → `sentinel` — security-critical code → sentinel deep scan
|
|
65
66
|
|
|
@@ -3,11 +3,12 @@ name: review-intake
|
|
|
3
3
|
description: Use when receiving code review feedback, PR comments, or external suggestions before implementing any changes. Prevents blind implementation, enforces verification-first discipline.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "1.
|
|
6
|
+
version: "1.2.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: sonnet
|
|
9
9
|
group: quality
|
|
10
|
-
tools: "Read, Glob, Grep"
|
|
10
|
+
tools: "Read, Write, Edit, Glob, Grep"
|
|
11
|
+
listen: outofscope.match
|
|
11
12
|
---
|
|
12
13
|
|
|
13
14
|
# review-intake
|
|
@@ -137,6 +138,24 @@ gh api repos/{owner}/{repo}/pulls/{pr}/comments/{id}/replies \
|
|
|
137
138
|
-f body="Fixed — [description]"
|
|
138
139
|
```
|
|
139
140
|
|
|
141
|
+
### Phase 4.5 — Rejection KB Write (when verdict = OUT OF SCOPE)
|
|
142
|
+
|
|
143
|
+
For every item with verdict `OUT OF SCOPE`, write a durable record to `.out-of-scope/`. Oral-only rejections leave no trace and force re-litigation in future sessions.
|
|
144
|
+
|
|
145
|
+
<HARD-GATE>
|
|
146
|
+
Every OUT OF SCOPE verdict MUST produce a `.out-of-scope/<slug>.md` file (or append to an existing one).
|
|
147
|
+
A rejection without a written record is a rejection that didn't happen.
|
|
148
|
+
</HARD-GATE>
|
|
149
|
+
|
|
150
|
+
**Procedure**:
|
|
151
|
+
|
|
152
|
+
1. Generate `slug` from the rejected concept (kebab-case, lowercase, max 40 chars, recognizable without opening the file).
|
|
153
|
+
2. Lexical-similarity check: `Glob` `.out-of-scope/*.md`, parse each frontmatter's `concept` + `aliases`, compute overlap with the new slug's tokens. If any existing concept has ≥0.7 overlap → APPEND to that file's `prior_requests` list instead of creating a new one.
|
|
154
|
+
3. If new file: write the format from [`ba/references/out-of-scope-format.md`](../ba/references/out-of-scope-format.md) — YAML frontmatter (concept / aliases / decision: rejected / rejected_at / rejected_by: review-intake / prior_requests / revisit_if) + Markdown body (concept name, "Why out of scope" reasoning, "What would change our mind" signals).
|
|
155
|
+
4. The reasoning MUST be substantive — not "we don't want this" but *why*. Reference project scope, technical constraints, or strategic decisions. Reject deferrals ("we're busy") — those don't belong here.
|
|
156
|
+
|
|
157
|
+
Only **enhancement** rejections produce `.out-of-scope/` entries. Bug rejections (won't fix because already fixed / not reproducible / not a bug) get a comment on the issue, not a KB file.
|
|
158
|
+
|
|
140
159
|
### Phase 6 — IMPLEMENT
|
|
141
160
|
|
|
142
161
|
Execute in priority order: P0 → P1 → P2 → P3 → P4.
|
|
@@ -223,6 +242,9 @@ How to push back:
|
|
|
223
242
|
| Implementing 4/6 items, leaving 2 unclear | HIGH | HARD-GATE: all-or-nothing comprehension |
|
|
224
243
|
| Performative agreement masking misunderstanding | MEDIUM | Banned phrases list + restate-in-own-words requirement |
|
|
225
244
|
| Fixing tests instead of code to make review pass | HIGH | Defer to `fix` constraints: fix CODE, not TESTS |
|
|
245
|
+
| OUT OF SCOPE verdict with no `.out-of-scope/` file written | HIGH | Phase 4.5 HARD-GATE — oral-only rejections force re-litigation in future sessions |
|
|
246
|
+
| Writing a deferral ("busy this quarter") to `.out-of-scope/` | MEDIUM | Deferrals belong in backlog, not the rejection KB. KB entries must cite durable reasons (scope, tech constraint, strategy) |
|
|
247
|
+
| Creating duplicate `.out-of-scope/` files for the same concept | MEDIUM | Lexical-similarity gate (≥0.7 overlap) — append to existing file's `prior_requests` instead of duplicating |
|
|
226
248
|
|
|
227
249
|
## Done When
|
|
228
250
|
|
|
@@ -231,6 +253,7 @@ How to push back:
|
|
|
231
253
|
- Verdicts assigned (correct/pushback/yagni/defer)
|
|
232
254
|
- Approved items implemented in priority order
|
|
233
255
|
- Tests pass after each individual fix
|
|
256
|
+
- Every OUT OF SCOPE verdict has produced a `.out-of-scope/<slug>.md` file (new or appended)
|
|
234
257
|
- Review Intake Report emitted
|
|
235
258
|
|
|
236
259
|
## Returns
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: safeguard
|
|
3
|
-
description: Build safety nets before refactoring. Creates characterization tests, boundary markers, config freezes, and rollback points.
|
|
3
|
+
description: Build safety nets before refactoring. Use when running surgeon or any risky refactor that needs a rollback point. Creates characterization tests, boundary markers, config freezes, and rollback points.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
6
|
version: "0.2.0"
|
package/skills/scout/SKILL.md
CHANGED
|
@@ -3,12 +3,13 @@ name: scout
|
|
|
3
3
|
description: "Fast codebase scanner. Use when any skill needs codebase context. Finds files, patterns, dependencies, project structure. Pure read-only — never modifies files."
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.4.0"
|
|
7
7
|
layer: L2
|
|
8
8
|
model: haiku
|
|
9
9
|
group: creation
|
|
10
10
|
tools: "Read, Glob, Grep"
|
|
11
11
|
emit: codebase.scanned
|
|
12
|
+
listen: agent.stuck
|
|
12
13
|
---
|
|
13
14
|
|
|
14
15
|
# scout
|
|
@@ -117,6 +118,36 @@ Scout's default is "max 10 file reads" — but the real question is whether addi
|
|
|
117
118
|
3. Find existing tests with `Glob`: `**/*.test.*`, `**/*.spec.*`, `**/test_*`
|
|
118
119
|
4. Determine test framework: `jest.config.*`, `vitest.config.*`, `pytest.ini`
|
|
119
120
|
|
|
121
|
+
### Phase 4.5: Zoom-Out Mode
|
|
122
|
+
|
|
123
|
+
Triggered by `mode="zoom-out"` from the caller, OR auto-triggered by listening on `agent.stuck` signal (emitted by `fix` after 2+ failed attempts on the same file, or by `debug` after 3+ disproved hypothesis cycles).
|
|
124
|
+
|
|
125
|
+
When activated, scout produces a 3-layer ascent map:
|
|
126
|
+
|
|
127
|
+
| Layer | What it includes | Cap |
|
|
128
|
+
|-------|------------------|-----|
|
|
129
|
+
| L0 (target) | The stuck file's symbols + immediate imports | unlimited |
|
|
130
|
+
| L1 (siblings) | Files in the same directory + their public exports | 8 files |
|
|
131
|
+
| L2 (callers/neighbors) | Modules that import L0's exports + neighboring modules in the same domain | 8 modules |
|
|
132
|
+
|
|
133
|
+
Output is a Mermaid diagram, NOT just a file list — visual is the value-add when an agent is stuck.
|
|
134
|
+
|
|
135
|
+
```mermaid
|
|
136
|
+
graph LR
|
|
137
|
+
target[src/auth/login.ts]:::stuck
|
|
138
|
+
target --> dep1[crypto.compare]
|
|
139
|
+
target --> dep2[db.users.get]
|
|
140
|
+
caller1[src/routes/auth.ts] --> target
|
|
141
|
+
caller2[src/middleware/protect.ts] --> target
|
|
142
|
+
sibling1[src/auth/refresh.ts] -.same-dir.- target
|
|
143
|
+
sibling2[src/auth/logout.ts] -.same-dir.- target
|
|
144
|
+
classDef stuck fill:#ff6b6b
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
**Bounded** — L2 ascent caps at 8 modules. If exceeded, collapse to "showing top 8 by import-frequency". Never blow past the cap silently.
|
|
148
|
+
|
|
149
|
+
After emitting the map, scout returns to its normal Phase 6 (Generate Report) with the zoom-out section as the primary output.
|
|
150
|
+
|
|
120
151
|
### Phase 5: Codebase Map (Optional)
|
|
121
152
|
|
|
122
153
|
When called by `cook`, `team`, `onboard`, or `autopsy` (skills that need full project understanding), generate a structured codebase map:
|
|
@@ -204,6 +235,7 @@ None — pure scanner using Glob, Grep, Read, and Bash tools directly. Does not
|
|
|
204
235
|
- `docs` (L2): scan codebase structure for documentation generation
|
|
205
236
|
- `logic-guardian` (L2): scan business logic modules for protection mapping
|
|
206
237
|
- `adversary` (L2): scan codebase before red-team analysis
|
|
238
|
+
- `improve-architecture` (L2): re-scan target module + callers when input context is stale
|
|
207
239
|
|
|
208
240
|
## Output Format
|
|
209
241
|
|
|
@@ -3,7 +3,7 @@ name: sentinel-env
|
|
|
3
3
|
description: Environment-aware pre-flight check. Validates OS, runtime versions, installed tools, port availability, env vars, and disk space BEFORE coding starts. Prevents "works on my machine" failures. Like sentinel but for the environment, not the code.
|
|
4
4
|
metadata:
|
|
5
5
|
author: runedev
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.3.0"
|
|
7
7
|
layer: L3
|
|
8
8
|
model: haiku
|
|
9
9
|
group: validation
|
|
@@ -117,25 +117,36 @@ Detect and verify tools the project depends on:
|
|
|
117
117
|
- `Grep` for `subprocess.run(`, `child_process.exec(`, `Deno.Command(` → project invokes external CLI
|
|
118
118
|
- `Read` README/docs for "requires X installed" or "depends on X"
|
|
119
119
|
|
|
120
|
-
For each detected hard dependency
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
For each detected hard dependency, apply the **9-tier binary detection** below — checking only `which`/`where` is insufficient and produces the largest category of "works on my machine" false-negatives (user has binary installed but PATH is stale, or installed via a package manager that didn't register it, or installed as a desktop app with a bundled binary).
|
|
121
|
+
|
|
122
|
+
**9-Tier Binary Detection** (stop at first hit):
|
|
123
|
+
|
|
124
|
+
| Tier | Source | Catches |
|
|
125
|
+
|------|--------|---------|
|
|
126
|
+
| 1 | Explicit `--<tool>-bin <path>` flag | CI, automation, manual override |
|
|
127
|
+
| 2 | Skill-specific env var `<SKILL>_<TOOL>_BIN` | Per-project pinning |
|
|
128
|
+
| 3 | Tool-family env var `<TOOL>_APP_BIN` | Ecosystem conventions |
|
|
129
|
+
| 4 | Generic tool env var `<TOOL>_BIN` | Legacy overrides |
|
|
130
|
+
| 5 | Platform desktop-app bundle (macOS `.app/Contents/Resources`, Windows `%LOCALAPPDATA%\Programs`, Linux `/opt`) | Desktop app users (~40% of population) |
|
|
131
|
+
| 6 | PATH lookup (`which`/`where.exe`) | Standard shell users |
|
|
132
|
+
| 7 | Package manager global bin (`npm config get prefix`, `pnpm`, `pipx --list`, `cargo install --root`) | npm-global on Windows (PATH oversight) |
|
|
133
|
+
| 8 | Platform common directories (`~/.local/bin`, `~/.npm-global/bin`, Homebrew, `%APPDATA%\npm`, `%LOCALAPPDATA%\Microsoft\WindowsApps`, `%ProgramFiles%\nodejs`) | Manual installers |
|
|
134
|
+
| 9 | Platform release archive names (e.g., `codex-x86_64-unknown-linux-musl`, `<tool>-aarch64-apple-darwin`) | Release-tarball downloaders |
|
|
127
135
|
|
|
128
136
|
**Verdict:**
|
|
129
|
-
- Tool found
|
|
130
|
-
- Tool NOT found → **BLOCK** with
|
|
137
|
+
- Tool found via any tier → PASS (log which tier + version)
|
|
138
|
+
- Tool NOT found → **BLOCK** with per-OS install guidance:
|
|
131
139
|
```
|
|
132
|
-
[ENV-XXX] Required tool '<tool>' not found
|
|
140
|
+
[ENV-XXX] Required tool '<tool>' not found (9-tier lookup exhausted)
|
|
133
141
|
→ Debian/Ubuntu: sudo apt install <tool>
|
|
134
|
-
→ macOS: brew install <tool>
|
|
142
|
+
→ macOS: brew install <tool> (or desktop app: <URL>)
|
|
135
143
|
→ Windows: winget install <tool> (or choco install <tool>)
|
|
136
|
-
→
|
|
144
|
+
→ Any platform: npm install -g <package> (if Node tool)
|
|
145
|
+
→ Manual: <download URL>
|
|
146
|
+
→ Pin explicitly: export <TOOL>_BIN=/path/to/binary
|
|
137
147
|
```
|
|
138
148
|
- This prevents the entire class of "it worked in CI but not locally" failures where `subprocess.run()` silently fails
|
|
149
|
+
- Reference implementation: `scripts/codex_imagen_bridge.mjs` in `@rune-pro/media` ports this pattern
|
|
139
150
|
|
|
140
151
|
### Step 4: Port Availability Check
|
|
141
152
|
|