@open-tomato/rafa 0.41.0 → 0.42.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.
@@ -1,49 +1,43 @@
1
1
  // @bun
2
2
  import {
3
+ BUSY_TIMEOUT_MAX_MS,
4
+ BUSY_TIMEOUT_MIN_MS,
3
5
  CONFIG_DEFAULTS,
4
6
  CONFIG_FILE,
5
7
  ConfigError,
6
8
  FINDING_DOMAINS,
7
9
  FINDING_KINDS,
8
10
  FINDING_SIGNALS,
9
- activeOutput,
10
- activeOutputMode,
11
- configFilePath,
12
- createTextOutput,
13
- hubContextOf,
14
- isStampableStub,
15
- parseConfigText,
16
- readRafaBlocks,
17
- resolveConfig
18
- } from "./index-3jpz9nr3.js";
19
- import {
20
- bless,
21
- merge
22
- } from "./index-d6d0942q.js";
23
- import {
24
- CommandExit,
25
- commandSpelling
26
- } from "./index-sr3kc4mf.js";
27
- import {
28
- BUSY_TIMEOUT_MAX_MS,
29
- BUSY_TIMEOUT_MIN_MS,
30
11
  RAFA_INSTINCTS_PATH,
31
12
  STORE_BACKENDS,
32
13
  SYNC_STRATEGIES,
33
14
  TEST_SCOPES,
15
+ activeOutput,
16
+ activeOutputMode,
34
17
  bundledBinDirectory,
18
+ configFilePath,
19
+ createTextOutput,
35
20
  describeValue,
21
+ hubContextOf,
36
22
  isBusyTimeoutMs,
37
23
  isGitHubLogin,
38
24
  isMapping,
25
+ isStampableStub,
39
26
  messageOf,
27
+ parseConfigText,
28
+ readRafaBlocks,
29
+ resolveConfig,
40
30
  resolveInstinctScopes,
41
31
  tierExists
42
- } from "./index-m2ahxjw8.js";
32
+ } from "./index-bceachy6.js";
33
+ import {
34
+ bless,
35
+ merge
36
+ } from "./index-nv34ptht.js";
43
37
  import {
44
38
  actionHash,
45
39
  triggerKey
46
- } from "./index-wp8c28fd.js";
40
+ } from "./index-hf2k497d.js";
47
41
 
48
42
  // src/adapters/registry.ts
49
43
  import { homedir } from "os";
@@ -259,13 +253,10 @@ import { Database as Database2 } from "bun:sqlite";
259
253
 
260
254
  // package.json
261
255
  var name = "@open-tomato/rafa";
262
- var version = "0.41.0";
256
+ var version = "0.42.0";
263
257
 
264
258
  // src/cli/version.ts
265
259
  var RAFA_VERSION = version;
266
- function versionLine() {
267
- return `rafa ${RAFA_VERSION}`;
268
- }
269
260
 
270
261
  // src/effort/store/development-build.ts
271
262
  import { tmpdir as tmpdir2 } from "os";
@@ -535,12 +526,6 @@ function writePositionFile(root, position) {
535
526
  function positionAt(place) {
536
527
  return { current: place, previous: null, home: place };
537
528
  }
538
- function rehome(position, place) {
539
- return { current: place, previous: position.current, home: place };
540
- }
541
- function hop(position, place) {
542
- return { current: place, previous: position.current, home: position.home };
543
- }
544
529
  function goHome(position) {
545
530
  return { current: position.home, previous: position.current, home: position.home };
546
531
  }
@@ -652,7 +637,6 @@ function staleAgainst(record, position) {
652
637
  // src/loop/session-record-parse.ts
653
638
  var SESSION_STATES = Object.freeze(["running", "paused", "stopped", "done"]);
654
639
  var SESSION_PHASES = Object.freeze(["task", "wrap-up", "pull-request", "ci", "repair"]);
655
- var DEFAULT_PHASE = "task";
656
640
  var RECORD_EXTENSION = ".json";
657
641
  var SESSION_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
658
642
  var SESSION_STEP_KINDS = Object.freeze(["baseline", "task", "stage", "pre-wrap-up"]);
@@ -698,8 +682,8 @@ function taskProblem(task) {
698
682
  function hopProblem(fields) {
699
683
  if (!Object.hasOwn(fields, "hop"))
700
684
  return null;
701
- const hop2 = field(fields, "hop");
702
- return asHopRecord(hop2) === null ? `hop is ${describeValue2(hop2)}, expected a hop record` : null;
685
+ const hop = field(fields, "hop");
686
+ return asHopRecord(hop) === null ? `hop is ${describeValue2(hop)}, expected a hop record` : null;
703
687
  }
704
688
  function worktreeProblem(fields) {
705
689
  if (!Object.hasOwn(fields, "worktree"))
@@ -845,8 +829,8 @@ function phaseEntry(phase) {
845
829
  return isSessionPhase(phase) ? { phase } : {};
846
830
  }
847
831
  function freezeHop(value) {
848
- const hop2 = asHopRecord(value);
849
- return Object.freeze({ ...hop2, home: Object.freeze(hop2.home), from: Object.freeze(hop2.from) });
832
+ const hop = asHopRecord(value);
833
+ return Object.freeze({ ...hop, home: Object.freeze(hop.home), from: Object.freeze(hop.from) });
850
834
  }
851
835
  function freezeFailures(failures) {
852
836
  return Object.freeze(failures.map((failure) => Object.freeze({ file: failure.file, name: failure.name })));
@@ -897,7 +881,7 @@ function decisionsEntry(decisions) {
897
881
  }
898
882
  function freezeRecord(fields) {
899
883
  const task = field(fields, "task");
900
- const hop2 = field(fields, "hop");
884
+ const hop = field(fields, "hop");
901
885
  const worktree = field(fields, "worktree");
902
886
  return Object.freeze({
903
887
  sessionId: field(fields, "sessionId"),
@@ -909,7 +893,7 @@ function freezeRecord(fields) {
909
893
  state: field(fields, "state"),
910
894
  task: isObject(task) ? Object.freeze({ line: field(task, "line"), text: field(task, "text") }) : null,
911
895
  ...phaseEntry(field(fields, "phase")),
912
- ...hop2 === undefined ? {} : { hop: freezeHop(hop2) },
896
+ ...hop === undefined ? {} : { hop: freezeHop(hop) },
913
897
  ...worktree === undefined ? {} : { worktree },
914
898
  ...stepsEntry(field(fields, "steps")),
915
899
  ...decisionsEntry(field(fields, "decisions"))
@@ -921,9 +905,6 @@ function sessionSteps(record) {
921
905
  function sessionDecisions(record) {
922
906
  return record.decisions ?? [];
923
907
  }
924
- function sessionPhase(record) {
925
- return record.phase ?? DEFAULT_PHASE;
926
- }
927
908
  function parseSessionRecord(text, file) {
928
909
  let parsed;
929
910
  try {
@@ -2212,8 +2193,32 @@ function openSqliteStore(repoRoot) {
2212
2193
  }
2213
2194
 
2214
2195
  // src/effort/sync/file.ts
2215
- import { existsSync as existsSync12 } from "fs";
2216
- import { join as join12, resolve as resolve5 } from "path";
2196
+ import { existsSync as existsSync11 } from "fs";
2197
+ import { join as join13, resolve as resolve5 } from "path";
2198
+
2199
+ // src/cli/spends.ts
2200
+ var SPENDS_GLYPH = "\uD83E\uDE99";
2201
+
2202
+ // src/cli/command.ts
2203
+ var MAX_EXIT_CODE = 255;
2204
+
2205
+ class CommandExit extends Error {
2206
+ exitCode;
2207
+ constructor(exitCode, message = "") {
2208
+ super(message);
2209
+ if (!Number.isInteger(exitCode) || exitCode < 0 || exitCode > MAX_EXIT_CODE) {
2210
+ throw new TypeError(`CommandExit: exit code is ${describeValue(exitCode)}, expected a whole number from 0 to ${MAX_EXIT_CODE}`);
2211
+ }
2212
+ this.name = "CommandExit";
2213
+ this.exitCode = exitCode;
2214
+ }
2215
+ }
2216
+ function isTopLevel(command) {
2217
+ return command.subject === command.action;
2218
+ }
2219
+ function commandSpelling(command) {
2220
+ return isTopLevel(command) ? command.subject : `${command.subject} ${command.action}`;
2221
+ }
2217
2222
 
2218
2223
  // src/effort/store/fix-schema.ts
2219
2224
  import { existsSync as existsSync8 } from "fs";
@@ -2587,7 +2592,7 @@ function withoutWayOut(message, nextStep) {
2587
2592
 
2588
2593
  // src/commands/plan/plan-files.ts
2589
2594
  import { statSync as statSync3 } from "fs";
2590
- import { resolve as resolve4 } from "path";
2595
+ import { basename as basename4, dirname as dirname11, join as join11, resolve as resolve4 } from "path";
2591
2596
 
2592
2597
  // src/config-load.ts
2593
2598
  import { existsSync as existsSync9, readFileSync as readFileSync8, realpathSync as realpathSync5 } from "fs";
@@ -2658,11 +2663,6 @@ function resolveProjectConfig(project, command, warn) {
2658
2663
  `));
2659
2664
  }
2660
2665
  }
2661
- var CHECKBOXES = {
2662
- unchecked: "[ ]",
2663
- blocked: "[BLOCKED]",
2664
- done: "[x]"
2665
- };
2666
2666
  function countTasks(tasks) {
2667
2667
  const done = tasks.filter((task) => task.status === "done").length;
2668
2668
  const blocked = tasks.filter((task) => task.status === "blocked").length;
@@ -2671,9 +2671,6 @@ function countTasks(tasks) {
2671
2671
  function formatCounts(counts) {
2672
2672
  return `${counts.done}/${counts.total} done, ${counts.blocked} blocked, ${counts.open} open`;
2673
2673
  }
2674
- function checkbox(status) {
2675
- return CHECKBOXES[status];
2676
- }
2677
2674
  function planFileName(stub, tracker) {
2678
2675
  return tracker ? `PLAN_TRACKER-${stub}.md` : `PLAN-${stub}.md`;
2679
2676
  }
@@ -2684,6 +2681,11 @@ function stubOfPlanFile(name2) {
2684
2681
  function isFile(path) {
2685
2682
  return statSync3(path, { throwIfNoEntry: false })?.isFile() ?? false;
2686
2683
  }
2684
+ var REJECTED_DIR = "rejected";
2685
+ function rejectedPath(path) {
2686
+ const parent = dirname11(path);
2687
+ return parent === "." ? join11(REJECTED_DIR, basename4(path)) : join11(parent, REJECTED_DIR, basename4(path));
2688
+ }
2687
2689
  function issueLine(file, issue) {
2688
2690
  return `${file}:${issue.line}: ${issue.reason}: ${issue.text}`;
2689
2691
  }
@@ -2704,15 +2706,6 @@ function expectOneArgument(args, usage) {
2704
2706
  throw new CommandExit(1, `\u274C Expected one argument, got ${got}
2705
2707
  Usage: ${usage}`);
2706
2708
  }
2707
- function expectAtMostOneArgument(args, usage) {
2708
- const [only] = args;
2709
- if (only === undefined)
2710
- return null;
2711
- if (args.length === 1)
2712
- return only;
2713
- throw new CommandExit(1, `\u274C Expected at most one argument, got ${args.length}: ${args.join(" ")}
2714
- Usage: ${usage}`);
2715
- }
2716
2709
  function readSwitch(name2, value, hint) {
2717
2710
  if (value === undefined || value === false || value === "false")
2718
2711
  return false;
@@ -2859,10 +2852,10 @@ var fix_schema_default = createFixSchemaCommand();
2859
2852
 
2860
2853
  // src/effort/store/merge-store.ts
2861
2854
  import { randomUUID as randomUUID5 } from "crypto";
2862
- import { existsSync as existsSync11, mkdtempSync, rmSync as rmSync7 } from "fs";
2855
+ import { existsSync as existsSync10, mkdtempSync, rmSync as rmSync7 } from "fs";
2863
2856
  import { tmpdir as tmpdir3 } from "os";
2864
- import { dirname as dirname11, join as join11 } from "path";
2865
- import { Database as Database6, SQLiteError as SQLiteError2 } from "bun:sqlite";
2857
+ import { dirname as dirname12, join as join12 } from "path";
2858
+ import { Database as Database5, SQLiteError as SQLiteError2 } from "bun:sqlite";
2866
2859
 
2867
2860
  // src/effort/commits.ts
2868
2861
  import { execFileSync } from "child_process";
@@ -3270,14 +3263,7 @@ function settleTable(local, other, union, trail) {
3270
3263
  function settleMatches(local, other, unions, trail) {
3271
3264
  return local.transaction(() => unions.map((union) => settleTable(local, other, union, trail)))();
3272
3265
  }
3273
-
3274
3266
  // src/effort/store/migrate.ts
3275
- import { existsSync as existsSync10 } from "fs";
3276
- import { Database as Database5 } from "bun:sqlite";
3277
- var LIVE2 = "live";
3278
- function asidePaths2(path, first, stamp) {
3279
- return { parallelPath: `${path}.migrate-${stamp}`, backupPath: `${path}.before-${first}-${stamp}.bak` };
3280
- }
3281
3267
  function liveLoop(path, options, nothingDone = "Nothing was migrated.", ownSessionId = null) {
3282
3268
  const root = storeProjectRoot(path);
3283
3269
  if (root === null)
@@ -3290,71 +3276,6 @@ function liveLoop(path, options, nothingDone = "Nothing was migrated.", ownSessi
3290
3276
  }
3291
3277
  return records.find((record) => (record.state === "running" || record.state === "paused") && record.sessionId !== ownSessionId);
3292
3278
  }
3293
- function refuseLiveLoop2(path, breaking, options) {
3294
- const loop = liveLoop(path, options);
3295
- if (loop === undefined)
3296
- return;
3297
- const named = `loop ${loop.sessionId} (pid ${String(loop.pid)}, plan ${loop.planStub ?? loop.plan}) is running on this store`;
3298
- const [first] = breaking;
3299
- const opening = first === undefined ? `REFUSED \u2014 ${named}, and swapping the migrated store in under it would lose what it writes.` : `REFUSED \u2014 migration ${first} breaks older runtimes, and ${named}.`;
3300
- throw new RebuildRefusal(`${opening} Nothing was migrated. Finish or stop that loop, then run it again.`);
3301
- }
3302
- function buildMigrated(path, parallelPath, migrations, stamp) {
3303
- vacuumInto(path, parallelPath);
3304
- const db = new Database5(parallelPath, { readwrite: true });
3305
- try {
3306
- const brought = bringForward(db, parallelPath, "write", "migrate", { migrations, ...stamp, builtAside: true });
3307
- db.run(`ATTACH DATABASE ? AS ${LIVE2}`, [path]);
3308
- const live = new Set(tableNames(db, LIVE2));
3309
- const counted = checkedCounts(db, tableNames(db, "main").filter((table) => live.has(table)), LIVE2);
3310
- db.run(`DETACH DATABASE ${LIVE2}`);
3311
- refuseCorrupt(db);
3312
- refuseUnusable(db, parallelPath, migrations);
3313
- return { userVersion: brought.userVersion, counted };
3314
- } finally {
3315
- db.close();
3316
- }
3317
- }
3318
- function migrateStore(options) {
3319
- const { path, dryRun, stamp } = options;
3320
- guardTestProcess(path);
3321
- const migrations = options.migrations ?? SQLITE_MIGRATIONS;
3322
- const appliedBy = appliedByName(options.identity ?? readRuntimeIdentity());
3323
- const nothing = { applying: [], breaking: [], unknown: [], userVersion: null, counted: [], backupPath: null };
3324
- if (!existsSync10(path)) {
3325
- return { path, status: "missing", storeVersion: null, logged: false, appliedBy, ...nothing };
3326
- }
3327
- refuseInFlight(path);
3328
- const store = readOnlySchema(path);
3329
- const found = { path, storeVersion: store.userVersion, logged: store.log !== null, appliedBy };
3330
- const plan = planSchema(store, sqliteCatalogue(migrations), "write", "migrate");
3331
- if (plan.verdict === "refuse")
3332
- throw new RebuildRefusal(plan.message);
3333
- const applying = writeNames(plan);
3334
- const planned = {
3335
- applying,
3336
- breaking: plan.pending.filter(({ breaks }) => breaks.length > 0).map(({ id }) => id),
3337
- unknown: plan.unknown
3338
- };
3339
- if (applying.length === 0)
3340
- return { ...found, ...nothing, ...planned, status: "current" };
3341
- if (!dryRun) {
3342
- refuseUnownedDevelopmentWrite(path, applying, options);
3343
- refuseLiveLoop2(path, planned.breaking, options);
3344
- }
3345
- const first = plan.pending[0]?.id ?? ADOPTION_NAME;
3346
- const { built, backupPath } = rebuildAside({
3347
- path,
3348
- ...asidePaths2(path, first, stamp),
3349
- dryRun,
3350
- build: (parallelPath) => buildMigrated(path, parallelPath, migrations, {
3351
- appliedBy,
3352
- now: options.now ?? (() => new Date)
3353
- })
3354
- });
3355
- const status = dryRun ? "would-migrate" : "migrated";
3356
- return { ...found, ...planned, ...built, status, backupPath };
3357
- }
3358
3279
 
3359
3280
  // src/effort/store/merge-store.ts
3360
3281
  var MOVE_TO_SQLITE = "rafa effort move --to=sqlite";
@@ -3367,7 +3288,7 @@ class MergeRefusal extends RebuildRefusal {
3367
3288
  this.reason = reason;
3368
3289
  }
3369
3290
  }
3370
- var LIVE3 = "live";
3291
+ var LIVE2 = "live";
3371
3292
  var MERGES_TABLE = "merges";
3372
3293
  var INSERT_MERGE = `INSERT INTO merges (id, other_store, merged_at, rows_added, rows_skipped, rows_in_conflict)
3373
3294
  VALUES (?, ?, ?, ?, ?, ?)`;
@@ -3378,14 +3299,14 @@ function refuseNdjson(backend) {
3378
3299
  throw new MergeRefusal("ndjson", `REFUSED \u2014 this project keeps its sessions and commits as NDJSON (store: ndjson), and a merge needs the SQLite store. ${NOTHING_MERGED}` + ` Next safe step: ${MOVE_TO_SQLITE}`);
3379
3300
  }
3380
3301
  function refuseMissing(path, which) {
3381
- if (existsSync11(path))
3302
+ if (existsSync10(path))
3382
3303
  return;
3383
3304
  throw new MergeRefusal("missing", `REFUSED \u2014 ${which} ${path} is not there. ${NOTHING_MERGED}`);
3384
3305
  }
3385
3306
  function refuseDamaged(path) {
3386
3307
  let answers;
3387
3308
  try {
3388
- const db = new Database6(path, { readonly: true });
3309
+ const db = new Database5(path, { readonly: true });
3389
3310
  try {
3390
3311
  answers = db.query("PRAGMA integrity_check").all().map((row) => row.integrity_check);
3391
3312
  } finally {
@@ -3407,7 +3328,7 @@ function writablePlan(path, migrations) {
3407
3328
  return plan;
3408
3329
  }
3409
3330
  function recordedMeta(path) {
3410
- const db = new Database6(path, { readonly: true });
3331
+ const db = new Database5(path, { readonly: true });
3411
3332
  try {
3412
3333
  const hasTable = db.query("SELECT count(*) AS n FROM sqlite_master WHERE type = 'table' AND name = 'store_meta'").get()?.n === 1;
3413
3334
  return hasTable ? readStoreMeta(db) : null;
@@ -3417,14 +3338,14 @@ function recordedMeta(path) {
3417
3338
  }
3418
3339
  function refuseOtherProject(options) {
3419
3340
  const other = recordedMeta(options.otherPath);
3420
- const here = recordedMeta(options.path)?.projectRootCommit ?? (options.readProject ?? readProjectIdentity)(dirname11(options.path)).rootCommit;
3341
+ const here = recordedMeta(options.path)?.projectRootCommit ?? (options.readProject ?? readProjectIdentity)(dirname12(options.path)).rootCommit;
3421
3342
  const there = other?.projectRootCommit ?? null;
3422
3343
  if (here !== null && there !== null && here !== there) {
3423
3344
  throw new MergeRefusal("other-project", `REFUSED \u2014 ${options.otherPath} is the effort store of another project (root commit ${there});` + ` this store's project has root commit ${here}. ${NOTHING_MERGED}`);
3424
3345
  }
3425
3346
  return other?.storeId ?? null;
3426
3347
  }
3427
- function refuseLiveLoop3(path, options, sessionId) {
3348
+ function refuseLiveLoop2(path, options, sessionId) {
3428
3349
  const loop = liveLoop(path, options, NOTHING_MERGED, sessionId);
3429
3350
  if (loop === undefined)
3430
3351
  return;
@@ -3433,18 +3354,18 @@ function refuseLiveLoop3(path, options, sessionId) {
3433
3354
  function openOther(otherPath, plan, stamp) {
3434
3355
  const needs = writeNames(plan);
3435
3356
  if (needs.length === 0) {
3436
- const db = new Database6(otherPath, { readonly: true });
3357
+ const db = new Database5(otherPath, { readonly: true });
3437
3358
  return { db, broughtForward: [], release: () => db.close() };
3438
3359
  }
3439
- const dir = mkdtempSync(join11(tmpdir3(), "rafa-merge-other-"));
3360
+ const dir = mkdtempSync(join12(tmpdir3(), "rafa-merge-other-"));
3440
3361
  const release = (db) => {
3441
3362
  db?.close();
3442
3363
  rmSync7(dir, { recursive: true, force: true });
3443
3364
  };
3444
3365
  try {
3445
- const copyPath = join11(dir, "other.sqlite");
3366
+ const copyPath = join12(dir, "other.sqlite");
3446
3367
  vacuumInto(otherPath, copyPath);
3447
- const db = new Database6(copyPath, { readwrite: true });
3368
+ const db = new Database5(copyPath, { readwrite: true });
3448
3369
  try {
3449
3370
  bringForward(db, copyPath, "write", "open", { ...stamp, builtAside: true });
3450
3371
  } catch (error) {
@@ -3488,14 +3409,14 @@ function addedRows(merged) {
3488
3409
  }
3489
3410
  function buildMerged(path, parallelPath, other, merge2) {
3490
3411
  vacuumInto(path, parallelPath);
3491
- const db = new Database6(parallelPath, { readwrite: true });
3412
+ const db = new Database5(parallelPath, { readwrite: true });
3492
3413
  try {
3493
3414
  bringForward(db, parallelPath, "write", "open", { ...merge2.stamp, builtAside: true });
3494
3415
  const merged = mergeInto(db, other, merge2.id, merge2.otherStore, merge2.stamp.now().toISOString());
3495
- db.run(`ATTACH DATABASE ? AS ${LIVE3}`, [path]);
3496
- const live = new Set(tableNames(db, LIVE3));
3497
- checkedCounts(db, tableNames(db, "main").filter((table) => live.has(table)), LIVE3, addedRows(merged));
3498
- db.run(`DETACH DATABASE ${LIVE3}`);
3416
+ db.run(`ATTACH DATABASE ? AS ${LIVE2}`, [path]);
3417
+ const live = new Set(tableNames(db, LIVE2));
3418
+ checkedCounts(db, tableNames(db, "main").filter((table) => live.has(table)), LIVE2, addedRows(merged));
3419
+ db.run(`DETACH DATABASE ${LIVE2}`);
3499
3420
  refuseCorrupt(db);
3500
3421
  refuseUnusable(db, parallelPath, merge2.stamp.migrations);
3501
3422
  return merged;
@@ -3516,7 +3437,7 @@ function refuseUnmergeable(options, migrations) {
3516
3437
  const otherStore = refuseOtherProject(options);
3517
3438
  if (!options.dryRun) {
3518
3439
  refuseUnownedDevelopmentWrite(path, [...writeNames(localPlan), MERGES_TABLE], options);
3519
- refuseLiveLoop3(path, options, options.sessionId ?? null);
3440
+ refuseLiveLoop2(path, options, options.sessionId ?? null);
3520
3441
  }
3521
3442
  return { otherPlan, otherStore };
3522
3443
  }
@@ -3564,7 +3485,7 @@ function refuseUncarriable(backend, source) {
3564
3485
  if (backend === "ndjson") {
3565
3486
  throw new FileSyncRefusal(`${REFUSAL}: this project keeps its sessions and commits as NDJSON (store: ndjson), and the file carried` + ` is effort.sqlite, which would hold none of them. ${NOTHING_COPIED} Next safe step: ${MOVE_TO_SQLITE}`);
3566
3487
  }
3567
- if (!existsSync12(join12(source, SQLITE_STORE_FILE_NAME))) {
3488
+ if (!existsSync11(join13(source, SQLITE_STORE_FILE_NAME))) {
3568
3489
  throw new FileSyncRefusal(`${REFUSAL}: no ${SQLITE_STORE_FILE_NAME} in ${source}. ${NOTHING_COPIED}`);
3569
3490
  }
3570
3491
  }
@@ -3582,11 +3503,11 @@ function createFileSync(options) {
3582
3503
  const source = storeDir();
3583
3504
  refuseUncarriable(backend, source);
3584
3505
  const copied = copyEffortStore({ source, target });
3585
- return Object.freeze({ status: "pushed", path: join12(copied.directory, SQLITE_STORE_FILE_NAME) });
3506
+ return Object.freeze({ status: "pushed", path: join13(copied.directory, SQLITE_STORE_FILE_NAME) });
3586
3507
  };
3587
3508
  const pull = async ({ from, dryRun, sessionId = null }) => {
3588
3509
  const otherPath = resolve5(repoRoot, requirePath("from", from));
3589
- const path = join12(storeDir(), SQLITE_STORE_FILE_NAME);
3510
+ const path = join13(storeDir(), SQLITE_STORE_FILE_NAME);
3590
3511
  const stamp = fileStamp(now());
3591
3512
  const merge2 = mergeStore({ ...mergeSeams(options), path, otherPath, backend, dryRun, stamp, now, sessionId });
3592
3513
  return Object.freeze({ status: "pulled", merge: merge2 });
@@ -3655,15 +3576,15 @@ function selectSync(repoRoot, config, registry = CORE_ADAPTER_REGISTRY) {
3655
3576
 
3656
3577
  // src/adapters/learning/local.ts
3657
3578
  import { appendFile, mkdir, readFile, rm, writeFile } from "fs/promises";
3658
- import { join as join15 } from "path";
3579
+ import { join as join16 } from "path";
3659
3580
 
3660
3581
  // src/commands/instinct/instinct-records.ts
3661
3582
  import { readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
3662
- import { join as join14 } from "path";
3583
+ import { join as join15 } from "path";
3663
3584
 
3664
3585
  // src/check/layout.ts
3665
3586
  import { readdirSync as readdirSync3, statSync as statSync4 } from "fs";
3666
- import { join as join13, relative as relative2 } from "path";
3587
+ import { join as join14, relative as relative2 } from "path";
3667
3588
  var SKILL_FILE = "SKILL.md";
3668
3589
  var MARKDOWN_EXTENSION = ".md";
3669
3590
  var LAYOUT_SEVERITY = Object.freeze({
@@ -3780,7 +3701,7 @@ function scanGroupMember(root, dir, name2) {
3780
3701
  const children = visibleNames(dir);
3781
3702
  if (children.length === 0)
3782
3703
  return [dotfileOnlyEntry("skill", root, dir)];
3783
- const skillPath = join13(dir, SKILL_FILE);
3704
+ const skillPath = join14(dir, SKILL_FILE);
3784
3705
  if (children.includes(SKILL_FILE) && entryKind(skillPath) === "file") {
3785
3706
  return [nestedGroupEntry(root, skillPath, name2)];
3786
3707
  }
@@ -3789,7 +3710,7 @@ function scanGroupMember(root, dir, name2) {
3789
3710
  function scanSkillGroup(root, dir, children) {
3790
3711
  const entries = [];
3791
3712
  for (const child of children) {
3792
- const path = join13(dir, child);
3713
+ const path = join14(dir, child);
3793
3714
  const found = entryKind(path);
3794
3715
  if (found === null) {
3795
3716
  entries.push(unreadableEntry("skill", root, path));
@@ -3810,7 +3731,7 @@ function scanSkillDirectory(root, dir, name2) {
3810
3731
  const children = visibleNames(dir);
3811
3732
  if (children.length === 0)
3812
3733
  return [dotfileOnlyEntry("skill", root, dir)];
3813
- const skillPath = join13(dir, SKILL_FILE);
3734
+ const skillPath = join14(dir, SKILL_FILE);
3814
3735
  if (children.includes(SKILL_FILE) && entryKind(skillPath) === "file") {
3815
3736
  return [skillFileEntry(skillPath, name2)];
3816
3737
  }
@@ -3819,7 +3740,7 @@ function scanSkillDirectory(root, dir, name2) {
3819
3740
  function scanSkillRoot(root) {
3820
3741
  const entries = [];
3821
3742
  for (const name2 of visibleNames(root)) {
3822
- const path = join13(root, name2);
3743
+ const path = join14(root, name2);
3823
3744
  const found = entryKind(path);
3824
3745
  if (found === null) {
3825
3746
  entries.push(unreadableEntry("skill", root, path));
@@ -3840,7 +3761,7 @@ function scanInstinctSubdirectory(root, dir) {
3840
3761
  return [dotfileOnlyEntry("instinct", root, dir)];
3841
3762
  const entries = [];
3842
3763
  for (const child of children) {
3843
- const path = join13(dir, child);
3764
+ const path = join14(dir, child);
3844
3765
  const found = entryKind(path);
3845
3766
  if (found === null) {
3846
3767
  entries.push(unreadableEntry("instinct", root, path));
@@ -3858,7 +3779,7 @@ function scanInstinctSubdirectory(root, dir) {
3858
3779
  function scanInstinctRoot(root) {
3859
3780
  const entries = [];
3860
3781
  for (const name2 of visibleNames(root)) {
3861
- const path = join13(root, name2);
3782
+ const path = join14(root, name2);
3862
3783
  const found = entryKind(path);
3863
3784
  if (found === null) {
3864
3785
  entries.push(unreadableEntry("instinct", root, path));
@@ -4327,7 +4248,7 @@ function isFile2(path) {
4327
4248
  }
4328
4249
  }
4329
4250
  function recordFiles(dir) {
4330
- return readdirSync4(dir).filter((name2) => isRecordFile(name2) && isFile2(join14(dir, name2))).sort((left, right) => left.localeCompare(right));
4251
+ return readdirSync4(dir).filter((name2) => isRecordFile(name2) && isFile2(join15(dir, name2))).sort((left, right) => left.localeCompare(right));
4331
4252
  }
4332
4253
  function readScope(scope, dir) {
4333
4254
  if (!tierExists(dir))
@@ -4336,23 +4257,12 @@ function readScope(scope, dir) {
4336
4257
  scope,
4337
4258
  dir,
4338
4259
  exists: true,
4339
- records: recordFiles(dir).map((name2) => readRecord(join14(dir, name2), scope, recordId(name2)))
4260
+ records: recordFiles(dir).map((name2) => readRecord(join15(dir, name2), scope, recordId(name2)))
4340
4261
  };
4341
4262
  }
4342
4263
  function readScopes(seams) {
4343
4264
  return resolveInstinctScopes(seams).map((location) => readScope(location.scope, location.dir));
4344
4265
  }
4345
- function allRecords(listings) {
4346
- return listings.flatMap((listing) => listing.records);
4347
- }
4348
- function findRecords(listings, id) {
4349
- return allRecords(listings).filter((entry) => entry.id === id);
4350
- }
4351
- function instinctProject(context, name2) {
4352
- if (context.project === null)
4353
- throw new Error(`${name2} runs inside a project, and was handed none`);
4354
- return context.project;
4355
- }
4356
4266
 
4357
4267
  // src/adapters/learning/held.ts
4358
4268
  function compareText2(left, right) {
@@ -4639,7 +4549,7 @@ function heldChanges(dir, held, result, described) {
4639
4549
  if (issue2 !== undefined) {
4640
4550
  throw new Error(`${PUSH_REFUSAL}: ${file} would not read back: ${issue2.field}: ${issue2.message}`);
4641
4551
  }
4642
- const path = join15(dir, file);
4552
+ const path = join16(dir, file);
4643
4553
  if (held.unreadable.has(path)) {
4644
4554
  throw new Error(`${PUSH_REFUSAL}: it would overwrite ${path}, which could not be read`);
4645
4555
  }
@@ -4669,18 +4579,18 @@ function pushLogLines(sourceId, described, result) {
4669
4579
  });
4670
4580
  }
4671
4581
  function localInstinctsDir(repoRoot) {
4672
- return join15(repoRoot, RAFA_INSTINCTS_PATH);
4582
+ return join16(repoRoot, RAFA_INSTINCTS_PATH);
4673
4583
  }
4674
4584
  function userInstinctsDir(home) {
4675
- return join15(home, RAFA_INSTINCTS_PATH);
4585
+ return join16(home, RAFA_INSTINCTS_PATH);
4676
4586
  }
4677
4587
  function createLocalLearning(options) {
4678
4588
  const { instinctsDir, minConfidence } = options;
4679
4589
  const userDir = userInstinctsDir(options.home);
4680
4590
  const now = options.now ?? (() => new Date().toISOString());
4681
4591
  const warn = options.warn ?? warnThroughActiveOutput;
4682
- const instinctsPath = join15(instinctsDir, INSTINCTS_FILE);
4683
- const flagsPath = join15(instinctsDir, FLAGS_FILE);
4592
+ const instinctsPath = join16(instinctsDir, INSTINCTS_FILE);
4593
+ const flagsPath = join16(instinctsDir, FLAGS_FILE);
4684
4594
  function readHeld(scope, dir) {
4685
4595
  const { records } = readScope(scope, dir);
4686
4596
  const unreadable = new Set;
@@ -4825,7 +4735,7 @@ function createJsonOutput({
4825
4735
  }
4826
4736
 
4827
4737
  // src/adapters/planner/claude.ts
4828
- import { existsSync as existsSync13 } from "fs";
4738
+ import { existsSync as existsSync12 } from "fs";
4829
4739
  import { mkdir as mkdir2, readFile as readFile2 } from "fs/promises";
4830
4740
  import { posix, resolve as resolve6 } from "path";
4831
4741
 
@@ -5167,7 +5077,7 @@ function createClaudePlanner(options) {
5167
5077
  const create = async ({ specPath, stub }) => {
5168
5078
  const planPath = planFilePath(planDir, `PLAN-${stub}.md`);
5169
5079
  const prerequisitesPath = planFilePath(planDir, `PREREQUISITES-${stub}.md`);
5170
- const isWritten = (path) => existsSync13(resolve6(root, path));
5080
+ const isWritten = (path) => existsSync12(resolve6(root, path));
5171
5081
  if (isWritten(planPath)) {
5172
5082
  throw new ClaudePlannerError(`${planPath} already exists`, FAILURE_EXIT_CODE);
5173
5083
  }
@@ -5688,7 +5598,7 @@ function createGithubTracker(options) {
5688
5598
 
5689
5599
  // src/adapters/tracker/local.ts
5690
5600
  import { mkdir as mkdir3, readdir, readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
5691
- import { join as join16 } from "path";
5601
+ import { join as join17 } from "path";
5692
5602
  var PREFIX4 = "local tracker";
5693
5603
  var FRONTMATTER = /^---\n([\s\S]*?)\n---\n([\s\S]*)$/;
5694
5604
  var ISSUE_NUMBER2 = /^[1-9]\d*$/;
@@ -5753,7 +5663,7 @@ function issueNumberOfFile(name2) {
5753
5663
  return name2.endsWith(ISSUE_EXTENSION) ? parseIssueNumber(name2.slice(0, -ISSUE_EXTENSION.length)) : null;
5754
5664
  }
5755
5665
  function issuePath(issuesDir, number) {
5756
- return join16(issuesDir, `${number}${ISSUE_EXTENSION}`);
5666
+ return join17(issuesDir, `${number}${ISSUE_EXTENSION}`);
5757
5667
  }
5758
5668
  async function issueNumbers(issuesDir) {
5759
5669
  let names;
@@ -5767,7 +5677,7 @@ async function issueNumbers(issuesDir) {
5767
5677
  return names.map(issueNumberOfFile).filter((number) => number !== null).sort((a, b) => a - b);
5768
5678
  }
5769
5679
  function localIssuesDir(repoRoot) {
5770
- return join16(repoRoot, ".rafa", "issues");
5680
+ return join17(repoRoot, ".rafa", "issues");
5771
5681
  }
5772
5682
  function renderLocalIssue(record) {
5773
5683
  const { draft } = record;
@@ -6261,65 +6171,11 @@ function requireTrustedAuthor(item, reading) {
6261
6171
  return;
6262
6172
  throw new CommandExit(TRUST_REFUSAL_EXIT, trustRefusalMessage(item, reading));
6263
6173
  }
6264
- var USER_COMMAND = "gh api user";
6265
- function noLogin(detail) {
6266
- return { login: null, detail };
6267
- }
6268
- function createGhEditorLogin(options) {
6269
- const { gh } = options;
6270
- return async () => {
6271
- const result = await gh(["api", "user"]);
6272
- if (!result.ok)
6273
- return noLogin(detailOf2(result, USER_COMMAND));
6274
- let payload;
6275
- try {
6276
- payload = JSON.parse(result.stdout);
6277
- } catch (error) {
6278
- return noLogin(`${USER_COMMAND} wrote output that is not JSON: ${messageOf(error)}`);
6279
- }
6280
- if (!isMapping(payload)) {
6281
- return noLogin(`${USER_COMMAND} answered ${describeValue(payload)}, expected a mapping`);
6282
- }
6283
- const login = payload["login"];
6284
- return typeof login === "string" && isGitHubLogin(login) ? { login, detail: "" } : noLogin(`${USER_COMMAND} answered ${describeValue(login)} as its login, which is not a GitHub login`);
6285
- };
6286
- }
6287
- async function readEditorTrust(trust, editor) {
6288
- const read = await editor();
6289
- if (read.login === null) {
6290
- return { login: null, trusted: false, refusal: "ownership-unknown", reading: null, detail: read.detail };
6291
- }
6292
- const reading = await readBoardTrust(trust, read.login);
6293
- return {
6294
- login: read.login,
6295
- trusted: reading.trusted,
6296
- refusal: editorRefusalOf(reading),
6297
- reading,
6298
- detail: ""
6299
- };
6300
- }
6301
- function editorRefusalOf(reading) {
6302
- if (reading.trusted)
6303
- return null;
6304
- return reading.refusal === "lookup-failed" ? "ownership-unknown" : "ownership";
6305
- }
6306
- function editorRefusalMessage(item, reading) {
6307
- const what = `${item.kind} #${String(item.number)}`;
6308
- if (reading.reading !== null) {
6309
- const because = trustRefusalClause(item.repo, reading.reading);
6310
- return `${what} cannot be edited by ${reading.reading.login}, ${because}; a member must make the edit`;
6311
- }
6312
- if (reading.trusted) {
6313
- throw new TypeError("board trust: a trusted editor has no refusal to name");
6314
- }
6315
- const detail = reading.detail === "" ? UNREPORTED : reading.detail;
6316
- return `${what} cannot be edited: the account running the edit could not be read (${detail}); ` + "log gh in with `gh auth login` and run it again";
6317
- }
6318
6174
  // src/effort/sync/wire.ts
6319
- import { existsSync as existsSync14, mkdtempSync as mkdtempSync2, rmSync as rmSync8 } from "fs";
6175
+ import { existsSync as existsSync13, mkdtempSync as mkdtempSync2, rmSync as rmSync8 } from "fs";
6320
6176
  import { tmpdir as tmpdir4 } from "os";
6321
- import { join as join17 } from "path";
6322
- import { Database as Database7, SQLiteError as SQLiteError3 } from "bun:sqlite";
6177
+ import { join as join18 } from "path";
6178
+ import { Database as Database6, SQLiteError as SQLiteError3 } from "bun:sqlite";
6323
6179
  var WIRE_FORMAT = "rafa-effort-wire";
6324
6180
  var WIRE_VERSION = 1;
6325
6181
 
@@ -6479,9 +6335,9 @@ function exportWirePayload(options) {
6479
6335
  const { path } = options;
6480
6336
  const cursor = checkCursor(options.cursor ?? {});
6481
6337
  guardTestProcess(path);
6482
- if (!existsSync14(path))
6338
+ if (!existsSync13(path))
6483
6339
  throw new WireExportRefusal(`wire: ${path} is not there`);
6484
- const db = new Database7(path, { readonly: true, safeIntegers: true });
6340
+ const db = new Database6(path, { readonly: true, safeIntegers: true });
6485
6341
  try {
6486
6342
  db.run(`PRAGMA busy_timeout = ${String(activeStoreSettings().busyTimeoutMs)}`);
6487
6343
  return db.transaction(() => readPayload(db, path, cursor))();
@@ -6520,7 +6376,7 @@ function insertRows(db, table, rows) {
6520
6376
  }
6521
6377
  function buildStore(path, payload, options) {
6522
6378
  const migrations = namedMigrations(payload.migrations, options.migrations ?? SQLITE_MIGRATIONS);
6523
- const db = new Database7(path, { create: true, readwrite: true });
6379
+ const db = new Database6(path, { create: true, readwrite: true });
6524
6380
  try {
6525
6381
  bringForward(db, path, "write", "open", {
6526
6382
  migrations,
@@ -6538,9 +6394,9 @@ function buildStore(path, payload, options) {
6538
6394
  }
6539
6395
  function materialiseWirePayload(payload, options = {}) {
6540
6396
  const checked = checkPayload(payload);
6541
- const directory = mkdtempSync2(join17(options.tempDir ?? tmpdir4(), "rafa-wire-"));
6397
+ const directory = mkdtempSync2(join18(options.tempDir ?? tmpdir4(), "rafa-wire-"));
6542
6398
  const release = () => rmSync8(directory, { recursive: true, force: true });
6543
- const path = join17(directory, SQLITE_STORE_FILE_NAME);
6399
+ const path = join18(directory, SQLITE_STORE_FILE_NAME);
6544
6400
  try {
6545
6401
  guardTestProcess(path);
6546
6402
  buildStore(path, checked, options);
@@ -6568,4 +6424,4 @@ function selectEffortStore(repoRoot, config) {
6568
6424
  return adapter.create({ repoRoot });
6569
6425
  }
6570
6426
 
6571
- export { EFFORT_STORE_DIR, effortStoreFileName, EFFORT_DIR_VARIABLE, effortStoreDir, guardTestProcess, EFFORT_KEY_PROJECTIONS, openNdjsonStore, name, version, RAFA_VERSION, versionLine, createGitRunner, gitSaid, NOT_A_REPOSITORY, mainCheckoutOf, SCOPE_DIR, INIT_COMMAND, DISK_FILE_SYSTEM, ScopeError, scopeAt, initHint, selfAndAncestors, resolveScope, POSITION_FILE, positionFilePath, readPositionFile, writePositionFile, positionAt, rehome, hop, goHome, HOP_FILE, hopFilePath, readHopRecord, writeHopRecord, staleAgainst, RECORD_EXTENSION, SessionRecordError, isSessionId, isPositiveWhole, sessionDecisions, sessionPhase, parseSessionRecord, SessionConflictError, SessionStateError, runsDir, sessionFilePath, errorCode, isPidAlive, readState, readSessions, readSession, samePlan, beginSession, updateSession, DEVELOPMENT_NEXT_STEP, DEVELOPMENT_MARK, DevelopmentBuildRefusedError, refuseUnownedDevelopmentWrite, LEGACY_GATE_OPEN, LEGACY_GATE_CLOSED, SQLITE_MIGRATIONS, sqliteCatalogue, planSchema, SchemaRefusedError, readStoreSchema, writeNames, ACROSS_STORES_ORDER, STAMPED_COLUMNS, stampedValues, activeStoreSettings, normalizeRemote, gitRemoteUrl, readStoreMeta, SQLITE_STORE_FILE_NAME, sqliteStorePath, LONE_SURROGATE, withSqliteStore, writeSqliteStore, openSqliteStore, EffortCopyRefusal, EffortCopyFailure, copyEffortStore, RebuildRefusal, readConfigFile, loadConfig, plansDirAt, requireProject, resolvePlansDir, resolveProjectConfig, countTasks, formatCounts, checkbox, planFileName, stubOfPlanFile, isFile, issueLine, plural, expectNoArgument, expectOneArgument, expectAtMostOneArgument, readSwitch, fileStamp, keepsIdLine, fix_schema_default, minutesBetween, readCommitLog, UnionSchemaMismatch, migrateStore, MOVE_TO_SQLITE, MergeRefusal, mergeStore, createFileSync, SyncModuleMissing, selectSync, SKILL_FILE, MARKDOWN_EXTENSION, scanLayout, declaredNameIssue, readFrontmatterDocument, readFrontmatter, renderFrontmatter, mergeFrontmatter, writeFrontmatter, ACTION_HEADING, CAUSE_HEADING, parseInstinct, writeInstinct, readScopes, allRecords, findRecords, instinctProject, toHeldRecords, EVENT_PREFIX, padKind, oneLine, sessionSpawnEnv, CLAUDE_BIN, claudeArgs, interruptClaudeSessions, spawnClaude, runClaude, spawnClaudeCaptured, runClaudeCaptured, planFilePath, ClaudePlannerError, ISSUE_TYPES, ISSUE_PRIORITIES, ISSUE_STATES, GITHUB_LABELS, createGhRunner, typeOfLabels, moduleOfLabels, createGithubTracker, createLocalTracker, PORT_VERSIONS, createAdapterRegistry, CORE_ADAPTER_REGISTRY, TRUSTED_PERMISSIONS, TRUST_REFUSAL_EXIT, createGhPermissions, readAuthorTrust, ghBoardTrust, readBoardTrust, requireTrustedBoardAuthor, trustRefusalClause, trustRefusalMessage, requireTrustedAuthor, createGhEditorLogin, readEditorTrust, editorRefusalMessage, WIRE_FORMAT, WIRE_VERSION, WireFormatError, WireExportRefusal, encodeWirePayload, decodeWirePayload, exportWirePayload, materialiseWirePayload, selectEffortStore };
6427
+ export { EFFORT_DIR_VARIABLE, effortStoreDir, guardTestProcess, EFFORT_KEY_PROJECTIONS, openNdjsonStore, name, version, RAFA_VERSION, createGitRunner, gitSaid, NOT_A_REPOSITORY, mainCheckoutOf, SCOPE_DIR, INIT_COMMAND, DISK_FILE_SYSTEM, ScopeError, scopeAt, initHint, selfAndAncestors, resolveScope, positionFilePath, readPositionFile, writePositionFile, positionAt, goHome, hopFilePath, readHopRecord, writeHopRecord, staleAgainst, SessionRecordError, isSessionId, sessionDecisions, SessionConflictError, runsDir, sessionFilePath, errorCode, isPidAlive, readSessions, readSession, samePlan, beginSession, updateSession, DEVELOPMENT_NEXT_STEP, DevelopmentBuildRefusedError, refuseUnownedDevelopmentWrite, SQLITE_MIGRATIONS, sqliteCatalogue, planSchema, readStoreSchema, writeNames, ACROSS_STORES_ORDER, STAMPED_COLUMNS, stampedValues, activeStoreSettings, normalizeRemote, gitRemoteUrl, readStoreMeta, SQLITE_STORE_FILE_NAME, sqliteStorePath, LONE_SURROGATE, withSqliteStore, writeSqliteStore, openSqliteStore, SPENDS_GLYPH, CommandExit, commandSpelling, readConfigFile, loadConfig, plansDirAt, requireProject, resolvePlansDir, countTasks, formatCounts, planFileName, stubOfPlanFile, isFile, rejectedPath, issueLine, plural, expectNoArgument, expectOneArgument, readSwitch, minutesBetween, readCommitLog, MOVE_TO_SQLITE, mergeStore, SyncModuleMissing, selectSync, SKILL_FILE, MARKDOWN_EXTENSION, scanLayout, declaredNameIssue, readFrontmatterDocument, readFrontmatter, mergeFrontmatter, writeFrontmatter, parseInstinct, readScopes, padKind, oneLine, interruptClaudeSessions, spawnClaude, runClaude, runClaudeCaptured, planFilePath, ClaudePlannerError, GITHUB_LABELS, createGhRunner, typeOfLabels, moduleOfLabels, createLocalTracker, PORT_VERSIONS, createAdapterRegistry, CORE_ADAPTER_REGISTRY, TRUSTED_PERMISSIONS, ghBoardTrust, readBoardTrust, requireTrustedBoardAuthor, trustRefusalClause, WIRE_FORMAT, WIRE_VERSION, WireFormatError, WireExportRefusal, encodeWirePayload, decodeWirePayload, exportWirePayload, materialiseWirePayload, selectEffortStore };