@rafinery/cli 0.15.0 → 0.15.2

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 CHANGED
@@ -4,6 +4,30 @@ 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.15.2 — rafa-validate implements the parallel-brain check
8
+
9
+ sage caught a card-ahead-of-procedure gap: prism's card claimed "a refresh that
10
+ minted parallel ids is a BLOCKER," but `rafa-validate` — the procedure prism
11
+ follows — never implemented the check. It was documented, not load-bearing.
12
+
13
+ `rafa-validate` step 9 now performs the continuity check: for every note the
14
+ refresh *added*, compare against the prior manifest — same domain/category +
15
+ equal-ish title or ≥50% shared cited files = a parallel-id blocker (founding
16
+ scans exempt). It's the scan-time twin of the reconciler's merge-time guard, so
17
+ the rule is enforced by a procedure at both ends.
18
+
19
+ ## 0.15.1 — fix `rafa reflex --consume` verdict parsing
20
+
21
+ A `rafa reflex --consume <id> --reason session-only` silently recorded `banked`
22
+ instead — the parser only accepted a bare positional verdict and rejected
23
+ anything starting with `-`, then fell through to the `banked` default. That's a
24
+ silent wrong value, exactly what the platform forbids.
25
+
26
+ Now the verdict accepts a flag form (`--verdict=<v>` / `--reason=<v>`, plus the
27
+ bare positional), and an **unrecognized verdict fails loudly** instead of
28
+ defaulting — a session-only correction is recorded session-only, or the consume
29
+ errors. Regression-tested.
30
+
7
31
  ## 0.15.0 — learnings are a `.rafa/` sibling
8
32
 
9
33
  sage's learnings move out of committed `.claude/rafa/learnings/` and become a
@@ -86,9 +86,21 @@ agent. So:
86
86
  (it violates the net-positive law: a wrong note is worse than none).
87
87
  8. **Connectivity** — orphan notes, dangling links (the checker's LINKS warn lane —
88
88
  `citation-check.md` § Links — is your pre-built worklist), literal `[[...]]` in prose → minor.
89
+ 9. **Continuity — the parallel-brain check (REFRESH scans only; contract §12.4).** A refresh
90
+ MUST update the existing brain in place, never re-derive a differently-named twin over
91
+ concepts the org already carries. Detect it: for each note/improvement the scan ADDED
92
+ (not in the prior brain), check whether an existing note in the same `domain`/`category`
93
+ already covers the concept — same/near-equal `title`, or ≥50% shared cited files. A new id
94
+ that duplicates an existing concept is a **BLOCKER** (continuity is the product: a parallel
95
+ brain orphans triage, resets trends, and destroys id stability). Ground it against the prior
96
+ brain: compare the scan's output ids to the pre-scan manifest; every genuinely-new id must
97
+ name, in its body, why no existing note covers it. (This is the validation twin of the
98
+ reconciler's deterministic parallel-brain guard — prism catches at scan-time what the guard
99
+ catches at merge-time; a founding scan, with no prior brain, is exempt.)
89
100
 
90
101
  ## Severity + decision
91
- - **Blocker** — hard-gate failure, broken checker, or a wrong/misleading note. Must be **0**.
102
+ - **Blocker** — hard-gate failure, broken checker, a wrong/misleading note, or a refresh that
103
+ minted parallel ids over existing concepts (continuity, step 9). Must be **0**.
92
104
  - **Major** — a real gap: missing essence, under-covered domain, unanswerable question.
93
105
  - **Minor** — nits (orphan, cosmetic). Logged, not looped on.
94
106
  - **PASS** = hard gates pass · quality score ≥ 85 · 0 blockers · majors ≤ 2 · **and no
package/lib/reflex.mjs CHANGED
@@ -3,7 +3,10 @@
3
3
  //
4
4
  // rafa reflex list unprocessed corrections
5
5
  // rafa reflex --json machine shape (bootstrap digest / spawn prompts)
6
- // rafa reflex --consume <id> [reason] mark one processed AFTER it was banked
6
+ // rafa reflex --consume <id> [verdict] mark one processed. verdict
7
+ // banked | session-only | refuted — a bare word, or --verdict=<v> /
8
+ // --reason=<v>. Omitted ⇒ banked (the SOP default). An UNRECOGNIZED
9
+ // verdict fails loudly — never a silent wrong outcome (no assumed values).
7
10
  // through the gates, or judged session-only
8
11
  //
9
12
  // Consume APPENDS a done-marker line ({id, done:true, verdict, at}) — the queue
@@ -50,7 +53,40 @@ export default async function reflex(args = []) {
50
53
  console.error(`✗ no unprocessed correction with id ${id} (see \`rafa reflex\`)`);
51
54
  process.exit(1);
52
55
  }
53
- const verdict = args[ci + 2] && !args[ci + 2].startsWith("-") ? args[ci + 2] : "banked";
56
+ // The verdict from a bare positional (`--consume <id> session-only`) OR a
57
+ // flag (`--verdict=X` · `--verdict X` · `--reason=X` · `--reason X`; the
58
+ // human reaches for `--reason`, so accept it). NO ASSUMED VALUES: default to
59
+ // `banked` ONLY when no verdict was supplied at all; an unrecognized verdict
60
+ // — or a flag whose value is unrecognized — fails LOUDLY rather than
61
+ // silently recording the wrong outcome (the 2026-07-27 mislabel: a
62
+ // `--reason session-only` fell through to a false `banked`).
63
+ const VERDICTS = ["banked", "session-only", "refuted"];
64
+ const rest = args.slice(ci + 2);
65
+ let verdict = null;
66
+ let supplied = false;
67
+ for (let i = 0; i < rest.length; i++) {
68
+ const a = rest[i];
69
+ const m = a.match(/^--(?:verdict|reason)(?:=(.+))?$/);
70
+ if (m) {
71
+ supplied = true;
72
+ verdict = m[1] ?? rest[++i] ?? null; // `=value` or the next token
73
+ } else if (!a.startsWith("-")) {
74
+ supplied = true;
75
+ verdict = a; // bare positional verdict
76
+ } else {
77
+ continue; // an unrelated flag (e.g. a future --json) — skip, don't consume it as a verdict
78
+ }
79
+ break;
80
+ }
81
+ if (!supplied) verdict = "banked"; // bare `--consume <id>` — the SOP's default
82
+ else if (!VERDICTS.includes(verdict)) {
83
+ console.error(
84
+ `✗ unrecognized verdict ${verdict === null ? "(none given after the flag)" : `"${verdict}"`} — ` +
85
+ `expected one of: ${VERDICTS.join(" | ")}.\n` +
86
+ ` usage: rafa reflex --consume <id> [${VERDICTS.join("|")}] (bare word, or --verdict=<v> / --reason=<v>)`,
87
+ );
88
+ process.exit(1);
89
+ }
54
90
  appendFileSync(
55
91
  file,
56
92
  JSON.stringify({ id, done: true, verdict, at: new Date().toISOString() }) + "\n",
package/lib/releases.mjs CHANGED
@@ -501,6 +501,34 @@ export const RELEASES = [
501
501
  "governance framing is retired; the DB is the store, `.rafa/learnings/` " +
502
502
  "the local working copy — no learning files clutter `.claude/`.",
503
503
  },
504
+ {
505
+ version: "0.15.1",
506
+ contract: 1,
507
+ plans: 2,
508
+ requires: "update",
509
+ summary:
510
+ "FIX `rafa reflex --consume`: the verdict now accepts a flag form " +
511
+ "(`--verdict=<v>` / `--reason=<v>`, since the human reaches for " +
512
+ "`--reason`) as well as the bare positional, and an UNRECOGNIZED verdict " +
513
+ "fails loudly instead of silently defaulting to `banked` (the 2026-07-27 " +
514
+ "mislabel: `--reason session-only` fell through to a false `banked` in " +
515
+ "reflex.jsonl + the loop event). No assumed values — a session-only " +
516
+ "correction is recorded session-only, or the consume errors.",
517
+ },
518
+ {
519
+ version: "0.15.2",
520
+ contract: 1,
521
+ plans: 2,
522
+ requires: "update",
523
+ summary:
524
+ "FIX a card-ahead-of-procedure gap (sage-caught): prism's card claimed " +
525
+ "'a refresh that minted parallel ids is a BLOCKER' but rafa-validate — " +
526
+ "the procedure prism follows — never implemented the check. rafa-validate " +
527
+ "step 9 now performs the continuity/parallel-brain check (added-note ids " +
528
+ "vs the prior manifest; same domain/category + title-or-cite overlap = " +
529
+ "blocker; founding exempt) — the scan-time twin of the reconciler's " +
530
+ "deterministic guard. A documented rule made load-bearing.",
531
+ },
504
532
  ];
505
533
 
506
534
  // The release this CLI build ships (last entry).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rafinery/cli",
3
- "version": "0.15.0",
3
+ "version": "0.15.2",
4
4
  "description": "rafa — the AI engineer CLI. Vendors the rafa blueprint into your repo (shadcn-style) and runs the deterministic contract gates.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "generatedAt": "2026-07-26T22:32:00.748Z",
2
+ "generatedAt": "2026-07-26T23:37:59.067Z",
3
3
  "skills": {
4
4
  "tdd": {
5
5
  "version": "1.0.0",