@rafinery/cli 0.4.1 → 0.6.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 (36) hide show
  1. package/CHANGELOG.md +144 -0
  2. package/bin/rafa.mjs +30 -5
  3. package/blueprint/.claude/agents/atlas.md +10 -5
  4. package/blueprint/.claude/agents/compass.md +3 -1
  5. package/blueprint/.claude/commands/rafa.md +103 -12
  6. package/blueprint/.claude/rafa/contract.md +111 -47
  7. package/blueprint/.claude/rafa/hooks/post-tool.mjs +62 -0
  8. package/blueprint/.claude/rafa/hooks/pre-push +24 -0
  9. package/blueprint/.claude/rafa/hooks/session-start.mjs +229 -0
  10. package/blueprint/.claude/rafa/hooks/statusline.mjs +113 -0
  11. package/blueprint/.claude/rafa/hooks/user-prompt-submit.mjs +87 -0
  12. package/blueprint/.claude/skills/rafa-build/SKILL.md +17 -5
  13. package/blueprint/.claude/skills/rafa-insights/SKILL.md +13 -2
  14. package/blueprint/.claude/skills/rafa-plan/SKILL.md +18 -3
  15. package/blueprint/.claude/skills/rafa-scan/SKILL.md +23 -3
  16. package/blueprint/.claude/skills/rafa-validate/SKILL.md +15 -2
  17. package/lib/blueprint.mjs +9 -1
  18. package/lib/brain-repo.mjs +10 -4
  19. package/lib/checkpoint.mjs +7 -0
  20. package/lib/ci-setup.mjs +2 -0
  21. package/lib/claude-config.mjs +113 -0
  22. package/lib/dirty.mjs +114 -0
  23. package/lib/distill.mjs +47 -2
  24. package/lib/gate/compile.mjs +145 -32
  25. package/lib/gate/verify-citations.mjs +214 -23
  26. package/lib/githook.mjs +54 -0
  27. package/lib/init.mjs +45 -0
  28. package/lib/leverage.mjs +13 -2
  29. package/lib/migrations/index.mjs +57 -2
  30. package/lib/pull.mjs +7 -0
  31. package/lib/push.mjs +21 -0
  32. package/lib/reflex.mjs +76 -0
  33. package/lib/releases.mjs +66 -0
  34. package/lib/status.mjs +152 -0
  35. package/lib/update.mjs +20 -0
  36. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -4,6 +4,150 @@ The machine-readable version of this lives in [`lib/releases.mjs`](lib/releases.
4
4
  CLI reads it to tell a client, on `rafa update`, exactly what an upgrade requires (nothing,
5
5
  a re-scan, or a `rafa migrate`).
6
6
 
7
+ ## 0.6.0 — core solidity: checker v2 + the M5 capture engine
8
+
9
+ **Adopt with:** `npx @rafinery/cli@latest update` — re-vendors the new lockstep hook
10
+ scripts (`.claude/rafa/hooks/`), merges the sensor hooks into `.claude/settings.json`
11
+ (never clobbers yours), and installs the per-clone git pre-push boundary. Brain data
12
+ unchanged; no re-scan. Teammates get the git hook at their next `rafa pull`.
13
+
14
+ **The ratchet (checker v2)** — the two catches prism recommended in the 2026-06-08 live
15
+ run are now deterministic gates in `rafa verify-citations`:
16
+
17
+ - **Absence (B3)**: a note that claims something does NOT exist declares
18
+ `absent: <token>` (repeatable, anchor-style). Every declared absence is re-grepped
19
+ every run (docs/`.md` excluded) — the moment code grows the thing, the gate fails with
20
+ the exact site. Mechanizes the 2026-06-08 blocker class (a "stubbed" note the code had
21
+ outgrown).
22
+ - **Inventory**: `coverage.md` declares `inventory:` entries
23
+ (`- <name> :: <glob> :: <count>`); each is recomputed via `git ls-files ':(glob)…'` —
24
+ coverage claiming a surface inventory the repo has outgrown fails with the path diff.
25
+ - **WARN heuristic (non-failing)**: an absence-shaped `title`/`summary` with no `absent:`
26
+ declared is listed for prism's 3b audit — a heuristic never fails the gate (that would
27
+ be an assumed value).
28
+ - **Recorded gate level**: the checker writes `citation-check.json`
29
+ (`{checkerVersion, at, pass, gates, warns}`) and `rafa compile` folds it into
30
+ `manifest.citations` — the platform knows which checker version a brain actually
31
+ passed. No recorded run → `citations: null`, honestly.
32
+ - Selftest extended: absence + inventory logic proven on throwaway git fixtures
33
+ (prism's mutation probe covers the new gates).
34
+
35
+ **The M5 capture engine** — checkpoint/staleness moments become deterministic code, not
36
+ SOP adherence (the E2E-proven weak link: a full build once produced zero captures,
37
+ silently):
38
+
39
+ - **SessionStart digest** (`.claude/rafa/hooks/session-start.mjs`): the session starts
40
+ knowing — dirty code files → the brain notes citing them (local manifest, or
41
+ `get_code_context` fail-soft ≤2s), pending `*.theirs.md` checkpoint conflicts, the
42
+ active plan. Prints nothing when there is nothing (silence is the honest digest).
43
+ - **PostToolUse dirty-marker** (`.claude/rafa/hooks/post-tool.mjs`): every Edit/Write is
44
+ appended to `.rafa/dirty.jsonl` the moment it happens — monotonic, no session-end
45
+ dependency (there is no session end), never blocks, transport-excluded from brain
46
+ pushes via `.rafa/.gitignore`.
47
+ - **git pre-push boundary**: `git push` of the code branch runs `rafa checkpoint`
48
+ (non-blocking — a checkpoint problem never stops a code push; conflicts land as
49
+ `.theirs.md` for YOUR decision). Installed at init/pull/update; a foreign pre-push
50
+ hook is respected, never clobbered (the chain line is printed instead).
51
+ - **`rafa dirty [--json|--consume]`**: the cite-graph invalidator's query surface —
52
+ dirty files → citing notes; at boundaries the conductor OFFERS a scoped refresh
53
+ (atlas re-derives only the citing notes → gates → checkpoint), `--consume` clears the
54
+ queue after the refresh ships. Past the drift threshold (15 files / 10 notes) the
55
+ digest recommends `/rafa scan --brain-only` — the fire-alarm rung.
56
+ - **Recursion guard (U7)**: headless runs (CI fold/distill, the Agent SDK worker) set
57
+ `RAFA_HOOKS_DISABLED=1`; every hook exits 0 immediately. Hooks also no-op outside a
58
+ rafa-provisioned repo (no `rafa.json` → silent).
59
+ - **The correction reflex** (`.claude/rafa/hooks/user-prompt-submit.mjs` +
60
+ `rafa reflex`): a correction-shaped prompt ("no —", "never use X", "use Y instead")
61
+ is queued to `.rafa/reflex.jsonl` AND answered with a steering injection at that
62
+ exact moment — the session validates and banks it through the normal gates
63
+ same-session (branch: cited note + checkpoint · main: full gates), confirms in one
64
+ line, and consumes the queue entry with a verdict. Ungroundable claims are never
65
+ banked; unprocessed corrections from abandoned sessions surface at the next
66
+ session start (monotonic). Corrections are the highest-value knowledge signal —
67
+ they no longer evaporate.
68
+ - **`rafa push` re-runs the checker itself** (before compile; improvements ledger too
69
+ when present) — a stale or hand-stamped `citation-check.json` can never ride a push;
70
+ the record that ships is the record of THAT push. Mechanized same-day from the
71
+ 2026-07-13 prism live-run recommendation (the disposition protocol working).
72
+ - Checker hardening: grep hits under `.rafa/**` are excluded categorically — the brain
73
+ never counts as "code", so an accidentally-tracked `.rafa/` can't self-collide the
74
+ completeness/absence gates.
75
+
76
+ **The frictionless loop** — devs won't run commands in order, so the loop guides
77
+ itself (owner directive; anti-nag etiquette unwaived — guidance is ambient,
78
+ front-loaded, or earned, never interleaved):
79
+
80
+ - **Loop-state statusline**: `.claude/rafa/hooks/statusline.mjs` renders
81
+ `rafa ▸ plan <id> 2/5 → <task> · 3 stale · 1 correction` at the bottom of every
82
+ session (silent outside rafa repos; a dev's existing statusline is NEVER replaced).
83
+ `rafa status [--line|--json]` is the harness-neutral core it mirrors.
84
+ - **Suggested next**: the SessionStart digest gains one deterministic
85
+ `[rafa · next]` line — ranked conflicts → corrections → resume plan → staleness —
86
+ so every session opens knowing the single best next step.
87
+ - **Direct-do path** (conductor 1.8.0): small work (≤ 1 domain, no contract surface,
88
+ one sitting) gets NO plan files and no approval — act first; the sensors carry the
89
+ loop; escalates to plan-lite with one announce line only when the work grows.
90
+ - **Brainstorm mode**: during exploration the conductor is a grounded, cited
91
+ participant with zero workflow talk; at crystallization, exactly one offer (a plan
92
+ if it's work, a working-set note if it's a conclusion).
93
+
94
+ **Portability (owner directive, 2026-07-13):** built for Claude Code now, ships for
95
+ Cursor/Codex later — loop logic lives in the harness-neutral core (CLI verbs + the
96
+ `.rafa/*.jsonl` queues + gates + MCP); everything under `.claude/rafa/hooks/` is a
97
+ thin per-harness adapter. The event protocol (detect → queue → steer →
98
+ bank-through-gates) is the portable contract.
99
+
100
+ The honest boundary, by design: hooks make **sync, staleness, and boundaries**
101
+ deterministic; **authoring stays model work** — steered by the injected digest, visible
102
+ on the platform ("working set clean" is a real answer, not a gap).
103
+
104
+ ## 0.5.0 — plans v2: the work-item tree
105
+
106
+ **Adopt with:** `npx @rafinery/cli@latest update` → it runs the mechanical `rafa migrate`
107
+ (plans data v1→v2: `parent`→`epic`, `child`→`task`, stored `blocked`→`todo` +
108
+ `blocked_reason`). Brain data unchanged; no re-scan. Re-push plans once so the platform
109
+ rows pick up the tree + glimpse fields.
110
+
111
+ - **The tree**: one epic → tasks → subtasks (three ranks — matching Linear/Jira/Asana's
112
+ ceiling so tracker sync stays lossless). Compile validates ranks, single root,
113
+ `blocked_by` resolution + acyclicity.
114
+ - **Vendor-blended vocabulary** (checked against the real APIs): `title` ·
115
+ `description` (1:1 with vendor description/notes) · `approach` (rafa's how-line) ·
116
+ `assignee` · `blocked_by` (a dependency IS a blocker) · `blocked_reason` ·
117
+ `priority` 0–4 (Linear scale) · `estimate` · `external {provider, key, url}`
118
+ (read-only tracker identity; provider-closed ≠ done — K6).
119
+ - **`blocked` is DERIVED, never stored** — the status enum is
120
+ todo|in-progress|done|superseded|abandoned; the platform renders a blocked chip from
121
+ unresolved `blocked_by`/`blocked_reason`.
122
+ - **Decisions are first-class**: `log_decision` (at · actor · context · options ·
123
+ decision · rationale — paraphrase + pivotal quotes) with the `## Decisions` body
124
+ section as the human mirror; rendered as a timeline on the plan detail page.
125
+ - Platform: glimpse cards (what/why/how/who/blocked/deps at a glance), tree detail
126
+ page, board blocked-chip (the Blocked column is gone — it's a condition, not a state).
127
+
128
+ ## 0.4.2
129
+
130
+ **Adopt with:** `npx @rafinery/cli@latest update` — file re-sync only (skills + contract
131
+ moved a few lines); no migration, no re-scan.
132
+
133
+ Owner E2E feedback round (research-canvas):
134
+
135
+ - **`rafa init` offers CI reconciliation** at provisioning (TTY only): yes runs
136
+ `ci-setup`, no prints the session-fallback path. Nothing is silently installed —
137
+ the workflow runs on the org's own secrets.
138
+ - **`rafa distill --headless` is observable**: streams the agent's narration lines and
139
+ prints per-phase timings (brain mirror · agent turns/cost · gates · total), so a CI
140
+ log shows liveness and where the time goes. Failure semantics unchanged: any
141
+ incomplete verdict or failed gate aborts with the working set intact.
142
+ - **Plans link to their brain slice**: optional parent-only `domains:` (contract §7) —
143
+ the blast radius named at plan time rides `push_plan`; the platform's new plan
144
+ detail page renders the plan's related knowledge beside its tasks + `## Log`
145
+ journals. Compile validates the shape (child `domains:` fails loudly).
146
+ - **Live improvement signal** (platform + SOP): bloom's fixed-in-passing during build
147
+ now also calls `report_improvement_status` — event-only (the ledger row keeps its
148
+ single writer, the ingest); the Improvements page shows it as *pending
149
+ reconciliation* until the next brain push confirms.
150
+
7
151
  ## 0.4.1
8
152
 
9
153
  **Adopt with:** `npx @rafinery/cli@latest <cmd>` — no file re-sync needed (the fix is inside
package/bin/rafa.mjs CHANGED
@@ -1,18 +1,25 @@
1
1
  #!/usr/bin/env node
2
2
  // rafa — the rafinery CLI. Thin dispatcher; each command lives in ../lib.
3
3
  //
4
- // rafa init [<setup-url>] provision this repo (vendor blueprint + wire the platform)
4
+ // rafa init [<setup-url>] provision this repo (vendor blueprint + wire the platform + sensors)
5
5
  // rafa update re-sync the blueprint into this repo (shadcn-style)
6
6
  // rafa compile run the contract gate → .rafa/manifest.json
7
- // rafa verify-citations deterministic citation checker (B1/B2/policy gates)
7
+ // rafa verify-citations deterministic citation checker (B1/B2/policy/absence/inventory)
8
8
  // rafa push compile + push .rafa/ to the brain remote (main-branch act)
9
9
  // rafa pull [--full] make this clone brain-ready (lazy skeleton; --full mirrors)
10
+ // rafa checkpoint sync this branch's working set (CAS; conflicts → .theirs.md)
11
+ // rafa hydrate fault knowledge into the lazy .rafa/
12
+ // rafa dirty [--json] staleness queue → citing notes; --consume after a refresh
13
+ // rafa fold branch→parent mechanical fold of the working set (no LLM)
14
+ // rafa distill --headless CI merge-to-main distillation (org's own LLM key)
15
+ // rafa ci-setup write the reconcile workflow (fold + distill on PR merge)
10
16
  // rafa leverage inspect your agent toolbox → proactive tips
11
17
  // rafa migrate bring structured files (plans/config) up to the current schema
12
18
  //
13
19
  // The gate tools live INSIDE this package (blueprint split, 0.4.0) — nothing is
14
20
  // vendored into .rafa/bin anymore. The LLM work (scan / improve / plan) runs
15
- // inside Claude Code via /rafa.
21
+ // inside Claude Code via /rafa. The M5 sensor hooks (.claude/rafa/hooks/) are
22
+ // vendored LOCKSTEP; commands are agent-internal machinery (zero-command rule).
16
23
 
17
24
  import { readFileSync } from "node:fs";
18
25
  import { dirname, join } from "node:path";
@@ -30,6 +37,9 @@ const COMMANDS = [
30
37
  "pull",
31
38
  "checkpoint",
32
39
  "hydrate",
40
+ "dirty",
41
+ "reflex",
42
+ "status",
33
43
  "fold",
34
44
  "distill",
35
45
  "ci-setup",
@@ -53,8 +63,10 @@ Commands:
53
63
  --keep keep all changed owned files without asking
54
64
  (default: ask per file; in a non-TTY it keeps them)
55
65
  compile Validate the brain against the contract → .rafa/manifest.json.
56
- verify-citations Deterministic citation checker: every cite resolves (B1), every
57
- contract anchor's code occurrences are cited (B2), policy holds.
66
+ verify-citations Deterministic citation checker (v2): every cite resolves (B1),
67
+ every contract anchor's code occurrences are cited (B2), policy
68
+ holds, declared absences re-grepped (B3), coverage inventories
69
+ re-counted. Records the run (citation-check.json → manifest).
58
70
  push Compile, then push .rafa/ to your brain remote (from main — the
59
71
  org brain describes the default branch). Stamps the contract copy.
60
72
  pull Make this clone brain-ready — bootstraps the lazy .rafa/ skeleton
@@ -67,6 +79,19 @@ Commands:
67
79
  hydrate Fault knowledge into the lazy .rafa/: hydrate rule <id> ·
68
80
  hydrate playbook <id> (org brain, stamped disposable-cache) ·
69
81
  hydrate --working-set (this branch's synced files).
82
+ dirty The staleness queue (M5): code files edited since the last brain
83
+ reconcile → the brain notes citing them. --json for agents;
84
+ --consume clears it AFTER a scoped refresh shipped. The queue is
85
+ written by the PostToolUse sensor hook the moment an edit happens.
86
+ reflex The correction queue (M5): corrections the UserPromptSubmit sensor
87
+ detected. List/--json; --consume <id> [verdict] AFTER banking it
88
+ through the gates (or judging it session-only). Corrections are
89
+ the highest-value knowledge signal — they must never evaporate.
90
+ status Where the loop stands, from local state only: active plan +
91
+ task progress · stale count · corrections · conflicts.
92
+ --line = the one-line ambient form (statuslines/prompts) ·
93
+ --json = machine shape. Harness-neutral core: the Claude Code
94
+ statusline adapter mirrors exactly this.
70
95
  fold Branch→parent MECHANICAL fold of the working set (no LLM):
71
96
  rafa fold --from <branch> --to <parent>. Divergence → flagged
72
97
  needs-adjudication for the next dev session, never guessed.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: atlas
3
- version: 3.5.0
3
+ version: 3.7.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: >-
@@ -10,13 +10,14 @@ description: >-
10
10
  when a codebase must be scanned, a brain repaired after validation, a plan
11
11
  drafted from recalled knowledge, or a plan's task implemented. Runs
12
12
  context-isolated; comprehensive, cited, never cherry-picked.
13
- tools: Read, Write, Edit, Bash, Grep, Glob, TodoWrite, mcp__rafinery
13
+ tools: Read, Write, Edit, Bash, Grep, Glob, TodoWrite, Skill, mcp__rafinery
14
14
  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
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"
19
19
  - "build-execution :: .claude/skills/rafa-build/SKILL.md :: implement per recalled knowledge · never hand-edit brain files around the gate · return what changed, cited"
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"
20
21
  ---
21
22
 
22
23
  # atlas — senior design engineer
@@ -84,9 +85,13 @@ Never act cold; never over-load.
84
85
  **never open `.env`/`.env.*` or any secret store, and never read or copy a value.** A key's
85
86
  *name* is a contract; its *value* is a secret. If a note genuinely needs a value, stop and ask
86
87
  the dev — don't harvest it. (Enforced in [the scan skill](../skills/rafa-scan/SKILL.md) step 4.)
87
- - **Orchestrate, don't bury.** At work-time, ride the host + the dev's existing skills/tools/MCP
88
- and recommend the best-fit one; never reinvent a capability that already exists. rafa conducts
89
- what's present.
88
+ - **Toolbox-first execution (automatic never an offer).** Before implementing any
89
+ task step, CHECK the repo's installed toolbox committed `.claude/skills/`,
90
+ `.mcp.json` servers, commands — for a capability that already does it, and INVOKE
91
+ it (Skill tool / MCP) instead of hand-rolling. The conductor passes the matching
92
+ inventory slice in your spawn prompt; consult it first. Only what is actually
93
+ installed — never guess a capability into existence. Record the choice in the
94
+ item's `approach` ("how: via the <x> skill").
90
95
 
91
96
  ## Style
92
97
  Dense, no filler, no praise. Short plan before acting. Bracketed status
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: compass
3
- version: 0.2.1
3
+ version: 0.3.0
4
4
  model: opus # a false note about a PERSON is worse than one about code — best model, never cheap
5
5
  groundTruth: sessions-over-time
6
6
  description: >-
@@ -16,6 +16,8 @@ duties:
16
16
  - "bootstrap :: .claude/skills/rafa-insights/SKILL.md :: native /insights report distilled with judgment (never parsed mechanically) into dev-level candidates — each OFFERED, banked only on yes"
17
17
  - "continuous-refinement :: .claude/skills/rafa-insights/SKILL.md :: session observations routed by the boundary (dev-level here, code-level to the branch working set) · update beats duplicate · every insight legible, correctable, deletable on request"
18
18
  - "steering :: .claude/skills/rafa-insights/SKILL.md :: propose-dev-disposes at natural boundaries · at most one nudge · dismissal is final for the session · never rank, never compare, never nag"
19
+ - "leverage-coaching :: .claude/skills/rafa-insights/SKILL.md :: the one boundary nudge may be sourced from toolbox × patterns (repo inventory + the dev's tooling insights) — always HAS a candidate ready, never raises nudge frequency; only capabilities actually installed"
20
+ - "tooling-capture :: .claude/skills/rafa-insights/SKILL.md :: personal ~/.claude tooling (names + descriptions ONLY) banked as kind:tooling insights under STANDING consent · legible/deletable · never enters org stores"
19
21
  ---
20
22
 
21
23
  # compass — the dev's coach
@@ -1,5 +1,5 @@
1
1
  ---
2
- version: 1.3.0
2
+ version: 1.8.0
3
3
  description: rafa — the repo's engineering SOP. Use whenever the dev wants to plan a feature or change, build/execute against the active plan, improve code health, or ground work in the repo's brain — intent counts, the dev does NOT need to type /rafa. Also explicit: /rafa <init|scan|improve|plan|build|push|leverage|migrate|update|help> [--brain-only]. Admin verbs (init/scan/push/migrate/update) run ONLY when explicitly invoked.
4
4
  ---
5
5
 
@@ -13,14 +13,40 @@ Admin verbs are expensive or side-effectful and run **only when explicitly typed
13
13
 
14
14
  | Prompt shape | Route |
15
15
  |---|---|
16
- | "let's add / build / implement / refactor X" (no active plan) | `## plan` weight by blast radius: lite vs full (see plan.md § plan-lite) |
16
+ | small work radius 1 domain, no contract surface, fits one sitting | **DIRECT-DO**: recall → implement → verify → done. NO plan files, NO approval, NOTHING to remember the sensors carry the loop (dirty-mark, reflex, checkpoint-at-push). Escalate only if it GROWS (below). |
17
+ | "let's add / build / implement / refactor X" — real blast radius (≥ 2 domains, a contract surface, or multi-session) (no active plan) | `## plan` — weight by blast radius: lite vs full (see plan.md § plan-lite) |
17
18
  | same, with an active plan covering it | `## build` |
18
19
  | "why / how / where does X …" (a question) | recall-and-answer: MCP `search_knowledge` → cited answer. No choreography. |
20
+ | exploration — "what if / should we / compare / thinking about X" | **BRAINSTORM mode** (§ below): grounded participant, zero workflow talk, one offer at crystallization. |
19
21
  | "list plans / what plans are there" | `list_plans` — NAMES ONLY (id · title · status · progress); never dump bodies |
20
22
  | "load / open / work on plan X" | `get_plan(X)` → materialize parent + children (bodies) into `.rafa/plans/<X>/` + set `active.md` → resume per `## build` |
21
23
  | "improve / clean up / what's rotting" | `## improve` |
22
24
  | explicit `/rafa <admin verb>` — init · scan · push · migrate · update | that verb, and ONLY then |
23
25
 
26
+ **Direct-do — the light path must be lighter than bypassing rafa.** For small work
27
+ the default INVERTS: act first, record only if it earns recording. No announcement
28
+ ceremony either — just do it (recall still automatic; verify still real: types/lint/
29
+ tests as the repo warrants). **The escalation rule:** the moment the work grows — a
30
+ second domain, a contract surface, or it clearly won't finish this sitting — say ONE
31
+ line (*"this grew — recording it as a plan so it's resumable"*), create the plan-lite
32
+ files THEN, and continue; never ask permission to keep the loop honest, and never
33
+ escalate a task that stayed small. What keeps direct-do safe with zero ceremony: the
34
+ sensors (every edit dirty-marked, corrections reflexed, `git push` checkpoints) plus
35
+ §capture for anything learned — the loop closes without the dev or you filing
36
+ paperwork.
37
+
38
+ **Brainstorm mode — grounded participant, not a process.** During exploration:
39
+ recall automatically and cite (the brain is WHY the brainstorm is good), think WITH
40
+ the dev, and say NOTHING about plans, captures, checkpoints, or process — zero
41
+ workflow talk mid-exploration. At CRYSTALLIZATION (the dev stops exploring and
42
+ starts concluding — "ok let's do X", "so the decision is Y", or asks to proceed):
43
+ exactly ONE offer, shaped by what the conversation produced — work → *"want me to
44
+ turn this into a plan?"* · a durable conclusion with no work attached → *"bank the
45
+ conclusion as a note?"* (a plan-less decision lands as a working-set note under
46
+ §capture, so brainstorm output survives even when no work item ever exists). A "no"
47
+ stands for the session. If nothing crystallized, offer nothing — an open exploration
48
+ is a fine place to end.
49
+
24
50
  **Announce-and-proceed, never ask-permission:** state the route in one line — *"this
25
51
  looks plan-shaped — following the plan SOP (say 'skip' to bypass)"* — then go. "skip"
26
52
  always wins, immediately and without argument. Never narrate other devs' activity
@@ -28,6 +54,20 @@ unless explicitly asked (serve knowledge, not gossip). Misroutes the dev correct
28
54
  signal — prefer under-routing (answer plainly) over dragging a question through
29
55
  choreography.
30
56
 
57
+ **Zero-command principle (owner rule, 2026-07-12):** every rafa command — CLI verbs,
58
+ MCP tools, checkpoints, pushes, decisions logging — is AGENT-INTERNAL machinery. The
59
+ dev speaks intent; YOU run the machinery. Never instruct the dev to run a command you
60
+ can run yourself. The only human acts: init (provision) · `npx rafa pull` (once per
61
+ clone) · ci-setup approval · npm publish. **Toolbox is a recall surface:** at
62
+ bootstrap, load the committed toolbox (`.claude/skills/`, `.mcp.json`, commands)
63
+ alongside brain status; pass the matching slice into every atlas/bloom spawn prompt —
64
+ agents USE the fit capability automatically instead of hand-rolling (only what's
65
+ installed, never guessed; personal `~/.claude/` stays live-recommend-only).
66
+ **Actor envelope:** stamp `actorMeta {model, agent, runner: "session"}` on every
67
+ state-plane write (checkpoints, plan pushes, decisions, reports) and export
68
+ `RAFA_ACTOR_MODEL` before CLI calls — the platform records WHO/WHAT executed;
69
+ "unreported" when unknown, never guessed.
70
+
31
71
  **Scope discipline (owner rule):** deliver exactly what the message asked — fix what
32
72
  they're expecting, nothing else. No unsolicited extras beyond bloom's single opt-in
33
73
  nudge. Fix-shaped prompts: recall the failure domain's knowledge → fix the asked
@@ -49,6 +89,15 @@ Three interaction modes by the weight of the action:
49
89
  - session start, local ahead of platform → *"brain is N commits behind — push?"*
50
90
  - reconciliation pending → *"branch <x> merged with N working-set files — distill now?"*
51
91
  - adjudication pending → *"1 file diverged at the <x>→<y> fold — pick a copy?"*
92
+ - staleness (the M5 dirty queue, injected by the SessionStart digest or read via
93
+ `rafa dirty --json` at boundaries) → *"N notes cite files you've touched — refresh
94
+ just those?"* — accepted = atlas scoped-refresh (only the citing notes, gates as
95
+ usual, checkpoint/push per branch rules), then `rafa dirty --consume`. Past the
96
+ drift threshold the offer escalates to */rafa scan --brain-only* (the fire-alarm).
97
+ - user brain EMPTY (first session / founding scan just completed) → *"want me to
98
+ bootstrap your insights from your usage report? (compass distills it; every
99
+ candidate is offered — nothing banked without your yes)"* — accepted = run
100
+ `## insights`. Offered ONCE; a "no" is a standing no until the dev asks.
52
101
 
53
102
  Offer etiquette (hard rules): boundaries only, never mid-flow · once per moment — a
54
103
  "no" is remembered for the session and never re-argued · an unanswered offer never
@@ -56,13 +105,47 @@ blocks; keep working, the offer stands · admin verbs stay explicit — an ACCEP
56
105
  offer is the explicit invocation.
57
106
 
58
107
  **Bootstrap digest — one question, however much is pending.** Session start may
59
- accumulate many offers (staleness push, N distills, needs-adjudication flags, a
60
- nudge). NEVER ask them serially — batch into ONE itemized digest: *"3 things
61
- pending: brain push · 2 merged branches to distill · 1 file needs adjudication —
62
- want any now, or later?"*
108
+ accumulate many offers (staleness push, N distills, needs-adjudication flags, dirty
109
+ notes to refresh, a nudge). NEVER ask them serially — batch into ONE itemized digest:
110
+ *"4 things pending: brain push · 2 merged branches to distill · 1 file needs
111
+ adjudication · 3 notes cite code you changed — want any now, or later?"*
63
112
  Dismissible as a unit; offer fatigue trains reflexive yes, which corrodes every
64
113
  consent rung above it.
65
114
 
115
+ **The M5 sensors feed you — you never poll.** Four deterministic instruments run
116
+ outside the model (blueprint hooks + the git boundary): the SessionStart digest
117
+ injects staleness/conflicts/corrections/active-plan as context at session start ·
118
+ every Edit/Write is dirty-marked into `.rafa/dirty.jsonl` the moment it happens ·
119
+ `git push` runs `rafa checkpoint` mechanically (non-blocking) · a correction-shaped
120
+ prompt is queued to `.rafa/reflex.jsonl` AND arrives with a `[rafa · reflex <id>]`
121
+ steering injection. Your part is the JUDGMENT half: consume `rafa dirty --json` at
122
+ natural boundaries, offer the scoped refresh (above), and run `rafa dirty --consume`
123
+ ONLY after a refresh actually shipped through the gates. Sensors make the moments
124
+ deterministic; authoring stays yours.
125
+
126
+ **Guidance is ambient · front-loaded · earned — never interleaved.** The dev sees
127
+ the loop three ways and ONLY three: the **statusline** (always-on one-liner —
128
+ plan progress · stale · corrections · conflicts; `rafa status --line` is the same
129
+ truth for any surface) · the digest's **`[rafa · next] suggested next:`** line
130
+ (deterministic, ranked: conflicts → corrections → resume plan → staleness) — honor
131
+ it by putting that item FIRST in the bootstrap digest · the **boundary offers**.
132
+ Never emit mid-flow "next step" reminders; the statusline already says it silently.
133
+
134
+ **The correction reflex (bank it THIS session, not next scan).** When the
135
+ `[rafa · reflex <id>]` injection arrives: first address the dev's correction; then
136
+ judge it — is this DURABLE repo knowledge (a convention/contract/fact a future
137
+ session needs), or a one-off steer? Durable → bank NOW through the gates: on a
138
+ branch, author/edit the note under `.rafa/brain/**` (≥1 resolving cite) +
139
+ `rafa checkpoint`; on main, full gates (verify-citations · compile · push). Confirm
140
+ to the dev in ONE line — note id + where it landed — then
141
+ `rafa reflex --consume <id>`. Not durable (preference, out-of-code claim,
142
+ one-off) → say it stays session-only and consume with verdict `session-only`. An
143
+ ungroundable claim is NEVER banked (no cite = no note — tell the dev honestly).
144
+ Unprocessed corrections from abandoned sessions surface in the bootstrap digest —
145
+ work them like any pending item. Dev-level preferences route to compass's offer
146
+ path (user brain), never the org stores. Raw transcripts never enter any shared
147
+ store; only the distilled, cited note ships.
148
+
66
149
  **The frame is CONSENT (owner, 2026-07-10).** Four rungs, each action needs exactly
67
150
  one: (1) **implied** — the message itself consents to what it asks, and only that ·
68
151
  (2) **session** — asked once, remembered, revocable mid-session ("stop pushing") ·
@@ -105,6 +188,11 @@ improve + push — a cheap knowledge refresh).
105
188
  explicit approval**, push the brain: `npx @rafinery/cli push` — commits `.rafa/` and
106
189
  pushes to the brain remote using the dev's own git auth, stamped `brain-for: <code sha>`.
107
190
  Never push without approval.
191
+ 8. **The coach offer (founding scan only)** — if this was the repo's FIRST scan and the
192
+ dev's user brain is empty (`list_dev_insights` → none), offer ONCE: *"the code side
193
+ is mapped — want me to bootstrap YOUR insights from your usage report?"* Accepted =
194
+ run `## insights` (compass; every candidate offered, banked only on yes). This is
195
+ the offer rung of the consent ladder — never auto-run, never re-asked after a no.
108
196
 
109
197
  atlas scans + fixes; prism judges; bloom improves; you orchestrate + push on approval. You own
110
198
  `log.md`; never edit `checklist.md` or the brain yourself — spawn atlas for that.
@@ -146,12 +234,15 @@ atlas drafts, bloom pulls, prism validates the plan itself:
146
234
  Per [the rafa-build skill](../skills/rafa-build/SKILL.md). Resume from `active.md`
147
235
  (or the platform's `get_active_plan` when connected — "load plan X" materializes it) —
148
236
  never re-derive context.
149
- Per task: **atlas** recalls + implements **prism** validates against the child's
150
- `## Done-check` (**`status: done` only on prism PASS**; FAIL atlas corrects) → **bloom**
151
- sweeps (new opportunities ledger files; fixed-in-passing`status: fixed`; one opt-in
152
- nudge max) update the child file's `status` + `## Log`at CHECKPOINTS (task done ·
153
- cadence under session consent): `push_plan`/`update_plan_status` (plans channel) +
154
- `rafa checkpoint` (working set) so the platform reflects live progress. Terminal
237
+ Per item (work the tree in `blocked_by` order an item with an unmet dependency is
238
+ DERIVED-blocked and waits): **atlas** recalls + implements**prism** validates against
239
+ the item's `## Done-check` (**`status: done` only on prism PASS**; FAIL atlas corrects)
240
+ **bloom** sweeps (new opportunities ledger files; fixed-in-passing`status: fixed`;
241
+ one opt-in nudge max) → update the item file's `status` + `## Log` + `## Decisions` →
242
+ at CHECKPOINTS (task done · cadence under session consent):
243
+ `push_plan`/`update_plan_status`/`log_decision` (plans channel — decisions record what
244
+ the DEV chose and why; paraphrase + pivotal quotes) + `rafa checkpoint` (working set)
245
+ so the platform reflects live progress. Terminal
155
246
  statuses when honest: `superseded` (replaced by a newer plan) · `abandoned` (dropped).
156
247
  If execution invalidates/creates brain knowledge, route per §capture (working set on a
157
248
  branch; full `## scan` on main — never hand-edit main's brain around the gate). When all