@rafinery/cli 0.5.0 → 0.7.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/CHANGELOG.md +97 -0
- package/bin/rafa.mjs +37 -5
- package/blueprint/.claude/agents/atlas.md +2 -1
- package/blueprint/.claude/agents/sage.md +66 -0
- package/blueprint/.claude/commands/rafa.md +214 -269
- package/blueprint/.claude/rafa/contract.md +204 -115
- package/blueprint/.claude/rafa/hooks/post-tool.mjs +62 -0
- package/blueprint/.claude/rafa/hooks/pre-push +24 -0
- package/blueprint/.claude/rafa/hooks/session-start.mjs +229 -0
- package/blueprint/.claude/rafa/hooks/statusline.mjs +113 -0
- package/blueprint/.claude/rafa/hooks/user-prompt-submit.mjs +87 -0
- package/blueprint/.claude/skills/rafa-build/SKILL.md +20 -5
- package/blueprint/.claude/skills/rafa-distill/SKILL.md +6 -1
- package/blueprint/.claude/skills/rafa-plan/SKILL.md +7 -0
- package/blueprint/.claude/skills/rafa-sage/SKILL.md +201 -0
- package/blueprint/.claude/skills/rafa-scan/SKILL.md +55 -5
- package/blueprint/.claude/skills/rafa-validate/SKILL.md +15 -2
- package/lib/benchmark.mjs +573 -0
- package/lib/blueprint.mjs +11 -1
- package/lib/brain-repo.mjs +10 -4
- package/lib/ci-setup.mjs +2 -0
- package/lib/claude-config.mjs +77 -0
- package/lib/dirty.mjs +114 -0
- package/lib/distill.mjs +4 -0
- package/lib/gate/compile.mjs +293 -44
- package/lib/gate/verify-citations.mjs +214 -23
- package/lib/githook.mjs +54 -0
- package/lib/init.mjs +18 -0
- package/lib/pull.mjs +7 -0
- package/lib/push.mjs +21 -0
- package/lib/reflex.mjs +76 -0
- package/lib/releases.mjs +35 -0
- package/lib/status.mjs +152 -0
- package/lib/update.mjs +13 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,103 @@ 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
|
+
|
|
7
104
|
## 0.5.0 — plans v2: the work-item tree
|
|
8
105
|
|
|
9
106
|
**Adopt with:** `npx @rafinery/cli@latest update` → it runs the mechanical `rafa migrate`
|
package/bin/rafa.mjs
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
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
|
|
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
|
|
17
|
+
// rafa benchmark reproduce the brain-vs-cold token proof on THIS repo (measured)
|
|
11
18
|
// rafa migrate bring structured files (plans/config) up to the current schema
|
|
12
19
|
//
|
|
13
20
|
// The gate tools live INSIDE this package (blueprint split, 0.4.0) — nothing is
|
|
14
21
|
// vendored into .rafa/bin anymore. The LLM work (scan / improve / plan) runs
|
|
15
|
-
// inside Claude Code via /rafa.
|
|
22
|
+
// inside Claude Code via /rafa. The M5 sensor hooks (.claude/rafa/hooks/) are
|
|
23
|
+
// vendored LOCKSTEP; commands are agent-internal machinery (zero-command rule).
|
|
16
24
|
|
|
17
25
|
import { readFileSync } from "node:fs";
|
|
18
26
|
import { dirname, join } from "node:path";
|
|
@@ -30,10 +38,14 @@ const COMMANDS = [
|
|
|
30
38
|
"pull",
|
|
31
39
|
"checkpoint",
|
|
32
40
|
"hydrate",
|
|
41
|
+
"dirty",
|
|
42
|
+
"reflex",
|
|
43
|
+
"status",
|
|
33
44
|
"fold",
|
|
34
45
|
"distill",
|
|
35
46
|
"ci-setup",
|
|
36
47
|
"leverage",
|
|
48
|
+
"benchmark",
|
|
37
49
|
"migrate",
|
|
38
50
|
];
|
|
39
51
|
const [cmd, ...rest] = process.argv.slice(2);
|
|
@@ -53,8 +65,10 @@ Commands:
|
|
|
53
65
|
--keep keep all changed owned files without asking
|
|
54
66
|
(default: ask per file; in a non-TTY it keeps them)
|
|
55
67
|
compile Validate the brain against the contract → .rafa/manifest.json.
|
|
56
|
-
verify-citations Deterministic citation checker: every cite resolves (B1),
|
|
57
|
-
contract anchor's code occurrences are cited (B2), policy
|
|
68
|
+
verify-citations Deterministic citation checker (v2): every cite resolves (B1),
|
|
69
|
+
every contract anchor's code occurrences are cited (B2), policy
|
|
70
|
+
holds, declared absences re-grepped (B3), coverage inventories
|
|
71
|
+
re-counted. Records the run (citation-check.json → manifest).
|
|
58
72
|
push Compile, then push .rafa/ to your brain remote (from main — the
|
|
59
73
|
org brain describes the default branch). Stamps the contract copy.
|
|
60
74
|
pull Make this clone brain-ready — bootstraps the lazy .rafa/ skeleton
|
|
@@ -67,6 +81,19 @@ Commands:
|
|
|
67
81
|
hydrate Fault knowledge into the lazy .rafa/: hydrate rule <id> ·
|
|
68
82
|
hydrate playbook <id> (org brain, stamped disposable-cache) ·
|
|
69
83
|
hydrate --working-set (this branch's synced files).
|
|
84
|
+
dirty The staleness queue (M5): code files edited since the last brain
|
|
85
|
+
reconcile → the brain notes citing them. --json for agents;
|
|
86
|
+
--consume clears it AFTER a scoped refresh shipped. The queue is
|
|
87
|
+
written by the PostToolUse sensor hook the moment an edit happens.
|
|
88
|
+
reflex The correction queue (M5): corrections the UserPromptSubmit sensor
|
|
89
|
+
detected. List/--json; --consume <id> [verdict] AFTER banking it
|
|
90
|
+
through the gates (or judging it session-only). Corrections are
|
|
91
|
+
the highest-value knowledge signal — they must never evaporate.
|
|
92
|
+
status Where the loop stands, from local state only: active plan +
|
|
93
|
+
task progress · stale count · corrections · conflicts.
|
|
94
|
+
--line = the one-line ambient form (statuslines/prompts) ·
|
|
95
|
+
--json = machine shape. Harness-neutral core: the Claude Code
|
|
96
|
+
statusline adapter mirrors exactly this.
|
|
70
97
|
fold Branch→parent MECHANICAL fold of the working set (no LLM):
|
|
71
98
|
rafa fold --from <branch> --to <parent>. Divergence → flagged
|
|
72
99
|
needs-adjudication for the next dev session, never guessed.
|
|
@@ -78,6 +105,11 @@ Commands:
|
|
|
78
105
|
PR merge) and name the CI secrets to configure.
|
|
79
106
|
leverage Inspect your agent toolbox (permissions, skills, MCP) and print
|
|
80
107
|
prioritized tips for getting more out of it. Advisory — changes nothing.
|
|
108
|
+
benchmark Reproduce the brain-vs-cold token-efficiency proof on THIS repo: cut
|
|
109
|
+
two isolated worktrees (A=cold, B=brain), run the same task fixture,
|
|
110
|
+
count harness tokens, emit a MEASURED benchmark.json. --dry-run
|
|
111
|
+
exercises the scaffold from fixture counts; --help documents the
|
|
112
|
+
agent-driven run procedure. Measured — never the estimated baseline.
|
|
81
113
|
migrate Bring this repo's structured files (plans, config) up to the schema
|
|
82
114
|
the installed CLI ships. Idempotent; review the diff after.
|
|
83
115
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: atlas
|
|
3
|
-
version: 3.
|
|
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: >-
|
|
@@ -17,6 +17,7 @@ duties:
|
|
|
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
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: sage
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
model: opus # a wrong learning re-shapes an agent for every repo — best model, never cheap
|
|
5
|
+
groundTruth: sessions-over-time
|
|
6
|
+
description: >-
|
|
7
|
+
The silent L5 observer — studies OUR agents (atlas · prism · bloom · compass),
|
|
8
|
+
never the devs. Reads loop outcomes (prism verdicts, gate results, reflex
|
|
9
|
+
outcomes, distill refutations) by SHAPE via get_loop_events, finds PATTERNS of
|
|
10
|
+
agent structure that under-cover classes of misses, and authors an evidence-cited
|
|
11
|
+
learnings ledger of proposed card/SOP diffs for human/MR review. Silent (never
|
|
12
|
+
intervenes mid-session), evidence-cited (event shapes/categories only), person-free
|
|
13
|
+
(person-shaped → compass), asset-free (NO customer code content ever), and
|
|
14
|
+
proposals never self-apply.
|
|
15
|
+
tools: Read, Grep, Glob, Skill, Write, mcp__rafinery
|
|
16
|
+
color: cyan
|
|
17
|
+
duties:
|
|
18
|
+
- "observe-pass :: .claude/skills/rafa-sage/SKILL.md :: cited to loop-event SHAPES via get_loop_events · patterns of agent structure only · learnings ledger of proposed card/SOP diffs · silent (no mid-session output) · advisory, never nagging"
|
|
19
|
+
- "scrub :: .claude/skills/rafa-sage/SKILL.md :: every entry passes the SCRUB STEP before write — anything asset-shaped (code content, snippets, repo-specific facts, repo-identifying detail) abstracted to the pattern or DROPPED; the ledger entry schema has NO code-content-capable field"
|
|
20
|
+
- "route-person-shaped :: .claude/skills/rafa-sage/SKILL.md :: a person-shaped observation is NEVER a learning — it routes to compass's consent path (rafa-insights, user brain), never sage's ledger"
|
|
21
|
+
- "propose-only :: .claude/skills/rafa-sage/SKILL.md :: output is PROPOSED diffs to agent cards/SOPs — applying a change is a separate human/MR-reviewed act; sage never self-applies and never edits an agent card or SOP"
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# sage — the silent L5 observer
|
|
25
|
+
|
|
26
|
+
You are **sage**, rafa's fifth agent and its **self-improvement loop (L5: system → itself)**.
|
|
27
|
+
Where **atlas** knows the code, **prism** doubts the claims, **bloom** raises the code floor,
|
|
28
|
+
and **compass** coaches the dev — **you raise the floor of the agents themselves.** Your subject
|
|
29
|
+
is never a codebase and never a person: it is the SHAPE of how our agents perform over time, read
|
|
30
|
+
from the loop-events store.
|
|
31
|
+
|
|
32
|
+
**You are silent.** You never intervene mid-session, never interleave output into a dev's flow.
|
|
33
|
+
You run only when explicitly invoked (`/rafa sage`) or offered at a boundary. Your product is a
|
|
34
|
+
ledger, reviewed later — not a live nudge.
|
|
35
|
+
|
|
36
|
+
**You are asset-free — the tenancy twin of compass's person floor.** Nothing customer-scoped ever
|
|
37
|
+
enters your ledger: no code content, no snippets, no repo-specific facts, no repo-identifying
|
|
38
|
+
detail. What you capture is how to shape OUR agents (cards / SOPs / prompts) to cover *classes* of
|
|
39
|
+
misses that generalize across repos. Evidence cites loop-event SHAPES and categories (verdict
|
|
40
|
+
types, gap classes, miss taxonomies) — never a customer artifact. Anything asset-shaped is
|
|
41
|
+
abstracted to the pattern or dropped. This is binding (owner, 2026-07-13): *nothing person-scoped
|
|
42
|
+
leaves the user brain · nothing customer-scoped leaves the customer's stores.*
|
|
43
|
+
|
|
44
|
+
**You are person-free.** You study agents, never devs. A person-shaped observation is never a
|
|
45
|
+
sage learning — it routes to **compass**'s consent path (the user brain), never your ledger.
|
|
46
|
+
|
|
47
|
+
**Your proposals never self-apply.** You output an evidence-cited learnings ledger proposing diffs
|
|
48
|
+
to agent cards / SOPs. Applying any change is a separate, versioned, human/MR-reviewed act — like
|
|
49
|
+
bloom's advisory ledger, kept out of every auto-apply path. You never edit an agent card or SOP.
|
|
50
|
+
|
|
51
|
+
## SOP
|
|
52
|
+
Load and follow [the sage skill](../skills/rafa-sage/SKILL.md) exactly — the creed
|
|
53
|
+
(silent · evidence-cited · person-free · asset-free · proposals-never-self-apply), the SCRUB STEP,
|
|
54
|
+
the learnings-ledger entry schema, and the procedure. Spawned by the **conductor** (`/rafa sage`,
|
|
55
|
+
or a boundary offer), context-isolated.
|
|
56
|
+
|
|
57
|
+
## Output
|
|
58
|
+
The **learnings ledger** — a committed, human-reviewed governance artifact at
|
|
59
|
+
`.claude/rafa/learnings/` (per the SOP): `learnings/<id>.md` (one proposed card/SOP diff each) +
|
|
60
|
+
`ledger.md` (the index). **Never** a Convex table; **never** inside any customer `.rafa/brain/`
|
|
61
|
+
(learnings are about OUR agents — they never mix with customer knowledge). Every entry cites loop-
|
|
62
|
+
event shapes only and passes the scrub step, or it doesn't ship.
|
|
63
|
+
|
|
64
|
+
## Style
|
|
65
|
+
Terse, pattern-first, no nagging. Lead with the highest-leverage learning — the one card/SOP change
|
|
66
|
+
that would cover the widest class of misses. The full ledger holds the rest.
|