@open-tomato/rafa 0.34.0 → 0.35.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
- CONFIG_DEFAULTS,
4
- CONFIG_FILE,
5
- ConfigError,
6
- FINDING_DOMAINS,
7
- FINDING_KINDS,
8
- FINDING_SIGNALS,
9
- activeOutput,
10
- activeOutputMode,
11
- configFilePath,
12
- createTextOutput,
13
- hubContextOf,
14
- isStampableStub,
15
- parseConfigText,
16
- readRafaBlocks,
17
- resolveConfig
18
- } from "./index-vp0xghk2.js";
19
- import {
20
- bless,
21
- merge
22
- } from "./index-d6d0942q.js";
23
- import {
24
- CommandExit,
25
- commandSpelling
26
- } from "./index-3mzw3kzh.js";
27
- import {
28
- BUSY_TIMEOUT_MAX_MS,
29
- BUSY_TIMEOUT_MIN_MS,
30
3
  RAFA_INSTINCTS_PATH,
31
- STORE_BACKENDS,
32
- SYNC_STRATEGIES,
33
- TEST_SCOPES,
34
4
  bundledBinDirectory,
5
+ resolveInstinctScopes,
6
+ tierExists,
7
+ TEST_SCOPES,
8
+ isMapping,
35
9
  describeValue,
10
+ messageOf,
11
+ STORE_BACKENDS2,
12
+ SYNC_STRATEGIES2,
13
+ BUSY_TIMEOUT_MIN_MS,
14
+ BUSY_TIMEOUT_MAX_MS,
36
15
  isBusyTimeoutMs,
37
16
  isGitHubLogin,
38
- isMapping,
39
- messageOf,
40
- resolveInstinctScopes,
41
- tierExists
42
- } from "./index-fzhd3d4y.js";
17
+ hubContextOf,
18
+ CONFIG_FILE2,
19
+ CONFIG_DEFAULTS2,
20
+ ConfigError2,
21
+ configFilePath2,
22
+ parseConfigText2,
23
+ resolveConfig2,
24
+ isStampableStub,
25
+ createTextOutput,
26
+ activeOutput,
27
+ activeOutputMode,
28
+ readRafaBlocks2,
29
+ FINDING_KINDS2,
30
+ FINDING_SIGNALS2,
31
+ FINDING_DOMAINS
32
+ } from "./index-2tjmxwvp.js";
43
33
  import {
44
- actionHash,
45
- triggerKey
46
- } from "./index-wp8c28fd.js";
34
+ bless2,
35
+ merge2
36
+ } from "./index-hgcvjke7.js";
37
+ import {
38
+ actionHash2,
39
+ triggerKey2
40
+ } from "./index-21jcfatr.js";
47
41
 
48
42
  // src/adapters/registry.ts
49
43
  import { homedir } from "os";
@@ -217,7 +211,7 @@ function guardTestProcess(path, probe = currentProbe()) {
217
211
  function keyOrNull(value) {
218
212
  return typeof value === "string" && value.length > 0 ? value : null;
219
213
  }
220
- var EFFORT_KEY_PROJECTIONS = {
214
+ var EFFORT_KEY_PROJECTIONS2 = {
221
215
  sessions: (row) => keyOrNull(row.sessionId),
222
216
  commits: (row) => keyOrNull(row.sha)
223
217
  };
@@ -236,13 +230,13 @@ function readKind(repoRoot, kind) {
236
230
  }
237
231
  function keysOfKind(repoRoot, kind) {
238
232
  const path = openedKindPath(repoRoot, kind);
239
- return collectedKeys(path, EFFORT_KEY_PROJECTIONS[kind]);
233
+ return collectedKeys(path, EFFORT_KEY_PROJECTIONS2[kind]);
240
234
  }
241
235
  function appendKind(repoRoot, kind, rows) {
242
236
  const path = openedKindPath(repoRoot, kind);
243
- return appendRows(path, rows, EFFORT_KEY_PROJECTIONS[kind]);
237
+ return appendRows(path, rows, EFFORT_KEY_PROJECTIONS2[kind]);
244
238
  }
245
- function openNdjsonStore(repoRoot) {
239
+ function openNdjsonStore2(repoRoot) {
246
240
  return {
247
241
  append: (kind, rows) => appendKind(repoRoot, kind, rows),
248
242
  keys: (kind) => keysOfKind(repoRoot, kind),
@@ -255,11 +249,11 @@ function openNdjsonStore(repoRoot) {
255
249
  // src/effort/store/sqlite.ts
256
250
  import { existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
257
251
  import { dirname as dirname10, join as join9 } from "path";
258
- import { Database } from "bun:sqlite";
252
+ import { Database as Database2 } from "bun:sqlite";
259
253
 
260
254
  // package.json
261
255
  var name = "@open-tomato/rafa";
262
- var version = "0.34.0";
256
+ var version = "0.35.0";
263
257
 
264
258
  // src/cli/version.ts
265
259
  var RAFA_VERSION = version;
@@ -352,36 +346,36 @@ function mainCheckoutOf(dir, seams = {}) {
352
346
  }
353
347
 
354
348
  // src/project/scope.ts
355
- var SCOPE_DIR = dirname3(CONFIG_FILE);
356
- var INIT_COMMAND = "rafa init";
357
- var DISK_FILE_SYSTEM = Object.freeze({
349
+ var SCOPE_DIR2 = dirname3(CONFIG_FILE2);
350
+ var INIT_COMMAND2 = "rafa init";
351
+ var DISK_FILE_SYSTEM2 = Object.freeze({
358
352
  exists: (path) => existsSync3(path),
359
353
  realpath: (path) => realpathSync2(path)
360
354
  });
361
355
 
362
- class ScopeError extends Error {
356
+ class ScopeError2 extends Error {
363
357
  constructor(message, options) {
364
358
  super(`rafa scope: ${message}`, options);
365
359
  this.name = "ScopeError";
366
360
  }
367
361
  }
368
- function scopeAt(base) {
369
- return { dir: join4(base, SCOPE_DIR), configFile: configFilePath(base) };
362
+ function scopeAt2(base) {
363
+ return { dir: join4(base, SCOPE_DIR2), configFile: configFilePath2(base) };
370
364
  }
371
- function initHint(start, passedUserConfig = null, probedMainCheckout = null) {
365
+ function initHint2(start, passedUserConfig = null, probedMainCheckout = null) {
372
366
  const passed = passedUserConfig === null ? [] : [`${passedUserConfig} is the user scope's config and marks no project`];
373
367
  const main = probedMainCheckout === null ? [] : [`nor in ${probedMainCheckout}, the main checkout of the repository holding it`];
374
368
  return [
375
- `not inside a rafa project: no ${CONFIG_FILE} in ${start} or any directory above it`,
369
+ `not inside a rafa project: no ${CONFIG_FILE2} in ${start} or any directory above it`,
376
370
  ...main,
377
371
  ...passed,
378
- `run \`${INIT_COMMAND}\` to set one up`
372
+ `run \`${INIT_COMMAND2}\` to set one up`
379
373
  ].join(`
380
374
  `);
381
375
  }
382
376
  function requireAbsolute(label, path) {
383
377
  if (!isAbsolute3(path)) {
384
- throw new ScopeError(`${label} is ${describeValue(path)}, expected an absolute path`);
378
+ throw new ScopeError2(`${label} is ${describeValue(path)}, expected an absolute path`);
385
379
  }
386
380
  }
387
381
  function realStartOf(start, fs) {
@@ -389,7 +383,7 @@ function realStartOf(start, fs) {
389
383
  return fs.realpath(start);
390
384
  } catch (error) {
391
385
  const message = `start directory ${start} does not resolve (${messageOf(error)})`;
392
- throw new ScopeError(message, { cause: error });
386
+ throw new ScopeError2(message, { cause: error });
393
387
  }
394
388
  }
395
389
  function realHomeOf(home, fs) {
@@ -399,15 +393,15 @@ function realHomeOf(home, fs) {
399
393
  return null;
400
394
  }
401
395
  }
402
- function selfAndAncestors(path) {
396
+ function selfAndAncestors2(path) {
403
397
  const parent = dirname3(path);
404
- return parent === path ? [path] : [path, ...selfAndAncestors(parent)];
398
+ return parent === path ? [path] : [path, ...selfAndAncestors2(parent)];
405
399
  }
406
400
  var GIT_MARKER = ".git";
407
401
  function walkUp(dirs, realHome, fs, stopAtTopLevel) {
408
402
  let passedUserConfig = false;
409
403
  for (const dir of dirs) {
410
- if (fs.exists(configFilePath(dir))) {
404
+ if (fs.exists(configFilePath2(dir))) {
411
405
  if (dir !== realHome)
412
406
  return { root: dir, passedUserConfig, topLevel: null };
413
407
  passedUserConfig = true;
@@ -424,39 +418,39 @@ function mainCheckoutAt(realStart, mainCheckout) {
424
418
  } catch (error) {
425
419
  if (!(error instanceof WorktreeRootError))
426
420
  throw error;
427
- throw new ScopeError(`cannot read the main checkout of ${realStart} (${error.message})`, { cause: error });
421
+ throw new ScopeError2(`cannot read the main checkout of ${realStart} (${error.message})`, { cause: error });
428
422
  }
429
423
  }
430
424
  function fallBack(realStart, realHome, fs, mainCheckout) {
431
425
  const main = mainCheckoutAt(realStart, mainCheckout);
432
- if (main === null || main === realHome || selfAndAncestors(realStart).includes(main)) {
426
+ if (main === null || main === realHome || selfAndAncestors2(realStart).includes(main)) {
433
427
  return { root: null, probed: null };
434
428
  }
435
- return fs.exists(configFilePath(main)) ? { root: main, probed: main } : { root: null, probed: main };
429
+ return fs.exists(configFilePath2(main)) ? { root: main, probed: main } : { root: null, probed: main };
436
430
  }
437
431
  function walkAbove(lower, realHome, fs) {
438
432
  if (lower.topLevel === null)
439
433
  return lower;
440
- const above = selfAndAncestors(lower.topLevel).slice(1);
434
+ const above = selfAndAncestors2(lower.topLevel).slice(1);
441
435
  const upper = walkUp(above, realHome, fs, false);
442
436
  return { ...upper, passedUserConfig: lower.passedUserConfig || upper.passedUserConfig };
443
437
  }
444
- function resolveScope(start, seams) {
445
- const { home, fs = DISK_FILE_SYSTEM, mainCheckout = mainCheckoutOf } = seams;
438
+ function resolveScope2(start, seams) {
439
+ const { home, fs = DISK_FILE_SYSTEM2, mainCheckout = mainCheckoutOf } = seams;
446
440
  requireAbsolute("start directory", start);
447
441
  requireAbsolute("home directory", home);
448
- const user = scopeAt(home);
442
+ const user = scopeAt2(home);
449
443
  const realStart = realStartOf(start, fs);
450
444
  const realHome = realHomeOf(home, fs);
451
- const lower = walkUp(selfAndAncestors(realStart), realHome, fs, true);
445
+ const lower = walkUp(selfAndAncestors2(realStart), realHome, fs, true);
452
446
  const fallback = lower.root === null ? fallBack(realStart, realHome, fs, mainCheckout) : { root: lower.root, probed: null };
453
447
  const walk = fallback.root === null ? walkAbove(lower, realHome, fs) : lower;
454
448
  const root = fallback.root ?? walk.root;
455
449
  if (root === null) {
456
450
  const passed = walk.passedUserConfig ? user.configFile : null;
457
- return { found: false, start, home, user, hint: initHint(start, passed, fallback.probed) };
451
+ return { found: false, start, home, user, hint: initHint2(start, passed, fallback.probed) };
458
452
  }
459
- return { found: true, root, home, project: scopeAt(root), user };
453
+ return { found: true, root, home, project: scopeAt2(root), user };
460
454
  }
461
455
 
462
456
  // src/loop/session-record-parse.ts
@@ -473,7 +467,7 @@ import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, rmS
473
467
  import { dirname as dirname4, join as join5 } from "path";
474
468
  var POSITION_FILE = "position.json";
475
469
  function positionFilePath(root) {
476
- return join5(scopeAt(root).dir, POSITION_FILE);
470
+ return join5(scopeAt2(root).dir, POSITION_FILE);
477
471
  }
478
472
  function isRecord(value) {
479
473
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -550,7 +544,7 @@ var HOP_FILE = "hop.json";
550
544
  var HOP_KINDS = ["blocker", "dry"];
551
545
  var HOP_STATES = ["away", "waiting", "merged", "halted"];
552
546
  function hopFilePath(root) {
553
- return join6(scopeAt(root).dir, HOP_FILE);
547
+ return join6(scopeAt2(root).dir, HOP_FILE);
554
548
  }
555
549
  function isRecord2(value) {
556
550
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -696,8 +690,8 @@ function taskProblem(task) {
696
690
  function hopProblem(fields) {
697
691
  if (!Object.hasOwn(fields, "hop"))
698
692
  return null;
699
- const hop2 = field(fields, "hop");
700
- return asHopRecord(hop2) === null ? `hop is ${describeValue2(hop2)}, expected a hop record` : null;
693
+ const hop = field(fields, "hop");
694
+ return asHopRecord(hop) === null ? `hop is ${describeValue2(hop)}, expected a hop record` : null;
701
695
  }
702
696
  function worktreeProblem(fields) {
703
697
  if (!Object.hasOwn(fields, "worktree"))
@@ -799,8 +793,8 @@ function phaseEntry(phase) {
799
793
  return isSessionPhase(phase) ? { phase } : {};
800
794
  }
801
795
  function freezeHop(value) {
802
- const hop2 = asHopRecord(value);
803
- return Object.freeze({ ...hop2, home: Object.freeze(hop2.home), from: Object.freeze(hop2.from) });
796
+ const hop = asHopRecord(value);
797
+ return Object.freeze({ ...hop, home: Object.freeze(hop.home), from: Object.freeze(hop.from) });
804
798
  }
805
799
  function freezeFailures(failures) {
806
800
  return Object.freeze(failures.map((failure) => Object.freeze({ file: failure.file, name: failure.name })));
@@ -824,7 +818,7 @@ function stepsEntry(steps) {
824
818
  }
825
819
  function freezeRecord(fields) {
826
820
  const task = field(fields, "task");
827
- const hop2 = field(fields, "hop");
821
+ const hop = field(fields, "hop");
828
822
  const worktree = field(fields, "worktree");
829
823
  return Object.freeze({
830
824
  sessionId: field(fields, "sessionId"),
@@ -836,7 +830,7 @@ function freezeRecord(fields) {
836
830
  state: field(fields, "state"),
837
831
  task: isObject(task) ? Object.freeze({ line: field(task, "line"), text: field(task, "text") }) : null,
838
832
  ...phaseEntry(field(fields, "phase")),
839
- ...hop2 === undefined ? {} : { hop: freezeHop(hop2) },
833
+ ...hop === undefined ? {} : { hop: freezeHop(hop) },
840
834
  ...worktree === undefined ? {} : { worktree },
841
835
  ...stepsEntry(field(fields, "steps"))
842
836
  });
@@ -887,7 +881,7 @@ class SessionStateError extends Error {
887
881
  }
888
882
  }
889
883
  function runsDir(root) {
890
- return join7(scopeAt(root).dir, RUNS_DIR);
884
+ return join7(scopeAt2(root).dir, RUNS_DIR);
891
885
  }
892
886
  function sessionFilePath(root, sessionId) {
893
887
  if (!isSessionId(sessionId)) {
@@ -937,7 +931,7 @@ function byStart(a, b) {
937
931
  function readSessions(root, seams = {}) {
938
932
  const dir = runsDir(root);
939
933
  const isAlive = seams.isAlive ?? isPidAlive;
940
- const records = recordNames(dir).filter((name2) => name2.endsWith(RECORD_EXTENSION)).map((name2) => readRecordFile(join7(dir, name2))).map((record) => Object.freeze({ ...record, state: readState(record, isAlive) }));
934
+ const records = recordNames(dir).filter((name) => name.endsWith(RECORD_EXTENSION)).map((name) => readRecordFile(join7(dir, name))).map((record) => Object.freeze({ ...record, state: readState(record, isAlive) }));
941
935
  return Object.freeze(records.sort(byStart));
942
936
  }
943
937
  function readSession(root, sessionId, seams = {}) {
@@ -1023,8 +1017,8 @@ function manifestName(file) {
1023
1017
  }
1024
1018
  if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
1025
1019
  return null;
1026
- const name2 = parsed["name"];
1027
- return typeof name2 === "string" ? name2 : null;
1020
+ const name = parsed["name"];
1021
+ return typeof name === "string" ? name : null;
1028
1022
  }
1029
1023
  function nearestRafaPackage(start) {
1030
1024
  let dir = start;
@@ -1069,7 +1063,7 @@ class DevelopmentBuildRefusedError extends Error {
1069
1063
  function storeProjectRoot(path) {
1070
1064
  const storeDir = dirname8(path);
1071
1065
  const scopeDir = dirname8(storeDir);
1072
- if (basename3(storeDir) !== EFFORT_DIR_NAME || basename3(scopeDir) !== SCOPE_DIR)
1066
+ if (basename3(storeDir) !== EFFORT_DIR_NAME || basename3(scopeDir) !== SCOPE_DIR2)
1073
1067
  return null;
1074
1068
  return dirname8(scopeDir);
1075
1069
  }
@@ -1469,6 +1463,13 @@ var SQLITE_MIGRATIONS = [
1469
1463
  recorded_at TEXT NOT NULL CHECK (recorded_at <> '')
1470
1464
  );
1471
1465
  `
1466
+ },
1467
+ {
1468
+ id: "store-meta-generation",
1469
+ breaks: [],
1470
+ sql: `
1471
+ ALTER TABLE store_meta ADD COLUMN generation TEXT CHECK (generation <> '');
1472
+ `
1472
1473
  }
1473
1474
  ];
1474
1475
  var SQLITE_SCHEMA_VERSION = SQLITE_MIGRATIONS.length;
@@ -1682,7 +1683,7 @@ function stampedValues(table) {
1682
1683
 
1683
1684
  // src/effort/store/settings.ts
1684
1685
  var DEFAULT_STORE_SETTINGS = Object.freeze({
1685
- busyTimeoutMs: CONFIG_DEFAULTS.effortBusyTimeoutMs
1686
+ busyTimeoutMs: CONFIG_DEFAULTS2.effortBusyTimeoutMs
1686
1687
  });
1687
1688
  var active = DEFAULT_STORE_SETTINGS;
1688
1689
  function setActiveStoreSettings(settings) {
@@ -1700,13 +1701,55 @@ function activeStoreSettings() {
1700
1701
  }
1701
1702
 
1702
1703
  // src/effort/store/store-meta.ts
1703
- import { randomUUID as randomUUID3 } from "crypto";
1704
+ import { randomUUID as randomUUID4 } from "crypto";
1704
1705
  import { dirname as dirname9 } from "path";
1706
+ import { Database } from "bun:sqlite";
1707
+
1708
+ // src/effort/store/store-generation.ts
1709
+ import { randomUUID as randomUUID3 } from "crypto";
1710
+ import { readFileSync as readFileSync6, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync4 } from "fs";
1711
+ var STORE_GENERATION_SUFFIX = ".generation";
1712
+ function storeGenerationPath(storePath) {
1713
+ return `${storePath}${STORE_GENERATION_SUFFIX}`;
1714
+ }
1715
+ function isMissingFile(error) {
1716
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
1717
+ }
1718
+ function readStoreGeneration(storePath) {
1719
+ let text;
1720
+ try {
1721
+ text = readFileSync6(storeGenerationPath(storePath), "utf8");
1722
+ } catch (error) {
1723
+ if (isMissingFile(error))
1724
+ return null;
1725
+ throw error;
1726
+ }
1727
+ const generation = text.trim();
1728
+ return generation === "" ? null : generation;
1729
+ }
1730
+ function assertWritableGeneration(generation) {
1731
+ if (generation === "" || generation !== generation.trim() || /[\r\n]/.test(generation)) {
1732
+ throw new Error(`store generation must be non-empty, unpadded and on one line, got ${JSON.stringify(generation)}`);
1733
+ }
1734
+ }
1735
+ function writeStoreGeneration(storePath, generation) {
1736
+ assertWritableGeneration(generation);
1737
+ const file = storeGenerationPath(storePath);
1738
+ const temporary = `${file}.${String(process.pid)}.${randomUUID3()}.tmp`;
1739
+ try {
1740
+ writeFileSync4(temporary, `${generation}
1741
+ `, { encoding: "utf8", flag: "wx" });
1742
+ renameSync4(temporary, file);
1743
+ } catch (error) {
1744
+ rmSync4(temporary, { force: true });
1745
+ throw error;
1746
+ }
1747
+ }
1705
1748
 
1706
1749
  // src/effort/store/store-identity.ts
1707
1750
  import { spawnSync as spawnSync3 } from "child_process";
1708
1751
  import { createHmac } from "crypto";
1709
- import { readFileSync as readFileSync6, realpathSync as realpathSync4, statSync } from "fs";
1752
+ import { readFileSync as readFileSync7, realpathSync as realpathSync4, statSync } from "fs";
1710
1753
  import { hostname, platform as currentPlatform } from "os";
1711
1754
 
1712
1755
  // src/schema/project-id.ts
@@ -1744,7 +1787,7 @@ function hostIdFrom(source, value) {
1744
1787
  }
1745
1788
  function readMachineIdFile() {
1746
1789
  try {
1747
- const value = readFileSync6(MACHINE_ID_PATH, "utf8").trim();
1790
+ const value = readFileSync7(MACHINE_ID_PATH, "utf8").trim();
1748
1791
  return value === "" ? null : value;
1749
1792
  } catch {
1750
1793
  return null;
@@ -1780,14 +1823,19 @@ function readStoreFileFacts(path) {
1780
1823
  return { storePath, fileDev: stats.dev, fileIno: stats.ino };
1781
1824
  }
1782
1825
  function observeStore(path, readHost = readHostId) {
1783
- return { hostId: readHost(), ...readStoreFileFacts(path) };
1826
+ const fileFacts = readStoreFileFacts(path);
1827
+ return { hostId: readHost(), ...fileFacts, generation: readStoreGeneration(fileFacts.storePath) };
1828
+ }
1829
+ function staleGeneration(recorded, facts) {
1830
+ return recorded.generation !== null && recorded.generation !== facts.generation;
1784
1831
  }
1785
1832
  function movedFacts(recorded, facts) {
1786
1833
  const sameFile = BigInt(recorded.fileDev) === facts.fileDev && BigInt(recorded.fileIno) === facts.fileIno;
1787
1834
  const moved = [
1788
1835
  ["host", recorded.hostId !== facts.hostId],
1789
1836
  ["path", recorded.storePath !== facts.storePath],
1790
- ["file", !sameFile]
1837
+ ["file", !sameFile],
1838
+ ["generation", staleGeneration(recorded, facts)]
1791
1839
  ];
1792
1840
  return moved.filter(([, differs]) => differs).map(([reason]) => reason);
1793
1841
  }
@@ -1827,8 +1875,12 @@ function toStoredInteger(value) {
1827
1875
  function fromStoredInteger(text) {
1828
1876
  return BigInt.asUintN(STORED_INTEGER_BITS, BigInt(text));
1829
1877
  }
1878
+ function hasGenerationColumn(db) {
1879
+ return db.query("SELECT count(*) AS n FROM pragma_table_info('store_meta') WHERE name = 'generation'").get()?.n === 1;
1880
+ }
1830
1881
  function readStoreMeta(db) {
1831
- const row = db.query("SELECT store_id, project_root_commit, project_remote, host_id, store_path," + " CAST(file_dev AS TEXT) AS file_dev, CAST(file_ino AS TEXT) AS file_ino, minted_at" + " FROM store_meta WHERE id = 1").get();
1882
+ const generation = hasGenerationColumn(db) ? "generation" : "NULL AS generation";
1883
+ const row = db.query("SELECT store_id, project_root_commit, project_remote, host_id, store_path," + " CAST(file_dev AS TEXT) AS file_dev, CAST(file_ino AS TEXT) AS file_ino, minted_at," + ` ${generation} FROM store_meta WHERE id = 1`).get();
1832
1884
  if (row === null)
1833
1885
  return null;
1834
1886
  return {
@@ -1839,7 +1891,8 @@ function readStoreMeta(db) {
1839
1891
  storePath: row.store_path,
1840
1892
  fileDev: fromStoredInteger(row.file_dev),
1841
1893
  fileIno: fromStoredInteger(row.file_ino),
1842
- mintedAt: row.minted_at
1894
+ mintedAt: row.minted_at,
1895
+ generation: row.generation
1843
1896
  };
1844
1897
  }
1845
1898
  function projectFor(storePath, recorded, seams) {
@@ -1850,14 +1903,30 @@ function projectFor(storePath, recorded, seams) {
1850
1903
  return null;
1851
1904
  return { rootCommit: recorded.projectRootCommit, remote: recorded.projectRemote };
1852
1905
  }
1853
- function writeStoreMeta(db, facts, project, seams) {
1854
- const storeId = (seams.newStoreId ?? randomUUID3)();
1906
+ function writeStoreMeta(db, facts, project, generation, seams) {
1907
+ const storeId = (seams.newStoreId ?? randomUUID4)();
1855
1908
  const mintedAt = (seams.now?.() ?? new Date).toISOString();
1856
- db.query("INSERT OR REPLACE INTO store_meta (id, store_id, project_root_commit, project_remote," + " host_id, store_path, file_dev, file_ino, minted_at) VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?)").run(storeId, project.rootCommit, project.remote, facts.hostId, facts.storePath, toStoredInteger(facts.fileDev), toStoredInteger(facts.fileIno), mintedAt);
1909
+ db.query("INSERT OR REPLACE INTO store_meta (id, store_id, project_root_commit, project_remote," + " host_id, store_path, file_dev, file_ino, minted_at, generation) VALUES (1, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(storeId, project.rootCommit, project.remote, facts.hostId, facts.storePath, toStoredInteger(facts.fileDev), toStoredInteger(facts.fileIno), mintedAt, generation);
1857
1910
  return storeId;
1858
1911
  }
1859
- function unminted(decision) {
1860
- return decision.action === "keep" ? { action: "keep", storeId: decision.storeId } : { action: "none" };
1912
+ function settleUnderLock(db, observe, prefetched, seams) {
1913
+ const current = readStoreMeta(db);
1914
+ const facts = observe();
1915
+ const decision = decideStoreIdentity("write", current, () => facts);
1916
+ if (decision.action === "none")
1917
+ return { action: "none" };
1918
+ const generation = (seams.newGeneration ?? randomUUID4)();
1919
+ if (decision.action === "keep") {
1920
+ db.query("UPDATE store_meta SET generation = ? WHERE id = 1").run(generation);
1921
+ writeStoreGeneration(facts.storePath, generation);
1922
+ return { action: "keep", storeId: decision.storeId };
1923
+ }
1924
+ const project = prefetched ?? projectFor(facts.storePath, current, seams);
1925
+ if (project === null)
1926
+ return { action: "no-project", reasons: decision.reasons };
1927
+ const storeId = writeStoreMeta(db, facts, project, generation, seams);
1928
+ writeStoreGeneration(facts.storePath, generation);
1929
+ return { action: "mint", storeId, reasons: decision.reasons };
1861
1930
  }
1862
1931
  function settleStoreIdentity(db, path, access, seams = {}) {
1863
1932
  if (access === "read")
@@ -1865,19 +1934,72 @@ function settleStoreIdentity(db, path, access, seams = {}) {
1865
1934
  const observe = () => observeStore(path, seams.readHostId ?? readHostId);
1866
1935
  const recorded = readStoreMeta(db);
1867
1936
  const first = decideStoreIdentity(access, recorded, observe);
1868
- if (first.action !== "mint")
1869
- return unminted(first);
1870
- const project = projectFor(first.facts.storePath, recorded, seams);
1871
- if (project === null)
1937
+ const prefetched = first.action === "mint" ? projectFor(first.facts.storePath, recorded, seams) : undefined;
1938
+ if (first.action === "mint" && prefetched === null)
1872
1939
  return { action: "no-project", reasons: first.reasons };
1873
- const mintUnderLock = db.transaction(() => {
1874
- const second = decideStoreIdentity(access, readStoreMeta(db), observe);
1875
- if (second.action !== "mint")
1876
- return unminted(second);
1877
- const storeId = writeStoreMeta(db, second.facts, project, seams);
1878
- return { action: "mint", storeId, reasons: second.reasons };
1879
- });
1880
- return mintUnderLock.immediate();
1940
+ const underLock = db.transaction(() => settleUnderLock(db, observe, prefetched ?? undefined, seams));
1941
+ return underLock.immediate();
1942
+ }
1943
+ function hasStoreMetaTable(db) {
1944
+ return db.query("SELECT count(*) AS n FROM sqlite_master WHERE type = 'table' AND name = 'store_meta'").get()?.n === 1;
1945
+ }
1946
+ function decideLiveWrite(livePath, readHost) {
1947
+ const live = new Database(livePath, { readonly: true });
1948
+ let recorded;
1949
+ try {
1950
+ if (!hasStoreMetaTable(live))
1951
+ return { action: "no-table" };
1952
+ recorded = readStoreMeta(live);
1953
+ } finally {
1954
+ live.close();
1955
+ }
1956
+ if (recorded === null)
1957
+ return { action: "no-row" };
1958
+ const facts = observeStore(livePath, readHost);
1959
+ const decision = decideStoreIdentity("write", recorded, () => facts);
1960
+ if (decision.action === "keep")
1961
+ return { action: "keep", storeId: decision.storeId };
1962
+ const reasons = decision.action === "mint" ? decision.reasons : [];
1963
+ return { action: "mint", reasons };
1964
+ }
1965
+ function holdsRowOf(db, storeId) {
1966
+ return hasStoreMetaTable(db) && readStoreMeta(db)?.storeId === storeId;
1967
+ }
1968
+ function spoilGeneration(db, newGeneration) {
1969
+ if (!hasStoreMetaTable(db) || !hasGenerationColumn(db))
1970
+ return null;
1971
+ const rows = db.query("SELECT count(*) AS n FROM store_meta WHERE id = 1").get()?.n;
1972
+ if (rows !== 1)
1973
+ return null;
1974
+ const generation = newGeneration();
1975
+ db.query("UPDATE store_meta SET generation = ? WHERE id = 1").run(generation);
1976
+ return generation;
1977
+ }
1978
+ function writeCarried(db, storeId, parallel, newGeneration) {
1979
+ const dev = toStoredInteger(parallel.fileDev);
1980
+ const ino = toStoredInteger(parallel.fileIno);
1981
+ if (hasGenerationColumn(db)) {
1982
+ const generation = newGeneration();
1983
+ db.query("UPDATE store_meta SET file_dev = ?, file_ino = ?, generation = ? WHERE id = 1").run(dev, ino, generation);
1984
+ return { action: "carried", storeId, generation };
1985
+ }
1986
+ db.query("UPDATE store_meta SET file_dev = ?, file_ino = ? WHERE id = 1").run(dev, ino);
1987
+ return { action: "carried", storeId, generation: null };
1988
+ }
1989
+ function carryStoreIdentity(livePath, parallelPath, seams = {}) {
1990
+ const parallel = readStoreFileFacts(parallelPath);
1991
+ const live = decideLiveWrite(livePath, seams.readHostId ?? readHostId);
1992
+ const newGeneration = seams.newGeneration ?? randomUUID4;
1993
+ const db = new Database(parallelPath, { readwrite: true });
1994
+ try {
1995
+ if (live.action === "keep" && holdsRowOf(db, live.storeId)) {
1996
+ return writeCarried(db, live.storeId, parallel, newGeneration);
1997
+ }
1998
+ const spoiled = spoilGeneration(db, newGeneration);
1999
+ return live.action === "keep" ? { action: "other-row", spoiled } : { ...live, spoiled };
2000
+ } finally {
2001
+ db.close();
2002
+ }
1881
2003
  }
1882
2004
 
1883
2005
  // src/effort/store/sqlite.ts
@@ -1897,7 +2019,7 @@ function refused(index, length, reason) {
1897
2019
  return new Error(`effort store: row ${index} of ${length} ${reason}; batch refused`);
1898
2020
  }
1899
2021
  function batchEntries(kind, rows) {
1900
- const keyOf = EFFORT_KEY_PROJECTIONS[kind];
2022
+ const keyOf = EFFORT_KEY_PROJECTIONS2[kind];
1901
2023
  const projected = rows.map((row) => ({ key: keyOf(row), row }));
1902
2024
  const keyed = projected.filter(hasKey);
1903
2025
  if (keyed.length < projected.length) {
@@ -1915,7 +2037,7 @@ function withSqliteStore(path, access, create, use, identity = {}) {
1915
2037
  guardTestProcess(path);
1916
2038
  if (create)
1917
2039
  mkdirSync5(dirname10(path), { recursive: true });
1918
- const db = new Database(path, { readwrite: true, create });
2040
+ const db = new Database2(path, { readwrite: true, create });
1919
2041
  try {
1920
2042
  db.run(`PRAGMA busy_timeout = ${String(activeStoreSettings().busyTimeoutMs)}`);
1921
2043
  bringForward(db, path, access, "open");
@@ -1949,8 +2071,8 @@ function appendKind2(path, kind, rows) {
1949
2071
  function keysOfKind2(path, kind) {
1950
2072
  if (!existsSync5(path))
1951
2073
  return new Set;
1952
- const { name: name2, keyColumn } = KIND_TABLES[kind];
1953
- const keys = withSqliteStore(path, "read", false, (db) => db.query(`SELECT ${keyColumn} AS key FROM ${name2} ORDER BY seq`).all());
2074
+ const { name, keyColumn } = KIND_TABLES[kind];
2075
+ const keys = withSqliteStore(path, "read", false, (db) => db.query(`SELECT ${keyColumn} AS key FROM ${name} ORDER BY seq`).all());
1954
2076
  return new Set(keys.map(({ key }) => key));
1955
2077
  }
1956
2078
  function parsedObject(body) {
@@ -1971,11 +2093,11 @@ function rowOf(body, where) {
1971
2093
  function readKind2(path, kind) {
1972
2094
  if (!existsSync5(path))
1973
2095
  return [];
1974
- const { name: name2 } = KIND_TABLES[kind];
1975
- const stored = withSqliteStore(path, "read", false, (db) => db.query(`SELECT seq, row_json AS body FROM ${name2} ORDER BY seq`).all());
1976
- return stored.map(({ seq, body }) => rowOf(body, `${path}: ${name2} row ${seq}`));
2096
+ const { name } = KIND_TABLES[kind];
2097
+ const stored = withSqliteStore(path, "read", false, (db) => db.query(`SELECT seq, row_json AS body FROM ${name} ORDER BY seq`).all());
2098
+ return stored.map(({ seq, body }) => rowOf(body, `${path}: ${name} row ${seq}`));
1977
2099
  }
1978
- function openSqliteStore(repoRoot) {
2100
+ function openSqliteStore2(repoRoot) {
1979
2101
  const path = sqliteStorePath(repoRoot);
1980
2102
  return {
1981
2103
  append: (kind, rows) => appendKind2(path, kind, rows),
@@ -1989,28 +2111,241 @@ function openSqliteStore(repoRoot) {
1989
2111
  import { existsSync as existsSync12 } from "fs";
1990
2112
  import { join as join12, resolve as resolve5 } from "path";
1991
2113
 
2114
+ // src/cli/spends.ts
2115
+ var SPENDS_GLYPH = "\uD83E\uDE99";
2116
+ var SPENDS_WHEN = ["always", "with", "unless", "through"];
2117
+ var FLAGGED = ["with", "unless"];
2118
+ var FLAG_SPELLING = /^--[^\s-]\S*$/;
2119
+ function flagProblem(when, flag) {
2120
+ if (FLAGGED.includes(when)) {
2121
+ return typeof flag === "string" && FLAG_SPELLING.test(flag) ? null : `spends.flag is ${describeValue(flag)}, expected a flag as typed, starting with --`;
2122
+ }
2123
+ return flag === undefined ? null : `spends.flag is ${describeValue(flag)}, expected absent when spends.when is "${when}"`;
2124
+ }
2125
+ function spendsProblem(value) {
2126
+ if (value === undefined)
2127
+ return null;
2128
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2129
+ return `spends is ${describeValue(value)}, expected absent or a mapping`;
2130
+ }
2131
+ const { when, what, flag } = value;
2132
+ if (!SPENDS_WHEN.includes(when)) {
2133
+ return `spends.when is ${describeValue(when)}, expected one of ${SPENDS_WHEN.join(", ")}`;
2134
+ }
2135
+ if (typeof what !== "string") {
2136
+ return `spends.what is ${describeValue(what)}, expected a string`;
2137
+ }
2138
+ return flagProblem(when, flag);
2139
+ }
2140
+
2141
+ // src/cli/command.ts
2142
+ var COMMAND_OUTPUTS = ["text", "json", "events", "tui"];
2143
+ var MAX_EXIT_CODE = 255;
2144
+
2145
+ class CommandExit extends Error {
2146
+ exitCode;
2147
+ constructor(exitCode, message = "") {
2148
+ super(message);
2149
+ if (!Number.isInteger(exitCode) || exitCode < 0 || exitCode > MAX_EXIT_CODE) {
2150
+ throw new TypeError(`CommandExit: exit code is ${describeValue(exitCode)}, expected a whole number from 0 to ${MAX_EXIT_CODE}`);
2151
+ }
2152
+ this.name = "CommandExit";
2153
+ this.exitCode = exitCode;
2154
+ }
2155
+ }
2156
+ function isListOf(value, check) {
2157
+ return Array.isArray(value) && value.every(check);
2158
+ }
2159
+ function hasStrings(value, keys) {
2160
+ if (typeof value !== "object" || value === null)
2161
+ return false;
2162
+ const record = value;
2163
+ return keys.every((key) => typeof record[key] === "string");
2164
+ }
2165
+ function isRoutingWord(value) {
2166
+ return typeof value === "string" && /^[^\s/-][^\s/]*$/.test(value);
2167
+ }
2168
+ function isFlag(item) {
2169
+ if (!hasStrings(item, ["name"]))
2170
+ return false;
2171
+ const { deprecated } = item;
2172
+ return deprecated === undefined || hasStrings(deprecated, ["use"]);
2173
+ }
2174
+ function fieldProblem(fields) {
2175
+ const checks = [
2176
+ ["subject", isRoutingWord(fields.subject), "a word with no space, no slash and no leading dash"],
2177
+ ["action", isRoutingWord(fields.action), "a word with no space, no slash and no leading dash"],
2178
+ ["name", typeof fields.name === "string", "a string"],
2179
+ ["summary", typeof fields.summary === "string", "a string"],
2180
+ ["description", typeof fields.description === "string", "a string"],
2181
+ ["args", isListOf(fields.args, (item) => hasStrings(item, ["name"])), "a list of named arguments"],
2182
+ ["flags", isListOf(fields.flags, isFlag), "a list of named flags, each deprecation naming its use"],
2183
+ ["examples", isListOf(fields.examples, (item) => hasStrings(item, ["cmd", "note"])), "a list of examples"],
2184
+ [
2185
+ "outputs",
2186
+ isListOf(fields.outputs, (item) => COMMAND_OUTPUTS.includes(item)),
2187
+ `a list of ${COMMAND_OUTPUTS.join(", ")}`
2188
+ ],
2189
+ [
2190
+ "aliases",
2191
+ fields.aliases === undefined || isListOf(fields.aliases, (item) => typeof item === "string"),
2192
+ "absent or a list of strings"
2193
+ ],
2194
+ [
2195
+ "lastingAliases",
2196
+ fields.lastingAliases === undefined || isListOf(fields.lastingAliases, (item) => typeof item === "string"),
2197
+ "absent or a list of strings"
2198
+ ],
2199
+ [
2200
+ "deprecated",
2201
+ fields.deprecated === undefined || hasStrings(fields.deprecated, ["since", "use"]),
2202
+ "absent or a mapping of since and use"
2203
+ ],
2204
+ ["hidden", fields.hidden === undefined || typeof fields.hidden === "boolean", "absent or a boolean"],
2205
+ [
2206
+ "needsProject",
2207
+ fields.needsProject === undefined || typeof fields.needsProject === "boolean",
2208
+ "absent or a boolean"
2209
+ ],
2210
+ ["exec", fields.exec === undefined || fields.exec === true, "absent or true"],
2211
+ ["run", typeof fields.run === "function", "a function"]
2212
+ ];
2213
+ const failed = checks.find(([, passes]) => !passes);
2214
+ if (failed === undefined)
2215
+ return null;
2216
+ const [key, , expected] = failed;
2217
+ return `${key} is ${describeValue(fields[key])}, expected ${expected}`;
2218
+ }
2219
+ function commandProblem(value) {
2220
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
2221
+ return `a command is ${describeValue(value)}, expected a mapping`;
2222
+ }
2223
+ const fields = value;
2224
+ const problem = fieldProblem(fields) ?? spendsProblem(fields.spends);
2225
+ if (problem === null)
2226
+ return null;
2227
+ const named = isRoutingWord(fields.subject) && isRoutingWord(fields.action) ? `command "${commandSpelling(fields)}"` : "a command";
2228
+ return `${named}: ${problem}`;
2229
+ }
2230
+ function isTopLevel(command) {
2231
+ return command.subject === command.action;
2232
+ }
2233
+ function commandSpelling(command) {
2234
+ return isTopLevel(command) ? command.subject : `${command.subject} ${command.action}`;
2235
+ }
2236
+
1992
2237
  // src/effort/store/fix-schema.ts
1993
- import { existsSync as existsSync7 } from "fs";
1994
- import { Database as Database2 } from "bun:sqlite";
2238
+ import { existsSync as existsSync8 } from "fs";
2239
+ import { Database as Database4 } from "bun:sqlite";
1995
2240
 
1996
2241
  // src/effort/store/rebuild-aside.ts
1997
- import { existsSync as existsSync6, renameSync as renameSync4, rmSync as rmSync4 } from "fs";
2242
+ import { closeSync, existsSync as existsSync7, fsyncSync, openSync, renameSync as renameSync5, rmSync as rmSync6 } from "fs";
2243
+
2244
+ // src/effort/store/copy.ts
2245
+ import { copyFileSync, constants, existsSync as existsSync6, mkdirSync as mkdirSync6, readdirSync as readdirSync2, rmSync as rmSync5, statSync as statSync2 } from "fs";
2246
+ import { join as join10, resolve as resolve3 } from "path";
2247
+ import { Database as Database3 } from "bun:sqlite";
2248
+ var NDJSON_KINDS = { sessions: true, commits: true };
2249
+ var EFFORT_COPY_FILE_NAMES = [
2250
+ SQLITE_STORE_FILE_NAME,
2251
+ ...Object.keys(NDJSON_KINDS).map((kind) => effortStoreFileName(kind))
2252
+ ];
2253
+
2254
+ class EffortCopyRefusal extends Error {
2255
+ name = "EffortCopyRefusal";
2256
+ }
2257
+
2258
+ class EffortCopyFailure extends Error {
2259
+ name = "EffortCopyFailure";
2260
+ }
2261
+ function refuseUsedTarget(target) {
2262
+ if (!existsSync6(target))
2263
+ return;
2264
+ let entries;
2265
+ try {
2266
+ if (!statSync2(target).isDirectory()) {
2267
+ throw new EffortCopyRefusal(`${target} is a file, not a directory; name an empty or absent directory with --to=<dir>.`);
2268
+ }
2269
+ entries = readdirSync2(target);
2270
+ } catch (error) {
2271
+ if (error instanceof EffortCopyRefusal)
2272
+ throw error;
2273
+ throw new EffortCopyFailure(`${target} cannot be read: ${String(error)}`);
2274
+ }
2275
+ if (entries.length === 0)
2276
+ return;
2277
+ throw new EffortCopyRefusal(`${target} is not empty (${String(entries.length)} entries); nothing was copied.` + " Name an empty or absent directory with --to=<dir>.");
2278
+ }
2279
+ function vacuumInto(source, target) {
2280
+ const db = new Database3(source, { readonly: true });
2281
+ try {
2282
+ db.run(`PRAGMA busy_timeout = ${String(activeStoreSettings().busyTimeoutMs)}`);
2283
+ db.run("VACUUM INTO ?", [target]);
2284
+ } finally {
2285
+ db.close();
2286
+ }
2287
+ }
2288
+ function copyOne(name, source, target) {
2289
+ if (name === SQLITE_STORE_FILE_NAME) {
2290
+ vacuumInto(join10(source, name), join10(target, name));
2291
+ return;
2292
+ }
2293
+ copyFileSync(join10(source, name), join10(target, name), constants.COPYFILE_EXCL);
2294
+ }
2295
+ function undo(target, written, madeDir) {
2296
+ try {
2297
+ if (madeDir === undefined) {
2298
+ for (const name of written)
2299
+ rmSync5(join10(target, name), { force: true });
2300
+ } else {
2301
+ rmSync5(madeDir, { recursive: true, force: true });
2302
+ }
2303
+ return "";
2304
+ } catch (error) {
2305
+ return ` Removing what it made failed too: ${String(error)}`;
2306
+ }
2307
+ }
2308
+ function copyEffortStore(request) {
2309
+ const source = resolve3(request.source);
2310
+ const target = resolve3(request.target);
2311
+ guardTestProcess(source);
2312
+ guardTestProcess(target);
2313
+ const files = EFFORT_COPY_FILE_NAMES.filter((name) => existsSync6(join10(source, name)));
2314
+ if (files.length === 0) {
2315
+ throw new EffortCopyRefusal(`no effort store at ${source}: it holds none of ${EFFORT_COPY_FILE_NAMES.join(", ")}. Nothing to copy.`);
2316
+ }
2317
+ refuseUsedTarget(target);
2318
+ const written = [];
2319
+ let madeDir;
2320
+ try {
2321
+ madeDir = mkdirSync6(target, { recursive: true });
2322
+ for (const name of files) {
2323
+ written.push(name);
2324
+ copyOne(name, source, target);
2325
+ }
2326
+ } catch (error) {
2327
+ const left = undo(target, written, madeDir);
2328
+ throw new EffortCopyFailure(`copying ${source} to ${target} failed: ${String(error)}.${left}`);
2329
+ }
2330
+ return Object.freeze({ source, directory: target, files: Object.freeze(files) });
2331
+ }
1998
2332
 
2333
+ // src/effort/store/rebuild-aside.ts
1999
2334
  class RebuildRefusal extends Error {
2000
- constructor(message) {
2001
- super(message);
2335
+ constructor(message, options) {
2336
+ super(message, options);
2002
2337
  this.name = "RebuildRefusal";
2003
2338
  }
2004
2339
  }
2005
- function quoted(name2) {
2006
- return `"${name2.replaceAll('"', '""')}"`;
2340
+ function quoted(name) {
2341
+ return `"${name.replaceAll('"', '""')}"`;
2007
2342
  }
2008
2343
  function count(db, sql) {
2009
2344
  return db.query(sql).get()?.n ?? 0;
2010
2345
  }
2011
2346
  function refuseInFlight(path) {
2012
2347
  for (const suffix of ["-journal", "-wal"]) {
2013
- if (existsSync6(`${path}${suffix}`)) {
2348
+ if (existsSync7(`${path}${suffix}`)) {
2014
2349
  throw new RebuildRefusal(`${path}${suffix} is there, so a write is in flight or was interrupted; stop whatever uses the store` + " and open it once with rafa before repairing it");
2015
2350
  }
2016
2351
  }
@@ -2033,21 +2368,78 @@ function refuseCorrupt(db) {
2033
2368
  throw new RebuildRefusal(`the rebuilt store failed integrity_check: ${answer ?? "no answer"}`);
2034
2369
  }
2035
2370
  function removeParallel(parallelPath) {
2036
- rmSync4(parallelPath, { force: true });
2037
- rmSync4(`${parallelPath}-journal`, { force: true });
2371
+ rmSync6(parallelPath, { force: true });
2372
+ rmSync6(`${parallelPath}-journal`, { force: true });
2373
+ }
2374
+ var STEP_TEXT = {
2375
+ backup: ({ path, backupPath }) => ({
2376
+ doing: `writing ${path} out to the backup ${backupPath}`,
2377
+ backup: `any part of the backup written at ${backupPath}`
2378
+ }),
2379
+ carry: ({ path, parallelPath, backupPath }) => ({
2380
+ doing: `carrying the store id of ${path} onto ${parallelPath}`,
2381
+ backup: `the whole backup at ${backupPath}`
2382
+ }),
2383
+ record: ({ path, parallelPath, backupPath }) => ({
2384
+ doing: `writing the generation carried onto ${parallelPath} to the side record of ${path}`,
2385
+ backup: `the whole backup at ${backupPath}`
2386
+ }),
2387
+ rename: ({ path, parallelPath, backupPath }) => ({
2388
+ doing: `renaming ${parallelPath} over ${path}`,
2389
+ backup: `the whole backup at ${backupPath}`
2390
+ })
2391
+ };
2392
+
2393
+ class SwapFailure extends RebuildRefusal {
2394
+ step;
2395
+ parallelPath;
2396
+ backupPath;
2397
+ constructor(step, files, cause) {
2398
+ const { doing, backup } = STEP_TEXT[step](files);
2399
+ const reason = cause instanceof Error ? cause.message : String(cause);
2400
+ super(`${doing} failed (${reason}), so ${files.path} was not replaced and is unchanged.` + ` The rebuilt store is left at ${files.parallelPath}, and ${backup}.`, { cause });
2401
+ this.name = "SwapFailure";
2402
+ this.step = step;
2403
+ this.parallelPath = files.parallelPath;
2404
+ this.backupPath = files.backupPath;
2405
+ }
2406
+ }
2407
+ function writeBackup(path, backupPath) {
2408
+ vacuumInto(path, backupPath);
2409
+ const backup = openSync(backupPath, "r");
2410
+ try {
2411
+ fsyncSync(backup);
2412
+ } finally {
2413
+ closeSync(backup);
2414
+ }
2038
2415
  }
2039
- function swapIn(path, parallelPath, backupPath) {
2040
- renameSync4(path, backupPath);
2416
+ var SWAP_STEPS = {
2417
+ backup: writeBackup,
2418
+ carry: (path, parallelPath) => carryStoreIdentity(path, parallelPath),
2419
+ record: writeStoreGeneration,
2420
+ rename: renameSync5
2421
+ };
2422
+ function runStep(step, files, act) {
2041
2423
  try {
2042
- renameSync4(parallelPath, path);
2424
+ return act();
2043
2425
  } catch (error) {
2044
- renameSync4(backupPath, path);
2045
- throw error;
2426
+ throw new SwapFailure(step, files, error);
2427
+ }
2428
+ }
2429
+ function swapIn(path, parallelPath, backupPath, steps = {}) {
2430
+ const { backup, carry, record, rename } = { ...SWAP_STEPS, ...steps };
2431
+ const files = { path, parallelPath, backupPath };
2432
+ runStep("backup", files, () => backup(path, backupPath));
2433
+ const carried = runStep("carry", files, () => carry(path, parallelPath));
2434
+ if (carried.action === "carried" && carried.generation !== null) {
2435
+ const { generation } = carried;
2436
+ runStep("record", files, () => record(path, generation));
2046
2437
  }
2438
+ runStep("rename", files, () => rename(parallelPath, path));
2047
2439
  }
2048
2440
  function refuseTaken(paths) {
2049
2441
  for (const taken of paths) {
2050
- if (existsSync6(taken))
2442
+ if (existsSync7(taken))
2051
2443
  throw new RebuildRefusal(`${taken} is already there; move it aside or pass another stamp`);
2052
2444
  }
2053
2445
  }
@@ -2086,7 +2478,7 @@ function columnNames(db, schema, table) {
2086
2478
  return db.query("SELECT name FROM pragma_table_info(?, ?)").all(table, schema).map((row) => row.name);
2087
2479
  }
2088
2480
  function readOnlySchema(path) {
2089
- const db = new Database2(path, { readonly: true });
2481
+ const db = new Database4(path, { readonly: true });
2090
2482
  try {
2091
2483
  return readStoreSchema(db, path);
2092
2484
  } finally {
@@ -2134,7 +2526,7 @@ function refuseUnusable(db, parallelPath, migrations) {
2134
2526
  throw new RebuildRefusal(`the rebuilt store still needs ${needs.join(", ")}`);
2135
2527
  }
2136
2528
  function buildParallel(path, parallelPath, migrations, stamp) {
2137
- const db = new Database2(parallelPath, { create: true, readwrite: true });
2529
+ const db = new Database4(parallelPath, { create: true, readwrite: true });
2138
2530
  try {
2139
2531
  bringForward(db, parallelPath, "write", "open", { migrations, ...stamp, builtAside: true });
2140
2532
  db.run(`ATTACH DATABASE ? AS ${LIVE}`, [path]);
@@ -2152,8 +2544,8 @@ function buildParallel(path, parallelPath, migrations, stamp) {
2152
2544
  db.close();
2153
2545
  }
2154
2546
  }
2155
- function asidePaths(path, version2, stamp) {
2156
- return { parallelPath: `${path}.fix-${stamp}`, backupPath: `${path}.v${String(version2)}-${stamp}.bak` };
2547
+ function asidePaths(path, version, stamp) {
2548
+ return { parallelPath: `${path}.fix-${stamp}`, backupPath: `${path}.v${String(version)}-${stamp}.bak` };
2157
2549
  }
2158
2550
  function isRepairable(reason) {
2159
2551
  return REPAIRABLE_REASONS.includes(reason);
@@ -2171,7 +2563,7 @@ function fixStoreSchema(options) {
2171
2563
  const appliedBy = appliedByName(identity);
2172
2564
  const known = migrations.map(({ id }) => id);
2173
2565
  const nothing = { known, appliedBy, pending: [], kept: [], leftTables: [], leftColumns: [], backupPath: null };
2174
- if (!existsSync7(path)) {
2566
+ if (!existsSync8(path)) {
2175
2567
  return { path, status: "missing", storeVersion: null, logged: false, reason: null, refusal: null, unknown: [], ...nothing };
2176
2568
  }
2177
2569
  refuseInFlight(path);
@@ -2186,8 +2578,8 @@ function fixStoreSchema(options) {
2186
2578
  const plan = planSchema(store, sqliteCatalogue(migrations), "write", "open");
2187
2579
  if (plan.verdict === "use") {
2188
2580
  const pending = writeNames(plan);
2189
- const status2 = pending.length === 0 ? "current" : "behind";
2190
- return { ...found, ...nothing, status: status2, reason: null, refusal: null, pending };
2581
+ const status = pending.length === 0 ? "current" : "behind";
2582
+ return { ...found, ...nothing, status, reason: null, refusal: null, pending };
2191
2583
  }
2192
2584
  if (!isRepairable(plan.reason)) {
2193
2585
  throw new RebuildRefusal(`a rebuild at this rafa's migrations does not repair ${plan.reason}. ${plan.message}`);
@@ -2213,24 +2605,24 @@ function withoutWayOut(message, nextStep) {
2213
2605
  }
2214
2606
 
2215
2607
  // src/commands/plan/plan-files.ts
2216
- import { statSync as statSync2 } from "fs";
2217
- import { resolve as resolve3 } from "path";
2608
+ import { statSync as statSync3 } from "fs";
2609
+ import { resolve as resolve4 } from "path";
2218
2610
 
2219
2611
  // src/config-load.ts
2220
- import { existsSync as existsSync8, readFileSync as readFileSync7, realpathSync as realpathSync5 } from "fs";
2612
+ import { existsSync as existsSync9, readFileSync as readFileSync8, realpathSync as realpathSync5 } from "fs";
2221
2613
  import { isAbsolute as isAbsolute6 } from "path";
2222
- function readConfigFile(root) {
2223
- const path = configFilePath(root);
2224
- if (!existsSync8(path))
2614
+ function readConfigFile2(root) {
2615
+ const path = configFilePath2(root);
2616
+ if (!existsSync9(path))
2225
2617
  return null;
2226
2618
  let text;
2227
2619
  try {
2228
- text = readFileSync7(path, "utf8");
2620
+ text = readFileSync8(path, "utf8");
2229
2621
  } catch (error) {
2230
2622
  const problem = `${path}: cannot be read (${messageOf(error)})`;
2231
- throw new ConfigError([problem], { cause: error });
2623
+ throw new ConfigError2([problem], { cause: error });
2232
2624
  }
2233
- return parseConfigText(text, path);
2625
+ return parseConfigText2(text, path);
2234
2626
  }
2235
2627
  function isSameDirectory(first, second) {
2236
2628
  try {
@@ -2241,19 +2633,19 @@ function isSameDirectory(first, second) {
2241
2633
  }
2242
2634
  function readUserConfigFile({ root, home }) {
2243
2635
  if (!isAbsolute6(home)) {
2244
- throw new ConfigError([
2636
+ throw new ConfigError2([
2245
2637
  `home directory is ${describeValue(home)}, expected an absolute path`
2246
2638
  ]);
2247
2639
  }
2248
- return isSameDirectory(root, home) ? null : readConfigFile(home);
2640
+ return isSameDirectory(root, home) ? null : readConfigFile2(home);
2249
2641
  }
2250
2642
  function printWarning(message) {
2251
2643
  activeOutput().warn(message);
2252
2644
  }
2253
- function loadConfig(roots, cli = {}, warn = printWarning) {
2645
+ function loadConfig2(roots, cli = {}, warn = printWarning) {
2254
2646
  const user = readUserConfigFile(roots);
2255
- const file = readConfigFile(roots.root);
2256
- const resolved = resolveConfig({ cli, file, user });
2647
+ const file = readConfigFile2(roots.root);
2648
+ const resolved = resolveConfig2({ cli, file, user });
2257
2649
  for (const warning of resolved.warnings)
2258
2650
  warn(warning);
2259
2651
  setActiveStoreSettings({ busyTimeoutMs: resolved.config.effortBusyTimeoutMs });
@@ -2262,7 +2654,7 @@ function loadConfig(roots, cli = {}, warn = printWarning) {
2262
2654
 
2263
2655
  // src/commands/plan/plan-files.ts
2264
2656
  function plansDirAt(root, planDir) {
2265
- return { label: planDir, path: resolve3(root, planDir) };
2657
+ return { label: planDir, path: resolve4(root, planDir) };
2266
2658
  }
2267
2659
  function requireProject(context, command) {
2268
2660
  if (context.project === null)
@@ -2274,9 +2666,9 @@ function resolvePlansDir(project, command, warn) {
2274
2666
  }
2275
2667
  function resolveProjectConfig(project, command, warn) {
2276
2668
  try {
2277
- return loadConfig({ root: project.root, home: project.home }, {}, warn).config;
2669
+ return loadConfig2({ root: project.root, home: project.home }, {}, warn).config;
2278
2670
  } catch (error) {
2279
- if (!(error instanceof ConfigError))
2671
+ if (!(error instanceof ConfigError2))
2280
2672
  throw error;
2281
2673
  throw new CommandExit(1, [
2282
2674
  `\u274C ${command}: the config cannot be used:`,
@@ -2304,18 +2696,18 @@ function checkbox(status) {
2304
2696
  function planFileName(stub, tracker) {
2305
2697
  return tracker ? `PLAN_TRACKER-${stub}.md` : `PLAN-${stub}.md`;
2306
2698
  }
2307
- function stubOfPlanFile(name2) {
2308
- const stub = /^PLAN-(.+)\.md$/.exec(name2)?.[1];
2699
+ function stubOfPlanFile(name) {
2700
+ const stub = /^PLAN-(.+)\.md$/.exec(name)?.[1];
2309
2701
  return stub !== undefined && isStampableStub(stub) ? stub : null;
2310
2702
  }
2311
2703
  function isFile(path) {
2312
- return statSync2(path, { throwIfNoEntry: false })?.isFile() ?? false;
2704
+ return statSync3(path, { throwIfNoEntry: false })?.isFile() ?? false;
2313
2705
  }
2314
2706
  function issueLine(file, issue) {
2315
2707
  return `${file}:${issue.line}: ${issue.reason}: ${issue.text}`;
2316
2708
  }
2317
- function plural(count2, noun) {
2318
- return count2 === 1 ? `${count2} ${noun}` : `${count2} ${noun}s`;
2709
+ function plural(count, noun) {
2710
+ return count === 1 ? `${count} ${noun}` : `${count} ${noun}s`;
2319
2711
  }
2320
2712
  function expectNoArgument(args, usage) {
2321
2713
  if (args.length === 0)
@@ -2340,12 +2732,12 @@ function expectAtMostOneArgument(args, usage) {
2340
2732
  throw new CommandExit(1, `\u274C Expected at most one argument, got ${args.length}: ${args.join(" ")}
2341
2733
  Usage: ${usage}`);
2342
2734
  }
2343
- function readSwitch(name2, value, hint) {
2735
+ function readSwitch(name, value, hint) {
2344
2736
  if (value === undefined || value === false || value === "false")
2345
2737
  return false;
2346
2738
  if (value === true || value === "true")
2347
2739
  return true;
2348
- throw new CommandExit(1, `\u274C --${name2} takes no value, and read "${value}" as one. ${hint}`);
2740
+ throw new CommandExit(1, `\u274C --${name} takes no value, and read "${value}" as one. ${hint}`);
2349
2741
  }
2350
2742
 
2351
2743
  // src/commands/effort/fix-schema.ts
@@ -2355,6 +2747,9 @@ var DRY_RUN_FLAG = "dry-run";
2355
2747
  function fileStamp(date) {
2356
2748
  return date.toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
2357
2749
  }
2750
+ function keepsIdLine(swapped) {
2751
+ return `The ${swapped} keeps the store's id; the backup is a copy, so renamed back it takes a new id on its` + " next write.";
2752
+ }
2358
2753
  function refuseLiveLoop(root, isAlive) {
2359
2754
  let records;
2360
2755
  try {
@@ -2412,7 +2807,7 @@ function renderFixSchema(result) {
2412
2807
  case "rebuilt":
2413
2808
  return [
2414
2809
  ...rebuildLines(result),
2415
- `\u2705 Rebuilt at this rafa's migrations. The original is kept whole at ${String(result.backupPath)};` + " rename it back to undo."
2810
+ `\u2705 Rebuilt at this rafa's migrations. The original is kept whole at ${String(result.backupPath)};` + ` rename it back to undo. ${keepsIdLine("rebuild")}`
2416
2811
  ];
2417
2812
  }
2418
2813
  }
@@ -2452,7 +2847,7 @@ function createFixSchemaCommand(seams = {}) {
2452
2847
  subject: "effort",
2453
2848
  action: "fix-schema",
2454
2849
  summary: "rebuild an effort store this rafa refuses at the migrations it knows, keeping the original",
2455
- description: "Repairs `.rafa/effort/effort.sqlite`, or the store under `RAFA_EFFORT_DIR`, when this rafa refuses" + " it for a reason a rebuild repairs: no migration log past the legacy entries (pre-log-unreleased), a log" + " with a schema version it does not match (gate-mismatch), a logged checksum this rafa holds otherwise" + " (edited), or a logged migration this rafa does not know that breaks older readers or writers" + " (unknown-breaks-readers, unknown-breaks-writers). Installing a rafa that knows the store's migrations" + " comes first where one exists. It builds a parallel store beside it at this rafa's migrations, with a" + " migration log naming this rafa, copies every table and column this rafa knows, checks the row counts," + " SQLite's integrity_check and the schema plan, and lists what only the newer schema holds, unknown" + " migrations included. Then it renames the original to `effort.sqlite.v<user_version>-<stamp>.bak`," + " whole, and moves the rebuild into its place. A store this rafa uses, current or behind, or no store, is" + " left alone. It refuses, changing nothing, while a loop session under the project is running or paused," + " from a development build, while a journal beside the store shows a write in flight, when the newer" + " schema lacks a table or column this rafa writes, and on a refusal a rebuild does not repair. With" + " `--output=json` the outcome is the data of the terminal result event. Starts no session.",
2850
+ description: "Repairs `.rafa/effort/effort.sqlite`, or the store under `RAFA_EFFORT_DIR`, when this rafa refuses" + " it for a reason a rebuild repairs: no migration log past the legacy entries (pre-log-unreleased), a log" + " with a schema version it does not match (gate-mismatch), a logged checksum this rafa holds otherwise" + " (edited), or a logged migration this rafa does not know that breaks older readers or writers" + " (unknown-breaks-readers, unknown-breaks-writers). Installing a rafa that knows the store's migrations" + " comes first where one exists. It builds a parallel store beside it at this rafa's migrations, with a" + " migration log naming this rafa, copies every table and column this rafa knows, checks the row counts," + " SQLite's integrity_check and the schema plan, and lists what only the newer schema holds, unknown" + " migrations included. Then it writes the original to `effort.sqlite.v<user_version>-<stamp>.bak`," + " whole, and moves the rebuild into its place. The rebuild keeps the store's id; the backup is a copy," + " so renamed back it takes a new id on its next write. A store this rafa uses, current or behind, or no store, is" + " left alone. It refuses, changing nothing, while a loop session under the project is running or paused," + " from a development build, while a journal beside the store shows a write in flight, when the newer" + " schema lacks a table or column this rafa writes, and on a refusal a rebuild does not repair. With" + " `--output=json` the outcome is the data of the terminal result event. Starts no session.",
2456
2851
  args: [],
2457
2852
  flags: [
2458
2853
  {
@@ -2481,101 +2876,12 @@ function createFixSchemaCommand(seams = {}) {
2481
2876
  }
2482
2877
  var fix_schema_default = createFixSchemaCommand();
2483
2878
 
2484
- // src/effort/store/copy.ts
2485
- import { copyFileSync, constants, existsSync as existsSync9, mkdirSync as mkdirSync6, readdirSync as readdirSync2, rmSync as rmSync5, statSync as statSync3 } from "fs";
2486
- import { join as join10, resolve as resolve4 } from "path";
2487
- import { Database as Database3 } from "bun:sqlite";
2488
- var NDJSON_KINDS = { sessions: true, commits: true };
2489
- var EFFORT_COPY_FILE_NAMES = [
2490
- SQLITE_STORE_FILE_NAME,
2491
- ...Object.keys(NDJSON_KINDS).map((kind) => effortStoreFileName(kind))
2492
- ];
2493
-
2494
- class EffortCopyRefusal extends Error {
2495
- name = "EffortCopyRefusal";
2496
- }
2497
-
2498
- class EffortCopyFailure extends Error {
2499
- name = "EffortCopyFailure";
2500
- }
2501
- function refuseUsedTarget(target) {
2502
- if (!existsSync9(target))
2503
- return;
2504
- let entries;
2505
- try {
2506
- if (!statSync3(target).isDirectory()) {
2507
- throw new EffortCopyRefusal(`${target} is a file, not a directory; name an empty or absent directory with --to=<dir>.`);
2508
- }
2509
- entries = readdirSync2(target);
2510
- } catch (error) {
2511
- if (error instanceof EffortCopyRefusal)
2512
- throw error;
2513
- throw new EffortCopyFailure(`${target} cannot be read: ${String(error)}`);
2514
- }
2515
- if (entries.length === 0)
2516
- return;
2517
- throw new EffortCopyRefusal(`${target} is not empty (${String(entries.length)} entries); nothing was copied.` + " Name an empty or absent directory with --to=<dir>.");
2518
- }
2519
- function vacuumInto(source, target) {
2520
- const db = new Database3(source, { readonly: true });
2521
- try {
2522
- db.run(`PRAGMA busy_timeout = ${String(activeStoreSettings().busyTimeoutMs)}`);
2523
- db.run("VACUUM INTO ?", [target]);
2524
- } finally {
2525
- db.close();
2526
- }
2527
- }
2528
- function copyOne(name2, source, target) {
2529
- if (name2 === SQLITE_STORE_FILE_NAME) {
2530
- vacuumInto(join10(source, name2), join10(target, name2));
2531
- return;
2532
- }
2533
- copyFileSync(join10(source, name2), join10(target, name2), constants.COPYFILE_EXCL);
2534
- }
2535
- function undo(target, written, madeDir) {
2536
- try {
2537
- if (madeDir === undefined) {
2538
- for (const name2 of written)
2539
- rmSync5(join10(target, name2), { force: true });
2540
- } else {
2541
- rmSync5(madeDir, { recursive: true, force: true });
2542
- }
2543
- return "";
2544
- } catch (error) {
2545
- return ` Removing what it made failed too: ${String(error)}`;
2546
- }
2547
- }
2548
- function copyEffortStore(request) {
2549
- const source = resolve4(request.source);
2550
- const target = resolve4(request.target);
2551
- guardTestProcess(source);
2552
- guardTestProcess(target);
2553
- const files = EFFORT_COPY_FILE_NAMES.filter((name2) => existsSync9(join10(source, name2)));
2554
- if (files.length === 0) {
2555
- throw new EffortCopyRefusal(`no effort store at ${source}: it holds none of ${EFFORT_COPY_FILE_NAMES.join(", ")}. Nothing to copy.`);
2556
- }
2557
- refuseUsedTarget(target);
2558
- const written = [];
2559
- let madeDir;
2560
- try {
2561
- madeDir = mkdirSync6(target, { recursive: true });
2562
- for (const name2 of files) {
2563
- written.push(name2);
2564
- copyOne(name2, source, target);
2565
- }
2566
- } catch (error) {
2567
- const left = undo(target, written, madeDir);
2568
- throw new EffortCopyFailure(`copying ${source} to ${target} failed: ${String(error)}.${left}`);
2569
- }
2570
- return Object.freeze({ source, directory: target, files: Object.freeze(files) });
2571
- }
2572
-
2573
2879
  // src/effort/store/merge-store.ts
2574
- import { randomUUID as randomUUID4 } from "crypto";
2575
- import { existsSync as existsSync11, mkdtempSync, rmSync as rmSync6 } from "fs";
2880
+ import { randomUUID as randomUUID5 } from "crypto";
2881
+ import { existsSync as existsSync11, mkdtempSync, rmSync as rmSync7 } from "fs";
2576
2882
  import { tmpdir as tmpdir3 } from "os";
2577
2883
  import { dirname as dirname11, join as join11 } from "path";
2578
- import { Database as Database5, SQLiteError as SQLiteError2 } from "bun:sqlite";
2884
+ import { Database as Database6, SQLiteError as SQLiteError2 } from "bun:sqlite";
2579
2885
 
2580
2886
  // src/effort/commits.ts
2581
2887
  import { execFileSync } from "child_process";
@@ -2593,8 +2899,8 @@ function normaliseBranch(source) {
2593
2899
  return null;
2594
2900
  return source.startsWith("refs/heads/") ? source.slice("refs/heads/".length) : source;
2595
2901
  }
2596
- function parseStatCount(field2) {
2597
- return /^\d+$/.test(field2) ? Number(field2) : null;
2902
+ function parseStatCount(field) {
2903
+ return /^\d+$/.test(field) ? Number(field) : null;
2598
2904
  }
2599
2905
  function parseCommitHeader(line) {
2600
2906
  const parts = line.split(FIELD_SEPARATOR);
@@ -2822,7 +3128,7 @@ function mergedTables() {
2822
3128
  return Object.entries(MERGE_RULES).flatMap(([table, rule]) => rule.scope === "merged" ? [{ table, identity: rule.identity }] : []);
2823
3129
  }
2824
3130
  function carriedColumns(db, table) {
2825
- return db.query(`PRAGMA table_info(${quoted(table)})`).all().map(({ name: name2 }) => name2).filter((name2) => name2 !== "seq");
3131
+ return db.query(`PRAGMA table_info(${quoted(table)})`).all().map(({ name }) => name).filter((name) => name !== "seq");
2826
3132
  }
2827
3133
  function refuseColumnMismatch(local, other, tables) {
2828
3134
  const faults = tables.flatMap(({ table }) => {
@@ -2913,29 +3219,29 @@ function sameValue(left, right) {
2913
3219
  return Buffer.from(left).equals(right);
2914
3220
  return (left ?? null) === (right ?? null);
2915
3221
  }
2916
- function fillStatement(table, field2) {
2917
- const statement = SET_ONCE_FILLS[`${table}.${field2}`];
3222
+ function fillStatement(table, field) {
3223
+ const statement = SET_ONCE_FILLS[`${table}.${field}`];
2918
3224
  if (statement === undefined) {
2919
- throw new Error(`${table}.${field2} is set-once in MERGE_RULES and has no statement in SET_ONCE_FILLS`);
3225
+ throw new Error(`${table}.${field} is set-once in MERGE_RULES and has no statement in SET_ONCE_FILLS`);
2920
3226
  }
2921
3227
  return statement;
2922
3228
  }
2923
- function settleSetOnce(local, table, field2, here, there) {
2924
- const incoming = there[field2] ?? null;
3229
+ function settleSetOnce(local, table, field, here, there) {
3230
+ const incoming = there[field] ?? null;
2925
3231
  if (incoming === null)
2926
3232
  return { skipped: true, filled: [], conflictFields: [] };
2927
- if ((here[field2] ?? null) !== null)
2928
- return { skipped: false, filled: [], conflictFields: [field2] };
2929
- local.query(fillStatement(table, field2)).run(incoming, Number(here.seq));
2930
- return { skipped: true, filled: [field2], conflictFields: [] };
3233
+ if ((here[field] ?? null) !== null)
3234
+ return { skipped: false, filled: [], conflictFields: [field] };
3235
+ local.query(fillStatement(table, field)).run(incoming, Number(here.seq));
3236
+ return { skipped: true, filled: [field], conflictFields: [] };
2931
3237
  }
2932
- function settleRecomputed(table, field2, here, there) {
2933
- const comparable = RECOMPUTED_COMPARISONS[`${table}.${field2}`];
3238
+ function settleRecomputed(table, field, here, there) {
3239
+ const comparable = RECOMPUTED_COMPARISONS[`${table}.${field}`];
2934
3240
  if (comparable === undefined) {
2935
- throw new Error(`${table}.${field2} is recomputed in MERGE_RULES and has no entry in RECOMPUTED_COMPARISONS`);
3241
+ throw new Error(`${table}.${field} is recomputed in MERGE_RULES and has no entry in RECOMPUTED_COMPARISONS`);
2936
3242
  }
2937
- const hereValue = here[field2];
2938
- const thereValue = there[field2];
3243
+ const hereValue = here[field];
3244
+ const thereValue = there[field];
2939
3245
  const same = typeof hereValue === "string" && typeof thereValue === "string" && comparable(hereValue) === comparable(thereValue);
2940
3246
  return same ? { skipped: true, filled: [], conflictFields: [] } : { skipped: false, filled: [], conflictFields: [null] };
2941
3247
  }
@@ -2945,12 +3251,12 @@ function settlePair(local, table, edited, here, there) {
2945
3251
  return { skipped: true, filled: [], conflictFields: [] };
2946
3252
  if (differing.some((column) => !Object.hasOwn(edited, column)))
2947
3253
  return { skipped: false, filled: [], conflictFields: [null] };
2948
- const outcomes = differing.map((field2) => {
2949
- if (edited[field2] === SET_ONCE)
2950
- return settleSetOnce(local, table, field2, here, there);
2951
- if (edited[field2] === RECOMPUTED)
2952
- return settleRecomputed(table, field2, here, there);
2953
- throw new Error(`${table}.${field2} has the rule ${edited[field2]}, which the merge does not apply`);
3254
+ const outcomes = differing.map((field) => {
3255
+ if (edited[field] === SET_ONCE)
3256
+ return settleSetOnce(local, table, field, here, there);
3257
+ if (edited[field] === RECOMPUTED)
3258
+ return settleRecomputed(table, field, here, there);
3259
+ throw new Error(`${table}.${field} has the rule ${edited[field]}, which the merge does not apply`);
2954
3260
  });
2955
3261
  return {
2956
3262
  skipped: outcomes.every((outcome) => outcome.skipped),
@@ -2967,16 +3273,16 @@ function settleTable(local, other, union, trail) {
2967
3273
  const here = rowAt(local, union.table, columns, match.localSeq, "here");
2968
3274
  const there = rowAt(other, union.table, columns, match.incomingSeq, "in the other store");
2969
3275
  const outcome = settlePair(local, union.table, rule.edited, here, there);
2970
- const conflicts = outcome.conflictFields.map((field2) => {
2971
- local.query(INSERT_CONFLICT).run(trail.mergeId, union.table, match.localSeq, field2, JSON.stringify(there), trail.recordedAt);
2972
- return { localSeq: match.localSeq, incomingSeq: match.incomingSeq, field: field2 };
3276
+ const conflicts = outcome.conflictFields.map((field) => {
3277
+ local.query(INSERT_CONFLICT).run(trail.mergeId, union.table, match.localSeq, field, JSON.stringify(there), trail.recordedAt);
3278
+ return { localSeq: match.localSeq, incomingSeq: match.incomingSeq, field };
2973
3279
  });
2974
3280
  return { match, outcome, conflicts };
2975
3281
  });
2976
3282
  return {
2977
3283
  table: union.table,
2978
3284
  skipped: settled.flatMap(({ match, outcome }) => outcome.skipped ? [match.localSeq] : []),
2979
- filled: settled.flatMap(({ match, outcome }) => outcome.filled.map((field2) => ({ localSeq: match.localSeq, field: field2 }))),
3285
+ filled: settled.flatMap(({ match, outcome }) => outcome.filled.map((field) => ({ localSeq: match.localSeq, field }))),
2980
3286
  conflicts: settled.flatMap(({ conflicts }) => conflicts)
2981
3287
  };
2982
3288
  }
@@ -2986,7 +3292,7 @@ function settleMatches(local, other, unions, trail) {
2986
3292
 
2987
3293
  // src/effort/store/migrate.ts
2988
3294
  import { existsSync as existsSync10 } from "fs";
2989
- import { Database as Database4 } from "bun:sqlite";
3295
+ import { Database as Database5 } from "bun:sqlite";
2990
3296
  var LIVE2 = "live";
2991
3297
  function asidePaths2(path, first, stamp) {
2992
3298
  return { parallelPath: `${path}.migrate-${stamp}`, backupPath: `${path}.before-${first}-${stamp}.bak` };
@@ -3014,7 +3320,7 @@ function refuseLiveLoop2(path, breaking, options) {
3014
3320
  }
3015
3321
  function buildMigrated(path, parallelPath, migrations, stamp) {
3016
3322
  vacuumInto(path, parallelPath);
3017
- const db = new Database4(parallelPath, { readwrite: true });
3323
+ const db = new Database5(parallelPath, { readwrite: true });
3018
3324
  try {
3019
3325
  const brought = bringForward(db, parallelPath, "write", "migrate", { migrations, ...stamp, builtAside: true });
3020
3326
  db.run(`ATTACH DATABASE ? AS ${LIVE2}`, [path]);
@@ -3098,7 +3404,7 @@ function refuseMissing(path, which) {
3098
3404
  function refuseDamaged(path) {
3099
3405
  let answers;
3100
3406
  try {
3101
- const db = new Database5(path, { readonly: true });
3407
+ const db = new Database6(path, { readonly: true });
3102
3408
  try {
3103
3409
  answers = db.query("PRAGMA integrity_check").all().map((row) => row.integrity_check);
3104
3410
  } finally {
@@ -3120,7 +3426,7 @@ function writablePlan(path, migrations) {
3120
3426
  return plan;
3121
3427
  }
3122
3428
  function recordedMeta(path) {
3123
- const db = new Database5(path, { readonly: true });
3429
+ const db = new Database6(path, { readonly: true });
3124
3430
  try {
3125
3431
  const hasTable = db.query("SELECT count(*) AS n FROM sqlite_master WHERE type = 'table' AND name = 'store_meta'").get()?.n === 1;
3126
3432
  return hasTable ? readStoreMeta(db) : null;
@@ -3146,18 +3452,18 @@ function refuseLiveLoop3(path, options, sessionId) {
3146
3452
  function openOther(otherPath, plan, stamp) {
3147
3453
  const needs = writeNames(plan);
3148
3454
  if (needs.length === 0) {
3149
- const db = new Database5(otherPath, { readonly: true });
3455
+ const db = new Database6(otherPath, { readonly: true });
3150
3456
  return { db, broughtForward: [], release: () => db.close() };
3151
3457
  }
3152
3458
  const dir = mkdtempSync(join11(tmpdir3(), "rafa-merge-other-"));
3153
3459
  const release = (db) => {
3154
3460
  db?.close();
3155
- rmSync6(dir, { recursive: true, force: true });
3461
+ rmSync7(dir, { recursive: true, force: true });
3156
3462
  };
3157
3463
  try {
3158
3464
  const copyPath = join11(dir, "other.sqlite");
3159
3465
  vacuumInto(otherPath, copyPath);
3160
- const db = new Database5(copyPath, { readwrite: true });
3466
+ const db = new Database6(copyPath, { readwrite: true });
3161
3467
  try {
3162
3468
  bringForward(db, copyPath, "write", "open", { ...stamp, builtAside: true });
3163
3469
  } catch (error) {
@@ -3186,7 +3492,7 @@ function mergeInto(db, other, mergeId, otherStore, mergedAt) {
3186
3492
  collided: union.collided.length
3187
3493
  };
3188
3494
  });
3189
- const sum = (field2) => tables.reduce((total, entry) => total + entry[field2], 0);
3495
+ const sum = (field) => tables.reduce((total, entry) => total + entry[field], 0);
3190
3496
  const totals = { rowsAdded: sum("added"), rowsSkipped: sum("skipped"), rowsInConflict: sum("inConflict") };
3191
3497
  db.query(INSERT_MERGE).run(mergeId, otherStore, mergedAt, totals.rowsAdded, totals.rowsSkipped, totals.rowsInConflict);
3192
3498
  return { tables, ...totals, gapsRewritten: gaps.length };
@@ -3199,18 +3505,18 @@ function addedRows(merged) {
3199
3505
  merge_conflicts: merged.rowsInConflict
3200
3506
  };
3201
3507
  }
3202
- function buildMerged(path, parallelPath, other, merge2) {
3508
+ function buildMerged(path, parallelPath, other, merge) {
3203
3509
  vacuumInto(path, parallelPath);
3204
- const db = new Database5(parallelPath, { readwrite: true });
3510
+ const db = new Database6(parallelPath, { readwrite: true });
3205
3511
  try {
3206
- bringForward(db, parallelPath, "write", "open", { ...merge2.stamp, builtAside: true });
3207
- const merged = mergeInto(db, other, merge2.id, merge2.otherStore, merge2.stamp.now().toISOString());
3512
+ bringForward(db, parallelPath, "write", "open", { ...merge.stamp, builtAside: true });
3513
+ const merged = mergeInto(db, other, merge.id, merge.otherStore, merge.stamp.now().toISOString());
3208
3514
  db.run(`ATTACH DATABASE ? AS ${LIVE3}`, [path]);
3209
3515
  const live = new Set(tableNames(db, LIVE3));
3210
3516
  checkedCounts(db, tableNames(db, "main").filter((table) => live.has(table)), LIVE3, addedRows(merged));
3211
3517
  db.run(`DETACH DATABASE ${LIVE3}`);
3212
3518
  refuseCorrupt(db);
3213
- refuseUnusable(db, parallelPath, merge2.stamp.migrations);
3519
+ refuseUnusable(db, parallelPath, merge.stamp.migrations);
3214
3520
  return merged;
3215
3521
  } finally {
3216
3522
  db.close();
@@ -3233,7 +3539,7 @@ function refuseUnmergeable(options, migrations) {
3233
3539
  }
3234
3540
  return { otherPlan, otherStore };
3235
3541
  }
3236
- function mergeStore(options) {
3542
+ function mergeStore2(options) {
3237
3543
  const { path, otherPath, dryRun, stamp } = options;
3238
3544
  guardTestProcess(path);
3239
3545
  guardTestProcess(otherPath);
@@ -3244,7 +3550,7 @@ function mergeStore(options) {
3244
3550
  appliedBy: appliedByName(options.identity ?? readRuntimeIdentity()),
3245
3551
  now: options.now ?? (() => new Date)
3246
3552
  };
3247
- const mergeId = (options.newMergeId ?? randomUUID4)();
3553
+ const mergeId = (options.newMergeId ?? randomUUID5)();
3248
3554
  const other = openOther(otherPath, otherPlan, mergeStamp);
3249
3555
  try {
3250
3556
  const { built, backupPath } = rebuildAside({
@@ -3268,10 +3574,10 @@ var NOTHING_COPIED = "Nothing was copied.";
3268
3574
  class FileSyncRefusal extends Error {
3269
3575
  name = "FileSyncRefusal";
3270
3576
  }
3271
- function requirePath(field2, value) {
3577
+ function requirePath(field, value) {
3272
3578
  if (typeof value === "string" && value !== "")
3273
3579
  return value;
3274
- throw new TypeError(`${REFUSAL}: ${field2} is ${describeValue(value)}, expected a path`);
3580
+ throw new TypeError(`${REFUSAL}: ${field} is ${describeValue(value)}, expected a path`);
3275
3581
  }
3276
3582
  function refuseUncarriable(backend, source) {
3277
3583
  if (backend === "ndjson") {
@@ -3301,8 +3607,8 @@ function createFileSync(options) {
3301
3607
  const otherPath = resolve5(repoRoot, requirePath("from", from));
3302
3608
  const path = join12(storeDir(), SQLITE_STORE_FILE_NAME);
3303
3609
  const stamp = fileStamp(now());
3304
- const merge2 = mergeStore({ ...mergeSeams(options), path, otherPath, backend, dryRun, stamp, now, sessionId });
3305
- return Object.freeze({ status: "pulled", merge: merge2 });
3610
+ const merge = mergeStore2({ ...mergeSeams(options), path, otherPath, backend, dryRun, stamp, now, sessionId });
3611
+ return Object.freeze({ status: "pulled", merge });
3306
3612
  };
3307
3613
  return Object.freeze({ kind: "file", push, pull });
3308
3614
  }
@@ -3353,7 +3659,7 @@ function contextOf(repoRoot, config) {
3353
3659
  ...hub === undefined ? {} : { hub }
3354
3660
  };
3355
3661
  }
3356
- function selectSync(repoRoot, config, registry = CORE_ADAPTER_REGISTRY) {
3662
+ function selectSync(repoRoot, config, registry = CORE_ADAPTER_REGISTRY2) {
3357
3663
  const kind = config.effortSync;
3358
3664
  const adapter = typeof kind === "string" ? registry.find("sync", kind) : undefined;
3359
3665
  if (adapter !== undefined)
@@ -3361,8 +3667,8 @@ function selectSync(repoRoot, config, registry = CORE_ADAPTER_REGISTRY) {
3361
3667
  const registered = registry.kinds("sync");
3362
3668
  if (isModuleStrategy(kind))
3363
3669
  throw new SyncModuleMissing(kind, registered);
3364
- const known = SYNC_STRATEGIES.includes(kind);
3365
- const expected = known ? `registered: ${listed(registered)}` : `expected one of: ${SYNC_STRATEGIES.join(", ")}`;
3670
+ const known = SYNC_STRATEGIES2.includes(kind);
3671
+ const expected = known ? `registered: ${listed(registered)}` : `expected one of: ${SYNC_STRATEGIES2.join(", ")}`;
3366
3672
  throw new TypeError(`${REFUSAL2}: effort.sync is ${describeValue(kind)}, and no sync adapter is registered under it; ${expected}`);
3367
3673
  }
3368
3674
 
@@ -3371,13 +3677,13 @@ import { appendFile, mkdir, readFile, rm, writeFile } from "fs/promises";
3371
3677
  import { join as join15 } from "path";
3372
3678
 
3373
3679
  // src/commands/instinct/instinct-records.ts
3374
- import { readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
3680
+ import { readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
3375
3681
  import { join as join14 } from "path";
3376
3682
 
3377
3683
  // src/check/layout.ts
3378
3684
  import { readdirSync as readdirSync3, statSync as statSync4 } from "fs";
3379
3685
  import { join as join13, relative as relative2 } from "path";
3380
- var SKILL_FILE = "SKILL.md";
3686
+ var SKILL_FILE2 = "SKILL.md";
3381
3687
  var MARKDOWN_EXTENSION = ".md";
3382
3688
  var LAYOUT_SEVERITY = Object.freeze({
3383
3689
  "flat-grouped-layout": "failure",
@@ -3405,13 +3711,13 @@ function entryKind(path) {
3405
3711
  }
3406
3712
  }
3407
3713
  function visibleNames(dir) {
3408
- return readdirSync3(dir).filter((name2) => !name2.startsWith(".")).sort((left, right) => left.localeCompare(right));
3714
+ return readdirSync3(dir).filter((name) => !name.startsWith(".")).sort((left, right) => left.localeCompare(right));
3409
3715
  }
3410
- function isMarkdown(name2) {
3411
- return name2.endsWith(MARKDOWN_EXTENSION);
3716
+ function isMarkdown(name) {
3717
+ return name.endsWith(MARKDOWN_EXTENSION);
3412
3718
  }
3413
- function markdownStem(name2) {
3414
- return name2.slice(0, -MARKDOWN_EXTENSION.length);
3719
+ function markdownStem(name) {
3720
+ return name.slice(0, -MARKDOWN_EXTENSION.length);
3415
3721
  }
3416
3722
  function shown(root, path) {
3417
3723
  return relative2(root, path) || ".";
@@ -3436,37 +3742,37 @@ function unreadableEntry(kind, root, path) {
3436
3742
  issues: [layoutIssue("unreadable-entry", `${shown(root, path)} cannot be read (a broken symlink, or a path stat refuses)`)]
3437
3743
  };
3438
3744
  }
3439
- function skillFileEntry(path, name2) {
3440
- return { kind: "skill", path, isFile: true, shape: "skill-file", name: name2, issues: [] };
3745
+ function skillFileEntry(path, name) {
3746
+ return { kind: "skill", path, isFile: true, shape: "skill-file", name, issues: [] };
3441
3747
  }
3442
- function flatGroupedEntry(root, path, name2) {
3748
+ function flatGroupedEntry(root, path, name) {
3443
3749
  return {
3444
3750
  kind: "skill",
3445
3751
  path,
3446
3752
  isFile: true,
3447
3753
  shape: "flat-grouped",
3448
- name: name2,
3449
- issues: [layoutIssue("flat-grouped-layout", `${shown(root, path)} is the flat grouped layout <dir>/<group>/<name>.md,` + ` which does not register; move it to <dir>/${name2}/${SKILL_FILE}`)]
3754
+ name,
3755
+ issues: [layoutIssue("flat-grouped-layout", `${shown(root, path)} is the flat grouped layout <dir>/<group>/<name>.md,` + ` which does not register; move it to <dir>/${name}/${SKILL_FILE2}`)]
3450
3756
  };
3451
3757
  }
3452
- function nestedGroupEntry(root, path, name2) {
3758
+ function nestedGroupEntry(root, path, name) {
3453
3759
  return {
3454
3760
  kind: "skill",
3455
3761
  path,
3456
3762
  isFile: true,
3457
3763
  shape: "nested-group",
3458
- name: name2,
3459
- issues: [layoutIssue("nested-group-layout", `${shown(root, path)} is the nested layout <dir>/<group>/<name>/${SKILL_FILE},` + ` which does not register; move it to <dir>/${name2}/${SKILL_FILE}`)]
3764
+ name,
3765
+ issues: [layoutIssue("nested-group-layout", `${shown(root, path)} is the nested layout <dir>/<group>/<name>/${SKILL_FILE2},` + ` which does not register; move it to <dir>/${name}/${SKILL_FILE2}`)]
3460
3766
  };
3461
3767
  }
3462
- function looseFileEntry(root, path, name2) {
3768
+ function looseFileEntry(root, path, name) {
3463
3769
  return {
3464
3770
  kind: "skill",
3465
3771
  path,
3466
3772
  isFile: true,
3467
3773
  shape: "loose-file",
3468
- name: name2,
3469
- issues: [layoutIssue("loose-file", `${shown(root, path)} sits directly under the skills directory, which registers` + ` only <dir>/<name>/${SKILL_FILE}; move it to <dir>/${name2}/${SKILL_FILE}`)]
3774
+ name,
3775
+ issues: [layoutIssue("loose-file", `${shown(root, path)} sits directly under the skills directory, which registers` + ` only <dir>/<name>/${SKILL_FILE2}; move it to <dir>/${name}/${SKILL_FILE2}`)]
3470
3776
  };
3471
3777
  }
3472
3778
  function noSkillFileEntry(root, dir) {
@@ -3476,26 +3782,26 @@ function noSkillFileEntry(root, dir) {
3476
3782
  isFile: false,
3477
3783
  shape: "no-skill-file",
3478
3784
  name: null,
3479
- issues: [layoutIssue("missing-skill-file", `${shown(root, dir)}/ holds no ${SKILL_FILE}, so it registers no skill`)]
3785
+ issues: [layoutIssue("missing-skill-file", `${shown(root, dir)}/ holds no ${SKILL_FILE2}, so it registers no skill`)]
3480
3786
  };
3481
3787
  }
3482
- function nestedInstinctEntry(root, path, name2) {
3788
+ function nestedInstinctEntry(root, path, name) {
3483
3789
  return {
3484
3790
  kind: "instinct",
3485
3791
  path,
3486
3792
  isFile: true,
3487
3793
  shape: "nested-instinct",
3488
- name: name2,
3489
- issues: [layoutIssue("nested-instinct-file", `${shown(root, path)} sits below the instincts directory, which is flat;` + ` move it to <dir>/${name2}${MARKDOWN_EXTENSION}`)]
3794
+ name,
3795
+ issues: [layoutIssue("nested-instinct-file", `${shown(root, path)} sits below the instincts directory, which is flat;` + ` move it to <dir>/${name}${MARKDOWN_EXTENSION}`)]
3490
3796
  };
3491
3797
  }
3492
- function scanGroupMember(root, dir, name2) {
3798
+ function scanGroupMember(root, dir, name) {
3493
3799
  const children = visibleNames(dir);
3494
3800
  if (children.length === 0)
3495
3801
  return [dotfileOnlyEntry("skill", root, dir)];
3496
- const skillPath = join13(dir, SKILL_FILE);
3497
- if (children.includes(SKILL_FILE) && entryKind(skillPath) === "file") {
3498
- return [nestedGroupEntry(root, skillPath, name2)];
3802
+ const skillPath = join13(dir, SKILL_FILE2);
3803
+ if (children.includes(SKILL_FILE2) && entryKind(skillPath) === "file") {
3804
+ return [nestedGroupEntry(root, skillPath, name)];
3499
3805
  }
3500
3806
  return [noSkillFileEntry(root, dir)];
3501
3807
  }
@@ -3519,31 +3825,31 @@ function scanSkillGroup(root, dir, children) {
3519
3825
  return [noSkillFileEntry(root, dir)];
3520
3826
  return entries;
3521
3827
  }
3522
- function scanSkillDirectory(root, dir, name2) {
3828
+ function scanSkillDirectory(root, dir, name) {
3523
3829
  const children = visibleNames(dir);
3524
3830
  if (children.length === 0)
3525
3831
  return [dotfileOnlyEntry("skill", root, dir)];
3526
- const skillPath = join13(dir, SKILL_FILE);
3527
- if (children.includes(SKILL_FILE) && entryKind(skillPath) === "file") {
3528
- return [skillFileEntry(skillPath, name2)];
3832
+ const skillPath = join13(dir, SKILL_FILE2);
3833
+ if (children.includes(SKILL_FILE2) && entryKind(skillPath) === "file") {
3834
+ return [skillFileEntry(skillPath, name)];
3529
3835
  }
3530
3836
  return scanSkillGroup(root, dir, children);
3531
3837
  }
3532
3838
  function scanSkillRoot(root) {
3533
3839
  const entries = [];
3534
- for (const name2 of visibleNames(root)) {
3535
- const path = join13(root, name2);
3840
+ for (const name of visibleNames(root)) {
3841
+ const path = join13(root, name);
3536
3842
  const found = entryKind(path);
3537
3843
  if (found === null) {
3538
3844
  entries.push(unreadableEntry("skill", root, path));
3539
3845
  continue;
3540
3846
  }
3541
3847
  if (found === "directory") {
3542
- entries.push(...scanSkillDirectory(root, path, name2));
3848
+ entries.push(...scanSkillDirectory(root, path, name));
3543
3849
  continue;
3544
3850
  }
3545
- if (isMarkdown(name2))
3546
- entries.push(looseFileEntry(root, path, markdownStem(name2)));
3851
+ if (isMarkdown(name))
3852
+ entries.push(looseFileEntry(root, path, markdownStem(name)));
3547
3853
  }
3548
3854
  return entries;
3549
3855
  }
@@ -3570,8 +3876,8 @@ function scanInstinctSubdirectory(root, dir) {
3570
3876
  }
3571
3877
  function scanInstinctRoot(root) {
3572
3878
  const entries = [];
3573
- for (const name2 of visibleNames(root)) {
3574
- const path = join13(root, name2);
3879
+ for (const name of visibleNames(root)) {
3880
+ const path = join13(root, name);
3575
3881
  const found = entryKind(path);
3576
3882
  if (found === null) {
3577
3883
  entries.push(unreadableEntry("instinct", root, path));
@@ -3581,14 +3887,14 @@ function scanInstinctRoot(root) {
3581
3887
  entries.push(...scanInstinctSubdirectory(root, path));
3582
3888
  continue;
3583
3889
  }
3584
- if (!isMarkdown(name2))
3890
+ if (!isMarkdown(name))
3585
3891
  continue;
3586
3892
  entries.push({
3587
3893
  kind: "instinct",
3588
3894
  path,
3589
3895
  isFile: true,
3590
3896
  shape: "instinct-file",
3591
- name: markdownStem(name2),
3897
+ name: markdownStem(name),
3592
3898
  issues: []
3593
3899
  });
3594
3900
  }
@@ -3608,9 +3914,9 @@ function scanLayout(root, kind) {
3608
3914
  function declaredNameIssue(entry, declared) {
3609
3915
  if (entry.name === null || declared === null || declared === entry.name)
3610
3916
  return null;
3611
- const field2 = entry.kind === "skill" ? "name" : "id";
3917
+ const field = entry.kind === "skill" ? "name" : "id";
3612
3918
  const source = entry.kind === "skill" ? "directory name" : "file name";
3613
- return layoutIssue("name-mismatch", `frontmatter ${field2} "${declared}" is not the ${source} "${entry.name}"`);
3919
+ return layoutIssue("name-mismatch", `frontmatter ${field} "${declared}" is not the ${source} "${entry.name}"`);
3614
3920
  }
3615
3921
 
3616
3922
  // src/schema/frontmatter.ts
@@ -3699,8 +4005,8 @@ function writeFrontmatter(document, data) {
3699
4005
  }
3700
4006
 
3701
4007
  // src/schema/instinct.ts
3702
- var INSTINCT_KINDS = FINDING_KINDS;
3703
- var INSTINCT_SIGNALS = FINDING_SIGNALS;
4008
+ var INSTINCT_KINDS = FINDING_KINDS2;
4009
+ var INSTINCT_SIGNALS = FINDING_SIGNALS2;
3704
4010
  var INSTINCT_DOMAINS = FINDING_DOMAINS;
3705
4011
  var INSTINCT_SCOPES = ["project", "user"];
3706
4012
  var INSTINCT_SOURCES = ["task-report", "loop-observed", "imported", "demoted"];
@@ -3730,8 +4036,8 @@ var INSTINCT_KEY_ORDER = [
3730
4036
  "created_at",
3731
4037
  "updated_at"
3732
4038
  ];
3733
- function issue(code, field2, message) {
3734
- return { code, field: field2, message };
4039
+ function issue(code, field, message) {
4040
+ return { code, field, message };
3735
4041
  }
3736
4042
  function typeName(value) {
3737
4043
  if (value === null)
@@ -3746,25 +4052,25 @@ function typeName(value) {
3746
4052
  return "a number";
3747
4053
  return `a ${typeof value}`;
3748
4054
  }
3749
- function requiredString(data, field2) {
3750
- const value = data[field2];
4055
+ function requiredString(data, field) {
4056
+ const value = data[field];
3751
4057
  if (value === undefined || value === null) {
3752
- return [issue("missing-field", field2, `${field2} is required and is absent`)];
4058
+ return [issue("missing-field", field, `${field} is required and is absent`)];
3753
4059
  }
3754
4060
  if (typeof value !== "string") {
3755
- return [issue("wrong-type", field2, `${field2} must be a string, not ${typeName(value)}`)];
4061
+ return [issue("wrong-type", field, `${field} must be a string, not ${typeName(value)}`)];
3756
4062
  }
3757
4063
  if (value.trim() === "") {
3758
- return [issue("missing-field", field2, `${field2} is required and is empty`)];
4064
+ return [issue("missing-field", field, `${field} is required and is empty`)];
3759
4065
  }
3760
4066
  return [];
3761
4067
  }
3762
- function requiredChoice(data, field2, allowed, code) {
3763
- const issues = requiredString(data, field2);
4068
+ function requiredChoice(data, field, allowed, code) {
4069
+ const issues = requiredString(data, field);
3764
4070
  if (issues.length > 0)
3765
4071
  return issues;
3766
- const value = data[field2];
3767
- return allowed.includes(value) ? [] : [issue(code, field2, `${field2} "${value}" is not one of ${allowed.join(", ")}`)];
4072
+ const value = data[field];
4073
+ return allowed.includes(value) ? [] : [issue(code, field, `${field} "${value}" is not one of ${allowed.join(", ")}`)];
3768
4074
  }
3769
4075
  function checkId(data) {
3770
4076
  const issues = requiredString(data, "id");
@@ -3800,11 +4106,11 @@ function checkSources(data) {
3800
4106
  return [issue("wrong-type", "sources", `sources must be a list, not ${typeName(value)}`)];
3801
4107
  }
3802
4108
  return value.flatMap((entry, index) => {
3803
- const field2 = `sources[${index}]`;
4109
+ const field = `sources[${index}]`;
3804
4110
  if (typeof entry !== "string") {
3805
- return [issue("wrong-type", field2, `sources entries must be strings, and this one is ${typeName(entry)}`)];
4111
+ return [issue("wrong-type", field, `sources entries must be strings, and this one is ${typeName(entry)}`)];
3806
4112
  }
3807
- return entry.trim() === "" ? [issue("wrong-type", field2, "sources entries must name a source, and this one is blank")] : [];
4113
+ return entry.trim() === "" ? [issue("wrong-type", field, "sources entries must name a source, and this one is blank")] : [];
3808
4114
  });
3809
4115
  }
3810
4116
  function checkPromotedTo(data) {
@@ -3833,26 +4139,26 @@ function checkProjectId(data) {
3833
4139
  }
3834
4140
  return PROJECT_ID_PATTERN.test(value) ? [] : [issue("invalid-project-id", "project_id", `project_id "${value}" is not ${PROJECT_ID_LENGTH} lowercase hex characters`)];
3835
4141
  }
3836
- function checkTimestamp(data, field2) {
3837
- const issues = requiredString(data, field2);
4142
+ function checkTimestamp(data, field) {
4143
+ const issues = requiredString(data, field);
3838
4144
  if (issues.length > 0)
3839
4145
  return issues;
3840
- const value = data[field2];
3841
- return TIMESTAMP_PATTERN.test(value) && !Number.isNaN(Date.parse(value)) ? [] : [issue("invalid-timestamp", field2, `${field2} "${value}" is not an ISO 8601 instant such as 2026-09-11T10:00:00Z`)];
4146
+ const value = data[field];
4147
+ return TIMESTAMP_PATTERN.test(value) && !Number.isNaN(Date.parse(value)) ? [] : [issue("invalid-timestamp", field, `${field} "${value}" is not an ISO 8601 instant such as 2026-09-11T10:00:00Z`)];
3842
4148
  }
3843
4149
  function isScalar(value) {
3844
4150
  return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
3845
4151
  }
3846
4152
  function checkEvidenceEntry(entry, index) {
3847
- const field2 = `evidence[${index}]`;
4153
+ const field = `evidence[${index}]`;
3848
4154
  if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
3849
- return [issue("wrong-type", field2, `evidence entries must be mappings, and this one is ${typeName(entry)}`)];
4155
+ return [issue("wrong-type", field, `evidence entries must be mappings, and this one is ${typeName(entry)}`)];
3850
4156
  }
3851
4157
  const entries = Object.entries(entry);
3852
4158
  if (entries.length === 0) {
3853
- return [issue("wrong-type", field2, "evidence entries must say something, and this one is empty")];
4159
+ return [issue("wrong-type", field, "evidence entries must say something, and this one is empty")];
3854
4160
  }
3855
- return entries.flatMap(([key, value]) => isScalar(value) ? [] : [issue("wrong-type", `${field2}.${key}`, `evidence values must be text, numbers or booleans, and this one is ${typeName(value)}`)]);
4161
+ return entries.flatMap(([key, value]) => isScalar(value) ? [] : [issue("wrong-type", `${field}.${key}`, `evidence values must be text, numbers or booleans, and this one is ${typeName(value)}`)]);
3856
4162
  }
3857
4163
  function checkEvidence(data) {
3858
4164
  const value = data["evidence"];
@@ -3965,7 +4271,7 @@ function buildInstinct(data, body) {
3965
4271
  updatedAt: data["updated_at"],
3966
4272
  action,
3967
4273
  cause: sectionText(body, CAUSE_HEADING) ?? "",
3968
- actionHash: actionHash(action)
4274
+ actionHash: actionHash2(action)
3969
4275
  };
3970
4276
  }
3971
4277
  function instinctFrontmatter(instinct) {
@@ -4012,11 +4318,11 @@ function writeInstinct(instinct, newline = `
4012
4318
  }
4013
4319
 
4014
4320
  // src/commands/instinct/instinct-records.ts
4015
- function isRecordFile(name2) {
4016
- return !name2.startsWith(".") && name2.endsWith(MARKDOWN_EXTENSION) && name2 !== MARKDOWN_EXTENSION;
4321
+ function isRecordFile(name) {
4322
+ return !name.startsWith(".") && name.endsWith(MARKDOWN_EXTENSION) && name !== MARKDOWN_EXTENSION;
4017
4323
  }
4018
- function recordId(name2) {
4019
- return name2.slice(0, -MARKDOWN_EXTENSION.length);
4324
+ function recordId(name) {
4325
+ return name.slice(0, -MARKDOWN_EXTENSION.length);
4020
4326
  }
4021
4327
  function unreadableIssue(message) {
4022
4328
  return { code: "missing-frontmatter", field: "file", message: `the file could not be read: ${message}` };
@@ -4024,7 +4330,7 @@ function unreadableIssue(message) {
4024
4330
  function readRecord(path, scope, id) {
4025
4331
  let text;
4026
4332
  try {
4027
- text = readFileSync8(path, "utf8");
4333
+ text = readFileSync9(path, "utf8");
4028
4334
  } catch (error) {
4029
4335
  const message = error instanceof Error ? error.message : String(error);
4030
4336
  return { scope, path, id, instinct: null, issues: [unreadableIssue(message)] };
@@ -4040,7 +4346,7 @@ function isFile2(path) {
4040
4346
  }
4041
4347
  }
4042
4348
  function recordFiles(dir) {
4043
- return readdirSync4(dir).filter((name2) => isRecordFile(name2) && isFile2(join14(dir, name2))).sort((left, right) => left.localeCompare(right));
4349
+ return readdirSync4(dir).filter((name) => isRecordFile(name) && isFile2(join14(dir, name))).sort((left, right) => left.localeCompare(right));
4044
4350
  }
4045
4351
  function readScope(scope, dir) {
4046
4352
  if (!tierExists(dir))
@@ -4049,7 +4355,7 @@ function readScope(scope, dir) {
4049
4355
  scope,
4050
4356
  dir,
4051
4357
  exists: true,
4052
- records: recordFiles(dir).map((name2) => readRecord(join14(dir, name2), scope, recordId(name2)))
4358
+ records: recordFiles(dir).map((name) => readRecord(join14(dir, name), scope, recordId(name)))
4053
4359
  };
4054
4360
  }
4055
4361
  function readScopes(seams) {
@@ -4061,9 +4367,9 @@ function allRecords(listings) {
4061
4367
  function findRecords(listings, id) {
4062
4368
  return allRecords(listings).filter((entry) => entry.id === id);
4063
4369
  }
4064
- function instinctProject(context, name2) {
4370
+ function instinctProject(context, name) {
4065
4371
  if (context.project === null)
4066
- throw new Error(`${name2} runs inside a project, and was handed none`);
4372
+ throw new Error(`${name} runs inside a project, and was handed none`);
4067
4373
  return context.project;
4068
4374
  }
4069
4375
 
@@ -4100,17 +4406,17 @@ function toHeldRecord(instinct) {
4100
4406
  function toHeldRecords(held) {
4101
4407
  const actions = new Map;
4102
4408
  for (const instinct of held) {
4103
- const key = triggerKey(instinct.trigger);
4409
+ const key = triggerKey2(instinct.trigger);
4104
4410
  actions.set(key, (actions.get(key) ?? new Set).add(instinct.actionHash));
4105
4411
  }
4106
4412
  return held.map((instinct) => {
4107
4413
  const record = toHeldRecord(instinct);
4108
- return actions.get(triggerKey(instinct.trigger)).size > 1 ? { ...record, status: "flagged" } : record;
4414
+ return actions.get(triggerKey2(instinct.trigger)).size > 1 ? { ...record, status: "flagged" } : record;
4109
4415
  });
4110
4416
  }
4111
4417
  function earliestHeldMember(record, held) {
4112
- const key = triggerKey(record.trigger);
4113
- const members = held.filter((instinct) => instinct.actionHash === record.action_hash && triggerKey(instinct.trigger) === key);
4418
+ const key = triggerKey2(record.trigger);
4419
+ const members = held.filter((instinct) => instinct.actionHash === record.action_hash && triggerKey2(instinct.trigger) === key);
4114
4420
  return [...members].sort(byAge)[0] ?? null;
4115
4421
  }
4116
4422
  function toHeldInstinct(record, held, fallback) {
@@ -4137,7 +4443,7 @@ function toHeldInstinct(record, held, fallback) {
4137
4443
  updatedAt: record.updated_at,
4138
4444
  action: record.action,
4139
4445
  cause: description.cause,
4140
- actionHash: actionHash(record.action)
4446
+ actionHash: actionHash2(record.action)
4141
4447
  };
4142
4448
  }
4143
4449
 
@@ -4219,7 +4525,7 @@ function recordProblem(record, index) {
4219
4525
  if (problem !== null)
4220
4526
  return problem;
4221
4527
  const { action, action_hash: hash, description } = record;
4222
- if (hash !== actionHash(action)) {
4528
+ if (hash !== actionHash2(action)) {
4223
4529
  return `action_hash is ${describeValue(hash)} in ${at}, expected the sha256 of its trimmed, lower-cased action`;
4224
4530
  }
4225
4531
  return description === undefined ? null : fieldsProblem(description, DESCRIPTION_CHECKS, `${at}.description`);
@@ -4231,7 +4537,7 @@ function payloadProblem(payload) {
4231
4537
  const { instincts } = payload;
4232
4538
  return instincts.map(recordProblem).find((found) => found !== null) ?? null;
4233
4539
  }
4234
- function flagProblem(value) {
4540
+ function flagProblem2(value) {
4235
4541
  return fieldsProblem(value, FLAG_CHECKS, "the flag");
4236
4542
  }
4237
4543
  function copyInstinct(record) {
@@ -4308,9 +4614,9 @@ function unflagged(records, flagged) {
4308
4614
  return records.filter((record) => !flagged.has(record.id));
4309
4615
  }
4310
4616
  function userAdditions(userBlessed, projectHeld, flagged) {
4311
- const heldTriggers = new Set(projectHeld.map((record) => triggerKey(record.trigger)));
4617
+ const heldTriggers = new Set(projectHeld.map((record) => triggerKey2(record.trigger)));
4312
4618
  const heldIds = new Set(projectHeld.map((record) => record.id));
4313
- return unflagged(userBlessed, flagged).filter((record) => !heldTriggers.has(triggerKey(record.trigger)) && !heldIds.has(record.id));
4619
+ return unflagged(userBlessed, flagged).filter((record) => !heldTriggers.has(triggerKey2(record.trigger)) && !heldIds.has(record.id));
4314
4620
  }
4315
4621
  function byAge2(left, right) {
4316
4622
  if (left.created_at !== right.created_at) {
@@ -4321,8 +4627,8 @@ function byAge2(left, right) {
4321
4627
  return left.id < right.id ? -1 : 1;
4322
4628
  }
4323
4629
  function payloadDescription(record, described) {
4324
- const key = triggerKey(record.trigger);
4325
- const members = described.filter((candidate) => candidate.description !== undefined && candidate.action_hash === record.action_hash && triggerKey(candidate.trigger) === key);
4630
+ const key = triggerKey2(record.trigger);
4631
+ const members = described.filter((candidate) => candidate.description !== undefined && candidate.action_hash === record.action_hash && triggerKey2(candidate.trigger) === key);
4326
4632
  return [...members].sort(byAge2)[0]?.description;
4327
4633
  }
4328
4634
  function producedRecords(result) {
@@ -4348,35 +4654,35 @@ function heldChanges(dir, held, result, described) {
4348
4654
  throw new Error(`${PUSH_REFUSAL}: ${file} has no held member and no payload description to be written with`);
4349
4655
  }
4350
4656
  const text = writeInstinct(instinct);
4351
- const [issue2] = parseInstinct(text).issues;
4352
- if (issue2 !== undefined) {
4353
- throw new Error(`${PUSH_REFUSAL}: ${file} would not read back: ${issue2.field}: ${issue2.message}`);
4657
+ const [issue] = parseInstinct(text).issues;
4658
+ if (issue !== undefined) {
4659
+ throw new Error(`${PUSH_REFUSAL}: ${file} would not read back: ${issue.field}: ${issue.message}`);
4354
4660
  }
4355
4661
  const path = join15(dir, file);
4356
4662
  if (held.unreadable.has(path)) {
4357
4663
  throw new Error(`${PUSH_REFUSAL}: it would overwrite ${path}, which could not be read`);
4358
4664
  }
4359
4665
  const before = heldAt.get(path);
4360
- if (before !== undefined && triggerKey(before.trigger) !== triggerKey(record.trigger)) {
4666
+ if (before !== undefined && triggerKey2(before.trigger) !== triggerKey2(record.trigger)) {
4361
4667
  throw new Error(`${PUSH_REFUSAL}: it would overwrite ${path}, which holds another trigger`);
4362
4668
  }
4363
4669
  kept.add(path);
4364
4670
  if (before === undefined || writeInstinct(before) !== text)
4365
4671
  writes.push({ path, text });
4366
4672
  }
4367
- const touched = new Set(result.decisions.map((decision) => triggerKey(decision.incoming.trigger)));
4368
- const removals = held.files.filter((file) => touched.has(triggerKey(file.instinct.trigger)) && !kept.has(file.path)).map((file) => file.path);
4673
+ const touched = new Set(result.decisions.map((decision) => triggerKey2(decision.incoming.trigger)));
4674
+ const removals = held.files.filter((file) => touched.has(triggerKey2(file.instinct.trigger)) && !kept.has(file.path)).map((file) => file.path);
4369
4675
  return { writes, removals };
4370
4676
  }
4371
4677
  function pushLogLines(sourceId, described, result) {
4372
4678
  return result.decisions.map((decision, index) => {
4373
- const key = triggerKey(decision.incoming.trigger);
4679
+ const key = triggerKey2(decision.incoming.trigger);
4374
4680
  const line = {
4375
4681
  source_id: sourceId,
4376
4682
  rule: decision.rule,
4377
4683
  incoming: loggedIncoming(described[index]),
4378
4684
  produced: decision.produced.map((record) => record.id),
4379
- discarded: result.discarded.filter((record) => triggerKey(record.trigger) === key).map((record) => record.id)
4685
+ discarded: result.discarded.filter((record) => triggerKey2(record.trigger) === key).map((record) => record.id)
4380
4686
  };
4381
4687
  return JSON.stringify(line);
4382
4688
  });
@@ -4401,7 +4707,7 @@ function createLocalLearning(options) {
4401
4707
  for (const entry of records) {
4402
4708
  if (entry.instinct === null) {
4403
4709
  unreadable.add(entry.path);
4404
- const problems = entry.issues.map((issue2) => `${issue2.field}: ${issue2.message}`).join("; ");
4710
+ const problems = entry.issues.map((issue) => `${issue.field}: ${issue.message}`).join("; ");
4405
4711
  warn(`${PREFIX}: ${entry.path} is not a held instinct, so it was skipped: ${problems}`);
4406
4712
  } else {
4407
4713
  files.push({ path: entry.path, instinct: entry.instinct });
@@ -4418,7 +4724,7 @@ function createLocalLearning(options) {
4418
4724
  async function flaggedIds() {
4419
4725
  const lines = numberedLines(await readIfPresent(flagsPath));
4420
4726
  return new Set(lines.map(([number, line]) => {
4421
- const reading = readLine(line, flagProblem);
4727
+ const reading = readLine(line, flagProblem2);
4422
4728
  if (reading.ok)
4423
4729
  return reading.value.id;
4424
4730
  throw new Error(`${PREFIX}: line ${number} of ${flagsPath} is not a flag,` + ` and a bundle skipping it could hold an instinct it flags: ${reading.problem}`);
@@ -4432,7 +4738,7 @@ function createLocalLearning(options) {
4432
4738
  }
4433
4739
  const described = payload.instincts;
4434
4740
  const held = heldSet();
4435
- const result = merge(toHeldRecords(held.files.map((file) => file.instinct)), { source_id: payload.source_id, instincts: described.map(copyInstinct) }, now());
4741
+ const result = merge2(toHeldRecords(held.files.map((file) => file.instinct)), { source_id: payload.source_id, instincts: described.map(copyInstinct) }, now());
4436
4742
  const changes = heldChanges(instinctsDir, held, result, described);
4437
4743
  const lines = pushLogLines(payload.source_id, described, result);
4438
4744
  if (lines.length > 0) {
@@ -4450,13 +4756,13 @@ function createLocalLearning(options) {
4450
4756
  pullBlessed: async () => {
4451
4757
  const flagged = await flaggedIds();
4452
4758
  const projectHeld = heldRecords(heldSet());
4453
- const project = bless(unflagged(projectHeld, flagged), { minConfidence }).instincts;
4454
- const user = bless(heldRecords(readHeld("user", userDir)), { minConfidence }).instincts;
4759
+ const project = bless2(unflagged(projectHeld, flagged), { minConfidence }).instincts;
4760
+ const user = bless2(heldRecords(readHeld("user", userDir)), { minConfidence }).instincts;
4455
4761
  return { version: now(), instincts: [...project, ...userAdditions(user, projectHeld, flagged)] };
4456
4762
  },
4457
4763
  flag: async (id, reason) => {
4458
4764
  const flag = { id, reason, flagged_at: now() };
4459
- const problem = flagProblem(flag);
4765
+ const problem = flagProblem2(flag);
4460
4766
  if (problem !== null) {
4461
4767
  throw new TypeError(`${PREFIX}: refused to write an invalid flag: ${problem}`);
4462
4768
  }
@@ -4576,8 +4882,8 @@ function describeValue3(value) {
4576
4882
  function messageOf2(error) {
4577
4883
  return error instanceof Error ? error.message : String(error);
4578
4884
  }
4579
- function counted(count2, noun) {
4580
- return count2 === 1 ? `1 ${noun}` : `${String(count2)} ${noun}s`;
4885
+ function counted(count, noun) {
4886
+ return count === 1 ? `1 ${noun}` : `${String(count)} ${noun}s`;
4581
4887
  }
4582
4888
  function valueAt(mapping, key) {
4583
4889
  return Object.hasOwn(mapping, key) ? mapping[key] ?? null : null;
@@ -4595,39 +4901,39 @@ function verdictOf(value) {
4595
4901
  const word = spelled.replace(VERDICT_BREAK, "-");
4596
4902
  return SPEC_REVIEW_VERDICTS.includes(word) ? word : null;
4597
4903
  }
4598
- function issueAt(field2, text) {
4599
- return { field: field2, text };
4904
+ function issueAt(field, text) {
4905
+ return { field, text };
4600
4906
  }
4601
- function readBlocking(item, field2, issues) {
4907
+ function readBlocking(item, field, issues) {
4602
4908
  const value = valueAt(item, "blocking");
4603
4909
  if (typeof value === "boolean")
4604
4910
  return value;
4605
- const text = `${field2}.blocking is ${describeValue3(value)}, not true or false; ` + "the gap is read as blocking";
4606
- issues.push(issueAt(`${field2}.blocking`, text));
4911
+ const text = `${field}.blocking is ${describeValue3(value)}, not true or false; ` + "the gap is read as blocking";
4912
+ issues.push(issueAt(`${field}.blocking`, text));
4607
4913
  return true;
4608
4914
  }
4609
- function readGap(item, field2, issues) {
4915
+ function readGap(item, field, issues) {
4610
4916
  if (!isMapping2(item)) {
4611
- const text = `${field2} is ${describeValue3(item)}, not a mapping of heading and what; dropped`;
4612
- issues.push(issueAt(field2, text));
4917
+ const text = `${field} is ${describeValue3(item)}, not a mapping of heading and what; dropped`;
4918
+ issues.push(issueAt(field, text));
4613
4919
  return null;
4614
4920
  }
4615
4921
  const what = stringAt(item, "what");
4616
4922
  if (what === null) {
4617
- const text = `${field2}.what is ${describeValue3(valueAt(item, "what"))}, ` + "not a sentence; the gap is dropped";
4618
- issues.push(issueAt(`${field2}.what`, text));
4923
+ const text = `${field}.what is ${describeValue3(valueAt(item, "what"))}, ` + "not a sentence; the gap is dropped";
4924
+ issues.push(issueAt(`${field}.what`, text));
4619
4925
  return null;
4620
4926
  }
4621
4927
  const heading = stringAt(item, "heading");
4622
4928
  if (heading === null) {
4623
- const text = `${field2}.heading is ${describeValue3(valueAt(item, "heading"))}, ` + `not a heading; the gap is filed under ${REVIEW_HEADING}`;
4624
- issues.push(issueAt(`${field2}.heading`, text));
4929
+ const text = `${field}.heading is ${describeValue3(valueAt(item, "heading"))}, ` + `not a heading; the gap is filed under ${REVIEW_HEADING}`;
4930
+ issues.push(issueAt(`${field}.heading`, text));
4625
4931
  }
4626
- const blocking = readBlocking(item, field2, issues);
4932
+ const blocking = readBlocking(item, field, issues);
4627
4933
  const assumption = stringAt(item, "assumption");
4628
4934
  if (!blocking && assumption === null) {
4629
- const text = `${field2}.assumption is ${describeValue3(valueAt(item, "assumption"))}, ` + "not what a non-blocking gap would be planned under; the gap is read as blocking";
4630
- issues.push(issueAt(`${field2}.assumption`, text));
4935
+ const text = `${field}.assumption is ${describeValue3(valueAt(item, "assumption"))}, ` + "not what a non-blocking gap would be planned under; the gap is read as blocking";
4936
+ issues.push(issueAt(`${field}.assumption`, text));
4631
4937
  return { heading: heading ?? REVIEW_HEADING, what, blocking: true, assumption: null };
4632
4938
  }
4633
4939
  return { heading: heading ?? REVIEW_HEADING, what, blocking, assumption };
@@ -4676,7 +4982,7 @@ function judged(verdict, gaps, block, issues) {
4676
4982
  };
4677
4983
  }
4678
4984
  function parseSpecReview(output) {
4679
- const reviews = readRafaBlocks(output).filter((found) => found.kind === SPEC_REVIEW_KIND);
4985
+ const reviews = readRafaBlocks2(output).filter((found) => found.kind === SPEC_REVIEW_KIND);
4680
4986
  const block = reviews.at(-1);
4681
4987
  if (block === undefined) {
4682
4988
  return unreadable("absent", null, "the session output holds no rafa:spec-review block");
@@ -4725,35 +5031,6 @@ function sessionSpawnEnv(base, binDir = bundledBinDirectory()) {
4725
5031
  }
4726
5032
 
4727
5033
  // src/utils/claude.ts
4728
- async function getClaudeUsagePercent() {
4729
- const envPct = process.env["CLAUDE_USAGE_PERCENT"];
4730
- if (envPct !== undefined) {
4731
- const pct = Number(envPct);
4732
- return Number.isFinite(pct) ? Math.max(0, Math.min(100, pct)) : null;
4733
- }
4734
- return null;
4735
- }
4736
- async function checkUsage(context) {
4737
- const pct = await getClaudeUsagePercent();
4738
- if (pct === null)
4739
- return false;
4740
- if (context === "task" && pct >= 90) {
4741
- activeOutput().warn(`
4742
- Claude usage at ${pct.toFixed(0)}% (>=90%). Pausing after current task to avoid hitting the limit.`);
4743
- return true;
4744
- }
4745
- if (pct >= 80) {
4746
- activeOutput().warn(`
4747
- Claude usage at ${pct.toFixed(0)}% (>=80%). Monitor closely \u2014 tasks may be interrupted.`);
4748
- } else if (context === "issue" && pct >= 70) {
4749
- activeOutput().warn(`
4750
- Claude usage at ${pct.toFixed(0)}% (>=70%). Consider whether to start the next issue.`);
4751
- } else {
4752
- activeOutput().info(`
4753
- Claude usage: ${pct.toFixed(0)}%`);
4754
- }
4755
- return false;
4756
- }
4757
5034
  var CLAUDE_BIN = "claude";
4758
5035
  var CLAUDE_BASE_ARGS = [
4759
5036
  "-p",
@@ -4774,16 +5051,16 @@ class UndeclaredSpendError extends Error {
4774
5051
  name = "UndeclaredSpendError";
4775
5052
  }
4776
5053
  function carriesFlag(flags, flag) {
4777
- const name2 = flag.replace(/^--/, "");
4778
- const value = flags[name2];
5054
+ const name = flag.replace(/^--/, "");
5055
+ const value = flags[name];
4779
5056
  if (value !== undefined && value !== false)
4780
5057
  return true;
4781
- return name2.startsWith("no-") && flags[name2.slice(3)] === false;
5058
+ return name.startsWith("no-") && flags[name.slice(3)] === false;
4782
5059
  }
4783
- function spendRefusal(running2) {
4784
- if (running2 === null)
5060
+ function spendRefusal(running) {
5061
+ if (running === null)
4785
5062
  return null;
4786
- const { command, flags } = running2;
5063
+ const { command, flags } = running;
4787
5064
  const spend = command.spends;
4788
5065
  const named = `rafa ${commandSpelling(command)}`;
4789
5066
  const remedy = "declare spends on the command to cover this run";
@@ -5028,8 +5305,8 @@ async function withDeadline(work, timeoutMs) {
5028
5305
  if (timeoutMs === undefined)
5029
5306
  return work;
5030
5307
  let timer;
5031
- const deadline = new Promise((resolve7) => {
5032
- timer = setTimeout(() => resolve7(TIMED_OUT), timeoutMs);
5308
+ const deadline = new Promise((resolve) => {
5309
+ timer = setTimeout(() => resolve(TIMED_OUT), timeoutMs);
5033
5310
  });
5034
5311
  try {
5035
5312
  return await Promise.race([work, deadline]);
@@ -5056,8 +5333,8 @@ function isRepoName(value) {
5056
5333
  function isLabelPart(value) {
5057
5334
  return typeof value === "string" && !value.includes(",");
5058
5335
  }
5059
- function optionalFlag(name2, value) {
5060
- return value === undefined ? [] : [name2, value];
5336
+ function optionalFlag(name, value) {
5337
+ return value === undefined ? [] : [name, value];
5061
5338
  }
5062
5339
  function detailOf(result) {
5063
5340
  return result.stderr.trim() || result.stdout.trim() || "it exited non-zero and wrote nothing";
@@ -5120,7 +5397,7 @@ function labelNames(value) {
5120
5397
  if (!Array.isArray(value))
5121
5398
  return null;
5122
5399
  const names = value.map((label) => isMapping(label) && typeof label["name"] === "string" ? label["name"] : null);
5123
- return names.every((name2) => name2 !== null) ? names : null;
5400
+ return names.every((name) => name !== null) ? names : null;
5124
5401
  }
5125
5402
  function viewProblem(payload, number) {
5126
5403
  if (!isMapping(payload))
@@ -5178,13 +5455,13 @@ function listedIssues(stdout) {
5178
5455
  }
5179
5456
  function listedOpenIssues(stdout) {
5180
5457
  return listedRows(stdout).map((row, index) => {
5181
- const listed2 = listedRow(row, index);
5458
+ const listed = listedRow(row, index);
5182
5459
  const { title, body } = row;
5183
5460
  if (typeof title !== "string")
5184
5461
  throw rowRefusal(index, `with title ${describeValue(title)}, expected a string`);
5185
5462
  if (typeof body !== "string")
5186
5463
  throw rowRefusal(index, `with body ${describeValue(body)}, expected a string`);
5187
- return { ...listed2, title, body };
5464
+ return { ...listed, title, body };
5188
5465
  });
5189
5466
  }
5190
5467
  function refOfRow(row) {
@@ -5242,9 +5519,9 @@ function createGithubTracker(options) {
5242
5519
  return result.stdout;
5243
5520
  }
5244
5521
  async function ensureLabels(names) {
5245
- const missing = [...new Set(names)].filter((name2) => !knownLabels.has(name2));
5246
- for (const name2 of missing) {
5247
- await run(["label", "create", name2, "--force"], `gh label create ${describeValue(name2)}`);
5522
+ const missing = [...new Set(names)].filter((name) => !knownLabels.has(name));
5523
+ for (const name of missing) {
5524
+ await run(["label", "create", name, "--force"], `gh label create ${describeValue(name)}`);
5248
5525
  }
5249
5526
  knownLabels = new Set([...knownLabels, ...missing]);
5250
5527
  }
@@ -5423,8 +5700,8 @@ function parseIssueNumber(text) {
5423
5700
  const number = Number(text);
5424
5701
  return Number.isSafeInteger(number) ? number : null;
5425
5702
  }
5426
- function issueNumberOfFile(name2) {
5427
- return name2.endsWith(ISSUE_EXTENSION) ? parseIssueNumber(name2.slice(0, -ISSUE_EXTENSION.length)) : null;
5703
+ function issueNumberOfFile(name) {
5704
+ return name.endsWith(ISSUE_EXTENSION) ? parseIssueNumber(name.slice(0, -ISSUE_EXTENSION.length)) : null;
5428
5705
  }
5429
5706
  function issuePath(issuesDir, number) {
5430
5707
  return join16(issuesDir, `${number}${ISSUE_EXTENSION}`);
@@ -5629,7 +5906,7 @@ function createLocalTracker(options) {
5629
5906
 
5630
5907
  // src/adapters/registry.ts
5631
5908
  var REFUSAL3 = "adapter registry";
5632
- var PORT_VERSIONS = Object.freeze({
5909
+ var PORT_VERSIONS2 = Object.freeze({
5633
5910
  tracker: 1,
5634
5911
  store: 1,
5635
5912
  learning: 1,
@@ -5637,7 +5914,7 @@ var PORT_VERSIONS = Object.freeze({
5637
5914
  planner: 1,
5638
5915
  sync: 1
5639
5916
  });
5640
- var SERVED_VERSIONS = new Map(Object.entries(PORT_VERSIONS));
5917
+ var SERVED_VERSIONS = new Map(Object.entries(PORT_VERSIONS2));
5641
5918
  var PORT_TYPE_LIST = [...SERVED_VERSIONS.keys()].join(", ");
5642
5919
  function checkPortType(port) {
5643
5920
  if (!SERVED_VERSIONS.has(port)) {
@@ -5677,11 +5954,11 @@ function indexByPort(adapters) {
5677
5954
  sync: only("sync")
5678
5955
  };
5679
5956
  }
5680
- function createAdapterRegistry(adapters = []) {
5957
+ function createAdapterRegistry2(adapters = []) {
5681
5958
  const held = adapters.reduce((accepted, adapter) => [...accepted, accept(adapter, accepted)], []);
5682
5959
  const byPort = indexByPort(held);
5683
5960
  const registry = {
5684
- register: (adapter) => createAdapterRegistry([...held, adapter]),
5961
+ register: (adapter) => createAdapterRegistry2([...held, adapter]),
5685
5962
  find: (port, kind) => SERVED_VERSIONS.has(port) ? byPort[port].get(kind) : undefined,
5686
5963
  resolve: (port, kind) => {
5687
5964
  checkPortType(port);
@@ -5689,8 +5966,8 @@ function createAdapterRegistry(adapters = []) {
5689
5966
  if (adapter !== undefined)
5690
5967
  return adapter;
5691
5968
  const registered = [...byPort[port].keys()];
5692
- const listed2 = registered.length === 0 ? "none" : registered.join(", ");
5693
- throw new Error(`${REFUSAL3}: no ${port} adapter is registered as ${describeValue(kind)};` + ` registered: ${listed2}`);
5969
+ const listed = registered.length === 0 ? "none" : registered.join(", ");
5970
+ throw new Error(`${REFUSAL3}: no ${port} adapter is registered as ${describeValue(kind)};` + ` registered: ${listed}`);
5694
5971
  },
5695
5972
  kinds: (port) => {
5696
5973
  checkPortType(port);
@@ -5700,38 +5977,38 @@ function createAdapterRegistry(adapters = []) {
5700
5977
  return Object.freeze(registry);
5701
5978
  }
5702
5979
  var STORE_OPENERS = {
5703
- sqlite: openSqliteStore,
5704
- ndjson: openNdjsonStore
5980
+ sqlite: openSqliteStore2,
5981
+ ndjson: openNdjsonStore2
5705
5982
  };
5706
5983
  var CORE_ADAPTERS = [
5707
- ...STORE_BACKENDS.map((backend) => ({
5984
+ ...STORE_BACKENDS2.map((backend) => ({
5708
5985
  port: "store",
5709
5986
  kind: backend,
5710
- portVersion: PORT_VERSIONS.store,
5987
+ portVersion: PORT_VERSIONS2.store,
5711
5988
  create: ({ repoRoot }) => STORE_OPENERS[backend](repoRoot)
5712
5989
  })),
5713
5990
  {
5714
5991
  port: "output",
5715
5992
  kind: "text",
5716
- portVersion: PORT_VERSIONS.output,
5993
+ portVersion: PORT_VERSIONS2.output,
5717
5994
  create: ({ stream = process.stdout, verbosity = 0 }) => createTextOutput({ verbosity, stream })
5718
5995
  },
5719
5996
  {
5720
5997
  port: "output",
5721
5998
  kind: "json",
5722
- portVersion: PORT_VERSIONS.output,
5999
+ portVersion: PORT_VERSIONS2.output,
5723
6000
  create: ({ stream = process.stdout }) => createJsonOutput({ stream })
5724
6001
  },
5725
6002
  {
5726
6003
  port: "output",
5727
6004
  kind: "events",
5728
- portVersion: PORT_VERSIONS.output,
6005
+ portVersion: PORT_VERSIONS2.output,
5729
6006
  create: ({ stream = process.stdout }) => createEventsOutput({ stream })
5730
6007
  },
5731
6008
  {
5732
6009
  port: "tracker",
5733
6010
  kind: "local",
5734
- portVersion: PORT_VERSIONS.tracker,
6011
+ portVersion: PORT_VERSIONS2.tracker,
5735
6012
  create: ({ repoRoot, fallbackReason = null }) => createLocalTracker({
5736
6013
  issuesDir: localIssuesDir(repoRoot),
5737
6014
  fallbackReason
@@ -5740,17 +6017,17 @@ var CORE_ADAPTERS = [
5740
6017
  {
5741
6018
  port: "tracker",
5742
6019
  kind: "github",
5743
- portVersion: PORT_VERSIONS.tracker,
6020
+ portVersion: PORT_VERSIONS2.tracker,
5744
6021
  create: ({ repoRoot, gh }) => createGithubTracker({ gh: gh ?? createGhRunner({ cwd: repoRoot }) })
5745
6022
  },
5746
6023
  {
5747
6024
  port: "learning",
5748
6025
  kind: "local",
5749
- portVersion: PORT_VERSIONS.learning,
6026
+ portVersion: PORT_VERSIONS2.learning,
5750
6027
  create: ({
5751
6028
  repoRoot,
5752
6029
  home = homedir(),
5753
- learningBlessMinConfidence = CONFIG_DEFAULTS.learningBlessMinConfidence
6030
+ learningBlessMinConfidence = CONFIG_DEFAULTS2.learningBlessMinConfidence
5754
6031
  }) => createLocalLearning({
5755
6032
  instinctsDir: localInstinctsDir(repoRoot),
5756
6033
  home,
@@ -5760,7 +6037,7 @@ var CORE_ADAPTERS = [
5760
6037
  {
5761
6038
  port: "planner",
5762
6039
  kind: "claude",
5763
- portVersion: PORT_VERSIONS.planner,
6040
+ portVersion: PORT_VERSIONS2.planner,
5764
6041
  create: ({ repoRoot, settingSources, planPrompt, planDir, claude }) => {
5765
6042
  if (!Array.isArray(settingSources)) {
5766
6043
  throw new TypeError(`${REFUSAL3}: planner/claude has settingSources ${describeValue(settingSources)} in its context,` + " expected a list of setting sources");
@@ -5777,26 +6054,26 @@ var CORE_ADAPTERS = [
5777
6054
  {
5778
6055
  port: "sync",
5779
6056
  kind: "local",
5780
- portVersion: PORT_VERSIONS.sync,
6057
+ portVersion: PORT_VERSIONS2.sync,
5781
6058
  create: () => createLocalSync()
5782
6059
  },
5783
6060
  {
5784
6061
  port: "sync",
5785
6062
  kind: "file",
5786
- portVersion: PORT_VERSIONS.sync,
6063
+ portVersion: PORT_VERSIONS2.sync,
5787
6064
  create: ({ repoRoot, store }) => {
5788
- if (!STORE_BACKENDS.includes(store)) {
5789
- throw new TypeError(`${REFUSAL3}: sync/file has store ${describeValue(store)} in its context,` + ` expected one of: ${STORE_BACKENDS.join(", ")}`);
6065
+ if (!STORE_BACKENDS2.includes(store)) {
6066
+ throw new TypeError(`${REFUSAL3}: sync/file has store ${describeValue(store)} in its context,` + ` expected one of: ${STORE_BACKENDS2.join(", ")}`);
5790
6067
  }
5791
6068
  return createFileSync({ repoRoot, backend: store });
5792
6069
  }
5793
6070
  }
5794
6071
  ];
5795
- var CORE_ADAPTER_REGISTRY = createAdapterRegistry(CORE_ADAPTERS);
6072
+ var CORE_ADAPTER_REGISTRY2 = createAdapterRegistry2(CORE_ADAPTERS);
5796
6073
 
5797
6074
  // src/board/trust.ts
5798
6075
  var REPO_PATH = "{owner}/{repo}";
5799
- var TRUSTED_PERMISSIONS = ["admin", "maintain", "write"];
6076
+ var TRUSTED_PERMISSIONS2 = ["admin", "maintain", "write"];
5800
6077
  var TRUST_REFUSAL_EXIT = 2;
5801
6078
  var REMEDY = Object.freeze({
5802
6079
  issue: "a member must open the spec",
@@ -5808,7 +6085,7 @@ function failureDetail(reading) {
5808
6085
  return detail === "" ? UNREPORTED : detail;
5809
6086
  }
5810
6087
  function isTrustedPermission(value) {
5811
- return TRUSTED_PERMISSIONS.some((permission) => permission === value);
6088
+ return TRUSTED_PERMISSIONS2.some((permission) => permission === value);
5812
6089
  }
5813
6090
  function stringOrNull(value) {
5814
6091
  return typeof value === "string" ? value : null;
@@ -5858,8 +6135,8 @@ async function readAuthorTrust(options) {
5858
6135
  };
5859
6136
  }
5860
6137
  const wanted = login.toLowerCase();
5861
- const listed2 = trustedAuthors.some((author) => author.toLowerCase() === wanted);
5862
- if (listed2) {
6138
+ const listed = trustedAuthors.some((author) => author.toLowerCase() === wanted);
6139
+ if (listed) {
5863
6140
  return { login, trusted: true, source: "allow-list", refusal: null, permission: null };
5864
6141
  }
5865
6142
  const permission = await permissions(login);
@@ -5911,18 +6188,18 @@ function requireTrustedAuthor(item, reading) {
5911
6188
  throw new CommandExit(TRUST_REFUSAL_EXIT, trustRefusalMessage(item, reading));
5912
6189
  }
5913
6190
  // src/effort/sync/wire.ts
5914
- import { existsSync as existsSync14, mkdtempSync as mkdtempSync2, rmSync as rmSync7 } from "fs";
6191
+ import { existsSync as existsSync14, mkdtempSync as mkdtempSync2, rmSync as rmSync8 } from "fs";
5915
6192
  import { tmpdir as tmpdir4 } from "os";
5916
6193
  import { join as join17 } from "path";
5917
- import { Database as Database6, SQLiteError as SQLiteError3 } from "bun:sqlite";
5918
- var WIRE_FORMAT = "rafa-effort-wire";
5919
- var WIRE_VERSION = 1;
6194
+ import { Database as Database7, SQLiteError as SQLiteError3 } from "bun:sqlite";
6195
+ var WIRE_FORMAT2 = "rafa-effort-wire";
6196
+ var WIRE_VERSION2 = 1;
5920
6197
 
5921
- class WireFormatError extends Error {
6198
+ class WireFormatError2 extends Error {
5922
6199
  name = "WireFormatError";
5923
6200
  }
5924
6201
 
5925
- class WireExportRefusal extends Error {
6202
+ class WireExportRefusal2 extends Error {
5926
6203
  name = "WireExportRefusal";
5927
6204
  }
5928
6205
  var MERGED_TABLES = Object.entries(MERGE_RULES).filter(([, rule]) => rule.scope === "merged").map(([table]) => table);
@@ -5933,17 +6210,17 @@ function isRecord4(value) {
5933
6210
  function isCount(value) {
5934
6211
  return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
5935
6212
  }
5936
- function isMergedTable(name2) {
5937
- return MERGED_TABLES.includes(name2);
6213
+ function isMergedTable(name) {
6214
+ return MERGED_TABLES.includes(name);
5938
6215
  }
5939
6216
  function checkCursor(value) {
5940
6217
  if (!isRecord4(value))
5941
- throw new WireFormatError("wire: cursor is not an object");
6218
+ throw new WireFormatError2("wire: cursor is not an object");
5942
6219
  const entries = Object.entries(value).map(([table, seq]) => {
5943
6220
  if (!isMergedTable(table))
5944
- throw new WireFormatError(`wire: cursor names ${JSON.stringify(table)}, which is no merged table`);
6221
+ throw new WireFormatError2(`wire: cursor names ${JSON.stringify(table)}, which is no merged table`);
5945
6222
  if (!isCount(seq))
5946
- throw new WireFormatError(`wire: cursor for ${table} is ${JSON.stringify(seq)}, expected a whole number of 0 or more`);
6223
+ throw new WireFormatError2(`wire: cursor for ${table} is ${JSON.stringify(seq)}, expected a whole number of 0 or more`);
5947
6224
  return [table, seq];
5948
6225
  });
5949
6226
  return Object.freeze(Object.fromEntries(entries));
@@ -5951,67 +6228,67 @@ function checkCursor(value) {
5951
6228
  function checkRow(table, value, index) {
5952
6229
  const where = `wire: ${table} row ${String(index)}`;
5953
6230
  if (!isRecord4(value))
5954
- throw new WireFormatError(`${where} is not an object`);
6231
+ throw new WireFormatError2(`${where} is not an object`);
5955
6232
  for (const [column, cell] of Object.entries(value)) {
5956
6233
  const carried = cell === null || typeof cell === "string" || typeof cell === "number" && Number.isFinite(cell);
5957
6234
  if (!carried)
5958
- throw new WireFormatError(`${where} holds ${JSON.stringify(cell) ?? typeof cell} in ${column}, expected a string, a number or null`);
6235
+ throw new WireFormatError2(`${where} holds ${JSON.stringify(cell) ?? typeof cell} in ${column}, expected a string, a number or null`);
5959
6236
  }
5960
6237
  const seq = value.seq;
5961
6238
  if (!isCount(seq) || seq === 0)
5962
- throw new WireFormatError(`${where} has seq ${JSON.stringify(seq) ?? "undefined"}, expected a whole number above 0`);
6239
+ throw new WireFormatError2(`${where} has seq ${JSON.stringify(seq) ?? "undefined"}, expected a whole number above 0`);
5963
6240
  return Object.freeze({ ...value });
5964
6241
  }
5965
6242
  function checkMigrations(value) {
5966
6243
  if (!Array.isArray(value))
5967
- throw new WireFormatError("wire: migrations is not a list");
6244
+ throw new WireFormatError2("wire: migrations is not a list");
5968
6245
  const ids = value.map((id) => {
5969
6246
  if (typeof id !== "string" || id === "")
5970
- throw new WireFormatError(`wire: migration id ${JSON.stringify(id)} is not a name`);
6247
+ throw new WireFormatError2(`wire: migration id ${JSON.stringify(id)} is not a name`);
5971
6248
  return id;
5972
6249
  });
5973
6250
  const twice = ids.filter((id, index) => ids.indexOf(id) !== index);
5974
6251
  if (twice.length > 0)
5975
- throw new WireFormatError(`wire: migrations name ${twice.join(", ")} more than once`);
6252
+ throw new WireFormatError2(`wire: migrations name ${twice.join(", ")} more than once`);
5976
6253
  return Object.freeze(ids);
5977
6254
  }
5978
6255
  function checkTables(value) {
5979
6256
  if (!isRecord4(value))
5980
- throw new WireFormatError("wire: tables is not an object");
6257
+ throw new WireFormatError2("wire: tables is not an object");
5981
6258
  const entries = Object.entries(value).map(([table, rows]) => {
5982
6259
  if (!isMergedTable(table))
5983
- throw new WireFormatError(`wire: tables names ${JSON.stringify(table)}, which is no merged table`);
6260
+ throw new WireFormatError2(`wire: tables names ${JSON.stringify(table)}, which is no merged table`);
5984
6261
  if (!Array.isArray(rows))
5985
- throw new WireFormatError(`wire: tables.${table} is not a list`);
6262
+ throw new WireFormatError2(`wire: tables.${table} is not a list`);
5986
6263
  return [table, Object.freeze(rows.map((row, index) => checkRow(table, row, index)))];
5987
6264
  });
5988
6265
  return Object.freeze(Object.fromEntries(entries));
5989
6266
  }
5990
6267
  function checkPayload(value) {
5991
6268
  if (!isRecord4(value))
5992
- throw new WireFormatError("wire: the payload is not an object");
5993
- if (value.format !== WIRE_FORMAT)
5994
- throw new WireFormatError(`wire: format is ${JSON.stringify(value.format) ?? "undefined"}, expected ${JSON.stringify(WIRE_FORMAT)}`);
5995
- if (value.version !== WIRE_VERSION)
5996
- throw new WireFormatError(`wire: version is ${JSON.stringify(value.version) ?? "undefined"}; this rafa reads version ${String(WIRE_VERSION)}`);
6269
+ throw new WireFormatError2("wire: the payload is not an object");
6270
+ if (value.format !== WIRE_FORMAT2)
6271
+ throw new WireFormatError2(`wire: format is ${JSON.stringify(value.format) ?? "undefined"}, expected ${JSON.stringify(WIRE_FORMAT2)}`);
6272
+ if (value.version !== WIRE_VERSION2)
6273
+ throw new WireFormatError2(`wire: version is ${JSON.stringify(value.version) ?? "undefined"}; this rafa reads version ${String(WIRE_VERSION2)}`);
5997
6274
  return Object.freeze({
5998
- format: WIRE_FORMAT,
5999
- version: WIRE_VERSION,
6275
+ format: WIRE_FORMAT2,
6276
+ version: WIRE_VERSION2,
6000
6277
  migrations: checkMigrations(value.migrations),
6001
6278
  tables: checkTables(value.tables),
6002
6279
  cursor: checkCursor(value.cursor)
6003
6280
  });
6004
6281
  }
6005
- function encodeWirePayload(payload) {
6282
+ function encodeWirePayload2(payload) {
6006
6283
  return JSON.stringify(payload);
6007
6284
  }
6008
- function decodeWirePayload(text) {
6285
+ function decodeWirePayload2(text) {
6009
6286
  let parsed;
6010
6287
  try {
6011
6288
  parsed = JSON.parse(text);
6012
6289
  } catch (error) {
6013
6290
  const reason = error instanceof Error ? error.message : String(error);
6014
- throw new WireFormatError(`wire: the payload is not JSON (${reason})`);
6291
+ throw new WireFormatError2(`wire: the payload is not JSON (${reason})`);
6015
6292
  }
6016
6293
  return checkPayload(parsed);
6017
6294
  }
@@ -6022,17 +6299,17 @@ function readLoggedIds(db) {
6022
6299
  return db.query(`SELECT id FROM ${MIGRATION_LOG_TABLE} ORDER BY seq`).all().map(({ id }) => id);
6023
6300
  }
6024
6301
  function columnsOf(db, table) {
6025
- return db.query(`PRAGMA table_info(${quoted(table)})`).all().map(({ name: name2 }) => name2);
6302
+ return db.query(`PRAGMA table_info(${quoted(table)})`).all().map(({ name }) => name);
6026
6303
  }
6027
6304
  function wireValue(value, where) {
6028
6305
  if (typeof value === "bigint") {
6029
6306
  const number = Number(value);
6030
6307
  if (Number.isSafeInteger(number))
6031
6308
  return number;
6032
- throw new WireExportRefusal(`wire: ${where} holds ${String(value)}, past the whole numbers JSON carries exactly`);
6309
+ throw new WireExportRefusal2(`wire: ${where} holds ${String(value)}, past the whole numbers JSON carries exactly`);
6033
6310
  }
6034
6311
  if (value instanceof Uint8Array)
6035
- throw new WireExportRefusal(`wire: ${where} holds a BLOB, which the wire does not carry`);
6312
+ throw new WireExportRefusal2(`wire: ${where} holds a BLOB, which the wire does not carry`);
6036
6313
  return value;
6037
6314
  }
6038
6315
  function readRows(db, table, columns, after, path) {
@@ -6045,7 +6322,7 @@ function readRows(db, table, columns, after, path) {
6045
6322
  function readPayload(db, path, cursor) {
6046
6323
  const migrations = readLoggedIds(db);
6047
6324
  if (migrations === null) {
6048
- throw new WireExportRefusal(`wire: ${path} has no migration log; any rafa command that writes the store brings it forward`);
6325
+ throw new WireExportRefusal2(`wire: ${path} has no migration log; any rafa command that writes the store brings it forward`);
6049
6326
  }
6050
6327
  const tables = {};
6051
6328
  const next = { ...cursor };
@@ -6055,7 +6332,7 @@ function readPayload(db, path, cursor) {
6055
6332
  continue;
6056
6333
  const missing = ORIGIN_COLUMNS.filter((column) => !columns.includes(column));
6057
6334
  if (missing.length > 0) {
6058
- throw new WireExportRefusal(`wire: ${path} holds no ${missing.map((column) => `${table}.${column}`).join(", ")}, so its rows carry no origin pair`);
6335
+ throw new WireExportRefusal2(`wire: ${path} holds no ${missing.map((column) => `${table}.${column}`).join(", ")}, so its rows carry no origin pair`);
6059
6336
  }
6060
6337
  const rows = readRows(db, table, columns, cursor[table] ?? 0, path);
6061
6338
  tables[table] = Object.freeze(rows);
@@ -6063,20 +6340,20 @@ function readPayload(db, path, cursor) {
6063
6340
  next[table] = last === undefined ? cursor[table] ?? 0 : Number(last.seq);
6064
6341
  }
6065
6342
  return Object.freeze({
6066
- format: WIRE_FORMAT,
6067
- version: WIRE_VERSION,
6343
+ format: WIRE_FORMAT2,
6344
+ version: WIRE_VERSION2,
6068
6345
  migrations: Object.freeze([...migrations]),
6069
6346
  tables: Object.freeze(tables),
6070
6347
  cursor: Object.freeze(next)
6071
6348
  });
6072
6349
  }
6073
- function exportWirePayload(options) {
6350
+ function exportWirePayload2(options) {
6074
6351
  const { path } = options;
6075
6352
  const cursor = checkCursor(options.cursor ?? {});
6076
6353
  guardTestProcess(path);
6077
6354
  if (!existsSync14(path))
6078
- throw new WireExportRefusal(`wire: ${path} is not there`);
6079
- const db = new Database6(path, { readonly: true, safeIntegers: true });
6355
+ throw new WireExportRefusal2(`wire: ${path} is not there`);
6356
+ const db = new Database7(path, { readonly: true, safeIntegers: true });
6080
6357
  try {
6081
6358
  db.run(`PRAGMA busy_timeout = ${String(activeStoreSettings().busyTimeoutMs)}`);
6082
6359
  return db.transaction(() => readPayload(db, path, cursor))();
@@ -6088,34 +6365,34 @@ function namedMigrations(ids, catalogue) {
6088
6365
  const known = new Set(catalogue.map(({ id }) => id));
6089
6366
  const unknown = ids.filter((id) => !known.has(id));
6090
6367
  if (unknown.length > 0) {
6091
- throw new WireFormatError(`wire: the payload's store holds migration ${unknown.join(", ")}, which this rafa does not know; update rafa to take its rows`);
6368
+ throw new WireFormatError2(`wire: the payload's store holds migration ${unknown.join(", ")}, which this rafa does not know; update rafa to take its rows`);
6092
6369
  }
6093
6370
  return catalogue.filter(({ id }) => ids.includes(id));
6094
6371
  }
6095
6372
  function insertRows(db, table, rows) {
6096
6373
  const columns = columnsOf(db, table);
6097
6374
  if (columns.length === 0)
6098
- throw new WireFormatError(`wire: the payload carries ${table}, which its migrations do not make`);
6375
+ throw new WireFormatError2(`wire: the payload carries ${table}, which its migrations do not make`);
6099
6376
  const statement = db.query(`INSERT INTO ${quoted(table)} (${columns.map(quoted).join(", ")}) VALUES (${columns.map(() => "?").join(", ")})`);
6100
6377
  const expected = [...columns].sort().join(",");
6101
6378
  rows.forEach((row, index) => {
6102
6379
  const where = `wire: ${table} row ${String(index)}`;
6103
6380
  const held = Object.keys(row);
6104
6381
  if ([...held].sort().join(",") !== expected) {
6105
- throw new WireFormatError(`${where} holds columns ${held.join(", ")}; its migrations make ${columns.join(", ")}`);
6382
+ throw new WireFormatError2(`${where} holds columns ${held.join(", ")}; its migrations make ${columns.join(", ")}`);
6106
6383
  }
6107
6384
  try {
6108
6385
  statement.run(...columns.map((column) => row[column] ?? null));
6109
6386
  } catch (error) {
6110
6387
  if (!(error instanceof SQLiteError3))
6111
6388
  throw error;
6112
- throw new WireFormatError(`${where} (seq ${String(row.seq)}) is refused by the table: ${error.message}`);
6389
+ throw new WireFormatError2(`${where} (seq ${String(row.seq)}) is refused by the table: ${error.message}`);
6113
6390
  }
6114
6391
  });
6115
6392
  }
6116
6393
  function buildStore(path, payload, options) {
6117
6394
  const migrations = namedMigrations(payload.migrations, options.migrations ?? SQLITE_MIGRATIONS);
6118
- const db = new Database6(path, { create: true, readwrite: true });
6395
+ const db = new Database7(path, { create: true, readwrite: true });
6119
6396
  try {
6120
6397
  bringForward(db, path, "write", "open", {
6121
6398
  migrations,
@@ -6131,10 +6408,10 @@ function buildStore(path, payload, options) {
6131
6408
  db.close();
6132
6409
  }
6133
6410
  }
6134
- function materialiseWirePayload(payload, options = {}) {
6411
+ function materialiseWirePayload2(payload, options = {}) {
6135
6412
  const checked = checkPayload(payload);
6136
6413
  const directory = mkdtempSync2(join17(options.tempDir ?? tmpdir4(), "rafa-wire-"));
6137
- const release = () => rmSync7(directory, { recursive: true, force: true });
6414
+ const release = () => rmSync8(directory, { recursive: true, force: true });
6138
6415
  const path = join17(directory, SQLITE_STORE_FILE_NAME);
6139
6416
  try {
6140
6417
  guardTestProcess(path);
@@ -6154,13 +6431,13 @@ function describeValue4(value) {
6154
6431
  return "an object";
6155
6432
  return String(value);
6156
6433
  }
6157
- function selectEffortStore(repoRoot, config) {
6158
- const adapter = CORE_ADAPTER_REGISTRY.find("store", config.store);
6434
+ function selectEffortStore2(repoRoot, config) {
6435
+ const adapter = CORE_ADAPTER_REGISTRY2.find("store", config.store);
6159
6436
  if (adapter === undefined) {
6160
- const expected = CORE_ADAPTER_REGISTRY.kinds("store").join(", ");
6437
+ const expected = CORE_ADAPTER_REGISTRY2.kinds("store").join(", ");
6161
6438
  throw new TypeError(`effort store: store is ${describeValue4(config.store)},` + ` expected one of: ${expected}`);
6162
6439
  }
6163
6440
  return adapter.create({ repoRoot });
6164
6441
  }
6165
6442
 
6166
- 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, SessionRecordError, isSessionId, sessionPhase, SessionConflictError, SessionStateError, runsDir, sessionFilePath, errorCode, isPidAlive, readSessions, readSession, 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, RebuildRefusal, readConfigFile, loadConfig, plansDirAt, requireProject, resolvePlansDir, resolveProjectConfig, countTasks, formatCounts, checkbox, planFileName, stubOfPlanFile, isFile, issueLine, plural, expectNoArgument, expectOneArgument, expectAtMostOneArgument, readSwitch, fileStamp, fix_schema_default, EffortCopyRefusal, EffortCopyFailure, copyEffortStore, 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, padKind, oneLine, sessionSpawnEnv, getClaudeUsagePercent, checkUsage, CLAUDE_BIN, claudeArgs, interruptClaudeSessions, spawnClaude, runClaude, spawnClaudeCaptured, runClaudeCaptured, planFilePath, ClaudePlannerError, ISSUE_TYPES, ISSUE_PRIORITIES, ISSUE_STATES, GITHUB_LABELS, createGhRunner, typeOfLabels, moduleOfLabels, createLocalTracker, PORT_VERSIONS, createAdapterRegistry, CORE_ADAPTER_REGISTRY, TRUSTED_PERMISSIONS, createGhPermissions, readAuthorTrust, ghBoardTrust, readBoardTrust, requireTrustedBoardAuthor, trustRefusalClause, requireTrustedAuthor, WIRE_FORMAT, WIRE_VERSION, WireFormatError, WireExportRefusal, encodeWirePayload, decodeWirePayload, exportWirePayload, materialiseWirePayload, selectEffortStore };
6443
+ export { EFFORT_STORE_DIR, effortStoreFileName, EFFORT_DIR_VARIABLE, effortStoreDir, guardTestProcess, EFFORT_KEY_PROJECTIONS2, openNdjsonStore2, name, version, RAFA_VERSION, versionLine, createGitRunner, gitSaid, NOT_A_REPOSITORY, mainCheckoutOf, SCOPE_DIR2, INIT_COMMAND2, DISK_FILE_SYSTEM2, ScopeError2, scopeAt2, initHint2, selfAndAncestors2, resolveScope2, POSITION_FILE, positionFilePath, readPositionFile, writePositionFile, positionAt, rehome, hop, goHome, HOP_FILE, hopFilePath, readHopRecord, writeHopRecord, staleAgainst, SessionRecordError, isSessionId, sessionPhase, SessionConflictError, SessionStateError, runsDir, sessionFilePath, errorCode, isPidAlive, readSessions, readSession, 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, openSqliteStore2, SPENDS_GLYPH, CommandExit, isRoutingWord, commandProblem, isTopLevel, commandSpelling, EffortCopyRefusal, EffortCopyFailure, copyEffortStore, RebuildRefusal, readConfigFile2, loadConfig2, 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, mergeStore2, createFileSync, SyncModuleMissing, selectSync, SKILL_FILE2, MARKDOWN_EXTENSION, scanLayout, declaredNameIssue, readFrontmatterDocument, readFrontmatter, renderFrontmatter, mergeFrontmatter, writeFrontmatter, ACTION_HEADING, CAUSE_HEADING, parseInstinct, writeInstinct, readScopes, allRecords, findRecords, instinctProject, toHeldRecords, padKind, oneLine, sessionSpawnEnv, CLAUDE_BIN, claudeArgs, interruptClaudeSessions, spawnClaude, runClaude, spawnClaudeCaptured, runClaudeCaptured, planFilePath, ClaudePlannerError, ISSUE_TYPES, ISSUE_PRIORITIES, ISSUE_STATES, GITHUB_LABELS, createGhRunner, typeOfLabels, moduleOfLabels, createLocalTracker, PORT_VERSIONS2, createAdapterRegistry2, CORE_ADAPTER_REGISTRY2, TRUSTED_PERMISSIONS2, createGhPermissions, readAuthorTrust, ghBoardTrust, readBoardTrust, requireTrustedBoardAuthor, trustRefusalClause, requireTrustedAuthor, WIRE_FORMAT2, WIRE_VERSION2, WireFormatError2, WireExportRefusal2, encodeWirePayload2, decodeWirePayload2, exportWirePayload2, materialiseWirePayload2, selectEffortStore2 };