@massu/core 1.16.1 → 1.16.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -49,16 +49,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
49
49
  ));
50
50
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
51
51
 
52
- // src/lib/memory-path.ts
53
- function encodeMemoryDirName(projectRoot) {
54
- return projectRoot.replace(/\//g, "-");
55
- }
56
- var init_memory_path = __esm({
57
- "src/lib/memory-path.ts"() {
58
- "use strict";
59
- }
60
- });
61
-
62
52
  // src/credentials.ts
63
53
  import { homedir } from "os";
64
54
  import { resolve } from "path";
@@ -168,6 +158,385 @@ var init_credentials = __esm({
168
158
  }
169
159
  });
170
160
 
161
+ // src/lib/fileLock.ts
162
+ import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
163
+ import { dirname } from "path";
164
+ import * as lockfile from "proper-lockfile";
165
+ function readLockHolderPid(lockPath) {
166
+ try {
167
+ const raw = readFileSync2(`${lockPath}.pid`, "utf-8").trim();
168
+ const pid = Number.parseInt(raw, 10);
169
+ if (!Number.isFinite(pid) || pid <= 0) return null;
170
+ return pid;
171
+ } catch {
172
+ return null;
173
+ }
174
+ }
175
+ function busyWaitSync(ms) {
176
+ if (typeof SharedArrayBuffer === "undefined" || typeof Atomics === "undefined") {
177
+ throw new Error(
178
+ `withFileLockSync requires SharedArrayBuffer + Atomics for its retry-loop wait. This Node runtime does not provide them \u2014 refusing to fall back to a CPU spinloop. If you hit this in a sandboxed serverless env, the fix is to perform the lock-protected operation in a host runtime that supports Atomics.`
179
+ );
180
+ }
181
+ const sab = new SharedArrayBuffer(4);
182
+ const view = new Int32Array(sab);
183
+ Atomics.wait(view, 0, 0, ms);
184
+ }
185
+ function withFileLockSync(lockPath, fn, opts = {}) {
186
+ mkdirSync2(dirname(lockPath), { recursive: true });
187
+ const staleMs = opts.staleMs ?? 3e4;
188
+ const blockMs = opts.retries === 0 ? 0 : opts.blockMs ?? 3e4;
189
+ const pollIntervalMs = opts.pollIntervalMs ?? 100;
190
+ const now = opts.now ?? Date.now;
191
+ const sleep = opts.sleep ?? busyWaitSync;
192
+ const makeBusyError = opts.errorFactory ?? ((path, pid, retrySeconds, code) => new FileLockBusyError(path, pid, retrySeconds, code));
193
+ let release = null;
194
+ const deadline = now() + blockMs;
195
+ for (; ; ) {
196
+ try {
197
+ release = lockfile.lockSync(lockPath, {
198
+ stale: staleMs,
199
+ retries: 0,
200
+ realpath: false
201
+ });
202
+ try {
203
+ writeFileSync2(`${lockPath}.pid`, String(process.pid), "utf-8");
204
+ } catch {
205
+ }
206
+ break;
207
+ } catch (err) {
208
+ const e2 = err;
209
+ const code = e2.code;
210
+ if (code !== "ELOCKED" && code !== "EBUSY") {
211
+ throw err;
212
+ }
213
+ if (now() >= deadline) {
214
+ const holderPid = readLockHolderPid(lockPath);
215
+ const remainingMs = Math.max(0, deadline - now());
216
+ const retryAfterSeconds = blockMs === 0 ? Math.round(staleMs / 1e3) : Math.round(remainingMs / 1e3);
217
+ throw makeBusyError(lockPath, holderPid, retryAfterSeconds, code);
218
+ }
219
+ sleep(pollIntervalMs);
220
+ }
221
+ }
222
+ try {
223
+ return fn();
224
+ } finally {
225
+ try {
226
+ if (release) release();
227
+ } catch {
228
+ }
229
+ try {
230
+ rmSync2(`${lockPath}.pid`, { force: true });
231
+ } catch {
232
+ }
233
+ }
234
+ }
235
+ var FileLockBusyError;
236
+ var init_fileLock = __esm({
237
+ "src/lib/fileLock.ts"() {
238
+ "use strict";
239
+ FileLockBusyError = class extends Error {
240
+ constructor(lockPath, holderPid, retryAfterSeconds, causeCode) {
241
+ const pidPart = holderPid != null ? `(PID=${holderPid})` : "(PID=unknown)";
242
+ super(`File lock at ${lockPath} held by another process ${pidPart} \u2014 try again in ${retryAfterSeconds}s`);
243
+ this.lockPath = lockPath;
244
+ this.holderPid = holderPid;
245
+ this.retryAfterSeconds = retryAfterSeconds;
246
+ this.causeCode = causeCode;
247
+ this.name = "FileLockBusyError";
248
+ }
249
+ lockPath;
250
+ holderPid;
251
+ retryAfterSeconds;
252
+ causeCode;
253
+ };
254
+ }
255
+ });
256
+
257
+ // src/lib/sqlite-loader.ts
258
+ import { createRequire } from "module";
259
+ import { spawnSync } from "child_process";
260
+ import { accessSync, appendFileSync, chmodSync as chmodSync2, constants as fsConstants, existsSync as existsSync2, mkdirSync as mkdirSync3 } from "fs";
261
+ import { dirname as dirname2, join } from "path";
262
+ function isNativeAbiError(err) {
263
+ const code = err?.code;
264
+ if (code === "ERR_DLOPEN_FAILED") return true;
265
+ const msg = err instanceof Error ? err.message : String(err);
266
+ return /NODE_MODULE_VERSION/.test(msg) || /was compiled against a different Node\.js version/.test(msg) || /ERR_DLOPEN_FAILED/.test(msg) || /\.node\b/.test(msg) && /dlopen|invalid ELF|mach-o|image not found|no such file|not a valid Win32/i.test(msg);
267
+ }
268
+ function loadBetterSqlite3(opts = {}) {
269
+ if (_testCtor) return _testCtor;
270
+ if (opts.fresh) bustNativeCache();
271
+ return req("better-sqlite3");
272
+ }
273
+ function bustNativeCache() {
274
+ try {
275
+ const cache = req.cache;
276
+ if (!cache) return;
277
+ for (const key of Object.keys(cache)) {
278
+ if (/better[-_]sqlite3|better_sqlite3\.node|[\\/]bindings[\\/]/.test(key)) {
279
+ delete cache[key];
280
+ }
281
+ }
282
+ } catch {
283
+ }
284
+ }
285
+ function openDatabase(dbPath, opts = {}) {
286
+ const { selfHeal: selfHealOpt = true, ...ctorOpts } = opts;
287
+ const selfHeal = selfHealOpt && process.env.MASSU_HOOK_RUNTIME !== "1";
288
+ const Ctor = loadBetterSqlite3();
289
+ try {
290
+ return new Ctor(dbPath, ctorOpts);
291
+ } catch (err) {
292
+ if (!isNativeAbiError(err)) {
293
+ throw err;
294
+ }
295
+ if (!selfHeal) {
296
+ recordHealEvent({ phase: "skipped", reason: "self-heal-disabled", abiTo: process.versions.modules });
297
+ throw new MemoryEngineUnusableError("abi-mismatch", detailOf(err));
298
+ }
299
+ const result = (_testHeal ?? attemptNativeHeal)(err);
300
+ if (!result.healed && !result.contended) {
301
+ throw new MemoryEngineUnusableError(result.reason ?? "heal-failed", result.detail ?? detailOf(err));
302
+ }
303
+ try {
304
+ const FreshCtor = loadBetterSqlite3({ fresh: true });
305
+ return new FreshCtor(dbPath, ctorOpts);
306
+ } catch (retryErr) {
307
+ throw new MemoryEngineUnusableError("heal-failed", detailOf(retryErr));
308
+ }
309
+ }
310
+ }
311
+ function probeMemoryDbUsable(opts = {}) {
312
+ const selfHeal = opts.selfHeal ?? false;
313
+ try {
314
+ const db = openDatabase(":memory:", { selfHeal });
315
+ try {
316
+ db.prepare("SELECT 1").get();
317
+ } finally {
318
+ db.close();
319
+ }
320
+ } catch (err) {
321
+ if (err instanceof MemoryEngineUnusableError) {
322
+ return { ok: false, reason: err.reason, remedy: err.remedy, detail: err.detail };
323
+ }
324
+ return {
325
+ ok: false,
326
+ reason: isNativeAbiError(err) ? "abi-mismatch" : "unreadable",
327
+ remedy: NATIVE_DB_REMEDY,
328
+ detail: err instanceof Error ? err.message : String(err)
329
+ };
330
+ }
331
+ const dbPath = opts.dbPath;
332
+ if (dbPath && dbPath !== ":memory:" && existsSync2(dbPath)) {
333
+ try {
334
+ const rdb = openDatabase(dbPath, { readonly: true, selfHeal: false });
335
+ try {
336
+ rdb.prepare("SELECT 1").get();
337
+ } finally {
338
+ rdb.close();
339
+ }
340
+ } catch (err) {
341
+ return {
342
+ ok: false,
343
+ reason: err instanceof MemoryEngineUnusableError ? err.reason : "unreadable",
344
+ remedy: NATIVE_DB_REMEDY,
345
+ detail: err instanceof Error ? err.message : String(err)
346
+ };
347
+ }
348
+ }
349
+ return { ok: true };
350
+ }
351
+ function attemptNativeHeal(err) {
352
+ const start = Date.now();
353
+ const abiTo = process.versions.modules;
354
+ const abiFrom = parseAbiFrom(err);
355
+ let pkgDir;
356
+ try {
357
+ pkgDir = dirname2(req.resolve("better-sqlite3/package.json"));
358
+ } catch {
359
+ recordHealEvent({ phase: "skipped", reason: "not-resolvable", abiFrom, abiTo });
360
+ return { healed: false, reason: "missing", abiFrom, abiTo, detail: "better-sqlite3 not resolvable" };
361
+ }
362
+ if (!isWritable(pkgDir)) {
363
+ recordHealEvent({ phase: "skipped", reason: "dir-not-writable", abiFrom, abiTo });
364
+ return { healed: false, reason: "heal-failed", abiFrom, abiTo, detail: `install dir not writable: ${pkgDir}` };
365
+ }
366
+ recordHealEvent({ phase: "attempt", reason: "abi-mismatch", abiFrom, abiTo });
367
+ try {
368
+ return withFileLockSync(
369
+ join(credentialsDir(), "native-heal.lock"),
370
+ () => runRebuild(pkgDir, abiFrom, abiTo, start),
371
+ { blockMs: 6e4, staleMs: 3e5 }
372
+ );
373
+ } catch (lockErr) {
374
+ const detail = lockErr instanceof Error ? lockErr.message : String(lockErr);
375
+ recordHealEvent({ phase: "failed", reason: "heal-failed", abiFrom, abiTo, detail: `lock: ${detail}` });
376
+ return { healed: false, contended: true, reason: "heal-failed", abiFrom, abiTo, detail: `heal lock contended: ${detail}` };
377
+ }
378
+ }
379
+ function runRebuild(pkgDir, abiFrom, abiTo, start) {
380
+ try {
381
+ const FreshCtor = loadBetterSqlite3({ fresh: true });
382
+ new FreshCtor(":memory:").close();
383
+ const res2 = {
384
+ healed: true,
385
+ abiFrom,
386
+ abiTo,
387
+ durationMs: Date.now() - start,
388
+ detail: "already healed by a concurrent process"
389
+ };
390
+ recordHealEvent({ phase: "success", reason: "already-healed", abiFrom, abiTo, durationMs: res2.durationMs });
391
+ return res2;
392
+ } catch (probeErr) {
393
+ if (!isNativeAbiError(probeErr)) {
394
+ return { healed: false, reason: "heal-failed", abiFrom, abiTo, durationMs: Date.now() - start, detail: detailOf(probeErr) };
395
+ }
396
+ }
397
+ const prebuildBin = resolveLocalBin(pkgDir, "prebuild-install");
398
+ if (prebuildBin) {
399
+ const r2 = spawnSync(process.execPath, [prebuildBin], {
400
+ cwd: pkgDir,
401
+ encoding: "utf-8",
402
+ timeout: 12e4
403
+ });
404
+ if (r2.status === 0) {
405
+ const res2 = { healed: true, method: "prebuild-install", abiFrom, abiTo, durationMs: Date.now() - start };
406
+ recordHealEvent({ phase: "success", reason: "abi-mismatch", ...res2 });
407
+ return res2;
408
+ }
409
+ }
410
+ const gypBin = resolveNodeGypBin();
411
+ if (gypBin && hasCompiler()) {
412
+ const r2 = spawnSync(process.execPath, [gypBin, "rebuild", "--release"], {
413
+ cwd: pkgDir,
414
+ encoding: "utf-8",
415
+ timeout: 3e5
416
+ });
417
+ if (r2.status === 0) {
418
+ const res2 = { healed: true, method: "node-gyp", abiFrom, abiTo, durationMs: Date.now() - start };
419
+ recordHealEvent({ phase: "success", reason: "abi-mismatch", ...res2 });
420
+ return res2;
421
+ }
422
+ }
423
+ const res = {
424
+ healed: false,
425
+ reason: "heal-failed",
426
+ abiFrom,
427
+ abiTo,
428
+ durationMs: Date.now() - start,
429
+ detail: prebuildBin ? "prebuild-install failed; node-gyp fallback unavailable or failed" : "no prebuild-install bin resolvable"
430
+ };
431
+ recordHealEvent({ phase: "failed", reason: "heal-failed", abiFrom, abiTo, durationMs: res.durationMs });
432
+ return res;
433
+ }
434
+ function recordHealEvent(event) {
435
+ try {
436
+ const rec = {
437
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
438
+ node: process.versions.node,
439
+ platform: process.platform,
440
+ arch: process.arch,
441
+ ...event
442
+ };
443
+ const dir = credentialsDir();
444
+ mkdirSync3(dir, { recursive: true });
445
+ const file = join(dir, "native-heal-events.jsonl");
446
+ appendFileSync(file, JSON.stringify(rec) + "\n", "utf-8");
447
+ try {
448
+ chmodSync2(file, 384);
449
+ } catch {
450
+ }
451
+ } catch {
452
+ }
453
+ }
454
+ function parseAbiFrom(err) {
455
+ const msg = err instanceof Error ? err.message : String(err ?? "");
456
+ const m3 = /NODE_MODULE_VERSION (\d+)/.exec(msg);
457
+ if (m3 && /^\d+$/.test(m3[1])) return m3[1];
458
+ return void 0;
459
+ }
460
+ function detailOf(err) {
461
+ const msg = err instanceof Error ? err.message : String(err);
462
+ return msg.slice(0, 300);
463
+ }
464
+ function isWritable(dir) {
465
+ try {
466
+ accessSync(dir, fsConstants.W_OK);
467
+ return true;
468
+ } catch {
469
+ return false;
470
+ }
471
+ }
472
+ function resolveLocalBin(pkgDir, name) {
473
+ const candidates = [
474
+ join(pkgDir, "node_modules", ".bin", name),
475
+ // nested install
476
+ join(pkgDir, "..", ".bin", name),
477
+ // hoisted (node_modules/.bin)
478
+ join(pkgDir, "..", "..", "node_modules", ".bin", name)
479
+ // workspace hoist
480
+ ];
481
+ for (const c2 of candidates) {
482
+ if (existsSync2(c2)) return c2;
483
+ }
484
+ return void 0;
485
+ }
486
+ function resolveNodeGypBin() {
487
+ try {
488
+ return req.resolve("node-gyp/bin/node-gyp.js");
489
+ } catch {
490
+ return void 0;
491
+ }
492
+ }
493
+ function hasCompiler() {
494
+ for (const cc of ["cc", "clang", "gcc"]) {
495
+ try {
496
+ const r2 = spawnSync(cc, ["--version"], { encoding: "utf-8", timeout: 5e3 });
497
+ if (r2.status === 0) return true;
498
+ } catch {
499
+ }
500
+ }
501
+ return false;
502
+ }
503
+ var req, NATIVE_DB_REMEDY, MemoryEngineUnusableError, _testCtor, _testHeal;
504
+ var init_sqlite_loader = __esm({
505
+ "src/lib/sqlite-loader.ts"() {
506
+ "use strict";
507
+ init_credentials();
508
+ init_fileLock();
509
+ req = createRequire(import.meta.url);
510
+ NATIVE_DB_REMEDY = "Run 'massu heal' to rebuild the database engine for your Node version, then restart your MCP client / Claude Code.";
511
+ MemoryEngineUnusableError = class extends Error {
512
+ reason;
513
+ remedy;
514
+ detail;
515
+ constructor(reason, detail) {
516
+ super(
517
+ `Massu memory engine is unusable (${reason}). ${NATIVE_DB_REMEDY}` + (detail ? ` [${detail}]` : "")
518
+ );
519
+ this.name = "MemoryEngineUnusableError";
520
+ this.reason = reason;
521
+ this.remedy = NATIVE_DB_REMEDY;
522
+ this.detail = detail;
523
+ }
524
+ };
525
+ _testCtor = null;
526
+ _testHeal = null;
527
+ }
528
+ });
529
+
530
+ // src/lib/memory-path.ts
531
+ function encodeMemoryDirName(projectRoot) {
532
+ return projectRoot.replace(/\//g, "-");
533
+ }
534
+ var init_memory_path = __esm({
535
+ "src/lib/memory-path.ts"() {
536
+ "use strict";
537
+ }
538
+ });
539
+
171
540
  // src/config-memory-schema.ts
172
541
  import { z } from "zod";
173
542
  var MemoryConfigSchema;
@@ -317,8 +686,8 @@ __export(config_exports, {
317
686
  getResolvedPaths: () => getResolvedPaths,
318
687
  resetConfig: () => resetConfig
319
688
  });
320
- import { resolve as resolve2, dirname } from "path";
321
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
689
+ import { resolve as resolve2, dirname as dirname3 } from "path";
690
+ import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
322
691
  import { homedir as homedir2 } from "os";
323
692
  import { parse as parseYaml } from "yaml";
324
693
  import { z as z2 } from "zod";
@@ -326,22 +695,22 @@ function findProjectRoot() {
326
695
  const cwd = process.cwd();
327
696
  let dir = cwd;
328
697
  while (true) {
329
- if (existsSync2(resolve2(dir, "massu.config.yaml"))) {
698
+ if (existsSync3(resolve2(dir, "massu.config.yaml"))) {
330
699
  return dir;
331
700
  }
332
- const parent = dirname(dir);
701
+ const parent = dirname3(dir);
333
702
  if (parent === dir) break;
334
703
  dir = parent;
335
704
  }
336
705
  dir = cwd;
337
706
  while (true) {
338
- if (existsSync2(resolve2(dir, "package.json"))) {
707
+ if (existsSync3(resolve2(dir, "package.json"))) {
339
708
  return dir;
340
709
  }
341
- if (existsSync2(resolve2(dir, ".git"))) {
710
+ if (existsSync3(resolve2(dir, ".git"))) {
342
711
  return dir;
343
712
  }
344
- const parent = dirname(dir);
713
+ const parent = dirname3(dir);
345
714
  if (parent === dir) break;
346
715
  dir = parent;
347
716
  }
@@ -358,8 +727,8 @@ function getConfig() {
358
727
  const root = getProjectRoot();
359
728
  const configPath = resolve2(root, "massu.config.yaml");
360
729
  let rawYaml = {};
361
- if (existsSync2(configPath)) {
362
- const content = readFileSync2(configPath, "utf-8");
730
+ if (existsSync3(configPath)) {
731
+ const content = readFileSync3(configPath, "utf-8");
363
732
  rawYaml = parseYaml(content) ?? {};
364
733
  }
365
734
  const result = RawConfigSchema.safeParse(rawYaml);
@@ -440,9 +809,13 @@ Hint: run \`massu config refresh\` to regenerate a valid config or fix the liste
440
809
  const resolvedEndpoint = resolveEndpoint({ configEndpoint: _config.cloud?.endpoint });
441
810
  if (resolvedKey.apiKey) {
442
811
  _config.cloud = {
443
- enabled: true,
444
812
  sync: { memory: true, analytics: true, audit: true },
445
813
  ..._config.cloud,
814
+ // Spread FIRST, then decide `enabled`, so a workspace that declares a `cloud:`
815
+ // block only to tune `requestTimeoutMs` does not disable its own sync. An
816
+ // EXPLICIT `enabled: false` is still honoured; `undefined` (not stated) means
817
+ // "a key resolved, so turn it on". (plan-2026-07-20-cloud-sync-timeout)
818
+ enabled: _config.cloud?.enabled ?? true,
446
819
  apiKey: resolvedKey.apiKey,
447
820
  endpoint: resolvedEndpoint
448
821
  };
@@ -671,9 +1044,22 @@ var init_config = __esm({
671
1044
  })).default([])
672
1045
  }).optional();
673
1046
  CloudConfigSchema = z2.object({
674
- enabled: z2.boolean().default(false),
1047
+ // OPTIONAL, not `.default(false)`. A zod default is indistinguishable from an
1048
+ // explicit value once parsed, so `.default(false)` meant that merely declaring a
1049
+ // `cloud:` block (to set any OTHER key) silently produced `enabled: false`, which
1050
+ // then overrode the `enabled: true` auto-enable below via object spread — turning
1051
+ // cloud sync OFF as a side effect of tuning it. `undefined` now means "not stated",
1052
+ // and the auto-enable preserves it. (plan-2026-07-20-cloud-sync-timeout)
1053
+ enabled: z2.boolean().optional(),
675
1054
  apiKey: z2.string().optional(),
676
1055
  endpoint: z2.string().optional(),
1056
+ // Per-request POST budget for the `/sync` ingest. cloud-sync.ts reads this
1057
+ // (`(cloud as { requestTimeoutMs?: number }).requestTimeoutMs`) but it was ABSENT
1058
+ // from this schema, and zod strips unknown keys — so the knob was unreachable from
1059
+ // massu.config.yaml and the default could never be tuned. Measured 2026-07-20: a
1060
+ // 423-observation payload takes ~9.2s against the live ingest. Capped at
1061
+ // SYNC_DEADLINE_MS (20s) since the overall deadline clamps each attempt anyway.
1062
+ requestTimeoutMs: z2.number().int().positive().max(2e4).optional(),
677
1063
  sync: z2.object({
678
1064
  memory: z2.boolean().default(true),
679
1065
  analytics: z2.boolean().default(true),
@@ -931,27 +1317,26 @@ var init_memory_vector = __esm({
931
1317
  });
932
1318
 
933
1319
  // src/db-backup.ts
934
- import Database from "better-sqlite3";
935
- import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync2 } from "fs";
936
- import { resolve as resolve3, join, basename, dirname as dirname2 } from "path";
1320
+ import { existsSync as existsSync4, mkdirSync as mkdirSync4, readdirSync, statSync, unlinkSync, copyFileSync, rmSync as rmSync3 } from "fs";
1321
+ import { resolve as resolve3, join as join2, basename, dirname as dirname4 } from "path";
937
1322
  import { homedir as homedir3 } from "os";
938
1323
  function dbBackupsRoot(home = homedir3()) {
939
1324
  return resolve3(home, ".massu", "db-backups");
940
1325
  }
941
1326
  function projectBackupDir(projectRoot, home = homedir3()) {
942
1327
  const slug = basename(projectRoot).replace(/[^A-Za-z0-9._-]/g, "_") || "project";
943
- return join(dbBackupsRoot(home), slug);
1328
+ return join2(dbBackupsRoot(home), slug);
944
1329
  }
945
1330
  function backupStamp(nowMs) {
946
1331
  return new Date(nowMs).toISOString().replace(/[:.]/g, "-");
947
1332
  }
948
1333
  function listDbBackups(projectRoot, home = homedir3()) {
949
1334
  const dir = projectBackupDir(projectRoot, home);
950
- if (!existsSync3(dir)) return [];
1335
+ if (!existsSync4(dir)) return [];
951
1336
  const out = [];
952
1337
  for (const f2 of readdirSync(dir)) {
953
1338
  if (!f2.endsWith(".db")) continue;
954
- const p19 = join(dir, f2);
1339
+ const p19 = join2(dir, f2);
955
1340
  const st = statSync(p19);
956
1341
  const db = f2.replace(/-\d{4}-\d{2}-\d{2}T.*$/, "");
957
1342
  out.push({ db, path: p19, bytes: st.size, mtimeMs: st.mtimeMs });
@@ -964,13 +1349,13 @@ function hasFreshDbBackup(projectRoot, dbPath, nowMs = Date.now(), home = homedi
964
1349
  if (backups.length === 0) return false;
965
1350
  const newest = backups[0];
966
1351
  if (nowMs - newest.mtimeMs > FRESH_WINDOW_MS) return false;
967
- if (existsSync3(dbPath) && statSync(dbPath).mtimeMs > newest.mtimeMs) return false;
1352
+ if (existsSync4(dbPath) && statSync(dbPath).mtimeMs > newest.mtimeMs) return false;
968
1353
  return true;
969
1354
  }
970
1355
  function integrityOk(dbPath) {
971
1356
  let db = null;
972
1357
  try {
973
- db = new Database(dbPath, { readonly: true });
1358
+ db = openDatabase(dbPath, { readonly: true });
974
1359
  const rows = db.pragma("integrity_check");
975
1360
  return rows.length === 1 && rows[0].integrity_check === "ok";
976
1361
  } catch {
@@ -983,16 +1368,16 @@ function integrityOk(dbPath) {
983
1368
  }
984
1369
  }
985
1370
  function backupDb(projectRoot, dbPath, nowMs = Date.now(), home = homedir3()) {
986
- if (!existsSync3(dbPath)) {
1371
+ if (!existsSync4(dbPath)) {
987
1372
  throw new DbBackupError(`cannot back up a database that does not exist: ${dbPath}`);
988
1373
  }
989
1374
  const dir = projectBackupDir(projectRoot, home);
990
- mkdirSync2(dir, { recursive: true });
1375
+ mkdirSync4(dir, { recursive: true });
991
1376
  const name = basename(dbPath, ".db");
992
- const dest = join(dir, `${name}-${backupStamp(nowMs)}.db`);
1377
+ const dest = join2(dir, `${name}-${backupStamp(nowMs)}.db`);
993
1378
  let src = null;
994
1379
  try {
995
- src = new Database(dbPath, { readonly: true });
1380
+ src = openDatabase(dbPath, { readonly: true });
996
1381
  src.exec(`VACUUM INTO '${dest.replace(/'/g, "''")}'`);
997
1382
  } catch (err) {
998
1383
  throw new DbBackupError(
@@ -1030,7 +1415,7 @@ function pruneDbBackups(projectRoot, dbName, keep = DEFAULT_RETENTION, home = ho
1030
1415
  return removed;
1031
1416
  }
1032
1417
  function restoreDb(backupPath, dbPath, nowMs = Date.now(), home = homedir3()) {
1033
- if (!existsSync3(backupPath)) {
1418
+ if (!existsSync4(backupPath)) {
1034
1419
  throw new DbBackupError(`backup not found: ${backupPath}`);
1035
1420
  }
1036
1421
  if (!integrityOk(backupPath)) {
@@ -1039,15 +1424,15 @@ function restoreDb(backupPath, dbPath, nowMs = Date.now(), home = homedir3()) {
1039
1424
  );
1040
1425
  }
1041
1426
  let preserved = null;
1042
- if (existsSync3(dbPath)) {
1043
- const dir = dirname2(backupPath) || projectBackupDir(process.cwd(), home);
1044
- mkdirSync2(dir, { recursive: true });
1045
- preserved = join(dir, `${basename(dbPath, ".db")}.corrupt-${backupStamp(nowMs)}.db`);
1427
+ if (existsSync4(dbPath)) {
1428
+ const dir = dirname4(backupPath) || projectBackupDir(process.cwd(), home);
1429
+ mkdirSync4(dir, { recursive: true });
1430
+ preserved = join2(dir, `${basename(dbPath, ".db")}.corrupt-${backupStamp(nowMs)}.db`);
1046
1431
  copyFileSync(dbPath, preserved);
1047
1432
  }
1048
1433
  for (const suffix of ["", "-wal", "-shm"]) {
1049
1434
  const p19 = `${dbPath}${suffix}`;
1050
- if (existsSync3(p19)) rmSync2(p19, { force: true });
1435
+ if (existsSync4(p19)) rmSync3(p19, { force: true });
1051
1436
  }
1052
1437
  copyFileSync(backupPath, dbPath);
1053
1438
  if (!integrityOk(dbPath)) {
@@ -1059,7 +1444,7 @@ function restoreDb(backupPath, dbPath, nowMs = Date.now(), home = homedir3()) {
1059
1444
  }
1060
1445
  function backupBeforeSchemaChange(projectRoot, dbPath, onError, nowMs = Date.now(), home = homedir3()) {
1061
1446
  try {
1062
- if (!existsSync3(dbPath)) return null;
1447
+ if (!existsSync4(dbPath)) return null;
1063
1448
  if (hasFreshDbBackup(projectRoot, dbPath, nowMs, home)) return null;
1064
1449
  return backupDb(projectRoot, dbPath, nowMs, home);
1065
1450
  } catch (err) {
@@ -1071,6 +1456,7 @@ var DEFAULT_RETENTION, FRESH_WINDOW_MS, DbBackupError;
1071
1456
  var init_db_backup = __esm({
1072
1457
  "src/db-backup.ts"() {
1073
1458
  "use strict";
1459
+ init_sqlite_loader();
1074
1460
  DEFAULT_RETENTION = 5;
1075
1461
  FRESH_WINDOW_MS = 24 * 60 * 60 * 1e3;
1076
1462
  DbBackupError = class extends Error {
@@ -1233,21 +1619,21 @@ var init_rule_candidate_store = __esm({
1233
1619
  });
1234
1620
 
1235
1621
  // src/hooks/lib/hook-failure-signal.ts
1236
- import { appendFileSync, mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
1237
- import { join as join2, dirname as dirname3 } from "path";
1622
+ import { appendFileSync as appendFileSync2, mkdirSync as mkdirSync5, existsSync as existsSync5 } from "fs";
1623
+ import { join as join3, dirname as dirname5 } from "path";
1238
1624
  function resolveFailureLogPath() {
1239
1625
  const explicit = process.env.MASSU_HOOK_FAILURE_LOG;
1240
1626
  if (explicit) return explicit;
1241
1627
  let dir = process.cwd();
1242
1628
  for (let i = 0; i < 12; i++) {
1243
- if (existsSync4(join2(dir, ".massu")) || existsSync4(join2(dir, "massu.config.yaml"))) {
1244
- return join2(dir, ".massu", "hook-failures.jsonl");
1629
+ if (existsSync5(join3(dir, ".massu")) || existsSync5(join3(dir, "massu.config.yaml"))) {
1630
+ return join3(dir, ".massu", "hook-failures.jsonl");
1245
1631
  }
1246
- const parent = dirname3(dir);
1632
+ const parent = dirname5(dir);
1247
1633
  if (parent === dir) break;
1248
1634
  dir = parent;
1249
1635
  }
1250
- return join2(process.cwd(), ".massu", "hook-failures.jsonl");
1636
+ return join3(process.cwd(), ".massu", "hook-failures.jsonl");
1251
1637
  }
1252
1638
  function recordHookFailure(hook, error, context) {
1253
1639
  const record = {
@@ -1260,8 +1646,8 @@ function recordHookFailure(hook, error, context) {
1260
1646
  let wroteSomething = false;
1261
1647
  try {
1262
1648
  const path = resolveFailureLogPath();
1263
- mkdirSync3(dirname3(path), { recursive: true });
1264
- appendFileSync(path, JSON.stringify(record) + "\n", "utf-8");
1649
+ mkdirSync5(dirname5(path), { recursive: true });
1650
+ appendFileSync2(path, JSON.stringify(record) + "\n", "utf-8");
1265
1651
  wroteSomething = true;
1266
1652
  } catch {
1267
1653
  }
@@ -1304,9 +1690,9 @@ var init_hook_failure_signal = __esm({
1304
1690
  });
1305
1691
 
1306
1692
  // src/memory-embedder-tokenizer.ts
1307
- import { readFileSync as readFileSync3 } from "fs";
1693
+ import { readFileSync as readFileSync4 } from "fs";
1308
1694
  function loadVocab(vocabPath) {
1309
- const lines = readFileSync3(vocabPath, "utf-8").split("\n");
1695
+ const lines = readFileSync4(vocabPath, "utf-8").split("\n");
1310
1696
  const vocab = /* @__PURE__ */ new Map();
1311
1697
  for (let i = 0; i < lines.length; i++) {
1312
1698
  const tok = lines[i].replace(/\r$/, "");
@@ -1426,9 +1812,9 @@ var init_memory_embedder_tokenizer = __esm({
1426
1812
 
1427
1813
  // src/memory-embedder.ts
1428
1814
  import { fileURLToPath } from "url";
1429
- import { dirname as dirname4, join as join3 } from "path";
1430
- import { existsSync as existsSync5 } from "fs";
1431
- import { createRequire } from "module";
1815
+ import { dirname as dirname6, join as join4 } from "path";
1816
+ import { existsSync as existsSync6 } from "fs";
1817
+ import { createRequire as createRequire2 } from "module";
1432
1818
  function getActiveEmbedModel() {
1433
1819
  return _activeModel;
1434
1820
  }
@@ -1449,21 +1835,21 @@ function embeddingsDisabled() {
1449
1835
  }
1450
1836
  function resolveModelDir() {
1451
1837
  try {
1452
- let dir = dirname4(fileURLToPath(import.meta.url));
1838
+ let dir = dirname6(fileURLToPath(import.meta.url));
1453
1839
  let root = null;
1454
1840
  for (let i = 0; i < 8; i++) {
1455
- if (existsSync5(join3(dir, "package.json"))) {
1841
+ if (existsSync6(join4(dir, "package.json"))) {
1456
1842
  root = dir;
1457
1843
  break;
1458
1844
  }
1459
- const parent = dirname4(dir);
1845
+ const parent = dirname6(dir);
1460
1846
  if (parent === dir) break;
1461
1847
  dir = parent;
1462
1848
  }
1463
1849
  if (!root) return null;
1464
1850
  for (const rel of ["dist/embedder", "assets/embedder"]) {
1465
- const candidate = join3(root, rel);
1466
- if (existsSync5(join3(candidate, "model_quantized.onnx"))) return candidate;
1851
+ const candidate = join4(root, rel);
1852
+ if (existsSync6(join4(candidate, "model_quantized.onnx"))) return candidate;
1467
1853
  }
1468
1854
  return null;
1469
1855
  } catch {
@@ -1472,9 +1858,9 @@ function resolveModelDir() {
1472
1858
  }
1473
1859
  function resolveWasmDir() {
1474
1860
  try {
1475
- const req = createRequire(import.meta.url);
1476
- const main2 = req.resolve(ORT_PKG);
1477
- return dirname4(main2);
1861
+ const req2 = createRequire2(import.meta.url);
1862
+ const main2 = req2.resolve(ORT_PKG);
1863
+ return dirname6(main2);
1478
1864
  } catch {
1479
1865
  return null;
1480
1866
  }
@@ -1494,8 +1880,8 @@ async function getSession() {
1494
1880
  ort.env.wasm.proxy = false;
1495
1881
  ort.env.wasm.wasmPaths = wasmDir.endsWith("/") ? wasmDir : wasmDir + "/";
1496
1882
  _ortTensor = ort.Tensor;
1497
- const modelPath = join3(modelDir, "model_quantized.onnx");
1498
- const vocabPath = join3(modelDir, "vocab.txt");
1883
+ const modelPath = join4(modelDir, "model_quantized.onnx");
1884
+ const vocabPath = join4(modelDir, "vocab.txt");
1499
1885
  _vocab = loadVocab(vocabPath);
1500
1886
  const session = await ort.InferenceSession.create(modelPath, {
1501
1887
  executionProviders: ["wasm"],
@@ -1847,9 +2233,8 @@ __export(memory_db_exports, {
1847
2233
  upsertObservationEmbedding: () => upsertObservationEmbedding,
1848
2234
  usageWarmupElapsed: () => usageWarmupElapsed
1849
2235
  });
1850
- import Database2 from "better-sqlite3";
1851
- import { dirname as dirname5, basename as basename2 } from "path";
1852
- import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
2236
+ import { dirname as dirname7, basename as basename2 } from "path";
2237
+ import { existsSync as existsSync7, mkdirSync as mkdirSync6 } from "fs";
1853
2238
  function sanitizeFts5Query(raw) {
1854
2239
  const trimmed = raw.trim();
1855
2240
  if (!trimmed) return '""';
@@ -1865,12 +2250,12 @@ function sanitizeFts5QueryOr(raw) {
1865
2250
  }
1866
2251
  function getMemoryDb() {
1867
2252
  const dbPath = getResolvedPaths().memoryDbPath;
1868
- const dir = dirname5(dbPath);
1869
- if (!existsSync6(dir)) {
1870
- mkdirSync4(dir, { recursive: true });
2253
+ const dir = dirname7(dbPath);
2254
+ if (!existsSync7(dir)) {
2255
+ mkdirSync6(dir, { recursive: true });
1871
2256
  }
1872
- const preExisting = existsSync6(dbPath);
1873
- const db = new Database2(dbPath);
2257
+ const preExisting = existsSync7(dbPath);
2258
+ const db = openDatabase(dbPath);
1874
2259
  db.pragma("journal_mode = WAL");
1875
2260
  db.pragma("foreign_keys = ON");
1876
2261
  const onDisk = db.pragma("user_version", { simple: true });
@@ -3576,6 +3961,7 @@ var MEMORY_SCHEMA_VERSION, TOOL_COST_EVENTS_RETENTION_DAYS, MAX_DRAFT_TEXT_LEN,
3576
3961
  var init_memory_db = __esm({
3577
3962
  "src/memory-db.ts"() {
3578
3963
  "use strict";
3964
+ init_sqlite_loader();
3579
3965
  init_config();
3580
3966
  init_memory_vector();
3581
3967
  init_db_backup();
@@ -3596,8 +3982,8 @@ var init_memory_db = __esm({
3596
3982
  });
3597
3983
 
3598
3984
  // src/memory-file-ingest.ts
3599
- import { readFileSync as readFileSync4, existsSync as existsSync7, readdirSync as readdirSync2 } from "fs";
3600
- import { join as join4 } from "path";
3985
+ import { readFileSync as readFileSync5, existsSync as existsSync8, readdirSync as readdirSync2 } from "fs";
3986
+ import { join as join5 } from "path";
3601
3987
  import { parse as parseYaml2 } from "yaml";
3602
3988
  import { basename as pathBasename } from "path";
3603
3989
  import { createHash } from "crypto";
@@ -3703,8 +4089,8 @@ function upsertMemoryFileMirror(db, f2) {
3703
4089
  return "inserted";
3704
4090
  }
3705
4091
  function ingestMemoryFile(db, sessionId, filePath) {
3706
- if (!existsSync7(filePath)) return "skipped";
3707
- const content = readFileSync4(filePath, "utf-8");
4092
+ if (!existsSync8(filePath)) return "skipped";
4093
+ const content = readFileSync5(filePath, "utf-8");
3708
4094
  if (Buffer.byteLength(content, "utf-8") > MAX_MEMORY_FILE_BYTES) {
3709
4095
  process.stderr.write(
3710
4096
  `[massu] memory file exceeds ${MAX_MEMORY_FILE_BYTES} bytes, not ingested: ${filePath}
@@ -3774,14 +4160,14 @@ ${body}` : body;
3774
4160
  }
3775
4161
  function backfillMemoryFiles(db, memoryDir, sessionId) {
3776
4162
  const stats = { inserted: 0, updated: 0, skipped: 0, total: 0 };
3777
- if (!existsSync7(memoryDir)) return stats;
4163
+ if (!existsSync8(memoryDir)) return stats;
3778
4164
  const files = readdirSync2(memoryDir).filter(
3779
4165
  (f2) => f2.endsWith(".md") && f2 !== "MEMORY.md"
3780
4166
  );
3781
4167
  stats.total = files.length;
3782
4168
  const sid = sessionId ?? `backfill-${Date.now()}`;
3783
4169
  for (const file of files) {
3784
- const result = ingestMemoryFile(db, sid, join4(memoryDir, file));
4170
+ const result = ingestMemoryFile(db, sid, join5(memoryDir, file));
3785
4171
  stats[result]++;
3786
4172
  }
3787
4173
  return stats;
@@ -3990,16 +4376,16 @@ var init_template_engine = __esm({
3990
4376
  // src/lib/settings-local.ts
3991
4377
  import {
3992
4378
  closeSync,
3993
- existsSync as existsSync8,
4379
+ existsSync as existsSync9,
3994
4380
  fsyncSync,
3995
- mkdirSync as mkdirSync5,
4381
+ mkdirSync as mkdirSync7,
3996
4382
  openSync,
3997
- readFileSync as readFileSync5,
4383
+ readFileSync as readFileSync6,
3998
4384
  renameSync,
3999
- rmSync as rmSync3,
4385
+ rmSync as rmSync4,
4000
4386
  writeSync
4001
4387
  } from "fs";
4002
- import { dirname as dirname6, resolve as resolve5 } from "path";
4388
+ import { dirname as dirname8, resolve as resolve5 } from "path";
4003
4389
  function atomicWriteFile(targetPath, content, mode = 420) {
4004
4390
  const tmpPath = `${targetPath}.${process.pid}.tmp`;
4005
4391
  try {
@@ -4013,9 +4399,9 @@ function atomicWriteFile(targetPath, content, mode = 420) {
4013
4399
  }
4014
4400
  renameSync(tmpPath, targetPath);
4015
4401
  } catch (err) {
4016
- if (existsSync8(tmpPath)) {
4402
+ if (existsSync9(tmpPath)) {
4017
4403
  try {
4018
- rmSync3(tmpPath, { force: true });
4404
+ rmSync4(tmpPath, { force: true });
4019
4405
  } catch {
4020
4406
  }
4021
4407
  }
@@ -4023,11 +4409,11 @@ function atomicWriteFile(targetPath, content, mode = 420) {
4023
4409
  }
4024
4410
  }
4025
4411
  function readSettingsAtPath(absolutePath) {
4026
- if (!existsSync8(absolutePath)) {
4412
+ if (!existsSync9(absolutePath)) {
4027
4413
  return {};
4028
4414
  }
4029
4415
  try {
4030
- const raw = readFileSync5(absolutePath, "utf-8");
4416
+ const raw = readFileSync6(absolutePath, "utf-8");
4031
4417
  const parsed = JSON.parse(raw);
4032
4418
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
4033
4419
  return {};
@@ -4042,9 +4428,9 @@ function readSettingsLocal(claudeDir) {
4042
4428
  }
4043
4429
  function writeSettingsLocalAtomic(claudeDir, settings) {
4044
4430
  const targetPath = resolve5(claudeDir, "settings.local.json");
4045
- const dir = dirname6(targetPath);
4046
- if (!existsSync8(dir)) {
4047
- mkdirSync5(dir, { recursive: true });
4431
+ const dir = dirname8(targetPath);
4432
+ if (!existsSync9(dir)) {
4433
+ mkdirSync7(dir, { recursive: true });
4048
4434
  }
4049
4435
  const content = JSON.stringify(settings, null, 2) + "\n";
4050
4436
  atomicWriteFile(targetPath, content);
@@ -4058,7 +4444,7 @@ var init_settings_local = __esm({
4058
4444
  // src/permissions.ts
4059
4445
  import { createHash as createHash2 } from "crypto";
4060
4446
  import { homedir as homedir4 } from "os";
4061
- import { join as join5 } from "path";
4447
+ import { join as join6 } from "path";
4062
4448
  function canonicalJson(value) {
4063
4449
  if (value === null || typeof value !== "object") {
4064
4450
  return JSON.stringify(value);
@@ -4097,7 +4483,7 @@ function detectInvalidDefaultMode(settings) {
4097
4483
  return { invalid: false };
4098
4484
  }
4099
4485
  function readGlobalSettings() {
4100
- return readSettingsAtPath(join5(homedir4(), ".claude", "settings.json"));
4486
+ return readSettingsAtPath(join6(homedir4(), ".claude", "settings.json"));
4101
4487
  }
4102
4488
  function mergedPermissionState(global2, local, canonical) {
4103
4489
  const globalPerm = global2.permissions ?? {};
@@ -4285,17 +4671,17 @@ __export(install_commands_exports, {
4285
4671
  syncDirectory: () => syncDirectory
4286
4672
  });
4287
4673
  import {
4288
- existsSync as existsSync9,
4289
- readFileSync as readFileSync6,
4290
- mkdirSync as mkdirSync6,
4674
+ existsSync as existsSync10,
4675
+ readFileSync as readFileSync7,
4676
+ mkdirSync as mkdirSync8,
4291
4677
  readdirSync as readdirSync3,
4292
4678
  statSync as statSync2
4293
4679
  } from "fs";
4294
- import { resolve as resolve6, dirname as dirname7, join as join6 } from "path";
4680
+ import { resolve as resolve6, dirname as dirname9, join as join7 } from "path";
4295
4681
  import { fileURLToPath as fileURLToPath2 } from "url";
4296
4682
  import { createHash as createHash3 } from "crypto";
4297
4683
  function dirHoldsAssets(dir) {
4298
- if (!existsSync9(dir)) return false;
4684
+ if (!existsSync10(dir)) return false;
4299
4685
  try {
4300
4686
  return readdirSync3(dir).some(
4301
4687
  (e2) => e2.endsWith(".md") || statSync2(resolve6(dir, e2)).isDirectory()
@@ -4330,10 +4716,10 @@ function canonicalizeOwned(content) {
4330
4716
  }
4331
4717
  function massuOwnedSourceIsValid(resolvedSourcePath, content) {
4332
4718
  const sidecar = `${resolvedSourcePath}.sha256`;
4333
- if (!existsSync9(sidecar)) return false;
4719
+ if (!existsSync10(sidecar)) return false;
4334
4720
  let expected;
4335
4721
  try {
4336
- expected = readFileSync6(sidecar, "utf-8").trim();
4722
+ expected = readFileSync7(sidecar, "utf-8").trim();
4337
4723
  } catch {
4338
4724
  return false;
4339
4725
  }
@@ -4344,11 +4730,11 @@ function hashContent(content) {
4344
4730
  }
4345
4731
  function loadManifest(claudeDir) {
4346
4732
  const path = resolve6(claudeDir, MANIFEST_RELPATH);
4347
- if (!existsSync9(path)) {
4733
+ if (!existsSync10(path)) {
4348
4734
  return emptyManifest();
4349
4735
  }
4350
4736
  try {
4351
- const raw = readFileSync6(path, "utf-8");
4737
+ const raw = readFileSync7(path, "utf-8");
4352
4738
  const parsed = JSON.parse(raw);
4353
4739
  if (!parsed || typeof parsed !== "object" || !parsed.entries) {
4354
4740
  return emptyManifest();
@@ -4360,8 +4746,8 @@ function loadManifest(claudeDir) {
4360
4746
  }
4361
4747
  function saveManifest(claudeDir, manifest) {
4362
4748
  const dir = resolve6(claudeDir, ".massu");
4363
- if (!existsSync9(dir)) {
4364
- mkdirSync6(dir, { recursive: true });
4749
+ if (!existsSync10(dir)) {
4750
+ mkdirSync8(dir, { recursive: true });
4365
4751
  }
4366
4752
  const finalPath = resolve6(dir, "install-manifest.json");
4367
4753
  manifest.generatedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -4426,17 +4812,17 @@ function pickVariant(baseName, sourceDir, framework) {
4426
4812
  for (const cand of candidates) {
4427
4813
  if (cand.subFramework) {
4428
4814
  const subPath = resolve6(sourceDir, `${baseName}.${cand.lang}-${cand.subFramework}.md`);
4429
- if (existsSync9(subPath)) {
4815
+ if (existsSync10(subPath)) {
4430
4816
  return { kind: "hit", suffix: `.${cand.lang}-${cand.subFramework}` };
4431
4817
  }
4432
4818
  }
4433
4819
  const langPath = resolve6(sourceDir, `${baseName}.${cand.lang}.md`);
4434
- if (existsSync9(langPath)) {
4820
+ if (existsSync10(langPath)) {
4435
4821
  return { kind: "hit", suffix: `.${cand.lang}` };
4436
4822
  }
4437
4823
  }
4438
4824
  const defaultPath = resolve6(sourceDir, `${baseName}.md`);
4439
- if (existsSync9(defaultPath)) {
4825
+ if (existsSync10(defaultPath)) {
4440
4826
  return { kind: "hit", suffix: "" };
4441
4827
  }
4442
4828
  if (framework.type === "multi" && !framework.primary) {
@@ -4452,8 +4838,8 @@ function isVariantFilename(entry) {
4452
4838
  }
4453
4839
  function syncDirectory(sourceDir, targetDir, framework, manifest, manifestKeyPrefix, topLevel = true, templateVars = {}) {
4454
4840
  const stats = { installed: 0, updated: 0, skipped: 0, kept: 0 };
4455
- if (!existsSync9(targetDir)) {
4456
- mkdirSync6(targetDir, { recursive: true });
4841
+ if (!existsSync10(targetDir)) {
4842
+ mkdirSync8(targetDir, { recursive: true });
4457
4843
  }
4458
4844
  const entries = readdirSync3(sourceDir);
4459
4845
  for (const entry of entries) {
@@ -4490,12 +4876,12 @@ function syncDirectory(sourceDir, targetDir, framework, manifest, manifestKeyPre
4490
4876
  sourceFilename = suffix === "" ? `${baseName}.md` : `${baseName}${suffix}.md`;
4491
4877
  }
4492
4878
  const resolvedSourcePath = resolve6(sourceDir, sourceFilename);
4493
- if (!existsSync9(resolvedSourcePath)) {
4879
+ if (!existsSync10(resolvedSourcePath)) {
4494
4880
  continue;
4495
4881
  }
4496
4882
  const targetFilename = topLevel ? `${baseName}.md` : entry;
4497
4883
  const targetPath = resolve6(targetDir, targetFilename);
4498
- const rawContent = readFileSync6(resolvedSourcePath, "utf-8");
4884
+ const rawContent = readFileSync7(resolvedSourcePath, "utf-8");
4499
4885
  let sourceContent;
4500
4886
  try {
4501
4887
  sourceContent = renderTemplate(rawContent, templateVars);
@@ -4513,11 +4899,11 @@ function syncDirectory(sourceDir, targetDir, framework, manifest, manifestKeyPre
4513
4899
  const sourceHash = hashContent(sourceContent);
4514
4900
  const manifestKey = manifestKeyPrefix === "" ? targetFilename : `${manifestKeyPrefix}/${targetFilename}`;
4515
4901
  const lastInstalledHash = manifest.entries[manifestKey];
4516
- if (existsSync9(targetPath)) {
4902
+ if (existsSync10(targetPath)) {
4517
4903
  let existingContent;
4518
4904
  try {
4519
4905
  if (!statSync2(targetPath).isFile()) throw new Error("not a regular file");
4520
- existingContent = readFileSync6(targetPath, "utf-8");
4906
+ existingContent = readFileSync7(targetPath, "utf-8");
4521
4907
  } catch (err) {
4522
4908
  process.stderr.write(
4523
4909
  `massu: skipping ${manifestKey}: target is not a readable file (${err instanceof Error ? err.message : String(err)}). Remove it and re-install.
@@ -4600,8 +4986,8 @@ function installCommands(projectRoot, opts = {}) {
4600
4986
  const claudeDirName = getConfig().conventions?.claudeDirName ?? ".claude";
4601
4987
  const claudeDir = resolve6(projectRoot, claudeDirName);
4602
4988
  const targetDir = resolve6(claudeDir, "commands");
4603
- if (!existsSync9(targetDir)) {
4604
- mkdirSync6(targetDir, { recursive: true });
4989
+ if (!existsSync10(targetDir)) {
4990
+ mkdirSync8(targetDir, { recursive: true });
4605
4991
  }
4606
4992
  const sourceDir = resolveAssetDir("commands");
4607
4993
  if (!sourceDir) {
@@ -4730,7 +5116,7 @@ var init_install_commands = __esm({
4730
5116
  init_settings_local();
4731
5117
  init_permissions();
4732
5118
  __filename = fileURLToPath2(import.meta.url);
4733
- __dirname = dirname7(__filename);
5119
+ __dirname = dirname9(__filename);
4734
5120
  ASSET_TYPES = [
4735
5121
  { name: "commands", targetSubdir: "commands", description: "slash commands" },
4736
5122
  { name: "agents", targetSubdir: "agents", description: "agent definitions" },
@@ -4739,7 +5125,7 @@ var init_install_commands = __esm({
4739
5125
  { name: "reference", targetSubdir: "reference", description: "reference files" }
4740
5126
  ];
4741
5127
  MANIFEST_VERSION = 1;
4742
- MANIFEST_RELPATH = join6(".massu", "install-manifest.json");
5128
+ MANIFEST_RELPATH = join7(".massu", "install-manifest.json");
4743
5129
  MASSU_OWNED_PATHS = ["commands/_verification-laws.md"];
4744
5130
  PASSTHROUGH_LANG_KEYS = [
4745
5131
  "typescript",
@@ -4952,17 +5338,17 @@ var init_manifest_registry = __esm({
4952
5338
  });
4953
5339
 
4954
5340
  // src/detect/package-detector.ts
4955
- import { readFileSync as readFileSync7, existsSync as existsSync10, statSync as statSync3, lstatSync, readdirSync as readdirSync4 } from "fs";
4956
- import { join as join7, relative as relative2 } from "path";
5341
+ import { readFileSync as readFileSync8, existsSync as existsSync11, statSync as statSync3, lstatSync, readdirSync as readdirSync4 } from "fs";
5342
+ import { join as join8, relative as relative2 } from "path";
4957
5343
  import { parse as parseToml } from "smol-toml";
4958
5344
  function safeRead(path) {
4959
5345
  try {
4960
- if (!existsSync10(path)) return null;
5346
+ if (!existsSync11(path)) return null;
4961
5347
  const ls = lstatSync(path);
4962
5348
  if (ls.isSymbolicLink()) return null;
4963
5349
  const st = statSync3(path);
4964
5350
  if (!st.isFile()) return null;
4965
- return readFileSync7(path, "utf-8");
5351
+ return readFileSync8(path, "utf-8");
4966
5352
  } catch {
4967
5353
  return null;
4968
5354
  }
@@ -4993,7 +5379,7 @@ function parsePackageJson(path, directory, root, warnings) {
4993
5379
  const peer = Object.keys(
4994
5380
  pkg.peerDependencies ?? {}
4995
5381
  );
4996
- const hasTs = deps.includes("typescript") || devDeps.includes("typescript") || existsSync10(join7(directory, "tsconfig.json"));
5382
+ const hasTs = deps.includes("typescript") || devDeps.includes("typescript") || existsSync11(join8(directory, "tsconfig.json"));
4997
5383
  const language = hasTs ? "typescript" : "javascript";
4998
5384
  const scripts = Object.keys(
4999
5385
  pkg.scripts ?? {}
@@ -5419,8 +5805,8 @@ function detectManifestsInDir(dir, root, warnings) {
5419
5805
  let dirEntries = null;
5420
5806
  for (const entry of getManifestRegistry2()) {
5421
5807
  if (!entry.pattern.startsWith("*")) {
5422
- const path = join7(dir, entry.pattern);
5423
- if (!existsSync10(path)) continue;
5808
+ const path = join8(dir, entry.pattern);
5809
+ if (!existsSync11(path)) continue;
5424
5810
  const m3 = entry.parse(path, dir, root, warnings);
5425
5811
  if (m3 !== null) out.push(m3);
5426
5812
  } else {
@@ -5433,8 +5819,8 @@ function detectManifestsInDir(dir, root, warnings) {
5433
5819
  }
5434
5820
  for (const fname of dirEntries) {
5435
5821
  if (!matchManifestPattern2(fname, entry.pattern)) continue;
5436
- const path = join7(dir, fname);
5437
- if (!existsSync10(path)) continue;
5822
+ const path = join8(dir, fname);
5823
+ if (!existsSync11(path)) continue;
5438
5824
  const m3 = entry.parse(path, dir, root, warnings);
5439
5825
  if (m3 !== null) out.push(m3);
5440
5826
  }
@@ -5444,7 +5830,7 @@ function detectManifestsInDir(dir, root, warnings) {
5444
5830
  }
5445
5831
  function listSubdirs(dir) {
5446
5832
  try {
5447
- return readdirSync4(dir, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !IGNORED_DIRS.has(e2.name)).map((e2) => join7(dir, e2.name));
5833
+ return readdirSync4(dir, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !IGNORED_DIRS.has(e2.name)).map((e2) => join8(dir, e2.name));
5448
5834
  } catch {
5449
5835
  return [];
5450
5836
  }
@@ -5454,8 +5840,8 @@ function detectPackageManifests(projectRoot) {
5454
5840
  const manifests = [];
5455
5841
  manifests.push(...detectManifestsInDir(projectRoot, projectRoot, warnings));
5456
5842
  for (const ws of WORKSPACE_DIRS) {
5457
- const wsRoot = join7(projectRoot, ws);
5458
- if (!existsSync10(wsRoot)) continue;
5843
+ const wsRoot = join8(projectRoot, ws);
5844
+ if (!existsSync11(wsRoot)) continue;
5459
5845
  for (const sub of listSubdirs(wsRoot)) {
5460
5846
  manifests.push(...detectManifestsInDir(sub, projectRoot, warnings));
5461
5847
  for (const sub2 of listSubdirs(sub)) {
@@ -5702,20 +6088,20 @@ var init_framework_detector = __esm({
5702
6088
 
5703
6089
  // src/lib/safe-write.ts
5704
6090
  import {
5705
- writeFileSync as writeFileSync2,
6091
+ writeFileSync as writeFileSync3,
5706
6092
  renameSync as renameSync2,
5707
6093
  openSync as openSync2,
5708
6094
  fsyncSync as fsyncSync2,
5709
6095
  closeSync as closeSync2,
5710
- existsSync as existsSync11,
6096
+ existsSync as existsSync12,
5711
6097
  realpathSync,
5712
6098
  unlinkSync as unlinkSync2,
5713
- accessSync,
6099
+ accessSync as accessSync2,
5714
6100
  statSync as statSync4,
5715
- chmodSync as chmodSync2,
6101
+ chmodSync as chmodSync3,
5716
6102
  constants
5717
6103
  } from "fs";
5718
- import { dirname as dirname8, resolve as resolve7, relative as relative3, isAbsolute, basename as basename3, sep } from "path";
6104
+ import { dirname as dirname10, resolve as resolve7, relative as relative3, isAbsolute, basename as basename3, sep } from "path";
5719
6105
  import { createHash as createHash4 } from "crypto";
5720
6106
  function assertContainedIn(rootDir, candidate, opts = {}) {
5721
6107
  if (candidate.includes("\0")) {
@@ -5747,8 +6133,8 @@ function isContainedIn(rootDir, candidate, opts = {}) {
5747
6133
  if (rel === "" && !opts.allowRoot) return false;
5748
6134
  if (rel.startsWith("..") || isAbsolute(rel)) return false;
5749
6135
  let probe = abs;
5750
- while (!existsSync11(probe) && probe.length > 1) {
5751
- const parent = dirname8(probe);
6136
+ while (!existsSync12(probe) && probe.length > 1) {
6137
+ const parent = dirname10(probe);
5752
6138
  if (parent === probe) break;
5753
6139
  probe = parent;
5754
6140
  }
@@ -5765,17 +6151,17 @@ function isContainedIn(rootDir, candidate, opts = {}) {
5765
6151
  return !realRel.startsWith("..") && !isAbsolute(realRel);
5766
6152
  }
5767
6153
  function atomicWriteFileSync(destPath, contents) {
5768
- const dir = dirname8(destPath);
6154
+ const dir = dirname10(destPath);
5769
6155
  const tmp = resolve7(dir, `.${basename3(destPath)}.massu-tmp-${process.pid}`);
5770
6156
  let destMode;
5771
- if (existsSync11(destPath)) {
5772
- accessSync(destPath, constants.W_OK);
6157
+ if (existsSync12(destPath)) {
6158
+ accessSync2(destPath, constants.W_OK);
5773
6159
  destMode = statSync4(destPath).mode & 511;
5774
6160
  }
5775
6161
  let fd;
5776
6162
  try {
5777
- writeFileSync2(tmp, contents, "utf-8");
5778
- if (destMode !== void 0) chmodSync2(tmp, destMode);
6163
+ writeFileSync3(tmp, contents, "utf-8");
6164
+ if (destMode !== void 0) chmodSync3(tmp, destMode);
5779
6165
  fd = openSync2(tmp, "r+");
5780
6166
  fsyncSync2(fd);
5781
6167
  closeSync2(fd);
@@ -5789,7 +6175,7 @@ function atomicWriteFileSync(destPath, contents) {
5789
6175
  }
5790
6176
  }
5791
6177
  try {
5792
- if (existsSync11(tmp)) unlinkSync2(tmp);
6178
+ if (existsSync12(tmp)) unlinkSync2(tmp);
5793
6179
  } catch {
5794
6180
  }
5795
6181
  throw err;
@@ -11800,38 +12186,38 @@ var init_source_dir_detector = __esm({
11800
12186
  });
11801
12187
 
11802
12188
  // src/detect/monorepo-detector.ts
11803
- import { readFileSync as readFileSync8, existsSync as existsSync12, statSync as statSync5, lstatSync as lstatSync2, readdirSync as readdirSync5 } from "fs";
11804
- import { join as join8, relative as relative4 } from "path";
12189
+ import { readFileSync as readFileSync9, existsSync as existsSync13, statSync as statSync5, lstatSync as lstatSync2, readdirSync as readdirSync5 } from "fs";
12190
+ import { join as join9, relative as relative4 } from "path";
11805
12191
  import { parse as parseYaml3 } from "yaml";
11806
12192
  import { parse as parseToml2 } from "smol-toml";
11807
12193
  function safeReadText(path) {
11808
12194
  try {
11809
- if (!existsSync12(path)) return null;
12195
+ if (!existsSync13(path)) return null;
11810
12196
  const ls = lstatSync2(path);
11811
12197
  if (ls.isSymbolicLink()) return null;
11812
12198
  const st = statSync5(path);
11813
12199
  if (!st.isFile()) return null;
11814
- return readFileSync8(path, "utf-8");
12200
+ return readFileSync9(path, "utf-8");
11815
12201
  } catch {
11816
12202
  return null;
11817
12203
  }
11818
12204
  }
11819
12205
  function firstManifestIn(dir) {
11820
12206
  for (const m3 of MANIFEST_PRIORITY) {
11821
- if (existsSync12(join8(dir, m3))) return m3;
12207
+ if (existsSync13(join9(dir, m3))) return m3;
11822
12208
  }
11823
12209
  return null;
11824
12210
  }
11825
12211
  function manifestName(dir, manifest) {
11826
12212
  try {
11827
12213
  if (manifest === "package.json") {
11828
- const raw = safeReadText(join8(dir, "package.json"));
12214
+ const raw = safeReadText(join9(dir, "package.json"));
11829
12215
  if (!raw) return null;
11830
12216
  const pkg = JSON.parse(raw);
11831
12217
  return typeof pkg.name === "string" ? pkg.name : null;
11832
12218
  }
11833
12219
  if (manifest === "pyproject.toml") {
11834
- const raw = safeReadText(join8(dir, "pyproject.toml"));
12220
+ const raw = safeReadText(join9(dir, "pyproject.toml"));
11835
12221
  if (!raw) return null;
11836
12222
  const toml = parseToml2(raw);
11837
12223
  const project = toml.project;
@@ -11842,7 +12228,7 @@ function manifestName(dir, manifest) {
11842
12228
  return null;
11843
12229
  }
11844
12230
  if (manifest === "Cargo.toml") {
11845
- const raw = safeReadText(join8(dir, "Cargo.toml"));
12231
+ const raw = safeReadText(join9(dir, "Cargo.toml"));
11846
12232
  if (!raw) return null;
11847
12233
  const toml = parseToml2(raw);
11848
12234
  const pkg = toml.package;
@@ -11850,7 +12236,7 @@ function manifestName(dir, manifest) {
11850
12236
  return null;
11851
12237
  }
11852
12238
  if (manifest === "go.mod") {
11853
- const raw = safeReadText(join8(dir, "go.mod"));
12239
+ const raw = safeReadText(join9(dir, "go.mod"));
11854
12240
  if (!raw) return null;
11855
12241
  for (const line of raw.split(/\r?\n/)) {
11856
12242
  const trimmed = line.trim();
@@ -11874,7 +12260,7 @@ function pkgFromDir(root, dir) {
11874
12260
  }
11875
12261
  function listSubdirs2(dir) {
11876
12262
  try {
11877
- return readdirSync5(dir, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !IGNORED_DIRS2.has(e2.name)).map((e2) => join8(dir, e2.name));
12263
+ return readdirSync5(dir, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !IGNORED_DIRS2.has(e2.name)).map((e2) => join9(dir, e2.name));
11878
12264
  } catch {
11879
12265
  return [];
11880
12266
  }
@@ -11882,8 +12268,8 @@ function listSubdirs2(dir) {
11882
12268
  function genericWorkspaces(root) {
11883
12269
  const out = [];
11884
12270
  for (const parent of CONVENTIONAL_WORKSPACE_PARENTS) {
11885
- const p19 = join8(root, parent);
11886
- if (!existsSync12(p19)) continue;
12271
+ const p19 = join9(root, parent);
12272
+ if (!existsSync13(p19)) continue;
11887
12273
  for (const sub of listSubdirs2(p19)) {
11888
12274
  const pkg = pkgFromDir(root, sub);
11889
12275
  if (pkg) out.push(pkg);
@@ -11892,7 +12278,7 @@ function genericWorkspaces(root) {
11892
12278
  return out;
11893
12279
  }
11894
12280
  function detectYarnWorkspaces(root) {
11895
- const raw = safeReadText(join8(root, "package.json"));
12281
+ const raw = safeReadText(join9(root, "package.json"));
11896
12282
  if (!raw) return null;
11897
12283
  let pkg;
11898
12284
  try {
@@ -11907,7 +12293,7 @@ function detectYarnWorkspaces(root) {
11907
12293
  return expandWorkspaceGlobs(root, globs);
11908
12294
  }
11909
12295
  function detectPnpmWorkspaces(root) {
11910
- const raw = safeReadText(join8(root, "pnpm-workspace.yaml"));
12296
+ const raw = safeReadText(join9(root, "pnpm-workspace.yaml"));
11911
12297
  if (!raw) return null;
11912
12298
  try {
11913
12299
  const parsed = parseYaml3(raw);
@@ -11923,8 +12309,8 @@ function expandWorkspaceGlobs(root, globs) {
11923
12309
  for (const pattern of globs) {
11924
12310
  const parts = pattern.split("/");
11925
12311
  if (parts.length === 2 && (parts[1] === "*" || parts[1] === "**")) {
11926
- const parent = join8(root, parts[0]);
11927
- if (!existsSync12(parent)) continue;
12312
+ const parent = join9(root, parts[0]);
12313
+ if (!existsSync13(parent)) continue;
11928
12314
  for (const sub of listSubdirs2(parent)) {
11929
12315
  const pkg = pkgFromDir(root, sub);
11930
12316
  if (pkg && !seen.has(pkg.path)) {
@@ -11934,8 +12320,8 @@ function expandWorkspaceGlobs(root, globs) {
11934
12320
  }
11935
12321
  continue;
11936
12322
  }
11937
- const direct = join8(root, pattern);
11938
- if (existsSync12(direct)) {
12323
+ const direct = join9(root, pattern);
12324
+ if (existsSync13(direct)) {
11939
12325
  const pkg = pkgFromDir(root, direct);
11940
12326
  if (pkg && !seen.has(pkg.path)) {
11941
12327
  seen.add(pkg.path);
@@ -11946,16 +12332,16 @@ function expandWorkspaceGlobs(root, globs) {
11946
12332
  return out;
11947
12333
  }
11948
12334
  function hasTurbo(root) {
11949
- return existsSync12(join8(root, "turbo.json"));
12335
+ return existsSync13(join9(root, "turbo.json"));
11950
12336
  }
11951
12337
  function hasNx(root) {
11952
- return existsSync12(join8(root, "nx.json"));
12338
+ return existsSync13(join9(root, "nx.json"));
11953
12339
  }
11954
12340
  function hasLerna(root) {
11955
- return existsSync12(join8(root, "lerna.json"));
12341
+ return existsSync13(join9(root, "lerna.json"));
11956
12342
  }
11957
12343
  function hasBazel(root) {
11958
- return existsSync12(join8(root, "WORKSPACE")) || existsSync12(join8(root, "WORKSPACE.bazel")) || existsSync12(join8(root, "MODULE.bazel"));
12344
+ return existsSync13(join9(root, "WORKSPACE")) || existsSync13(join9(root, "WORKSPACE.bazel")) || existsSync13(join9(root, "MODULE.bazel"));
11959
12345
  }
11960
12346
  function detectMonorepo(projectRoot) {
11961
12347
  const nested = [];
@@ -12146,8 +12532,8 @@ var init_vr_command_map = __esm({
12146
12532
  });
12147
12533
 
12148
12534
  // src/detect/domain-inferrer.ts
12149
- import { existsSync as existsSync13, readdirSync as readdirSync6 } from "fs";
12150
- import { join as join9 } from "path";
12535
+ import { existsSync as existsSync14, readdirSync as readdirSync6 } from "fs";
12536
+ import { join as join10 } from "path";
12151
12537
  function titleCase(s) {
12152
12538
  if (!s) return s;
12153
12539
  return s.split(/[-_\s]+/).filter(Boolean).map((p19) => p19.charAt(0).toUpperCase() + p19.slice(1)).join(" ");
@@ -12167,8 +12553,8 @@ function topLevelSrcSubdirs(root, sourceDirs) {
12167
12553
  const effective = sourceDirs.length > 0 ? sourceDirs : ["src"];
12168
12554
  const seen = /* @__PURE__ */ new Set();
12169
12555
  for (const rel of effective) {
12170
- const abs = join9(root, rel);
12171
- if (!existsSync13(abs)) continue;
12556
+ const abs = join10(root, rel);
12557
+ if (!existsSync14(abs)) continue;
12172
12558
  try {
12173
12559
  for (const e2 of readdirSync6(abs, { withFileTypes: true })) {
12174
12560
  if (!e2.isDirectory()) continue;
@@ -12255,8 +12641,8 @@ var init_domain_inferrer = __esm({
12255
12641
  });
12256
12642
 
12257
12643
  // src/detect/regex-fallback.ts
12258
- import { existsSync as existsSync14, readdirSync as readdirSync7, readFileSync as readFileSync9, statSync as statSync6 } from "fs";
12259
- import { resolve as resolve8, join as join10, basename as basename4 } from "path";
12644
+ import { existsSync as existsSync15, readdirSync as readdirSync7, readFileSync as readFileSync10, statSync as statSync6 } from "fs";
12645
+ import { resolve as resolve8, join as join11, basename as basename4 } from "path";
12260
12646
  function introspectPython(detection, projectRoot) {
12261
12647
  const sourceDir = resolveSourceDir(detection, "python", projectRoot);
12262
12648
  if (!sourceDir) return null;
@@ -12423,9 +12809,9 @@ function resolveSourceDir(detection, lang, projectRoot) {
12423
12809
  if (list.length > 0) {
12424
12810
  const first = list[0];
12425
12811
  const abs = resolve8(projectRoot, first);
12426
- return existsSync14(abs) ? abs : null;
12812
+ return existsSync15(abs) ? abs : null;
12427
12813
  }
12428
- return existsSync14(projectRoot) ? projectRoot : null;
12814
+ return existsSync15(projectRoot) ? projectRoot : null;
12429
12815
  }
12430
12816
  function sampleFiles(dir, nameRegex, pathFilter) {
12431
12817
  const out = [];
@@ -12445,7 +12831,7 @@ function sampleFiles(dir, nameRegex, pathFilter) {
12445
12831
  if (entry === "__pycache__") continue;
12446
12832
  if (entry === "venv" || entry === ".venv") continue;
12447
12833
  if (entry === "dist" || entry === "build") continue;
12448
- const child = join10(path, entry);
12834
+ const child = join11(path, entry);
12449
12835
  let st;
12450
12836
  try {
12451
12837
  st = statSync6(child);
@@ -12470,7 +12856,7 @@ function readSafe(path) {
12470
12856
  try {
12471
12857
  const st = statSync6(path);
12472
12858
  if (st.size > MAX_FILE_BYTES) return null;
12473
- return readFileSync9(path, "utf-8");
12859
+ return readFileSync10(path, "utf-8");
12474
12860
  } catch {
12475
12861
  return null;
12476
12862
  }
@@ -12551,8 +12937,8 @@ var init_parse_guard = __esm({
12551
12937
 
12552
12938
  // src/detect/adapters/runner.ts
12553
12939
  import { basename as basename5, relative as relative5 } from "path";
12554
- import { existsSync as existsSync15, readdirSync as readdirSync8, readFileSync as readFileSync10, statSync as statSync7 } from "fs";
12555
- import { join as join11 } from "path";
12940
+ import { existsSync as existsSync16, readdirSync as readdirSync8, readFileSync as readFileSync11, statSync as statSync7 } from "fs";
12941
+ import { join as join12 } from "path";
12556
12942
  async function runAdapters(adapters, rootDir, signals, options = {}) {
12557
12943
  const out = {
12558
12944
  byAdapter: {},
@@ -12649,7 +13035,7 @@ function buildDetectionSignals(rootDir) {
12649
13035
  for (const entry of readdirSync8(rootDir)) {
12650
13036
  if (entry.startsWith(".")) continue;
12651
13037
  try {
12652
- const st = statSync7(join11(rootDir, entry));
13038
+ const st = statSync7(join12(rootDir, entry));
12653
13039
  if (st.isDirectory()) presentDirs.add(entry);
12654
13040
  else if (st.isFile()) presentFiles.add(entry);
12655
13041
  } catch {
@@ -12658,14 +13044,14 @@ function buildDetectionSignals(rootDir) {
12658
13044
  } catch {
12659
13045
  }
12660
13046
  return {
12661
- packageJson: tryReadJson(join11(rootDir, "package.json")),
12662
- pyprojectToml: tryReadToml(join11(rootDir, "pyproject.toml")),
12663
- gemfile: tryReadString(join11(rootDir, "Gemfile")),
12664
- cargoToml: tryReadToml(join11(rootDir, "Cargo.toml")),
12665
- goMod: tryReadString(join11(rootDir, "go.mod")),
12666
- mixExs: tryReadString(join11(rootDir, "mix.exs")),
13047
+ packageJson: tryReadJson(join12(rootDir, "package.json")),
13048
+ pyprojectToml: tryReadToml(join12(rootDir, "pyproject.toml")),
13049
+ gemfile: tryReadString(join12(rootDir, "Gemfile")),
13050
+ cargoToml: tryReadToml(join12(rootDir, "Cargo.toml")),
13051
+ goMod: tryReadString(join12(rootDir, "go.mod")),
13052
+ mixExs: tryReadString(join12(rootDir, "mix.exs")),
12667
13053
  csproj: tryReadFirstCsproj(rootDir, presentFiles),
12668
- pomXml: tryReadString(join11(rootDir, "pom.xml")),
13054
+ pomXml: tryReadString(join12(rootDir, "pom.xml")),
12669
13055
  gradleBuild: tryReadGradleBuild(rootDir, presentFiles),
12670
13056
  presentDirs,
12671
13057
  presentFiles
@@ -12674,21 +13060,21 @@ function buildDetectionSignals(rootDir) {
12674
13060
  function tryReadFirstCsproj(rootDir, presentFiles) {
12675
13061
  const csprojNames = [...presentFiles].filter((f2) => f2.endsWith(".csproj")).sort();
12676
13062
  if (csprojNames.length === 0) return void 0;
12677
- return tryReadString(join11(rootDir, csprojNames[0]));
13063
+ return tryReadString(join12(rootDir, csprojNames[0]));
12678
13064
  }
12679
13065
  function tryReadGradleBuild(rootDir, presentFiles) {
12680
13066
  if (presentFiles.has("build.gradle.kts")) {
12681
- return tryReadString(join11(rootDir, "build.gradle.kts"));
13067
+ return tryReadString(join12(rootDir, "build.gradle.kts"));
12682
13068
  }
12683
13069
  if (presentFiles.has("build.gradle")) {
12684
- return tryReadString(join11(rootDir, "build.gradle"));
13070
+ return tryReadString(join12(rootDir, "build.gradle"));
12685
13071
  }
12686
13072
  return void 0;
12687
13073
  }
12688
13074
  function tryReadString(path) {
12689
- if (!existsSync15(path)) return void 0;
13075
+ if (!existsSync16(path)) return void 0;
12690
13076
  try {
12691
- return readFileSync10(path, "utf-8");
13077
+ return readFileSync11(path, "utf-8");
12692
13078
  } catch {
12693
13079
  return void 0;
12694
13080
  }
@@ -12805,24 +13191,24 @@ ${querySource}`
12805
13191
  // src/detect/adapters/tree-sitter-loader.ts
12806
13192
  import { createHash as createHash5 } from "crypto";
12807
13193
  import {
12808
- mkdirSync as mkdirSync7,
13194
+ mkdirSync as mkdirSync9,
12809
13195
  readdirSync as readdirSync9,
12810
- readFileSync as readFileSync11,
12811
- writeFileSync as writeFileSync3,
13196
+ readFileSync as readFileSync12,
13197
+ writeFileSync as writeFileSync4,
12812
13198
  renameSync as renameSync3,
12813
13199
  unlinkSync as unlinkSync3,
12814
13200
  lstatSync as lstatSync3,
12815
- chmodSync as chmodSync3,
13201
+ chmodSync as chmodSync4,
12816
13202
  utimesSync
12817
13203
  } from "fs";
12818
13204
  import { homedir as homedir5 } from "os";
12819
- import { dirname as dirname9, join as join12 } from "path";
13205
+ import { dirname as dirname11, join as join13 } from "path";
12820
13206
  import { Language, Parser } from "web-tree-sitter";
12821
13207
  function getCacheDir() {
12822
- return process.env.MASSU_WASM_CACHE_DIR ?? join12(homedir5(), ".massu", "wasm-cache");
13208
+ return process.env.MASSU_WASM_CACHE_DIR ?? join13(homedir5(), ".massu", "wasm-cache");
12823
13209
  }
12824
13210
  function getCachedPath(language, sha) {
12825
- return join12(getCacheDir(), `${language}-${sha}.wasm`);
13211
+ return join13(getCacheDir(), `${language}-${sha}.wasm`);
12826
13212
  }
12827
13213
  function getCacheRetainCount() {
12828
13214
  const env = process.env.MASSU_WASM_CACHE_RETAIN;
@@ -12850,7 +13236,7 @@ function evictBeyondRetainCount(retain = getCacheRetainCount()) {
12850
13236
  const candidates = [];
12851
13237
  for (const name of entries) {
12852
13238
  if (!name.endsWith(".wasm")) continue;
12853
- const path = join12(dir, name);
13239
+ const path = join13(dir, name);
12854
13240
  let stat;
12855
13241
  try {
12856
13242
  stat = lstatSync3(path);
@@ -12907,7 +13293,7 @@ async function loadGrammar(language, options = {}) {
12907
13293
  }
12908
13294
  let bytes;
12909
13295
  try {
12910
- bytes = readFileSync11(cachePath);
13296
+ bytes = readFileSync12(cachePath);
12911
13297
  } catch (e2) {
12912
13298
  bytes = new Uint8Array(0);
12913
13299
  }
@@ -12947,21 +13333,21 @@ async function loadGrammar(language, options = {}) {
12947
13333
  throw new GrammarSHAMismatchError(language, manifest.sha256, downloadedSha);
12948
13334
  }
12949
13335
  try {
12950
- mkdirSync7(dirname9(cachePath), { recursive: true, mode: 448 });
13336
+ mkdirSync9(dirname11(cachePath), { recursive: true, mode: 448 });
12951
13337
  try {
12952
- chmodSync3(dirname9(cachePath), 448);
13338
+ chmodSync4(dirname11(cachePath), 448);
12953
13339
  } catch {
12954
13340
  }
12955
13341
  const tmpPath = `${cachePath}.tmp.${process.pid}`;
12956
- writeFileSync3(tmpPath, body, { mode: 384 });
13342
+ writeFileSync4(tmpPath, body, { mode: 384 });
12957
13343
  try {
12958
- chmodSync3(tmpPath, 384);
13344
+ chmodSync4(tmpPath, 384);
12959
13345
  } catch {
12960
13346
  }
12961
13347
  try {
12962
13348
  renameSync3(tmpPath, cachePath);
12963
13349
  try {
12964
- chmodSync3(cachePath, 384);
13350
+ chmodSync4(cachePath, 384);
12965
13351
  } catch {
12966
13352
  }
12967
13353
  } catch (e2) {
@@ -13825,8 +14211,8 @@ __export(file_sampler_exports, {
13825
14211
  SAMPLE_TEST_FILE_PATTERNS: () => SAMPLE_TEST_FILE_PATTERNS,
13826
14212
  sampleFilesForAdapter: () => sampleFilesForAdapter
13827
14213
  });
13828
- import { readdirSync as readdirSync10, readFileSync as readFileSync12, lstatSync as lstatSync4 } from "node:fs";
13829
- import { join as join13, extname } from "node:path";
14214
+ import { readdirSync as readdirSync10, readFileSync as readFileSync13, lstatSync as lstatSync4 } from "node:fs";
14215
+ import { join as join14, extname } from "node:path";
13830
14216
  function sampleFilesForAdapter(adapter, projectRoot, detection, options = {}) {
13831
14217
  const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH;
13832
14218
  const maxFiles = options.maxFilesPerAdapter ?? DEFAULT_MAX_FILES;
@@ -13841,7 +14227,7 @@ function sampleFilesForAdapter(adapter, projectRoot, detection, options = {}) {
13841
14227
  const langDetection = detection.sourceDirs[langKey];
13842
14228
  const candidateDirs = [];
13843
14229
  if (langDetection?.source_dirs && langDetection.source_dirs.length > 0) {
13844
- candidateDirs.push(...langDetection.source_dirs.map((d2) => join13(projectRoot, d2)));
14230
+ candidateDirs.push(...langDetection.source_dirs.map((d2) => join14(projectRoot, d2)));
13845
14231
  } else {
13846
14232
  candidateDirs.push(projectRoot);
13847
14233
  }
@@ -13865,7 +14251,7 @@ function walkDir(dir, exts, testPatterns, lang, maxDepth, curDepth, out, seen, m
13865
14251
  if (out.length >= maxFiles) return;
13866
14252
  if (entry.startsWith(".")) continue;
13867
14253
  if (IGNORED_DIRS3.has(entry)) continue;
13868
- const fullPath = join13(dir, entry);
14254
+ const fullPath = join14(dir, entry);
13869
14255
  let st;
13870
14256
  try {
13871
14257
  st = lstatSync4(fullPath);
@@ -13886,7 +14272,7 @@ function walkDir(dir, exts, testPatterns, lang, maxDepth, curDepth, out, seen, m
13886
14272
  seen.add(fullPath);
13887
14273
  let content;
13888
14274
  try {
13889
- content = readFileSync12(fullPath, "utf-8");
14275
+ content = readFileSync13(fullPath, "utf-8");
13890
14276
  } catch {
13891
14277
  continue;
13892
14278
  }
@@ -15310,8 +15696,8 @@ __export(init_exports, {
15310
15696
  validateWrittenConfig: () => validateWrittenConfig,
15311
15697
  writeConfigAtomic: () => writeConfigAtomic
15312
15698
  });
15313
- import { closeSync as closeSync3, existsSync as existsSync16, fsyncSync as fsyncSync3, openSync as openSync3, readFileSync as readFileSync13, writeFileSync as writeFileSync4, writeSync as writeSync2, mkdirSync as mkdirSync8, readdirSync as readdirSync11, renameSync as renameSync4, rmSync as rmSync4, statSync as statSync9, chmodSync as chmodSync4 } from "fs";
15314
- import { resolve as resolve9, basename as basename6, dirname as dirname10 } from "path";
15699
+ import { closeSync as closeSync3, existsSync as existsSync17, fsyncSync as fsyncSync3, openSync as openSync3, readFileSync as readFileSync14, writeFileSync as writeFileSync5, writeSync as writeSync2, mkdirSync as mkdirSync10, readdirSync as readdirSync11, renameSync as renameSync4, rmSync as rmSync5, statSync as statSync9, chmodSync as chmodSync5 } from "fs";
15700
+ import { resolve as resolve9, basename as basename6, dirname as dirname12 } from "path";
15315
15701
  import { fileURLToPath as fileURLToPath3 } from "url";
15316
15702
  import { homedir as homedir6 } from "os";
15317
15703
  import { stringify as yamlStringify, parse as yamlParse } from "yaml";
@@ -15323,9 +15709,9 @@ function detectFramework(projectRoot) {
15323
15709
  ui: "none"
15324
15710
  };
15325
15711
  const pkgPath = resolve9(projectRoot, "package.json");
15326
- if (!existsSync16(pkgPath)) return result;
15712
+ if (!existsSync17(pkgPath)) return result;
15327
15713
  try {
15328
- const pkg = JSON.parse(readFileSync13(pkgPath, "utf-8"));
15714
+ const pkg = JSON.parse(readFileSync14(pkgPath, "utf-8"));
15329
15715
  const allDeps = {
15330
15716
  ...pkg.dependencies,
15331
15717
  ...pkg.devDependencies
@@ -15359,7 +15745,7 @@ function detectPython(projectRoot) {
15359
15745
  alembicDir: null
15360
15746
  };
15361
15747
  const markers = ["pyproject.toml", "setup.py", "requirements.txt", "Pipfile"];
15362
- const hasMarker = markers.some((m3) => existsSync16(resolve9(projectRoot, m3)));
15748
+ const hasMarker = markers.some((m3) => existsSync17(resolve9(projectRoot, m3)));
15363
15749
  if (!hasMarker) return result;
15364
15750
  result.detected = true;
15365
15751
  const depFiles = [
@@ -15370,32 +15756,32 @@ function detectPython(projectRoot) {
15370
15756
  ];
15371
15757
  for (const { file } of depFiles) {
15372
15758
  const filePath = resolve9(projectRoot, file);
15373
- if (existsSync16(filePath)) {
15759
+ if (existsSync17(filePath)) {
15374
15760
  try {
15375
- const content = readFileSync13(filePath, "utf-8").toLowerCase();
15761
+ const content = readFileSync14(filePath, "utf-8").toLowerCase();
15376
15762
  if (content.includes("fastapi")) result.hasFastapi = true;
15377
15763
  if (content.includes("sqlalchemy")) result.hasSqlalchemy = true;
15378
15764
  } catch {
15379
15765
  }
15380
15766
  }
15381
15767
  }
15382
- if (existsSync16(resolve9(projectRoot, "alembic.ini"))) {
15768
+ if (existsSync17(resolve9(projectRoot, "alembic.ini"))) {
15383
15769
  result.hasAlembic = true;
15384
- if (existsSync16(resolve9(projectRoot, "alembic"))) {
15770
+ if (existsSync17(resolve9(projectRoot, "alembic"))) {
15385
15771
  result.alembicDir = "alembic";
15386
15772
  }
15387
- } else if (existsSync16(resolve9(projectRoot, "alembic"))) {
15773
+ } else if (existsSync17(resolve9(projectRoot, "alembic"))) {
15388
15774
  result.hasAlembic = true;
15389
15775
  result.alembicDir = "alembic";
15390
15776
  }
15391
15777
  const candidateRoots = ["app", "src", "backend", "api"];
15392
15778
  for (const candidate of candidateRoots) {
15393
15779
  const candidatePath = resolve9(projectRoot, candidate);
15394
- if (existsSync16(candidatePath) && existsSync16(resolve9(candidatePath, "__init__.py"))) {
15780
+ if (existsSync17(candidatePath) && existsSync17(resolve9(candidatePath, "__init__.py"))) {
15395
15781
  result.root = candidate;
15396
15782
  break;
15397
15783
  }
15398
- if (existsSync16(candidatePath)) {
15784
+ if (existsSync17(candidatePath)) {
15399
15785
  try {
15400
15786
  const files = readdirSync11(candidatePath);
15401
15787
  if (files.some((f2) => f2.endsWith(".py"))) {
@@ -15416,7 +15802,7 @@ function generateConfig(projectRoot, framework) {
15416
15802
  "[@massu/core] generateConfig() is deprecated since 1.2.1 \u2014 use buildConfigFromDetection instead. It cannot produce valid configs for monorepos."
15417
15803
  );
15418
15804
  const configPath = resolve9(projectRoot, "massu.config.yaml");
15419
- if (existsSync16(configPath)) {
15805
+ if (existsSync17(configPath)) {
15420
15806
  return false;
15421
15807
  }
15422
15808
  const projectName = basename6(projectRoot);
@@ -15462,7 +15848,7 @@ function generateConfig(projectRoot, framework) {
15462
15848
  # Documentation: https://massu.ai/docs/getting-started/configuration
15463
15849
 
15464
15850
  ${yamlStringify(config)}`;
15465
- writeFileSync4(configPath, yamlContent, "utf-8");
15851
+ writeFileSync5(configPath, yamlContent, "utf-8");
15466
15852
  return true;
15467
15853
  }
15468
15854
  function monorepoCommonRoot(packages) {
@@ -15527,10 +15913,10 @@ function buildConfigFromDetection(opts) {
15527
15913
  pathsSource = monorepoCommonRoot(detection.monorepo.packages);
15528
15914
  }
15529
15915
  }
15530
- if (pathsSource === "src" && !existsSync16(resolve9(projectRoot, "src"))) {
15916
+ if (pathsSource === "src" && !existsSync17(resolve9(projectRoot, "src"))) {
15531
15917
  const fallbacks = ["app", "pages", "."];
15532
15918
  for (const fallback of fallbacks) {
15533
- if (fallback === "." || existsSync16(resolve9(projectRoot, fallback))) {
15919
+ if (fallback === "." || existsSync17(resolve9(projectRoot, fallback))) {
15534
15920
  pathsSource = fallback;
15535
15921
  break;
15536
15922
  }
@@ -15614,7 +16000,7 @@ function buildConfigFromDetection(opts) {
15614
16000
  };
15615
16001
  if (pyFw?.framework) pythonBlock.framework = pyFw.framework;
15616
16002
  if (pyFw?.orm) pythonBlock.orm = pyFw.orm;
15617
- if (existsSync16(resolve9(projectRoot, "alembic.ini")) || existsSync16(resolve9(projectRoot, "alembic"))) {
16003
+ if (existsSync17(resolve9(projectRoot, "alembic.ini")) || existsSync17(resolve9(projectRoot, "alembic"))) {
15618
16004
  pythonBlock.alembic_dir = "alembic";
15619
16005
  }
15620
16006
  config.python = pythonBlock;
@@ -15639,10 +16025,10 @@ function applyVariantTemplate(config, templatesDir) {
15639
16025
  }
15640
16026
  if (templateId === null) return config;
15641
16027
  const templatePath = resolve9(templatesDir, templateId, "massu.config.yaml");
15642
- if (!existsSync16(templatePath)) return config;
16028
+ if (!existsSync17(templatePath)) return config;
15643
16029
  let template;
15644
16030
  try {
15645
- template = yamlParse(readFileSync13(templatePath, "utf-8"));
16031
+ template = yamlParse(readFileSync14(templatePath, "utf-8"));
15646
16032
  } catch {
15647
16033
  return config;
15648
16034
  }
@@ -15701,7 +16087,7 @@ ${yamlStringify(config)}`;
15701
16087
  function writeConfigAtomic(configPath, content) {
15702
16088
  const tmpPath = `${configPath}.tmp`;
15703
16089
  let existingMode;
15704
- if (existsSync16(configPath)) {
16090
+ if (existsSync17(configPath)) {
15705
16091
  try {
15706
16092
  existingMode = statSync9(configPath).mode;
15707
16093
  } catch {
@@ -15709,7 +16095,7 @@ function writeConfigAtomic(configPath, content) {
15709
16095
  }
15710
16096
  }
15711
16097
  try {
15712
- mkdirSync8(dirname10(configPath), { recursive: true });
16098
+ mkdirSync10(dirname12(configPath), { recursive: true });
15713
16099
  const fd = openSync3(tmpPath, "w", 420);
15714
16100
  try {
15715
16101
  const buf = Buffer.from(content, "utf-8");
@@ -15725,15 +16111,15 @@ function writeConfigAtomic(configPath, content) {
15725
16111
  renameSync4(tmpPath, configPath);
15726
16112
  if (existingMode !== void 0) {
15727
16113
  try {
15728
- chmodSync4(configPath, existingMode);
16114
+ chmodSync5(configPath, existingMode);
15729
16115
  } catch {
15730
16116
  }
15731
16117
  }
15732
16118
  return { validated: true };
15733
16119
  } catch (err) {
15734
- if (existsSync16(tmpPath)) {
16120
+ if (existsSync17(tmpPath)) {
15735
16121
  try {
15736
- rmSync4(tmpPath, { force: true });
16122
+ rmSync5(tmpPath, { force: true });
15737
16123
  } catch {
15738
16124
  }
15739
16125
  }
@@ -15742,8 +16128,8 @@ function writeConfigAtomic(configPath, content) {
15742
16128
  }
15743
16129
  function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
15744
16130
  try {
15745
- if (!existsSync16(configPath)) return "Config file does not exist after write";
15746
- const content = readFileSync13(configPath, "utf-8");
16131
+ if (!existsSync17(configPath)) return "Config file does not exist after write";
16132
+ const content = readFileSync14(configPath, "utf-8");
15747
16133
  const parsed = yamlParse(content);
15748
16134
  if (parsed === null || typeof parsed !== "object") {
15749
16135
  return "Config is not a valid YAML object";
@@ -15764,7 +16150,7 @@ function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
15764
16150
  const src = cfg.paths.source;
15765
16151
  if (src && src !== ".") {
15766
16152
  const srcAbs = resolve9(projectRoot, src);
15767
- if (!existsSync16(srcAbs)) {
16153
+ if (!existsSync17(srcAbs)) {
15768
16154
  return `paths.source '${src}' does not exist on disk`;
15769
16155
  }
15770
16156
  }
@@ -15775,7 +16161,7 @@ function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
15775
16161
  for (const d2 of rawDirs) {
15776
16162
  if (typeof d2 !== "string" || d2 === ".") continue;
15777
16163
  const abs = resolve9(projectRoot, d2);
15778
- if (!existsSync16(abs)) {
16164
+ if (!existsSync17(abs)) {
15779
16165
  return `framework.languages.${lang}.source_dirs '${d2}' does not exist on disk`;
15780
16166
  }
15781
16167
  }
@@ -15784,7 +16170,7 @@ function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
15784
16170
  if (Array.isArray(mRoots)) {
15785
16171
  for (const r2 of mRoots) {
15786
16172
  if (typeof r2 !== "string" || r2 === ".") continue;
15787
- if (!existsSync16(resolve9(projectRoot, r2))) {
16173
+ if (!existsSync17(resolve9(projectRoot, r2))) {
15788
16174
  return `paths.monorepo_roots '${r2}' does not exist on disk`;
15789
16175
  }
15790
16176
  }
@@ -15830,7 +16216,7 @@ function resolveTemplatesDir() {
15830
16216
  resolve9(__dirname2, "../../../templates")
15831
16217
  ];
15832
16218
  for (const c2 of candidates) {
15833
- if (existsSync16(c2)) return c2;
16219
+ if (existsSync17(c2)) return c2;
15834
16220
  }
15835
16221
  return null;
15836
16222
  }
@@ -15840,13 +16226,13 @@ function copyTemplateConfig(templateName, targetPath, projectName) {
15840
16226
  return { success: false, error: `Templates directory not found (looked in node_modules and dist/src)` };
15841
16227
  }
15842
16228
  const srcPath = resolve9(templatesDir, templateName, "massu.config.yaml");
15843
- if (!existsSync16(srcPath)) {
16229
+ if (!existsSync17(srcPath)) {
15844
16230
  return { success: false, error: `Template '${templateName}' not found at ${srcPath}` };
15845
16231
  }
15846
16232
  try {
15847
- let content = readFileSync13(srcPath, "utf-8");
16233
+ let content = readFileSync14(srcPath, "utf-8");
15848
16234
  content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
15849
- writeFileSync4(targetPath, content, "utf-8");
16235
+ writeFileSync5(targetPath, content, "utf-8");
15850
16236
  return { success: true };
15851
16237
  } catch (err) {
15852
16238
  return { success: false, error: err instanceof Error ? err.message : String(err) };
@@ -15858,9 +16244,9 @@ function getInstallerVersion() {
15858
16244
  resolve9(__dirname2, "../../package.json")
15859
16245
  ];
15860
16246
  for (const candidate of candidates) {
15861
- if (existsSync16(candidate)) {
16247
+ if (existsSync17(candidate)) {
15862
16248
  try {
15863
- const pkg = JSON.parse(readFileSync13(candidate, "utf-8"));
16249
+ const pkg = JSON.parse(readFileSync14(candidate, "utf-8"));
15864
16250
  if (typeof pkg.version === "string" && pkg.version.length > 0 && pkg.name === "@massu/core") {
15865
16251
  return pkg.version;
15866
16252
  }
@@ -15875,9 +16261,9 @@ function getInstallerVersion() {
15875
16261
  function registerMcpServer(projectRoot) {
15876
16262
  const mcpPath = resolve9(projectRoot, ".mcp.json");
15877
16263
  let existing = {};
15878
- if (existsSync16(mcpPath)) {
16264
+ if (existsSync17(mcpPath)) {
15879
16265
  try {
15880
- existing = JSON.parse(readFileSync13(mcpPath, "utf-8"));
16266
+ existing = JSON.parse(readFileSync14(mcpPath, "utf-8"));
15881
16267
  } catch {
15882
16268
  existing = {};
15883
16269
  }
@@ -15893,17 +16279,17 @@ function registerMcpServer(projectRoot) {
15893
16279
  args: ["-y", `@massu/core@${version}`]
15894
16280
  };
15895
16281
  existing.mcpServers = servers;
15896
- writeFileSync4(mcpPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
16282
+ writeFileSync5(mcpPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
15897
16283
  return true;
15898
16284
  }
15899
16285
  function resolveHooksDir() {
15900
16286
  const cwd = process.cwd();
15901
16287
  const nodeModulesPath = resolve9(cwd, "node_modules/@massu/core/dist/hooks");
15902
- if (existsSync16(nodeModulesPath)) {
16288
+ if (existsSync17(nodeModulesPath)) {
15903
16289
  return "node_modules/@massu/core/dist/hooks";
15904
16290
  }
15905
16291
  const localPath = resolve9(__dirname2, "../dist/hooks");
15906
- if (existsSync16(localPath)) {
16292
+ if (existsSync17(localPath)) {
15907
16293
  return localPath;
15908
16294
  }
15909
16295
  return "node_modules/@massu/core/dist/hooks";
@@ -16053,8 +16439,8 @@ function installHooks(projectRoot) {
16053
16439
  claudeDirName = ".claude";
16054
16440
  }
16055
16441
  const claudeDir = resolve9(projectRoot, claudeDirName);
16056
- if (!existsSync16(claudeDir)) {
16057
- mkdirSync8(claudeDir, { recursive: true });
16442
+ if (!existsSync17(claudeDir)) {
16443
+ mkdirSync10(claudeDir, { recursive: true });
16058
16444
  }
16059
16445
  const settings = readSettingsLocal(claudeDir);
16060
16446
  const hooksConfig = buildHooksConfig(resolveHooksDir());
@@ -16075,14 +16461,14 @@ function initMemoryDir(projectRoot) {
16075
16461
  const memoryDir = resolve9(homedir6(), `.claude/projects/${encodedRoot}/memory`);
16076
16462
  let migratedFromLegacy = false;
16077
16463
  const legacyDir = resolve9(homedir6(), `.claude/projects/-${encodedRoot}/memory`);
16078
- if (existsSync16(legacyDir) && !existsSync16(memoryDir)) {
16464
+ if (existsSync17(legacyDir) && !existsSync17(memoryDir)) {
16079
16465
  try {
16080
- mkdirSync8(resolve9(memoryDir, ".."), { recursive: true });
16466
+ mkdirSync10(resolve9(memoryDir, ".."), { recursive: true });
16081
16467
  renameSync4(legacyDir, memoryDir);
16082
16468
  try {
16083
16469
  const legacyParent = resolve9(legacyDir, "..");
16084
- if (existsSync16(legacyParent) && readdirSync11(legacyParent).length === 0) {
16085
- rmSync4(legacyParent, { recursive: false });
16470
+ if (existsSync17(legacyParent) && readdirSync11(legacyParent).length === 0) {
16471
+ rmSync5(legacyParent, { recursive: false });
16086
16472
  }
16087
16473
  } catch {
16088
16474
  }
@@ -16091,13 +16477,13 @@ function initMemoryDir(projectRoot) {
16091
16477
  }
16092
16478
  }
16093
16479
  let created = false;
16094
- if (!existsSync16(memoryDir)) {
16095
- mkdirSync8(memoryDir, { recursive: true });
16480
+ if (!existsSync17(memoryDir)) {
16481
+ mkdirSync10(memoryDir, { recursive: true });
16096
16482
  created = true;
16097
16483
  }
16098
16484
  const memoryMdPath = resolve9(memoryDir, "MEMORY.md");
16099
16485
  let memoryMdCreated = false;
16100
- if (!existsSync16(memoryMdPath)) {
16486
+ if (!existsSync17(memoryMdPath)) {
16101
16487
  const projectName = basename6(projectRoot);
16102
16488
  const memoryContent = `# ${projectName} - Massu Memory
16103
16489
 
@@ -16113,7 +16499,7 @@ function initMemoryDir(projectRoot) {
16113
16499
  ## File Index
16114
16500
  <!-- Significant files and directories -->
16115
16501
  `;
16116
- writeFileSync4(memoryMdPath, memoryContent, "utf-8");
16502
+ writeFileSync5(memoryMdPath, memoryContent, "utf-8");
16117
16503
  memoryMdCreated = true;
16118
16504
  }
16119
16505
  return { created, memoryMdCreated, migratedFromLegacy };
@@ -16212,7 +16598,7 @@ async function runInit(argv, overrides) {
16212
16598
  log("========================");
16213
16599
  log("");
16214
16600
  const configPath = resolve9(projectRoot, "massu.config.yaml");
16215
- if (existsSync16(configPath)) {
16601
+ if (existsSync17(configPath)) {
16216
16602
  if (opts.ci && !opts.force) {
16217
16603
  errLog(`error: massu.config.yaml already exists at ${configPath}`);
16218
16604
  errLog(" rerun with --force to overwrite, or remove the file first");
@@ -16240,7 +16626,7 @@ async function runInit(argv, overrides) {
16240
16626
  const validation2 = validateWrittenConfig(configPath, projectRoot, false);
16241
16627
  if (validation2 !== null) {
16242
16628
  try {
16243
- rmSync4(configPath, { force: true });
16629
+ rmSync5(configPath, { force: true });
16244
16630
  } catch {
16245
16631
  }
16246
16632
  errLog(`error: template config failed validation: ${validation2}`);
@@ -16318,7 +16704,7 @@ async function runInit(argv, overrides) {
16318
16704
  const validation = validateWrittenConfig(configPath, projectRoot, !emptyStack);
16319
16705
  if (validation !== null) {
16320
16706
  try {
16321
- rmSync4(configPath, { force: true });
16707
+ rmSync5(configPath, { force: true });
16322
16708
  } catch {
16323
16709
  }
16324
16710
  errLog(`error: generated config failed validation: ${validation}`);
@@ -16352,7 +16738,7 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
16352
16738
  const stackResolved = !emptyStack && commandStats && (commandStats.installed > 0 || commandStats.updated > 0 || commandStats.kept > 0);
16353
16739
  if (!stackResolved) {
16354
16740
  const placeholderPath = resolve9(cmdResult.claudeDir, "commands", "_massu-needs-stack.md");
16355
- if (!existsSync16(placeholderPath)) {
16741
+ if (!existsSync17(placeholderPath)) {
16356
16742
  const placeholderBody = [
16357
16743
  "# Massu \u2014 stack not yet detected",
16358
16744
  "",
@@ -16373,8 +16759,8 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
16373
16759
  "\u2014 Massu"
16374
16760
  ].join("\n");
16375
16761
  try {
16376
- mkdirSync8(resolve9(cmdResult.claudeDir, "commands"), { recursive: true });
16377
- writeFileSync4(placeholderPath, placeholderBody, "utf-8");
16762
+ mkdirSync10(resolve9(cmdResult.claudeDir, "commands"), { recursive: true });
16763
+ writeFileSync5(placeholderPath, placeholderBody, "utf-8");
16378
16764
  log(" Wrote _massu-needs-stack.md placeholder (no stack detected yet)");
16379
16765
  } catch {
16380
16766
  }
@@ -16397,7 +16783,7 @@ function installSideEffects(projectRoot, log, skipCommands = false, emptyStack =
16397
16783
  try {
16398
16784
  const encodedRoot = encodeMemoryDirName(projectRoot);
16399
16785
  const memoryDir = resolve9(homedir6(), ".claude", "projects", encodedRoot, "memory");
16400
- const memFiles = existsSync16(memoryDir) ? readdirSync11(memoryDir).filter((f2) => f2.endsWith(".md") && f2 !== "MEMORY.md") : [];
16786
+ const memFiles = existsSync17(memoryDir) ? readdirSync11(memoryDir).filter((f2) => f2.endsWith(".md") && f2 !== "MEMORY.md") : [];
16401
16787
  if (memFiles.length > 0) {
16402
16788
  const { getMemoryDb: getMemoryDb2 } = await Promise.resolve().then(() => (init_memory_db(), memory_db_exports));
16403
16789
  const db = getMemoryDb2();
@@ -16460,7 +16846,7 @@ var init_init = __esm({
16460
16846
  init_detect();
16461
16847
  init_drift();
16462
16848
  __filename2 = fileURLToPath3(import.meta.url);
16463
- __dirname2 = dirname10(__filename2);
16849
+ __dirname2 = dirname12(__filename2);
16464
16850
  FRAMEWORK_TO_TEMPLATE_ID = {
16465
16851
  rails: "rails",
16466
16852
  phoenix: "phoenix",
@@ -16577,7 +16963,7 @@ function verifyLicenseResponse(payload) {
16577
16963
  );
16578
16964
  }
16579
16965
  function isLicenseSignatureRequired() {
16580
- return process.env.MASSU_REQUIRE_SIGNED_LICENSE === "true";
16966
+ return process.env.MASSU_REQUIRE_SIGNED_LICENSE !== "false";
16581
16967
  }
16582
16968
  var init_license_response_verifier = __esm({
16583
16969
  "src/security/license-response-verifier.ts"() {
@@ -17081,21 +17467,22 @@ var init_hook_registry = __esm({
17081
17467
  // src/commands/doctor.ts
17082
17468
  var doctor_exports = {};
17083
17469
  __export(doctor_exports, {
17470
+ checkNativeModules: () => checkNativeModules,
17084
17471
  formatLicenseCheck: () => formatLicenseCheck,
17085
17472
  runDoctor: () => runDoctor,
17086
17473
  runValidateConfig: () => runValidateConfig
17087
17474
  });
17088
- import { existsSync as existsSync17, readFileSync as readFileSync14, readdirSync as readdirSync12 } from "fs";
17089
- import { resolve as resolve10, dirname as dirname11 } from "path";
17475
+ import { existsSync as existsSync18, readFileSync as readFileSync15, readdirSync as readdirSync12 } from "fs";
17476
+ import { resolve as resolve10, dirname as dirname13 } from "path";
17090
17477
  import { fileURLToPath as fileURLToPath4 } from "url";
17091
17478
  import { parse as parseYaml4 } from "yaml";
17092
17479
  function checkConfig(projectRoot) {
17093
17480
  const configPath = resolve10(projectRoot, "massu.config.yaml");
17094
- if (!existsSync17(configPath)) {
17481
+ if (!existsSync18(configPath)) {
17095
17482
  return { name: "Configuration", status: "fail", detail: "massu.config.yaml not found. Run: npx massu init" };
17096
17483
  }
17097
17484
  try {
17098
- const content = readFileSync14(configPath, "utf-8");
17485
+ const content = readFileSync15(configPath, "utf-8");
17099
17486
  const parsed = parseYaml4(content);
17100
17487
  if (!parsed || typeof parsed !== "object") {
17101
17488
  return { name: "Configuration", status: "fail", detail: "massu.config.yaml is empty or invalid YAML" };
@@ -17107,11 +17494,11 @@ function checkConfig(projectRoot) {
17107
17494
  }
17108
17495
  function checkMcpServer(projectRoot) {
17109
17496
  const mcpPath = getResolvedPaths().mcpJsonPath;
17110
- if (!existsSync17(mcpPath)) {
17497
+ if (!existsSync18(mcpPath)) {
17111
17498
  return { name: "MCP Server", status: "fail", detail: ".mcp.json not found. Run: npx massu init" };
17112
17499
  }
17113
17500
  try {
17114
- const content = JSON.parse(readFileSync14(mcpPath, "utf-8"));
17501
+ const content = JSON.parse(readFileSync15(mcpPath, "utf-8"));
17115
17502
  const servers = content.mcpServers ?? {};
17116
17503
  if (!servers.massu) {
17117
17504
  return { name: "MCP Server", status: "fail", detail: "massu not registered in .mcp.json. Run: npx massu init" };
@@ -17123,7 +17510,7 @@ function checkMcpServer(projectRoot) {
17123
17510
  }
17124
17511
  function checkHooksConfig(projectRoot) {
17125
17512
  const settingsPath = getResolvedPaths().settingsLocalPath;
17126
- if (!existsSync17(settingsPath)) {
17513
+ if (!existsSync18(settingsPath)) {
17127
17514
  return { name: "Hooks Config", status: "fail", detail: ".claude/settings.local.json not found. Run: npx massu init" };
17128
17515
  }
17129
17516
  try {
@@ -17153,9 +17540,9 @@ function checkHooksConfig(projectRoot) {
17153
17540
  function checkHookFiles(projectRoot) {
17154
17541
  const nodeModulesHooksDir = resolve10(projectRoot, "node_modules/@massu/core/dist/hooks");
17155
17542
  let hooksDir = nodeModulesHooksDir;
17156
- if (!existsSync17(nodeModulesHooksDir)) {
17543
+ if (!existsSync18(nodeModulesHooksDir)) {
17157
17544
  const devHooksDir = resolve10(__dirname3, "../../dist/hooks");
17158
- if (existsSync17(devHooksDir)) {
17545
+ if (existsSync18(devHooksDir)) {
17159
17546
  hooksDir = devHooksDir;
17160
17547
  } else {
17161
17548
  return { name: "Hook Files", status: "fail", detail: "Compiled hooks not found. Run: npm install @massu/core" };
@@ -17163,7 +17550,7 @@ function checkHookFiles(projectRoot) {
17163
17550
  }
17164
17551
  const missing = [];
17165
17552
  for (const hookFile of EXPECTED_HOOKS) {
17166
- if (!existsSync17(resolve10(hooksDir, hookFile))) {
17553
+ if (!existsSync18(resolve10(hooksDir, hookFile))) {
17167
17554
  missing.push(hookFile);
17168
17555
  }
17169
17556
  }
@@ -17173,12 +17560,17 @@ function checkHookFiles(projectRoot) {
17173
17560
  return { name: "Hook Files", status: "pass", detail: `${EXPECTED_HOOKS.length}/${EXPECTED_HOOKS.length} compiled hooks present` };
17174
17561
  }
17175
17562
  async function checkNativeModules() {
17176
- try {
17177
- await import("better-sqlite3");
17178
- return { name: "Native Modules", status: "pass", detail: "better-sqlite3 loads correctly" };
17179
- } catch (err) {
17180
- return { name: "Native Modules", status: "fail", detail: `better-sqlite3 failed: ${err instanceof Error ? err.message : String(err)}. Try: npm rebuild better-sqlite3` };
17563
+ const memoryDbPath = getResolvedPaths().memoryDbPath;
17564
+ const verdict = probeMemoryDbUsable({ dbPath: memoryDbPath, selfHeal: false });
17565
+ if (verdict.ok) {
17566
+ return { name: "Native Modules", status: "pass", detail: "better-sqlite3 constructs a DB and SELECT 1 succeeds" };
17181
17567
  }
17568
+ const because = verdict.detail ? ` (${verdict.detail})` : "";
17569
+ return {
17570
+ name: "Native Modules",
17571
+ status: "fail",
17572
+ detail: `better-sqlite3 unusable \u2014 ${verdict.reason}${because}. ${verdict.remedy ?? NATIVE_DB_REMEDY}`
17573
+ };
17182
17574
  }
17183
17575
  function checkNodeVersion() {
17184
17576
  const version = process.versions.node;
@@ -17190,12 +17582,12 @@ function checkNodeVersion() {
17190
17582
  }
17191
17583
  async function checkGitRepo(projectRoot) {
17192
17584
  const gitDir = resolve10(projectRoot, ".git");
17193
- if (!existsSync17(gitDir)) {
17585
+ if (!existsSync18(gitDir)) {
17194
17586
  return { name: "Git Repository", status: "warn", detail: "Not a git repository (optional but recommended)" };
17195
17587
  }
17196
17588
  try {
17197
- const { spawnSync: spawnSync4 } = await import("child_process");
17198
- const result = spawnSync4("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
17589
+ const { spawnSync: spawnSync5 } = await import("child_process");
17590
+ const result = spawnSync5("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
17199
17591
  encoding: "utf-8",
17200
17592
  timeout: 5e3,
17201
17593
  cwd: projectRoot
@@ -17208,7 +17600,7 @@ async function checkGitRepo(projectRoot) {
17208
17600
  }
17209
17601
  function checkKnowledgeDb(projectRoot) {
17210
17602
  const knowledgeDbPath = getResolvedPaths().memoryDbPath;
17211
- if (!existsSync17(knowledgeDbPath)) {
17603
+ if (!existsSync18(knowledgeDbPath)) {
17212
17604
  return {
17213
17605
  name: "Knowledge DB",
17214
17606
  status: "warn",
@@ -17219,7 +17611,7 @@ function checkKnowledgeDb(projectRoot) {
17219
17611
  }
17220
17612
  function checkMemoryDir(_projectRoot2) {
17221
17613
  const memoryDir = getResolvedPaths().memoryDir;
17222
- if (!existsSync17(memoryDir)) {
17614
+ if (!existsSync18(memoryDir)) {
17223
17615
  return {
17224
17616
  name: "Memory Directory",
17225
17617
  status: "warn",
@@ -17230,7 +17622,7 @@ function checkMemoryDir(_projectRoot2) {
17230
17622
  }
17231
17623
  function checkShellHooksWired(_projectRoot2) {
17232
17624
  const settingsPath = getResolvedPaths().settingsLocalPath;
17233
- if (!existsSync17(settingsPath)) {
17625
+ if (!existsSync18(settingsPath)) {
17234
17626
  return {
17235
17627
  name: "Shell Hooks",
17236
17628
  status: "fail",
@@ -17306,8 +17698,8 @@ async function checkLicenseStatus() {
17306
17698
  async function checkApiKeyHygiene(projectRoot) {
17307
17699
  if (getResolvedApiKeySource() !== "config") return null;
17308
17700
  try {
17309
- const { spawnSync: spawnSync4 } = await import("child_process");
17310
- const res = spawnSync4("git", ["ls-files", "--error-unmatch", "massu.config.yaml"], {
17701
+ const { spawnSync: spawnSync5 } = await import("child_process");
17702
+ const res = spawnSync5("git", ["ls-files", "--error-unmatch", "massu.config.yaml"], {
17311
17703
  cwd: projectRoot,
17312
17704
  timeout: 5e3,
17313
17705
  encoding: "utf-8"
@@ -17327,7 +17719,7 @@ function checkPythonHealth(projectRoot) {
17327
17719
  const config = getConfig();
17328
17720
  if (!config.python?.root) return null;
17329
17721
  const pythonRoot = resolve10(projectRoot, config.python.root);
17330
- if (!existsSync17(pythonRoot)) {
17722
+ if (!existsSync18(pythonRoot)) {
17331
17723
  return {
17332
17724
  name: "Python",
17333
17725
  status: "fail",
@@ -17347,7 +17739,7 @@ function checkPythonHealth(projectRoot) {
17347
17739
  const excludeDirs = config.python?.exclude_dirs || ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"];
17348
17740
  if (!excludeDirs.includes(entry.name)) {
17349
17741
  const subdir = resolve10(dir, entry.name);
17350
- if (depth <= 2 && !existsSync17(resolve10(subdir, "__init__.py"))) {
17742
+ if (depth <= 2 && !existsSync18(resolve10(subdir, "__init__.py"))) {
17351
17743
  try {
17352
17744
  const subEntries = readdirSync12(subdir);
17353
17745
  if (subEntries.some((f2) => f2.endsWith(".py") && f2 !== "__init__.py")) {
@@ -17445,14 +17837,14 @@ async function runDoctor() {
17445
17837
  async function runValidateConfig() {
17446
17838
  const projectRoot = process.cwd();
17447
17839
  const configPath = resolve10(projectRoot, "massu.config.yaml");
17448
- if (!existsSync17(configPath)) {
17840
+ if (!existsSync18(configPath)) {
17449
17841
  console.error("Error: massu.config.yaml not found in current directory");
17450
17842
  console.error("Run: npx massu init");
17451
17843
  process.exit(1);
17452
17844
  return;
17453
17845
  }
17454
17846
  try {
17455
- const content = readFileSync14(configPath, "utf-8");
17847
+ const content = readFileSync15(configPath, "utf-8");
17456
17848
  const parsed = parseYaml4(content);
17457
17849
  if (!parsed || typeof parsed !== "object") {
17458
17850
  console.error("Error: massu.config.yaml is empty or not a valid YAML object");
@@ -17493,8 +17885,9 @@ var init_doctor = __esm({
17493
17885
  init_credentials();
17494
17886
  init_settings_local();
17495
17887
  init_hook_registry();
17888
+ init_sqlite_loader();
17496
17889
  __filename3 = fileURLToPath4(import.meta.url);
17497
- __dirname3 = dirname11(__filename3);
17890
+ __dirname3 = dirname13(__filename3);
17498
17891
  EXPECTED_HOOKS = getExpectedHookFiles();
17499
17892
  }
17500
17893
  });
@@ -17682,6 +18075,67 @@ var init_login = __esm({
17682
18075
  }
17683
18076
  });
17684
18077
 
18078
+ // src/commands/heal.ts
18079
+ var heal_exports = {};
18080
+ __export(heal_exports, {
18081
+ runHeal: () => runHeal
18082
+ });
18083
+ async function runHeal(argv = []) {
18084
+ const check = argv.includes("--check");
18085
+ const runningAbi = process.versions.modules;
18086
+ const verdict = probeMemoryDbUsable({ selfHeal: false });
18087
+ const abiFrom = (() => {
18088
+ const m3 = /NODE_MODULE_VERSION (\d+)/.exec(verdict.detail ?? "");
18089
+ return m3 ? m3[1] : void 0;
18090
+ })();
18091
+ const probe = { ok: verdict.ok, abiFrom, detail: verdict.detail };
18092
+ if (check) {
18093
+ if (probe.ok) {
18094
+ process.stdout.write(
18095
+ `massu heal --check: native engine OK \u2014 better-sqlite3 matches this Node (NODE_MODULE_VERSION ${runningAbi}, ${process.version}).
18096
+ `
18097
+ );
18098
+ return { exitCode: 0 };
18099
+ }
18100
+ process.stdout.write(
18101
+ `massu heal --check: ABI MISMATCH \u2014 this Node needs NODE_MODULE_VERSION ${runningAbi} (${process.version})` + (probe.abiFrom ? `, the installed binary is ${probe.abiFrom}` : "") + `. Run 'massu heal' to rebuild it.
18102
+ `
18103
+ );
18104
+ return { exitCode: 1 };
18105
+ }
18106
+ if (probe.ok) {
18107
+ process.stdout.write(
18108
+ `massu heal: native engine already healthy for ${process.version} (NODE_MODULE_VERSION ${runningAbi}) \u2014 nothing to do.
18109
+ `
18110
+ );
18111
+ return { exitCode: 0 };
18112
+ }
18113
+ process.stdout.write(
18114
+ `massu heal: rebuilding better-sqlite3 for ${process.version} (NODE_MODULE_VERSION ${runningAbi})\u2026
18115
+ `
18116
+ );
18117
+ const result = attemptNativeHeal(probe.detail ? new Error(probe.detail) : void 0);
18118
+ if (result.healed) {
18119
+ process.stdout.write(
18120
+ `massu heal: rebuilt via ${result.method} (ABI ${result.abiFrom ?? "?"} \u2192 ${result.abiTo}, ${result.durationMs ?? "?"}ms). Restart your MCP client / Claude Code to pick up the healed engine.
18121
+ `
18122
+ );
18123
+ return { exitCode: 0 };
18124
+ }
18125
+ process.stderr.write(
18126
+ `massu heal: could not rebuild the native engine (${result.reason}${result.detail ? `: ${result.detail}` : ""}).
18127
+ Ensure the install directory is writable and either network access (for a compiler-free prebuilt) or a C/C++ toolchain (for a source build) is available, then retry.
18128
+ `
18129
+ );
18130
+ return { exitCode: 1 };
18131
+ }
18132
+ var init_heal = __esm({
18133
+ "src/commands/heal.ts"() {
18134
+ "use strict";
18135
+ init_sqlite_loader();
18136
+ }
18137
+ });
18138
+
17685
18139
  // src/commands/install-hooks.ts
17686
18140
  var install_hooks_exports = {};
17687
18141
  __export(install_hooks_exports, {
@@ -17713,8 +18167,8 @@ __export(hook_runner_exports, {
17713
18167
  resolveHookFile: () => resolveHookFile,
17714
18168
  runHookRunner: () => runHookRunner
17715
18169
  });
17716
- import { existsSync as existsSync18 } from "fs";
17717
- import { resolve as resolve11, dirname as dirname12 } from "path";
18170
+ import { existsSync as existsSync19 } from "fs";
18171
+ import { resolve as resolve11, dirname as dirname14 } from "path";
17718
18172
  import { fileURLToPath as fileURLToPath5 } from "url";
17719
18173
  import { spawn } from "child_process";
17720
18174
  function resolveHookFile(hookName) {
@@ -17733,7 +18187,7 @@ function resolveHookFile(hookName) {
17733
18187
  resolve11(__dirname4, "../../dist/hooks", file)
17734
18188
  ];
17735
18189
  for (const candidate of candidates) {
17736
- if (existsSync18(candidate)) {
18190
+ if (existsSync19(candidate)) {
17737
18191
  return candidate;
17738
18192
  }
17739
18193
  }
@@ -17763,7 +18217,10 @@ Recognized: ${Object.keys(HOOK_NAME_TO_FILE).join(", ")}
17763
18217
  return new Promise((resolvePromise) => {
17764
18218
  const child = spawn(process.execPath, [hookFile], {
17765
18219
  stdio: ["inherit", "inherit", "inherit"],
17766
- env: process.env
18220
+ // MASSU_HOOK_RUNTIME marks the hook process so the SSOT SQLite loader NEVER
18221
+ // self-heals here (5s budget / CR-12, CR-65 P0-003) — even for indirect opens
18222
+ // via getMemoryDb(). The next server/CLI touch performs the rebuild.
18223
+ env: { ...process.env, MASSU_HOOK_RUNTIME: "1" }
17767
18224
  });
17768
18225
  child.on("exit", (code, signal) => {
17769
18226
  if (signal) {
@@ -17785,7 +18242,7 @@ var init_hook_runner = __esm({
17785
18242
  "use strict";
17786
18243
  init_hook_registry();
17787
18244
  __filename4 = fileURLToPath5(import.meta.url);
17788
- __dirname4 = dirname12(__filename4);
18245
+ __dirname4 = dirname14(__filename4);
17789
18246
  HOOK_NAME_TO_FILE = Object.freeze(
17790
18247
  Object.fromEntries(REGISTERED_HOOKS.map((name) => [name, `${name}.js`]))
17791
18248
  );
@@ -17924,7 +18381,7 @@ var db_exports = {};
17924
18381
  __export(db_exports, {
17925
18382
  handleDbSubcommand: () => handleDbSubcommand
17926
18383
  });
17927
- import { existsSync as existsSync19, statSync as statSync10 } from "fs";
18384
+ import { existsSync as existsSync20, statSync as statSync10 } from "fs";
17928
18385
  import { basename as basename7 } from "path";
17929
18386
  function human(bytes) {
17930
18387
  if (bytes < 1024) return `${bytes} B`;
@@ -17969,7 +18426,7 @@ async function handleDbSubcommand(args2) {
17969
18426
 
17970
18427
  `);
17971
18428
  for (const store of allStores()) {
17972
- if (!existsSync19(store.path)) {
18429
+ if (!existsSync20(store.path)) {
17973
18430
  process.stdout.write(` ${"\u2014"} ${store.name.padEnd(10)} not present, skipped
17974
18431
  `);
17975
18432
  continue;
@@ -18067,7 +18524,7 @@ Restore with: massu db restore --latest memory
18067
18524
  target = found.path;
18068
18525
  }
18069
18526
  try {
18070
- const before = existsSync19(target) ? statSync10(target).size : 0;
18527
+ const before = existsSync20(target) ? statSync10(target).size : 0;
18071
18528
  const res = restoreDb(backupPath, target);
18072
18529
  process.stdout.write(
18073
18530
  `Restored ${basename7(target)}
@@ -18233,7 +18690,7 @@ var init_license2 = __esm({
18233
18690
  });
18234
18691
 
18235
18692
  // src/changelog-generator.ts
18236
- import { existsSync as existsSync20, readFileSync as readFileSync15, readdirSync as readdirSync13 } from "fs";
18693
+ import { existsSync as existsSync21, readFileSync as readFileSync16, readdirSync as readdirSync13 } from "fs";
18237
18694
  import { resolve as resolve13 } from "path";
18238
18695
  function parseCommitsForPlanTokens(subjects) {
18239
18696
  const tokens = /* @__PURE__ */ new Set();
@@ -18251,7 +18708,7 @@ function parseCommitsForPlanTokens(subjects) {
18251
18708
  function loadPlanSummaries(tokens, planDir) {
18252
18709
  const result = /* @__PURE__ */ new Map();
18253
18710
  if (tokens.size === 0) return result;
18254
- if (!existsSync20(planDir)) {
18711
+ if (!existsSync21(planDir)) {
18255
18712
  throw new Error(`Plan directory does not exist: ${planDir}`);
18256
18713
  }
18257
18714
  const files = readdirSync13(planDir).filter((f2) => f2.endsWith(".md"));
@@ -18260,7 +18717,7 @@ function loadPlanSummaries(tokens, planDir) {
18260
18717
  let content = "";
18261
18718
  for (const file of files) {
18262
18719
  const path = resolve13(planDir, file);
18263
- const text18 = readFileSync15(path, "utf-8");
18720
+ const text18 = readFileSync16(path, "utf-8");
18264
18721
  const tokenRe = new RegExp(
18265
18722
  `^\\*\\*Plan Token\\*\\*:\\s*\`?${token.replace(/[.*+?^${}()|[\\]\\\\]/g, "\\$&")}\`?(\\s|$)`,
18266
18723
  "m"
@@ -18341,7 +18798,7 @@ __export(changelog_exports, {
18341
18798
  printChangelogHelp: () => printChangelogHelp
18342
18799
  });
18343
18800
  import { execSync } from "child_process";
18344
- import { existsSync as existsSync21, readFileSync as readFileSync16 } from "fs";
18801
+ import { existsSync as existsSync22, readFileSync as readFileSync17 } from "fs";
18345
18802
  import { resolve as resolve14 } from "path";
18346
18803
  function resolveRepoRoot() {
18347
18804
  try {
@@ -18367,8 +18824,8 @@ function getCommitSubjects(range) {
18367
18824
  }
18368
18825
  function getCurrentVersion(repoRoot) {
18369
18826
  const pkgPath = resolve14(repoRoot, "packages/core/package.json");
18370
- if (!existsSync21(pkgPath)) return "0.0.0";
18371
- const pkg = JSON.parse(readFileSync16(pkgPath, "utf-8"));
18827
+ if (!existsSync22(pkgPath)) return "0.0.0";
18828
+ const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
18372
18829
  return pkg.version || "0.0.0";
18373
18830
  }
18374
18831
  function todayDate() {
@@ -18376,8 +18833,8 @@ function todayDate() {
18376
18833
  }
18377
18834
  function getLatestChangelogEntryBody(repoRoot) {
18378
18835
  const path = resolve14(repoRoot, "CHANGELOG.md");
18379
- if (!existsSync21(path)) return "";
18380
- const content = readFileSync16(path, "utf-8");
18836
+ if (!existsSync22(path)) return "";
18837
+ const content = readFileSync17(path, "utf-8");
18381
18838
  const m3 = content.match(/^## \[[\d.]+\][^\n]*\n([\s\S]*?)(?=\n## \[|$)/m);
18382
18839
  return m3 ? m3[1] : "";
18383
18840
  }
@@ -18472,16 +18929,15 @@ var init_changelog = __esm({
18472
18929
  });
18473
18930
 
18474
18931
  // src/knowledge-db.ts
18475
- import Database3 from "better-sqlite3";
18476
- import { dirname as dirname13 } from "path";
18477
- import { existsSync as existsSync22, mkdirSync as mkdirSync9 } from "fs";
18932
+ import { dirname as dirname15 } from "path";
18933
+ import { existsSync as existsSync23, mkdirSync as mkdirSync11 } from "fs";
18478
18934
  function getKnowledgeDb() {
18479
18935
  const dbPath = getResolvedPaths().knowledgeDbPath;
18480
- const dir = dirname13(dbPath);
18481
- if (!existsSync22(dir)) {
18482
- mkdirSync9(dir, { recursive: true });
18936
+ const dir = dirname15(dbPath);
18937
+ if (!existsSync23(dir)) {
18938
+ mkdirSync11(dir, { recursive: true });
18483
18939
  }
18484
- const db = new Database3(dbPath);
18940
+ const db = openDatabase(dbPath);
18485
18941
  db.pragma("journal_mode = WAL");
18486
18942
  db.pragma("foreign_keys = ON");
18487
18943
  initKnowledgeSchema(db);
@@ -18693,6 +19149,7 @@ async function embedMissingChunks(db, opts = {}) {
18693
19149
  var init_knowledge_db = __esm({
18694
19150
  "src/knowledge-db.ts"() {
18695
19151
  "use strict";
19152
+ init_sqlite_loader();
18696
19153
  init_config();
18697
19154
  init_memory_vector();
18698
19155
  init_memory_embed_sweep();
@@ -18704,7 +19161,7 @@ var memory_embed_backfill_exports = {};
18704
19161
  __export(memory_embed_backfill_exports, {
18705
19162
  runMemoryEmbedBackfill: () => runMemoryEmbedBackfill
18706
19163
  });
18707
- import { existsSync as existsSync23 } from "fs";
19164
+ import { existsSync as existsSync24 } from "fs";
18708
19165
  async function runMemoryEmbedBackfill(_args = []) {
18709
19166
  await embed("massu memory embed backfill probe");
18710
19167
  const active = getActiveEmbedModel();
@@ -18731,7 +19188,7 @@ async function runMemoryEmbedBackfill(_args = []) {
18731
19188
  );
18732
19189
  let chunks = { embedded: 0, scanned: 0 };
18733
19190
  const knowledgeDbPath = getResolvedPaths().knowledgeDbPath;
18734
- if (existsSync23(knowledgeDbPath)) {
19191
+ if (existsSync24(knowledgeDbPath)) {
18735
19192
  const knowledgeDb = getKnowledgeDb();
18736
19193
  try {
18737
19194
  chunks = await embedMissingChunks(knowledgeDb);
@@ -18764,7 +19221,7 @@ var init_memory_embed_backfill = __esm({
18764
19221
 
18765
19222
  // src/memory-authorship.ts
18766
19223
  import { createHmac, randomBytes, timingSafeEqual } from "crypto";
18767
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync5, existsSync as existsSync24, mkdirSync as mkdirSync10, chmodSync as chmodSync5, statSync as statSync11 } from "fs";
19224
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync6, existsSync as existsSync25, mkdirSync as mkdirSync12, chmodSync as chmodSync6, statSync as statSync11 } from "fs";
18768
19225
  import { homedir as homedir7 } from "os";
18769
19226
  import { resolve as resolve15 } from "path";
18770
19227
  function renderKeyPath(home = homedir7()) {
@@ -18773,8 +19230,8 @@ function renderKeyPath(home = homedir7()) {
18773
19230
  function readRenderKey(home = homedir7()) {
18774
19231
  const p19 = renderKeyPath(home);
18775
19232
  try {
18776
- if (!existsSync24(p19)) return void 0;
18777
- const raw = readFileSync17(p19);
19233
+ if (!existsSync25(p19)) return void 0;
19234
+ const raw = readFileSync18(p19);
18778
19235
  if (raw.length !== 32) return void 0;
18779
19236
  return raw;
18780
19237
  } catch {
@@ -18787,15 +19244,15 @@ function ensureRenderKey(home = homedir7()) {
18787
19244
  const p19 = renderKeyPath(home);
18788
19245
  try {
18789
19246
  const dir = resolve15(home, ".massu");
18790
- mkdirSync10(dir, { recursive: true, mode: 448 });
19247
+ mkdirSync12(dir, { recursive: true, mode: 448 });
18791
19248
  try {
18792
- chmodSync5(dir, 448);
19249
+ chmodSync6(dir, 448);
18793
19250
  } catch {
18794
19251
  }
18795
19252
  const key = randomBytes(32);
18796
- writeFileSync5(p19, key, { mode: 384 });
19253
+ writeFileSync6(p19, key, { mode: 384 });
18797
19254
  try {
18798
- chmodSync5(p19, 384);
19255
+ chmodSync6(p19, 384);
18799
19256
  } catch {
18800
19257
  }
18801
19258
  return key;
@@ -18844,11 +19301,11 @@ var init_memory_authorship = __esm({
18844
19301
  });
18845
19302
 
18846
19303
  // src/rule-candidate-snapshot.ts
18847
- import { existsSync as existsSync25, readFileSync as readFileSync18, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4 } from "fs";
19304
+ import { existsSync as existsSync26, readFileSync as readFileSync19, writeFileSync as writeFileSync7, unlinkSync as unlinkSync4 } from "fs";
18848
19305
  function takeSnapshots(paths) {
18849
19306
  const out = /* @__PURE__ */ new Map();
18850
19307
  for (const p19 of paths) {
18851
- if (existsSync25(p19)) out.set(p19, readFileSync18(p19, "utf-8"));
19308
+ if (existsSync26(p19)) out.set(p19, readFileSync19(p19, "utf-8"));
18852
19309
  else out.set(p19, null);
18853
19310
  }
18854
19311
  return out;
@@ -18858,9 +19315,9 @@ function restoreSnapshots(snapshot) {
18858
19315
  for (const [path, content] of snapshot) {
18859
19316
  try {
18860
19317
  if (content === null) {
18861
- if (existsSync25(path)) unlinkSync4(path);
19318
+ if (existsSync26(path)) unlinkSync4(path);
18862
19319
  } else {
18863
- writeFileSync6(path, content, "utf-8");
19320
+ writeFileSync7(path, content, "utf-8");
18864
19321
  }
18865
19322
  } catch (err) {
18866
19323
  errors.push(`${path}: ${err instanceof Error ? err.message : String(err)}`);
@@ -18938,18 +19395,18 @@ var init_memory_render_path = __esm({
18938
19395
  });
18939
19396
 
18940
19397
  // src/memory-tombstones.ts
18941
- import { readFileSync as readFileSync19, appendFileSync as appendFileSync2, existsSync as existsSync26 } from "fs";
18942
- import { join as join14 } from "path";
19398
+ import { readFileSync as readFileSync20, appendFileSync as appendFileSync3, existsSync as existsSync27 } from "fs";
19399
+ import { join as join15 } from "path";
18943
19400
  function tombstoneLedgerPath(memoryDir) {
18944
- return join14(memoryDir, TOMBSTONE_LEDGER);
19401
+ return join15(memoryDir, TOMBSTONE_LEDGER);
18945
19402
  }
18946
19403
  function readTombstones(memoryDir) {
18947
19404
  const out = /* @__PURE__ */ new Map();
18948
19405
  const p19 = tombstoneLedgerPath(memoryDir);
18949
- if (!existsSync26(p19)) return out;
19406
+ if (!existsSync27(p19)) return out;
18950
19407
  let raw;
18951
19408
  try {
18952
- raw = readFileSync19(p19, "utf8");
19409
+ raw = readFileSync20(p19, "utf8");
18953
19410
  } catch {
18954
19411
  return out;
18955
19412
  }
@@ -18977,7 +19434,7 @@ function tombstone(memoryDir, relPath, reason, nowEpoch) {
18977
19434
  reason
18978
19435
  };
18979
19436
  try {
18980
- appendFileSync2(tombstoneLedgerPath(memoryDir), `${JSON.stringify(entry)}
19437
+ appendFileSync3(tombstoneLedgerPath(memoryDir), `${JSON.stringify(entry)}
18981
19438
  `, "utf8");
18982
19439
  } catch (err) {
18983
19440
  throw new TombstoneWriteError(
@@ -19173,15 +19630,15 @@ var init_memory_llm = __esm({
19173
19630
  // src/memory-backup.ts
19174
19631
  import {
19175
19632
  readdirSync as readdirSync14,
19176
- mkdirSync as mkdirSync11,
19633
+ mkdirSync as mkdirSync13,
19177
19634
  copyFileSync as copyFileSync2,
19178
19635
  statSync as statSync12,
19179
- existsSync as existsSync27,
19180
- rmSync as rmSync5,
19181
- readFileSync as readFileSync20
19636
+ existsSync as existsSync28,
19637
+ rmSync as rmSync6,
19638
+ readFileSync as readFileSync21
19182
19639
  } from "fs";
19183
19640
  import { homedir as homedir8 } from "os";
19184
- import { join as join15, resolve as resolve16 } from "path";
19641
+ import { join as join16, resolve as resolve16 } from "path";
19185
19642
  function backupsRoot(home = homedir8()) {
19186
19643
  return resolve16(home, ".massu", "memory-backups");
19187
19644
  }
@@ -19189,10 +19646,10 @@ function backupStamp2(nowMs) {
19189
19646
  return new Date(nowMs).toISOString().replace(/:/g, "-");
19190
19647
  }
19191
19648
  function newestMtimeMs(dir) {
19192
- if (!existsSync27(dir)) return 0;
19649
+ if (!existsSync28(dir)) return 0;
19193
19650
  let newest = 0;
19194
19651
  for (const entry of readdirSync14(dir)) {
19195
- const p19 = join15(dir, entry);
19652
+ const p19 = join16(dir, entry);
19196
19653
  try {
19197
19654
  const st = statSync12(p19);
19198
19655
  if (st.isFile() && st.mtimeMs > newest) newest = st.mtimeMs;
@@ -19204,10 +19661,10 @@ function newestMtimeMs(dir) {
19204
19661
  }
19205
19662
  function listBackups(home = homedir8()) {
19206
19663
  const root = backupsRoot(home);
19207
- if (!existsSync27(root)) return [];
19664
+ if (!existsSync28(root)) return [];
19208
19665
  const out = [];
19209
19666
  for (const stamp of readdirSync14(root)) {
19210
- const dir = join15(root, stamp);
19667
+ const dir = join16(root, stamp);
19211
19668
  try {
19212
19669
  const st = statSync12(dir);
19213
19670
  if (!st.isDirectory()) continue;
@@ -19225,21 +19682,21 @@ function hasFreshBackup(memoryDir, home = homedir8()) {
19225
19682
  return backups[0].createdMs >= newestChange;
19226
19683
  }
19227
19684
  function takeBackup(memoryDir, nowMs, home = homedir8(), retention = DEFAULT_RETENTION2) {
19228
- if (!existsSync27(memoryDir)) {
19685
+ if (!existsSync28(memoryDir)) {
19229
19686
  throw new BackupError(`memory directory does not exist: ${memoryDir}`);
19230
19687
  }
19231
19688
  const stamp = backupStamp2(nowMs);
19232
- const dir = join15(backupsRoot(home), stamp);
19689
+ const dir = join16(backupsRoot(home), stamp);
19233
19690
  try {
19234
- mkdirSync11(dir, { recursive: true, mode: 448 });
19691
+ mkdirSync13(dir, { recursive: true, mode: 448 });
19235
19692
  for (const entry of readdirSync14(memoryDir)) {
19236
- const srcPath = join15(memoryDir, entry);
19693
+ const srcPath = join16(memoryDir, entry);
19237
19694
  try {
19238
19695
  if (!statSync12(srcPath).isFile()) continue;
19239
19696
  } catch {
19240
19697
  continue;
19241
19698
  }
19242
- copyFileSync2(srcPath, join15(dir, entry));
19699
+ copyFileSync2(srcPath, join16(dir, entry));
19243
19700
  }
19244
19701
  } catch (err) {
19245
19702
  throw new BackupError(`backup failed: ${err.message}`);
@@ -19251,7 +19708,7 @@ function pruneBackups(home = homedir8(), retention = DEFAULT_RETENTION2) {
19251
19708
  const backups = listBackups(home);
19252
19709
  for (const stale of backups.slice(Math.max(retention, 1))) {
19253
19710
  try {
19254
- rmSync5(stale.dir, { recursive: true, force: true });
19711
+ rmSync6(stale.dir, { recursive: true, force: true });
19255
19712
  } catch {
19256
19713
  }
19257
19714
  }
@@ -19265,14 +19722,14 @@ function restoreBackup(memoryDir, opts = {}) {
19265
19722
  const wouldRestore = [];
19266
19723
  for (const entry of readdirSync14(chosen.dir)) {
19267
19724
  try {
19268
- if (statSync12(join15(chosen.dir, entry)).isFile()) wouldRestore.push(entry);
19725
+ if (statSync12(join16(chosen.dir, entry)).isFile()) wouldRestore.push(entry);
19269
19726
  } catch {
19270
19727
  continue;
19271
19728
  }
19272
19729
  }
19273
- const currentFiles = existsSync27(memoryDir) ? readdirSync14(memoryDir).filter((e2) => {
19730
+ const currentFiles = existsSync28(memoryDir) ? readdirSync14(memoryDir).filter((e2) => {
19274
19731
  try {
19275
- return statSync12(join15(memoryDir, e2)).isFile();
19732
+ return statSync12(join16(memoryDir, e2)).isFile();
19276
19733
  } catch {
19277
19734
  return false;
19278
19735
  }
@@ -19287,10 +19744,10 @@ function restoreBackup(memoryDir, opts = {}) {
19287
19744
  presentButNotInBackup
19288
19745
  };
19289
19746
  }
19290
- mkdirSync11(memoryDir, { recursive: true });
19747
+ mkdirSync13(memoryDir, { recursive: true });
19291
19748
  let n = 0;
19292
19749
  for (const entry of wouldRestore) {
19293
- copyFileSync2(join15(chosen.dir, entry), join15(memoryDir, entry));
19750
+ copyFileSync2(join16(chosen.dir, entry), join16(memoryDir, entry));
19294
19751
  n++;
19295
19752
  }
19296
19753
  return {
@@ -19315,105 +19772,9 @@ var init_memory_backup = __esm({
19315
19772
  }
19316
19773
  });
19317
19774
 
19318
- // src/lib/fileLock.ts
19319
- import { mkdirSync as mkdirSync12, readFileSync as readFileSync21, rmSync as rmSync6, writeFileSync as writeFileSync7 } from "fs";
19320
- import { dirname as dirname14 } from "path";
19321
- import * as lockfile from "proper-lockfile";
19322
- function readLockHolderPid(lockPath) {
19323
- try {
19324
- const raw = readFileSync21(`${lockPath}.pid`, "utf-8").trim();
19325
- const pid = Number.parseInt(raw, 10);
19326
- if (!Number.isFinite(pid) || pid <= 0) return null;
19327
- return pid;
19328
- } catch {
19329
- return null;
19330
- }
19331
- }
19332
- function busyWaitSync(ms) {
19333
- if (typeof SharedArrayBuffer === "undefined" || typeof Atomics === "undefined") {
19334
- throw new Error(
19335
- `withFileLockSync requires SharedArrayBuffer + Atomics for its retry-loop wait. This Node runtime does not provide them \u2014 refusing to fall back to a CPU spinloop. If you hit this in a sandboxed serverless env, the fix is to perform the lock-protected operation in a host runtime that supports Atomics.`
19336
- );
19337
- }
19338
- const sab = new SharedArrayBuffer(4);
19339
- const view = new Int32Array(sab);
19340
- Atomics.wait(view, 0, 0, ms);
19341
- }
19342
- function withFileLockSync(lockPath, fn, opts = {}) {
19343
- mkdirSync12(dirname14(lockPath), { recursive: true });
19344
- const staleMs = opts.staleMs ?? 3e4;
19345
- const blockMs = opts.retries === 0 ? 0 : opts.blockMs ?? 3e4;
19346
- const pollIntervalMs = opts.pollIntervalMs ?? 100;
19347
- const now = opts.now ?? Date.now;
19348
- const sleep = opts.sleep ?? busyWaitSync;
19349
- const makeBusyError = opts.errorFactory ?? ((path, pid, retrySeconds, code) => new FileLockBusyError(path, pid, retrySeconds, code));
19350
- let release = null;
19351
- const deadline = now() + blockMs;
19352
- for (; ; ) {
19353
- try {
19354
- release = lockfile.lockSync(lockPath, {
19355
- stale: staleMs,
19356
- retries: 0,
19357
- realpath: false
19358
- });
19359
- try {
19360
- writeFileSync7(`${lockPath}.pid`, String(process.pid), "utf-8");
19361
- } catch {
19362
- }
19363
- break;
19364
- } catch (err) {
19365
- const e2 = err;
19366
- const code = e2.code;
19367
- if (code !== "ELOCKED" && code !== "EBUSY") {
19368
- throw err;
19369
- }
19370
- if (now() >= deadline) {
19371
- const holderPid = readLockHolderPid(lockPath);
19372
- const remainingMs = Math.max(0, deadline - now());
19373
- const retryAfterSeconds = blockMs === 0 ? Math.round(staleMs / 1e3) : Math.round(remainingMs / 1e3);
19374
- throw makeBusyError(lockPath, holderPid, retryAfterSeconds, code);
19375
- }
19376
- sleep(pollIntervalMs);
19377
- }
19378
- }
19379
- try {
19380
- return fn();
19381
- } finally {
19382
- try {
19383
- if (release) release();
19384
- } catch {
19385
- }
19386
- try {
19387
- rmSync6(`${lockPath}.pid`, { force: true });
19388
- } catch {
19389
- }
19390
- }
19391
- }
19392
- var FileLockBusyError;
19393
- var init_fileLock = __esm({
19394
- "src/lib/fileLock.ts"() {
19395
- "use strict";
19396
- FileLockBusyError = class extends Error {
19397
- constructor(lockPath, holderPid, retryAfterSeconds, causeCode) {
19398
- const pidPart = holderPid != null ? `(PID=${holderPid})` : "(PID=unknown)";
19399
- super(`File lock at ${lockPath} held by another process ${pidPart} \u2014 try again in ${retryAfterSeconds}s`);
19400
- this.lockPath = lockPath;
19401
- this.holderPid = holderPid;
19402
- this.retryAfterSeconds = retryAfterSeconds;
19403
- this.causeCode = causeCode;
19404
- this.name = "FileLockBusyError";
19405
- }
19406
- lockPath;
19407
- holderPid;
19408
- retryAfterSeconds;
19409
- causeCode;
19410
- };
19411
- }
19412
- });
19413
-
19414
19775
  // src/memory-index-region.ts
19415
- import { readFileSync as readFileSync22, existsSync as existsSync28 } from "fs";
19416
- import { dirname as dirname15, join as join16 } from "path";
19776
+ import { readFileSync as readFileSync22, existsSync as existsSync29 } from "fs";
19777
+ import { dirname as dirname16, join as join17 } from "path";
19417
19778
  function parseRegion(content) {
19418
19779
  const begins = countOccurrences(content, BEGIN_SENTINEL);
19419
19780
  const ends = countOccurrences(content, END_SENTINEL);
@@ -19505,7 +19866,7 @@ function readRegionLines(content) {
19505
19866
  return inner.split("\n").filter((l2) => l2.trim().length > 0);
19506
19867
  }
19507
19868
  function memoryIndexLockPath(memoryDir) {
19508
- return join16(dirname15(memoryDir), ".massu-memory-index.lock");
19869
+ return join17(dirname16(memoryDir), ".massu-memory-index.lock");
19509
19870
  }
19510
19871
  function withMemoryIndexLock(memoryDir, fn) {
19511
19872
  return withFileLockSync(memoryIndexLockPath(memoryDir), fn, {
@@ -19517,7 +19878,7 @@ function withMemoryIndexLock(memoryDir, fn) {
19517
19878
  });
19518
19879
  }
19519
19880
  function readMemoryIndex(indexPath) {
19520
- if (!existsSync28(indexPath)) return void 0;
19881
+ if (!existsSync29(indexPath)) return void 0;
19521
19882
  try {
19522
19883
  return readFileSync22(indexPath, "utf8");
19523
19884
  } catch {
@@ -19590,8 +19951,8 @@ var init_memory_files_config = __esm({
19590
19951
  });
19591
19952
 
19592
19953
  // src/memory-renderer.ts
19593
- import { existsSync as existsSync29, readFileSync as readFileSync23 } from "fs";
19594
- import { join as join17 } from "path";
19954
+ import { existsSync as existsSync30, readFileSync as readFileSync23 } from "fs";
19955
+ import { join as join18 } from "path";
19595
19956
  import { homedir as homedir9 } from "os";
19596
19957
  import { createHash as createHash8 } from "crypto";
19597
19958
  function renderMemoryFiles(db, candidates, opts) {
@@ -19605,7 +19966,7 @@ function renderMemoryFiles(db, candidates, opts) {
19605
19966
  const audit = opts.audit ?? (() => {
19606
19967
  });
19607
19968
  const { memoryDir } = opts;
19608
- if (!existsSync29(memoryDir)) {
19969
+ if (!existsSync30(memoryDir)) {
19609
19970
  return EMPTY("no_memory_dir");
19610
19971
  }
19611
19972
  try {
@@ -19673,7 +20034,7 @@ function renderLocked(db, candidates, o) {
19673
20034
  refusals.push({ name: c2.name, reason: "tombstoned" });
19674
20035
  continue;
19675
20036
  }
19676
- if (existsSync29(absPath)) {
20037
+ if (existsSync30(absPath)) {
19677
20038
  const existing = readFileSync23(absPath, "utf8");
19678
20039
  const fm = readMemoryFileFrontmatter(existing);
19679
20040
  const storeRow = db.prepare(
@@ -19723,7 +20084,7 @@ function renderLocked(db, candidates, o) {
19723
20084
  return EMPTY("backup_failed");
19724
20085
  }
19725
20086
  }
19726
- const indexPath = o.indexPath ?? join17(memoryDir, "MEMORY.md");
20087
+ const indexPath = o.indexPath ?? join18(memoryDir, "MEMORY.md");
19727
20088
  const targets = [...planned.map((p19) => p19.absPath), indexPath];
19728
20089
  const snapshot = takeSnapshots(targets);
19729
20090
  let bytesWritten = 0;
@@ -19895,16 +20256,16 @@ var init_memory_renderer = __esm({
19895
20256
  });
19896
20257
 
19897
20258
  // src/commands/memory-render-cli.ts
19898
- import { readdirSync as readdirSync15, readFileSync as readFileSync24, existsSync as existsSync30, rmSync as rmSync7, statSync as statSync13 } from "fs";
19899
- import { join as join18 } from "path";
20259
+ import { readdirSync as readdirSync15, readFileSync as readFileSync24, existsSync as existsSync31, rmSync as rmSync7, statSync as statSync13 } from "fs";
20260
+ import { join as join19 } from "path";
19900
20261
  import { homedir as homedir10 } from "os";
19901
20262
  function memoryFiles(memoryDir) {
19902
- if (!existsSync30(memoryDir)) return [];
20263
+ if (!existsSync31(memoryDir)) return [];
19903
20264
  return readdirSync15(memoryDir).filter((f2) => {
19904
20265
  if (!f2.endsWith(".md")) return false;
19905
20266
  if (f2 === "MEMORY.md") return false;
19906
20267
  try {
19907
- return statSync13(join18(memoryDir, f2)).isFile();
20268
+ return statSync13(join19(memoryDir, f2)).isFile();
19908
20269
  } catch {
19909
20270
  return false;
19910
20271
  }
@@ -19915,7 +20276,7 @@ function massuAuthoredFiles(db, memoryDir, home = homedir10()) {
19915
20276
  for (const f2 of memoryFiles(memoryDir)) {
19916
20277
  let content;
19917
20278
  try {
19918
- content = readFileSync24(join18(memoryDir, f2), "utf8");
20279
+ content = readFileSync24(join19(memoryDir, f2), "utf8");
19919
20280
  } catch {
19920
20281
  continue;
19921
20282
  }
@@ -19943,7 +20304,7 @@ function memoryAdopt(db, memoryDir, opts = {}) {
19943
20304
  for (const f2 of memoryFiles(memoryDir)) {
19944
20305
  const row = db.prepare(`SELECT id FROM memory_files WHERE rel_path = ? COLLATE NOCASE`).get(f2);
19945
20306
  if (row) continue;
19946
- const content = readFileSync24(join18(memoryDir, f2), "utf8");
20307
+ const content = readFileSync24(join19(memoryDir, f2), "utf8");
19947
20308
  if (verifyAuthorship(stripFrontmatter(content), readMemoryFileFrontmatter(content), null, home)) {
19948
20309
  candidates.push(f2);
19949
20310
  }
@@ -19973,7 +20334,7 @@ function memoryAdopt(db, memoryDir, opts = {}) {
19973
20334
  db.exec("BEGIN");
19974
20335
  try {
19975
20336
  for (const f2 of candidates) {
19976
- const content = readFileSync24(join18(memoryDir, f2), "utf8");
20337
+ const content = readFileSync24(join19(memoryDir, f2), "utf8");
19977
20338
  const fm = readMemoryFileFrontmatter(content);
19978
20339
  insert.run(
19979
20340
  f2,
@@ -20021,7 +20382,7 @@ function memoryUnrender(db, memoryDir, opts = {}) {
20021
20382
  for (const f2 of targets) {
20022
20383
  tombstone(memoryDir, f2, "unrendered", now);
20023
20384
  try {
20024
- rmSync7(join18(memoryDir, f2));
20385
+ rmSync7(join19(memoryDir, f2));
20025
20386
  } catch {
20026
20387
  }
20027
20388
  db.prepare(`UPDATE memory_files SET tombstoned_at_epoch = ? WHERE rel_path = ? COLLATE NOCASE`).run(
@@ -20029,7 +20390,7 @@ function memoryUnrender(db, memoryDir, opts = {}) {
20029
20390
  f2
20030
20391
  );
20031
20392
  }
20032
- const indexPath = join18(memoryDir, "MEMORY.md");
20393
+ const indexPath = join19(memoryDir, "MEMORY.md");
20033
20394
  const pre = readMemoryIndex(indexPath);
20034
20395
  if (pre !== void 0) {
20035
20396
  try {
@@ -20104,16 +20465,16 @@ var init_memory_render_candidates = __esm({
20104
20465
  });
20105
20466
 
20106
20467
  // src/capability-advisor.ts
20107
- import { existsSync as existsSync31, mkdirSync as mkdirSync13, readFileSync as readFileSync25, writeFileSync as writeFileSync8 } from "fs";
20468
+ import { existsSync as existsSync32, mkdirSync as mkdirSync14, readFileSync as readFileSync25, writeFileSync as writeFileSync8 } from "fs";
20108
20469
  import { homedir as homedir11 } from "os";
20109
- import { dirname as dirname16, join as join19 } from "path";
20470
+ import { dirname as dirname17, join as join20 } from "path";
20110
20471
  function advisorStatePath(home = homedir11()) {
20111
- return join19(home, ".massu", "advisor-state.json");
20472
+ return join20(home, ".massu", "advisor-state.json");
20112
20473
  }
20113
20474
  function readAdvisorState(home) {
20114
20475
  try {
20115
20476
  const p19 = advisorStatePath(home);
20116
- if (!existsSync31(p19)) return {};
20477
+ if (!existsSync32(p19)) return {};
20117
20478
  return JSON.parse(readFileSync25(p19, "utf-8"));
20118
20479
  } catch {
20119
20480
  return {};
@@ -20122,7 +20483,7 @@ function readAdvisorState(home) {
20122
20483
  function writeAdvisorState(state, home) {
20123
20484
  try {
20124
20485
  const p19 = advisorStatePath(home);
20125
- mkdirSync13(dirname16(p19), { recursive: true });
20486
+ mkdirSync14(dirname17(p19), { recursive: true });
20126
20487
  writeFileSync8(p19, JSON.stringify(state, null, 2), { mode: 384 });
20127
20488
  } catch {
20128
20489
  }
@@ -20714,8 +21075,8 @@ var init_rule_candidate_hardened = __esm({
20714
21075
  });
20715
21076
 
20716
21077
  // src/rule-candidate-applier.ts
20717
- import { readFileSync as readFileSync26, writeFileSync as writeFileSync9, existsSync as existsSync32, unlinkSync as unlinkSync5, mkdirSync as mkdirSync14 } from "fs";
20718
- import { join as join20, dirname as dirname17, isAbsolute as isAbsolute2 } from "path";
21078
+ import { readFileSync as readFileSync26, writeFileSync as writeFileSync9, existsSync as existsSync33, unlinkSync as unlinkSync5, mkdirSync as mkdirSync15 } from "fs";
21079
+ import { join as join21, dirname as dirname18, isAbsolute as isAbsolute2 } from "path";
20719
21080
  import { homedir as homedir12 } from "os";
20720
21081
  import { createHash as createHash9 } from "crypto";
20721
21082
  function isRuleDestination(value) {
@@ -20725,10 +21086,10 @@ function isTeamShareableDestination(destination) {
20725
21086
  return TEAM_SHAREABLE_DESTINATIONS.includes(destination);
20726
21087
  }
20727
21088
  function resolveMemoryDir(projectRoot = getProjectRoot(), home = homedir12()) {
20728
- return join20(home, ".claude", "projects", encodeMemoryDirName(projectRoot), "memory");
21089
+ return join21(home, ".claude", "projects", encodeMemoryDirName(projectRoot), "memory");
20729
21090
  }
20730
21091
  function resolveMemoryIndexPath(projectRoot = getProjectRoot(), home = homedir12()) {
20731
- return join20(resolveMemoryDir(projectRoot, home), "MEMORY.md");
21092
+ return join21(resolveMemoryDir(projectRoot, home), "MEMORY.md");
20732
21093
  }
20733
21094
  function deriveSlug2(prompt) {
20734
21095
  return deriveSlug(prompt);
@@ -20747,17 +21108,17 @@ function writeIndexLineInRegion(indexPath, line) {
20747
21108
  function correctionsMdTargets(slug, projectRoot, home) {
20748
21109
  const dir = resolveMemoryDir(projectRoot, home);
20749
21110
  return {
20750
- correctionsMd: join20(dir, "corrections.md"),
20751
- feedbackMd: join20(dir, `feedback_${slug}.md`),
20752
- memoryIndex: join20(dir, "MEMORY.md")
21111
+ correctionsMd: join21(dir, "corrections.md"),
21112
+ feedbackMd: join21(dir, `feedback_${slug}.md`),
21113
+ memoryIndex: join21(dir, "MEMORY.md")
20753
21114
  };
20754
21115
  }
20755
21116
  function readCandidate(candidateId, projectRoot = getProjectRoot()) {
20756
21117
  if (!CANDIDATE_ID_PATTERN.test(candidateId)) {
20757
21118
  throw new InvalidCandidateIdError(candidateId);
20758
21119
  }
20759
- const path = join20(projectRoot, ".massu", "rule-candidates", `${candidateId}.json`);
20760
- if (!existsSync32(path)) throw new CandidateNotFoundError(path);
21120
+ const path = join21(projectRoot, ".massu", "rule-candidates", `${candidateId}.json`);
21121
+ if (!existsSync33(path)) throw new CandidateNotFoundError(path);
20761
21122
  const raw = readFileSync26(path, "utf-8");
20762
21123
  let parsed;
20763
21124
  try {
@@ -20869,7 +21230,7 @@ async function applyRuleCandidate(db, opts) {
20869
21230
  throw new InvalidSlugError(slug);
20870
21231
  }
20871
21232
  const memoryIndex = resolveMemoryIndexPath(projectRoot, home);
20872
- if (!existsSync32(memoryIndex)) {
21233
+ if (!existsSync33(memoryIndex)) {
20873
21234
  throw new MemoryIndexMissingError(memoryIndex);
20874
21235
  }
20875
21236
  let destTargets;
@@ -20878,7 +21239,7 @@ async function applyRuleCandidate(db, opts) {
20878
21239
  } catch (err) {
20879
21240
  return { ok: false, error: err instanceof Error ? err.message : String(err) };
20880
21241
  }
20881
- const candidatePath = join20(projectRoot, ".massu", "rule-candidates", `${opts.candidateId}.json`);
21242
+ const candidatePath = join21(projectRoot, ".massu", "rule-candidates", `${opts.candidateId}.json`);
20882
21243
  const snapshot = takeSnapshots([
20883
21244
  ...destTargets.paths,
20884
21245
  memoryIndex
@@ -20925,7 +21286,7 @@ async function applyRuleCandidate(db, opts) {
20925
21286
  throw err;
20926
21287
  }
20927
21288
  }
20928
- if (existsSync32(candidatePath)) unlinkSync5(candidatePath);
21289
+ if (existsSync33(candidatePath)) unlinkSync5(candidatePath);
20929
21290
  let teamShared = false;
20930
21291
  const localOrigin = candidate.provenance?.origin !== "team" && candidate.provenance?.origin !== "pack";
20931
21292
  const entitledTeam = entitledForTeamSharedPromotion(ent.currentTier);
@@ -20970,15 +21331,15 @@ function computeDestinationTargets(opts, candidate, slug, projectRoot, home) {
20970
21331
  if (opts.patternScannerCheckNumber == null) {
20971
21332
  throw new DestinationConfigError("pattern-scanner destination requires patternScannerCheckNumber");
20972
21333
  }
20973
- const scannerPath = join20(projectRoot, "scripts", "massu-pattern-scanner.sh");
20974
- const driftGuardPath = join20(projectRoot, "packages", "core", "src", "__tests__", `${slug}-drift-guard.test.ts`);
21334
+ const scannerPath = join21(projectRoot, "scripts", "massu-pattern-scanner.sh");
21335
+ const driftGuardPath = join21(projectRoot, "packages", "core", "src", "__tests__", `${slug}-drift-guard.test.ts`);
20975
21336
  return { primary: scannerPath, paths: [scannerPath, driftGuardPath] };
20976
21337
  }
20977
21338
  if (opts.destination === "claude-md-cr") {
20978
21339
  if (opts.claudeMdCrNumber == null) {
20979
21340
  throw new DestinationConfigError("claude-md-cr destination requires claudeMdCrNumber");
20980
21341
  }
20981
- const claudePath = join20(projectRoot, ".claude", "CLAUDE.md");
21342
+ const claudePath = join21(projectRoot, ".claude", "CLAUDE.md");
20982
21343
  return { primary: claudePath, paths: [claudePath] };
20983
21344
  }
20984
21345
  if (opts.destination === "custom-destination") {
@@ -20986,7 +21347,7 @@ function computeDestinationTargets(opts, candidate, slug, projectRoot, home) {
20986
21347
  throw new DestinationConfigError("custom-destination requires customDestination config entry");
20987
21348
  }
20988
21349
  const raw = opts.customDestination.path;
20989
- const absolute = isAbsolute2(raw) ? raw : join20(projectRoot, raw);
21350
+ const absolute = isAbsolute2(raw) ? raw : join21(projectRoot, raw);
20990
21351
  try {
20991
21352
  assertContainedIn(projectRoot, absolute, { allowNested: true });
20992
21353
  } catch (err) {
@@ -21026,8 +21387,8 @@ function writeCorrectionsMd(opts, candidate, slug, targets, auditRowId) {
21026
21387
  audit_log_id: auditRowId
21027
21388
  }
21028
21389
  });
21029
- if (!existsSync32(dirname17(correctionsMd))) mkdirSync14(dirname17(correctionsMd), { recursive: true });
21030
- const correctionsPre = existsSync32(correctionsMd) ? readFileSync26(correctionsMd, "utf-8") : "# Corrections\n";
21390
+ if (!existsSync33(dirname18(correctionsMd))) mkdirSync15(dirname18(correctionsMd), { recursive: true });
21391
+ const correctionsPre = existsSync33(correctionsMd) ? readFileSync26(correctionsMd, "utf-8") : "# Corrections\n";
21031
21392
  writeFileSync9(correctionsMd, correctionsPre + correctionsEntry, "utf-8");
21032
21393
  const body = `${opts.draftText}
21033
21394
  `;
@@ -21053,7 +21414,7 @@ function writeCorrectionsMd(opts, candidate, slug, targets, auditRowId) {
21053
21414
  function writePatternScanner(opts, candidate, slug, targets) {
21054
21415
  const [scannerPath, driftGuardPath] = targets.paths;
21055
21416
  const checkNumber = opts.patternScannerCheckNumber;
21056
- const scannerPre = existsSync32(scannerPath) ? readFileSync26(scannerPath, "utf-8") : "";
21417
+ const scannerPre = existsSync33(scannerPath) ? readFileSync26(scannerPath, "utf-8") : "";
21057
21418
  if (scannerPre.includes(`${SCANNER_AUTOGEN_MARKER_PREFIX} ${candidate.prompt_hash}`)) {
21058
21419
  throw new DestinationConfigError(
21059
21420
  `scanner already contains a check auto-generated for prompt_hash ${candidate.prompt_hash}`
@@ -21089,13 +21450,13 @@ function writePatternScanner(opts, candidate, slug, targets) {
21089
21450
  `});`,
21090
21451
  ""
21091
21452
  ].join("\n");
21092
- if (!existsSync32(dirname17(driftGuardPath))) mkdirSync14(dirname17(driftGuardPath), { recursive: true });
21453
+ if (!existsSync33(dirname18(driftGuardPath))) mkdirSync15(dirname18(driftGuardPath), { recursive: true });
21093
21454
  writeFileSync9(driftGuardPath, driftGuard, "utf-8");
21094
21455
  }
21095
21456
  function writeClaudeMdCr(opts, candidate, slug, targets) {
21096
21457
  const [claudePath] = targets.paths;
21097
21458
  const crNumber = opts.claudeMdCrNumber;
21098
- const pre = existsSync32(claudePath) ? readFileSync26(claudePath, "utf-8") : "";
21459
+ const pre = existsSync33(claudePath) ? readFileSync26(claudePath, "utf-8") : "";
21099
21460
  if (new RegExp(`\\bCR-${crNumber}\\b`).test(pre)) {
21100
21461
  throw new DestinationConfigError(`CLAUDE.md already contains a CR-${crNumber} entry`);
21101
21462
  }
@@ -21137,8 +21498,8 @@ function writeCustomDestination(opts, candidate, slug, targets) {
21137
21498
  destination_name: entry.name
21138
21499
  };
21139
21500
  const rendered = renderTemplate2(entry.template, vars);
21140
- if (!existsSync32(dirname17(destPath))) mkdirSync14(dirname17(destPath), { recursive: true });
21141
- const pre = existsSync32(destPath) ? readFileSync26(destPath, "utf-8") : "";
21501
+ if (!existsSync33(dirname18(destPath))) mkdirSync15(dirname18(destPath), { recursive: true });
21502
+ const pre = existsSync33(destPath) ? readFileSync26(destPath, "utf-8") : "";
21142
21503
  const sep3 = pre && !pre.endsWith("\n") ? "\n" : "";
21143
21504
  writeFileSync9(destPath, pre + sep3 + rendered + (rendered.endsWith("\n") ? "" : "\n"), "utf-8");
21144
21505
  }
@@ -21148,7 +21509,7 @@ function dismissRuleCandidate(db, opts) {
21148
21509
  }
21149
21510
  const projectRoot = opts.projectRoot ?? getProjectRoot();
21150
21511
  const candidate = readCandidate(opts.candidateId, projectRoot);
21151
- const candidatePath = join20(projectRoot, ".massu", "rule-candidates", `${opts.candidateId}.json`);
21512
+ const candidatePath = join21(projectRoot, ".massu", "rule-candidates", `${opts.candidateId}.json`);
21152
21513
  db.exec("BEGIN");
21153
21514
  let auditRowId;
21154
21515
  let blacklistUpdates = 0;
@@ -21190,9 +21551,9 @@ function dismissRuleCandidate(db, opts) {
21190
21551
  };
21191
21552
  }
21192
21553
  try {
21193
- const dismissedLog = join20(projectRoot, ".massu", "rule-candidates", ".dismissed.jsonl");
21194
- if (!existsSync32(dirname17(dismissedLog))) mkdirSync14(dirname17(dismissedLog), { recursive: true });
21195
- const pre = existsSync32(dismissedLog) ? readFileSync26(dismissedLog, "utf-8") : "";
21554
+ const dismissedLog = join21(projectRoot, ".massu", "rule-candidates", ".dismissed.jsonl");
21555
+ if (!existsSync33(dirname18(dismissedLog))) mkdirSync15(dirname18(dismissedLog), { recursive: true });
21556
+ const pre = existsSync33(dismissedLog) ? readFileSync26(dismissedLog, "utf-8") : "";
21196
21557
  const sep3 = pre && !pre.endsWith("\n") ? "\n" : "";
21197
21558
  writeFileSync9(dismissedLog, pre + sep3 + JSON.stringify({
21198
21559
  id: opts.candidateId,
@@ -21203,7 +21564,7 @@ function dismissRuleCandidate(db, opts) {
21203
21564
  audit_log_id: auditRowId,
21204
21565
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
21205
21566
  }) + "\n", "utf-8");
21206
- if (existsSync32(candidatePath)) unlinkSync5(candidatePath);
21567
+ if (existsSync33(candidatePath)) unlinkSync5(candidatePath);
21207
21568
  } catch (err) {
21208
21569
  appendFailureLog(projectRoot, {
21209
21570
  candidate_id: opts.candidateId,
@@ -21221,10 +21582,10 @@ function dismissRuleCandidate(db, opts) {
21221
21582
  }
21222
21583
  function appendFailureLog(projectRoot, entry) {
21223
21584
  try {
21224
- const dir = join20(projectRoot, ".massu", "rule-candidates");
21225
- if (!existsSync32(dir)) mkdirSync14(dir, { recursive: true });
21226
- const logPath = join20(dir, ".failures.jsonl");
21227
- const pre = existsSync32(logPath) ? readFileSync26(logPath, "utf-8") : "";
21585
+ const dir = join21(projectRoot, ".massu", "rule-candidates");
21586
+ if (!existsSync33(dir)) mkdirSync15(dir, { recursive: true });
21587
+ const logPath = join21(dir, ".failures.jsonl");
21588
+ const pre = existsSync33(logPath) ? readFileSync26(logPath, "utf-8") : "";
21228
21589
  const sep3 = pre && !pre.endsWith("\n") ? "\n" : "";
21229
21590
  writeFileSync9(logPath, pre + sep3 + JSON.stringify(entry) + "\n", "utf-8");
21230
21591
  } catch {
@@ -21283,7 +21644,7 @@ var init_rule_candidate_applier = __esm({
21283
21644
  ];
21284
21645
  MemoryIndexMissingError = class extends Error {
21285
21646
  constructor(path) {
21286
- super(`MEMORY.md missing at ${path} \u2014 v0.2 requires the canonical memory index. Create it via \`mkdir -p ${dirname17(path)} && echo '# Memory Index' > ${path}\` or run \`/massu-bearings\``);
21647
+ super(`MEMORY.md missing at ${path} \u2014 v0.2 requires the canonical memory index. Create it via \`mkdir -p ${dirname18(path)} && echo '# Memory Index' > ${path}\` or run \`/massu-bearings\``);
21287
21648
  this.path = path;
21288
21649
  this.name = "MemoryIndexMissingError";
21289
21650
  }
@@ -21307,7 +21668,7 @@ var init_rule_candidate_applier = __esm({
21307
21668
  });
21308
21669
 
21309
21670
  // src/rule-candidate-preview.ts
21310
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync10, existsSync as existsSync33 } from "node:fs";
21671
+ import { readFileSync as readFileSync27, writeFileSync as writeFileSync10, existsSync as existsSync34 } from "node:fs";
21311
21672
  function renderHardenedPreview(destination, body) {
21312
21673
  const rendered = String(body ?? "");
21313
21674
  const riskFindings = RISK_PATTERNS.filter((p19) => p19.re.test(rendered)).map((p19) => p19.label);
@@ -21335,7 +21696,7 @@ function validateReviewAttestation(att) {
21335
21696
  };
21336
21697
  }
21337
21698
  function recordHardenedReviewAttestation(sidecarPath2, attestation) {
21338
- if (!existsSync33(sidecarPath2)) {
21699
+ if (!existsSync34(sidecarPath2)) {
21339
21700
  throw new Error(`candidate sidecar not found: ${sidecarPath2}`);
21340
21701
  }
21341
21702
  const validated = validateReviewAttestation(attestation);
@@ -21447,7 +21808,7 @@ var init_rule_candidate_renderer = __esm({
21447
21808
  });
21448
21809
 
21449
21810
  // src/rule-promotion-effectiveness.ts
21450
- import { readFileSync as readFileSync28, existsSync as existsSync34 } from "fs";
21811
+ import { readFileSync as readFileSync28, existsSync as existsSync35 } from "fs";
21451
21812
  function evaluateCr53Effectiveness(inputs) {
21452
21813
  const { db, failureLogPath, knownLimitations } = inputs;
21453
21814
  const allowlist = new Set(knownLimitations.map((k3) => k3.promptHash));
@@ -21478,7 +21839,7 @@ function evaluateCr53Effectiveness(inputs) {
21478
21839
  });
21479
21840
  }
21480
21841
  const failureLogViolations = [];
21481
- if (existsSync34(failureLogPath)) {
21842
+ if (existsSync35(failureLogPath)) {
21482
21843
  try {
21483
21844
  const raw = readFileSync28(failureLogPath, "utf-8");
21484
21845
  const cutoff = Date.now() - SEVEN_DAYS_MS;
@@ -21657,8 +22018,8 @@ var init_rule_pack_schema = __esm({
21657
22018
  });
21658
22019
 
21659
22020
  // src/rule-pack-sync.ts
21660
- import { existsSync as existsSync35, writeFileSync as writeFileSync11, mkdirSync as mkdirSync15 } from "fs";
21661
- import { join as join21, dirname as dirname18 } from "path";
22021
+ import { existsSync as existsSync36, writeFileSync as writeFileSync11, mkdirSync as mkdirSync16 } from "fs";
22022
+ import { join as join22, dirname as dirname19 } from "path";
21662
22023
  async function pullInstalledPackRules(db, opts = {}) {
21663
22024
  const config = getConfig();
21664
22025
  const cloud = config.cloud;
@@ -21721,7 +22082,7 @@ async function pullInstalledPackRules(db, opts = {}) {
21721
22082
  result.pulled += 1;
21722
22083
  const promptHash = packRulePromptHash(pack.slug, rule);
21723
22084
  const candidatePath = sidecarPath(projectRoot, promptHash);
21724
- if (existsSync35(candidatePath) || alreadyApplied(db, promptHash)) {
22085
+ if (existsSync36(candidatePath) || alreadyApplied(db, promptHash)) {
21725
22086
  result.skipped += 1;
21726
22087
  continue;
21727
22088
  }
@@ -21759,7 +22120,7 @@ function packRulePromptHash(slug, rule) {
21759
22120
  return createHash15("sha256").update(body, "utf-8").digest("hex").slice(0, 16);
21760
22121
  }
21761
22122
  function sidecarPath(projectRoot, promptHash) {
21762
- return join21(projectRoot, ".massu", "rule-candidates", `${promptHash}.json`);
22123
+ return join22(projectRoot, ".massu", "rule-candidates", `${promptHash}.json`);
21763
22124
  }
21764
22125
  function alreadyApplied(db, promptHash) {
21765
22126
  try {
@@ -21808,8 +22169,8 @@ function materializeCandidate(projectRoot, candidatePath, promptHash, rule, pack
21808
22169
  destination: rule.destination,
21809
22170
  draft_text: draftText
21810
22171
  };
21811
- const dir = dirname18(candidatePath);
21812
- if (!existsSync35(dir)) mkdirSync15(dir, { recursive: true });
22172
+ const dir = dirname19(candidatePath);
22173
+ if (!existsSync36(dir)) mkdirSync16(dir, { recursive: true });
21813
22174
  writeFileSync11(candidatePath, JSON.stringify(sidecar, null, 2), "utf-8");
21814
22175
  }
21815
22176
  function emitDropTelemetry(db, eventType, data) {
@@ -21852,7 +22213,7 @@ var rule_exports = {};
21852
22213
  __export(rule_exports, {
21853
22214
  handleRuleSubcommand: () => handleRuleSubcommand
21854
22215
  });
21855
- import { join as join22 } from "node:path";
22216
+ import { join as join23 } from "node:path";
21856
22217
  function flagValue2(args2, flag) {
21857
22218
  const i = args2.indexOf(flag);
21858
22219
  if (i === -1 || i === args2.length - 1) return void 0;
@@ -21909,7 +22270,7 @@ async function handleRuleSubcommand(args2) {
21909
22270
  case "effectiveness": {
21910
22271
  const db = getMemoryDb();
21911
22272
  try {
21912
- const failureLogPath = join22(
22273
+ const failureLogPath = join23(
21913
22274
  getProjectRoot(),
21914
22275
  ".massu",
21915
22276
  "rule-candidates",
@@ -22032,7 +22393,7 @@ ${"-".repeat(60)}
22032
22393
  reviewed_at: (/* @__PURE__ */ new Date()).toISOString(),
22033
22394
  note: flagValue2(args2, "--attest-note") ?? ""
22034
22395
  });
22035
- const sidecar = join22(getProjectRoot(), ".massu", "rule-candidates", `${candidateId}.json`);
22396
+ const sidecar = join23(getProjectRoot(), ".massu", "rule-candidates", `${candidateId}.json`);
22036
22397
  recordHardenedReviewAttestation(sidecar, attestation);
22037
22398
  process.stdout.write(`Attestation recorded by '${operator}'. This candidate may now be approved.
22038
22399
  `);
@@ -22680,8 +23041,8 @@ var init_memory_supersede = __esm({
22680
23041
 
22681
23042
  // src/memory-consolidate.ts
22682
23043
  import { createHash as createHash10 } from "crypto";
22683
- import { existsSync as existsSync36, mkdirSync as mkdirSync16, writeFileSync as writeFileSync12 } from "fs";
22684
- import { join as join23 } from "path";
23044
+ import { existsSync as existsSync37, mkdirSync as mkdirSync17, writeFileSync as writeFileSync12 } from "fs";
23045
+ import { join as join24 } from "path";
22685
23046
  function emptyResult() {
22686
23047
  return {
22687
23048
  deduped: 0,
@@ -22843,7 +23204,7 @@ ${r2.detail ?? ""}`.trim());
22843
23204
  }
22844
23205
  clusters.push(cluster);
22845
23206
  }
22846
- const candidateDir = join23(projectRoot, ".massu", "rule-candidates");
23207
+ const candidateDir = join24(projectRoot, ".massu", "rule-candidates");
22847
23208
  let promoted = 0;
22848
23209
  for (const cluster of clusters) {
22849
23210
  const occurrences = cluster.reduce((n, c2) => n + (c2.recurrence_count || 1), 0);
@@ -22856,13 +23217,13 @@ ${r2.detail ?? ""}`.trim());
22856
23217
  ${representative.detail}` : ""}`;
22857
23218
  const clusterKey = cluster.map((c2) => c2.title.toLowerCase().replace(/\s+/g, " ").trim()).sort().join("|");
22858
23219
  const promptHash = createHash10("sha256").update(clusterKey).digest("hex").slice(0, 16);
22859
- const candidatePath = join23(candidateDir, `${promptHash}.json`);
22860
- if (existsSync36(candidatePath)) continue;
23220
+ const candidatePath = join24(candidateDir, `${promptHash}.json`);
23221
+ if (existsSync37(candidatePath)) continue;
22861
23222
  if (dryRun) {
22862
23223
  promoted++;
22863
23224
  continue;
22864
23225
  }
22865
- mkdirSync16(candidateDir, { recursive: true });
23226
+ mkdirSync17(candidateDir, { recursive: true });
22866
23227
  writeFileSync12(
22867
23228
  candidatePath,
22868
23229
  JSON.stringify(
@@ -23049,7 +23410,23 @@ async function runConsolidateCommand(args2 = []) {
23049
23410
  return { exitCode: 1 };
23050
23411
  }
23051
23412
  const cfg = resolveConsolidationConfig();
23052
- const db = getMemoryDb();
23413
+ let db;
23414
+ try {
23415
+ db = getMemoryDb();
23416
+ } catch (err) {
23417
+ if (err instanceof MemoryEngineUnusableError) {
23418
+ if (json) {
23419
+ process.stdout.write(
23420
+ JSON.stringify({ error: "memory-engine-unusable", reason: err.reason, remedy: err.remedy }) + "\n"
23421
+ );
23422
+ } else {
23423
+ process.stderr.write(`massu consolidate: the memory engine is unavailable \u2014 ${err.remedy}
23424
+ `);
23425
+ }
23426
+ return { exitCode: 1 };
23427
+ }
23428
+ throw err;
23429
+ }
23053
23430
  try {
23054
23431
  const result = await runConsolidation(db, {
23055
23432
  config: cfg,
@@ -23125,6 +23502,7 @@ var init_consolidate = __esm({
23125
23502
  init_memory_db();
23126
23503
  init_memory_consolidate();
23127
23504
  init_consolidation_config();
23505
+ init_sqlite_loader();
23128
23506
  }
23129
23507
  });
23130
23508
 
@@ -23133,7 +23511,7 @@ var show_template_exports = {};
23133
23511
  __export(show_template_exports, {
23134
23512
  runShowTemplate: () => runShowTemplate
23135
23513
  });
23136
- import { existsSync as existsSync37, readFileSync as readFileSync29 } from "fs";
23514
+ import { existsSync as existsSync38, readFileSync as readFileSync29 } from "fs";
23137
23515
  import { resolve as resolve17 } from "path";
23138
23516
  function normalizeBaseName(input) {
23139
23517
  return input.endsWith(".md") ? input.slice(0, -".md".length) : input;
@@ -23163,7 +23541,7 @@ async function runShowTemplate(args2) {
23163
23541
  }
23164
23542
  const suffix = choice.kind === "hit" ? choice.suffix : "";
23165
23543
  const file = suffix === "" ? resolve17(sourceDir, `${baseName}.md`) : resolve17(sourceDir, `${baseName}${suffix}.md`);
23166
- if (!existsSync37(file)) {
23544
+ if (!existsSync38(file)) {
23167
23545
  process.stderr.write(`massu: resolved template "${file}" no longer exists
23168
23546
  `);
23169
23547
  process.exit(1);
@@ -23264,7 +23642,7 @@ __export(config_refresh_exports, {
23264
23642
  mergeRefresh: () => mergeRefresh,
23265
23643
  runConfigRefresh: () => runConfigRefresh
23266
23644
  });
23267
- import { existsSync as existsSync38, readFileSync as readFileSync30, rmSync as rmSync8 } from "fs";
23645
+ import { existsSync as existsSync39, readFileSync as readFileSync30, rmSync as rmSync8 } from "fs";
23268
23646
  import { resolve as resolve19 } from "path";
23269
23647
  import { parse as parseYaml5 } from "yaml";
23270
23648
  function flatten(obj, prefix3 = "") {
@@ -23396,7 +23774,7 @@ async function runConfigRefresh(opts = {}) {
23396
23774
  const configPath = resolve19(cwd, "massu.config.yaml");
23397
23775
  const log = opts.silent ? () => {
23398
23776
  } : (s) => process.stdout.write(s);
23399
- if (!existsSync38(configPath)) {
23777
+ if (!existsSync39(configPath)) {
23400
23778
  const message = "massu.config.yaml not found. Run: npx massu init";
23401
23779
  if (!opts.silent) process.stderr.write(message + "\n");
23402
23780
  return { exitCode: 1, applied: false, dryRun: !!opts.dryRun, diff: [], message };
@@ -23477,7 +23855,7 @@ async function runConfigRefresh(opts = {}) {
23477
23855
  const stackResolved = installResult.totalInstalled > 0 || installResult.totalUpdated > 0;
23478
23856
  if (stackResolved) {
23479
23857
  const placeholderPath = resolve19(installResult.claudeDir, "commands", "_massu-needs-stack.md");
23480
- if (existsSync38(placeholderPath)) {
23858
+ if (existsSync39(placeholderPath)) {
23481
23859
  try {
23482
23860
  rmSync8(placeholderPath, { force: true });
23483
23861
  log("Removed _massu-needs-stack.md (stack now declared).\n");
@@ -23527,7 +23905,7 @@ var init_config_refresh = __esm({
23527
23905
  });
23528
23906
 
23529
23907
  // src/lib/pidLiveness.ts
23530
- import { spawnSync } from "child_process";
23908
+ import { spawnSync as spawnSync2 } from "child_process";
23531
23909
  function isPidAlive(pid, opts = {}) {
23532
23910
  if (!Number.isFinite(pid) || pid <= 0) return false;
23533
23911
  const platform = opts.platformOverride ?? process.platform;
@@ -23552,7 +23930,7 @@ function checkPosix(pid, killOverride) {
23552
23930
  }
23553
23931
  function checkWindows(pid) {
23554
23932
  try {
23555
- const res = spawnSync("tasklist", ["/FI", `PID eq ${pid}`, "/NH"], {
23933
+ const res = spawnSync2("tasklist", ["/FI", `PID eq ${pid}`, "/NH"], {
23556
23934
  encoding: "utf-8",
23557
23935
  windowsHide: true
23558
23936
  });
@@ -23570,9 +23948,9 @@ var init_pidLiveness = __esm({
23570
23948
  });
23571
23949
 
23572
23950
  // src/lib/gitToplevel.ts
23573
- import { spawnSync as spawnSync2 } from "child_process";
23951
+ import { spawnSync as spawnSync3 } from "child_process";
23574
23952
  function gitToplevel(cwd) {
23575
- const res = spawnSync2("git", ["rev-parse", "--show-toplevel"], {
23953
+ const res = spawnSync3("git", ["rev-parse", "--show-toplevel"], {
23576
23954
  cwd,
23577
23955
  encoding: "utf-8"
23578
23956
  });
@@ -23586,12 +23964,12 @@ var init_gitToplevel = __esm({
23586
23964
  });
23587
23965
 
23588
23966
  // src/watch/lockfile-detector.ts
23589
- import { existsSync as existsSync39, statSync as statSync14 } from "fs";
23967
+ import { existsSync as existsSync40, statSync as statSync14 } from "fs";
23590
23968
  import { resolve as resolve20 } from "path";
23591
23969
  function lockfileMidWrite(projectRoot, now = Date.now(), windowMs = LOCKFILE_WINDOW_MS) {
23592
23970
  for (const lf of KNOWN_LOCKFILES) {
23593
23971
  const p19 = resolve20(projectRoot, lf);
23594
- if (!existsSync39(p19)) continue;
23972
+ if (!existsSync40(p19)) continue;
23595
23973
  try {
23596
23974
  const stat = statSync14(p19);
23597
23975
  const delta = now - stat.mtimeMs;
@@ -23604,7 +23982,7 @@ function lockfileMidWrite(projectRoot, now = Date.now(), windowMs = LOCKFILE_WIN
23604
23982
  function gitMidOperation(projectRoot) {
23605
23983
  const sentinels = ["MERGE_HEAD", "REBASE_HEAD", "CHERRY_PICK_HEAD", "rebase-apply", "rebase-merge"];
23606
23984
  for (const s of sentinels) {
23607
- if (existsSync39(resolve20(projectRoot, ".git", s))) return true;
23985
+ if (existsSync40(resolve20(projectRoot, ".git", s))) return true;
23608
23986
  }
23609
23987
  return false;
23610
23988
  }
@@ -23803,8 +24181,8 @@ var init_paths = __esm({
23803
24181
  });
23804
24182
 
23805
24183
  // src/watch/state.ts
23806
- import { closeSync as closeSync4, existsSync as existsSync40, fsyncSync as fsyncSync4, mkdirSync as mkdirSync17, openSync as openSync4, readFileSync as readFileSync31, renameSync as renameSync5, rmSync as rmSync9, writeFileSync as writeFileSync13, writeSync as writeSync3 } from "fs";
23807
- import { dirname as dirname19, resolve as resolve21 } from "path";
24184
+ import { closeSync as closeSync4, existsSync as existsSync41, fsyncSync as fsyncSync4, mkdirSync as mkdirSync18, openSync as openSync4, readFileSync as readFileSync31, renameSync as renameSync5, rmSync as rmSync9, writeFileSync as writeFileSync13, writeSync as writeSync3 } from "fs";
24185
+ import { dirname as dirname20, resolve as resolve21 } from "path";
23808
24186
  function watchStatePath(projectRoot) {
23809
24187
  return resolve21(projectRoot, ".massu", "watch-state.json");
23810
24188
  }
@@ -23813,7 +24191,7 @@ function backupStatePath(projectRoot) {
23813
24191
  }
23814
24192
  function readState(projectRoot) {
23815
24193
  const path = watchStatePath(projectRoot);
23816
- if (!existsSync40(path)) return { ...DEFAULT_STATE };
24194
+ if (!existsSync41(path)) return { ...DEFAULT_STATE };
23817
24195
  const content = readFileSync31(path, "utf-8");
23818
24196
  let raw;
23819
24197
  try {
@@ -23856,14 +24234,14 @@ function readState(projectRoot) {
23856
24234
  }
23857
24235
  function archiveCorrupt(projectRoot, content) {
23858
24236
  const bak = backupStatePath(projectRoot);
23859
- mkdirSync17(dirname19(bak), { recursive: true });
24237
+ mkdirSync18(dirname20(bak), { recursive: true });
23860
24238
  writeFileSync13(bak, content, "utf-8");
23861
24239
  }
23862
24240
  function writeStateAtomic(projectRoot, state) {
23863
24241
  const path = watchStatePath(projectRoot);
23864
24242
  writeStateAtomicCounter = writeStateAtomicCounter + 1 >>> 0;
23865
24243
  const tmp = `${path}.${process.pid}.${writeStateAtomicCounter}.tmp`;
23866
- mkdirSync17(dirname19(path), { recursive: true });
24244
+ mkdirSync18(dirname20(path), { recursive: true });
23867
24245
  let renamed = false;
23868
24246
  try {
23869
24247
  const fd = openSync4(tmp, "w");
@@ -23877,7 +24255,7 @@ function writeStateAtomic(projectRoot, state) {
23877
24255
  renameSync5(tmp, path);
23878
24256
  renamed = true;
23879
24257
  } finally {
23880
- if (!renamed && existsSync40(tmp)) {
24258
+ if (!renamed && existsSync41(tmp)) {
23881
24259
  try {
23882
24260
  rmSync9(tmp, { force: true });
23883
24261
  } catch {
@@ -24158,9 +24536,9 @@ __export(watch_exports, {
24158
24536
  runOnQuiescent: () => runOnQuiescent,
24159
24537
  runWatch: () => runWatch
24160
24538
  });
24161
- import { spawnSync as spawnSync3 } from "child_process";
24162
- import { basename as basename8, dirname as dirname20, resolve as resolve22 } from "path";
24163
- import { appendFileSync as appendFileSync3, existsSync as existsSync41, mkdirSync as mkdirSync18, readFileSync as readFileSync32 } from "fs";
24539
+ import { spawnSync as spawnSync4 } from "child_process";
24540
+ import { basename as basename8, dirname as dirname21, resolve as resolve22 } from "path";
24541
+ import { appendFileSync as appendFileSync4, existsSync as existsSync42, mkdirSync as mkdirSync19, readFileSync as readFileSync32 } from "fs";
24164
24542
  function parseFlags(args2) {
24165
24543
  const out = {
24166
24544
  foreground: false,
@@ -24186,8 +24564,8 @@ function parseFlags(args2) {
24186
24564
  function findClaudeBg() {
24187
24565
  const home = process.env.HOME ?? "";
24188
24566
  const fixed = home ? resolve22(home, ".claude", "bin", "claude-bg") : null;
24189
- if (fixed && existsSync41(fixed)) return fixed;
24190
- const which = spawnSync3("which", ["claude-bg"], { encoding: "utf-8" });
24567
+ if (fixed && existsSync42(fixed)) return fixed;
24568
+ const which = spawnSync4("which", ["claude-bg"], { encoding: "utf-8" });
24191
24569
  if (which.status === 0 && which.stdout) {
24192
24570
  const p19 = which.stdout.trim();
24193
24571
  if (p19) return p19;
@@ -24229,7 +24607,7 @@ async function runWatch(args2) {
24229
24607
  return { exitCode: 1, message: msg };
24230
24608
  }
24231
24609
  const name = watchName(root);
24232
- const res = spawnSync3(claudeBg, [
24610
+ const res = spawnSync4(claudeBg, [
24233
24611
  "start",
24234
24612
  "--name",
24235
24613
  name,
@@ -24247,7 +24625,7 @@ async function runWatch(args2) {
24247
24625
  }
24248
24626
  function runStatus(root) {
24249
24627
  const path = watchStatePath(root);
24250
- if (!existsSync41(path)) {
24628
+ if (!existsSync42(path)) {
24251
24629
  process.stdout.write("massu watch: not running (no state file)\n");
24252
24630
  return { exitCode: 0 };
24253
24631
  }
@@ -24285,7 +24663,7 @@ function runStop(root) {
24285
24663
  process.stderr.write("massu watch --stop: claude-bg not found; cannot kill registered daemon\n");
24286
24664
  return { exitCode: 1 };
24287
24665
  }
24288
- const res = spawnSync3(claudeBg, ["kill", watchName(root)], { stdio: "inherit" });
24666
+ const res = spawnSync4(claudeBg, ["kill", watchName(root)], { stdio: "inherit" });
24289
24667
  return { exitCode: (res.status ?? 1) === 0 ? 0 : 1 };
24290
24668
  }
24291
24669
  async function runApplyNow(root) {
@@ -24405,14 +24783,14 @@ function refreshLogPath(projectRoot) {
24405
24783
  function appendRefreshLog(projectRoot, event) {
24406
24784
  const path = refreshLogPath(projectRoot);
24407
24785
  try {
24408
- mkdirSync18(dirname20(path), { recursive: true });
24409
- appendFileSync3(path, JSON.stringify(event) + "\n", "utf-8");
24786
+ mkdirSync19(dirname21(path), { recursive: true });
24787
+ appendFileSync4(path, JSON.stringify(event) + "\n", "utf-8");
24410
24788
  } catch {
24411
24789
  }
24412
24790
  }
24413
24791
  function readRefreshLog(projectRoot, limit = 10, opts = {}) {
24414
24792
  const path = refreshLogPath(projectRoot);
24415
- if (!existsSync41(path)) return [];
24793
+ if (!existsSync42(path)) return [];
24416
24794
  const warn = opts.warn ?? ((s) => {
24417
24795
  process.stderr.write(s);
24418
24796
  });
@@ -24487,28 +24865,28 @@ var init_refresh_log = __esm({
24487
24865
 
24488
24866
  // src/security/atomic-write.ts
24489
24867
  import {
24490
- chmodSync as chmodSync6,
24868
+ chmodSync as chmodSync7,
24491
24869
  closeSync as closeSync5,
24492
- existsSync as existsSync42,
24870
+ existsSync as existsSync43,
24493
24871
  fsyncSync as fsyncSync5,
24494
- mkdirSync as mkdirSync19,
24872
+ mkdirSync as mkdirSync20,
24495
24873
  openSync as openSync5,
24496
24874
  renameSync as renameSync6,
24497
24875
  rmSync as rmSync10,
24498
24876
  statSync as statSync15,
24499
24877
  writeSync as writeSync4
24500
24878
  } from "node:fs";
24501
- import { dirname as dirname21 } from "node:path";
24879
+ import { dirname as dirname22 } from "node:path";
24502
24880
  function atomicWrite(path, content, opts = {}) {
24503
24881
  const tmpPath = `${path}.tmp`;
24504
- const parentDir = dirname21(path);
24882
+ const parentDir = dirname22(path);
24505
24883
  try {
24506
- if (!existsSync42(parentDir)) {
24884
+ if (!existsSync43(parentDir)) {
24507
24885
  const mkdirOpts = { recursive: true };
24508
24886
  if (opts.ensureParentDirMode !== void 0) {
24509
24887
  mkdirOpts.mode = opts.ensureParentDirMode;
24510
24888
  }
24511
- mkdirSync19(parentDir, mkdirOpts);
24889
+ mkdirSync20(parentDir, mkdirOpts);
24512
24890
  }
24513
24891
  const buf = typeof content === "string" ? Buffer.from(content, "utf-8") : content;
24514
24892
  const openMode = opts.mode ?? 420;
@@ -24520,12 +24898,12 @@ function atomicWrite(path, content, opts = {}) {
24520
24898
  closeSync5(fd);
24521
24899
  }
24522
24900
  if (opts.mode !== void 0) {
24523
- chmodSync6(tmpPath, opts.mode);
24901
+ chmodSync7(tmpPath, opts.mode);
24524
24902
  }
24525
24903
  renameSync6(tmpPath, path);
24526
24904
  return { written: true };
24527
24905
  } catch (err) {
24528
- if (existsSync42(tmpPath)) {
24906
+ if (existsSync43(tmpPath)) {
24529
24907
  try {
24530
24908
  rmSync10(tmpPath, { force: true });
24531
24909
  } catch {
@@ -24874,7 +25252,7 @@ var init_fetcher = __esm({
24874
25252
  });
24875
25253
 
24876
25254
  // src/security/manifest-cache.ts
24877
- import { existsSync as existsSync43, readFileSync as readFileSync33, statSync as statSync16 } from "node:fs";
25255
+ import { existsSync as existsSync44, readFileSync as readFileSync33, statSync as statSync16 } from "node:fs";
24878
25256
  import { homedir as homedir13 } from "node:os";
24879
25257
  import { resolve as resolve23 } from "node:path";
24880
25258
  import { z as z5 } from "zod";
@@ -24886,7 +25264,7 @@ function defaultCachePaths() {
24886
25264
  };
24887
25265
  }
24888
25266
  function loadCachedManifest(paths = defaultCachePaths()) {
24889
- if (!existsSync43(paths.cachePath)) {
25267
+ if (!existsSync44(paths.cachePath)) {
24890
25268
  return { kind: "absent" };
24891
25269
  }
24892
25270
  let raw;
@@ -25080,7 +25458,7 @@ var init_adapter_origin = __esm({
25080
25458
  });
25081
25459
 
25082
25460
  // src/security/local-fingerprint.ts
25083
- import { existsSync as existsSync44, readFileSync as readFileSync34, lstatSync as lstatSync5 } from "node:fs";
25461
+ import { existsSync as existsSync45, readFileSync as readFileSync34, lstatSync as lstatSync5 } from "node:fs";
25084
25462
  import { homedir as homedir14 } from "node:os";
25085
25463
  import { resolve as resolve24, isAbsolute as isAbsolute3 } from "node:path";
25086
25464
  import { createHash as createHash12 } from "node:crypto";
@@ -25109,7 +25487,7 @@ function computeLocalFingerprint(localPaths, projectRoot) {
25109
25487
  return createHash12("sha256").update(canonical).digest("hex");
25110
25488
  }
25111
25489
  function readFingerprintSentinel(path = FINGERPRINT_PATH) {
25112
- if (!existsSync44(path)) return null;
25490
+ if (!existsSync45(path)) return null;
25113
25491
  let raw;
25114
25492
  try {
25115
25493
  raw = JSON.parse(readFileSync34(path, "utf-8"));
@@ -25176,15 +25554,15 @@ var init_local_fingerprint = __esm({
25176
25554
  });
25177
25555
 
25178
25556
  // src/security/install-tracking.ts
25179
- import { readFileSync as readFileSync35, readdirSync as readdirSync16, lstatSync as lstatSync6, existsSync as existsSync45 } from "node:fs";
25180
- import { join as join24, relative as relative7, sep as sep2 } from "node:path";
25557
+ import { readFileSync as readFileSync35, readdirSync as readdirSync16, lstatSync as lstatSync6, existsSync as existsSync46 } from "node:fs";
25558
+ import { join as join25, relative as relative7, sep as sep2 } from "node:path";
25181
25559
  import { homedir as homedir15 } from "node:os";
25182
25560
  import { resolve as resolve25 } from "node:path";
25183
25561
  import { createHash as createHash13 } from "node:crypto";
25184
25562
  import { z as z7 } from "zod";
25185
25563
  function containsHiddenDirs(packageDir) {
25186
25564
  for (const hidden of EXCLUDED_DIR_NAMES) {
25187
- if (existsSync45(`${packageDir}/${hidden}`)) {
25565
+ if (existsSync46(`${packageDir}/${hidden}`)) {
25188
25566
  return hidden;
25189
25567
  }
25190
25568
  }
@@ -25201,7 +25579,7 @@ function sha256OfDir(dir, opts = {}) {
25201
25579
  return;
25202
25580
  }
25203
25581
  for (const entry of entries.sort()) {
25204
- const absPath = join24(currentDir, entry);
25582
+ const absPath = join25(currentDir, entry);
25205
25583
  let lst;
25206
25584
  try {
25207
25585
  lst = lstatSync6(absPath);
@@ -25239,7 +25617,7 @@ function sha256OfDir(dir, opts = {}) {
25239
25617
  return top.digest("hex");
25240
25618
  }
25241
25619
  function readInstalledManifest(path = INSTALLED_MANIFEST_PATH) {
25242
- if (!existsSync45(path)) return {};
25620
+ if (!existsSync46(path)) return {};
25243
25621
  let raw;
25244
25622
  try {
25245
25623
  raw = JSON.parse(readFileSync35(path, "utf-8"));
@@ -25329,12 +25707,12 @@ var init_install_tracking = __esm({
25329
25707
  });
25330
25708
 
25331
25709
  // src/detect/adapters/discover.ts
25332
- import { existsSync as existsSync46, readdirSync as readdirSync17, readFileSync as readFileSync36, lstatSync as lstatSync7 } from "node:fs";
25710
+ import { existsSync as existsSync47, readdirSync as readdirSync17, readFileSync as readFileSync36, lstatSync as lstatSync7 } from "node:fs";
25333
25711
  import { resolve as resolve26, isAbsolute as isAbsolute4 } from "node:path";
25334
25712
  import { z as z8 } from "zod";
25335
25713
  function walkNodeModules(projectRoot, warnings) {
25336
25714
  const nodeModulesDir = resolve26(projectRoot, "node_modules");
25337
- if (!existsSync46(nodeModulesDir)) {
25715
+ if (!existsSync47(nodeModulesDir)) {
25338
25716
  return [];
25339
25717
  }
25340
25718
  const candidates = [];
@@ -25389,7 +25767,7 @@ function walkNodeModules(projectRoot, warnings) {
25389
25767
  }
25390
25768
  function tryReadAdapterPackage(packageDir, warnings) {
25391
25769
  const pkgJsonPath = resolve26(packageDir, "package.json");
25392
- if (!existsSync46(pkgJsonPath)) return null;
25770
+ if (!existsSync47(pkgJsonPath)) return null;
25393
25771
  let raw;
25394
25772
  try {
25395
25773
  raw = JSON.parse(readFileSync36(pkgJsonPath, "utf-8"));
@@ -25527,7 +25905,7 @@ function discoverAdapters(opts) {
25527
25905
  for (const localPath of opts.configLocalPaths) {
25528
25906
  if (seenIds.has(localPath)) continue;
25529
25907
  const absPath = isAbsolute4(localPath) ? localPath : resolve26(opts.projectRoot, localPath);
25530
- if (!existsSync46(absPath)) {
25908
+ if (!existsSync47(absPath)) {
25531
25909
  warnings.push(
25532
25910
  `local adapter file not found: ${localPath} (resolved to ${absPath}). Remove via: massu adapters remove-local ${localPath}`
25533
25911
  );
@@ -25609,7 +25987,7 @@ __export(adapters_exports, {
25609
25987
  runAdaptersResyncLocalFingerprint: () => runAdaptersResyncLocalFingerprint,
25610
25988
  runAdaptersSearch: () => runAdaptersSearch
25611
25989
  });
25612
- import { existsSync as existsSync47, readFileSync as readFileSync37 } from "node:fs";
25990
+ import { existsSync as existsSync48, readFileSync as readFileSync37 } from "node:fs";
25613
25991
  import { resolve as resolve27 } from "node:path";
25614
25992
  import { parseDocument } from "yaml";
25615
25993
  async function handleAdaptersSubcommand(args2) {
@@ -25878,7 +26256,7 @@ function mutateLocalArray(mutator, command) {
25878
26256
  return { exitCode: 2 };
25879
26257
  }
25880
26258
  const yamlPath = resolve27(projectRoot, "massu.config.yaml");
25881
- if (!existsSync47(yamlPath)) {
26259
+ if (!existsSync48(yamlPath)) {
25882
26260
  process.stderr.write(
25883
26261
  `${command}: massu.config.yaml not found at ${yamlPath}. Run \`massu init\` first.
25884
26262
  `
@@ -25978,7 +26356,7 @@ async function runAdaptersInstall(args2) {
25978
26356
  return { exitCode: 1 };
25979
26357
  }
25980
26358
  const packageDir = resolve27(projectRoot, "node_modules", ...packageName.split("/"));
25981
- if (!existsSync47(packageDir)) {
26359
+ if (!existsSync48(packageDir)) {
25982
26360
  process.stderr.write(
25983
26361
  `install: ${packageName} is not installed in node_modules. Run \`npm install ${packageName}\` first.
25984
26362
  `
@@ -25986,7 +26364,7 @@ async function runAdaptersInstall(args2) {
25986
26364
  return { exitCode: 1 };
25987
26365
  }
25988
26366
  const pkgJsonPath = resolve27(packageDir, "package.json");
25989
- if (!existsSync47(pkgJsonPath)) {
26367
+ if (!existsSync48(pkgJsonPath)) {
25990
26368
  process.stderr.write(`install: ${packageName} has no package.json at ${pkgJsonPath}
25991
26369
  `);
25992
26370
  return { exitCode: 1 };
@@ -26113,7 +26491,7 @@ async function runAdaptersResign(_args) {
26113
26491
  continue;
26114
26492
  }
26115
26493
  const packageDir = resolve27(projectRoot, "node_modules", ...name.split("/"));
26116
- if (!existsSync47(packageDir)) {
26494
+ if (!existsSync48(packageDir)) {
26117
26495
  removed++;
26118
26496
  warnings.push(`${name}@${entry.version}: not present in node_modules \u2014 REMOVED from sidecar`);
26119
26497
  removeInstalledManifestEntry(name);
@@ -26199,16 +26577,15 @@ var init_adapters2 = __esm({
26199
26577
  });
26200
26578
 
26201
26579
  // src/preflight.ts
26202
- import Database4 from "better-sqlite3";
26203
- import { existsSync as existsSync48 } from "fs";
26580
+ import { existsSync as existsSync49 } from "fs";
26204
26581
  function assertCodegraphUsable(dbPath) {
26205
26582
  const path = dbPath ?? getResolvedPaths().codegraphDbPath;
26206
- if (!existsSync48(path)) {
26583
+ if (!existsSync49(path)) {
26207
26584
  throw new CodegraphDbUnusableError(path, "missing");
26208
26585
  }
26209
26586
  let db = null;
26210
26587
  try {
26211
- db = new Database4(path, { readonly: true });
26588
+ db = openDatabase(path, { readonly: true });
26212
26589
  const row = db.prepare("SELECT COUNT(*) AS c FROM files").get();
26213
26590
  const files = row?.c ?? 0;
26214
26591
  if (files === 0) {
@@ -26232,6 +26609,7 @@ var CodegraphDbNotInitializedError, CodegraphDbUnusableError;
26232
26609
  var init_preflight = __esm({
26233
26610
  "src/preflight.ts"() {
26234
26611
  "use strict";
26612
+ init_sqlite_loader();
26235
26613
  init_config();
26236
26614
  CodegraphDbNotInitializedError = class extends Error {
26237
26615
  dbPath;
@@ -26291,23 +26669,22 @@ var init_sql_table_names = __esm({
26291
26669
  });
26292
26670
 
26293
26671
  // src/db.ts
26294
- import Database5 from "better-sqlite3";
26295
- import { dirname as dirname22, join as join25 } from "path";
26296
- import { existsSync as existsSync49, mkdirSync as mkdirSync20, readdirSync as readdirSync18, statSync as statSync17 } from "fs";
26672
+ import { dirname as dirname23, join as join26 } from "path";
26673
+ import { existsSync as existsSync50, mkdirSync as mkdirSync21, readdirSync as readdirSync18, statSync as statSync17 } from "fs";
26297
26674
  function getCodeGraphDb() {
26298
26675
  const dbPath = getResolvedPaths().codegraphDbPath;
26299
26676
  assertCodegraphUsable(dbPath);
26300
- const db = new Database5(dbPath, { readonly: true });
26677
+ const db = openDatabase(dbPath, { readonly: true });
26301
26678
  db.pragma("journal_mode = WAL");
26302
26679
  return db;
26303
26680
  }
26304
26681
  function getDataDb() {
26305
26682
  const dbPath = getResolvedPaths().dataDbPath;
26306
- const dir = dirname22(dbPath);
26307
- if (!existsSync49(dir)) {
26308
- mkdirSync20(dir, { recursive: true });
26683
+ const dir = dirname23(dbPath);
26684
+ if (!existsSync50(dir)) {
26685
+ mkdirSync21(dir, { recursive: true });
26309
26686
  }
26310
- const db = new Database5(dbPath);
26687
+ const db = openDatabase(dbPath);
26311
26688
  db.pragma("journal_mode = WAL");
26312
26689
  db.pragma("foreign_keys = ON");
26313
26690
  initDataSchema(db);
@@ -26577,7 +26954,7 @@ function isPythonDataStale(dataDb, pythonRoot) {
26577
26954
  try {
26578
26955
  const entries = readdirSync18(dir, { withFileTypes: true });
26579
26956
  for (const entry of entries) {
26580
- const fullPath = join25(dir, entry.name);
26957
+ const fullPath = join26(dir, entry.name);
26581
26958
  if (entry.isDirectory()) {
26582
26959
  if (["__pycache__", ".venv", "venv", "node_modules", ".mypy_cache", ".pytest_cache"].includes(entry.name)) continue;
26583
26960
  if (checkDir(fullPath)) return true;
@@ -26597,6 +26974,7 @@ function updatePythonBuildTimestamp(dataDb) {
26597
26974
  var init_db2 = __esm({
26598
26975
  "src/db.ts"() {
26599
26976
  "use strict";
26977
+ init_sqlite_loader();
26600
26978
  init_preflight();
26601
26979
  init_config();
26602
26980
  init_sql_table_names();
@@ -26681,8 +27059,8 @@ var init_rules = __esm({
26681
27059
  });
26682
27060
 
26683
27061
  // src/import-resolver.ts
26684
- import { readFileSync as readFileSync38, existsSync as existsSync50, statSync as statSync18 } from "fs";
26685
- import { resolve as resolve29, dirname as dirname23, join as join26 } from "path";
27062
+ import { readFileSync as readFileSync38, existsSync as existsSync51, statSync as statSync18 } from "fs";
27063
+ import { resolve as resolve29, dirname as dirname24, join as join27 } from "path";
26686
27064
  function parseImports(source) {
26687
27065
  const imports = [];
26688
27066
  const lines = source.split("\n");
@@ -26740,21 +27118,21 @@ function resolveImportPath(specifier, fromFile) {
26740
27118
  const paths = getResolvedPaths();
26741
27119
  basePath = resolve29(paths.pathAlias["@"] ?? paths.srcDir, specifier.slice(2));
26742
27120
  } else {
26743
- basePath = resolve29(dirname23(fromFile), specifier);
27121
+ basePath = resolve29(dirname24(fromFile), specifier);
26744
27122
  }
26745
- if (existsSync50(basePath) && !isDirectory(basePath)) {
27123
+ if (existsSync51(basePath) && !isDirectory(basePath)) {
26746
27124
  return toRelative(basePath);
26747
27125
  }
26748
27126
  const resolvedPaths = getResolvedPaths();
26749
27127
  for (const ext of resolvedPaths.extensions) {
26750
27128
  const withExt = basePath + ext;
26751
- if (existsSync50(withExt)) {
27129
+ if (existsSync51(withExt)) {
26752
27130
  return toRelative(withExt);
26753
27131
  }
26754
27132
  }
26755
27133
  for (const indexFile of resolvedPaths.indexFiles) {
26756
- const indexPath = join26(basePath, indexFile);
26757
- if (existsSync50(indexPath)) {
27134
+ const indexPath = join27(basePath, indexFile);
27135
+ if (existsSync51(indexPath)) {
26758
27136
  return toRelative(indexPath);
26759
27137
  }
26760
27138
  }
@@ -26791,7 +27169,7 @@ function buildImportIndex(dataDb, codegraphDb) {
26791
27169
  let batch = [];
26792
27170
  for (const file of files) {
26793
27171
  const absPath = ensureWithinRoot(resolve29(projectRoot, file.path), projectRoot);
26794
- if (!existsSync50(absPath)) continue;
27172
+ if (!existsSync51(absPath)) continue;
26795
27173
  let source;
26796
27174
  try {
26797
27175
  source = readFileSync38(absPath, "utf-8");
@@ -26831,12 +27209,12 @@ var init_import_resolver = __esm({
26831
27209
  });
26832
27210
 
26833
27211
  // src/trpc-index.ts
26834
- import { readFileSync as readFileSync39, existsSync as existsSync51, readdirSync as readdirSync19 } from "fs";
26835
- import { resolve as resolve30, join as join27 } from "path";
27212
+ import { readFileSync as readFileSync39, existsSync as existsSync52, readdirSync as readdirSync19 } from "fs";
27213
+ import { resolve as resolve30, join as join28 } from "path";
26836
27214
  function parseRootRouter() {
26837
27215
  const paths = getResolvedPaths();
26838
27216
  const rootPath = paths.rootRouterPath;
26839
- if (!existsSync51(rootPath)) {
27217
+ if (!existsSync52(rootPath)) {
26840
27218
  throw new Error(`Root router not found at ${rootPath}`);
26841
27219
  }
26842
27220
  const source = readFileSync39(rootPath, "utf-8");
@@ -26851,12 +27229,12 @@ function parseRootRouter() {
26851
27229
  for (const ext of [".ts", ".tsx", ""]) {
26852
27230
  const candidate = fullPath + ext;
26853
27231
  const routersRelPath = getConfig().paths.routers ?? "src/server/api/routers";
26854
- if (existsSync51(candidate)) {
27232
+ if (existsSync52(candidate)) {
26855
27233
  filePath = routersRelPath + "/" + filePath + ext;
26856
27234
  break;
26857
27235
  }
26858
- const indexCandidate = join27(fullPath, "index.ts");
26859
- if (existsSync51(indexCandidate)) {
27236
+ const indexCandidate = join28(fullPath, "index.ts");
27237
+ if (existsSync52(indexCandidate)) {
26860
27238
  filePath = routersRelPath + "/" + filePath + "/index.ts";
26861
27239
  break;
26862
27240
  }
@@ -26876,7 +27254,7 @@ function parseRootRouter() {
26876
27254
  }
26877
27255
  function extractProcedures(routerFilePath) {
26878
27256
  const absPath = resolve30(getProjectRoot(), routerFilePath);
26879
- if (!existsSync51(absPath)) return [];
27257
+ if (!existsSync52(absPath)) return [];
26880
27258
  const source = readFileSync39(absPath, "utf-8");
26881
27259
  const procedures = [];
26882
27260
  const seen = /* @__PURE__ */ new Set();
@@ -26906,7 +27284,7 @@ function findUICallSites(routerKey, procedureName) {
26906
27284
  ];
26907
27285
  const searchPattern = `api.${routerKey}.${procedureName}`;
26908
27286
  for (const dir of searchDirs) {
26909
- if (!existsSync51(dir)) continue;
27287
+ if (!existsSync52(dir)) continue;
26910
27288
  searchDirectory(dir, searchPattern, callSites);
26911
27289
  }
26912
27290
  return callSites;
@@ -26914,7 +27292,7 @@ function findUICallSites(routerKey, procedureName) {
26914
27292
  function searchDirectory(dir, pattern, results) {
26915
27293
  const entries = readdirSync19(dir, { withFileTypes: true });
26916
27294
  for (const entry of entries) {
26917
- const fullPath = join27(dir, entry.name);
27295
+ const fullPath = join28(dir, entry.name);
26918
27296
  if (entry.isDirectory()) {
26919
27297
  if (entry.name === "node_modules" || entry.name === ".next") continue;
26920
27298
  searchDirectory(fullPath, pattern, results);
@@ -26984,7 +27362,7 @@ var init_trpc_index = __esm({
26984
27362
  });
26985
27363
 
26986
27364
  // src/page-deps.ts
26987
- import { readFileSync as readFileSync40, existsSync as existsSync52 } from "fs";
27365
+ import { readFileSync as readFileSync40, existsSync as existsSync53 } from "fs";
26988
27366
  import { resolve as resolve31 } from "path";
26989
27367
  function deriveRoute(pageFile) {
26990
27368
  let route = pageFile.replace(/^src\/app/, "").replace(/\/page\.tsx?$/, "").replace(/\/page\.jsx?$/, "");
@@ -27024,7 +27402,7 @@ function findRouterCalls(files) {
27024
27402
  const projectRoot = getProjectRoot();
27025
27403
  for (const file of files) {
27026
27404
  const absPath = ensureWithinRoot(resolve31(projectRoot, file), projectRoot);
27027
- if (!existsSync52(absPath)) continue;
27405
+ if (!existsSync53(absPath)) continue;
27028
27406
  try {
27029
27407
  const source = readFileSync40(absPath, "utf-8");
27030
27408
  const apiCallRegex = /api\.(\w+)\.\w+/g;
@@ -27045,7 +27423,7 @@ function findTablesFromRouters(routerNames, dataDb) {
27045
27423
  ).all(routerName);
27046
27424
  for (const proc of procs) {
27047
27425
  const absPath = ensureWithinRoot(resolve31(getProjectRoot(), proc.router_file), getProjectRoot());
27048
- if (!existsSync52(absPath)) continue;
27426
+ if (!existsSync53(absPath)) continue;
27049
27427
  try {
27050
27428
  const source = readFileSync40(absPath, "utf-8");
27051
27429
  const dbPattern = getConfig().dbAccessPattern ?? "ctx.db.{table}";
@@ -27319,11 +27697,11 @@ var init_domains = __esm({
27319
27697
  });
27320
27698
 
27321
27699
  // src/schema-mapper.ts
27322
- import { readFileSync as readFileSync41, existsSync as existsSync53, readdirSync as readdirSync20 } from "fs";
27323
- import { join as join28 } from "path";
27700
+ import { readFileSync as readFileSync41, existsSync as existsSync54, readdirSync as readdirSync20 } from "fs";
27701
+ import { join as join29 } from "path";
27324
27702
  function parsePrismaSchema() {
27325
27703
  const schemaPath = getResolvedPaths().prismaSchemaPath;
27326
- if (!existsSync53(schemaPath)) {
27704
+ if (!existsSync54(schemaPath)) {
27327
27705
  throw new Error(`Prisma schema not found at ${schemaPath}`);
27328
27706
  }
27329
27707
  const source = readFileSync41(schemaPath, "utf-8");
@@ -27384,14 +27762,14 @@ function toSnakeCase(str) {
27384
27762
  function findColumnUsageInRouters(tableName) {
27385
27763
  const usage2 = /* @__PURE__ */ new Map();
27386
27764
  const routersDir = getResolvedPaths().routersDir;
27387
- if (!existsSync53(routersDir)) return usage2;
27765
+ if (!existsSync54(routersDir)) return usage2;
27388
27766
  scanDirectory(routersDir, tableName, usage2);
27389
27767
  return usage2;
27390
27768
  }
27391
27769
  function scanDirectory(dir, tableName, usage2) {
27392
27770
  const entries = readdirSync20(dir, { withFileTypes: true });
27393
27771
  for (const entry of entries) {
27394
- const fullPath = join28(dir, entry.name);
27772
+ const fullPath = join29(dir, entry.name);
27395
27773
  if (entry.isDirectory()) {
27396
27774
  scanDirectory(fullPath, tableName, usage2);
27397
27775
  } else if (entry.name.endsWith(".ts")) {
@@ -27446,10 +27824,10 @@ function detectMismatches(models) {
27446
27824
  }
27447
27825
  function findFilesUsingColumn(dir, column, tableName) {
27448
27826
  const result = [];
27449
- if (!existsSync53(dir)) return result;
27827
+ if (!existsSync54(dir)) return result;
27450
27828
  const entries = readdirSync20(dir, { withFileTypes: true });
27451
27829
  for (const entry of entries) {
27452
- const fullPath = join28(dir, entry.name);
27830
+ const fullPath = join29(dir, entry.name);
27453
27831
  if (entry.isDirectory()) {
27454
27832
  result.push(...findFilesUsingColumn(fullPath, column, tableName));
27455
27833
  } else if (entry.name.endsWith(".ts")) {
@@ -27599,34 +27977,34 @@ var init_import_parser = __esm({
27599
27977
  });
27600
27978
 
27601
27979
  // src/python/import-resolver.ts
27602
- import { readFileSync as readFileSync42, existsSync as existsSync54, readdirSync as readdirSync21 } from "fs";
27603
- import { resolve as resolve33, join as join29, relative as relative8, dirname as dirname24 } from "path";
27980
+ import { readFileSync as readFileSync42, existsSync as existsSync55, readdirSync as readdirSync21 } from "fs";
27981
+ import { resolve as resolve33, join as join30, relative as relative8, dirname as dirname25 } from "path";
27604
27982
  function resolvePythonModulePath(module, fromFile, pythonRoot, level) {
27605
27983
  const projectRoot = getProjectRoot();
27606
27984
  if (level > 0) {
27607
- let baseDir = dirname24(resolve33(projectRoot, fromFile));
27985
+ let baseDir = dirname25(resolve33(projectRoot, fromFile));
27608
27986
  for (let i = 1; i < level; i++) {
27609
- baseDir = dirname24(baseDir);
27987
+ baseDir = dirname25(baseDir);
27610
27988
  }
27611
27989
  const modulePart = module.replace(/^\.+/, "");
27612
27990
  if (modulePart) {
27613
27991
  const parts2 = modulePart.split(".");
27614
- return tryResolvePythonPath(join29(baseDir, ...parts2), projectRoot);
27992
+ return tryResolvePythonPath(join30(baseDir, ...parts2), projectRoot);
27615
27993
  }
27616
27994
  return tryResolvePythonPath(baseDir, projectRoot);
27617
27995
  }
27618
27996
  const parts = module.split(".");
27619
- const candidate = join29(resolve33(projectRoot, pythonRoot), ...parts);
27997
+ const candidate = join30(resolve33(projectRoot, pythonRoot), ...parts);
27620
27998
  return tryResolvePythonPath(candidate, projectRoot);
27621
27999
  }
27622
28000
  function tryResolvePythonPath(basePath, projectRoot) {
27623
- if (existsSync54(basePath + ".py")) {
28001
+ if (existsSync55(basePath + ".py")) {
27624
28002
  return relative8(projectRoot, basePath + ".py");
27625
28003
  }
27626
- if (existsSync54(join29(basePath, "__init__.py"))) {
27627
- return relative8(projectRoot, join29(basePath, "__init__.py"));
28004
+ if (existsSync55(join30(basePath, "__init__.py"))) {
28005
+ return relative8(projectRoot, join30(basePath, "__init__.py"));
27628
28006
  }
27629
- if (basePath.endsWith(".py") && existsSync54(basePath)) {
28007
+ if (basePath.endsWith(".py") && existsSync55(basePath)) {
27630
28008
  return relative8(projectRoot, basePath);
27631
28009
  }
27632
28010
  return null;
@@ -27638,9 +28016,9 @@ function walkPythonFiles(dir, excludeDirs) {
27638
28016
  for (const entry of entries) {
27639
28017
  if (entry.isDirectory()) {
27640
28018
  if (excludeDirs.includes(entry.name)) continue;
27641
- files.push(...walkPythonFiles(join29(dir, entry.name), excludeDirs));
28019
+ files.push(...walkPythonFiles(join30(dir, entry.name), excludeDirs));
27642
28020
  } else if (entry.name.endsWith(".py")) {
27643
- files.push(join29(dir, entry.name));
28021
+ files.push(join30(dir, entry.name));
27644
28022
  }
27645
28023
  }
27646
28024
  } catch {
@@ -27934,7 +28312,7 @@ var init_route_parser = __esm({
27934
28312
 
27935
28313
  // src/python/route-indexer.ts
27936
28314
  import { readFileSync as readFileSync43, readdirSync as readdirSync22 } from "fs";
27937
- import { join as join30, relative as relative9 } from "path";
28315
+ import { join as join31, relative as relative9 } from "path";
27938
28316
  function walkPyFiles(dir, excludeDirs) {
27939
28317
  const files = [];
27940
28318
  try {
@@ -27942,9 +28320,9 @@ function walkPyFiles(dir, excludeDirs) {
27942
28320
  for (const entry of entries) {
27943
28321
  if (entry.isDirectory()) {
27944
28322
  if (excludeDirs.includes(entry.name)) continue;
27945
- files.push(...walkPyFiles(join30(dir, entry.name), excludeDirs));
28323
+ files.push(...walkPyFiles(join31(dir, entry.name), excludeDirs));
27946
28324
  } else if (entry.name.endsWith(".py")) {
27947
- files.push(join30(dir, entry.name));
28325
+ files.push(join31(dir, entry.name));
27948
28326
  }
27949
28327
  }
27950
28328
  } catch {
@@ -27953,7 +28331,7 @@ function walkPyFiles(dir, excludeDirs) {
27953
28331
  }
27954
28332
  function buildPythonRouteIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
27955
28333
  const projectRoot = getProjectRoot();
27956
- const absRoot = join30(projectRoot, pythonRoot);
28334
+ const absRoot = join31(projectRoot, pythonRoot);
27957
28335
  dataDb.exec(`DELETE FROM ${t("py_routes")}`);
27958
28336
  dataDb.exec(`DELETE FROM ${t("py_route_callers")}`);
27959
28337
  const insertStmt = dataDb.prepare(
@@ -28179,7 +28557,7 @@ var init_model_parser = __esm({
28179
28557
 
28180
28558
  // src/python/model-indexer.ts
28181
28559
  import { readFileSync as readFileSync44, readdirSync as readdirSync23 } from "fs";
28182
- import { join as join31, relative as relative10 } from "path";
28560
+ import { join as join32, relative as relative10 } from "path";
28183
28561
  function walkPyFiles2(dir, excludeDirs) {
28184
28562
  const files = [];
28185
28563
  try {
@@ -28187,9 +28565,9 @@ function walkPyFiles2(dir, excludeDirs) {
28187
28565
  for (const entry of entries) {
28188
28566
  if (entry.isDirectory()) {
28189
28567
  if (excludeDirs.includes(entry.name)) continue;
28190
- files.push(...walkPyFiles2(join31(dir, entry.name), excludeDirs));
28568
+ files.push(...walkPyFiles2(join32(dir, entry.name), excludeDirs));
28191
28569
  } else if (entry.name.endsWith(".py")) {
28192
- files.push(join31(dir, entry.name));
28570
+ files.push(join32(dir, entry.name));
28193
28571
  }
28194
28572
  }
28195
28573
  } catch {
@@ -28198,7 +28576,7 @@ function walkPyFiles2(dir, excludeDirs) {
28198
28576
  }
28199
28577
  function buildPythonModelIndex(dataDb, pythonRoot, excludeDirs = ["__pycache__", ".venv", "venv", ".mypy_cache", ".pytest_cache"]) {
28200
28578
  const projectRoot = getProjectRoot();
28201
- const absRoot = join31(projectRoot, pythonRoot);
28579
+ const absRoot = join32(projectRoot, pythonRoot);
28202
28580
  dataDb.exec(`DELETE FROM ${t("py_models")}`);
28203
28581
  dataDb.exec(`DELETE FROM ${t("py_fk_edges")}`);
28204
28582
  const insertModel = dataDb.prepare(
@@ -28476,18 +28854,18 @@ var init_migration_parser = __esm({
28476
28854
 
28477
28855
  // src/python/migration-indexer.ts
28478
28856
  import { readFileSync as readFileSync45, readdirSync as readdirSync24 } from "fs";
28479
- import { join as join32, relative as relative11 } from "path";
28857
+ import { join as join33, relative as relative11 } from "path";
28480
28858
  function buildPythonMigrationIndex(dataDb, alembicDir) {
28481
28859
  const projectRoot = getProjectRoot();
28482
- const absDir = join32(projectRoot, alembicDir);
28860
+ const absDir = join33(projectRoot, alembicDir);
28483
28861
  dataDb.exec(`DELETE FROM ${t("py_migrations")}`);
28484
- const versionsDir = join32(absDir, "versions");
28862
+ const versionsDir = join33(absDir, "versions");
28485
28863
  let files = [];
28486
28864
  try {
28487
- files = readdirSync24(versionsDir).filter((f2) => f2.endsWith(".py")).map((f2) => join32(versionsDir, f2));
28865
+ files = readdirSync24(versionsDir).filter((f2) => f2.endsWith(".py")).map((f2) => join33(versionsDir, f2));
28488
28866
  } catch {
28489
28867
  try {
28490
- files = readdirSync24(absDir).filter((f2) => f2.endsWith(".py") && f2 !== "env.py").map((f2) => join32(absDir, f2));
28868
+ files = readdirSync24(absDir).filter((f2) => f2.endsWith(".py") && f2 !== "env.py").map((f2) => join33(absDir, f2));
28491
28869
  } catch {
28492
28870
  }
28493
28871
  }
@@ -28537,11 +28915,11 @@ var init_migration_indexer = __esm({
28537
28915
 
28538
28916
  // src/python/coupling-detector.ts
28539
28917
  import { readFileSync as readFileSync46, readdirSync as readdirSync25 } from "fs";
28540
- import { join as join33, relative as relative12 } from "path";
28918
+ import { join as join34, relative as relative12 } from "path";
28541
28919
  function buildPythonCouplingIndex(dataDb) {
28542
28920
  const projectRoot = getProjectRoot();
28543
28921
  const config = getConfig();
28544
- const srcDir = join33(projectRoot, config.paths.source);
28922
+ const srcDir = join34(projectRoot, config.paths.source);
28545
28923
  const routes = dataDb.prepare(`SELECT id, method, path FROM ${t("py_routes")}`).all();
28546
28924
  if (routes.length === 0) return 0;
28547
28925
  dataDb.exec(`DELETE FROM ${t("py_route_callers")}`);
@@ -28605,9 +28983,9 @@ function walkFrontendFiles(dir) {
28605
28983
  for (const entry of entries) {
28606
28984
  if (entry.isDirectory()) {
28607
28985
  if (exclude.includes(entry.name)) continue;
28608
- files.push(...walkFrontendFiles(join33(dir, entry.name)));
28986
+ files.push(...walkFrontendFiles(join34(dir, entry.name)));
28609
28987
  } else if (/\.(tsx?|jsx?)$/.test(entry.name)) {
28610
- files.push(join33(dir, entry.name));
28988
+ files.push(join34(dir, entry.name));
28611
28989
  }
28612
28990
  }
28613
28991
  } catch {
@@ -28979,7 +29357,7 @@ var init_memory_tools = __esm({
28979
29357
  });
28980
29358
 
28981
29359
  // src/docs-tools.ts
28982
- import { readFileSync as readFileSync47, existsSync as existsSync55 } from "fs";
29360
+ import { readFileSync as readFileSync47, existsSync as existsSync56 } from "fs";
28983
29361
  import { resolve as resolve34, basename as basename9 } from "path";
28984
29362
  function p4(baseName) {
28985
29363
  return `${getConfig().toolPrefix}_${baseName}`;
@@ -29035,7 +29413,7 @@ function handleDocsToolCall(name, args2) {
29035
29413
  }
29036
29414
  function loadDocsMap() {
29037
29415
  const mapPath = getResolvedPaths().docsMapPath;
29038
- if (!existsSync55(mapPath)) {
29416
+ if (!existsSync56(mapPath)) {
29039
29417
  throw new Error(`docs-map.json not found at ${mapPath}`);
29040
29418
  }
29041
29419
  return JSON.parse(readFileSync47(mapPath, "utf-8"));
@@ -29109,9 +29487,9 @@ function extractFrontmatter(content) {
29109
29487
  function extractProcedureNames(routerPath) {
29110
29488
  const root = getProjectRoot();
29111
29489
  const absPath = ensureWithinRoot(resolve34(getResolvedPaths().srcDir, "..", routerPath), root);
29112
- if (!existsSync55(absPath)) {
29490
+ if (!existsSync56(absPath)) {
29113
29491
  const altPath = ensureWithinRoot(resolve34(getResolvedPaths().srcDir, "../server/api/routers", basename9(routerPath)), root);
29114
- if (!existsSync55(altPath)) return [];
29492
+ if (!existsSync56(altPath)) return [];
29115
29493
  return extractProcedureNamesFromContent(readFileSync47(altPath, "utf-8"));
29116
29494
  }
29117
29495
  return extractProcedureNamesFromContent(readFileSync47(absPath, "utf-8"));
@@ -29155,7 +29533,7 @@ function handleDocsAudit(args2) {
29155
29533
  const mapping = docsMap.mappings.find((m3) => m3.id === mappingId);
29156
29534
  if (!mapping) continue;
29157
29535
  const helpPagePath = ensureWithinRoot(resolve34(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
29158
- if (!existsSync55(helpPagePath)) {
29536
+ if (!existsSync56(helpPagePath)) {
29159
29537
  results.push({
29160
29538
  helpPage: mapping.helpPage,
29161
29539
  mappingId,
@@ -29208,7 +29586,7 @@ function handleDocsAudit(args2) {
29208
29586
  for (const [guideName, parentId] of Object.entries(docsMap.userGuideInheritance.examples)) {
29209
29587
  if (parentId === mappingId) {
29210
29588
  const guidePath = ensureWithinRoot(resolve34(getResolvedPaths().helpSitePath, `pages/user-guides/${guideName}/index.mdx`), getProjectRoot());
29211
- if (existsSync55(guidePath)) {
29589
+ if (existsSync56(guidePath)) {
29212
29590
  const guideContent = readFileSync47(guidePath, "utf-8");
29213
29591
  const guideFrontmatter = extractFrontmatter(guideContent);
29214
29592
  if (!guideFrontmatter?.lastVerified || status === "STALE") {
@@ -29243,7 +29621,7 @@ function handleDocsCoverage(args2) {
29243
29621
  const mappings = filterDomain ? docsMap.mappings.filter((m3) => m3.id === filterDomain) : docsMap.mappings;
29244
29622
  for (const mapping of mappings) {
29245
29623
  const helpPagePath = ensureWithinRoot(resolve34(getResolvedPaths().helpSitePath, mapping.helpPage), getProjectRoot());
29246
- const exists = existsSync55(helpPagePath);
29624
+ const exists = existsSync56(helpPagePath);
29247
29625
  let hasContent = false;
29248
29626
  let lineCount = 0;
29249
29627
  let lastVerified = null;
@@ -29590,7 +29968,7 @@ var init_observability_tools = __esm({
29590
29968
  });
29591
29969
 
29592
29970
  // src/sentinel-db.ts
29593
- import { existsSync as existsSync56 } from "fs";
29971
+ import { existsSync as existsSync57 } from "fs";
29594
29972
  import { resolve as resolve35 } from "path";
29595
29973
  function parsePortalScope(raw) {
29596
29974
  if (!raw) return [];
@@ -29828,22 +30206,22 @@ function validateFeatures(db, domainFilter) {
29828
30206
  const missingPages = [];
29829
30207
  for (const comp of components) {
29830
30208
  const absPath = resolve35(PROJECT_ROOT, comp.component_file);
29831
- if (!existsSync56(absPath)) {
30209
+ if (!existsSync57(absPath)) {
29832
30210
  missingComponents.push(comp.component_file);
29833
30211
  }
29834
30212
  }
29835
30213
  for (const proc of procedures) {
29836
30214
  const routerPath = resolve35(PROJECT_ROOT, `src/server/api/routers/${proc.router_name}.ts`);
29837
- if (!existsSync56(routerPath)) {
30215
+ if (!existsSync57(routerPath)) {
29838
30216
  missingProcedures.push({ router: proc.router_name, procedure: proc.procedure_name });
29839
30217
  }
29840
30218
  }
29841
30219
  for (const page of pages) {
29842
30220
  const routeToPath = page.page_route.replace(/^\/(portal-[^/]+\/)?/, "src/app/").replace(/\/$/, "") + "/page.tsx";
29843
30221
  const absPath = resolve35(PROJECT_ROOT, routeToPath);
29844
- if (page.page_route.startsWith("/") && !existsSync56(absPath)) {
30222
+ if (page.page_route.startsWith("/") && !existsSync57(absPath)) {
29845
30223
  const altPath = resolve35(PROJECT_ROOT, `src/app${page.page_route}/page.tsx`);
29846
- if (!existsSync56(altPath)) {
30224
+ if (!existsSync57(altPath)) {
29847
30225
  missingPages.push(page.page_route);
29848
30226
  }
29849
30227
  }
@@ -30369,8 +30747,8 @@ var init_sentinel_tools = __esm({
30369
30747
  });
30370
30748
 
30371
30749
  // src/sentinel-scanner.ts
30372
- import { readFileSync as readFileSync48, existsSync as existsSync57, readdirSync as readdirSync26, statSync as statSync19 } from "fs";
30373
- import { resolve as resolve36, join as join34, basename as basename10, dirname as dirname25, relative as relative13 } from "path";
30750
+ import { readFileSync as readFileSync48, existsSync as existsSync58, readdirSync as readdirSync26, statSync as statSync19 } from "fs";
30751
+ import { resolve as resolve36, join as join35, basename as basename10, dirname as dirname26, relative as relative13 } from "path";
30374
30752
  function inferDomain(filePath) {
30375
30753
  const domains = getConfig().domains;
30376
30754
  const path = filePath.toLowerCase();
@@ -30502,7 +30880,7 @@ function scanComponentExports(dataDb) {
30502
30880
  const componentsBase = config.paths.components ?? config.paths.source + "/components";
30503
30881
  const componentDirs = [];
30504
30882
  const basePath = resolve36(projectRoot, componentsBase);
30505
- if (existsSync57(basePath)) {
30883
+ if (existsSync58(basePath)) {
30506
30884
  try {
30507
30885
  const entries = readdirSync26(basePath, { withFileTypes: true });
30508
30886
  for (const entry of entries) {
@@ -30515,7 +30893,7 @@ function scanComponentExports(dataDb) {
30515
30893
  }
30516
30894
  for (const dir of componentDirs) {
30517
30895
  const absDir = resolve36(projectRoot, dir);
30518
- if (!existsSync57(absDir)) continue;
30896
+ if (!existsSync58(absDir)) continue;
30519
30897
  const files = walkDir2(absDir).filter((f2) => f2.endsWith(".tsx") || f2.endsWith(".ts"));
30520
30898
  for (const file of files) {
30521
30899
  const relPath = relative13(projectRoot, file);
@@ -30545,7 +30923,7 @@ function scanComponentExports(dataDb) {
30545
30923
  if (hasHandlers && exportMatch) {
30546
30924
  const componentName = exportMatch[1];
30547
30925
  const domain = inferDomain(relPath);
30548
- const subdomain = basename10(dirname25(relPath));
30926
+ const subdomain = basename10(dirname26(relPath));
30549
30927
  const featureKey = `component.${subdomain}.${componentName.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "")}`;
30550
30928
  if (!annotations.some((a2) => a2.featureKey === featureKey)) {
30551
30929
  features.push({
@@ -30570,7 +30948,7 @@ function walkDir2(dir) {
30570
30948
  try {
30571
30949
  const entries = readdirSync26(dir);
30572
30950
  for (const entry of entries) {
30573
- const fullPath = join34(dir, entry);
30951
+ const fullPath = join35(dir, entry);
30574
30952
  try {
30575
30953
  const stat = statSync19(fullPath);
30576
30954
  if (stat.isDirectory()) {
@@ -31280,7 +31658,7 @@ var init_prompt_analyzer = __esm({
31280
31658
  });
31281
31659
 
31282
31660
  // src/validation-engine.ts
31283
- import { existsSync as existsSync58, readFileSync as readFileSync49 } from "fs";
31661
+ import { existsSync as existsSync59, readFileSync as readFileSync49 } from "fs";
31284
31662
  function p10(baseName) {
31285
31663
  return `${getConfig().toolPrefix}_${baseName}`;
31286
31664
  }
@@ -31311,7 +31689,7 @@ function validateFile(filePath, projectRoot) {
31311
31689
  });
31312
31690
  return checks;
31313
31691
  }
31314
- if (!existsSync58(absPath)) {
31692
+ if (!existsSync59(absPath)) {
31315
31693
  checks.push({
31316
31694
  name: "file_exists",
31317
31695
  severity: "error",
@@ -31779,7 +32157,7 @@ var init_adr_generator = __esm({
31779
32157
  });
31780
32158
 
31781
32159
  // src/security-scorer.ts
31782
- import { existsSync as existsSync59, readFileSync as readFileSync50 } from "fs";
32160
+ import { existsSync as existsSync60, readFileSync as readFileSync50 } from "fs";
31783
32161
  function p12(baseName) {
31784
32162
  return `${getConfig().toolPrefix}_${baseName}`;
31785
32163
  }
@@ -31803,7 +32181,7 @@ function scoreFileSecurity(filePath, projectRoot) {
31803
32181
  }]
31804
32182
  };
31805
32183
  }
31806
- if (!existsSync59(absPath)) {
32184
+ if (!existsSync60(absPath)) {
31807
32185
  return { riskScore: 0, findings: [] };
31808
32186
  }
31809
32187
  let source;
@@ -32098,7 +32476,7 @@ var init_security_scorer = __esm({
32098
32476
  });
32099
32477
 
32100
32478
  // src/dependency-scorer.ts
32101
- import { existsSync as existsSync60, readFileSync as readFileSync51 } from "fs";
32479
+ import { existsSync as existsSync61, readFileSync as readFileSync51 } from "fs";
32102
32480
  import { resolve as resolve37 } from "path";
32103
32481
  function p13(baseName) {
32104
32482
  return `${getConfig().toolPrefix}_${baseName}`;
@@ -32132,7 +32510,7 @@ function calculateDepRisk(factors) {
32132
32510
  }
32133
32511
  function getInstalledPackages(projectRoot) {
32134
32512
  const pkgPath = resolve37(projectRoot, "package.json");
32135
- if (!existsSync60(pkgPath)) return /* @__PURE__ */ new Map();
32513
+ if (!existsSync61(pkgPath)) return /* @__PURE__ */ new Map();
32136
32514
  try {
32137
32515
  const pkg = JSON.parse(readFileSync51(pkgPath, "utf-8"));
32138
32516
  const packages = /* @__PURE__ */ new Map();
@@ -32740,7 +33118,7 @@ var init_regression_detector = __esm({
32740
33118
 
32741
33119
  // src/knowledge-indexer.ts
32742
33120
  import { createHash as createHash14 } from "crypto";
32743
- import { readFileSync as readFileSync52, readdirSync as readdirSync27, statSync as statSync20, existsSync as existsSync61 } from "fs";
33121
+ import { readFileSync as readFileSync52, readdirSync as readdirSync27, statSync as statSync20, existsSync as existsSync62 } from "fs";
32744
33122
  import { resolve as resolve38, relative as relative14, basename as basename11, extname as extname2 } from "path";
32745
33123
  function getKnowledgePaths() {
32746
33124
  const resolved = getResolvedPaths();
@@ -33048,11 +33426,11 @@ function indexAllKnowledge(db) {
33048
33426
  files.push(...memFiles);
33049
33427
  } catch {
33050
33428
  }
33051
- if (existsSync61(paths.plansDir)) {
33429
+ if (existsSync62(paths.plansDir)) {
33052
33430
  const planFiles = discoverMarkdownFiles(paths.plansDir);
33053
33431
  files.push(...planFiles);
33054
33432
  }
33055
- if (existsSync61(paths.docsDir)) {
33433
+ if (existsSync62(paths.docsDir)) {
33056
33434
  const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
33057
33435
  const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
33058
33436
  files.push(...docsFiles);
@@ -33095,7 +33473,7 @@ function indexAllKnowledge(db) {
33095
33473
  } catch {
33096
33474
  }
33097
33475
  for (const filePath of files) {
33098
- if (!existsSync61(filePath)) continue;
33476
+ if (!existsSync62(filePath)) continue;
33099
33477
  const content = readFileSync52(filePath, "utf-8");
33100
33478
  const hash = hashContent2(content);
33101
33479
  const relPath = filePath.startsWith(paths.claudeDir) ? relative14(paths.claudeDir, filePath) : filePath.startsWith(paths.plansDir) ? "plans/" + relative14(paths.plansDir, filePath) : filePath.startsWith(paths.docsDir) ? "docs/" + relative14(paths.docsDir, filePath) : filePath.startsWith(paths.memoryDir) ? `memory/${relative14(paths.memoryDir, filePath)}` : basename11(filePath);
@@ -33231,10 +33609,10 @@ function isKnowledgeStale(db) {
33231
33609
  files.push(...discoverMarkdownFiles(paths.memoryDir));
33232
33610
  } catch {
33233
33611
  }
33234
- if (existsSync61(paths.plansDir)) {
33612
+ if (existsSync62(paths.plansDir)) {
33235
33613
  files.push(...discoverMarkdownFiles(paths.plansDir));
33236
33614
  }
33237
- if (existsSync61(paths.docsDir)) {
33615
+ if (existsSync62(paths.docsDir)) {
33238
33616
  const excludePatterns = getConfig().conventions?.excludePatterns ?? ["/ARCHIVE/", "/SESSION-HISTORY/"];
33239
33617
  const docsFiles = discoverMarkdownFiles(paths.docsDir).filter((f2) => !f2.includes("/plans/") && !excludePatterns.some((p19) => f2.includes(p19)));
33240
33618
  files.push(...docsFiles);
@@ -33263,7 +33641,7 @@ var init_knowledge_indexer = __esm({
33263
33641
  });
33264
33642
 
33265
33643
  // src/knowledge-tools.ts
33266
- import { readFileSync as readFileSync53, writeFileSync as writeFileSync14, appendFileSync as appendFileSync4, readdirSync as readdirSync28 } from "fs";
33644
+ import { readFileSync as readFileSync53, writeFileSync as writeFileSync14, appendFileSync as appendFileSync5, readdirSync as readdirSync28 } from "fs";
33267
33645
  import { resolve as resolve39, basename as basename12 } from "path";
33268
33646
  function p16(baseName) {
33269
33647
  return `${getConfig().toolPrefix}_${baseName}`;
@@ -34025,7 +34403,7 @@ function handleCorrect(db, args2) {
34025
34403
  const after = existing.slice(archiveIdx);
34026
34404
  writeFileSync14(correctionsPath, before + entry + after);
34027
34405
  } else {
34028
- appendFileSync4(correctionsPath, entry);
34406
+ appendFileSync5(correctionsPath, entry);
34029
34407
  }
34030
34408
  const doc = db.prepare("SELECT id FROM knowledge_documents WHERE file_path LIKE ?").get("%corrections.md");
34031
34409
  if (doc) {
@@ -34972,7 +35350,7 @@ var init_framework_supports = __esm({
34972
35350
  });
34973
35351
 
34974
35352
  // src/tools.ts
34975
- import { readFileSync as readFileSync54, existsSync as existsSync63 } from "fs";
35353
+ import { readFileSync as readFileSync54, existsSync as existsSync64 } from "fs";
34976
35354
  import { resolve as resolve40, basename as basename13 } from "path";
34977
35355
  function prefix2() {
34978
35356
  return getConfig().toolPrefix;
@@ -35392,7 +35770,7 @@ function handleContext(file, dataDb, codegraphDb) {
35392
35770
  const resolvedPaths = getResolvedPaths();
35393
35771
  const root = getProjectRoot();
35394
35772
  const absFilePath = ensureWithinRoot(resolve40(resolvedPaths.srcDir, "..", file), root);
35395
- if (existsSync63(absFilePath)) {
35773
+ if (existsSync64(absFilePath)) {
35396
35774
  const fileContent = readFileSync54(absFilePath, "utf-8").slice(0, 3e3);
35397
35775
  const keywords = [];
35398
35776
  if (fileContent.includes("ctx.db")) keywords.push("database", "schema");
@@ -35831,7 +36209,7 @@ function handleSchema(args2) {
35831
36209
  lines.push("");
35832
36210
  const projectRoot = getProjectRoot();
35833
36211
  const absPath = ensureWithinRoot(resolve40(projectRoot, file), projectRoot);
35834
- if (!existsSync63(absPath)) {
36212
+ if (!existsSync64(absPath)) {
35835
36213
  return text17(`File not found: ${file}`);
35836
36214
  }
35837
36215
  const source = readFileSync54(absPath, "utf-8");
@@ -36267,7 +36645,7 @@ var init_startup_health = __esm({
36267
36645
  // src/server.ts
36268
36646
  var server_exports = {};
36269
36647
  import { readFileSync as readFileSync55 } from "fs";
36270
- import { resolve as resolve41, dirname as dirname26 } from "path";
36648
+ import { resolve as resolve41, dirname as dirname27 } from "path";
36271
36649
  import { fileURLToPath as fileURLToPath6 } from "url";
36272
36650
  function pruneMemoryOnStartup() {
36273
36651
  try {
@@ -36310,7 +36688,9 @@ var init_server = __esm({
36310
36688
  init_license();
36311
36689
  init_server_dispatch();
36312
36690
  init_startup_health();
36313
- __dirname5 = dirname26(fileURLToPath6(import.meta.url));
36691
+ init_sqlite_loader();
36692
+ init_config();
36693
+ __dirname5 = dirname27(fileURLToPath6(import.meta.url));
36314
36694
  PKG_VERSION = (() => {
36315
36695
  try {
36316
36696
  const pkg = JSON.parse(readFileSync55(resolve41(__dirname5, "..", "package.json"), "utf-8"));
@@ -36321,7 +36701,14 @@ var init_server = __esm({
36321
36701
  })();
36322
36702
  dispatcher = createDispatcher({ serverInfoVersion: PKG_VERSION });
36323
36703
  try {
36324
- assertMemoryEngineHealthy(getMemoryDb);
36704
+ const memoryDbPath = getResolvedPaths().memoryDbPath;
36705
+ const verdict = probeMemoryDbUsable({ dbPath: memoryDbPath, selfHeal: true });
36706
+ if (!verdict.ok) {
36707
+ throw new FatalStartupError(
36708
+ `the memory database engine is unusable (reason: ${verdict.reason}). ${verdict.detail ? verdict.detail.trim() + " " : ""}${NATIVE_DB_REMEDY}`
36709
+ );
36710
+ }
36711
+ assertMemoryEngineHealthy(() => openDatabase(memoryDbPath));
36325
36712
  } catch (error) {
36326
36713
  if (error instanceof FatalStartupError) {
36327
36714
  process.stderr.write(`massu: FATAL \u2014 ${error.message}
@@ -36609,7 +36996,7 @@ var config_upgrade_exports = {};
36609
36996
  __export(config_upgrade_exports, {
36610
36997
  runConfigUpgrade: () => runConfigUpgrade
36611
36998
  });
36612
- import { existsSync as existsSync64, readFileSync as readFileSync56, writeFileSync as writeFileSync15, copyFileSync as copyFileSync3, unlinkSync as unlinkSync6 } from "fs";
36999
+ import { existsSync as existsSync65, readFileSync as readFileSync56, writeFileSync as writeFileSync15, copyFileSync as copyFileSync3, unlinkSync as unlinkSync6 } from "fs";
36613
37000
  import { resolve as resolve42 } from "path";
36614
37001
  import { parse as parseYaml6 } from "yaml";
36615
37002
  async function runConfigUpgrade(opts = {}) {
@@ -36621,7 +37008,7 @@ async function runConfigUpgrade(opts = {}) {
36621
37008
  const err = opts.silent ? () => {
36622
37009
  } : (s) => process.stderr.write(s);
36623
37010
  if (opts.rollback) {
36624
- if (!existsSync64(bakPath)) {
37011
+ if (!existsSync65(bakPath)) {
36625
37012
  const message = `No backup found at ${bakPath}`;
36626
37013
  err(message + "\n");
36627
37014
  return { exitCode: 1, action: "none", message };
@@ -36637,7 +37024,7 @@ async function runConfigUpgrade(opts = {}) {
36637
37024
  return { exitCode: 2, action: "none", message };
36638
37025
  }
36639
37026
  }
36640
- if (!existsSync64(configPath)) {
37027
+ if (!existsSync65(configPath)) {
36641
37028
  const message = "massu.config.yaml not found. Run: npx massu init";
36642
37029
  err(message + "\n");
36643
37030
  return { exitCode: 1, action: "none", message };
@@ -36701,7 +37088,7 @@ var config_check_drift_exports = {};
36701
37088
  __export(config_check_drift_exports, {
36702
37089
  runConfigCheckDrift: () => runConfigCheckDrift
36703
37090
  });
36704
- import { existsSync as existsSync65, readFileSync as readFileSync57 } from "fs";
37091
+ import { existsSync as existsSync66, readFileSync as readFileSync57 } from "fs";
36705
37092
  import { resolve as resolve43 } from "path";
36706
37093
  import { parse as parseYaml7 } from "yaml";
36707
37094
  function renderChanges(changes) {
@@ -36715,7 +37102,7 @@ async function runConfigCheckDrift(opts = {}) {
36715
37102
  } : (s) => process.stdout.write(s);
36716
37103
  const err = opts.silent ? () => {
36717
37104
  } : (s) => process.stderr.write(s);
36718
- if (!existsSync65(configPath)) {
37105
+ if (!existsSync66(configPath)) {
36719
37106
  const message = "massu.config.yaml not found. Run: npx massu init";
36720
37107
  err(message + "\n");
36721
37108
  return {
@@ -36797,10 +37184,10 @@ var init_config_check_drift = __esm({
36797
37184
 
36798
37185
  // src/cli.ts
36799
37186
  import { readFileSync as readFileSync58 } from "fs";
36800
- import { resolve as resolve44, dirname as dirname27 } from "path";
37187
+ import { resolve as resolve44, dirname as dirname28 } from "path";
36801
37188
  import { fileURLToPath as fileURLToPath7 } from "url";
36802
37189
  var __filename5 = fileURLToPath7(import.meta.url);
36803
- var __dirname6 = dirname27(__filename5);
37190
+ var __dirname6 = dirname28(__filename5);
36804
37191
  var args = process.argv.slice(2);
36805
37192
  var subcommand = args[0];
36806
37193
  async function main() {
@@ -36820,6 +37207,12 @@ async function main() {
36820
37207
  await runLogin2(args.slice(1));
36821
37208
  break;
36822
37209
  }
37210
+ case "heal": {
37211
+ const { runHeal: runHeal2 } = await Promise.resolve().then(() => (init_heal(), heal_exports));
37212
+ const result = await runHeal2(args.slice(1));
37213
+ process.exit(result.exitCode);
37214
+ return;
37215
+ }
36823
37216
  case "logout": {
36824
37217
  const { runLogout: runLogout2 } = await Promise.resolve().then(() => (init_login(), login_exports));
36825
37218
  await runLogout2();