@rafinery/cli 0.10.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.
@@ -268,22 +268,26 @@ export function runCompile(argv = []) {
268
268
  "leverage",
269
269
  "required · { impact, effort } ∈ low|medium|high",
270
270
  );
271
+ // `category` is canonical; `lens` is the pre-2026-07-26 name, accepted
272
+ // as a deprecated alias so already-authored ledgers keep compiling.
273
+ const category = reqEnum(
274
+ { category: data.category ?? data.lens },
275
+ "category",
276
+ [
277
+ "security",
278
+ "correctness",
279
+ "performance",
280
+ "architecture",
281
+ "product",
282
+ "ops",
283
+ ],
284
+ path,
285
+ );
271
286
  out.push({
272
287
  id,
273
288
  priority: reqEnum(data, "priority", ["P0", "P1", "P2", "P3"], path),
274
- lens: reqEnum(
275
- data,
276
- "lens",
277
- [
278
- "security",
279
- "correctness",
280
- "performance",
281
- "architecture",
282
- "product",
283
- "ops",
284
- ],
285
- path,
286
- ),
289
+ category,
290
+ lens: category, // transitional dual-key — dropped with the backfill arc
287
291
  status: reqEnum(
288
292
  data,
289
293
  "status",
package/lib/init.mjs CHANGED
@@ -183,8 +183,9 @@ export default async function init(args) {
183
183
  );
184
184
  }
185
185
 
186
- // Reconciliation runs on the PLATFORM (App-only era, owner call 2026-07-18):
187
- // merged PRs are detected and distilled by the platform's own sandbox — no
186
+ // Reconciliation runs on the PLATFORM (App-only era, owner call 2026-07-18;
187
+ // agent-native since 2026-07-21): merged PRs are detected and reconciled by
188
+ // the server-side LangGraph agent — no
188
189
  // CI workflow, no repo secrets, nothing to wire here. The org-CI adapter
189
190
  // stays available as an explicit opt-out for teams that want the compute in
190
191
  // their own CI: `rafa ci-setup`. Init no longer asks — one fewer question,
package/lib/manifest.mjs CHANGED
@@ -165,7 +165,8 @@ export default async function manifest() {
165
165
  return {
166
166
  id,
167
167
  priority: PRIORITIES.has(d.priority) ? d.priority : "P2",
168
- lens: str(d.lens, "general"),
168
+ category: str(d.category ?? d.lens, "general"),
169
+ lens: str(d.category ?? d.lens, "general"), // transitional mirror of category
169
170
  status: IMP_STATUSES.has(d.status) ? d.status : "open",
170
171
  title: str(d.title, id),
171
172
  summary: str(d.summary),
@@ -18,12 +18,20 @@ import { CLI_VERSION } from "./releases.mjs";
18
18
 
19
19
  // The CLI's own actor envelope for state-plane writes (wave 5: REQUIRED on every
20
20
  // loop event — strict, no legacy path). model is the explicit "mechanical"
21
- // sentinel: no LLM ruled here, and the split stays grep-able for sage.
21
+ // sentinel: no LLM ruled here, and the split stays grep-able for sage. The
22
+ // runner honors RAFA_ACTOR_RUNNER first (platform tiers export it —
23
+ // sandbox|ci|session; "sandbox" is a legacy wire value kept for historical
24
+ // rows), else CI env, else session.
22
25
  export function cliActorMeta() {
26
+ const declared = process.env.RAFA_ACTOR_RUNNER;
23
27
  return {
24
28
  model: "mechanical",
25
29
  agent: `cli@${CLI_VERSION}`,
26
- runner: process.env.CI ? "ci" : "session",
30
+ runner: ["sandbox", "ci", "session"].includes(declared)
31
+ ? declared
32
+ : process.env.CI
33
+ ? "ci"
34
+ : "session",
27
35
  };
28
36
  }
29
37
 
package/lib/push.mjs CHANGED
@@ -189,6 +189,11 @@ export default async function push(args = []) {
189
189
  // on it.
190
190
  const verbArg = args.find((a) => a.startsWith("--verb="));
191
191
  const verb = verbArg ? verbArg.slice("--verb=".length) : "update";
192
+ // Custom subject (owner 2026-07-26: reconciliation commits are DESCRIPTIVE):
193
+ // --message="…" replaces the generic manifest-derived subject; the brain-for
194
+ // trailer machinery below is untouched — provenance consumers keep their key.
195
+ const msgArg = args.find((a) => a.startsWith("--message="));
196
+ const customSubject = msgArg ? msgArg.slice("--message=".length).trim().replace(/"/g, "'") : null;
192
197
  const subjectParts = [];
193
198
  try {
194
199
  const m = JSON.parse(readFileSync(join(rafaDir, "manifest.json"), "utf8"));
@@ -214,9 +219,10 @@ export default async function push(args = []) {
214
219
  } catch {
215
220
  /* stat is garnish */
216
221
  }
217
- const subject = `brain(${verb}): ${
218
- subjectParts.length ? subjectParts.join(" · ") : "state sync"
219
- } · brain-for: ${codeSha}`.replace(/"/g, "'");
222
+ const subject = (
223
+ customSubject ??
224
+ `brain(${verb}): ${subjectParts.length ? subjectParts.join(" · ") : "state sync"} · brain-for: ${codeSha}`
225
+ ).replace(/"/g, "'");
220
226
  try {
221
227
  inRafa(
222
228
  `git commit -m "${subject}" -m "brain-for: ${codeSha}${stagedStat ? ` · ${stagedStat}` : ""} · cli: ${CLI_VERSION}"`,
package/lib/releases.mjs CHANGED
@@ -382,6 +382,33 @@ export const RELEASES = [
382
382
  "--json` carries the harness-neutral agentSkills + skillDeps blocks; " +
383
383
  "doctor gains a capabilities section.",
384
384
  },
385
+ {
386
+ version: "0.11.0",
387
+ contract: 1,
388
+ plans: 2,
389
+ requires: "update",
390
+ summary:
391
+ "SCHEMA-AWARE RECONCILIATION (owner's 4-case doctrine): distillation " +
392
+ "resolves the version lattice BEFORE judging — target below source → " +
393
+ "full target rewrite onto the newer schema (rides the run's gates + " +
394
+ "push); source below target → incoming candidates lift before judging; " +
395
+ "equal-but-old → the merged target rewrites onto the runner's latest; " +
396
+ "equal-and-current → plain diff (today). Either side newer than the " +
397
+ "runner aborts LOUDLY (update the runner; knowledge is never " +
398
+ "downgraded); transforms are registered per step and a missing step " +
399
+ "fails loudly — the ladder never guesses a schema. Also in this " +
400
+ "release (missed 0.10.0's publish): distill-refutation emits carry the " +
401
+ "required actor envelope + dedupeKey (a re-run counts once); " +
402
+ "cliActorMeta honors RAFA_ACTOR_RUNNER (sandbox|ci|session); dependsOn " +
403
+ "invalidation documented NOT transitive with breadth-as-conservative " +
404
+ "taught at facts add/help/prism's card (pinned by test). DESCRIPTIVE " +
405
+ "COMMITS: reconciliation pushes compose reconcile(<branch>): N banked " +
406
+ "· M refuted · K adjudication (rafa push --message= override); the " +
407
+ "commit contract requires an agent-readable body on dev commits. The " +
408
+ "configurable prod branch reaches the CLI: trunkBranchOf (stamp → " +
409
+ "origin/HEAD → main) drives the checkpoint trunk guard + CI distill " +
410
+ "target.",
411
+ },
385
412
  ];
386
413
 
387
414
  // The release this CLI build ships (last entry).
package/lib/stamp.mjs CHANGED
@@ -3,6 +3,7 @@
3
3
  // stamp against what the running CLI ships to know what changed and what to migrate FROM.
4
4
  // (Also holds platform identity fields when the repo was provisioned via a setup URL.)
5
5
 
6
+ import { execSync } from "node:child_process";
6
7
  import { existsSync, readFileSync, writeFileSync } from "node:fs";
7
8
  import { join } from "node:path";
8
9
  import { CURRENT, CLI_VERSION, RELEASES } from "./releases.mjs";
@@ -34,6 +35,29 @@ export function writeStamp(cwd, patch = {}) {
34
35
  return next;
35
36
  }
36
37
 
38
+ // The code repo's canonical (prod) branch (owner 2026-07-26: configurable,
39
+ // never hardcoded). Resolution chain: the rafa.json stamp's `prodBranch`
40
+ // (mirrors the platform's per-repo setting — carried down so the CLI's trunk
41
+ // guards agree with the platform's routing) → git's own origin/HEAD symref
42
+ // (the repo's actual default) → "main".
43
+ export function trunkBranchOf(cwd) {
44
+ const s = readStamp(cwd);
45
+ if (typeof s.prodBranch === "string" && s.prodBranch.trim() !== "")
46
+ return s.prodBranch.trim();
47
+ try {
48
+ const out = execSync("git symbolic-ref refs/remotes/origin/HEAD", {
49
+ cwd,
50
+ encoding: "utf8",
51
+ stdio: ["ignore", "pipe", "ignore"],
52
+ }).trim();
53
+ const m = out.match(/refs\/remotes\/origin\/(.+)$/);
54
+ if (m) return m[1];
55
+ } catch {
56
+ /* no remote / no symref — fall through */
57
+ }
58
+ return "main";
59
+ }
60
+
37
61
  // The versions this repo was last stamped at. Un-stamped repos predate the stamp (added in
38
62
  // 0.2.0), so default to the FIRST release's schema — never raise a false migration alarm.
39
63
  export function stampedVersions(cwd) {
@@ -160,15 +160,16 @@ export function materializeImprovement(cwd, data, brainForSha) {
160
160
  }
161
161
 
162
162
  // Deterministic ledger-file writer for hydrated improvements — mirrors the shape
163
- // bloom authors (see any improve/improvements/*.md): priority · lens · status ·
163
+ // bloom authors (see any improve/improvements/*.md): priority · category · status ·
164
164
  // fix · leverage · blast_radius · cites, then the prose body.
165
165
  export function renderImprovement(d) {
166
+ const category = d.category ?? d.lens;
166
167
  const lines = [
167
168
  "---",
168
169
  "schemaVersion: 1",
169
170
  `id: ${d.id}`,
170
171
  `priority: ${d.priority}`,
171
- ...(d.lens ? [`lens: ${d.lens}`] : []),
172
+ ...(category ? [`category: ${category}`] : []),
172
173
  `status: ${d.status}`,
173
174
  `title: ${q(d.title)}`,
174
175
  ...(d.summary ? [`summary: ${q(d.summary)}`] : []),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rafinery/cli",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
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-25T18:10:32.629Z",
2
+ "generatedAt": "2026-07-26T15:51:05.847Z",
3
3
  "skills": {
4
4
  "tdd": {
5
5
  "version": "1.0.0",