@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.
Files changed (49) hide show
  1. package/README.md +41 -7
  2. package/compiler/__tests__/adr-scoring.test.js +91 -0
  3. package/compiler/__tests__/context-md-format.test.js +180 -0
  4. package/compiler/__tests__/context-pack-smell-tests.test.js +215 -0
  5. package/compiler/__tests__/diversity-score.test.js +117 -0
  6. package/compiler/__tests__/improve-architecture.test.js +171 -0
  7. package/compiler/__tests__/openclaw-adapter.test.js +31 -0
  8. package/compiler/__tests__/out-of-scope-format.test.js +303 -0
  9. package/compiler/__tests__/zoom-out-output.test.js +112 -0
  10. package/compiler/adapters/openclaw.js +43 -3
  11. package/package.json +2 -2
  12. package/skills/adversary/SKILL.md +1 -1
  13. package/skills/audit/SKILL.md +1 -0
  14. package/skills/autopsy/SKILL.md +1 -1
  15. package/skills/ba/SKILL.md +241 -82
  16. package/skills/ba/references/context-md-format.md +136 -0
  17. package/skills/ba/references/explore-first.md +107 -0
  18. package/skills/ba/references/out-of-scope-format.md +152 -0
  19. package/skills/brainstorm/SKILL.md +77 -1
  20. package/skills/brainstorm/references/design-it-twice.md +155 -0
  21. package/skills/context-pack/SKILL.md +69 -26
  22. package/skills/context-pack/evals.md +122 -0
  23. package/skills/context-pack/references/brief-template.md +121 -0
  24. package/skills/context-pack/references/durability-rules.md +109 -0
  25. package/skills/cook/SKILL.md +4 -4
  26. package/skills/debug/SKILL.md +2 -1
  27. package/skills/fix/SKILL.md +2 -1
  28. package/skills/graft/SKILL.md +1 -1
  29. package/skills/improve-architecture/SKILL.md +275 -0
  30. package/skills/improve-architecture/evals.md +145 -0
  31. package/skills/improve-architecture/references/deepening.md +87 -0
  32. package/skills/improve-architecture/references/interface-design.md +68 -0
  33. package/skills/improve-architecture/references/language.md +81 -0
  34. package/skills/improve-architecture/references/scoring.md +122 -0
  35. package/skills/journal/SKILL.md +34 -7
  36. package/skills/journal/references/adr-criteria.md +109 -0
  37. package/skills/marketing/SKILL.md +2 -1
  38. package/skills/review/SKILL.md +1 -0
  39. package/skills/review-intake/SKILL.md +25 -2
  40. package/skills/safeguard/SKILL.md +1 -1
  41. package/skills/scout/SKILL.md +33 -1
  42. package/skills/sentinel-env/SKILL.md +24 -13
  43. package/skills/skill-forge/SKILL.md +108 -1
  44. package/skills/surgeon/SKILL.md +17 -2
  45. package/skills/test/SKILL.md +48 -1
  46. package/skills/test/evals.md +137 -0
  47. package/skills/test/references/mocking-policy.md +121 -0
  48. package/skills/test/references/test-quality.md +124 -0
  49. 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.
@@ -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.3.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
- 1. Generate an ADR filename: `.rune/adr/ADR-[NNN]-[slug].md` where NNN is the next sequential number
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 with rationale
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.5.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
@@ -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.1.0"
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"
@@ -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.3.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.2.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
- ```bash
122
- # Verify the tool exists on PATH
123
- which <tool-name> 2>/dev/null || echo "MISSING: <tool-name>"
124
- # If found, check version
125
- <tool-name> --version 2>/dev/null
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 on PATH → PASS (log version)
130
- - Tool NOT found → **BLOCK** with clear install instructions per OS:
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 on PATH
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
- Manual: <download URL if known>
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