@massu/core 2.5.3 → 2.5.5

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
@@ -421,12 +421,12 @@ function runRebuild(pkgDir, abiFrom, abiTo, start) {
421
421
  }
422
422
  const prebuildBin = resolveLocalBin(pkgDir, "prebuild-install");
423
423
  if (prebuildBin) {
424
- const r2 = spawnSync2(process.execPath, [prebuildBin], {
424
+ const r3 = spawnSync2(process.execPath, [prebuildBin], {
425
425
  cwd: pkgDir,
426
426
  encoding: "utf-8",
427
427
  timeout: 12e4
428
428
  });
429
- if (r2.status === 0) {
429
+ if (r3.status === 0) {
430
430
  const res2 = { healed: true, method: "prebuild-install", abiFrom, abiTo, durationMs: Date.now() - start };
431
431
  recordHealEvent({ phase: "success", reason: "abi-mismatch", ...res2 });
432
432
  return res2;
@@ -434,12 +434,12 @@ function runRebuild(pkgDir, abiFrom, abiTo, start) {
434
434
  }
435
435
  const gypBin = resolveNodeGypBin();
436
436
  if (gypBin && hasCompiler()) {
437
- const r2 = spawnSync2(process.execPath, [gypBin, "rebuild", "--release"], {
437
+ const r3 = spawnSync2(process.execPath, [gypBin, "rebuild", "--release"], {
438
438
  cwd: pkgDir,
439
439
  encoding: "utf-8",
440
440
  timeout: 3e5
441
441
  });
442
- if (r2.status === 0) {
442
+ if (r3.status === 0) {
443
443
  const res2 = { healed: true, method: "node-gyp", abiFrom, abiTo, durationMs: Date.now() - start };
444
444
  recordHealEvent({ phase: "success", reason: "abi-mismatch", ...res2 });
445
445
  return res2;
@@ -518,8 +518,8 @@ function resolveNodeGypBin() {
518
518
  function hasCompiler() {
519
519
  for (const cc of ["cc", "clang", "gcc"]) {
520
520
  try {
521
- const r2 = spawnSync2(cc, ["--version"], { encoding: "utf-8", timeout: 5e3 });
522
- if (r2.status === 0) return true;
521
+ const r3 = spawnSync2(cc, ["--version"], { encoding: "utf-8", timeout: 5e3 });
522
+ if (r3.status === 0) return true;
523
523
  } catch {
524
524
  }
525
525
  }
@@ -593,10 +593,10 @@ function openNodeSqlite(dbPath, opts) {
593
593
  const st = raw.prepare(sql);
594
594
  return {
595
595
  run: (...p19) => {
596
- const r2 = st.run(...p19);
596
+ const r3 = st.run(...p19);
597
597
  return {
598
- changes: typeof r2.changes === "bigint" ? Number(r2.changes) : r2.changes,
599
- lastInsertRowid: r2.lastInsertRowid
598
+ changes: typeof r3.changes === "bigint" ? Number(r3.changes) : r3.changes,
599
+ lastInsertRowid: r3.lastInsertRowid
600
600
  };
601
601
  },
602
602
  get: (...p19) => plainRow(st.get(...p19)),
@@ -1170,7 +1170,8 @@ var init_config = __esm({
1170
1170
  input_per_million: z2.number(),
1171
1171
  output_per_million: z2.number(),
1172
1172
  cache_read_per_million: z2.number().optional(),
1173
- cache_write_per_million: z2.number().optional()
1173
+ cache_write_per_million: z2.number().optional(),
1174
+ cache_write_1h_per_million: z2.number().optional()
1174
1175
  });
1175
1176
  AnalyticsConfigSchema = z2.object({
1176
1177
  quality: z2.object({
@@ -1793,7 +1794,7 @@ function tableExists(db, table) {
1793
1794
  }
1794
1795
  function columns(db, table) {
1795
1796
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
1796
- return new Set(rows.map((r2) => r2.name));
1797
+ return new Set(rows.map((r3) => r3.name));
1797
1798
  }
1798
1799
  function migrateRuleDelivery(db) {
1799
1800
  const ADDITIONS = [
@@ -1814,8 +1815,8 @@ function migrateRuleDelivery(db) {
1814
1815
  function undeliveredSnapshot(db) {
1815
1816
  const count = (t2) => {
1816
1817
  if (!tableExists(db, t2)) return 0;
1817
- const r2 = db.prepare(`SELECT COUNT(*) AS n FROM ${t2}`).get();
1818
- return r2.n;
1818
+ const r3 = db.prepare(`SELECT COUNT(*) AS n FROM ${t2}`).get();
1819
+ return r3.n;
1819
1820
  };
1820
1821
  const promotions = count("team_promotion_outbound");
1821
1822
  const revocations = count("team_revocation_outbound");
@@ -1825,9 +1826,9 @@ function undeliveredSnapshot(db) {
1825
1826
  for (const t2 of RULE_OUTBOUND_TABLES) {
1826
1827
  if (!tableExists(db, t2)) continue;
1827
1828
  if (!columns(db, t2).has("attempts")) continue;
1828
- const r2 = db.prepare(`SELECT MAX(attempts) AS a, MIN(created_at) AS c FROM ${t2}`).get();
1829
- if (r2.a !== null && r2.a > maxAttempts) maxAttempts = r2.a;
1830
- if (r2.c !== null && (oldest === null || r2.c < oldest)) oldest = r2.c;
1829
+ const r3 = db.prepare(`SELECT MAX(attempts) AS a, MIN(created_at) AS c FROM ${t2}`).get();
1830
+ if (r3.a !== null && r3.a > maxAttempts) maxAttempts = r3.a;
1831
+ if (r3.c !== null && (oldest === null || r3.c < oldest)) oldest = r3.c;
1831
1832
  }
1832
1833
  return {
1833
1834
  promotions,
@@ -1918,9 +1919,9 @@ function setCandidateStatus(db, promptHash, status, destination) {
1918
1919
  }
1919
1920
  function getCandidate(db, promptHash) {
1920
1921
  ensureRuleCandidatesTable(db);
1921
- const r2 = db.prepare("SELECT * FROM rule_candidates WHERE prompt_hash = ?").get(promptHash);
1922
- if (!r2) return null;
1923
- return { ...r2, payload: safeParse(r2.payload_json) };
1922
+ const r3 = db.prepare("SELECT * FROM rule_candidates WHERE prompt_hash = ?").get(promptHash);
1923
+ if (!r3) return null;
1924
+ return { ...r3, payload: safeParse(r3.payload_json) };
1924
1925
  }
1925
1926
  function safeParse(raw) {
1926
1927
  try {
@@ -2138,11 +2139,11 @@ function getActiveEmbedModel() {
2138
2139
  }
2139
2140
  function loadEmbedSettings() {
2140
2141
  try {
2141
- const r2 = getConfig().memory?.recall;
2142
+ const r3 = getConfig().memory?.recall;
2142
2143
  return {
2143
- enabled: r2?.embedEnabled ?? true,
2144
- endpoint: r2?.embedEndpoint,
2145
- model: r2?.embedModel
2144
+ enabled: r3?.embedEnabled ?? true,
2145
+ endpoint: r3?.embedEndpoint,
2146
+ model: r3?.embedModel
2146
2147
  };
2147
2148
  } catch {
2148
2149
  return { enabled: true };
@@ -2416,13 +2417,13 @@ async function runEmbedSweep(db, cfg, opts = {}) {
2416
2417
  break;
2417
2418
  }
2418
2419
  const units = [];
2419
- for (const r2 of rows) {
2420
+ for (const r3 of rows) {
2420
2421
  if (cfg.chunked) {
2421
- const parts = chunkForEmbedding(r2.text);
2422
+ const parts = chunkForEmbedding(r3.text);
2422
2423
  if (parts.length === 0) continue;
2423
- parts.forEach((text18, chunkIx) => units.push({ id: r2.id, chunkIx, text: text18 }));
2424
+ parts.forEach((text18, chunkIx) => units.push({ id: r3.id, chunkIx, text: text18 }));
2424
2425
  } else {
2425
- units.push({ id: r2.id, chunkIx: 0, text: r2.text });
2426
+ units.push({ id: r3.id, chunkIx: 0, text: r3.text });
2426
2427
  }
2427
2428
  }
2428
2429
  const vecs = await embedBatch(units.map((u2) => u2.text));
@@ -2541,6 +2542,7 @@ __export(memory_db_exports, {
2541
2542
  pruneToolCostEvents: () => pruneToolCostEvents,
2542
2543
  recordRecallHits: () => recordRecallHits,
2543
2544
  recordTelemetry: () => recordTelemetry,
2545
+ releaseMetaLease: () => releaseMetaLease,
2544
2546
  removePendingSync: () => removePendingSync,
2545
2547
  sanitizeFts5Query: () => sanitizeFts5Query,
2546
2548
  sanitizeFts5QueryOr: () => sanitizeFts5QueryOr,
@@ -2549,6 +2551,7 @@ __export(memory_db_exports, {
2549
2551
  searchObservations: () => searchObservations,
2550
2552
  setLastProcessedLine: () => setLastProcessedLine,
2551
2553
  setMemoryMeta: () => setMemoryMeta,
2554
+ tryAcquireMetaLease: () => tryAcquireMetaLease,
2552
2555
  upsertObservationEmbedding: () => upsertObservationEmbedding,
2553
2556
  usageWarmupElapsed: () => usageWarmupElapsed
2554
2557
  });
@@ -3054,6 +3057,15 @@ function initMemorySchema(db) {
3054
3057
  );
3055
3058
  CREATE INDEX IF NOT EXISTS idx_sc_session ON session_costs(session_id);
3056
3059
  `);
3060
+ const costCols = db.prepare(`PRAGMA table_info(session_costs)`).all();
3061
+ const addCostCol = (name, ddl) => {
3062
+ if (!costCols.some((c2) => c2.name === name)) db.exec(`ALTER TABLE session_costs ADD COLUMN ${ddl}`);
3063
+ };
3064
+ addCostCol("cost_status", `cost_status TEXT NOT NULL DEFAULT 'unknown'`);
3065
+ addCostCol("unpriced_models", `unpriced_models TEXT NOT NULL DEFAULT ''`);
3066
+ addCostCol("priced_responses", `priced_responses INTEGER NOT NULL DEFAULT 0`);
3067
+ addCostCol("unpriced_responses", `unpriced_responses INTEGER NOT NULL DEFAULT 0`);
3068
+ addCostCol("pricing_version", `pricing_version INTEGER NOT NULL DEFAULT 0`);
3057
3069
  db.exec(`
3058
3070
  CREATE TABLE IF NOT EXISTS feature_costs (
3059
3071
  id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -3483,6 +3495,18 @@ function getMemoryMeta(db, key) {
3483
3495
  function setMemoryMeta(db, key, value) {
3484
3496
  db.prepare("INSERT OR REPLACE INTO memory_meta (key, value) VALUES (?, ?)").run(key, value);
3485
3497
  }
3498
+ function tryAcquireMetaLease(db, key, ttlSec, nowSec = Math.floor(Date.now() / 1e3)) {
3499
+ const r3 = db.prepare(
3500
+ `INSERT INTO memory_meta (key, value) VALUES (?, ?)
3501
+ ON CONFLICT(key) DO UPDATE SET value = excluded.value
3502
+ WHERE memory_meta.value = ''
3503
+ OR CAST(substr(memory_meta.value, instr(memory_meta.value, ':') + 1) AS INTEGER) <= ?`
3504
+ ).run(key, `${process.pid}:${nowSec + ttlSec}`, nowSec);
3505
+ return Number(r3.changes) === 1;
3506
+ }
3507
+ function releaseMetaLease(db, key) {
3508
+ db.prepare(`UPDATE memory_meta SET value = '' WHERE key = ? AND value LIKE ?`).run(key, `${process.pid}:%`);
3509
+ }
3486
3510
  function upsertObservationEmbedding(db, observationId, vec, modelId, dim) {
3487
3511
  db.prepare(
3488
3512
  `INSERT OR REPLACE INTO observation_embeddings (observation_id, model_id, dim, vec, created_at)
@@ -3524,7 +3548,7 @@ async function embedMissingObservations(db, opts = {}) {
3524
3548
  )
3525
3549
  ORDER BY o.id LIMIT ?`
3526
3550
  ).all(cursor, batchSize);
3527
- return rows.map((r2) => ({ id: r2.id, text: observationEmbedText(r2.title, r2.detail) }));
3551
+ return rows.map((r3) => ({ id: r3.id, text: observationEmbedText(r3.title, r3.detail) }));
3528
3552
  }
3529
3553
  },
3530
3554
  opts
@@ -3612,9 +3636,9 @@ function rescueLearningFromStalePayloads(db, stale) {
3612
3636
  rescued++;
3613
3637
  }
3614
3638
  const revocations = Array.isArray(payload.rule_revocations) ? payload.rule_revocations : [];
3615
- for (const r2 of revocations) {
3616
- if (typeof r2?.prompt_hash === "string") {
3617
- enqueueTeamRevocation(db, r2.prompt_hash);
3639
+ for (const r3 of revocations) {
3640
+ if (typeof r3?.prompt_hash === "string") {
3641
+ enqueueTeamRevocation(db, r3.prompt_hash);
3618
3642
  rescued++;
3619
3643
  }
3620
3644
  }
@@ -4351,7 +4375,7 @@ var init_memory_db = __esm({
4351
4375
  init_rule_candidate_store();
4352
4376
  init_hook_failure_signal();
4353
4377
  init_memory_embed_sweep();
4354
- MEMORY_SCHEMA_VERSION = 1;
4378
+ MEMORY_SCHEMA_VERSION = 2;
4355
4379
  TOOL_COST_EVENTS_RETENTION_DAYS = 90;
4356
4380
  MAX_DRAFT_TEXT_LEN = 16384;
4357
4381
  FUNNEL_EVENT_OUTBOX_CAP = 2e4;
@@ -5831,7 +5855,7 @@ var init_install_commands = __esm({
5831
5855
  });
5832
5856
 
5833
5857
  // src/lib/hook-timeouts.ts
5834
- var HOOK_TIMEOUTS;
5858
+ var HOOK_TIMEOUTS, BACKGROUND_HOOKS;
5835
5859
  var init_hook_timeouts = __esm({
5836
5860
  "src/lib/hook-timeouts.ts"() {
5837
5861
  "use strict";
@@ -5865,6 +5889,7 @@ var init_hook_timeouts = __esm({
5865
5889
  // always fails open on its own terms before the platform kills it.
5866
5890
  "memory-recall": 10
5867
5891
  };
5892
+ BACKGROUND_HOOKS = /* @__PURE__ */ new Set(["session-end"]);
5868
5893
  }
5869
5894
  });
5870
5895
 
@@ -6583,13 +6608,13 @@ var init_package_detector = __esm({
6583
6608
  // src/detect/framework-detector.ts
6584
6609
  function matchRule(rules, language, kind, deps) {
6585
6610
  let best = null;
6586
- for (const r2 of rules) {
6587
- if (r2.language !== language) continue;
6588
- if (r2.kind !== kind) continue;
6589
- if (!deps.has(r2.keyword.toLowerCase())) continue;
6590
- const pr = r2.priority ?? 0;
6611
+ for (const r3 of rules) {
6612
+ if (r3.language !== language) continue;
6613
+ if (r3.kind !== kind) continue;
6614
+ if (!deps.has(r3.keyword.toLowerCase())) continue;
6615
+ const pr = r3.priority ?? 0;
6591
6616
  if (!best || pr > best.priority) {
6592
- best = { value: r2.value, priority: pr };
6617
+ best = { value: r3.value, priority: pr };
6593
6618
  }
6594
6619
  }
6595
6620
  return best;
@@ -15121,12 +15146,12 @@ async function introspectAsync(detection, projectRoot) {
15121
15146
  }
15122
15147
  return out;
15123
15148
  }
15124
- function serializeAdapterBlock(r2) {
15125
- const block = { ...r2.conventions };
15126
- if (Object.keys(r2._provenance).length > 0) {
15127
- block._provenance = r2._provenance;
15149
+ function serializeAdapterBlock(r3) {
15150
+ const block = { ...r3.conventions };
15151
+ if (Object.keys(r3._provenance).length > 0) {
15152
+ block._provenance = r3._provenance;
15128
15153
  }
15129
- block._confidence = r2.confidence;
15154
+ block._confidence = r3.confidence;
15130
15155
  return block;
15131
15156
  }
15132
15157
  var FIRST_PARTY_ADAPTERS;
@@ -16058,7 +16083,7 @@ var init_dist2 = __esm({
16058
16083
  }
16059
16084
  };
16060
16085
  k2 = (s) => {
16061
- const { cursor: n, options: t2, style: i } = s, r2 = s.maxItems ?? Number.POSITIVE_INFINITY, c2 = Math.max(process.stdout.rows - 4, 0), o = Math.min(c2, Math.max(r2, 5));
16086
+ const { cursor: n, options: t2, style: i } = s, r3 = s.maxItems ?? Number.POSITIVE_INFINITY, c2 = Math.max(process.stdout.rows - 4, 0), o = Math.min(c2, Math.max(r3, 5));
16062
16087
  let l2 = 0;
16063
16088
  n >= l2 + o - 3 ? l2 = Math.max(Math.min(n - o + 3, t2.length - o), 0) : n < l2 + 2 && (l2 = Math.max(n - 2, 0));
16064
16089
  const $2 = o < t2.length && l2 > 0, d2 = o < t2.length && l2 + o < t2.length;
@@ -16114,12 +16139,12 @@ ${import_picocolors2.default.cyan(m2)}
16114
16139
  return new fD({ active: n, inactive: t2, initialValue: s.initialValue ?? true, render() {
16115
16140
  const i = `${import_picocolors2.default.gray(a)}
16116
16141
  ${y2(this.state)} ${s.message}
16117
- `, r2 = this.value ? n : t2;
16142
+ `, r3 = this.value ? n : t2;
16118
16143
  switch (this.state) {
16119
16144
  case "submit":
16120
- return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(r2)}`;
16145
+ return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(r3)}`;
16121
16146
  case "cancel":
16122
- return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}
16147
+ return `${i}${import_picocolors2.default.gray(a)} ${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}
16123
16148
  ${import_picocolors2.default.gray(a)}`;
16124
16149
  default:
16125
16150
  return `${i}${import_picocolors2.default.cyan(a)} ${this.value ? `${import_picocolors2.default.green(j2)} ${n}` : `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(n)}`} ${import_picocolors2.default.dim("/")} ${this.value ? `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(t2)}` : `${import_picocolors2.default.green(j2)} ${t2}`}
@@ -16130,16 +16155,16 @@ ${import_picocolors2.default.cyan(m2)}
16130
16155
  };
16131
16156
  de = (s) => {
16132
16157
  const n = (t2, i) => {
16133
- const r2 = t2.label ?? String(t2.value);
16158
+ const r3 = t2.label ?? String(t2.value);
16134
16159
  switch (i) {
16135
16160
  case "selected":
16136
- return `${import_picocolors2.default.dim(r2)}`;
16161
+ return `${import_picocolors2.default.dim(r3)}`;
16137
16162
  case "active":
16138
- return `${import_picocolors2.default.green(j2)} ${r2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}`;
16163
+ return `${import_picocolors2.default.green(j2)} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}`;
16139
16164
  case "cancelled":
16140
- return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}`;
16165
+ return `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}`;
16141
16166
  default:
16142
- return `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(r2)}`;
16167
+ return `${import_picocolors2.default.dim(R2)} ${import_picocolors2.default.dim(r3)}`;
16143
16168
  }
16144
16169
  };
16145
16170
  return new jD({ options: s.options, initialValue: s.initialValue, render() {
@@ -16153,7 +16178,7 @@ ${y2(this.state)} ${s.message}
16153
16178
  return `${t2}${import_picocolors2.default.gray(a)} ${n(this.options[this.cursor], "cancelled")}
16154
16179
  ${import_picocolors2.default.gray(a)}`;
16155
16180
  default:
16156
- return `${t2}${import_picocolors2.default.cyan(a)} ${k2({ cursor: this.cursor, options: this.options, maxItems: s.maxItems, style: (i, r2) => n(i, r2 ? "active" : "inactive") }).join(`
16181
+ return `${t2}${import_picocolors2.default.cyan(a)} ${k2({ cursor: this.cursor, options: this.options, maxItems: s.maxItems, style: (i, r3) => n(i, r3 ? "active" : "inactive") }).join(`
16157
16182
  ${import_picocolors2.default.cyan(a)} `)}
16158
16183
  ${import_picocolors2.default.cyan(m2)}
16159
16184
  `;
@@ -16162,8 +16187,8 @@ ${import_picocolors2.default.cyan(m2)}
16162
16187
  };
16163
16188
  he = (s) => {
16164
16189
  const n = (t2, i = "inactive") => {
16165
- const r2 = t2.label ?? String(t2.value);
16166
- return i === "selected" ? `${import_picocolors2.default.dim(r2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}` : i === "active" ? `${import_picocolors2.default.bgCyan(import_picocolors2.default.gray(` ${t2.value} `))} ${r2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : `${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(` ${t2.value} `)))} ${r2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}`;
16190
+ const r3 = t2.label ?? String(t2.value);
16191
+ return i === "selected" ? `${import_picocolors2.default.dim(r3)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}` : i === "active" ? `${import_picocolors2.default.bgCyan(import_picocolors2.default.gray(` ${t2.value} `))} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : `${import_picocolors2.default.gray(import_picocolors2.default.bgWhite(import_picocolors2.default.inverse(` ${t2.value} `)))} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}`;
16167
16192
  };
16168
16193
  return new OD({ options: s.options, initialValue: s.initialValue, render() {
16169
16194
  const t2 = `${import_picocolors2.default.gray(a)}
@@ -16176,7 +16201,7 @@ ${y2(this.state)} ${s.message}
16176
16201
  return `${t2}${import_picocolors2.default.gray(a)} ${n(this.options[0], "cancelled")}
16177
16202
  ${import_picocolors2.default.gray(a)}`;
16178
16203
  default:
16179
- return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r2) => n(i, r2 === this.cursor ? "active" : "inactive")).join(`
16204
+ return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r3) => n(i, r3 === this.cursor ? "active" : "inactive")).join(`
16180
16205
  ${import_picocolors2.default.cyan(a)} `)}
16181
16206
  ${import_picocolors2.default.cyan(m2)}
16182
16207
  `;
@@ -16185,8 +16210,8 @@ ${import_picocolors2.default.cyan(m2)}
16185
16210
  };
16186
16211
  pe = (s) => {
16187
16212
  const n = (t2, i) => {
16188
- const r2 = t2.label ?? String(t2.value);
16189
- return i === "active" ? `${import_picocolors2.default.cyan(V2)} ${r2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(r2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r2))}` : i === "active-selected" ? `${import_picocolors2.default.green(M2)} ${r2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(r2)}` : `${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(r2)}`;
16213
+ const r3 = t2.label ?? String(t2.value);
16214
+ return i === "active" ? `${import_picocolors2.default.cyan(V2)} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "selected" ? `${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(r3)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(r3))}` : i === "active-selected" ? `${import_picocolors2.default.green(M2)} ${r3} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(r3)}` : `${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(r3)}`;
16190
16215
  };
16191
16216
  return new wD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t2) {
16192
16217
  if (this.required && t2.length === 0) return `Please select at least one option.
@@ -16194,25 +16219,25 @@ ${import_picocolors2.default.reset(import_picocolors2.default.dim(`Press ${impor
16194
16219
  }, render() {
16195
16220
  const t2 = `${import_picocolors2.default.gray(a)}
16196
16221
  ${y2(this.state)} ${s.message}
16197
- `, i = (r2, c2) => {
16198
- const o = this.value.includes(r2.value);
16199
- return c2 && o ? n(r2, "active-selected") : o ? n(r2, "selected") : n(r2, c2 ? "active" : "inactive");
16222
+ `, i = (r3, c2) => {
16223
+ const o = this.value.includes(r3.value);
16224
+ return c2 && o ? n(r3, "active-selected") : o ? n(r3, "selected") : n(r3, c2 ? "active" : "inactive");
16200
16225
  };
16201
16226
  switch (this.state) {
16202
16227
  case "submit":
16203
- return `${t2}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: r2 }) => this.value.includes(r2)).map((r2) => n(r2, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
16228
+ return `${t2}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: r3 }) => this.value.includes(r3)).map((r3) => n(r3, "submitted")).join(import_picocolors2.default.dim(", ")) || import_picocolors2.default.dim("none")}`;
16204
16229
  case "cancel": {
16205
- const r2 = this.options.filter(({ value: c2 }) => this.value.includes(c2)).map((c2) => n(c2, "cancelled")).join(import_picocolors2.default.dim(", "));
16206
- return `${t2}${import_picocolors2.default.gray(a)} ${r2.trim() ? `${r2}
16230
+ const r3 = this.options.filter(({ value: c2 }) => this.value.includes(c2)).map((c2) => n(c2, "cancelled")).join(import_picocolors2.default.dim(", "));
16231
+ return `${t2}${import_picocolors2.default.gray(a)} ${r3.trim() ? `${r3}
16207
16232
  ${import_picocolors2.default.gray(a)}` : ""}`;
16208
16233
  }
16209
16234
  case "error": {
16210
- const r2 = this.error.split(`
16235
+ const r3 = this.error.split(`
16211
16236
  `).map((c2, o) => o === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(c2)}` : ` ${c2}`).join(`
16212
16237
  `);
16213
16238
  return `${t2 + import_picocolors2.default.yellow(a)} ${k2({ options: this.options, cursor: this.cursor, maxItems: s.maxItems, style: i }).join(`
16214
16239
  ${import_picocolors2.default.yellow(a)} `)}
16215
- ${r2}
16240
+ ${r3}
16216
16241
  `;
16217
16242
  }
16218
16243
  default:
@@ -16224,8 +16249,8 @@ ${import_picocolors2.default.cyan(m2)}
16224
16249
  } }).prompt();
16225
16250
  };
16226
16251
  ge = (s) => {
16227
- const n = (t2, i, r2 = []) => {
16228
- const c2 = t2.label ?? String(t2.value), o = typeof t2.group == "string", l2 = o && (r2[r2.indexOf(t2) + 1] ?? { group: true }), $2 = o && l2.group === true, d2 = o ? `${$2 ? m2 : a} ` : "";
16252
+ const n = (t2, i, r3 = []) => {
16253
+ const c2 = t2.label ?? String(t2.value), o = typeof t2.group == "string", l2 = o && (r3[r3.indexOf(t2) + 1] ?? { group: true }), $2 = o && l2.group === true, d2 = o ? `${$2 ? m2 : a} ` : "";
16229
16254
  return i === "active" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.cyan(V2)} ${c2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "group-active" ? `${d2}${import_picocolors2.default.cyan(V2)} ${import_picocolors2.default.dim(c2)}` : i === "group-active-selected" ? `${d2}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${import_picocolors2.default.dim(c2)}` : i === "cancelled" ? `${import_picocolors2.default.strikethrough(import_picocolors2.default.dim(c2))}` : i === "active-selected" ? `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.green(M2)} ${c2} ${t2.hint ? import_picocolors2.default.dim(`(${t2.hint})`) : ""}` : i === "submitted" ? `${import_picocolors2.default.dim(c2)}` : `${import_picocolors2.default.dim(d2)}${import_picocolors2.default.dim(G2)} ${import_picocolors2.default.dim(c2)}`;
16230
16255
  };
16231
16256
  return new dD({ options: s.options, initialValues: s.initialValues, required: s.required ?? true, cursorAt: s.cursorAt, validate(t2) {
@@ -16239,25 +16264,25 @@ ${y2(this.state)} ${s.message}
16239
16264
  case "submit":
16240
16265
  return `${t2}${import_picocolors2.default.gray(a)} ${this.options.filter(({ value: i }) => this.value.includes(i)).map((i) => n(i, "submitted")).join(import_picocolors2.default.dim(", "))}`;
16241
16266
  case "cancel": {
16242
- const i = this.options.filter(({ value: r2 }) => this.value.includes(r2)).map((r2) => n(r2, "cancelled")).join(import_picocolors2.default.dim(", "));
16267
+ const i = this.options.filter(({ value: r3 }) => this.value.includes(r3)).map((r3) => n(r3, "cancelled")).join(import_picocolors2.default.dim(", "));
16243
16268
  return `${t2}${import_picocolors2.default.gray(a)} ${i.trim() ? `${i}
16244
16269
  ${import_picocolors2.default.gray(a)}` : ""}`;
16245
16270
  }
16246
16271
  case "error": {
16247
16272
  const i = this.error.split(`
16248
- `).map((r2, c2) => c2 === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(r2)}` : ` ${r2}`).join(`
16273
+ `).map((r3, c2) => c2 === 0 ? `${import_picocolors2.default.yellow(m2)} ${import_picocolors2.default.yellow(r3)}` : ` ${r3}`).join(`
16249
16274
  `);
16250
- return `${t2}${import_picocolors2.default.yellow(a)} ${this.options.map((r2, c2, o) => {
16251
- const l2 = this.value.includes(r2.value) || r2.group === true && this.isGroupSelected(`${r2.value}`), $2 = c2 === this.cursor;
16252
- return !$2 && typeof r2.group == "string" && this.options[this.cursor].value === r2.group ? n(r2, l2 ? "group-active-selected" : "group-active", o) : $2 && l2 ? n(r2, "active-selected", o) : l2 ? n(r2, "selected", o) : n(r2, $2 ? "active" : "inactive", o);
16275
+ return `${t2}${import_picocolors2.default.yellow(a)} ${this.options.map((r3, c2, o) => {
16276
+ const l2 = this.value.includes(r3.value) || r3.group === true && this.isGroupSelected(`${r3.value}`), $2 = c2 === this.cursor;
16277
+ return !$2 && typeof r3.group == "string" && this.options[this.cursor].value === r3.group ? n(r3, l2 ? "group-active-selected" : "group-active", o) : $2 && l2 ? n(r3, "active-selected", o) : l2 ? n(r3, "selected", o) : n(r3, $2 ? "active" : "inactive", o);
16253
16278
  }).join(`
16254
16279
  ${import_picocolors2.default.yellow(a)} `)}
16255
16280
  ${i}
16256
16281
  `;
16257
16282
  }
16258
16283
  default:
16259
- return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r2, c2) => {
16260
- const o = this.value.includes(i.value) || i.group === true && this.isGroupSelected(`${i.value}`), l2 = r2 === this.cursor;
16284
+ return `${t2}${import_picocolors2.default.cyan(a)} ${this.options.map((i, r3, c2) => {
16285
+ const o = this.value.includes(i.value) || i.group === true && this.isGroupSelected(`${i.value}`), l2 = r3 === this.cursor;
16261
16286
  return !l2 && typeof i.group == "string" && this.options[this.cursor].value === i.group ? n(i, o ? "group-active-selected" : "group-active", c2) : l2 && o ? n(i, "active-selected", c2) : o ? n(i, "selected", c2) : n(i, l2 ? "active" : "inactive", c2);
16262
16287
  }).join(`
16263
16288
  ${import_picocolors2.default.cyan(a)} `)}
@@ -16270,15 +16295,15 @@ ${import_picocolors2.default.cyan(m2)}
16270
16295
  const t2 = `
16271
16296
  ${s}
16272
16297
  `.split(`
16273
- `), i = T2(n).length, r2 = Math.max(t2.reduce((o, l2) => {
16298
+ `), i = T2(n).length, r3 = Math.max(t2.reduce((o, l2) => {
16274
16299
  const $2 = T2(l2);
16275
16300
  return $2.length > o ? $2.length : o;
16276
- }, 0), i) + 2, c2 = t2.map((o) => `${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(o)}${" ".repeat(r2 - T2(o).length)}${import_picocolors2.default.gray(a)}`).join(`
16301
+ }, 0), i) + 2, c2 = t2.map((o) => `${import_picocolors2.default.gray(a)} ${import_picocolors2.default.dim(o)}${" ".repeat(r3 - T2(o).length)}${import_picocolors2.default.gray(a)}`).join(`
16277
16302
  `);
16278
16303
  process.stdout.write(`${import_picocolors2.default.gray(a)}
16279
- ${import_picocolors2.default.green(S2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(N2.repeat(Math.max(r2 - i - 1, 1)) + re)}
16304
+ ${import_picocolors2.default.green(S2)} ${import_picocolors2.default.reset(n)} ${import_picocolors2.default.gray(N2.repeat(Math.max(r3 - i - 1, 1)) + re)}
16280
16305
  ${c2}
16281
- ${import_picocolors2.default.gray(ie + N2.repeat(r2 + 2) + ne)}
16306
+ ${import_picocolors2.default.gray(ie + N2.repeat(r3 + 2) + ne)}
16282
16307
  `);
16283
16308
  };
16284
16309
  ve = (s = "") => {
@@ -16299,9 +16324,9 @@ ${import_picocolors2.default.gray(m2)} ${s}
16299
16324
  v2 = { message: (s = "", { symbol: n = import_picocolors2.default.gray(a) } = {}) => {
16300
16325
  const t2 = [`${import_picocolors2.default.gray(a)}`];
16301
16326
  if (s) {
16302
- const [i, ...r2] = s.split(`
16327
+ const [i, ...r3] = s.split(`
16303
16328
  `);
16304
- t2.push(`${n} ${i}`, ...r2.map((c2) => `${import_picocolors2.default.gray(a)} ${c2}`));
16329
+ t2.push(`${n} ${i}`, ...r3.map((c2) => `${import_picocolors2.default.gray(a)} ${c2}`));
16305
16330
  }
16306
16331
  process.stdout.write(`${t2.join(`
16307
16332
  `)}
@@ -16321,7 +16346,7 @@ ${import_picocolors2.default.gray(m2)} ${s}
16321
16346
  } };
16322
16347
  L2 = () => {
16323
16348
  const s = E ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], n = E ? 80 : 120, t2 = process.env.CI === "true";
16324
- let i, r2, c2 = false, o = "", l2;
16349
+ let i, r3, c2 = false, o = "", l2;
16325
16350
  const $2 = (h2) => {
16326
16351
  const g2 = h2 > 1 ? "Something went wrong" : "Canceled";
16327
16352
  c2 && P2(g2, h2);
@@ -16340,14 +16365,14 @@ ${import_picocolors2.default.gray(m2)} ${s}
16340
16365
  c2 = true, i = cD(), o = x2(h2), process.stdout.write(`${import_picocolors2.default.gray(a)}
16341
16366
  `);
16342
16367
  let g2 = 0, f2 = 0;
16343
- b2(), r2 = setInterval(() => {
16368
+ b2(), r3 = setInterval(() => {
16344
16369
  if (t2 && o === l2) return;
16345
16370
  I2(), l2 = o;
16346
16371
  const W2 = import_picocolors2.default.magenta(s[g2]), _2 = t2 ? "..." : ".".repeat(Math.floor(f2)).slice(0, 3);
16347
16372
  process.stdout.write(`${W2} ${o}${_2}`), g2 = g2 + 1 < s.length ? g2 + 1 : 0, f2 = f2 < s.length ? f2 + 0.125 : 0;
16348
16373
  }, n);
16349
16374
  }, P2 = (h2 = "", g2 = 0) => {
16350
- c2 = false, clearInterval(r2), I2();
16375
+ c2 = false, clearInterval(r3), I2();
16351
16376
  const f2 = g2 === 0 ? import_picocolors2.default.green(S2) : g2 === 1 ? import_picocolors2.default.red(A2) : import_picocolors2.default.red(B);
16352
16377
  o = x2(h2 ?? o), process.stdout.write(`${f2} ${o}
16353
16378
  `), C(), i();
@@ -16358,15 +16383,15 @@ ${import_picocolors2.default.gray(m2)} ${s}
16358
16383
  };
16359
16384
  be = async (s, n) => {
16360
16385
  const t2 = {}, i = Object.keys(s);
16361
- for (const r2 of i) {
16362
- const c2 = s[r2], o = await c2({ results: t2 })?.catch((l2) => {
16386
+ for (const r3 of i) {
16387
+ const c2 = s[r3], o = await c2({ results: t2 })?.catch((l2) => {
16363
16388
  throw l2;
16364
16389
  });
16365
16390
  if (typeof n?.onCancel == "function" && BD(o)) {
16366
- t2[r2] = "canceled", n.onCancel({ results: t2 });
16391
+ t2[r3] = "canceled", n.onCancel({ results: t2 });
16367
16392
  continue;
16368
16393
  }
16369
- t2[r2] = o;
16394
+ t2[r3] = o;
16370
16395
  }
16371
16396
  return t2;
16372
16397
  };
@@ -16901,10 +16926,10 @@ function validateWrittenConfig(configPath, projectRoot, checkPaths = true) {
16901
16926
  }
16902
16927
  const mRoots = cfg.paths.monorepo_roots;
16903
16928
  if (Array.isArray(mRoots)) {
16904
- for (const r2 of mRoots) {
16905
- if (typeof r2 !== "string" || r2 === ".") continue;
16906
- if (!existsSync21(resolve12(projectRoot, r2))) {
16907
- return `paths.monorepo_roots '${r2}' does not exist on disk`;
16929
+ for (const r3 of mRoots) {
16930
+ if (typeof r3 !== "string" || r3 === ".") continue;
16931
+ if (!existsSync21(resolve12(projectRoot, r3))) {
16932
+ return `paths.monorepo_roots '${r3}' does not exist on disk`;
16908
16933
  }
16909
16934
  }
16910
16935
  }
@@ -17121,13 +17146,18 @@ function hookCmd(version, hookName, shim) {
17121
17146
  function getHookTimeout(name) {
17122
17147
  return HOOK_TIMEOUTS[name] ?? 5;
17123
17148
  }
17149
+ function hookEntry(version, name, shim) {
17150
+ const entry = { type: "command", command: hookCmd(version, name, shim), timeout: getHookTimeout(name) };
17151
+ if (BACKGROUND_HOOKS.has(name)) entry.async = true;
17152
+ return entry;
17153
+ }
17124
17154
  function buildHooksConfig(_hooksDir, shim = resolveMassuShim()) {
17125
17155
  const version = getInstallerVersion();
17126
17156
  return {
17127
17157
  SessionStart: [
17128
17158
  {
17129
17159
  hooks: [
17130
- { type: "command", command: hookCmd(version, "session-start", shim), timeout: getHookTimeout("session-start") }
17160
+ hookEntry(version, "session-start", shim)
17131
17161
  ]
17132
17162
  }
17133
17163
  ],
@@ -17142,26 +17172,26 @@ function buildHooksConfig(_hooksDir, shim = resolveMassuShim()) {
17142
17172
  {
17143
17173
  matcher: "Bash|Write|Edit",
17144
17174
  hooks: [
17145
- { type: "command", command: hookCmd(version, "pre-tool-use-gate", shim), timeout: getHookTimeout("pre-tool-use-gate") }
17175
+ hookEntry(version, "pre-tool-use-gate", shim)
17146
17176
  ]
17147
17177
  }
17148
17178
  ],
17149
17179
  PostToolUse: [
17150
17180
  {
17151
17181
  hooks: [
17152
- { type: "command", command: hookCmd(version, "post-tool-use", shim), timeout: getHookTimeout("post-tool-use") },
17153
- { type: "command", command: hookCmd(version, "quality-event", shim), timeout: getHookTimeout("quality-event") },
17154
- { type: "command", command: hookCmd(version, "cost-tracker", shim), timeout: getHookTimeout("cost-tracker") }
17182
+ hookEntry(version, "post-tool-use", shim),
17183
+ hookEntry(version, "quality-event", shim),
17184
+ hookEntry(version, "cost-tracker", shim)
17155
17185
  ]
17156
17186
  },
17157
17187
  {
17158
17188
  matcher: "Edit|Write",
17159
17189
  hooks: [
17160
- { type: "command", command: hookCmd(version, "post-edit-context", shim), timeout: getHookTimeout("post-edit-context") },
17190
+ hookEntry(version, "post-edit-context", shim),
17161
17191
  // Auto-learning pipeline — classifies failures and detects fixes on
17162
17192
  // file changes. See Phase 5-6 of the autodetect plan.
17163
- { type: "command", command: hookCmd(version, "fix-detector", shim), timeout: getHookTimeout("fix-detector") },
17164
- { type: "command", command: hookCmd(version, "classify-failure", shim), timeout: getHookTimeout("classify-failure") }
17193
+ hookEntry(version, "fix-detector", shim),
17194
+ hookEntry(version, "classify-failure", shim)
17165
17195
  ]
17166
17196
  },
17167
17197
  {
@@ -17169,35 +17199,35 @@ function buildHooksConfig(_hooksDir, shim = resolveMassuShim()) {
17169
17199
  hooks: [
17170
17200
  // Incident + rule enforcement pipelines fire on Write-only (incidents
17171
17201
  // are authored as .md files; rules are enforced after new-file drops).
17172
- { type: "command", command: hookCmd(version, "incident-pipeline", shim), timeout: getHookTimeout("incident-pipeline") },
17173
- { type: "command", command: hookCmd(version, "rule-enforcement-pipeline", shim), timeout: getHookTimeout("rule-enforcement-pipeline") }
17202
+ hookEntry(version, "incident-pipeline", shim),
17203
+ hookEntry(version, "rule-enforcement-pipeline", shim)
17174
17204
  ]
17175
17205
  }
17176
17206
  ],
17177
17207
  Stop: [
17178
17208
  {
17179
17209
  hooks: [
17180
- { type: "command", command: hookCmd(version, "session-end", shim), timeout: getHookTimeout("session-end") },
17210
+ hookEntry(version, "session-end", shim),
17181
17211
  // Session-end auto-learning aggregation (failure-class roll-up).
17182
- { type: "command", command: hookCmd(version, "auto-learning-pipeline", shim), timeout: getHookTimeout("auto-learning-pipeline") }
17212
+ hookEntry(version, "auto-learning-pipeline", shim)
17183
17213
  ]
17184
17214
  }
17185
17215
  ],
17186
17216
  PreCompact: [
17187
17217
  {
17188
17218
  hooks: [
17189
- { type: "command", command: hookCmd(version, "pre-compact", shim), timeout: getHookTimeout("pre-compact") }
17219
+ hookEntry(version, "pre-compact", shim)
17190
17220
  ]
17191
17221
  }
17192
17222
  ],
17193
17223
  UserPromptSubmit: [
17194
17224
  {
17195
17225
  hooks: [
17196
- { type: "command", command: hookCmd(version, "user-prompt", shim), timeout: getHookTimeout("user-prompt") },
17197
- { type: "command", command: hookCmd(version, "intent-suggester", shim), timeout: getHookTimeout("intent-suggester") },
17226
+ hookEntry(version, "user-prompt", shim),
17227
+ hookEntry(version, "intent-suggester", shim),
17198
17228
  // plan-living-memory-slice-1 P3-002: automatic relevant-recall.
17199
17229
  // Injects a compact "🧠 Relevant memory" block; fails open (empty).
17200
- { type: "command", command: hookCmd(version, "memory-recall", shim), timeout: getHookTimeout("memory-recall") }
17230
+ hookEntry(version, "memory-recall", shim)
17201
17231
  ]
17202
17232
  }
17203
17233
  ]
@@ -20165,7 +20195,7 @@ async function embedMissingChunks(db, opts = {}) {
20165
20195
  )
20166
20196
  ORDER BY c.id LIMIT ?`
20167
20197
  ).all(cursor, batchSize);
20168
- return rows.map((r2) => ({ id: r2.id, text: chunkEmbedText(r2.heading, r2.content) }));
20198
+ return rows.map((r3) => ({ id: r3.id, text: chunkEmbedText(r3.heading, r3.content) }));
20169
20199
  }
20170
20200
  },
20171
20201
  opts
@@ -21285,7 +21315,7 @@ function buildIndexLines(db, memoryDir, planned, config) {
21285
21315
  ORDER BY o.importance DESC, o.created_at_epoch DESC
21286
21316
  LIMIT ?`
21287
21317
  ).all(config.indexMaxLines + planned.length);
21288
- const byPath = new Map(rows.map((r2) => [r2.rel_path.toLowerCase(), r2]));
21318
+ const byPath = new Map(rows.map((r3) => [r3.rel_path.toLowerCase(), r3]));
21289
21319
  for (const p19 of planned) {
21290
21320
  byPath.set(p19.relPath.toLowerCase(), {
21291
21321
  rel_path: p19.relPath,
@@ -21294,11 +21324,11 @@ function buildIndexLines(db, memoryDir, planned, config) {
21294
21324
  created_at_epoch: 0
21295
21325
  });
21296
21326
  }
21297
- const live = [...byPath.values()].filter((r2) => !isTombstoned(memoryDir, r2.rel_path));
21327
+ const live = [...byPath.values()].filter((r3) => !isTombstoned(memoryDir, r3.rel_path));
21298
21328
  const ranked = live.sort(
21299
21329
  (a2, b2) => b2.importance - a2.importance || b2.created_at_epoch - a2.created_at_epoch
21300
21330
  );
21301
- return ranked.slice(0, config.indexMaxLines).map((r2) => `- [${oneLine(r2.name)}](${r2.rel_path}) \u2014 learned by Massu`);
21331
+ return ranked.slice(0, config.indexMaxLines).map((r3) => `- [${oneLine(r3.name)}](${r3.rel_path}) \u2014 learned by Massu`);
21302
21332
  }
21303
21333
  function oneLine(s) {
21304
21334
  return s.replace(/[\r\n]+/g, " ").slice(0, 120);
@@ -21494,14 +21524,14 @@ function memoryRestore(memoryDir, opts = {}) {
21494
21524
  return { exitCode: 1, output: "No backups exist yet. Nothing to restore." };
21495
21525
  }
21496
21526
  try {
21497
- const r2 = restoreBackup(memoryDir, { ...opts, home });
21527
+ const r3 = restoreBackup(memoryDir, { ...opts, home });
21498
21528
  const lines = [
21499
- r2.dryRun ? `--dry-run: would restore ${r2.wouldRestore.length} file(s) from ${r2.stamp}. Nothing changed.` : `Restored ${r2.filesRestored} file(s) from ${r2.stamp}.`
21529
+ r3.dryRun ? `--dry-run: would restore ${r3.wouldRestore.length} file(s) from ${r3.stamp}. Nothing changed.` : `Restored ${r3.filesRestored} file(s) from ${r3.stamp}.`
21500
21530
  ];
21501
- for (const f2 of r2.wouldRestore) lines.push(` ${f2}`);
21502
- if (r2.presentButNotInBackup.length > 0) {
21531
+ for (const f2 of r3.wouldRestore) lines.push(` ${f2}`);
21532
+ if (r3.presentButNotInBackup.length > 0) {
21503
21533
  lines.push("", "These files exist now but are NOT in the backup. Massu left them alone:");
21504
- for (const f2 of r2.presentButNotInBackup) lines.push(` ${f2}`);
21534
+ for (const f2 of r3.presentButNotInBackup) lines.push(` ${f2}`);
21505
21535
  }
21506
21536
  return { exitCode: 0, output: lines.join("\n") };
21507
21537
  } catch (err) {
@@ -21535,8 +21565,8 @@ function loadRenderCandidates(db) {
21535
21565
  ORDER BY importance DESC, created_at_epoch DESC
21536
21566
  LIMIT ${CANDIDATE_WINDOW}`
21537
21567
  ).all(cfg.renderMinImportance, ...RENDERABLE_MEMORY_TYPES);
21538
- const reingest = rows.filter((r2) => r2.title.startsWith("[memory-file]"));
21539
- const kept = rows.filter((r2) => !r2.title.startsWith("[memory-file]"));
21568
+ const reingest = rows.filter((r3) => r3.title.startsWith("[memory-file]"));
21569
+ const kept = rows.filter((r3) => !r3.title.startsWith("[memory-file]"));
21540
21570
  const excluded = reingest.length ? [{ reason: EXCLUSION_MEMORY_FILE_REINGEST, count: reingest.length }] : [];
21541
21571
  const ledger = {
21542
21572
  population,
@@ -21553,13 +21583,13 @@ function loadRenderCandidates(db) {
21553
21583
  }
21554
21584
  return {
21555
21585
  ledger,
21556
- candidates: kept.map((r2) => ({
21557
- observationId: r2.id,
21558
- name: r2.title,
21559
- title: r2.title,
21560
- body: r2.detail ?? "",
21561
- importance: r2.importance,
21562
- origin: r2.origin
21586
+ candidates: kept.map((r3) => ({
21587
+ observationId: r3.id,
21588
+ name: r3.title,
21589
+ title: r3.title,
21590
+ body: r3.detail ?? "",
21591
+ importance: r3.importance,
21592
+ origin: r3.origin
21563
21593
  }))
21564
21594
  };
21565
21595
  }
@@ -21742,8 +21772,8 @@ async function runMemoryRenderCli(sub, args2) {
21742
21772
  }
21743
21773
  if (result.refusals.length > 0) {
21744
21774
  lines.push("", `${result.refusals.length} memory/memories REFUSED:`);
21745
- for (const r2 of result.refusals) {
21746
- lines.push(` ${r2.name}: ${r2.reason}${r2.detail ? ` (${r2.detail})` : ""}`);
21775
+ for (const r3 of result.refusals) {
21776
+ lines.push(` ${r3.name}: ${r3.reason}${r3.detail ? ` (${r3.detail})` : ""}`);
21747
21777
  }
21748
21778
  }
21749
21779
  lines.push("", `Bytes written: ${result.bytesWritten} (a dry run always writes 0).`);
@@ -21765,7 +21795,7 @@ async function runMemoryRenderCli(sub, args2) {
21765
21795
  "",
21766
21796
  "Sample (first 10):"
21767
21797
  ];
21768
- for (const r2 of sampleNoise2(db, 10)) lines.push(` [${r2.reason}] id=${r2.id} ${r2.type}: ${r2.title.slice(0, 60)}`);
21798
+ for (const r3 of sampleNoise2(db, 10)) lines.push(` [${r3.reason}] id=${r3.id} ${r3.type}: ${r3.title.slice(0, 60)}`);
21769
21799
  if (apply) {
21770
21800
  const result = pruneNoiseObservations2(db, { dryRun: false });
21771
21801
  lines.push("", `Expired ${result.expired} row(s) (CR-61: expired, NOT deleted; still asOf-queryable).`);
@@ -21859,12 +21889,12 @@ function readReposRegistry(home = homedir13()) {
21859
21889
  try {
21860
21890
  const parsed = JSON.parse(readFileSync29(p19, "utf-8"));
21861
21891
  if (!parsed || typeof parsed !== "object") return emptyRegistry();
21862
- const r2 = parsed;
21863
- if (!Array.isArray(r2.repos)) return emptyRegistry();
21864
- const repos = r2.repos.filter(
21892
+ const r3 = parsed;
21893
+ if (!Array.isArray(r3.repos)) return emptyRegistry();
21894
+ const repos = r3.repos.filter(
21865
21895
  (e2) => !!e2 && typeof e2 === "object" && typeof e2.repo_id === "string" && typeof e2.label === "string"
21866
21896
  );
21867
- return { version: typeof r2.version === "number" ? r2.version : REPOS_REGISTRY_VERSION, repos };
21897
+ return { version: typeof r3.version === "number" ? r3.version : REPOS_REGISTRY_VERSION, repos };
21868
21898
  } catch {
21869
21899
  return emptyRegistry();
21870
21900
  }
@@ -22038,7 +22068,7 @@ function acceptSharedMemory(db, recordHash, opts = {}) {
22038
22068
  const verdict = verifyLocalShareEnvelope(env, pinned, home);
22039
22069
  if (verdict.kind !== "valid") return refuse(db, recordHash, `reverify_${verdict.kind}`);
22040
22070
  if (!hasSignedLoadBearingKeys(env)) return refuse(db, recordHash, "unsigned_field");
22041
- const signed = parseRecords(env.records_json).find((r2) => r2.record_hash === recordHash);
22071
+ const signed = parseRecords(env.records_json).find((r3) => r3.record_hash === recordHash);
22042
22072
  if (!signed) return refuse(db, recordHash, "not_in_signed_records");
22043
22073
  if (hashSharedMemoryRecord(stripHash(signed)) !== recordHash) {
22044
22074
  return refuse(db, recordHash, "record_hash_mismatch");
@@ -22134,20 +22164,20 @@ function listPendingSharedMemories(db, opts = {}) {
22134
22164
  LIMIT 500`
22135
22165
  ).all();
22136
22166
  const out = [];
22137
- for (const r2 of rows) {
22167
+ for (const r3 of rows) {
22138
22168
  let rec = null;
22139
22169
  let valid = false;
22140
22170
  try {
22141
- rec = JSON.parse(r2.record_json);
22142
- const env = JSON.parse(r2.envelope_raw);
22143
- const pinned = getSharedPin(db, r2.origin_repo_id);
22171
+ rec = JSON.parse(r3.record_json);
22172
+ const env = JSON.parse(r3.envelope_raw);
22173
+ const pinned = getSharedPin(db, r3.origin_repo_id);
22144
22174
  valid = !!pinned && verifyLocalShareEnvelope(env, pinned, home).kind === "valid";
22145
22175
  } catch {
22146
22176
  }
22147
22177
  out.push({
22148
- record_hash: r2.record_hash,
22149
- origin_repo_label: deriveRepoLabel(r2.origin_repo_label),
22150
- received_at_epoch: r2.received_at_epoch,
22178
+ record_hash: r3.record_hash,
22179
+ origin_repo_label: deriveRepoLabel(r3.origin_repo_label),
22180
+ received_at_epoch: r3.received_at_epoch,
22151
22181
  type: rec?.type ?? "unknown",
22152
22182
  title: sanitizeCrossRepoTitle(rec?.title ?? ""),
22153
22183
  detail: sanitizeCrossRepoBody(rec?.detail ?? ""),
@@ -22168,14 +22198,14 @@ function parseRecords(json) {
22168
22198
  return [];
22169
22199
  }
22170
22200
  }
22171
- function stripHash(r2) {
22201
+ function stripHash(r3) {
22172
22202
  return {
22173
- type: r2.type,
22174
- title: r2.title,
22175
- detail: r2.detail,
22176
- importance: r2.importance,
22177
- created_at_epoch: r2.created_at_epoch,
22178
- superseded_by_hash: r2.superseded_by_hash
22203
+ type: r3.type,
22204
+ title: r3.title,
22205
+ detail: r3.detail,
22206
+ importance: r3.importance,
22207
+ created_at_epoch: r3.created_at_epoch,
22208
+ superseded_by_hash: r3.superseded_by_hash
22179
22209
  };
22180
22210
  }
22181
22211
  function clampImportance(n) {
@@ -22902,40 +22932,40 @@ function validateCandidatePayload(raw) {
22902
22932
  if (!raw || typeof raw !== "object") {
22903
22933
  throw new CandidatePayloadValidationError("payload is not an object");
22904
22934
  }
22905
- const r2 = raw;
22906
- if (typeof r2.prompt !== "string" || r2.prompt.length === 0) {
22935
+ const r3 = raw;
22936
+ if (typeof r3.prompt !== "string" || r3.prompt.length === 0) {
22907
22937
  throw new CandidatePayloadValidationError("prompt must be a non-empty string");
22908
22938
  }
22909
- if (typeof r2.prompt_hash !== "string" || !/^[a-f0-9]{16}$/.test(r2.prompt_hash)) {
22939
+ if (typeof r3.prompt_hash !== "string" || !/^[a-f0-9]{16}$/.test(r3.prompt_hash)) {
22910
22940
  throw new CandidatePayloadValidationError("prompt_hash must be 16 hex chars");
22911
22941
  }
22912
- if (typeof r2.score !== "number" || r2.score < -200 || r2.score > 200 || !Number.isFinite(r2.score)) {
22942
+ if (typeof r3.score !== "number" || r3.score < -200 || r3.score > 200 || !Number.isFinite(r3.score)) {
22913
22943
  throw new CandidatePayloadValidationError("score must be a finite number in [-200, 200]");
22914
22944
  }
22915
- if (!Array.isArray(r2.signals)) {
22945
+ if (!Array.isArray(r3.signals)) {
22916
22946
  throw new CandidatePayloadValidationError("signals must be an array");
22917
22947
  }
22918
- for (const s of r2.signals) {
22948
+ for (const s of r3.signals) {
22919
22949
  if (!s || typeof s !== "object") throw new CandidatePayloadValidationError("signal entry not an object");
22920
22950
  const sig = s;
22921
22951
  if (typeof sig.name !== "string") throw new CandidatePayloadValidationError("signal.name must be a string");
22922
22952
  if (typeof sig.baseWeight !== "number") throw new CandidatePayloadValidationError("signal.baseWeight must be a number");
22923
22953
  if (typeof sig.applied !== "number") throw new CandidatePayloadValidationError("signal.applied must be a number");
22924
22954
  }
22925
- if (!Array.isArray(r2.prior_turn_files)) {
22955
+ if (!Array.isArray(r3.prior_turn_files)) {
22926
22956
  throw new CandidatePayloadValidationError("prior_turn_files must be an array");
22927
22957
  }
22928
- if (typeof r2.timestamp !== "string") {
22958
+ if (typeof r3.timestamp !== "string") {
22929
22959
  throw new CandidatePayloadValidationError("timestamp must be a string");
22930
22960
  }
22931
- if (typeof r2.session_id !== "string") {
22961
+ if (typeof r3.session_id !== "string") {
22932
22962
  throw new CandidatePayloadValidationError("session_id must be a string");
22933
22963
  }
22934
- if (r2.provenance !== void 0) {
22935
- if (!r2.provenance || typeof r2.provenance !== "object") {
22964
+ if (r3.provenance !== void 0) {
22965
+ if (!r3.provenance || typeof r3.provenance !== "object") {
22936
22966
  throw new CandidatePayloadValidationError("provenance must be an object when present");
22937
22967
  }
22938
- const p19 = r2.provenance;
22968
+ const p19 = r3.provenance;
22939
22969
  const origin = p19.origin;
22940
22970
  const isTeamOrPack = origin === "team" || origin === "pack";
22941
22971
  const isRepo = typeof origin === "string" && isCrossRepoOrigin(origin);
@@ -22960,17 +22990,17 @@ function validateCandidatePayload(raw) {
22960
22990
  if (p19.apply_mac !== void 0 && typeof p19.apply_mac !== "string") {
22961
22991
  throw new CandidatePayloadValidationError("provenance.apply_mac, when present, must be a string");
22962
22992
  }
22963
- if (!isRuleDestination(r2.destination)) {
22993
+ if (!isRuleDestination(r3.destination)) {
22964
22994
  throw new CandidatePayloadValidationError("provenance-bearing candidate must declare a valid destination");
22965
22995
  }
22966
- if (r2.draft_text !== void 0 && typeof r2.draft_text !== "string") {
22996
+ if (r3.draft_text !== void 0 && typeof r3.draft_text !== "string") {
22967
22997
  throw new CandidatePayloadValidationError("draft_text must be a string when present");
22968
22998
  }
22969
22999
  }
22970
- } else if (r2.destination !== void 0 && !isRuleDestination(r2.destination)) {
23000
+ } else if (r3.destination !== void 0 && !isRuleDestination(r3.destination)) {
22971
23001
  throw new CandidatePayloadValidationError("destination, when present, must be a valid RuleDestination");
22972
23002
  }
22973
- return r2;
23003
+ return r3;
22974
23004
  }
22975
23005
  async function applyRuleCandidate(db, opts) {
22976
23006
  const ent = await assertAutoLearningEntitled();
@@ -23325,8 +23355,8 @@ function dismissRuleCandidate(db, opts) {
23325
23355
  `);
23326
23356
  for (const sig of candidate.signals) {
23327
23357
  if (sig.baseWeight <= 0) continue;
23328
- const r2 = upsert.run(sig.name);
23329
- blacklistUpdates += r2.changes;
23358
+ const r3 = upsert.run(sig.name);
23359
+ blacklistUpdates += r3.changes;
23330
23360
  }
23331
23361
  const entry = {
23332
23362
  eventType: "rule_dismissed",
@@ -23758,27 +23788,27 @@ function validateRulePackRule(rule) {
23758
23788
  if (typeof rule !== "object" || rule === null || Array.isArray(rule)) {
23759
23789
  return { valid: false, errors: ["rule must be a non-null object"], requiresHardened: false };
23760
23790
  }
23761
- const r2 = rule;
23762
- if (!isNonEmptyString(r2.title)) {
23791
+ const r3 = rule;
23792
+ if (!isNonEmptyString(r3.title)) {
23763
23793
  errors.push("missing required field: title");
23764
23794
  }
23765
- if (!isNonEmptyString(r2.description)) {
23795
+ if (!isNonEmptyString(r3.description)) {
23766
23796
  errors.push("missing required field: description");
23767
23797
  }
23768
- if (!isNonEmptyString(r2.severity)) {
23798
+ if (!isNonEmptyString(r3.severity)) {
23769
23799
  errors.push("missing required field: severity");
23770
23800
  }
23771
- const destinationKnown = isRuleDestination2(r2.destination);
23801
+ const destinationKnown = isRuleDestination2(r3.destination);
23772
23802
  if (!destinationKnown) {
23773
23803
  errors.push(
23774
- `invalid destination: ${JSON.stringify(r2.destination)} is not a known RuleDestination (one of ${RULE_DESTINATIONS.join(", ")})`
23804
+ `invalid destination: ${JSON.stringify(r3.destination)} is not a known RuleDestination (one of ${RULE_DESTINATIONS.join(", ")})`
23775
23805
  );
23776
23806
  }
23777
23807
  if (destinationKnown) {
23778
- const destination = r2.destination;
23779
- const hasPattern = isNonEmptyString(r2.pattern);
23780
- const hasCheck = isNonEmptyString(r2.check);
23781
- const hasTextBody = isNonEmptyString(r2.description);
23808
+ const destination = r3.destination;
23809
+ const hasPattern = isNonEmptyString(r3.pattern);
23810
+ const hasCheck = isNonEmptyString(r3.check);
23811
+ const hasTextBody = isNonEmptyString(r3.description);
23782
23812
  switch (destination) {
23783
23813
  case "pattern-scanner":
23784
23814
  if (!hasPattern && !hasCheck) {
@@ -23804,7 +23834,7 @@ function validateRulePackRule(rule) {
23804
23834
  break;
23805
23835
  }
23806
23836
  }
23807
- const requiresHardened = destinationKnown && isExecutableDestination(r2.destination);
23837
+ const requiresHardened = destinationKnown && isExecutableDestination(r3.destination);
23808
23838
  return { valid: errors.length === 0, errors, requiresHardened };
23809
23839
  }
23810
23840
  var RULE_DESTINATIONS;
@@ -23916,8 +23946,8 @@ function countUntrusted(envelope) {
23916
23946
  }
23917
23947
  function isValidInstalledPack(p19) {
23918
23948
  if (!p19 || typeof p19 !== "object") return false;
23919
- const r2 = p19;
23920
- return typeof r2.slug === "string" && r2.slug.length > 0 && Array.isArray(r2.rules);
23949
+ const r3 = p19;
23950
+ return typeof r3.slug === "string" && r3.slug.length > 0 && Array.isArray(r3.rules);
23921
23951
  }
23922
23952
  function packRulePromptHash(slug, rule) {
23923
23953
  const { createHash: createHash17 } = __require("node:crypto");
@@ -24403,14 +24433,14 @@ function collectObservations(memDb, queryText, pool, nowMs, loadVec, modelId, di
24403
24433
  WHERE observations_fts MATCH ?${bm25Temporal ? ` AND ${bm25Temporal}` : ""}
24404
24434
  ORDER BY rank LIMIT ?`
24405
24435
  ).all(sanitizeFts5QueryOr(queryText), pool);
24406
- rows.forEach((r2, i) => {
24407
- map.set(r2.id, {
24408
- id: r2.id,
24436
+ rows.forEach((r3, i) => {
24437
+ map.set(r3.id, {
24438
+ id: r3.id,
24409
24439
  source: "observation",
24410
- title: r2.title,
24411
- snippet: snippetOf(r2.detail ?? r2.title),
24412
- importance: r2.importance,
24413
- ageDays: ageDaysFrom(r2.created_at_epoch * 1e3, nowMs),
24440
+ title: r3.title,
24441
+ snippet: snippetOf(r3.detail ?? r3.title),
24442
+ importance: r3.importance,
24443
+ ageDays: ageDaysFrom(r3.created_at_epoch * 1e3, nowMs),
24414
24444
  bm25Order: i,
24415
24445
  vecs: []
24416
24446
  });
@@ -24421,15 +24451,15 @@ function collectObservations(memDb, queryText, pool, nowMs, loadVec, modelId, di
24421
24451
  `SELECT id, title, detail, importance, created_at_epoch
24422
24452
  FROM observations${plainTemporal ? ` WHERE ${plainTemporal}` : ""} ORDER BY created_at_epoch DESC LIMIT ?`
24423
24453
  ).all(pool);
24424
- for (const r2 of recent) {
24425
- if (!map.has(r2.id)) {
24426
- map.set(r2.id, {
24427
- id: r2.id,
24454
+ for (const r3 of recent) {
24455
+ if (!map.has(r3.id)) {
24456
+ map.set(r3.id, {
24457
+ id: r3.id,
24428
24458
  source: "observation",
24429
- title: r2.title,
24430
- snippet: snippetOf(r2.detail ?? r2.title),
24431
- importance: r2.importance,
24432
- ageDays: ageDaysFrom(r2.created_at_epoch * 1e3, nowMs),
24459
+ title: r3.title,
24460
+ snippet: snippetOf(r3.detail ?? r3.title),
24461
+ importance: r3.importance,
24462
+ ageDays: ageDaysFrom(r3.created_at_epoch * 1e3, nowMs),
24433
24463
  bm25Order: null,
24434
24464
  vecs: []
24435
24465
  });
@@ -24469,14 +24499,14 @@ function collectLikeSource(db, source, cfg, queryText, pool, nowMs) {
24469
24499
  FROM ${cfg.table} WHERE (${likeClause})${cfg.temporalClause ? ` AND ${cfg.temporalClause}` : ""}
24470
24500
  ORDER BY ${cfg.createdCol} DESC LIMIT ?`
24471
24501
  ).all(...params, pool);
24472
- rows.forEach((r2, i) => {
24473
- map.set(r2.id, {
24474
- id: r2.id,
24502
+ rows.forEach((r3, i) => {
24503
+ map.set(r3.id, {
24504
+ id: r3.id,
24475
24505
  source,
24476
- title: r2.title,
24477
- snippet: snippetOf(r2.snippet ?? r2.title),
24506
+ title: r3.title,
24507
+ snippet: snippetOf(r3.snippet ?? r3.title),
24478
24508
  importance: 3,
24479
- ageDays: ageExpr(r2.created),
24509
+ ageDays: ageExpr(r3.created),
24480
24510
  bm25Order: i,
24481
24511
  vecs: []
24482
24512
  });
@@ -24489,15 +24519,15 @@ function collectLikeSource(db, source, cfg, queryText, pool, nowMs) {
24489
24519
  ${cfg.snippetCol} AS snippet, ${cfg.createdCol} AS created
24490
24520
  FROM ${cfg.table}${cfg.temporalClause ? ` WHERE ${cfg.temporalClause}` : ""} ORDER BY ${cfg.createdCol} DESC LIMIT ?`
24491
24521
  ).all(pool);
24492
- for (const r2 of recent) {
24493
- if (!map.has(r2.id)) {
24494
- map.set(r2.id, {
24495
- id: r2.id,
24522
+ for (const r3 of recent) {
24523
+ if (!map.has(r3.id)) {
24524
+ map.set(r3.id, {
24525
+ id: r3.id,
24496
24526
  source,
24497
- title: r2.title,
24498
- snippet: snippetOf(r2.snippet ?? r2.title),
24527
+ title: r3.title,
24528
+ snippet: snippetOf(r3.snippet ?? r3.title),
24499
24529
  importance: 3,
24500
- ageDays: ageExpr(r2.created),
24530
+ ageDays: ageExpr(r3.created),
24501
24531
  bm25Order: null,
24502
24532
  vecs: []
24503
24533
  });
@@ -24517,14 +24547,14 @@ function collectKnowledgeChunks(knowledgeDb, queryText, pool, nowMs, loadVec, mo
24517
24547
  WHERE knowledge_fts MATCH ?
24518
24548
  ORDER BY rank LIMIT ?`
24519
24549
  ).all(sanitizeFts5QueryOr(queryText), pool);
24520
- rows.forEach((r2, i) => {
24521
- map.set(r2.id, {
24522
- id: r2.id,
24550
+ rows.forEach((r3, i) => {
24551
+ map.set(r3.id, {
24552
+ id: r3.id,
24523
24553
  source: "knowledge_chunk",
24524
- title: r2.heading || snippetOf(r2.content, 60),
24525
- snippet: snippetOf(r2.content),
24554
+ title: r3.heading || snippetOf(r3.content, 60),
24555
+ snippet: snippetOf(r3.content),
24526
24556
  importance: 3,
24527
- ageDays: ageDaysFrom((r2.epoch ?? 0) * 1e3, nowMs),
24557
+ ageDays: ageDaysFrom((r3.epoch ?? 0) * 1e3, nowMs),
24528
24558
  bm25Order: i,
24529
24559
  vecs: []
24530
24560
  });
@@ -24556,9 +24586,9 @@ function loadEmbeddings(db, table, idCol, ids, modelId, dim, assign) {
24556
24586
  WHERE ${idCol} IN (${placeholders}) AND model_id = ? AND dim = ?
24557
24587
  LIMIT ?`
24558
24588
  ).all(...ids, modelId, dim, ids.length);
24559
- for (const r2 of rows) {
24560
- const v3 = blobToFloat32(r2.vec);
24561
- if (v3 && v3.length === dim) assign(r2.id, v3);
24589
+ for (const r3 of rows) {
24590
+ const v3 = blobToFloat32(r3.vec);
24591
+ if (v3 && v3.length === dim) assign(r3.id, v3);
24562
24592
  }
24563
24593
  } catch {
24564
24594
  }
@@ -24668,17 +24698,17 @@ function hybridSearch(memDb, knowledgeDb, opts) {
24668
24698
  ageDays: c2.ageDays
24669
24699
  };
24670
24700
  });
24671
- const top = ranked.filter((r2) => r2.score >= minScore).sort((a2, b2) => b2.score - a2.score || a2.ageDays - b2.ageDays).slice(0, limit);
24701
+ const top = ranked.filter((r3) => r3.score >= minScore).sort((a2, b2) => b2.score - a2.score || a2.ageDays - b2.ageDays).slice(0, limit);
24672
24702
  if (includeSuperseded && opts.asOf == null) {
24673
- for (const r2 of top) {
24674
- const table = r2.source === "observation" ? "observations" : r2.source === "architecture_decision" ? "architecture_decisions" : null;
24703
+ for (const r3 of top) {
24704
+ const table = r3.source === "observation" ? "observations" : r3.source === "architecture_decision" ? "architecture_decisions" : null;
24675
24705
  if (!table) continue;
24676
24706
  try {
24677
- const row = memDb.prepare(`SELECT valid_to, superseded_by, expired_at_epoch FROM ${table} WHERE id = ?`).get(r2.id);
24707
+ const row = memDb.prepare(`SELECT valid_to, superseded_by, expired_at_epoch FROM ${table} WHERE id = ?`).get(r3.id);
24678
24708
  if (row && row.expired_at_epoch != null) {
24679
24709
  const when = row.valid_to ? row.valid_to.slice(0, 10) : "an earlier date";
24680
24710
  const by = row.superseded_by != null ? ` by #${row.superseded_by}` : "";
24681
- r2.snippet = `(superseded on ${when}${by}) ${r2.snippet}`;
24711
+ r3.snippet = `(superseded on ${when}${by}) ${r3.snippet}`;
24682
24712
  }
24683
24713
  } catch {
24684
24714
  }
@@ -24808,11 +24838,11 @@ async function supersedeIfContradicted(memDb, knowledgeDb, args2) {
24808
24838
  candidatePool: 20
24809
24839
  });
24810
24840
  const scored = [];
24811
- for (const r2 of results) {
24812
- if (r2.id === args2.newId) continue;
24841
+ for (const r3 of results) {
24842
+ if (r3.id === args2.newId) continue;
24813
24843
  if (Date.now() - start > cfg.budgetMs) break;
24814
- const vec = await candidateVec(memDb, args2.source, r2.id);
24815
- if (vec) scored.push({ id: r2.id, source: args2.source, cosine: cosineSim(queryVec, vec) });
24844
+ const vec = await candidateVec(memDb, args2.source, r3.id);
24845
+ if (vec) scored.push({ id: r3.id, source: args2.source, cosine: cosineSim(queryVec, vec) });
24816
24846
  }
24817
24847
  let verdict = null;
24818
24848
  if (cfg.judgeEndpoint && Date.now() - start < cfg.budgetMs) {
@@ -24871,17 +24901,11 @@ function emptyResult() {
24871
24901
  };
24872
24902
  }
24873
24903
  function acquireLease(db, now, ttlSec) {
24874
- const raw = getMemoryMeta(db, LEASE_KEY);
24875
- if (raw) {
24876
- const expiry = Number(raw.split(":")[1]);
24877
- if (Number.isFinite(expiry) && expiry > now) return false;
24878
- }
24879
- setMemoryMeta(db, LEASE_KEY, `${process.pid}:${now + ttlSec}`);
24880
- return true;
24904
+ return tryAcquireMetaLease(db, LEASE_KEY, ttlSec, now);
24881
24905
  }
24882
24906
  function releaseLease(db) {
24883
24907
  try {
24884
- setMemoryMeta(db, LEASE_KEY, "");
24908
+ releaseMetaLease(db, LEASE_KEY);
24885
24909
  } catch {
24886
24910
  }
24887
24911
  }
@@ -24900,19 +24924,19 @@ async function stageDedupe(db, cfg, deadline, now) {
24900
24924
  return 0;
24901
24925
  }
24902
24926
  let deduped = 0;
24903
- for (const r2 of rows) {
24927
+ for (const r3 of rows) {
24904
24928
  if (Date.now() > deadline) break;
24905
- const live = db.prepare(`SELECT expired_at FROM observations WHERE id = ?`).get(r2.id);
24929
+ const live = db.prepare(`SELECT expired_at FROM observations WHERE id = ?`).get(r3.id);
24906
24930
  if (!live || live.expired_at != null) continue;
24907
24931
  const res = await supersedeIfContradicted(db, null, {
24908
- text: `${r2.title}
24909
- ${r2.detail ?? ""}`.trim(),
24932
+ text: `${r3.title}
24933
+ ${r3.detail ?? ""}`.trim(),
24910
24934
  source: "observation",
24911
- newId: r2.id,
24935
+ newId: r3.id,
24912
24936
  nowEpochSec: now
24913
24937
  });
24914
24938
  if (res.superseded != null) deduped++;
24915
- setMemoryMeta(db, DEDUPE_CURSOR, String(r2.id));
24939
+ setMemoryMeta(db, DEDUPE_CURSOR, String(r3.id));
24916
24940
  }
24917
24941
  return deduped;
24918
24942
  }
@@ -24990,11 +25014,11 @@ async function stagePromote(db, cfg, projectRoot, deadline, now, dryRun) {
24990
25014
  ).all(MAX_ROWS_PER_STAGE);
24991
25015
  if (rows.length === 0) return { promoted: 0, refusedByTier: 0, embedderUnavailable: false };
24992
25016
  const vecs = /* @__PURE__ */ new Map();
24993
- for (const r2 of rows) {
25017
+ for (const r3 of rows) {
24994
25018
  if (Date.now() > deadline) break;
24995
- const v3 = await embed(`${r2.title}
24996
- ${r2.detail ?? ""}`.trim());
24997
- if (v3) vecs.set(r2.id, v3);
25019
+ const v3 = await embed(`${r3.title}
25020
+ ${r3.detail ?? ""}`.trim());
25021
+ if (v3) vecs.set(r3.id, v3);
24998
25022
  }
24999
25023
  if (vecs.size === 0) {
25000
25024
  return { promoted: 0, refusedByTier: 0, embedderUnavailable: true };
@@ -25002,13 +25026,13 @@ ${r2.detail ?? ""}`.trim());
25002
25026
  const CLUSTER_THRESHOLD = 0.8;
25003
25027
  const used = /* @__PURE__ */ new Set();
25004
25028
  const clusters = [];
25005
- for (const r2 of rows) {
25006
- if (used.has(r2.id) || !vecs.has(r2.id)) continue;
25007
- const cluster = [r2];
25008
- used.add(r2.id);
25029
+ for (const r3 of rows) {
25030
+ if (used.has(r3.id) || !vecs.has(r3.id)) continue;
25031
+ const cluster = [r3];
25032
+ used.add(r3.id);
25009
25033
  for (const other of rows) {
25010
25034
  if (used.has(other.id) || !vecs.has(other.id)) continue;
25011
- if (cosineSim(vecs.get(r2.id), vecs.get(other.id)) >= CLUSTER_THRESHOLD) {
25035
+ if (cosineSim(vecs.get(r3.id), vecs.get(other.id)) >= CLUSTER_THRESHOLD) {
25012
25036
  cluster.push(other);
25013
25037
  used.add(other.id);
25014
25038
  }
@@ -25107,14 +25131,14 @@ function stageReweight(db, cfg, now) {
25107
25131
  ON CONFLICT(source, record_id) DO UPDATE SET last_reweight_epoch = excluded.last_reweight_epoch`
25108
25132
  );
25109
25133
  const tx = db.transaction(() => {
25110
- for (const r2 of promote) {
25111
- bump.run(r2.id);
25112
- mark.run(r2.id, now);
25134
+ for (const r3 of promote) {
25135
+ bump.run(r3.id);
25136
+ mark.run(r3.id, now);
25113
25137
  changed++;
25114
25138
  }
25115
- for (const r2 of demote) {
25116
- drop.run(r2.id);
25117
- mark.run(r2.id, now);
25139
+ for (const r3 of demote) {
25140
+ drop.run(r3.id);
25141
+ mark.run(r3.id, now);
25118
25142
  changed++;
25119
25143
  }
25120
25144
  });
@@ -28060,8 +28084,8 @@ async function runAdaptersList(_args) {
28060
28084
  `);
28061
28085
  }
28062
28086
  } else {
28063
- for (const r2 of manifestResult.reasons) {
28064
- process.stderr.write(`[manifest] ${r2}
28087
+ for (const r3 of manifestResult.reasons) {
28088
+ process.stderr.write(`[manifest] ${r3}
28065
28089
  `);
28066
28090
  }
28067
28091
  }
@@ -28980,9 +29004,9 @@ var init_security_utils = __esm({
28980
29004
 
28981
29005
  // src/rules.ts
28982
29006
  function getPatternRules() {
28983
- return getConfig().rules.map((r2) => ({
28984
- match: r2.pattern,
28985
- rules: r2.rules
29007
+ return getConfig().rules.map((r3) => ({
29008
+ match: r3.pattern,
29009
+ rules: r3.rules
28986
29010
  }));
28987
29011
  }
28988
29012
  function matchRules(filePath) {
@@ -31244,8 +31268,8 @@ function handleSearch(args2, db) {
31244
31268
  const lines = [`## Search Results for "${query}" (${results.length} matches)`, ""];
31245
31269
  lines.push("| ID | Type | Title | Date | Importance |");
31246
31270
  lines.push("|----|------|-------|------|------------|");
31247
- for (const r2 of results) {
31248
- lines.push(`| ${r2.id} | ${r2.type} | ${r2.title.slice(0, 80)} | ${r2.created_at.split("T")[0]} | ${r2.importance} |`);
31271
+ for (const r3 of results) {
31272
+ lines.push(`| ${r3.id} | ${r3.type} | ${r3.title.slice(0, 80)} | ${r3.created_at.split("T")[0]} | ${r3.importance} |`);
31249
31273
  }
31250
31274
  lines.push("");
31251
31275
  lines.push(`Use ${p3("memory_detail")} with IDs for full details.`);
@@ -31678,9 +31702,9 @@ function handleDocsAudit(args2) {
31678
31702
  }
31679
31703
  }
31680
31704
  }
31681
- const staleCount = results.filter((r2) => r2.status === "STALE").length;
31682
- const newCount = results.filter((r2) => r2.status === "NEW").length;
31683
- const okCount = results.filter((r2) => r2.status === "OK").length;
31705
+ const staleCount = results.filter((r3) => r3.status === "STALE").length;
31706
+ const newCount = results.filter((r3) => r3.status === "NEW").length;
31707
+ const okCount = results.filter((r3) => r3.status === "OK").length;
31684
31708
  const report = {
31685
31709
  affectedPages: results,
31686
31710
  summary: `${results.length} pages checked: ${staleCount} STALE, ${newCount} NEW, ${okCount} OK. ${staleCount + newCount > 0 ? `${staleCount + newCount} pages need updates.` : "All docs are current."}`
@@ -31932,8 +31956,8 @@ function handlePromptAnalysis(args2, db) {
31932
31956
  const lines = [`## Prompt Search: "${query}" (${results.length} results)`, ""];
31933
31957
  lines.push("| Session | Turn | Prompt (truncated) | Tools | Response Tokens | Date |");
31934
31958
  lines.push("|---------|------|--------------------|-------|-----------------|------|");
31935
- for (const r2 of results) {
31936
- lines.push(`| ${r2.session_id.slice(0, 8)}... | ${r2.turn_number} | ${r2.user_prompt.slice(0, 60).replace(/\|/g, "\\|")} | ${r2.tool_call_count} | ${r2.response_tokens ?? "-"} | ${r2.created_at.split("T")[0]} |`);
31959
+ for (const r3 of results) {
31960
+ lines.push(`| ${r3.session_id.slice(0, 8)}... | ${r3.turn_number} | ${r3.user_prompt.slice(0, 60).replace(/\|/g, "\\|")} | ${r3.tool_call_count} | ${r3.response_tokens ?? "-"} | ${r3.created_at.split("T")[0]} |`);
31937
31961
  }
31938
31962
  return text4(lines.join("\n"));
31939
31963
  }
@@ -33373,12 +33397,49 @@ var init_analytics = __esm({
33373
33397
  }
33374
33398
  });
33375
33399
 
33400
+ // src/model-pricing.ts
33401
+ var PRICE_TABLE_SOURCE, PRICE_TABLE_AS_OF, r2, US, BUILT_IN_PRICES;
33402
+ var init_model_pricing = __esm({
33403
+ "src/model-pricing.ts"() {
33404
+ "use strict";
33405
+ PRICE_TABLE_SOURCE = "https://platform.claude.com/docs/en/about-claude/pricing";
33406
+ PRICE_TABLE_AS_OF = "2026-11-09";
33407
+ r2 = (input, cacheWrite5m, cacheWrite1h, cacheRead, output) => ({ input, cacheWrite5m, cacheWrite1h, cacheRead, output });
33408
+ US = 1.1;
33409
+ BUILT_IN_PRICES = {
33410
+ "claude-fable-5-1": { ...r2(10, 12.5, 20, 0.25, 50), usGeoMultiplier: US },
33411
+ "claude-mythos-5-1": { ...r2(10, 12.5, 20, 0.25, 50), usGeoMultiplier: US },
33412
+ "claude-fable-5": { ...r2(10, 12.5, 20, 1, 50), usGeoMultiplier: US },
33413
+ "claude-mythos-5": { ...r2(10, 12.5, 20, 1, 50), usGeoMultiplier: US },
33414
+ "claude-opus-5-5": { ...r2(4, 5, 8, 0.2, 20), fast: { input: 8, output: 40 }, usGeoMultiplier: US },
33415
+ "claude-opus-5": { ...r2(5, 6.25, 10, 0.5, 25), fast: { input: 10, output: 50 }, usGeoMultiplier: US },
33416
+ "claude-opus-4-8": { ...r2(5, 6.25, 10, 0.5, 25), fast: { input: 10, output: 50 }, usGeoMultiplier: US },
33417
+ "claude-opus-4-7": { ...r2(5, 6.25, 10, 0.5, 25), usGeoMultiplier: US },
33418
+ "claude-opus-4-6": { ...r2(5, 6.25, 10, 0.5, 25), usGeoMultiplier: US },
33419
+ "claude-opus-4-5": r2(5, 6.25, 10, 0.5, 25),
33420
+ "claude-opus-4-1": r2(15, 18.75, 30, 1.5, 75),
33421
+ "claude-opus-4": r2(15, 18.75, 30, 1.5, 75),
33422
+ "claude-sonnet-5-5": { ...r2(2, 2.5, 4, 0.1, 10), usGeoMultiplier: US },
33423
+ "claude-sonnet-5": { ...r2(2, 2.5, 4, 0.2, 10), usGeoMultiplier: US },
33424
+ "claude-sonnet-4-6": { ...r2(3, 3.75, 6, 0.3, 15), usGeoMultiplier: US },
33425
+ "claude-sonnet-4-5": r2(3, 3.75, 6, 0.3, 15),
33426
+ "claude-sonnet-4": r2(3, 3.75, 6, 0.3, 15),
33427
+ "claude-haiku-5-5": {
33428
+ ...r2(0.1, 0.125, 0.2, 0.01, 0.5),
33429
+ longPrompt: { overTokens: 1e5, rates: r2(0.5, 0.625, 1, 0.05, 2.5) },
33430
+ usGeoMultiplier: US
33431
+ },
33432
+ "claude-haiku-4-5": r2(1, 1.25, 2, 0.1, 5)
33433
+ };
33434
+ }
33435
+ });
33436
+
33376
33437
  // src/cost-tracker.ts
33377
33438
  function p8(baseName) {
33378
33439
  return `${getConfig().toolPrefix}_${baseName}`;
33379
33440
  }
33380
- function getModelPricing() {
33381
- return getConfig().analytics?.cost?.models ?? DEFAULT_MODEL_PRICING;
33441
+ function getCurrency() {
33442
+ return getConfig().analytics?.cost?.currency ?? "USD";
33382
33443
  }
33383
33444
  function getCostToolDefinitions() {
33384
33445
  return [
@@ -33452,25 +33513,31 @@ function handleCostSession(args2, db) {
33452
33513
  if (!cost) {
33453
33514
  return text7(`No cost data found for session ${sessionId}. Cost data is recorded automatically when sessions end via the session-end hook. If the session is still active, data will appear after it completes. Try: ${p8("cost_trend")} { days: 30 } to see aggregate cost data instead.`);
33454
33515
  }
33455
- const modelPricing = getModelPricing();
33456
- const mp = modelPricing[cost.model] ?? modelPricing["claude-sonnet-4-5"] ?? { input_per_million: 3, output_per_million: 15 };
33457
- const inputCost = cost.input_tokens / 1e6 * mp.input_per_million;
33458
- const outputCost = cost.output_tokens / 1e6 * mp.output_per_million;
33459
- const cacheReadCost = cost.cache_read_tokens / 1e6 * (mp.cache_read_per_million ?? 0);
33460
- const cacheWriteCost = cost.cache_write_tokens / 1e6 * (mp.cache_write_per_million ?? 0);
33516
+ const status = cost.cost_status ?? "unknown";
33517
+ const dollars = cost.estimated_cost_usd;
33518
+ const headline = status === "unknown" ? "unknown" : `$${dollars.toFixed(4)}${status === "partial" ? " (partial, see below)" : ""}`;
33461
33519
  const lines = [
33462
- `## Session Cost: $${cost.estimated_cost_usd.toFixed(4)}`,
33463
- `Model: ${cost.model}`,
33520
+ `## Session Cost: ${headline}`,
33521
+ `Model: ${cost.model ?? "unknown"}`,
33464
33522
  "",
33465
33523
  "### Token Usage",
33466
- `| Type | Tokens | Est. Cost |`,
33467
- `|------|--------|-----------|`,
33468
- `| Input | ${cost.input_tokens.toLocaleString()} | $${inputCost.toFixed(4)} |`,
33469
- `| Output | ${cost.output_tokens.toLocaleString()} | $${outputCost.toFixed(4)} |`,
33470
- `| Cache Read | ${cost.cache_read_tokens.toLocaleString()} | $${cacheReadCost.toFixed(4)} |`,
33471
- `| Cache Write | ${cost.cache_write_tokens.toLocaleString()} | $${cacheWriteCost.toFixed(4)} |`,
33472
- `| **Total** | ${cost.total_tokens.toLocaleString()} | **$${cost.estimated_cost_usd.toFixed(4)}** |`
33524
+ `| Type | Tokens |`,
33525
+ `|------|--------|`,
33526
+ `| Input | ${cost.input_tokens.toLocaleString()} |`,
33527
+ `| Output | ${cost.output_tokens.toLocaleString()} |`,
33528
+ `| Cache Read | ${cost.cache_read_tokens.toLocaleString()} |`,
33529
+ `| Cache Write | ${cost.cache_write_tokens.toLocaleString()} |`,
33530
+ `| **Total** | ${cost.total_tokens.toLocaleString()} |`,
33531
+ "",
33532
+ `Responses priced: ${cost.priced_responses ?? 0}; without a price: ${cost.unpriced_responses ?? 0}.`
33473
33533
  ];
33534
+ if (status === "unknown" && !cost.unpriced_responses) {
33535
+ lines.push("No transcript was available to price this session.");
33536
+ }
33537
+ if (cost.unpriced_models) {
33538
+ lines.push(`No price known for: ${cost.unpriced_models}. Add it under analytics.cost.models in massu.config.yaml.`);
33539
+ }
33540
+ lines.push(`Prices: ${PRICE_TABLE_SOURCE} as of ${PRICE_TABLE_AS_OF} (${getCurrency()}).`);
33474
33541
  return text7(lines.join("\n"));
33475
33542
  }
33476
33543
  function handleCostTrend(args2, db) {
@@ -33481,17 +33548,21 @@ function handleCostTrend(args2, db) {
33481
33548
  }
33482
33549
  const sql = groupBy === "week" ? `SELECT strftime('%Y-W%W', created_at) as period,
33483
33550
  COUNT(*) as sessions,
33484
- SUM(estimated_cost_usd) as total_cost,
33551
+ SUM(CASE WHEN cost_status = 'unknown' THEN 0 ELSE estimated_cost_usd END) as total_cost,
33485
33552
  SUM(total_tokens) as total_tokens,
33486
- AVG(estimated_cost_usd) as avg_cost
33553
+ SUM(CASE WHEN cost_status = 'priced' THEN 1 ELSE 0 END) as priced_sessions,
33554
+ SUM(CASE WHEN cost_status = 'partial' THEN 1 ELSE 0 END) as partial_sessions,
33555
+ SUM(CASE WHEN cost_status = 'unknown' THEN 1 ELSE 0 END) as unknown_sessions
33487
33556
  FROM session_costs
33488
33557
  WHERE created_at >= datetime('now', ?)
33489
33558
  GROUP BY period
33490
33559
  ORDER BY period ASC` : `SELECT strftime('%Y-%m-%d', created_at) as period,
33491
33560
  COUNT(*) as sessions,
33492
- SUM(estimated_cost_usd) as total_cost,
33561
+ SUM(CASE WHEN cost_status = 'unknown' THEN 0 ELSE estimated_cost_usd END) as total_cost,
33493
33562
  SUM(total_tokens) as total_tokens,
33494
- AVG(estimated_cost_usd) as avg_cost
33563
+ SUM(CASE WHEN cost_status = 'priced' THEN 1 ELSE 0 END) as priced_sessions,
33564
+ SUM(CASE WHEN cost_status = 'partial' THEN 1 ELSE 0 END) as partial_sessions,
33565
+ SUM(CASE WHEN cost_status = 'unknown' THEN 1 ELSE 0 END) as unknown_sessions
33495
33566
  FROM session_costs
33496
33567
  WHERE created_at >= datetime('now', ?)
33497
33568
  GROUP BY period
@@ -33500,22 +33571,28 @@ function handleCostTrend(args2, db) {
33500
33571
  if (rows.length === 0) {
33501
33572
  return text7(`No cost data found in the last ${days} days. Cost tracking records token usage automatically at session end via hooks. Ensure session-end hooks are configured in your settings. Try: ${p8("cost_session")} { session_id: "..." } to check a specific session.`);
33502
33573
  }
33503
- const totalCost = rows.reduce((sum, r2) => sum + r2.total_cost, 0);
33504
- const totalSessions = rows.reduce((sum, r2) => sum + r2.sessions, 0);
33574
+ const sum = (k3) => rows.reduce((acc, r3) => acc + (r3[k3] ?? 0), 0);
33575
+ const totalCost = sum("total_cost");
33576
+ const totalSessions = sum("sessions");
33577
+ const known = sum("priced_sessions") + sum("partial_sessions");
33578
+ const unknown = sum("unknown_sessions");
33579
+ const partial = sum("partial_sessions");
33505
33580
  const lines = [
33506
33581
  `## Cost Trend (${days} days)`,
33507
- `Total: $${totalCost.toFixed(2)} across ${totalSessions} sessions`,
33508
- `Average per session: $${(totalCost / totalSessions).toFixed(4)}`,
33582
+ `Total: $${totalCost.toFixed(2)} across ${known} priced session(s)` + (unknown ? `; ${unknown} session(s) of ${totalSessions} have unknown cost and are NOT in this total` : ""),
33583
+ known ? `Average per priced session: $${(totalCost / known).toFixed(4)}` : "No session has a known cost in this window."
33584
+ ];
33585
+ if (partial) lines.push(`${partial} session(s) are partial: a model they used has no price, so they are under-counted.`);
33586
+ lines.push(
33509
33587
  "",
33510
33588
  `### By ${groupBy === "week" ? "Week" : "Day"}`,
33511
- `| Period | Sessions | Cost | Avg/Session |`,
33512
- `|--------|----------|------|-------------|`
33513
- ];
33589
+ `| Period | Sessions | Cost | Unknown |`,
33590
+ `|--------|----------|------|---------|`
33591
+ );
33514
33592
  for (const row of rows) {
33515
- lines.push(
33516
- `| ${row.period} | ${row.sessions} | $${row.total_cost.toFixed(2)} | $${row.avg_cost.toFixed(4)} |`
33517
- );
33593
+ lines.push(`| ${row.period} | ${row.sessions} | $${row.total_cost.toFixed(2)} | ${row.unknown_sessions} |`);
33518
33594
  }
33595
+ lines.push("", `Prices: ${PRICE_TABLE_SOURCE} as of ${PRICE_TABLE_AS_OF} (${getCurrency()}).`);
33519
33596
  return text7(lines.join("\n"));
33520
33597
  }
33521
33598
  function handleCostFeature(args2, db) {
@@ -33530,7 +33607,7 @@ function handleCostFeature(args2, db) {
33530
33607
  if (rows.length === 0) {
33531
33608
  return text7(`No feature cost data found in the last ${days} days. Feature costs are attributed automatically when sessions work on registered features. Ensure features are registered, then costs are tracked per-session. Try: ${p8("cost_trend")} { days: 30 } for session-level cost trends instead.`);
33532
33609
  }
33533
- const totalCost = rows.reduce((sum, r2) => sum + r2.total_cost, 0);
33610
+ const totalCost = rows.reduce((sum, r3) => sum + r3.total_cost, 0);
33534
33611
  const lines = [
33535
33612
  `## Feature Cost Attribution (${days} days)`,
33536
33613
  `Total: $${totalCost.toFixed(2)} across ${rows.length} features`,
@@ -33549,18 +33626,12 @@ function handleCostFeature(args2, db) {
33549
33626
  function text7(content) {
33550
33627
  return { content: [{ type: "text", text: content }] };
33551
33628
  }
33552
- var DEFAULT_MODEL_PRICING, COST_BASE_NAMES;
33629
+ var COST_BASE_NAMES;
33553
33630
  var init_cost_tracker = __esm({
33554
33631
  "src/cost-tracker.ts"() {
33555
33632
  "use strict";
33556
33633
  init_config();
33557
- DEFAULT_MODEL_PRICING = {
33558
- "claude-opus-4-6": { input_per_million: 15, output_per_million: 75, cache_read_per_million: 1.5, cache_write_per_million: 18.75 },
33559
- "claude-sonnet-4-6": { input_per_million: 3, output_per_million: 15, cache_read_per_million: 0.3, cache_write_per_million: 3.75 },
33560
- "claude-sonnet-4-5": { input_per_million: 3, output_per_million: 15, cache_read_per_million: 0.3, cache_write_per_million: 3.75 },
33561
- "claude-haiku-4-5-20251001": { input_per_million: 0.8, output_per_million: 4, cache_read_per_million: 0.08, cache_write_per_million: 1 },
33562
- "default": { input_per_million: 3, output_per_million: 15, cache_read_per_million: 0.3, cache_write_per_million: 3.75 }
33563
- };
33634
+ init_model_pricing();
33564
33635
  COST_BASE_NAMES = /* @__PURE__ */ new Set(["cost_session", "cost_trend", "cost_feature"]);
33565
33636
  }
33566
33637
  });
@@ -33973,8 +34044,8 @@ function handleValidationReport(args2, db) {
33973
34044
  if (results.length === 0) {
33974
34045
  return text9(`No validation results found in the last ${days} days. Run ${p10("validation_check")} { file: "src/path/to/file.ts" } on specific files to generate validation data, or try a longer time range with { days: 90 }.`);
33975
34046
  }
33976
- const passedCount = results.filter((r2) => r2.passed === 1).length;
33977
- const failedCount = results.filter((r2) => r2.passed === 0).length;
34047
+ const passedCount = results.filter((r3) => r3.passed === 1).length;
34048
+ const failedCount = results.filter((r3) => r3.passed === 0).length;
33978
34049
  const lines = [
33979
34050
  `## Validation Report (${days} days)`,
33980
34051
  `Files validated: ${results.length}`,
@@ -33985,11 +34056,11 @@ function handleValidationReport(args2, db) {
33985
34056
  "| File | Rules Violated | Date |",
33986
34057
  "|------|----------------|------|"
33987
34058
  ];
33988
- const failedResults = results.filter((r2) => r2.passed === 0);
33989
- for (const r2 of failedResults.slice(0, 30)) {
33990
- const filename = r2.file_path.split("/").pop();
33991
- const rules = r2.rules_violated ?? "-";
33992
- lines.push(`| ${filename} | ${rules.slice(0, 60)} | ${r2.created_at.slice(0, 10)} |`);
34059
+ const failedResults = results.filter((r3) => r3.passed === 0);
34060
+ for (const r3 of failedResults.slice(0, 30)) {
34061
+ const filename = r3.file_path.split("/").pop();
34062
+ const rules = r3.rules_violated ?? "-";
34063
+ lines.push(`| ${filename} | ${rules.slice(0, 60)} | ${r3.created_at.slice(0, 10)} |`);
33993
34064
  }
33994
34065
  if (failedResults.length > 30) {
33995
34066
  lines.push(`... and ${failedResults.length - 30} more`);
@@ -34918,9 +34989,9 @@ function handleTeamSearch(args2, db) {
34918
34989
  "| Developer | Type | Summary | Module | Date |",
34919
34990
  "|-----------|------|---------|--------|------|"
34920
34991
  ];
34921
- for (const r2 of results) {
34992
+ for (const r3 of results) {
34922
34993
  lines.push(
34923
- `| ${r2.developer_id} | ${r2.observation_type} | ${r2.summary.slice(0, 60)} | ${r2.module ?? "-"} | ${r2.created_at.split("T")[0]} |`
34994
+ `| ${r3.developer_id} | ${r3.observation_type} | ${r3.summary.slice(0, 60)} | ${r3.module ?? "-"} | ${r3.created_at.split("T")[0]} |`
34924
34995
  );
34925
34996
  }
34926
34997
  return text13(lines.join("\n"));
@@ -36013,10 +36084,10 @@ function handleSearch3(db, args2) {
36013
36084
  } else {
36014
36085
  lines.push(`Found ${results.length} result(s):`);
36015
36086
  lines.push("");
36016
- for (const r2 of results) {
36017
- const preview = r2.content.length > 500 ? r2.content.substring(0, 500) + "..." : r2.content;
36018
- lines.push(`### ${r2.heading || r2.title} [${r2.chunk_type}]`);
36019
- lines.push(`**File**: ${claudeDir}/${r2.file_path} | **Category**: ${r2.category}`);
36087
+ for (const r3 of results) {
36088
+ const preview = r3.content.length > 500 ? r3.content.substring(0, 500) + "..." : r3.content;
36089
+ lines.push(`### ${r3.heading || r3.title} [${r3.chunk_type}]`);
36090
+ lines.push(`**File**: ${claudeDir}/${r3.file_path} | **Category**: ${r3.category}`);
36020
36091
  lines.push("");
36021
36092
  lines.push(preview);
36022
36093
  lines.push("");
@@ -36250,11 +36321,11 @@ function handlePattern(db, args2) {
36250
36321
  LIMIT 10
36251
36322
  `).all(sanitizeFts5Query(topic), ...docIds);
36252
36323
  if (topicResults.length > 0) {
36253
- for (const r2 of topicResults) {
36254
- lines.push(`### ${r2.heading || "(section)"} [${r2.chunk_type}]`);
36255
- lines.push(`*Source: ${claudeDir}/${r2.file_path}*`);
36324
+ for (const r3 of topicResults) {
36325
+ lines.push(`### ${r3.heading || "(section)"} [${r3.chunk_type}]`);
36326
+ lines.push(`*Source: ${claudeDir}/${r3.file_path}*`);
36256
36327
  lines.push("");
36257
- lines.push(r2.content.length > 800 ? r2.content.substring(0, 800) + "..." : r2.content);
36328
+ lines.push(r3.content.length > 800 ? r3.content.substring(0, 800) + "..." : r3.content);
36258
36329
  lines.push("");
36259
36330
  lines.push("---");
36260
36331
  lines.push("");
@@ -36298,8 +36369,8 @@ function handlePattern(db, args2) {
36298
36369
  if (ftsResults.length > 0) {
36299
36370
  lines.push("### Broad Search Results");
36300
36371
  lines.push("");
36301
- for (const r2 of ftsResults) {
36302
- lines.push(`- **${r2.heading || "(section)"}** (${claudeDir}/${r2.file_path}): ${r2.content.substring(0, 200)}...`);
36372
+ for (const r3 of ftsResults) {
36373
+ lines.push(`- **${r3.heading || "(section)"}** (${claudeDir}/${r3.file_path}): ${r3.content.substring(0, 200)}...`);
36303
36374
  }
36304
36375
  }
36305
36376
  } catch {
@@ -36447,9 +36518,9 @@ function handleCommand(db, args2) {
36447
36518
  `).all(`%${keyword}%`, `%${keyword}%`);
36448
36519
  lines.push(`## Commands matching "${keyword}" (${results.length} found)`);
36449
36520
  lines.push("");
36450
- for (const r2 of results) {
36451
- const preview = r2.content.substring(0, 200).replace(/\n/g, " ");
36452
- lines.push(`- **${r2.heading}** (${claudeDir}/${r2.file_path}): ${preview}...`);
36521
+ for (const r3 of results) {
36522
+ const preview = r3.content.substring(0, 200).replace(/\n/g, " ");
36523
+ lines.push(`- **${r3.heading}** (${claudeDir}/${r3.file_path}): ${preview}...`);
36453
36524
  }
36454
36525
  } else {
36455
36526
  const commands = db.prepare(`
@@ -36534,8 +36605,8 @@ function handlePlan(db, args2) {
36534
36605
  `).all(`%${basename12(file)}%`);
36535
36606
  lines.push(`## Plans referencing \`${file}\` (${results.length} found)`);
36536
36607
  lines.push("");
36537
- for (const r2 of results) {
36538
- lines.push(`- **${r2.title}** (${r2.file_path})`);
36608
+ for (const r3 of results) {
36609
+ lines.push(`- **${r3.title}** (${r3.file_path})`);
36539
36610
  }
36540
36611
  } else if (keyword) {
36541
36612
  try {
@@ -36550,8 +36621,8 @@ function handlePlan(db, args2) {
36550
36621
  `).all(sanitizeFts5Query(keyword));
36551
36622
  lines.push(`## Plans matching "${keyword}" (${results.length} found)`);
36552
36623
  lines.push("");
36553
- for (const r2 of results) {
36554
- lines.push(`- **${r2.title}** (${r2.file_path})`);
36624
+ for (const r3 of results) {
36625
+ lines.push(`- **${r3.title}** (${r3.file_path})`);
36555
36626
  }
36556
36627
  } catch {
36557
36628
  lines.push(`FTS search error for "${keyword}". Try simpler terms.`);
@@ -36744,7 +36815,7 @@ function handleEffectiveness2(db, args2) {
36744
36815
  }
36745
36816
  if (ruleId || mode === "detail") {
36746
36817
  const targetRule = ruleId || "";
36747
- const rule = allRules.find((r2) => r2.rule_id === targetRule);
36818
+ const rule = allRules.find((r3) => r3.rule_id === targetRule);
36748
36819
  if (!rule) {
36749
36820
  return text15(`Rule ${targetRule} not found.`);
36750
36821
  }
@@ -36767,10 +36838,10 @@ function handleEffectiveness2(db, args2) {
36767
36838
  lines.push(`| Linked Corrections | ${correctionEdges.cnt} |`);
36768
36839
  lines.push(`| Effectiveness Score | ${violations === 0 ? "HIGH (never violated)" : violations < 3 ? "MEDIUM" : "LOW (frequently violated)"} |`);
36769
36840
  } else {
36770
- const rulesWithCounts = allRules.map((r2) => ({
36771
- ...r2,
36772
- violations: violationCounts.get(r2.rule_id) || 0,
36773
- last_at: lastViolated.get(r2.rule_id) || "Never"
36841
+ const rulesWithCounts = allRules.map((r3) => ({
36842
+ ...r3,
36843
+ violations: violationCounts.get(r3.rule_id) || 0,
36844
+ last_at: lastViolated.get(r3.rule_id) || "Never"
36774
36845
  }));
36775
36846
  if (mode === "most_violated") {
36776
36847
  rulesWithCounts.sort((a2, b2) => b2.violations - a2.violations);
@@ -36786,9 +36857,9 @@ function handleEffectiveness2(db, args2) {
36786
36857
  lines.push("");
36787
36858
  lines.push(`| Rule | Text | Violations | Last Violated |`);
36788
36859
  lines.push(`|------|------|------------|---------------|`);
36789
- for (const r2 of rulesWithCounts.slice(0, topN)) {
36790
- const ruleText = r2.rule_text.length > 40 ? r2.rule_text.substring(0, 40) + "..." : r2.rule_text;
36791
- lines.push(`| ${r2.rule_id} | ${ruleText} | ${r2.violations} | ${r2.last_at} |`);
36860
+ for (const r3 of rulesWithCounts.slice(0, topN)) {
36861
+ const ruleText = r3.rule_text.length > 40 ? r3.rule_text.substring(0, 40) + "..." : r3.rule_text;
36862
+ lines.push(`| ${r3.rule_id} | ${ruleText} | ${r3.violations} | ${r3.last_at} |`);
36792
36863
  }
36793
36864
  }
36794
36865
  return text15(lines.join("\n"));
@@ -37085,21 +37156,21 @@ function handlePyRoutes(args2, dataDb) {
37085
37156
  const routes = dataDb.prepare(query).all(...params);
37086
37157
  if (args2.uncoupled) {
37087
37158
  const callerCountStmt = dataDb.prepare(`SELECT COUNT(*) as cnt FROM ${t("py_route_callers")} WHERE route_id = ?`);
37088
- const uncoupledRoutes = routes.filter((r2) => {
37089
- const callers = callerCountStmt.get(r2.id).cnt;
37159
+ const uncoupledRoutes = routes.filter((r3) => {
37160
+ const callers = callerCountStmt.get(r3.id).cnt;
37090
37161
  return callers === 0;
37091
37162
  });
37092
37163
  lines.push(`## Uncoupled Routes (${uncoupledRoutes.length} with no frontend callers)`);
37093
- for (const r2 of uncoupledRoutes) {
37094
- lines.push(`- ${r2.method} ${r2.path} \u2192 ${r2.function_name} (${r2.file}:${r2.line})`);
37164
+ for (const r3 of uncoupledRoutes) {
37165
+ lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name} (${r3.file}:${r3.line})`);
37095
37166
  }
37096
37167
  } else {
37097
37168
  lines.push(`## Python Routes (${routes.length} found)`);
37098
- for (const r2 of routes) {
37099
- const auth = r2.is_authenticated ? "" : " [UNAUTH]";
37100
- const deps = safeParseArray(r2.dependencies);
37101
- lines.push(`- ${r2.method} ${r2.path} \u2192 ${r2.function_name} (${r2.file}:${r2.line})${auth}`);
37102
- if (r2.response_model) lines.push(` Response: ${r2.response_model}`);
37169
+ for (const r3 of routes) {
37170
+ const auth = r3.is_authenticated ? "" : " [UNAUTH]";
37171
+ const deps = safeParseArray(r3.dependencies);
37172
+ lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name} (${r3.file}:${r3.line})${auth}`);
37173
+ if (r3.response_model) lines.push(` Response: ${r3.response_model}`);
37103
37174
  if (deps.length > 0) lines.push(` Depends: ${deps.join(", ")}`);
37104
37175
  }
37105
37176
  }
@@ -37301,8 +37372,8 @@ function handlePyImpact(args2, dataDb) {
37301
37372
  if (routes.length > 0) {
37302
37373
  lines.push(`
37303
37374
  ### Routes Defined (${routes.length})`);
37304
- for (const r2 of routes) {
37305
- lines.push(`- ${r2.method} ${r2.path} \u2192 ${r2.function_name}`);
37375
+ for (const r3 of routes) {
37376
+ lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name}`);
37306
37377
  }
37307
37378
  }
37308
37379
  const models = dataDb.prepare(
@@ -37320,7 +37391,7 @@ function handlePyImpact(args2, dataDb) {
37320
37391
  const placeholders = routeIds.map(() => "?").join(",");
37321
37392
  const callers = dataDb.prepare(
37322
37393
  `SELECT DISTINCT frontend_file FROM ${t("py_route_callers")} WHERE route_id IN (${placeholders}) LIMIT 100000`
37323
- ).all(...routeIds.map((r2) => r2.id));
37394
+ ).all(...routeIds.map((r3) => r3.id));
37324
37395
  if (callers.length > 0) {
37325
37396
  lines.push(`
37326
37397
  ### Frontend Callers (${callers.length} files)`);
@@ -37363,8 +37434,8 @@ function handlePyContext(args2, dataDb) {
37363
37434
  const routes = dataDb.prepare(`SELECT method, path, function_name, line FROM ${t("py_routes")} WHERE file = ? LIMIT 10000`).all(file);
37364
37435
  if (routes.length > 0) {
37365
37436
  lines.push("\n### Routes");
37366
- for (const r2 of routes) {
37367
- lines.push(`- ${r2.method} ${r2.path} \u2192 ${r2.function_name} (L${r2.line})`);
37437
+ for (const r3 of routes) {
37438
+ lines.push(`- ${r3.method} ${r3.path} \u2192 ${r3.function_name} (L${r3.line})`);
37368
37439
  }
37369
37440
  }
37370
37441
  const models = dataDb.prepare(`SELECT class_name, table_name, line FROM ${t("py_models")} WHERE file = ? LIMIT 10000`).all(file);
@@ -37375,8 +37446,8 @@ function handlePyContext(args2, dataDb) {
37375
37446
  }
37376
37447
  }
37377
37448
  const rules = config.rules || [];
37378
- const matchingRules = rules.filter((r2) => {
37379
- const pattern = r2.pattern;
37449
+ const matchingRules = rules.filter((r3) => {
37450
+ const pattern = r3.pattern;
37380
37451
  if (pattern === "**") return true;
37381
37452
  if (pattern.includes("**/*.py")) return file.endsWith(".py");
37382
37453
  return file.includes(pattern.replace(/\*\*/g, ""));
@@ -37384,8 +37455,8 @@ function handlePyContext(args2, dataDb) {
37384
37455
  if (matchingRules.length > 0) {
37385
37456
  lines.push("\n### Applicable Rules");
37386
37457
  for (const rule of matchingRules) {
37387
- for (const r2 of rule.rules) {
37388
- lines.push(`- ${r2}`);
37458
+ for (const r3 of rule.rules) {
37459
+ lines.push(`- ${r3}`);
37389
37460
  }
37390
37461
  }
37391
37462
  }
@@ -37791,8 +37862,8 @@ function handleContext(file, dataDb, codegraphDb) {
37791
37862
  lines.push("## Applicable Rules");
37792
37863
  for (const rule of rules) {
37793
37864
  const severity = rule.severity ? `[${rule.severity}]` : "";
37794
- for (const r2 of rule.rules) {
37795
- lines.push(`- ${severity} ${r2}`);
37865
+ for (const r3 of rule.rules) {
37866
+ lines.push(`- ${severity} ${r3}`);
37796
37867
  }
37797
37868
  if (rule.patternFile) {
37798
37869
  lines.push(` See: .claude/${rule.patternFile}`);
@@ -37880,7 +37951,7 @@ function handleContext(file, dataDb, codegraphDb) {
37880
37951
  WHERE kf.content MATCH ? AND kc.chunk_type = 'rule'
37881
37952
  LIMIT 8
37882
37953
  `).all(ftsQuery);
37883
- ftsRuleIds = ftsResults.map((r2) => r2.rule_id).filter((id) => id.startsWith("CR-"));
37954
+ ftsRuleIds = ftsResults.map((r3) => r3.rule_id).filter((id) => id.startsWith("CR-"));
37884
37955
  } catch {
37885
37956
  }
37886
37957
  }
@@ -38234,7 +38305,7 @@ function handleDomains(args2, dataDb, codegraphDb) {
38234
38305
  }
38235
38306
  lines.push("");
38236
38307
  lines.push(`### Routers (${files.routers.length})`);
38237
- for (const r2 of files.routers) lines.push(`- ${r2}`);
38308
+ for (const r3 of files.routers) lines.push(`- ${r3}`);
38238
38309
  lines.push("");
38239
38310
  lines.push(`### Pages (${files.pages.length})`);
38240
38311
  for (const p19 of files.pages) lines.push(`- ${p19}`);
@@ -39324,8 +39395,8 @@ function winManagerDirs(env) {
39324
39395
  function windowsAllowlistRoots(env) {
39325
39396
  const d2 = winManagerDirs(env);
39326
39397
  const roots = [];
39327
- for (const r2 of [d2.userprofile, d2.nvmHome, d2.nvmSymlink, d2.fnmDir, d2.voltaHome, d2.localappdata]) {
39328
- if (r2) roots.push(r2);
39398
+ for (const r3 of [d2.userprofile, d2.nvmHome, d2.nvmSymlink, d2.fnmDir, d2.voltaHome, d2.localappdata]) {
39399
+ if (r3) roots.push(r3);
39329
39400
  }
39330
39401
  roots.push("C:\\Program Files\\nodejs", "C:\\Program Files (x86)\\nodejs");
39331
39402
  return roots;