@rafinery/cli 0.11.0 → 0.12.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/bin/rafa.mjs CHANGED
@@ -18,6 +18,8 @@
18
18
  // rafa distill --headless CI merge-to-main distillation (org's own LLM key)
19
19
  // rafa ci-setup write the reconcile workflow (fold + distill on PR merge)
20
20
  // rafa leverage inspect your agent toolbox → proactive tips
21
+ // rafa audit [--json] self-contained security engine: dep CVEs (OSV) ·
22
+ // secrets (built-in ruleset) · SAST (semgrep if present)
21
23
  // rafa benchmark reproduce the brain-vs-cold token proof on THIS repo (measured)
22
24
  // rafa migrate bring structured files (plans/config) up to the current schema
23
25
  //
@@ -53,6 +55,7 @@ const COMMANDS = [
53
55
  "distill",
54
56
  "ci-setup",
55
57
  "leverage",
58
+ "audit",
56
59
  "benchmark",
57
60
  "manifest",
58
61
  "review",
@@ -140,6 +143,13 @@ Commands:
140
143
  PR merge) and name the CI secrets to configure.
141
144
  leverage Inspect your agent toolbox (permissions, skills, MCP) and print
142
145
  prioritized tips for getting more out of it. Advisory — changes nothing.
146
+ audit Self-contained security engine (rafa.audit/v1): dependency CVEs via
147
+ the built-in lockfile parser + OSV.dev (pnpm audit merged in),
148
+ secrets via the built-in ruleset (tracked files only, .env* never
149
+ opened, fingerprints never bytes), SAST via semgrep IF present —
150
+ tiers that can't run say so honestly. --json emits the envelope;
151
+ writes .rafa/improve/security-audit.{json,md} when .rafa exists.
152
+ Exit: 0 clean · 1 findings · 2 engine error. Installs nothing.
143
153
  benchmark Reproduce the brain-vs-cold token-efficiency proof on THIS repo: cut
144
154
  two isolated worktrees (A=cold, B=brain), run the same task fixture,
145
155
  count harness tokens, emit a MEASURED benchmark.json. --dry-run
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: atlas
3
- version: 4.0.0
3
+ version: 4.1.0
4
4
  model: opus # authoring is correctness-critical — a hallucinated note poisons the brain; best model, never cheap
5
5
  groundTruth: code-at-sha
6
6
  description: >-
@@ -15,7 +15,7 @@ color: blue
15
15
  duties:
16
16
  - "scan :: .claude/skills/rafa-scan/SKILL.md :: comprehensive breadth-first cited brain · verify-citations exits 0 · coverage honest (thin/gap stated, never hidden)"
17
17
  - "repair :: .claude/skills/rafa-scan/SKILL.md :: every blocker + major in checklist.md fixed against the code · checker re-run to exit 0 · never weaken a check to pass it"
18
- - "plan-drafting :: .claude/skills/rafa-plan/SKILL.md :: recall-grounded decomposition (coverage → search → notes) · blast radius named · contract §7 files · every child carries a Done-check"
18
+ - "plan-drafting :: .claude/skills/rafa-plan/SKILL.md :: recall-grounded decomposition (coverage → search → notes) · blast radius named · contract §7 files · every child carries a Done-check · the security audit runs BEFORE approval and its picture is presented to the dev verbatim (§3b — totals + blast-radius criticals; clean said out loud, never silence)"
19
19
  - "build-execution :: .claude/skills/rafa-build/SKILL.md :: implement per recalled knowledge · TDD-DEFAULT when the tdd skill + a harness are present (the Done-check is a failing test FIRST at the plan-named seam; red→green evidence in the return) · UI tasks run the installed design skills per SOP (brain conventions win) · read session-facts FIRST and bank new expensive verifications (rafa facts add) · never hand-edit brain files around the gate · return what changed, cited"
20
20
  - "scoped-refresh :: .claude/skills/rafa-scan/SKILL.md :: re-derive ONLY the dirty-cited notes against current code (input: rafa dirty --json) · same gates as scan (verify-citations exit 0) · on main: compile+push; on a branch: working-set edit + checkpoint · queue consumed only after the refresh ships"
21
21
  - "okf-surface :: .claude/skills/rafa-okf/SKILL.md :: authored files pass rafa okf check as written — body links are markdown (never wikilinks); emit-owned sections untouched"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: bloom
3
- version: 0.9.0
3
+ version: 0.10.0
4
4
  model: opus # a false flag mutes the whole ledger — best model, never cheap
5
5
  groundTruth: code-trend
6
6
  description: >-
@@ -15,7 +15,8 @@ color: green
15
15
  duties:
16
16
  - "improve-pass :: .claude/skills/rafa-improve/SKILL.md :: cited · prioritized P0–P3 · the architecture lens applies the deletion-test/depth method with its vocabulary (Confidence-lined candidates, first-slice-or-backlog, never big-bang) · leverage-ranked · cite-checked (unresolved dropped) · ledger + debt trend regenerated"
17
17
  - "plan-pull :: .claude/skills/rafa-plan/SKILL.md :: top-leverage OPEN improvements in the blast radius surfaced as optional child tasks — dismissible, never blocking"
18
- - "build-sweep :: .claude/skills/rafa-build/SKILL.md :: newly spotted → ledger files · fixed-in-passing → status fixed · at most ONE opt-in nudge per task"
18
+ - "build-sweep :: .claude/skills/rafa-build/SKILL.md :: newly spotted → ledger files · fixed-in-passing → status fixed · at most ONE opt-in nudge per task · the cheap dependency tier of `rafa audit` re-runs so a mid-build lockfile change is caught"
19
+ - "security-profile :: .claude/skills/rafa-security/SKILL.md :: `rafa audit --json` is the engine (never LLM-pretended) · findings → category:security rows with the MECHANICAL priority map (critical→P0…dev-only→P3, annotate reachability, never downgrade) · P0 security rows are the ONE class that may surface outside the blast radius (dismissible, never blocking)"
19
20
  - "staleness-watch :: .claude/skills/rafa-improve/SKILL.md :: median open-item age stays minimal — every sweep re-validates or closes aged items; no improvement ages silently"
20
21
  - "okf-surface :: .claude/skills/rafa-okf/SKILL.md :: improvements/ledger pass rafa okf check as written · found: authored so timestamps are authored truth"
21
22
  ---
@@ -232,7 +232,7 @@ explicitly typed; an ACCEPTED boundary offer counts as the explicit invocation.
232
232
  |---|---|---|
233
233
  | `plan <intent>` | trio decomposition — atlas drafts brain-grounded contract §7 files (Done-checks), bloom pulls blast-radius improvements, prism validates the plan; approval → compile → `push_plan` + `set_active_plan` | [rafa-plan](../skills/rafa-plan/SKILL.md) |
234
234
  | `build` | execute the active plan per item (in `blocked_by` order): atlas recalls+implements → prism gates `status: done` on the `## Done-check` → bloom sweeps the ledger → update file + journals → checkpoint (push_plan/log_decision/`rafa checkpoint`); final verify + clear `active.md` when all children done | [rafa-build](../skills/rafa-build/SKILL.md) |
235
- | `improve` | spawn bloom → cited, prioritized P0–P3 ledger in `.rafa/improve/`; surface only the top few high-leverage items, never nag | [rafa-improve](../skills/rafa-improve/SKILL.md) |
235
+ | `improve` | spawn bloom → cited, prioritized P0–P3 ledger in `.rafa/improve/`; surface only the top few high-leverage items, never nag. Includes the security profile ([rafa-security](../skills/rafa-security/SKILL.md)): `rafa audit --json` → category:security rows, mechanical priority map, P0 security rows may surface outside the blast radius | [rafa-improve](../skills/rafa-improve/SKILL.md) |
236
236
  | `scan [--brain-only]` | the full pass know → verify → improve → push — atlas maps → gate-1 checker → prism validates → iterate (max 3) → improve → push on approval → founding-scan coach offer. `--brain-only` stops after validation. The whole conductor orchestration lives in the skill (§ Conductor orchestration). | [rafa-scan](../skills/rafa-scan/SKILL.md) |
237
237
  | `init` | first run: ensure `.rafa/active.md` = `# No active plan` (idempotent), then run the full scan pass | [rafa-scan](../skills/rafa-scan/SKILL.md) |
238
238
  | `distill [<branch>]` | reconcile a merged branch's working set into the org brain — prism validates each file vs merged MAIN, atlas authors survivors through verify-citations · compile · push, refutes with cites, flags `needs-adjudication`. Offer-driven at bootstrap; CI runs it headlessly. | [rafa-distill](../skills/rafa-distill/SKILL.md) |
@@ -197,7 +197,8 @@ JSON. This is the exact shape the platform binds to.
197
197
  {
198
198
  "id": "dead-model-options-google-crewai",
199
199
  "priority": "P1", // P0 | P1 | P2 | P3
200
- "lens": "product", // security|correctness|performance|architecture|product|ops
200
+ "category": "product", // security|correctness|performance|architecture|product|ops
201
+ "lens": "product", // transitional mirror of category (pre-2026-07-26 name) — dropped with the backfill arc
201
202
  "status": "open", // open | backlog | fixed | wontfix
202
203
  "title": "…",
203
204
  "summary": "…",
@@ -278,7 +279,7 @@ value).
278
279
  schemaVersion: 1
279
280
  id: dead-model-options-google-crewai # required · == filename stem
280
281
  priority: P1 # required · P0 | P1 | P2 | P3
281
- lens: product # required · security|correctness|performance|architecture|product|ops
282
+ category: product # required · security|correctness|performance|architecture|product|ops
282
283
  status: open # required · open | backlog | fixed | wontfix
283
284
  title: Two of the four model options are dead and fail silently # required
284
285
  summary: google_genai and crewai route to unwired agents # required
@@ -295,6 +296,11 @@ found: 2026-07-02 # optional · ISO date
295
296
  Note: `title`, `summary`, `fix` are now **required frontmatter** — previously scraped
296
297
  from prose. That scraping is gone; these are authored values.
297
298
 
299
+ `category` is the canonical field name (2026-07-26). The pre-rename name `lens`
300
+ is accepted as a **deprecated alias** by the compile gate (`category ?? lens`,
301
+ same enum); the manifest carries both keys during the transition. New files
302
+ author `category:` only.
303
+
298
304
  ---
299
305
 
300
306
  ## 4. Health file — `brain/checklist.md`
@@ -529,9 +535,9 @@ i.e. the default branch's instance).
529
535
 
530
536
  **Search = deterministic lexical retrieval; the server retrieves, the agent decides.**
531
537
  Fields searched per type — rule/playbook: `title, summary, domain, type` ·
532
- improvement: `title, summary, lens, blast_radius` · plan: `title, plan, parent`.
538
+ improvement: `title, summary, category, blast_radius` · plan: `title, plan, parent`.
533
539
  Score = Σ over matched case-folded query tokens of field weight (`title` 3 ·
534
- `domain`/`lens`/`blast_radius`/`type`/`plan`/`parent` 2 · `summary` 1); tie-break
540
+ `domain`/`category`/`blast_radius`/`type`/`plan`/`parent` 2 · `summary` 1); tie-break
535
541
  score desc then id asc; fields a type lacks are omitted, never defaulted. Candidates
536
542
  carry `matchKind: "lexical"` (`"semantic"` reserved).
537
543
 
@@ -43,7 +43,11 @@ platform MCP (one read path — the same surface any third-party agent uses).
43
43
  [rafa-commit](../rafa-commit/SKILL.md) format — `[<task-id>] <type>:
44
44
  <subject>` (the id join-key; intent records + the branch manifest lift it
45
45
  into per-note provenance)** → prism validates vs `## Done-check` →
46
- bloom sweeps (push new / close fixed / nudge) update the child file's `status`
46
+ bloom sweeps (push new / close fixed / nudge; **when THIS task changed a
47
+ lockfile/manifest, re-run the cheap dependency tier — `rafa audit --json` —
48
+ and report the delta to the dev in one transparent line: new/cleared
49
+ findings, never silence**; a new critical → a `category: security` P0 row
50
+ surfaced now) → update the child file's `status`
47
51
  **and append a dated entry to the child's `## Log`** (body links: markdown,
48
52
  per [rafa-okf](../rafa-okf/SKILL.md)) — what was done, what was
49
53
  decided, what surprised (body prose: displayed verbatim on the platform, never
@@ -50,7 +50,7 @@ Invoke via `/rafa improve`. The brain (#1) must exist — bloom *uses* it as the
50
50
  ## Output (to `.rafa/improve/`)
51
51
 
52
52
  - `improvements/<id>.md` — one file per improvement (cited, prioritized, status-tracked).
53
- - `ledger.md` — generated index: counts by priority/lens/status + the **health/debt trend**.
53
+ - `ledger.md` — generated index: counts by priority/category/status + the **health/debt trend**.
54
54
  Its **frontmatter carries the machine-read `open` · `debt_score` · `by_priority`** (per
55
55
  [`.claude/rafa/contract.md`](../../rafa/contract.md) §5) — the platform reads *that*, never the body tables,
56
56
  and `rafa compile` cross-checks `open`/`by_priority` against the actual improvement rows.
@@ -65,7 +65,7 @@ platform shows them; nothing is scraped from prose). Example *illustrative — f
65
65
  schemaVersion: 1
66
66
  id: rsc-route-level-use-client # required · kebab = filename stem
67
67
  priority: P1 # required · P0|P1|P2|P3
68
- lens: architecture # required · security|correctness|performance|architecture|product|ops
68
+ category: architecture # required · security|correctness|performance|architecture|product|ops (pre-2026-07-26 name `lens` is a deprecated alias)
69
69
  status: open # required · open|backlog|fixed|wontfix
70
70
  title: Route-level "use client" silently disables RSC # required
71
71
  summary: A route-level directive kills RSC down the whole subtree; no gate catches it # required
@@ -109,9 +109,15 @@ convention — see [RSC client boundary](/brain/rules/rsc-client-boundary.md)).
109
109
  ledger speaks the repo's own language).
110
110
  - **The big-bang guard is sovereign** (directive 1): a `Strong` candidate lands as its first
111
111
  10-minute slice or a P2 backlog item — never a grand refactor plan.
112
- 3. **Delegate security.** Run `pnpm audit` (dep CVEs). Recommend/run the **`security-review`**
113
- skill and semgrep/CodeQL if available. Record *tool* results as improvements; the LLM pass is
114
- observational only — never present it as an authoritative audit.
112
+ 3. **The security profile.** Run `npx @rafinery/cli audit --json` the SELF-CONTAINED
113
+ engine (dep CVEs via the built-in OSV client + pnpm audit; secrets via the built-in
114
+ ruleset; SAST via semgrep only if present a tier that didn't run says `ran:false`).
115
+ Then follow [rafa-security](../rafa-security/SKILL.md): findings → `category: security`
116
+ rows with the MECHANICAL priority map (critical→P0 · high→P1 · moderate→P2 ·
117
+ low/dev-only→P3), reachability annotated from the brain's domain map but never
118
+ downgraded, same-fix CVEs grouped into one row. The LLM pass (authz per route,
119
+ webhook verification, input validation) is observational only — never present it
120
+ as an authoritative audit.
115
121
  4. **Write improvements.** One file per improvement, cited (`file:line :: token`), prioritized,
116
122
  leverage-ranked. **Reconcile** against the existing ledger: dedup; **auto-close** improvements
117
123
  whose code is now clean (`status: fixed`); **preserve** the dev's prior triage
@@ -119,7 +125,7 @@ convention — see [RSC client boundary](/brain/rules/rsc-client-boundary.md)).
119
125
  5. **Cite-check (the fidelity gate).** Run
120
126
  `npx @rafinery/cli verify-citations --root=.rafa/improve --dirs=improvements`. Every cite
121
127
  must resolve; **drop or fix any that don't** — a hallucinated improvement is the cardinal sin.
122
- 6. **Ledger + trend.** Regenerate `ledger.md`: counts by priority/lens/status + a **debt
128
+ 6. **Ledger + trend.** Regenerate `ledger.md`: counts by priority/category/status + a **debt
123
129
  score** (weighted open improvements) and its trend vs the last run — the compounding made
124
130
  visible. Write the machine-read **frontmatter** `open` · `debt_score` · `by_priority`
125
131
  ([contract §5](../../rafa/contract.md)) — the platform reads that.
@@ -167,6 +173,11 @@ in that area and nudge once — *"2 P1s here, one's a 10-min fix — take it whi
167
173
  ranked by leverage, **dismissible, never blocking.** Not built here; this capability produces
168
174
  the ledger the nudge will read.
169
175
 
176
+ **The one exception to blast-radius scoping: `category: security` P0s.** A critical
177
+ CVE lives in no file the dev is touching, so a P0 security row may surface at
178
+ plan/build boundaries regardless of region — one line, dismissible, never blocking,
179
+ never re-nagged in the same session.
180
+
170
181
  ---
171
182
 
172
183
  ## Anti-patterns (each is a way bloom gets muted)
@@ -50,7 +50,7 @@ Conformance is our distribution wedge; verification stays the moat.
50
50
  | Agent | Files | What OKF-native means for you |
51
51
  |---|---|---|
52
52
  | **atlas** | `brain/rules/` · `brain/playbooks/` · `brain/coverage.md` | author `type` (§2 enum) + `title` + `summary` as ever; body cross-links as markdown links; optionally author `description`/`tags` — emit derives them from `summary`/`domain` if you don't |
53
- | **bloom** | `improve/improvements/` · `improve/ledger.md` | same; your files gain `type: Improvement` + `tags: [lens, priority]` at emit — author `found:` so timestamps are yours, not git's |
53
+ | **bloom** | `improve/improvements/` · `improve/ledger.md` | same; your files gain `type: Improvement` + `tags: [category, priority]` at emit — author `found:` so timestamps are yours, not git's |
54
54
  | **prism** | `brain/checklist.md` | verdict frontmatter as ever (emit stamps `type: Health Report` + a derived description); at validation, treat the checker's LINKS warns as a worklist — dangling links are claims of future knowledge |
55
55
  | **sage** | `.claude/rafa/learnings/` | learnings are OKF concepts too: frontmatter + `type: Learning` + markdown links; outside the bundle but under the same protocol |
56
56
  | **conductor / plan·build** | `plans/**` · `brain/log.md` | plan items gain `type` from `kind` at emit (per-epic `plans/index.md`); journals + bodies use markdown links; `log.md` stays the reserved trail |
@@ -23,7 +23,9 @@ Planning is a choreography, not one agent (spec: knowledge-mcp-build-agent):
23
23
  the tools; the dev never asks for it. Repo not platform-connected (no `rafinery`
24
24
  MCP in the session)? Fall back to reading `.rafa/brain/` files directly — same
25
25
  knowledge, just unserved.*
26
- - **bloom pulls** — `list_improvements` in the blast radius; surface the
26
+ - **bloom pulls** — `list_improvements` in the blast radius (PLUS any open
27
+ `category: security` P0 regardless of region — the one class that travels;
28
+ one line, dismissible, never blocking); surface the
27
29
  top-leverage open items as optional *"while-you're-here"* child tasks
28
30
  (leverage-ranked, dismissible, never blocking). **Any improvement the plan
29
31
  ADOPTS (as a task or the plan's very subject) is hydrated NOW** —
@@ -100,6 +102,17 @@ Planning is a choreography, not one agent (spec: knowledge-mcp-build-agent):
100
102
  the pivotal choices are logged as DECISIONS at approval (`log_decision`:
101
103
  context · options · decision · rationale; actor = the dev for their calls).
102
104
  3. **Ledger pull** (bloom) → optional leverage tasks in the blast radius.
105
+ 3b. **Security transparency** (2026-07-26 r2 — "security is not an aftermath").
106
+ Run `npx @rafinery/cli audit --json` (seconds; reuse a same-session
107
+ `security-audit.json` if fresh) and present the picture TO THE DEV, verbatim
108
+ and unburied, before the plan is approved: one line of severity totals +
109
+ which tiers ran, then any critical/high finding whose package or file sits
110
+ in THIS plan's blast radius (per [rafa-security](../rafa-security/SKILL.md)'s
111
+ reachability method). A blast-radius critical/high → propose it as a plan
112
+ child task (the fix rides the work); open `category: security` P0s surface
113
+ regardless of region. Transparent means: the dev sees the counts even when
114
+ everything is clean — "dependency tier clean at <sha>" is one honest line,
115
+ never silence.
103
116
  4. **Leverage-match** — recommend existing skills/tools/MCP that fit the tasks;
104
117
  never plan to hand-roll what a capability already does.
105
118
  5. **prism plan-validation** → REJECT/fix loop until clean.
@@ -201,6 +201,13 @@ retrieval index. Bodies read like a senior engineer explaining that one concept
201
201
  6. **Flow tracing** [LLM, cited] — from each entry point, hop-by-hop to termination
202
202
  (render / DB write / response) → `flow` playbooks. Add `how-to` playbooks for the
203
203
  recurring "add X" procedures these flows imply.
204
+ **One `security-posture` playbook is required** (2026-07-26): the repo's trust
205
+ boundaries (what's server-exposed vs build-time), auth chokepoints (where
206
+ authz is enforced — cited), and the secret-handling convention (where env
207
+ names are read; names only, per the step-4 guardrail). This is durable
208
+ KNOWLEDGE, not findings — it grounds bloom's security profile
209
+ ([rafa-security](../rafa-security/SKILL.md)): reachability annotations on
210
+ CVE rows come FROM this note's map.
204
211
 
205
212
  7. **Verification & synthesis** — apply the 100× filter (a note earns a file only if it
206
213
  answers a work-time question AND eliminates a recurring tax), then write the notes. Run
@@ -255,7 +262,8 @@ pipeline; **`--brain-only`** stops after the brain is validated (step 5 PASS)
255
262
  do **not** improve or push (never improve/push an unvalidated brain).
256
263
  6. **Improve** *(skip if `--brain-only`)* — run the improve pass ([rafa-improve](../rafa-improve/SKILL.md)):
257
264
  spawn `bloom` → `.rafa/improve/`. It reads the *validated* brain as its index, so it only
258
- runs after PASS.
265
+ runs after PASS. The security profile rides this step ([rafa-security](../rafa-security/SKILL.md):
266
+ `rafa audit --json` → category:security rows) — every scan carries it; no separate command.
259
267
  7. **Prove it — the measured benchmark** *(skip if `--brain-only`; skip if
260
268
  `.rafa/benchmark.json` already carries `measured: true` for this repo)* —
261
269
  the proof engine is WORKFLOW-WOVEN, never a dev-typed command (owner
@@ -0,0 +1,96 @@
1
+ ---
2
+ name: rafa-security
3
+ description: "rafa SOP — the security profile: run the self-contained `rafa audit` engine (dep CVEs via OSV · secrets · SAST if present), brain-ground reachability, author category:security improvements with the mechanical priority map, emit the profile. Loaded by bloom/the conductor at profiling moments (scan's improve pass, build-time sweep) — NEVER a dev-typed verb."
4
+ ---
5
+
6
+ # security — the profile (woven, never a command)
7
+
8
+ rafa's security posture is **woven into the loop, not a chore**: the dev never
9
+ types a security command. Owner doctrine (2026-07-26 r2): *"security is not an
10
+ aftermath — it is an integral part of the development cycle."* The engine
11
+ fires at every moment of that cycle:
12
+
13
+ - **plan** — the audit runs before approval and its picture is presented to
14
+ the dev verbatim (rafa-plan §3b): totals + blast-radius criticals; clean is
15
+ said out loud, never implied by silence.
16
+ - **build** — a task that touches the lockfile re-runs the cheap dep tier and
17
+ reports the delta in one line (rafa-build §2).
18
+ - **improve / scan** — the full three-tier profile (this SOP's procedure below).
19
+ - **every merge** — branch→branch merges get a platform-side dep audit at fold
20
+ time; canonical merges get the reconcile graph's security lane. Both mint
21
+ Security-tab rows — freshness at every level, not just prod.
22
+
23
+ Findings land as ordinary contract §3 improvements with `category: security`;
24
+ the platform's Security tab reads the merge-level rows.
25
+
26
+ ## The engine — deterministic first, always
27
+
28
+ Run **`npx @rafinery/cli audit --json`** and parse the `rafa.audit/v1`
29
+ envelope. The engine is SELF-CONTAINED — it needs no installs, ever:
30
+
31
+ - **dependency** — built-in pnpm-lock parser + the OSV.dev advisory API,
32
+ merged with `pnpm audit`; per finding: package · GHSA/CVE + aliases ·
33
+ severity + CVSS · direct-vs-transitive chain · fixed-in · dev-only flag.
34
+ - **secrets** — built-in curated ruleset over tracked files (`.env*` never
35
+ opened; fingerprints, never secret bytes). gitleaks enhances if present.
36
+ - **sast** — semgrep if installed (pinned `p/security-audit`), otherwise the
37
+ envelope says `ran:false` with the reason. semgrep/gitleaks are OPTIONAL
38
+ enhancers; mention their value once when relevant (`rafa doctor` shows
39
+ install hints) — installing is always the dev's own consented choice.
40
+ **Never LLM-pretend a tier that did not run** — `tiers.<t>.ran` is the truth.
41
+
42
+ ## Findings → improvements (the mechanical part)
43
+
44
+ One §3 improvement file per finding worth a row (group same-package CVEs into
45
+ one row when they share the fix — one lockfile bump = one improvement).
46
+ Required frontmatter as ever (`title` · `summary` · `fix` · `leverage` ·
47
+ `cites`), plus:
48
+
49
+ - `category: security` — always.
50
+ - **Priority maps mechanically, never by vibe**: critical → P0 · high → P1 ·
51
+ moderate → P2 · low or dev-only (`dev:true`) → P3. The LLM may ANNOTATE
52
+ (see below) but **never downgrades** a mapped priority.
53
+ - `fix:` carries the concrete path: the upgrade target (`fixedIn`), whether the
54
+ dep is direct (bump it) or transitive (dedupe/overrides/parent-bump), the
55
+ secret's rotation step. Comprehensive detail (chain, refs, CVSS) rides the
56
+ body — machine-sourced from the envelope, never re-guessed.
57
+ - Dependency-tier rows cite the lockfile/manifest line that pins the package;
58
+ secret/sast rows cite the `file:line` from the finding.
59
+
60
+ **Reconcile like any improvement**: dedupe against existing rows by the stable
61
+ finding id (in the body); auto-close rows whose finding vanished from a fresh
62
+ audit (`status: fixed` — the lockfile bump landed); preserve the dev's triage
63
+ (backlog/wontfix stay).
64
+
65
+ ## Brain-ground the reachability (the judgment part)
66
+
67
+ The brain's domain map is what raw scanners lack. For each dependency finding,
68
+ answer from the brain — *is this package on a server-exposed path?* (API
69
+ routes, webhook handlers, auth boundary) — and write the answer into the body
70
+ as an annotation: `Reachability: server-exposed via <domain> — see
71
+ [<note>](/brain/...)` or `Reachability: build-time only`. Cited, observational,
72
+ and **priority-neutral** — it informs the dev's triage, it never overrides the
73
+ mechanical map.
74
+
75
+ The wider observational pass (authz per route, webhook verification, input
76
+ validation against the brain's contracts) belongs to the improve SOP's
77
+ security lens — cited `file:line`, labeled observational, never presented as
78
+ SAST output.
79
+
80
+ ## The P0 exception — the one row that travels
81
+
82
+ Improvement nudges are blast-radius-scoped — EXCEPT `category: security` P0s:
83
+ a critical CVE lives in no file the dev is touching, so a P0 security row may
84
+ surface at plan/build boundaries regardless of region. Still one line, still
85
+ dismissible, never blocking, never re-nagged in the same session.
86
+
87
+ ## Anti-patterns
88
+
89
+ - Running the engine and PARAPHRASING its output into rows without the
90
+ envelope's fields — the detail is machine-sourced or it doesn't ship.
91
+ - Downgrading a mapped priority because it "seems fine" — annotate, never
92
+ downgrade.
93
+ - A wall of per-CVE rows for one package — group by shared fix.
94
+ - Presenting the observational pass as scanner output.
95
+ - Asking the dev to install semgrep/gitleaks more than once — the doctor
96
+ carries the hint; a decline stands.