@hivelore/cli 0.33.0 → 0.34.1

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/index.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  preCommitCheck,
11
11
  readPresumedCorrectTargets,
12
12
  runHaiveMcpStdio
13
- } from "./chunk-XDB7EKL4.js";
13
+ } from "./chunk-X6UHROFL.js";
14
14
  import {
15
15
  registerMemoryPending
16
16
  } from "./chunk-OYJKHD22.js";
@@ -208,7 +208,7 @@ async function getHotFiles(root, daysBack, maxHotFiles, filePaths) {
208
208
  if (!f) continue;
209
209
  counts.set(f, (counts.get(f) ?? 0) + 1);
210
210
  }
211
- let entries = [...counts.entries()].map(([path46, changes]) => ({ path: path46, changes }));
211
+ let entries = [...counts.entries()].map(([path47, changes]) => ({ path: path47, changes }));
212
212
  const lowerPaths = filePaths.map((p) => p.toLowerCase());
213
213
  if (lowerPaths.length > 0) {
214
214
  entries = entries.filter((e) => lowerPaths.some((p) => e.path.toLowerCase().includes(p)));
@@ -322,9 +322,9 @@ async function lintMemoriesAsync(root, options = {}) {
322
322
  message: "Reads like generic best practice a capable model already follows. Hivelore's value is UNGUESSABLE team knowledge \u2014 add the concrete, arbitrary specifics (exact names, values, formats, magic numbers) or consider removing it to keep briefings high-signal."
323
323
  });
324
324
  }
325
- const suggestedAnchors = suggestAnchors(root, { filePath, memory: memory2 }, codeMap, trackedFiles);
326
- const isUnanchoredSeed = fm.tags.includes("stack-pack") && fm.tags.includes("needs_anchor");
327
- if (ANCHOR_TYPES.has(fm.type) && fm.anchor.paths.length === 0 && fm.status === "validated" && !isUnanchoredSeed) {
325
+ const isStackSeed = fm.tags.includes("stack-pack");
326
+ const suggestedAnchors = isStackSeed ? { paths: [], symbols: [] } : suggestAnchors(root, { filePath, memory: memory2 }, codeMap, trackedFiles);
327
+ if (ANCHOR_TYPES.has(fm.type) && fm.anchor.paths.length === 0 && fm.status === "validated" && !isStackSeed) {
328
328
  out.push({
329
329
  file: filePath,
330
330
  id: fm.id,
@@ -728,20 +728,7 @@ async function projectContextVersionStatus(root, paths) {
728
728
  async function refreshCodeMap(root, paths, force) {
729
729
  const existing = await loadCodeMap2(paths);
730
730
  if (existing && !force) return false;
731
- const map = await buildCodeMap(root, {
732
- includeUntracked: true,
733
- excludeDirs: [
734
- "node_modules",
735
- "dist",
736
- "build",
737
- "out",
738
- ".git",
739
- ".next",
740
- ".turbo",
741
- ".vitest-cache",
742
- "coverage"
743
- ]
744
- });
731
+ const map = await buildCodeMap(root, { includeUntracked: true });
745
732
  if (existing && existing.root === map.root && JSON.stringify(existing.files) === JSON.stringify(map.files)) {
746
733
  return false;
747
734
  }
@@ -1355,6 +1342,7 @@ import path6 from "path";
1355
1342
  import "commander";
1356
1343
  import {
1357
1344
  buildCodeMap as buildCodeMap2,
1345
+ CODE_MAP_DEFAULT_EXCLUDE,
1358
1346
  codeMapPath,
1359
1347
  findProjectRoot as findProjectRoot4,
1360
1348
  loadCodeMap as loadCodeMap4,
@@ -1383,18 +1371,7 @@ function registerIndexCode(program2) {
1383
1371
  ui.info(`Indexing source files in ${root}\u2026`);
1384
1372
  const map = await buildCodeMap2(root, {
1385
1373
  includeUntracked: true,
1386
- excludeDirs: [
1387
- "node_modules",
1388
- "dist",
1389
- "build",
1390
- "out",
1391
- ".git",
1392
- ".next",
1393
- ".turbo",
1394
- ".vitest-cache",
1395
- "coverage",
1396
- ...extraExcludes
1397
- ]
1374
+ excludeDirs: [...CODE_MAP_DEFAULT_EXCLUDE, ...extraExcludes]
1398
1375
  });
1399
1376
  await saveCodeMap2(paths, map);
1400
1377
  const fileCount = Object.keys(map.files).length;
@@ -1504,14 +1481,14 @@ function isCodeMapStale(root, generatedAt, files) {
1504
1481
  // src/commands/init.ts
1505
1482
  import { execFile as execFile2 } from "child_process";
1506
1483
  import { mkdir as mkdir6, readFile as readFile6, readdir as readdir2, writeFile as writeFile7 } from "fs/promises";
1507
- import { existsSync as existsSync11 } from "fs";
1508
- import path12 from "path";
1484
+ import { existsSync as existsSync12 } from "fs";
1485
+ import path13 from "path";
1509
1486
  import { spawnSync as spawnSync3 } from "child_process";
1510
1487
  import { promisify as promisify2 } from "util";
1511
1488
  import "commander";
1512
1489
  import {
1513
1490
  AUTOPILOT_DEFAULTS as AUTOPILOT_DEFAULTS2,
1514
- BRIDGE_TARGETS,
1491
+ BRIDGE_TARGETS as BRIDGE_TARGETS2,
1515
1492
  buildCodeMap as buildCodeMap3,
1516
1493
  buildFrontmatter as buildFrontmatter2,
1517
1494
  detectStacksFromManifests,
@@ -1523,20 +1500,93 @@ import {
1523
1500
  serializeMemory as serializeMemory3
1524
1501
  } from "@hivelore/core";
1525
1502
 
1503
+ // src/utils/doc-files.ts
1504
+ import { readdirSync } from "fs";
1505
+ function findDocFile(root, stem) {
1506
+ let entries;
1507
+ try {
1508
+ entries = readdirSync(root);
1509
+ } catch {
1510
+ return void 0;
1511
+ }
1512
+ const re = new RegExp(`^${stem}(\\.(md|markdown|txt|rst))?$`, "i");
1513
+ return entries.find((e) => re.test(e));
1514
+ }
1515
+
1516
+ // src/utils/bridge-detect.ts
1517
+ import { existsSync as existsSync6, readdirSync as readdirSync2 } from "fs";
1518
+ import { homedir } from "os";
1519
+ import path7 from "path";
1520
+ import { BRIDGE_TARGET_PATH, BRIDGE_TARGETS } from "@hivelore/core";
1521
+ var VSCODE_EXTENSION_SIGNALS = {
1522
+ copilot: ["github.copilot"],
1523
+ cline: ["saoudrizwan.claude-dev"],
1524
+ roo: ["rooveterinaryinc.roo"],
1525
+ cody: ["sourcegraph.cody"],
1526
+ continue: ["continue.continue"]
1527
+ };
1528
+ var HOME_SIGNALS = {
1529
+ claude: [".claude", ".claude.json"],
1530
+ cursor: [".cursor"],
1531
+ windsurf: [".codeium/windsurf", ".windsurf"],
1532
+ gemini: [".gemini"],
1533
+ continue: [".continue"],
1534
+ aider: [".aider.conf.yml", ".aider"],
1535
+ zed: [".config/zed", "Library/Application Support/Zed"],
1536
+ copilot: [".config/github-copilot"]
1537
+ };
1538
+ var ENV_SIGNALS = {
1539
+ claude: ["CLAUDECODE", "CLAUDE_CODE_ENTRYPOINT"],
1540
+ cursor: ["CURSOR_AGENT"],
1541
+ gemini: ["GEMINI_CLI"],
1542
+ aider: ["AIDER_MODEL"]
1543
+ };
1544
+ function vscodeExtensionIds(home) {
1545
+ const ids = [];
1546
+ for (const dir of [".vscode/extensions", ".vscode-server/extensions", ".vscode-oss/extensions"]) {
1547
+ try {
1548
+ ids.push(...readdirSync2(path7.join(home, dir)).map((e) => e.toLowerCase()));
1549
+ } catch {
1550
+ }
1551
+ }
1552
+ return ids;
1553
+ }
1554
+ function detectBridgeTargets(root, env = process.env, home = homedir()) {
1555
+ const reasons = { agents: "universal" };
1556
+ const extensions = vscodeExtensionIds(home);
1557
+ for (const target of BRIDGE_TARGETS) {
1558
+ if (target === "agents") continue;
1559
+ if (existsSync6(path7.join(root, BRIDGE_TARGET_PATH[target]))) {
1560
+ reasons[target] = "repo file";
1561
+ continue;
1562
+ }
1563
+ const homeHit = (HOME_SIGNALS[target] ?? []).some((p) => existsSync6(path7.join(home, p)));
1564
+ const envHit = (ENV_SIGNALS[target] ?? []).some((v) => env[v]);
1565
+ const extHit = (VSCODE_EXTENSION_SIGNALS[target] ?? []).some(
1566
+ (prefix) => extensions.some((id) => id.startsWith(prefix))
1567
+ );
1568
+ if (homeHit || envHit || extHit) reasons[target] = "installed";
1569
+ }
1570
+ return {
1571
+ targets: BRIDGE_TARGETS.filter((t) => t in reasons),
1572
+ reasons
1573
+ };
1574
+ }
1575
+
1526
1576
  // src/utils/bridge-files.ts
1527
1577
  import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
1528
- import { existsSync as existsSync6 } from "fs";
1529
- import path7 from "path";
1578
+ import { existsSync as existsSync7 } from "fs";
1579
+ import path8 from "path";
1530
1580
  import {
1531
1581
  BRIDGE_MARKERS,
1532
- BRIDGE_TARGET_PATH,
1582
+ BRIDGE_TARGET_PATH as BRIDGE_TARGET_PATH2,
1533
1583
  generateBridges,
1534
1584
  isRetiredMemory,
1535
1585
  loadMemoriesFromDir as loadMemoriesFromDir5
1536
1586
  } from "@hivelore/core";
1537
1587
  async function writeBridgeFiles(root, paths, opts) {
1538
1588
  const result = { created: [], updated: [], unchanged: [], skipped: [], warnings: [] };
1539
- if (!existsSync6(paths.memoriesDir)) return result;
1589
+ if (!existsSync7(paths.memoriesDir)) return result;
1540
1590
  const allLoaded = await loadMemoriesFromDir5(paths.memoriesDir);
1541
1591
  const memories = allLoaded.map((l) => l.memory).filter((m) => !isRetiredMemory(m.frontmatter, m.body));
1542
1592
  const sensors = [];
@@ -1554,8 +1604,8 @@ async function writeBridgeFiles(root, paths, opts) {
1554
1604
  const maxMemories = Math.max(1, opts.maxMemories ?? 8);
1555
1605
  const outputs = generateBridges(memories, sensors, { maxMemories, targets: opts.targets });
1556
1606
  for (const output of outputs) {
1557
- const targetFile = path7.join(root, output.path);
1558
- const fileExists = existsSync6(targetFile);
1607
+ const targetFile = path8.join(root, output.path);
1608
+ const fileExists = existsSync7(targetFile);
1559
1609
  if (opts.onlyExisting && !fileExists) continue;
1560
1610
  if (opts.dryRun) {
1561
1611
  if (!fileExists) {
@@ -1574,7 +1624,7 @@ async function writeBridgeFiles(root, paths, opts) {
1574
1624
  }
1575
1625
  continue;
1576
1626
  }
1577
- await mkdir2(path7.dirname(targetFile), { recursive: true });
1627
+ await mkdir2(path8.dirname(targetFile), { recursive: true });
1578
1628
  if (!fileExists) {
1579
1629
  await writeFile3(targetFile, output.content, "utf8");
1580
1630
  result.created.push(output.path);
@@ -1597,10 +1647,10 @@ async function writeBridgeFiles(root, paths, opts) {
1597
1647
  return result;
1598
1648
  }
1599
1649
  async function getBridgeFileStatuses(root, paths, opts) {
1600
- if (!existsSync6(paths.memoriesDir)) {
1650
+ if (!existsSync7(paths.memoriesDir)) {
1601
1651
  return opts.targets.map((target) => ({
1602
1652
  target,
1603
- path: BRIDGE_TARGET_PATH[target],
1653
+ path: BRIDGE_TARGET_PATH2[target],
1604
1654
  exists: false,
1605
1655
  state: "missing",
1606
1656
  wouldChange: false,
@@ -1627,8 +1677,8 @@ async function getBridgeFileStatuses(root, paths, opts) {
1627
1677
  });
1628
1678
  const statuses = [];
1629
1679
  for (const output of outputs) {
1630
- const targetFile = path7.join(root, output.path);
1631
- const exists = existsSync6(targetFile);
1680
+ const targetFile = path8.join(root, output.path);
1681
+ const exists = existsSync7(targetFile);
1632
1682
  if (!exists) {
1633
1683
  statuses.push({
1634
1684
  target: output.target,
@@ -1784,18 +1834,18 @@ function legacyManagedRange(text) {
1784
1834
 
1785
1835
  // src/commands/agent.ts
1786
1836
  import { spawnSync as spawnSync2 } from "child_process";
1787
- import { existsSync as existsSync8 } from "fs";
1837
+ import { existsSync as existsSync9 } from "fs";
1788
1838
  import { mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
1789
1839
  import os2 from "os";
1790
- import path9 from "path";
1840
+ import path10 from "path";
1791
1841
  import { createInterface } from "readline/promises";
1792
1842
  import "commander";
1793
1843
  import { findProjectRoot as findProjectRoot5, resolveHaivePaths as resolveHaivePaths5 } from "@hivelore/core";
1794
1844
 
1795
1845
  // src/commands/init-mcp-setup.ts
1796
1846
  import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir3 } from "fs/promises";
1797
- import { existsSync as existsSync7 } from "fs";
1798
- import path8 from "path";
1847
+ import { existsSync as existsSync8 } from "fs";
1848
+ import path9 from "path";
1799
1849
  import os from "os";
1800
1850
  var HOME = os.homedir();
1801
1851
  var HAIVE_MCP_ENTRY = {
@@ -1810,14 +1860,14 @@ function projectMcpEntry(root) {
1810
1860
  };
1811
1861
  }
1812
1862
  function cursorMcpPath() {
1813
- return path8.join(HOME, ".cursor", "mcp.json");
1863
+ return path9.join(HOME, ".cursor", "mcp.json");
1814
1864
  }
1815
1865
  async function configureCursor() {
1816
1866
  const mcpPath = cursorMcpPath();
1817
- const cursorDir = path8.join(HOME, ".cursor");
1818
- if (!existsSync7(cursorDir)) return { client: "Cursor", status: "not_installed" };
1867
+ const cursorDir = path9.join(HOME, ".cursor");
1868
+ if (!existsSync8(cursorDir)) return { client: "Cursor", status: "not_installed" };
1819
1869
  let config = {};
1820
- if (existsSync7(mcpPath)) {
1870
+ if (existsSync8(mcpPath)) {
1821
1871
  try {
1822
1872
  config = JSON.parse(await readFile4(mcpPath, "utf8"));
1823
1873
  } catch {
@@ -1832,16 +1882,16 @@ async function configureCursor() {
1832
1882
  }
1833
1883
  function vscodeMcpPath() {
1834
1884
  const candidates = [
1835
- path8.join(HOME, ".config", "Code", "User", "mcp.json"),
1885
+ path9.join(HOME, ".config", "Code", "User", "mcp.json"),
1836
1886
  // Linux
1837
- path8.join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
1887
+ path9.join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
1838
1888
  // macOS
1839
- path8.join(HOME, "AppData", "Roaming", "Code", "User", "mcp.json"),
1889
+ path9.join(HOME, "AppData", "Roaming", "Code", "User", "mcp.json"),
1840
1890
  // Windows
1841
- path8.join(HOME, ".config", "Code - Insiders", "User", "mcp.json")
1891
+ path9.join(HOME, ".config", "Code - Insiders", "User", "mcp.json")
1842
1892
  ];
1843
1893
  for (const c of candidates) {
1844
- if (existsSync7(path8.dirname(c))) return c;
1894
+ if (existsSync8(path9.dirname(c))) return c;
1845
1895
  }
1846
1896
  return null;
1847
1897
  }
@@ -1849,7 +1899,7 @@ async function configureVSCode() {
1849
1899
  const mcpPath = vscodeMcpPath();
1850
1900
  if (!mcpPath) return { client: "VS Code", status: "not_installed" };
1851
1901
  let config = {};
1852
- if (existsSync7(mcpPath)) {
1902
+ if (existsSync8(mcpPath)) {
1853
1903
  try {
1854
1904
  config = JSON.parse(await readFile4(mcpPath, "utf8"));
1855
1905
  } catch {
@@ -1858,24 +1908,24 @@ async function configureVSCode() {
1858
1908
  config.servers ??= {};
1859
1909
  if (config.servers["hivelore"] || config.servers["haive"]) return { client: "VS Code", status: "already_configured" };
1860
1910
  config.servers["hivelore"] = { ...HAIVE_MCP_ENTRY, type: "stdio" };
1861
- await mkdir3(path8.dirname(mcpPath), { recursive: true });
1911
+ await mkdir3(path9.dirname(mcpPath), { recursive: true });
1862
1912
  await writeFile4(mcpPath, JSON.stringify(config, null, 2), "utf8");
1863
1913
  return { client: "VS Code", status: "configured", path: mcpPath };
1864
1914
  }
1865
1915
  function claudeConfigPath() {
1866
- const p = path8.join(HOME, ".claude.json");
1867
- if (existsSync7(p)) return p;
1868
- const p2 = path8.join(HOME, ".config", "claude", "claude.json");
1869
- if (existsSync7(path8.dirname(p2))) return p2;
1916
+ const p = path9.join(HOME, ".claude.json");
1917
+ if (existsSync8(p)) return p;
1918
+ const p2 = path9.join(HOME, ".config", "claude", "claude.json");
1919
+ if (existsSync8(path9.dirname(p2))) return p2;
1870
1920
  return null;
1871
1921
  }
1872
1922
  async function configureClaude() {
1873
- const cfgPath = claudeConfigPath() ?? path8.join(HOME, ".claude.json");
1874
- if (!existsSync7(cfgPath) && !existsSync7(path8.join(HOME, ".claude"))) {
1923
+ const cfgPath = claudeConfigPath() ?? path9.join(HOME, ".claude.json");
1924
+ if (!existsSync8(cfgPath) && !existsSync8(path9.join(HOME, ".claude"))) {
1875
1925
  return { client: "Claude Code", status: "not_installed" };
1876
1926
  }
1877
1927
  let config = {};
1878
- if (existsSync7(cfgPath)) {
1928
+ if (existsSync8(cfgPath)) {
1879
1929
  try {
1880
1930
  config = JSON.parse(await readFile4(cfgPath, "utf8"));
1881
1931
  } catch {
@@ -1889,11 +1939,11 @@ async function configureClaude() {
1889
1939
  }
1890
1940
  function windsurfMcpPath() {
1891
1941
  const candidates = [
1892
- path8.join(HOME, ".codeium", "windsurf", "mcp_config.json"),
1893
- path8.join(HOME, ".windsurf", "mcp.json")
1942
+ path9.join(HOME, ".codeium", "windsurf", "mcp_config.json"),
1943
+ path9.join(HOME, ".windsurf", "mcp.json")
1894
1944
  ];
1895
1945
  for (const c of candidates) {
1896
- if (existsSync7(path8.dirname(c))) return c;
1946
+ if (existsSync8(path9.dirname(c))) return c;
1897
1947
  }
1898
1948
  return null;
1899
1949
  }
@@ -1901,7 +1951,7 @@ async function configureWindsurf() {
1901
1951
  const mcpPath = windsurfMcpPath();
1902
1952
  if (!mcpPath) return { client: "Windsurf", status: "not_installed" };
1903
1953
  let config = {};
1904
- if (existsSync7(mcpPath)) {
1954
+ if (existsSync8(mcpPath)) {
1905
1955
  try {
1906
1956
  config = JSON.parse(await readFile4(mcpPath, "utf8"));
1907
1957
  } catch {
@@ -1910,7 +1960,7 @@ async function configureWindsurf() {
1910
1960
  config.mcpServers ??= {};
1911
1961
  if (config.mcpServers["hivelore"] || config.mcpServers["haive"]) return { client: "Windsurf", status: "already_configured" };
1912
1962
  config.mcpServers["hivelore"] = HAIVE_MCP_ENTRY;
1913
- await mkdir3(path8.dirname(mcpPath), { recursive: true });
1963
+ await mkdir3(path9.dirname(mcpPath), { recursive: true });
1914
1964
  await writeFile4(mcpPath, JSON.stringify(config, null, 2), "utf8");
1915
1965
  return { client: "Windsurf", status: "configured", path: mcpPath };
1916
1966
  }
@@ -1931,9 +1981,9 @@ async function configureProjectMcpClients(root) {
1931
1981
  const entry = projectMcpEntry(root);
1932
1982
  const results = [];
1933
1983
  try {
1934
- const cursorPath = path8.join(root, ".cursor", "mcp.json");
1984
+ const cursorPath = path9.join(root, ".cursor", "mcp.json");
1935
1985
  let config = {};
1936
- if (existsSync7(cursorPath)) {
1986
+ if (existsSync8(cursorPath)) {
1937
1987
  try {
1938
1988
  config = JSON.parse(await readFile4(cursorPath, "utf8"));
1939
1989
  } catch {
@@ -1942,16 +1992,16 @@ async function configureProjectMcpClients(root) {
1942
1992
  config.mcpServers ??= {};
1943
1993
  delete config.mcpServers["haive"];
1944
1994
  config.mcpServers["hivelore"] = entry;
1945
- await mkdir3(path8.dirname(cursorPath), { recursive: true });
1995
+ await mkdir3(path9.dirname(cursorPath), { recursive: true });
1946
1996
  await writeFile4(cursorPath, JSON.stringify(config, null, 2) + "\n", "utf8");
1947
1997
  results.push({ client: "Cursor (project)", status: "configured", path: cursorPath });
1948
1998
  } catch (err) {
1949
1999
  results.push({ client: "Cursor (project)", status: "error", error: String(err) });
1950
2000
  }
1951
2001
  try {
1952
- const vscodePath = path8.join(root, ".vscode", "mcp.json");
2002
+ const vscodePath = path9.join(root, ".vscode", "mcp.json");
1953
2003
  let config = {};
1954
- if (existsSync7(vscodePath)) {
2004
+ if (existsSync8(vscodePath)) {
1955
2005
  try {
1956
2006
  config = JSON.parse(await readFile4(vscodePath, "utf8"));
1957
2007
  } catch {
@@ -1960,16 +2010,16 @@ async function configureProjectMcpClients(root) {
1960
2010
  config.servers ??= {};
1961
2011
  delete config.servers["haive"];
1962
2012
  config.servers["hivelore"] = { ...entry, type: "stdio" };
1963
- await mkdir3(path8.dirname(vscodePath), { recursive: true });
2013
+ await mkdir3(path9.dirname(vscodePath), { recursive: true });
1964
2014
  await writeFile4(vscodePath, JSON.stringify(config, null, 2) + "\n", "utf8");
1965
2015
  results.push({ client: "VS Code (workspace)", status: "configured", path: vscodePath });
1966
2016
  } catch (err) {
1967
2017
  results.push({ client: "VS Code (workspace)", status: "error", error: String(err) });
1968
2018
  }
1969
2019
  try {
1970
- const mcpPath = path8.join(root, ".mcp.json");
2020
+ const mcpPath = path9.join(root, ".mcp.json");
1971
2021
  let config = {};
1972
- if (existsSync7(mcpPath)) {
2022
+ if (existsSync8(mcpPath)) {
1973
2023
  try {
1974
2024
  config = JSON.parse(await readFile4(mcpPath, "utf8"));
1975
2025
  } catch {
@@ -2044,9 +2094,9 @@ async function detectAgentMode(dir) {
2044
2094
  const root = findProjectRoot5(dir);
2045
2095
  const paths = resolveHaivePaths5(root);
2046
2096
  const projectMcp = [
2047
- { client: "Claude Code", path: path9.join(root, ".mcp.json"), present: existsSync8(path9.join(root, ".mcp.json")) },
2048
- { client: "Cursor", path: path9.join(root, ".cursor", "mcp.json"), present: existsSync8(path9.join(root, ".cursor", "mcp.json")) },
2049
- { client: "VS Code", path: path9.join(root, ".vscode", "mcp.json"), present: existsSync8(path9.join(root, ".vscode", "mcp.json")) }
2097
+ { client: "Claude Code", path: path10.join(root, ".mcp.json"), present: existsSync9(path10.join(root, ".mcp.json")) },
2098
+ { client: "Cursor", path: path10.join(root, ".cursor", "mcp.json"), present: existsSync9(path10.join(root, ".cursor", "mcp.json")) },
2099
+ { client: "VS Code", path: path10.join(root, ".vscode", "mcp.json"), present: existsSync9(path10.join(root, ".vscode", "mcp.json")) }
2050
2100
  ];
2051
2101
  const installedAgents = [
2052
2102
  { agent: "Codex", command: "codex", installed: commandExists("codex"), mcp_configured: codexMcpConfigured() },
@@ -2061,7 +2111,7 @@ async function detectAgentMode(dir) {
2061
2111
  const recommendedCommand = recommendedMode === "mcp" ? "Restart your AI client, then call get_briefing before editing." : recommendedMode === "wrapped" && wrapperAgent ? `hivelore run -- ${wrapperAgent.command}` : 'hivelore briefing --task "..." --files "..."';
2062
2112
  return {
2063
2113
  root,
2064
- initialized: existsSync8(paths.haiveDir),
2114
+ initialized: existsSync9(paths.haiveDir),
2065
2115
  project_mcp: projectMcp,
2066
2116
  installed_agents: installedAgents,
2067
2117
  recommended_mode: recommendedMode,
@@ -2069,9 +2119,9 @@ async function detectAgentMode(dir) {
2069
2119
  };
2070
2120
  }
2071
2121
  async function writeAgentModeRecord(paths, detection, skippedReason) {
2072
- const dir = path9.join(paths.runtimeDir, "enforcement");
2122
+ const dir = path10.join(paths.runtimeDir, "enforcement");
2073
2123
  await mkdir4(dir, { recursive: true });
2074
- const file = path9.join(dir, "agent-mode.json");
2124
+ const file = path10.join(dir, "agent-mode.json");
2075
2125
  const record = {
2076
2126
  selected_mode: detection.recommended_mode,
2077
2127
  recommended_command: detection.recommended_command,
@@ -2112,7 +2162,7 @@ async function configureCodexIfAvailable(root) {
2112
2162
  "mcp",
2113
2163
  "--stdio"
2114
2164
  ], { encoding: "utf8" });
2115
- if (result.status === 0) return { client: "Codex", status: "configured", path: path9.join(os2.homedir(), ".codex", "config.toml") };
2165
+ if (result.status === 0) return { client: "Codex", status: "configured", path: path10.join(os2.homedir(), ".codex", "config.toml") };
2116
2166
  return { client: "Codex", status: "error", error: result.stderr || result.stdout || "codex mcp add failed" };
2117
2167
  }
2118
2168
  function commandExists(command) {
@@ -2139,7 +2189,7 @@ function printDetection(detection, json) {
2139
2189
  console.log(ui.dim(` root: ${detection.root}`));
2140
2190
  console.log(`${detection.initialized ? ui.green("\u2713") : ui.red("\u2717")} project initialized`);
2141
2191
  for (const cfg of detection.project_mcp) {
2142
- console.log(`${cfg.present ? ui.green("\u2713") : ui.yellow("\u2022")} ${cfg.client} project MCP ${ui.dim(path9.relative(detection.root, cfg.path))}`);
2192
+ console.log(`${cfg.present ? ui.green("\u2713") : ui.yellow("\u2022")} ${cfg.client} project MCP ${ui.dim(path10.relative(detection.root, cfg.path))}`);
2143
2193
  }
2144
2194
  for (const agent of detection.installed_agents) {
2145
2195
  const marker = agent.installed ? ui.green("\u2713") : ui.dim("\u2022");
@@ -2168,8 +2218,8 @@ function printSetupResult(result) {
2168
2218
 
2169
2219
  // src/commands/init-bootstrap.ts
2170
2220
  import { readdir, readFile as readFile5 } from "fs/promises";
2171
- import { existsSync as existsSync9, readdirSync } from "fs";
2172
- import path10 from "path";
2221
+ import { existsSync as existsSync10, readdirSync as readdirSync3 } from "fs";
2222
+ import path11 from "path";
2173
2223
  var IGNORE_DIRS = /* @__PURE__ */ new Set([
2174
2224
  "node_modules",
2175
2225
  "dist",
@@ -2255,12 +2305,12 @@ function detectKeyDeps(allDeps) {
2255
2305
  return KEY_DEPS.filter((d) => allDeps[d] !== void 0);
2256
2306
  }
2257
2307
  function detectLanguage(root) {
2258
- if (existsSync9(path10.join(root, "tsconfig.json"))) return "TypeScript";
2259
- if (existsSync9(path10.join(root, "pyproject.toml")) || existsSync9(path10.join(root, "setup.py"))) return "Python";
2260
- if (existsSync9(path10.join(root, "go.mod"))) return "Go";
2261
- if (existsSync9(path10.join(root, "pom.xml")) || existsSync9(path10.join(root, "build.gradle"))) return "Java/Kotlin";
2262
- if (existsSync9(path10.join(root, "Cargo.toml"))) return "Rust";
2263
- if (existsSync9(path10.join(root, "package.json"))) {
2308
+ if (existsSync10(path11.join(root, "tsconfig.json"))) return "TypeScript";
2309
+ if (existsSync10(path11.join(root, "pyproject.toml")) || existsSync10(path11.join(root, "setup.py"))) return "Python";
2310
+ if (existsSync10(path11.join(root, "go.mod"))) return "Go";
2311
+ if (existsSync10(path11.join(root, "pom.xml")) || existsSync10(path11.join(root, "build.gradle"))) return "Java/Kotlin";
2312
+ if (existsSync10(path11.join(root, "Cargo.toml"))) return "Rust";
2313
+ if (existsSync10(path11.join(root, "package.json"))) {
2264
2314
  return hasSourceWithExt(root, [".ts", ".tsx", ".mts", ".cts"]) ? "TypeScript" : "JavaScript";
2265
2315
  }
2266
2316
  return "Unknown";
@@ -2270,7 +2320,7 @@ function hasSourceWithExt(root, exts) {
2270
2320
  const scanDir = (dir, depth) => {
2271
2321
  let entries;
2272
2322
  try {
2273
- entries = readdirSync(dir, { withFileTypes: true });
2323
+ entries = readdirSync3(dir, { withFileTypes: true });
2274
2324
  } catch {
2275
2325
  return false;
2276
2326
  }
@@ -2280,7 +2330,7 @@ function hasSourceWithExt(root, exts) {
2280
2330
  if (depth <= 0) return false;
2281
2331
  for (const entry of entries) {
2282
2332
  if (entry.isDirectory() && !IGNORE_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
2283
- if (scanDir(path10.join(dir, entry.name), depth - 1)) return true;
2333
+ if (scanDir(path11.join(dir, entry.name), depth - 1)) return true;
2284
2334
  }
2285
2335
  }
2286
2336
  return false;
@@ -2301,7 +2351,7 @@ function detectProjectType(frameworks, scripts, isMonorepo) {
2301
2351
  if (frameworks.includes("Express") || frameworks.includes("Fastify") || frameworks.includes("Hono")) return "Backend API";
2302
2352
  if (frameworks.includes("React") || frameworks.includes("Vue") || frameworks.includes("Svelte")) return "Frontend SPA";
2303
2353
  if (scripts["build"] && !scripts["dev"]) return "CLI tool / library";
2304
- if (existsSync9("pom.xml")) return "Java backend";
2354
+ if (existsSync10("pom.xml")) return "Java backend";
2305
2355
  return "Application";
2306
2356
  }
2307
2357
  async function scanDirs(root, maxDepth = 2) {
@@ -2317,9 +2367,9 @@ async function scanDirs(root, maxDepth = 2) {
2317
2367
  for (const entry of entries) {
2318
2368
  if (!entry.isDirectory()) continue;
2319
2369
  if (IGNORE_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
2320
- const rel = path10.relative(root, path10.join(dir, entry.name));
2370
+ const rel = path11.relative(root, path11.join(dir, entry.name));
2321
2371
  results.push(rel);
2322
- await walk(path10.join(dir, entry.name), depth + 1);
2372
+ await walk(path11.join(dir, entry.name), depth + 1);
2323
2373
  }
2324
2374
  }
2325
2375
  await walk(root, 0);
@@ -2436,8 +2486,8 @@ function readmeExcerpt(readme) {
2436
2486
  }
2437
2487
  async function generateBootstrapContext(root) {
2438
2488
  let pkg = {};
2439
- const pkgPath = path10.join(root, "package.json");
2440
- if (existsSync9(pkgPath)) {
2489
+ const pkgPath = path11.join(root, "package.json");
2490
+ if (existsSync10(pkgPath)) {
2441
2491
  try {
2442
2492
  pkg = JSON.parse(await readFile5(pkgPath, "utf8"));
2443
2493
  } catch {
@@ -2449,18 +2499,15 @@ async function generateBootstrapContext(root) {
2449
2499
  const language = detectLanguage(root);
2450
2500
  const isMonorepo = pkg.workspaces !== void 0 && (Array.isArray(pkg.workspaces) ? pkg.workspaces.length > 0 : true);
2451
2501
  const projectType = detectProjectType(frameworks, pkg.scripts ?? {}, isMonorepo);
2452
- const projectName = pkg.name ?? path10.basename(root);
2502
+ const projectName = pkg.name ?? path11.basename(root);
2453
2503
  const projectDesc = pkg.description ?? "";
2454
2504
  let readmeSummary = "";
2455
- for (const name of ["README.md", "readme.md", "README"]) {
2456
- const p = path10.join(root, name);
2457
- if (existsSync9(p)) {
2458
- try {
2459
- const content = await readFile5(p, "utf8");
2460
- readmeSummary = readmeExcerpt(content);
2461
- break;
2462
- } catch {
2463
- }
2505
+ const readmeName = findDocFile(root, "readme");
2506
+ if (readmeName) {
2507
+ try {
2508
+ const content = await readFile5(path11.join(root, readmeName), "utf8");
2509
+ readmeSummary = readmeExcerpt(content);
2510
+ } catch {
2464
2511
  }
2465
2512
  }
2466
2513
  const dirs = await scanDirs(root, 2);
@@ -2513,7 +2560,7 @@ async function generateBootstrapContext(root) {
2513
2560
  "",
2514
2561
  `## Gotchas`,
2515
2562
  `TODO \u2014 known traps, surprising behavior, things newcomers stub their toes on.`,
2516
- `(Run \`hivelore memory import-changelog\` or \`hivelore memory import README.md\` to seed these automatically.)`,
2563
+ `(Seed these with \`hivelore memory import --from ${findDocFile(root, "changelog") ?? "CHANGELOG.md"} --changelog\` or \`hivelore memory import --from ${findDocFile(root, "readme") ?? "README.md"}\` via your AI client.)`,
2517
2564
  ""
2518
2565
  ];
2519
2566
  return lines.join("\n");
@@ -2521,8 +2568,8 @@ async function generateBootstrapContext(root) {
2521
2568
 
2522
2569
  // src/commands/init-stack-packs.ts
2523
2570
  import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
2524
- import { existsSync as existsSync10 } from "fs";
2525
- import path11 from "path";
2571
+ import { existsSync as existsSync11 } from "fs";
2572
+ import path12 from "path";
2526
2573
  import {
2527
2574
  buildFrontmatter,
2528
2575
  loadMemoriesFromDir as loadMemoriesFromDir6,
@@ -3626,7 +3673,7 @@ async function seedStackPack(haivePaths, stack) {
3626
3673
  const existingTopics = /* @__PURE__ */ new Set();
3627
3674
  const existingSignatures = /* @__PURE__ */ new Set();
3628
3675
  const handWrittenSlugs = [];
3629
- if (existsSync10(haivePaths.memoriesDir)) {
3676
+ if (existsSync11(haivePaths.memoriesDir)) {
3630
3677
  for (const { memory: memory2 } of await loadMemoriesFromDir6(haivePaths.memoriesDir)) {
3631
3678
  if (memory2.frontmatter.topic) existingTopics.add(memory2.frontmatter.topic);
3632
3679
  existingSignatures.add(memory2.frontmatter.id.replace(DATE_PREFIX, ""));
@@ -3671,7 +3718,7 @@ async function seedStackPack(haivePaths, stack) {
3671
3718
  ...sensor ? { sensor } : {}
3672
3719
  });
3673
3720
  const filePath = memoryFilePath(haivePaths, "team", fm.id);
3674
- if (existsSync10(filePath)) continue;
3721
+ if (existsSync11(filePath)) continue;
3675
3722
  const ruleSlug = combinedSlug.startsWith(`${stack}-`) ? combinedSlug.slice(stack.length + 1) : combinedSlug;
3676
3723
  const titleCase = (s) => s.split("-").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
3677
3724
  const heading = `${titleCase(stack)}: ${titleCase(ruleSlug)}`;
@@ -3681,7 +3728,7 @@ ${mem.body}`;
3681
3728
  const content = serializeMemory2({ frontmatter: fm, body: `${titledBody}
3682
3729
 
3683
3730
  ${SEED_FOOTER(stack)}` });
3684
- await mkdir5(path11.dirname(filePath), { recursive: true });
3731
+ await mkdir5(path12.dirname(filePath), { recursive: true });
3685
3732
  await writeFile6(filePath, content, "utf8");
3686
3733
  existingTopics.add(topic);
3687
3734
  existingSignatures.add(signature);
@@ -3708,7 +3755,7 @@ ${SEED_FOOTER(stack)}` });
3708
3755
 
3709
3756
  // src/commands/init.ts
3710
3757
  var execFileAsync = promisify2(execFile2);
3711
- var HAIVE_GITHUB_ACTION_REF = `v${"0.33.0"}`;
3758
+ var HAIVE_GITHUB_ACTION_REF = `v${"0.34.1"}`;
3712
3759
  var PROJECT_CONTEXT_TEMPLATE = `# Project context
3713
3760
 
3714
3761
  > Generated by \`hivelore init\`. Run \`hivelore init --bootstrap\` to auto-fill from your codebase,
@@ -3901,9 +3948,9 @@ function registerInit(program2) {
3901
3948
  "Initialize a Hivelore project \u2014 autopilot mode ON by default (zero human intervention).\n Auto-bootstraps project-context.md from local files and seeds detected stack packs.\n Seeds draft memories from git revert/hotfix history (--seed, on by default).\n Add --manual to control memory approval and session recaps yourself.\n Add --no-bootstrap and --stack none to disable the auto-features."
3902
3949
  ).option("-d, --dir <dir>", "project root", process.cwd()).option("--no-bridges", "do not generate any native agent bridge files").option(
3903
3950
  "--bridge-targets <list>",
3904
- `which agent bridges to generate: 'all' (default) | comma-list.
3905
- Available: ${BRIDGE_TARGETS.join(", ")}. Each carries top memories + block sensors.`,
3906
- "all"
3951
+ `which agent bridges to generate: 'auto' (default \u2014 clients detected on this machine/repo, plus AGENTS.md) | 'all' | comma-list.
3952
+ Available: ${BRIDGE_TARGETS2.join(", ")}. Each carries top memories + block sensors.`,
3953
+ "auto"
3907
3954
  ).option("--with-ci", "write a GitHub Actions workflow (.github/workflows/haive-sync.yml) \u2014 included automatically in autopilot mode").option(
3908
3955
  "--manual",
3909
3956
  "opt out of autopilot: memories require manual approval, no auto-session recap, no auto-context"
@@ -3936,7 +3983,7 @@ function registerInit(program2) {
3936
3983
  "approve user-level AI client configuration prompts during agent setup",
3937
3984
  false
3938
3985
  ).option("--json", "emit a machine-readable summary on stdout (human logs go to stderr)", false).action(async (opts) => {
3939
- const root = path12.resolve(opts.dir);
3986
+ const root = path13.resolve(opts.dir);
3940
3987
  const paths = resolveHaivePaths6(root);
3941
3988
  const autopilot = opts.manual !== true;
3942
3989
  const json = opts.json === true;
@@ -3953,9 +4000,10 @@ function registerInit(program2) {
3953
4000
  gitCommitsScanned: 0,
3954
4001
  gitRevertsFound: 0,
3955
4002
  gitRecurring: 0,
3956
- bridgesWritten: 0
4003
+ bridgesWritten: 0,
4004
+ bridgeTargets: []
3957
4005
  };
3958
- if (existsSync11(paths.haiveDir)) {
4006
+ if (existsSync12(paths.haiveDir)) {
3959
4007
  ui.warn(`.ai/ already exists at ${paths.haiveDir} \u2014 leaving existing files in place.`);
3960
4008
  }
3961
4009
  await mkdir6(paths.personalDir, { recursive: true });
@@ -3963,8 +4011,8 @@ function registerInit(program2) {
3963
4011
  await mkdir6(paths.moduleDir, { recursive: true });
3964
4012
  await mkdir6(paths.modulesContextDir, { recursive: true });
3965
4013
  await ensureAiRuntimeLayout(paths.runtimeDir);
3966
- await ensureAiCacheLayout(path12.join(paths.haiveDir, ".cache"));
3967
- if (!existsSync11(paths.projectContext)) {
4014
+ await ensureAiCacheLayout(path13.join(paths.haiveDir, ".cache"));
4015
+ if (!existsSync12(paths.projectContext)) {
3968
4016
  if (wantBootstrap) {
3969
4017
  ui.info("Bootstrapping project context from local files\u2026");
3970
4018
  try {
@@ -3977,11 +4025,11 @@ function registerInit(program2) {
3977
4025
  }
3978
4026
  } else {
3979
4027
  await writeFile7(paths.projectContext, PROJECT_CONTEXT_TEMPLATE, "utf8");
3980
- ui.success(`Created ${path12.relative(root, paths.projectContext)}`);
4028
+ ui.success(`Created ${path13.relative(root, paths.projectContext)}`);
3981
4029
  }
3982
4030
  }
3983
- const configExists = existsSync11(
3984
- path12.join(paths.haiveDir, "haive.config.json")
4031
+ const configExists = existsSync12(
4032
+ path13.join(paths.haiveDir, "haive.config.json")
3985
4033
  );
3986
4034
  if (!configExists) {
3987
4035
  await saveConfig2(paths, autopilot ? AUTOPILOT_DEFAULTS2 : { autopilot: false });
@@ -4031,11 +4079,14 @@ function registerInit(program2) {
4031
4079
  }
4032
4080
  }
4033
4081
  if (opts.bridges) {
4034
- const targets = resolveBridgeTargets(opts.bridgeTargets);
4082
+ const targets = resolveBridgeTargets(opts.bridgeTargets, root);
4035
4083
  const res = await writeBridgeFiles(root, paths, { targets });
4036
- await writeCursorHaiveRule(root);
4084
+ if (targets.includes("cursor")) {
4085
+ await writeCursorHaiveRule(root);
4086
+ }
4037
4087
  const made = res.created.length + res.updated.length;
4038
4088
  report.bridgesWritten = made;
4089
+ report.bridgeTargets = targets;
4039
4090
  if (res.created.length > 0) {
4040
4091
  ui.success(`Generated ${res.created.length} agent bridge(s): ${res.created.join(", ")}`);
4041
4092
  }
@@ -4048,13 +4099,13 @@ function registerInit(program2) {
4048
4099
  }
4049
4100
  const wantCi = opts.withCi || autopilot;
4050
4101
  if (wantCi) {
4051
- const ciPath = path12.join(root, ".github", "workflows", "haive-sync.yml");
4052
- if (existsSync11(ciPath)) {
4102
+ const ciPath = path13.join(root, ".github", "workflows", "haive-sync.yml");
4103
+ if (existsSync12(ciPath)) {
4053
4104
  ui.info("CI workflow already exists \u2014 skipped");
4054
4105
  } else {
4055
- await mkdir6(path12.dirname(ciPath), { recursive: true });
4106
+ await mkdir6(path13.dirname(ciPath), { recursive: true });
4056
4107
  await writeFile7(ciPath, CI_WORKFLOW, "utf8");
4057
- ui.success(`Created ${path12.relative(root, ciPath)}`);
4108
+ ui.success(`Created ${path13.relative(root, ciPath)}`);
4058
4109
  }
4059
4110
  }
4060
4111
  if (autopilot) {
@@ -4094,7 +4145,7 @@ function registerInit(program2) {
4094
4145
  interactive: process.stdin.isTTY
4095
4146
  });
4096
4147
  for (const r of agentSetup.project_results) {
4097
- if (r.status === "configured" && r.path) ui.success(`hivelore MCP project config written (${path12.relative(root, r.path)})`);
4148
+ if (r.status === "configured" && r.path) ui.success(`hivelore MCP project config written (${path13.relative(root, r.path)})`);
4098
4149
  else if (r.status === "error") ui.warn(`${r.client}: ${r.error}`);
4099
4150
  }
4100
4151
  for (const r of agentSetup.global_results) {
@@ -4160,10 +4211,18 @@ function registerInit(program2) {
4160
4211
  console.log(ui.dim(" Review .ai/project-context.md and fill in the TODO sections."));
4161
4212
  console.log(ui.dim(" Or invoke the MCP prompt `bootstrap_project` for a richer AI-generated version."));
4162
4213
  }
4163
- console.log();
4164
- console.log(ui.dim(" Seed more memories instantly:"));
4165
- console.log(ui.dim(" hivelore memory import-changelog \u2014 from CHANGELOG.md"));
4166
- console.log(ui.dim(" hivelore memory import README.md \u2014 from README / docs"));
4214
+ const changelogFile = findDocFile(root, "changelog");
4215
+ const readmeFile = findDocFile(root, "readme");
4216
+ if (changelogFile || readmeFile) {
4217
+ console.log();
4218
+ console.log(ui.dim(" Seed more memories:"));
4219
+ if (changelogFile) {
4220
+ console.log(ui.dim(` hivelore memory import --from ${changelogFile} --changelog \u2014 extract breaking-change gotchas (no AI needed)`));
4221
+ }
4222
+ if (readmeFile) {
4223
+ console.log(ui.dim(` hivelore memory import --from ${readmeFile} \u2014 prepare an import prompt for your AI client`));
4224
+ }
4225
+ }
4167
4226
  } else {
4168
4227
  console.log(ui.bold("Next steps:"));
4169
4228
  if (!wantBootstrap) {
@@ -4189,7 +4248,42 @@ async function resolveStacksToSeed(root, stackOpt) {
4189
4248
  return stackOpt.split(",").map((s) => s.trim().toLowerCase()).filter(isValidStack);
4190
4249
  }
4191
4250
  async function collectNestedPackageDeps(root) {
4192
- const SKIP = /* @__PURE__ */ new Set(["node_modules", "dist", "build", "out", ".git", ".next", "coverage", "vendor"]);
4251
+ const SKIP = /* @__PURE__ */ new Set([
4252
+ "node_modules",
4253
+ "dist",
4254
+ "build",
4255
+ "out",
4256
+ ".git",
4257
+ ".next",
4258
+ "coverage",
4259
+ "vendor",
4260
+ // Fixture/demo trees describe what the project TESTS AGAINST, not what it is built with.
4261
+ // Vite's playground/ pulls react+vue+tailwind+express into detection and seeds four
4262
+ // irrelevant stack packs on a build-tool repo.
4263
+ "playground",
4264
+ "playgrounds",
4265
+ "example",
4266
+ "examples",
4267
+ "fixtures",
4268
+ "__fixtures__",
4269
+ "e2e",
4270
+ "test",
4271
+ "tests",
4272
+ "demo",
4273
+ "demos",
4274
+ "template",
4275
+ "templates",
4276
+ "bench",
4277
+ "benchmarks",
4278
+ "samples",
4279
+ "sandbox",
4280
+ // Doc sites are built with their own framework (VitePress→vue, Docusaurus→react) — that is
4281
+ // the DOCS' stack, not the product's.
4282
+ "docs",
4283
+ "doc",
4284
+ "website"
4285
+ ]);
4286
+ const SKIP_PREFIX = /^(template|example|fixture|demo|sample)s?-/;
4193
4287
  const merged = {};
4194
4288
  let found = false;
4195
4289
  async function scan(dir, depth) {
@@ -4201,10 +4295,10 @@ async function collectNestedPackageDeps(root) {
4201
4295
  return;
4202
4296
  }
4203
4297
  for (const entry of entries) {
4204
- if (!entry.isDirectory() || entry.name.startsWith(".") || SKIP.has(entry.name)) continue;
4205
- const sub = path12.join(dir, entry.name);
4206
- const pkgPath = path12.join(sub, "package.json");
4207
- if (existsSync11(pkgPath)) {
4298
+ if (!entry.isDirectory() || entry.name.startsWith(".") || SKIP.has(entry.name) || SKIP_PREFIX.test(entry.name)) continue;
4299
+ const sub = path13.join(dir, entry.name);
4300
+ const pkgPath = path13.join(sub, "package.json");
4301
+ if (existsSync12(pkgPath)) {
4208
4302
  try {
4209
4303
  const pkg = JSON.parse(await readFile6(pkgPath, "utf8"));
4210
4304
  Object.assign(merged, pkg.dependencies ?? {}, pkg.devDependencies ?? {});
@@ -4223,8 +4317,8 @@ async function autoDetectStacksFromRoot(root) {
4223
4317
  let requirementsTxt;
4224
4318
  let goMod;
4225
4319
  let pomXml;
4226
- const pkgPath = path12.join(root, "package.json");
4227
- if (existsSync11(pkgPath)) {
4320
+ const pkgPath = path13.join(root, "package.json");
4321
+ if (existsSync12(pkgPath)) {
4228
4322
  try {
4229
4323
  const pkg = JSON.parse(await readFile6(pkgPath, "utf8"));
4230
4324
  packageJsonDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
@@ -4234,8 +4328,8 @@ async function autoDetectStacksFromRoot(root) {
4234
4328
  const nestedDeps = await collectNestedPackageDeps(root);
4235
4329
  if (nestedDeps) packageJsonDeps = { ...packageJsonDeps ?? {}, ...nestedDeps };
4236
4330
  for (const name of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
4237
- const reqPath = path12.join(root, name);
4238
- if (existsSync11(reqPath)) {
4331
+ const reqPath = path13.join(root, name);
4332
+ if (existsSync12(reqPath)) {
4239
4333
  try {
4240
4334
  requirementsTxt = await readFile6(reqPath, "utf8");
4241
4335
  break;
@@ -4243,39 +4337,39 @@ async function autoDetectStacksFromRoot(root) {
4243
4337
  }
4244
4338
  }
4245
4339
  }
4246
- const goModPath = path12.join(root, "go.mod");
4247
- if (existsSync11(goModPath)) {
4340
+ const goModPath = path13.join(root, "go.mod");
4341
+ if (existsSync12(goModPath)) {
4248
4342
  try {
4249
4343
  goMod = await readFile6(goModPath, "utf8");
4250
4344
  } catch {
4251
4345
  }
4252
4346
  }
4253
- const pomPath = path12.join(root, "pom.xml");
4254
- if (existsSync11(pomPath)) {
4347
+ const pomPath = path13.join(root, "pom.xml");
4348
+ if (existsSync12(pomPath)) {
4255
4349
  try {
4256
4350
  pomXml = await readFile6(pomPath, "utf8");
4257
4351
  } catch {
4258
4352
  }
4259
4353
  }
4260
4354
  let composerJson;
4261
- const composerPath = path12.join(root, "composer.json");
4262
- if (existsSync11(composerPath)) {
4355
+ const composerPath = path13.join(root, "composer.json");
4356
+ if (existsSync12(composerPath)) {
4263
4357
  try {
4264
4358
  composerJson = await readFile6(composerPath, "utf8");
4265
4359
  } catch {
4266
4360
  }
4267
4361
  }
4268
4362
  let gemfile;
4269
- const gemfilePath = path12.join(root, "Gemfile");
4270
- if (existsSync11(gemfilePath)) {
4363
+ const gemfilePath = path13.join(root, "Gemfile");
4364
+ if (existsSync12(gemfilePath)) {
4271
4365
  try {
4272
4366
  gemfile = await readFile6(gemfilePath, "utf8");
4273
4367
  } catch {
4274
4368
  }
4275
4369
  }
4276
- const hasDockerfile = existsSync11(path12.join(root, "Dockerfile"));
4277
- const hasTurboJson = existsSync11(path12.join(root, "turbo.json"));
4278
- const hasNxJson = existsSync11(path12.join(root, "nx.json"));
4370
+ const hasDockerfile = existsSync12(path13.join(root, "Dockerfile"));
4371
+ const hasTurboJson = existsSync12(path13.join(root, "turbo.json"));
4372
+ const hasNxJson = existsSync12(path13.join(root, "nx.json"));
4279
4373
  let hasCsproj = false;
4280
4374
  try {
4281
4375
  const entries = await readdir2(root);
@@ -4327,8 +4421,8 @@ async function seedFromGitHistory(root, paths, limit) {
4327
4421
  _Seeded from git ${p.kind} commit ${p.source_sha}. Review and validate (or delete) \u2014 not yet authoritative._
4328
4422
  `;
4329
4423
  const file = memoryFilePath2(paths, fm.scope, fm.id, fm.module);
4330
- if (existsSync11(file)) continue;
4331
- await mkdir6(path12.dirname(file), { recursive: true });
4424
+ if (existsSync12(file)) continue;
4425
+ await mkdir6(path13.dirname(file), { recursive: true });
4332
4426
  await writeFile7(file, serializeMemory3({ frontmatter: fm, body }), "utf8");
4333
4427
  written++;
4334
4428
  }
@@ -4369,7 +4463,7 @@ function printInitReport(r) {
4369
4463
  lines.push(` Total ready : ${r.totalMemories} lesson(s), ${r.totalSensors} sensor(s) \u2014 0 written by hand`);
4370
4464
  }
4371
4465
  if (r.bridgesWritten > 0) {
4372
- lines.push(` Reach : ${r.bridgesWritten} agent bridge(s) generated (Cursor, Cline, Copilot, Roo, Gemini, \u2026)`);
4466
+ lines.push(` Reach : ${r.bridgesWritten} agent bridge(s) generated (${r.bridgeTargets.join(", ")})`);
4373
4467
  }
4374
4468
  if (lines.length === 0) return;
4375
4469
  const width = Math.max(...lines.map((l) => l.length), 44);
@@ -4390,33 +4484,37 @@ function printInitReport(r) {
4390
4484
  }
4391
4485
  async function writeCursorHaiveRule(root) {
4392
4486
  const relPath = ".cursor/rules/haive-mcp-required.mdc";
4393
- const target = path12.join(root, relPath);
4394
- if (existsSync11(target)) {
4487
+ const target = path13.join(root, relPath);
4488
+ if (existsSync12(target)) {
4395
4489
  ui.info(`Cursor rule ${relPath} already exists \u2014 skipped`);
4396
4490
  return;
4397
4491
  }
4398
- await mkdir6(path12.dirname(target), { recursive: true });
4492
+ await mkdir6(path13.dirname(target), { recursive: true });
4399
4493
  await writeFile7(target, CURSOR_HAIVE_RULE_MDC, "utf8");
4400
4494
  ui.success(`Created Cursor rule ${relPath}`);
4401
4495
  }
4402
- function resolveBridgeTargets(opt) {
4403
- const raw = (opt ?? "all").trim().toLowerCase();
4404
- if (raw === "" || raw === "all") return [...BRIDGE_TARGETS];
4496
+ function resolveBridgeTargets(opt, root) {
4497
+ const raw = (opt ?? "auto").trim().toLowerCase();
4498
+ if (raw === "all") return [...BRIDGE_TARGETS2];
4499
+ if (raw === "" || raw === "auto") {
4500
+ const detection = detectBridgeTargets(root);
4501
+ const named = detection.targets.map((t) => detection.reasons[t] === "repo file" ? `${t} (already in repo)` : t).join(", ");
4502
+ ui.info(`Bridge targets (detected): ${named} \u2014 pass --bridge-targets all for every supported client`);
4503
+ return detection.targets;
4504
+ }
4405
4505
  const requested = raw.split(",").map((t) => t.trim()).filter(Boolean);
4406
- const valid = requested.filter((t) => BRIDGE_TARGETS.includes(t));
4407
- const invalid = requested.filter((t) => !BRIDGE_TARGETS.includes(t));
4506
+ const valid = requested.filter((t) => BRIDGE_TARGETS2.includes(t));
4507
+ const invalid = requested.filter((t) => !BRIDGE_TARGETS2.includes(t));
4408
4508
  if (invalid.length > 0) {
4409
- ui.warn(`Ignoring unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS.join(", ")}`);
4509
+ ui.warn(`Ignoring unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS2.join(", ")}`);
4410
4510
  }
4411
- return valid.length > 0 ? valid : [...BRIDGE_TARGETS];
4511
+ return valid.length > 0 ? valid : [...BRIDGE_TARGETS2];
4412
4512
  }
4413
4513
  var RUNTIME_README_BODY = `# .ai/.runtime \u2014 disposable local layer
4414
4514
 
4415
4515
  Not team truth. Use for machine-local session notes or tooling scratch files.
4416
4516
  Official memories belong in .ai/memories/ (versioned in Git).
4417
4517
  Only .gitignore and this README are meant to commit; everything else stays untracked.
4418
-
4419
- Session continuity (local): agents may append \`session-journal.ndjson\` via MCP \`runtime_journal_append\` or \`hivelore runtime journal append\`.
4420
4518
  `;
4421
4519
  var RUNTIME_GITIGNORE_BODY = `*
4422
4520
  !.gitignore
@@ -4424,27 +4522,27 @@ var RUNTIME_GITIGNORE_BODY = `*
4424
4522
  `;
4425
4523
  async function ensureAiRuntimeLayout(runtimeDir) {
4426
4524
  await mkdir6(runtimeDir, { recursive: true });
4427
- const gi = path12.join(runtimeDir, ".gitignore");
4428
- if (!existsSync11(gi)) {
4525
+ const gi = path13.join(runtimeDir, ".gitignore");
4526
+ if (!existsSync12(gi)) {
4429
4527
  await writeFile7(gi, RUNTIME_GITIGNORE_BODY, "utf8");
4430
4528
  }
4431
- const readme = path12.join(runtimeDir, "README.md");
4432
- if (!existsSync11(readme)) {
4529
+ const readme = path13.join(runtimeDir, "README.md");
4530
+ if (!existsSync12(readme)) {
4433
4531
  await writeFile7(readme, RUNTIME_README_BODY, "utf8");
4434
4532
  }
4435
4533
  }
4436
4534
  async function ensureAiCacheLayout(cacheDir) {
4437
4535
  await mkdir6(cacheDir, { recursive: true });
4438
- const gi = path12.join(cacheDir, ".gitignore");
4439
- if (!existsSync11(gi)) {
4536
+ const gi = path13.join(cacheDir, ".gitignore");
4537
+ if (!existsSync12(gi)) {
4440
4538
  await writeFile7(gi, "*\n!.gitignore\n", "utf8");
4441
4539
  }
4442
4540
  }
4443
4541
  async function ensureGitignoreEntries(root, patterns) {
4444
4542
  try {
4445
- const gitignorePath = path12.join(root, ".gitignore");
4543
+ const gitignorePath = path13.join(root, ".gitignore");
4446
4544
  let existing = "";
4447
- if (existsSync11(gitignorePath)) {
4545
+ if (existsSync12(gitignorePath)) {
4448
4546
  existing = await readFile6(gitignorePath, "utf8");
4449
4547
  }
4450
4548
  const lines = existing.split("\n");
@@ -4458,8 +4556,8 @@ async function ensureGitignoreEntries(root, patterns) {
4458
4556
 
4459
4557
  // src/commands/observe.ts
4460
4558
  import { appendFile, mkdir as mkdir7 } from "fs/promises";
4461
- import { existsSync as existsSync12 } from "fs";
4462
- import path13 from "path";
4559
+ import { existsSync as existsSync13 } from "fs";
4560
+ import path14 from "path";
4463
4561
  import "commander";
4464
4562
  import { findProjectRoot as findProjectRoot7, resolveHaivePaths as resolveHaivePaths7 } from "@hivelore/core";
4465
4563
  var MAX_STDIN_BYTES = 256 * 1024;
@@ -4566,7 +4664,7 @@ function registerObserve(program2) {
4566
4664
  })();
4567
4665
  if (!root) return;
4568
4666
  const paths = resolveHaivePaths7(root);
4569
- if (!existsSync12(paths.haiveDir)) return;
4667
+ if (!existsSync13(paths.haiveDir)) return;
4570
4668
  const failureHint = detectFailure(payload);
4571
4669
  const observation = {
4572
4670
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -4577,10 +4675,10 @@ function registerObserve(program2) {
4577
4675
  files: extractFiles(payload),
4578
4676
  ...failureHint ? { failure_hint: true } : {}
4579
4677
  };
4580
- const cacheDir = path13.join(paths.haiveDir, ".cache");
4678
+ const cacheDir = path14.join(paths.haiveDir, ".cache");
4581
4679
  await mkdir7(cacheDir, { recursive: true });
4582
4680
  await appendFile(
4583
- path13.join(cacheDir, "observations.jsonl"),
4681
+ path14.join(cacheDir, "observations.jsonl"),
4584
4682
  JSON.stringify(observation) + "\n",
4585
4683
  "utf8"
4586
4684
  );
@@ -4611,8 +4709,8 @@ function registerMcp(program2) {
4611
4709
  // src/commands/sync.ts
4612
4710
  import { spawnSync as spawnSync4 } from "child_process";
4613
4711
  import { readFile as readFile7, writeFile as writeFile8, mkdir as mkdir8 } from "fs/promises";
4614
- import { existsSync as existsSync13 } from "fs";
4615
- import path14 from "path";
4712
+ import { existsSync as existsSync14 } from "fs";
4713
+ import path15 from "path";
4616
4714
  import "commander";
4617
4715
  import {
4618
4716
  DEFAULT_AUTO_PROMOTE_RULE,
@@ -4634,7 +4732,7 @@ import {
4634
4732
  verifyAnchor,
4635
4733
  watchContracts
4636
4734
  } from "@hivelore/core";
4637
- import { BRIDGE_TARGETS as BRIDGE_TARGETS2 } from "@hivelore/core";
4735
+ import { BRIDGE_TARGETS as BRIDGE_TARGETS3 } from "@hivelore/core";
4638
4736
  var BRIDGE_START = "<!-- haive:memories-start -->";
4639
4737
  var BRIDGE_END = "<!-- haive:memories-end -->";
4640
4738
  function registerSync(program2) {
@@ -4649,7 +4747,7 @@ function registerSync(program2) {
4649
4747
  ).option("--bridge-file <path>", "bridge file to inject into (default: CLAUDE.md)").option("--bridge-max-memories <n>", "max memories to inject into bridge file", "5").option("--embed", "rebuild embeddings index after sync (requires @haive/embeddings)").option("--no-cross-repo", "skip cross-repo memory pull even if crossRepoSources is configured").option("--no-deps", "skip dependency version tracking").option("--no-contracts", "skip contract file diff checking").option("--no-bridges", "skip auto-refresh of existing native agent bridge files (.cursor/rules, .clinerules, \u2026)").option("--dry-run", "report what would change without writing any files").action(async (opts) => {
4650
4748
  const root = findProjectRoot9(opts.dir);
4651
4749
  const paths = resolveHaivePaths8(root);
4652
- if (!existsSync13(paths.memoriesDir)) {
4750
+ if (!existsSync14(paths.memoriesDir)) {
4653
4751
  if (!opts.quiet) ui.warn(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
4654
4752
  process.exitCode = 1;
4655
4753
  return;
@@ -4805,7 +4903,7 @@ function registerSync(program2) {
4805
4903
  if (opts.injectBridge) {
4806
4904
  const maxInject = Math.max(1, Number(opts.bridgeMaxMemories ?? 5));
4807
4905
  if (opts.bridgeFile) {
4808
- await injectBridge(path14.resolve(opts.bridgeFile), paths.memoriesDir, maxInject, root, opts.quiet);
4906
+ await injectBridge(path15.resolve(opts.bridgeFile), paths.memoriesDir, maxInject, root, opts.quiet);
4809
4907
  } else if (!dryRun) {
4810
4908
  const res = await writeBridgeFiles(root, paths, {
4811
4909
  targets: ["claude", "agents"],
@@ -4834,7 +4932,7 @@ function registerSync(program2) {
4834
4932
  if (opts.noBridges !== true) {
4835
4933
  try {
4836
4934
  const res = await writeBridgeFiles(root, paths, {
4837
- targets: BRIDGE_TARGETS2,
4935
+ targets: BRIDGE_TARGETS3,
4838
4936
  onlyExisting: true,
4839
4937
  dryRun
4840
4938
  });
@@ -4954,10 +5052,10 @@ Wait for **explicit confirmation** before acting.
4954
5052
  topic: `dep-bump-${slugParts}`
4955
5053
  });
4956
5054
  if (!dryRun) {
4957
- const teamDir = path14.join(paths.memoriesDir, "team");
5055
+ const teamDir = path15.join(paths.memoriesDir, "team");
4958
5056
  await mkdir8(teamDir, { recursive: true });
4959
5057
  await writeFile8(
4960
- path14.join(teamDir, `${fm.id}.md`),
5058
+ path15.join(teamDir, `${fm.id}.md`),
4961
5059
  serializeMemory4({ frontmatter: { ...fm, requires_human_approval: true }, body }),
4962
5060
  "utf8"
4963
5061
  );
@@ -5023,10 +5121,10 @@ Wait for **explicit confirmation** before acting.
5023
5121
  topic: `contract-breaking-${diff.contract}`
5024
5122
  });
5025
5123
  if (!dryRun) {
5026
- const teamDir = path14.join(paths.memoriesDir, "team");
5124
+ const teamDir = path15.join(paths.memoriesDir, "team");
5027
5125
  await mkdir8(teamDir, { recursive: true });
5028
5126
  await writeFile8(
5029
- path14.join(teamDir, `${fm.id}.md`),
5127
+ path15.join(teamDir, `${fm.id}.md`),
5030
5128
  serializeMemory4({ frontmatter: { ...fm, requires_human_approval: true }, body }),
5031
5129
  "utf8"
5032
5130
  );
@@ -5117,7 +5215,7 @@ function bridgeSummaryLine(body) {
5117
5215
  return oneLine.length > 140 ? oneLine.slice(0, 137) + "\u2026" : oneLine;
5118
5216
  }
5119
5217
  async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
5120
- if (!existsSync13(memoriesDir)) return;
5218
+ if (!existsSync14(memoriesDir)) return;
5121
5219
  const all = await loadMemoriesFromDir7(memoriesDir);
5122
5220
  const top = all.filter(({ memory: memory2 }) => {
5123
5221
  const s = memory2.frontmatter.status;
@@ -5143,17 +5241,17 @@ async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
5143
5241
  ` + block + `
5144
5242
 
5145
5243
  ${BRIDGE_END}`;
5146
- const fileExists = existsSync13(bridgeFile);
5244
+ const fileExists = existsSync14(bridgeFile);
5147
5245
  let existing = fileExists ? await readFile7(bridgeFile, "utf8") : "";
5148
5246
  existing = existing.replace(/\r\n/g, "\n");
5149
5247
  const startIdx = existing.indexOf(BRIDGE_START);
5150
5248
  const endIdx = existing.indexOf(BRIDGE_END);
5151
5249
  if (startIdx !== -1 && endIdx === -1) {
5152
- ui.warn(`${path14.relative(root, bridgeFile)}: found ${BRIDGE_START} without ${BRIDGE_END}. Fix the file manually before running --inject-bridge.`);
5250
+ ui.warn(`${path15.relative(root, bridgeFile)}: found ${BRIDGE_START} without ${BRIDGE_END}. Fix the file manually before running --inject-bridge.`);
5153
5251
  return;
5154
5252
  }
5155
5253
  if (startIdx === -1 && endIdx !== -1) {
5156
- ui.warn(`${path14.relative(root, bridgeFile)}: found ${BRIDGE_END} without ${BRIDGE_START}. Fix the file manually before running --inject-bridge.`);
5254
+ ui.warn(`${path15.relative(root, bridgeFile)}: found ${BRIDGE_END} without ${BRIDGE_START}. Fix the file manually before running --inject-bridge.`);
5157
5255
  return;
5158
5256
  }
5159
5257
  let updated;
@@ -5161,14 +5259,14 @@ ${BRIDGE_END}`;
5161
5259
  updated = existing.slice(0, startIdx) + injected + existing.slice(endIdx + BRIDGE_END.length);
5162
5260
  } else {
5163
5261
  if (!fileExists && !quiet) {
5164
- ui.info(`Creating ${path14.relative(root, bridgeFile)} with hivelore memory block.`);
5262
+ ui.info(`Creating ${path15.relative(root, bridgeFile)} with hivelore memory block.`);
5165
5263
  }
5166
5264
  updated = existing + (existing.endsWith("\n") ? "" : "\n") + "\n" + injected + "\n";
5167
5265
  }
5168
5266
  await writeFile8(bridgeFile, updated, "utf8");
5169
5267
  if (!quiet) {
5170
5268
  console.log(
5171
- ui.dim(`bridge: injected ${top.length} memor${top.length === 1 ? "y" : "ies"} into ${path14.relative(root, bridgeFile)}`)
5269
+ ui.dim(`bridge: injected ${top.length} memor${top.length === 1 ? "y" : "ies"} into ${path15.relative(root, bridgeFile)}`)
5172
5270
  );
5173
5271
  }
5174
5272
  }
@@ -5194,8 +5292,8 @@ function collectSinceChanges(root, ref) {
5194
5292
  // src/commands/memory-add.ts
5195
5293
  import { createHash } from "crypto";
5196
5294
  import { mkdir as mkdir9, readFile as readFile8, writeFile as writeFile9 } from "fs/promises";
5197
- import { existsSync as existsSync14 } from "fs";
5198
- import path15 from "path";
5295
+ import { existsSync as existsSync15 } from "fs";
5296
+ import path16 from "path";
5199
5297
  import { Option } from "commander";
5200
5298
  import {
5201
5299
  buildFrontmatter as buildFrontmatter4,
@@ -5237,7 +5335,7 @@ function registerMemoryAdd(memory2) {
5237
5335
  if (opts.body === void 0 && opts.content !== void 0) opts.body = opts.content;
5238
5336
  const root = findProjectRoot10(opts.dir);
5239
5337
  const paths = resolveHaivePaths9(root);
5240
- if (!existsSync14(paths.haiveDir)) {
5338
+ if (!existsSync15(paths.haiveDir)) {
5241
5339
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
5242
5340
  process.exitCode = 1;
5243
5341
  return;
@@ -5254,7 +5352,7 @@ function registerMemoryAdd(memory2) {
5254
5352
  const inferredTags = autoTagsEnabled ? inferModulesFromPaths2(anchorPaths) : [];
5255
5353
  const mergedTags = Array.from(/* @__PURE__ */ new Set([...userTags, ...inferredTags]));
5256
5354
  if (anchorPaths.length > 0) {
5257
- const missing = anchorPaths.filter((p) => !existsSync14(path15.resolve(root, p)));
5355
+ const missing = anchorPaths.filter((p) => !existsSync15(path16.resolve(root, p)));
5258
5356
  if (missing.length > 0) {
5259
5357
  ui.warn(`Anchor path${missing.length > 1 ? "s" : ""} not found in project:`);
5260
5358
  for (const p of missing) ui.warn(` \u2717 ${p}`);
@@ -5267,7 +5365,7 @@ function registerMemoryAdd(memory2) {
5267
5365
  const slug = slugify(opts.slug ?? opts.title ?? opts.topic ?? opts.body ?? `${opts.type}-memory`);
5268
5366
  let body;
5269
5367
  if (opts.bodyFile !== void 0) {
5270
- if (!existsSync14(opts.bodyFile)) {
5368
+ if (!existsSync15(opts.bodyFile)) {
5271
5369
  ui.error(`--body-file not found: ${opts.bodyFile}`);
5272
5370
  process.exitCode = 1;
5273
5371
  return;
@@ -5283,7 +5381,7 @@ TODO \u2014 write the memory body.
5283
5381
  `;
5284
5382
  }
5285
5383
  const scope = opts.scope ?? config.defaultScope ?? "personal";
5286
- if (existsSync14(paths.memoriesDir)) {
5384
+ if (existsSync15(paths.memoriesDir)) {
5287
5385
  const incomingHash = createHash("sha256").update(body.trim()).digest("hex").slice(0, 12);
5288
5386
  const allForHash = await loadMemoriesFromDir8(paths.memoriesDir);
5289
5387
  const hashDup = allForHash.find(
@@ -5296,7 +5394,7 @@ TODO \u2014 write the memory body.
5296
5394
  return;
5297
5395
  }
5298
5396
  }
5299
- if (opts.topic && existsSync14(paths.memoriesDir)) {
5397
+ if (opts.topic && existsSync15(paths.memoriesDir)) {
5300
5398
  const existing = await loadMemoriesFromDir8(paths.memoriesDir);
5301
5399
  const topicMatch = existing.find(
5302
5400
  ({ memory: memory3 }) => memory3.frontmatter.topic === opts.topic && memory3.frontmatter.scope === scope && (!opts.module || memory3.frontmatter.module === opts.module)
@@ -5316,7 +5414,7 @@ TODO \u2014 write the memory body.
5316
5414
  }
5317
5415
  };
5318
5416
  await writeFile9(topicMatch.filePath, serializeMemory5({ frontmatter: newFrontmatter, body }), "utf8");
5319
- ui.success(`Updated (topic upsert) ${path15.relative(root, topicMatch.filePath)}`);
5417
+ ui.success(`Updated (topic upsert) ${path16.relative(root, topicMatch.filePath)}`);
5320
5418
  ui.info(`id=${fm.id} revision=${revisionCount}`);
5321
5419
  printSensorLoopHint(opts.type, body, newFrontmatter.anchor.paths, Boolean(newFrontmatter.sensor));
5322
5420
  await runPostMemoryAutopilot(root, paths, config);
@@ -5340,13 +5438,13 @@ TODO \u2014 write the memory body.
5340
5438
  });
5341
5439
  if (frontmatter.status === "validated") frontmatter.validated_by = "auto";
5342
5440
  const file = memoryFilePath3(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
5343
- await mkdir9(path15.dirname(file), { recursive: true });
5344
- if (existsSync14(file)) {
5441
+ await mkdir9(path16.dirname(file), { recursive: true });
5442
+ if (existsSync15(file)) {
5345
5443
  ui.error(`Memory already exists at ${file}`);
5346
5444
  process.exitCode = 1;
5347
5445
  return;
5348
5446
  }
5349
- if (existsSync14(paths.memoriesDir)) {
5447
+ if (existsSync15(paths.memoriesDir)) {
5350
5448
  const existing = await loadMemoriesFromDir8(paths.memoriesDir);
5351
5449
  const slugTokens = slug.toLowerCase().split(/[-_\s]+/).filter(Boolean);
5352
5450
  const similar = existing.filter(({ memory: memory3 }) => {
@@ -5359,7 +5457,7 @@ TODO \u2014 write the memory body.
5359
5457
  }
5360
5458
  }
5361
5459
  await writeFile9(file, serializeMemory5({ frontmatter, body }), "utf8");
5362
- ui.success(`Created ${path15.relative(root, file)}`);
5460
+ ui.success(`Created ${path16.relative(root, file)}`);
5363
5461
  ui.info(`id=${frontmatter.id} scope=${frontmatter.scope} status=${frontmatter.status}`);
5364
5462
  printSensorLoopHint(opts.type, body, anchorPaths, Boolean(frontmatter.sensor));
5365
5463
  await runPostMemoryAutopilot(root, paths, config);
@@ -5453,8 +5551,8 @@ function slugify(value) {
5453
5551
  }
5454
5552
 
5455
5553
  // src/commands/memory-list.ts
5456
- import { existsSync as existsSync15 } from "fs";
5457
- import path16 from "path";
5554
+ import { existsSync as existsSync16 } from "fs";
5555
+ import path17 from "path";
5458
5556
  import "commander";
5459
5557
  import { findProjectRoot as findProjectRoot11, resolveHaivePaths as resolveHaivePaths10 } from "@hivelore/core";
5460
5558
  function registerMemoryList(memory2) {
@@ -5466,7 +5564,7 @@ function registerMemoryList(memory2) {
5466
5564
  }
5467
5565
  const root = findProjectRoot11(opts.dir);
5468
5566
  const paths = resolveHaivePaths10(root);
5469
- if (!existsSync15(paths.memoriesDir)) {
5567
+ if (!existsSync16(paths.memoriesDir)) {
5470
5568
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`hivelore init\` first.`);
5471
5569
  process.exitCode = 1;
5472
5570
  return;
@@ -5505,7 +5603,7 @@ function registerMemoryList(memory2) {
5505
5603
  );
5506
5604
  const title = mem.body.match(/^#\s+(.+)$/m)?.[1]?.trim();
5507
5605
  if (title && title !== fm.id) console.log(` ${title}`);
5508
- console.log(` ${ui.dim(path16.relative(root, filePath))}`);
5606
+ console.log(` ${ui.dim(path17.relative(root, filePath))}`);
5509
5607
  }
5510
5608
  const totalLabel = clipped > 0 ? `
5511
5609
  ${displayed.length} of ${filtered.length} memories shown (use --limit to adjust)` : `
@@ -5543,8 +5641,8 @@ function matchesFilters(loaded, opts) {
5543
5641
 
5544
5642
  // src/commands/memory-promote.ts
5545
5643
  import { mkdir as mkdir10, unlink, writeFile as writeFile10 } from "fs/promises";
5546
- import { existsSync as existsSync16 } from "fs";
5547
- import path17 from "path";
5644
+ import { existsSync as existsSync17 } from "fs";
5645
+ import path18 from "path";
5548
5646
  import "commander";
5549
5647
  import {
5550
5648
  findProjectRoot as findProjectRoot12,
@@ -5556,7 +5654,7 @@ function registerMemoryPromote(memory2) {
5556
5654
  memory2.command("promote <id>").description("Promote a personal memory to team scope (status -> proposed)").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
5557
5655
  const root = findProjectRoot12(opts.dir);
5558
5656
  const paths = resolveHaivePaths11(root);
5559
- if (!existsSync16(paths.memoriesDir)) {
5657
+ if (!existsSync17(paths.memoriesDir)) {
5560
5658
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`hivelore init\` first.`);
5561
5659
  process.exitCode = 1;
5562
5660
  return;
@@ -5591,19 +5689,19 @@ function registerMemoryPromote(memory2) {
5591
5689
  body: found.memory.body
5592
5690
  };
5593
5691
  const newPath = memoryFilePath4(paths, "team", updated.frontmatter.id);
5594
- await mkdir10(path17.dirname(newPath), { recursive: true });
5692
+ await mkdir10(path18.dirname(newPath), { recursive: true });
5595
5693
  await writeFile10(newPath, serializeMemory6(updated), "utf8");
5596
5694
  await unlink(found.filePath);
5597
5695
  ui.success(`Promoted ${id} to team scope (status=proposed)`);
5598
- ui.info(`Now at ${path17.relative(root, newPath)}`);
5696
+ ui.info(`Now at ${path18.relative(root, newPath)}`);
5599
5697
  console.log(ui.dim(`\u2192 next: hivelore memory approve ${id} (validate for team use)`));
5600
5698
  });
5601
5699
  }
5602
5700
 
5603
5701
  // src/commands/memory-approve.ts
5604
- import { existsSync as existsSync17 } from "fs";
5702
+ import { existsSync as existsSync18 } from "fs";
5605
5703
  import { writeFile as writeFile11 } from "fs/promises";
5606
- import path18 from "path";
5704
+ import path19 from "path";
5607
5705
  import "commander";
5608
5706
  import {
5609
5707
  findProjectRoot as findProjectRoot13,
@@ -5614,7 +5712,7 @@ function registerMemoryApprove(memory2) {
5614
5712
  memory2.command("approve [id]").description("Mark a memory as 'validated'. Use --all to bulk-approve all proposed/draft memories.").option("--all", "approve all proposed and draft memories at once").option("--pending", "approve all memories with status 'proposed'").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
5615
5713
  const root = findProjectRoot13(opts.dir);
5616
5714
  const paths = resolveHaivePaths12(root);
5617
- if (!existsSync17(paths.memoriesDir)) {
5715
+ if (!existsSync18(paths.memoriesDir)) {
5618
5716
  ui.error(`No .ai/memories at ${root}.`);
5619
5717
  process.exitCode = 1;
5620
5718
  return;
@@ -5668,15 +5766,15 @@ function registerMemoryApprove(memory2) {
5668
5766
  };
5669
5767
  await writeFile11(found.filePath, serializeMemory7(next), "utf8");
5670
5768
  ui.success(`Approved ${id} (status=validated, by=human)`);
5671
- ui.info(path18.relative(root, found.filePath));
5769
+ ui.info(path19.relative(root, found.filePath));
5672
5770
  });
5673
5771
  }
5674
5772
 
5675
5773
  // src/commands/memory-update.ts
5676
5774
  import { spawn } from "child_process";
5677
5775
  import { readFile as readFile9, writeFile as writeFile12 } from "fs/promises";
5678
- import { existsSync as existsSync18 } from "fs";
5679
- import path19 from "path";
5776
+ import { existsSync as existsSync19 } from "fs";
5777
+ import path20 from "path";
5680
5778
  import "commander";
5681
5779
  import {
5682
5780
  findProjectRoot as findProjectRoot14,
@@ -5689,7 +5787,7 @@ function registerMemoryUpdate(memory2) {
5689
5787
  const root = findProjectRoot14(opts.dir);
5690
5788
  const paths = resolveHaivePaths13(root);
5691
5789
  if (opts.edit) {
5692
- const all = existsSync18(paths.memoriesDir) ? await loadMemoriesFromDir(paths.memoriesDir) : [];
5790
+ const all = existsSync19(paths.memoriesDir) ? await loadMemoriesFromDir(paths.memoriesDir) : [];
5693
5791
  const found = all.find((m) => m.memory.frontmatter.id === id);
5694
5792
  if (!found) {
5695
5793
  ui.error(`No memory with id "${id}".`);
@@ -5697,7 +5795,7 @@ function registerMemoryUpdate(memory2) {
5697
5795
  return;
5698
5796
  }
5699
5797
  const editor = opts.editor ?? process.env.EDITOR ?? process.env.VISUAL ?? "vi";
5700
- ui.info(`Opening ${path19.relative(root, found.filePath)} with ${editor}\u2026`);
5798
+ ui.info(`Opening ${path20.relative(root, found.filePath)} with ${editor}\u2026`);
5701
5799
  const code = await new Promise((resolve) => {
5702
5800
  const child = spawn(editor, [found.filePath], { stdio: "inherit" });
5703
5801
  child.on("exit", (c) => resolve(c ?? 0));
@@ -5714,7 +5812,7 @@ function registerMemoryUpdate(memory2) {
5714
5812
  }
5715
5813
  return;
5716
5814
  }
5717
- if (!existsSync18(paths.memoriesDir)) {
5815
+ if (!existsSync19(paths.memoriesDir)) {
5718
5816
  ui.error(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
5719
5817
  process.exitCode = 1;
5720
5818
  return;
@@ -5756,7 +5854,7 @@ function registerMemoryUpdate(memory2) {
5756
5854
  if (opts.author !== void 0) updated.push("author");
5757
5855
  let newBody;
5758
5856
  if (opts.bodyFile !== void 0) {
5759
- if (!existsSync18(opts.bodyFile)) {
5857
+ if (!existsSync19(opts.bodyFile)) {
5760
5858
  ui.error(`--body-file not found: ${opts.bodyFile}`);
5761
5859
  process.exitCode = 1;
5762
5860
  return;
@@ -5782,7 +5880,7 @@ function registerMemoryUpdate(memory2) {
5782
5880
  serializeMemory8({ frontmatter: newFrontmatter, body: newBody }),
5783
5881
  "utf8"
5784
5882
  );
5785
- ui.success(`Updated ${path19.relative(root, loaded.filePath)}`);
5883
+ ui.success(`Updated ${path20.relative(root, loaded.filePath)}`);
5786
5884
  ui.info(`fields: ${updated.join(", ")}`);
5787
5885
  });
5788
5886
  }
@@ -5801,8 +5899,8 @@ function parseCsv3(value) {
5801
5899
  }
5802
5900
 
5803
5901
  // src/commands/memory-tried.ts
5804
- import { existsSync as existsSync19 } from "fs";
5805
- import path20 from "path";
5902
+ import { existsSync as existsSync20 } from "fs";
5903
+ import path21 from "path";
5806
5904
  import "commander";
5807
5905
  import {
5808
5906
  findProjectRoot as findProjectRoot15,
@@ -5817,7 +5915,7 @@ function registerMemoryTried(memory2) {
5817
5915
  ).requiredOption("--what <text>", "what approach was tried (short, descriptive title)").requiredOption("--why-failed <text>", "why it failed or should NOT be used (include the exact error if possible)").option("--instead <text>", "the correct approach to use instead").option("--scope <scope>", "personal | team | module", "personal").option("--module <name>", "module name (required when scope=module)").option("--tags <csv>", "comma-separated tags").option("--paths <csv>", "anchor paths, comma-separated").option("--files <csv>", "alias for --paths (matches the MCP `files` parameter)").option("--author <author>", "author email or handle").option("--sensor-pattern <regex>", "one-shot: regex matching the FAULTY usage \u2014 validates + attaches a sensor in this call").option("--sensor-command <cmd>", "one-shot BEHAVIOUR sensor: a command (test/script) the gate runs when the diff touches --paths; non-zero exit = lesson fires").option("--sensor-kind <kind>", "with --sensor-command: shell | test (default test)").option("--sensor-timeout <ms>", "with --sensor-command: max runtime in ms (default 120000)").option("--sensor-absent <regex>", "one-shot: regex marking CORRECT usage nearby (excludes it from firing)").option("--sensor-severity <level>", "one-shot sensor severity: warn | block", "block").option("--sensor-message <text>", "one-shot: self-correction message shown when the sensor fires").option("--bad-example <code>", "one-shot: code snippet the sensor must fire on (validation)").option("-d, --dir <dir>", "project root").action(async (opts) => {
5818
5916
  const root = findProjectRoot15(opts.dir);
5819
5917
  const paths = resolveHaivePaths14(root);
5820
- if (!existsSync19(paths.haiveDir)) {
5918
+ if (!existsSync20(paths.haiveDir)) {
5821
5919
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
5822
5920
  process.exitCode = 1;
5823
5921
  return;
@@ -5863,7 +5961,7 @@ function registerMemoryTried(memory2) {
5863
5961
  process.exitCode = 1;
5864
5962
  return;
5865
5963
  }
5866
- ui.success(`Recorded: ${path20.relative(root, result.file_path)}`);
5964
+ ui.success(`Recorded: ${path21.relative(root, result.file_path)}`);
5867
5965
  ui.info(`id=${result.id} type=attempt status=validated (auto-approved)`);
5868
5966
  if (result.sensor_result) {
5869
5967
  if (result.sensor_result.accepted) {
@@ -5887,8 +5985,8 @@ function registerMemoryTried(memory2) {
5887
5985
 
5888
5986
  // src/commands/memory-seed.ts
5889
5987
  import { readFile as readFile10 } from "fs/promises";
5890
- import { existsSync as existsSync20 } from "fs";
5891
- import path21 from "path";
5988
+ import { existsSync as existsSync21 } from "fs";
5989
+ import path22 from "path";
5892
5990
  import "commander";
5893
5991
  import {
5894
5992
  findProjectRoot as findProjectRoot16,
@@ -5897,7 +5995,7 @@ import {
5897
5995
  } from "@hivelore/core";
5898
5996
  async function readDependencyMap(root) {
5899
5997
  try {
5900
- const raw = await readFile10(path21.join(root, "package.json"), "utf8");
5998
+ const raw = await readFile10(path22.join(root, "package.json"), "utf8");
5901
5999
  const pkg = JSON.parse(raw);
5902
6000
  return { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
5903
6001
  } catch {
@@ -5932,7 +6030,7 @@ function registerMemorySeed(memory2) {
5932
6030
  }
5933
6031
  return;
5934
6032
  }
5935
- if (!existsSync20(paths.haiveDir)) {
6033
+ if (!existsSync21(paths.haiveDir)) {
5936
6034
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
5937
6035
  process.exitCode = 1;
5938
6036
  return;
@@ -5988,8 +6086,8 @@ function registerMemorySeed(memory2) {
5988
6086
  }
5989
6087
 
5990
6088
  // src/commands/memory-query.ts
5991
- import { existsSync as existsSync21 } from "fs";
5992
- import path22 from "path";
6089
+ import { existsSync as existsSync22 } from "fs";
6090
+ import path23 from "path";
5993
6091
  import "commander";
5994
6092
  import {
5995
6093
  extractSnippet,
@@ -6005,7 +6103,7 @@ function registerMemoryQuery(memory2) {
6005
6103
  memory2.command("search <text>").alias("query").description("Search memories by id, tag, or substring (AND, OR fallback). Mirrors MCP mem_search. Alias: query").option("-d, --dir <dir>", "project root").option("--limit <n>", "max results", "20").option("--scope <scope>", "personal | team | module").option("--status <csv>", "filter by status (draft,proposed,validated,stale,rejected)").option("--show-rejected", "include rejected memories (hidden by default)").action(async (text, opts) => {
6006
6104
  const root = findProjectRoot17(opts.dir);
6007
6105
  const paths = resolveHaivePaths16(root);
6008
- if (!existsSync21(paths.memoriesDir)) {
6106
+ if (!existsSync22(paths.memoriesDir)) {
6009
6107
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`hivelore init\` first.`);
6010
6108
  process.exitCode = 1;
6011
6109
  return;
@@ -6046,7 +6144,7 @@ function registerMemoryQuery(memory2) {
6046
6144
  const fm = mem.frontmatter;
6047
6145
  const statusBadge = ui.statusBadge(fm.status);
6048
6146
  console.log(`${ui.bold(fm.id)} ${ui.dim(fm.scope)} ${statusBadge}`);
6049
- console.log(` ${ui.dim(path22.relative(root, filePath))}`);
6147
+ console.log(` ${ui.dim(path23.relative(root, filePath))}`);
6050
6148
  const snippet = extractSnippet(mem.body, snippetNeedle);
6051
6149
  if (snippet) console.log(` ${snippet}`);
6052
6150
  }
@@ -6064,7 +6162,7 @@ ${top.length} of ${matches.length} match${matches.length === 1 ? "" : "es"}`)
6064
6162
 
6065
6163
  // src/commands/memory-reject.ts
6066
6164
  import { writeFile as writeFile13 } from "fs/promises";
6067
- import { existsSync as existsSync22 } from "fs";
6165
+ import { existsSync as existsSync23 } from "fs";
6068
6166
  import "commander";
6069
6167
  import {
6070
6168
  findProjectRoot as findProjectRoot18,
@@ -6078,7 +6176,7 @@ function registerMemoryReject(memory2) {
6078
6176
  memory2.command("reject <id>").description("Record a rejection (blocks auto-promotion and lowers confidence)").option("-r, --reason <reason>", "why this memory is being rejected").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
6079
6177
  const root = findProjectRoot18(opts.dir);
6080
6178
  const paths = resolveHaivePaths17(root);
6081
- if (!existsSync22(paths.memoriesDir)) {
6179
+ if (!existsSync23(paths.memoriesDir)) {
6082
6180
  ui.error(`No .ai/memories at ${root}.`);
6083
6181
  process.exitCode = 1;
6084
6182
  return;
@@ -6114,9 +6212,9 @@ function registerMemoryReject(memory2) {
6114
6212
  }
6115
6213
 
6116
6214
  // src/commands/memory-rm.ts
6117
- import { existsSync as existsSync23 } from "fs";
6215
+ import { existsSync as existsSync24 } from "fs";
6118
6216
  import { unlink as unlink2 } from "fs/promises";
6119
- import path23 from "path";
6217
+ import path24 from "path";
6120
6218
  import { createInterface as createInterface2 } from "readline/promises";
6121
6219
  import "commander";
6122
6220
  import {
@@ -6129,7 +6227,7 @@ function registerMemoryRm(memory2) {
6129
6227
  memory2.command("delete <id>").alias("rm").description("Delete a memory file (and its usage entry by default). Mirrors MCP mem_delete. Alias: rm").option("-y, --yes", "skip the confirmation prompt").option("--keep-usage", "do not remove the usage.json entry").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
6130
6228
  const root = findProjectRoot19(opts.dir);
6131
6229
  const paths = resolveHaivePaths18(root);
6132
- if (!existsSync23(paths.memoriesDir)) {
6230
+ if (!existsSync24(paths.memoriesDir)) {
6133
6231
  ui.error(`No .ai/memories at ${root}.`);
6134
6232
  process.exitCode = 1;
6135
6233
  return;
@@ -6141,7 +6239,7 @@ function registerMemoryRm(memory2) {
6141
6239
  process.exitCode = 1;
6142
6240
  return;
6143
6241
  }
6144
- const rel = path23.relative(root, found.filePath);
6242
+ const rel = path24.relative(root, found.filePath);
6145
6243
  if (!opts.yes) {
6146
6244
  const rl = createInterface2({ input: process.stdin, output: process.stdout });
6147
6245
  const answer = (await rl.question(`Delete ${rel}? [y/N] `)).trim().toLowerCase();
@@ -6165,9 +6263,9 @@ function registerMemoryRm(memory2) {
6165
6263
  }
6166
6264
 
6167
6265
  // src/commands/memory-show.ts
6168
- import { existsSync as existsSync24 } from "fs";
6266
+ import { existsSync as existsSync25 } from "fs";
6169
6267
  import { readFile as readFile11 } from "fs/promises";
6170
- import path24 from "path";
6268
+ import path25 from "path";
6171
6269
  import "commander";
6172
6270
  import {
6173
6271
  deriveConfidence,
@@ -6180,7 +6278,7 @@ function registerMemoryShow(memory2) {
6180
6278
  memory2.command("get <id>").alias("show").description("Print a memory's frontmatter, body, and confidence/usage. Mirrors MCP mem_get. Alias: show").option("--raw", "print the raw file contents instead of a summary").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
6181
6279
  const root = findProjectRoot20(opts.dir);
6182
6280
  const paths = resolveHaivePaths19(root);
6183
- if (!existsSync24(paths.memoriesDir)) {
6281
+ if (!existsSync25(paths.memoriesDir)) {
6184
6282
  ui.error(`No .ai/memories at ${root}.`);
6185
6283
  process.exitCode = 1;
6186
6284
  return;
@@ -6209,7 +6307,7 @@ function registerMemoryShow(memory2) {
6209
6307
  if (fm.verified_at) console.log(`${ui.dim("verified:")} ${fm.verified_at}`);
6210
6308
  if (fm.stale_reason) console.log(`${ui.dim("stale:")} ${fm.stale_reason}`);
6211
6309
  console.log(`${ui.dim("reads:")} ${u.read_count} ${ui.dim("rejections:")} ${u.rejected_count}`);
6212
- console.log(`${ui.dim("file:")} ${path24.relative(root, found.filePath)}`);
6310
+ console.log(`${ui.dim("file:")} ${path25.relative(root, found.filePath)}`);
6213
6311
  if (fm.anchor.paths.length || fm.anchor.symbols.length) {
6214
6312
  console.log(ui.dim("anchor:"));
6215
6313
  if (fm.anchor.commit) console.log(` ${ui.dim("commit:")} ${fm.anchor.commit}`);
@@ -6224,8 +6322,8 @@ function registerMemoryShow(memory2) {
6224
6322
  }
6225
6323
 
6226
6324
  // src/commands/memory-stats.ts
6227
- import { existsSync as existsSync25 } from "fs";
6228
- import path25 from "path";
6325
+ import { existsSync as existsSync26 } from "fs";
6326
+ import path26 from "path";
6229
6327
  import "commander";
6230
6328
  import {
6231
6329
  deriveConfidence as deriveConfidence2,
@@ -6238,7 +6336,7 @@ function registerMemoryStats(memory2) {
6238
6336
  memory2.command("stats").description("Show usage stats and confidence levels per memory").option("--id <id>", "show stats for a single memory id").option("--hot", "only unvalidated (draft/proposed) memories read often \u2014 promotion candidates (absorbed `memory hot`)").option("--threshold <n>", "with --hot: minimum read_count to qualify", "3").option("-d, --dir <dir>", "project root").action(async (opts) => {
6239
6337
  const root = findProjectRoot21(opts.dir);
6240
6338
  const paths = resolveHaivePaths20(root);
6241
- if (!existsSync25(paths.memoriesDir)) {
6339
+ if (!existsSync26(paths.memoriesDir)) {
6242
6340
  ui.error(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
6243
6341
  process.exitCode = 1;
6244
6342
  return;
@@ -6269,13 +6367,13 @@ function registerMemoryStats(memory2) {
6269
6367
  console.log(
6270
6368
  ` ${ui.dim("status:")} ${fm.status} ${ui.dim("reads:")} ${u.read_count} ${ui.dim("rejections:")} ${u.rejected_count}`
6271
6369
  );
6272
- console.log(` ${ui.dim(path25.relative(root, filePath))}`);
6370
+ console.log(` ${ui.dim(path26.relative(root, filePath))}`);
6273
6371
  }
6274
6372
  });
6275
6373
  }
6276
6374
 
6277
6375
  // src/commands/memory-impact.ts
6278
- import { existsSync as existsSync26 } from "fs";
6376
+ import { existsSync as existsSync27 } from "fs";
6279
6377
  import "commander";
6280
6378
  import {
6281
6379
  compareImpact,
@@ -6292,7 +6390,7 @@ function registerMemoryImpact(memory2) {
6292
6390
  ).option("--id <id>", "show impact for a single memory id").option("--prune", "list only prune candidates (dead weight worth reviewing)", false).option("--tier <tier>", "filter to a tier: high | medium | low | dormant").option("--json", "emit JSON", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
6293
6391
  const root = findProjectRoot22(opts.dir);
6294
6392
  const paths = resolveHaivePaths21(root);
6295
- if (!existsSync26(paths.memoriesDir)) {
6393
+ if (!existsSync27(paths.memoriesDir)) {
6296
6394
  ui.error(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
6297
6395
  process.exitCode = 1;
6298
6396
  return;
@@ -6363,7 +6461,7 @@ function pad(value, width) {
6363
6461
  }
6364
6462
 
6365
6463
  // src/commands/memory-feedback.ts
6366
- import { existsSync as existsSync27 } from "fs";
6464
+ import { existsSync as existsSync28 } from "fs";
6367
6465
  import { writeFile as writeFile14 } from "fs/promises";
6368
6466
  import "commander";
6369
6467
  import {
@@ -6390,7 +6488,7 @@ function registerMemoryFeedback(memory2) {
6390
6488
  }
6391
6489
  const root = findProjectRoot23(opts.dir);
6392
6490
  const paths = resolveHaivePaths22(root);
6393
- if (!existsSync27(paths.memoriesDir)) {
6491
+ if (!existsSync28(paths.memoriesDir)) {
6394
6492
  ui.error(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
6395
6493
  process.exitCode = 1;
6396
6494
  return;
@@ -6431,8 +6529,8 @@ function registerMemoryFeedback(memory2) {
6431
6529
 
6432
6530
  // src/commands/memory-verify.ts
6433
6531
  import { writeFile as writeFile15 } from "fs/promises";
6434
- import { existsSync as existsSync28 } from "fs";
6435
- import path26 from "path";
6532
+ import { existsSync as existsSync29 } from "fs";
6533
+ import path27 from "path";
6436
6534
  import "commander";
6437
6535
  import {
6438
6536
  findProjectRoot as findProjectRoot24,
@@ -6446,7 +6544,7 @@ function registerMemoryVerify(memory2) {
6446
6544
  ).option("--id <id>", "verify a single memory by id").option("--all", "verify every memory (default if --id is omitted)").option("--update", "write status=stale or status=validated back to disk").option("--json", "emit machine-readable JSON (for CI / agents)").option("-d, --dir <dir>", "project root").action(async (opts) => {
6447
6545
  const root = findProjectRoot24(opts.dir);
6448
6546
  const paths = resolveHaivePaths23(root);
6449
- if (!existsSync28(paths.memoriesDir)) {
6547
+ if (!existsSync29(paths.memoriesDir)) {
6450
6548
  if (opts.json) {
6451
6549
  console.log(JSON.stringify({ error: "not-initialized", root }, null, 2));
6452
6550
  } else {
@@ -6474,7 +6572,7 @@ function registerMemoryVerify(memory2) {
6474
6572
  for (const { memory: mem, filePath } of targets) {
6475
6573
  const result = await verifyAnchor2(mem, { projectRoot: root });
6476
6574
  const isAnchored = mem.frontmatter.anchor.paths.length > 0 || mem.frontmatter.anchor.symbols.length > 0;
6477
- const rel = path26.relative(root, filePath);
6575
+ const rel = path27.relative(root, filePath);
6478
6576
  if (!isAnchored) {
6479
6577
  anchorlessIds.push(mem.frontmatter.id);
6480
6578
  entries.push({ id: mem.frontmatter.id, status: "anchorless", path: rel });
@@ -6567,7 +6665,7 @@ function applyVerification(mem, result) {
6567
6665
 
6568
6666
  // src/commands/memory-import.ts
6569
6667
  import { readFile as readFile12 } from "fs/promises";
6570
- import { existsSync as existsSync29 } from "fs";
6668
+ import { existsSync as existsSync30 } from "fs";
6571
6669
  import "commander";
6572
6670
  import {
6573
6671
  findProjectRoot as findProjectRoot25,
@@ -6584,12 +6682,12 @@ function registerMemoryImport(memory2) {
6584
6682
  }
6585
6683
  const root = findProjectRoot25(opts.dir);
6586
6684
  const paths = resolveHaivePaths24(root);
6587
- if (!existsSync29(paths.haiveDir)) {
6685
+ if (!existsSync30(paths.haiveDir)) {
6588
6686
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
6589
6687
  process.exitCode = 1;
6590
6688
  return;
6591
6689
  }
6592
- if (!existsSync29(opts.from)) {
6690
+ if (!existsSync30(opts.from)) {
6593
6691
  ui.error(`File not found: ${opts.from}`);
6594
6692
  process.exitCode = 1;
6595
6693
  return;
@@ -6622,9 +6720,9 @@ function registerMemoryImport(memory2) {
6622
6720
  }
6623
6721
 
6624
6722
  // src/commands/memory-digest.ts
6625
- import { existsSync as existsSync30 } from "fs";
6723
+ import { existsSync as existsSync31 } from "fs";
6626
6724
  import { writeFile as writeFile16 } from "fs/promises";
6627
- import path27 from "path";
6725
+ import path28 from "path";
6628
6726
  import "commander";
6629
6727
  import {
6630
6728
  deriveConfidence as deriveConfidence3,
@@ -6647,7 +6745,7 @@ function registerMemoryDigest(program2) {
6647
6745
  ).option("--days <n>", "look-back window in days (default: 7)", "7").option("--scope <scope>", "personal | team | module | all (default: team)", "team").option("--out <file>", "write digest to a file instead of stdout").option("-d, --dir <dir>", "project root").action(async (opts) => {
6648
6746
  const root = findProjectRoot26(opts.dir);
6649
6747
  const paths = resolveHaivePaths25(root);
6650
- if (!existsSync30(paths.memoriesDir)) {
6748
+ if (!existsSync31(paths.memoriesDir)) {
6651
6749
  ui.error("No .ai/memories found. Run `hivelore init` first.");
6652
6750
  process.exitCode = 1;
6653
6751
  return;
@@ -6719,7 +6817,7 @@ function registerMemoryDigest(program2) {
6719
6817
  );
6720
6818
  const digest = lines.join("\n");
6721
6819
  if (opts.out) {
6722
- const outPath = path27.resolve(process.cwd(), opts.out);
6820
+ const outPath = path28.resolve(process.cwd(), opts.out);
6723
6821
  await writeFile16(outPath, digest, "utf8");
6724
6822
  ui.success(`Digest written to ${opts.out} (${recent.length} memor${recent.length === 1 ? "y" : "ies"})`);
6725
6823
  } else {
@@ -6730,9 +6828,9 @@ function registerMemoryDigest(program2) {
6730
6828
 
6731
6829
  // src/commands/session-end.ts
6732
6830
  import { writeFile as writeFile17, mkdir as mkdir11, readFile as readFile13, rm } from "fs/promises";
6733
- import { existsSync as existsSync31 } from "fs";
6831
+ import { existsSync as existsSync32 } from "fs";
6734
6832
  import { spawn as spawn2 } from "child_process";
6735
- import path28 from "path";
6833
+ import path29 from "path";
6736
6834
  import { Option as Option2 } from "commander";
6737
6835
  import {
6738
6836
  buildFrontmatter as buildFrontmatter5,
@@ -6749,8 +6847,8 @@ import {
6749
6847
  writeSessionHandoff
6750
6848
  } from "@hivelore/core";
6751
6849
  async function buildAutoRecap(paths) {
6752
- const obsFile = path28.join(paths.haiveDir, ".cache", "observations.jsonl");
6753
- if (!existsSync31(obsFile)) return await buildGitAutoRecap(paths);
6850
+ const obsFile = path29.join(paths.haiveDir, ".cache", "observations.jsonl");
6851
+ if (!existsSync32(obsFile)) return await buildGitAutoRecap(paths);
6754
6852
  const raw = await readFile13(obsFile, "utf8").catch(() => "");
6755
6853
  if (!raw.trim()) return await buildGitAutoRecap(paths);
6756
6854
  const lines = raw.split("\n").filter(Boolean);
@@ -6918,8 +7016,8 @@ function runGit(cwd, args) {
6918
7016
  });
6919
7017
  }
6920
7018
  async function observationStart(paths) {
6921
- const obsFile = path28.join(paths.haiveDir, ".cache", "observations.jsonl");
6922
- if (!existsSync31(obsFile)) return null;
7019
+ const obsFile = path29.join(paths.haiveDir, ".cache", "observations.jsonl");
7020
+ if (!existsSync32(obsFile)) return null;
6923
7021
  const raw = await readFile13(obsFile, "utf8").catch(() => "");
6924
7022
  let first = null;
6925
7023
  for (const line of raw.split("\n")) {
@@ -6935,7 +7033,7 @@ async function observationStart(paths) {
6935
7033
  }
6936
7034
  async function printCaughtForYou(paths, since, quiet) {
6937
7035
  if (quiet) return;
6938
- const memories = existsSync31(paths.memoriesDir) ? await loadMemoriesFromDir10(paths.memoriesDir) : [];
7036
+ const memories = existsSync32(paths.memoriesDir) ? await loadMemoriesFromDir10(paths.memoriesDir) : [];
6939
7037
  const usage = await loadUsageIndex11(paths);
6940
7038
  const events = await loadPreventionEvents(paths);
6941
7039
  const summary = summarizeCaughtForYou(events, memories, usage, {
@@ -6973,7 +7071,7 @@ function registerSessionEnd(session2) {
6973
7071
  ).option("--goal <text>", "what you were trying to accomplish (1\u20132 sentences)").option("--accomplished <text>", "what was actually done (bullet list recommended)").addOption(new Option2("--summary <text>", "alias for --accomplished").hideHelp()).option("--discoveries <text>", "bugs, surprises, or inconsistencies found during this session").option("--files <csv>", "key files touched, comma-separated (used as anchor for staleness detection)").option("--next <text>", "what should happen next (for the next session or a teammate)").option("--scope <scope>", "personal | team | module (default: personal)", "personal").option("--module <name>", "module name (required when scope=module)").option("--auto", "synthesize the recap from .ai/.cache/observations.jsonl (used by Claude Code SessionEnd hook)").option("--quiet", "suppress non-error output (for hook use)").option("-d, --dir <dir>", "project root").action(async (opts) => {
6974
7072
  const root = findProjectRoot27(opts.dir);
6975
7073
  const paths = resolveHaivePaths26(root);
6976
- if (!existsSync31(paths.haiveDir)) {
7074
+ if (!existsSync32(paths.haiveDir)) {
6977
7075
  if (opts.auto || opts.quiet) return;
6978
7076
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
6979
7077
  process.exitCode = 1;
@@ -7007,15 +7105,15 @@ function registerSessionEnd(session2) {
7007
7105
  });
7008
7106
  const topic = recapTopic(scope, opts.module);
7009
7107
  const filesTouched = parseCsv5(resolvedFiles).map((p) => normalizeAnchorPath(root, p));
7010
- const missingPaths = filesTouched.filter((p) => !existsSync31(path28.resolve(root, p)));
7108
+ const missingPaths = filesTouched.filter((p) => !existsSync32(path29.resolve(root, p)));
7011
7109
  if (missingPaths.length > 0 && !opts.quiet) {
7012
7110
  ui.warn(`Anchor path${missingPaths.length > 1 ? "s" : ""} not found in project (will be stale):`);
7013
7111
  for (const p of missingPaths) ui.warn(` \u2717 ${p}`);
7014
7112
  }
7015
7113
  const cleanupObservations = async () => {
7016
7114
  if (!opts.auto) return;
7017
- const obsFile = path28.join(paths.haiveDir, ".cache", "observations.jsonl");
7018
- if (existsSync31(obsFile)) await rm(obsFile).catch(() => {
7115
+ const obsFile = path29.join(paths.haiveDir, ".cache", "observations.jsonl");
7116
+ if (existsSync32(obsFile)) await rm(obsFile).catch(() => {
7019
7117
  });
7020
7118
  };
7021
7119
  const config = await loadConfig6(paths);
@@ -7039,7 +7137,7 @@ function registerSessionEnd(session2) {
7039
7137
  }
7040
7138
  return;
7041
7139
  }
7042
- if (existsSync31(paths.memoriesDir)) {
7140
+ if (existsSync32(paths.memoriesDir)) {
7043
7141
  const existing = await loadMemoriesFromDir10(paths.memoriesDir);
7044
7142
  const topicMatch = existing.find(
7045
7143
  ({ memory: memory2 }) => memory2.frontmatter.topic === topic && memory2.frontmatter.scope === scope && (!opts.module || memory2.frontmatter.module === opts.module)
@@ -7060,7 +7158,7 @@ function registerSessionEnd(session2) {
7060
7158
  await cleanupObservations();
7061
7159
  if (!opts.quiet) {
7062
7160
  ui.success(`Session recap updated (revision #${revisionCount})`);
7063
- ui.info(`id=${fm.id} file=${path28.relative(root, topicMatch.filePath)}`);
7161
+ ui.info(`id=${fm.id} file=${path29.relative(root, topicMatch.filePath)}`);
7064
7162
  await printCaughtForYou(paths, caughtSince, opts.quiet);
7065
7163
  ui.info("Tip: `hivelore stats --export-report` generates a usage JSON suitable for dashboards.");
7066
7164
  }
@@ -7078,12 +7176,12 @@ function registerSessionEnd(session2) {
7078
7176
  status: "validated"
7079
7177
  });
7080
7178
  const file = memoryFilePath5(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
7081
- await mkdir11(path28.dirname(file), { recursive: true });
7179
+ await mkdir11(path29.dirname(file), { recursive: true });
7082
7180
  await writeFile17(file, serializeMemory12({ frontmatter, body }), "utf8");
7083
7181
  await cleanupObservations();
7084
7182
  if (!opts.quiet) {
7085
7183
  ui.success(`Session recap created`);
7086
- ui.info(`id=${frontmatter.id} scope=${scope} file=${path28.relative(root, file)}`);
7184
+ ui.info(`id=${frontmatter.id} scope=${scope} file=${path29.relative(root, file)}`);
7087
7185
  await printCaughtForYou(paths, caughtSince, opts.quiet);
7088
7186
  ui.info("Next session: call `get_briefing` \u2014 the recap will be surfaced automatically.");
7089
7187
  ui.info("Tip: export a local MCP usage rollup with `hivelore stats --export-report .ai/tool-usage-roi-report.json`.");
@@ -7096,17 +7194,17 @@ function parseCsv5(value) {
7096
7194
  }
7097
7195
  function normalizeAnchorPath(root, filePath) {
7098
7196
  if (!filePath) return filePath;
7099
- if (!path28.isAbsolute(filePath)) return filePath;
7100
- const rel = path28.relative(root, filePath);
7197
+ if (!path29.isAbsolute(filePath)) return filePath;
7198
+ const rel = path29.relative(root, filePath);
7101
7199
  if (rel.startsWith("..")) return filePath;
7102
7200
  return rel;
7103
7201
  }
7104
7202
 
7105
7203
  // src/commands/stats.ts
7106
7204
  import "commander";
7107
- import { existsSync as existsSync32 } from "fs";
7205
+ import { existsSync as existsSync33 } from "fs";
7108
7206
  import { mkdir as mkdir12, writeFile as writeFile18 } from "fs/promises";
7109
- import path29 from "path";
7207
+ import path30 from "path";
7110
7208
  import {
7111
7209
  aggregateUsage,
7112
7210
  findProjectRoot as findProjectRoot28,
@@ -7178,11 +7276,11 @@ function registerStats(program2) {
7178
7276
  });
7179
7277
  }
7180
7278
  async function writeRoiReport(paths, root, sinceRaw, outRelative) {
7181
- const outAbs = path29.isAbsolute(outRelative) ? path29.resolve(outRelative) : path29.resolve(root, outRelative);
7279
+ const outAbs = path30.isAbsolute(outRelative) ? path30.resolve(outRelative) : path30.resolve(root, outRelative);
7182
7280
  const size = await usageLogSize(paths);
7183
7281
  let events = await readUsageEvents(paths);
7184
7282
  let memoryCount = { team: 0, personal: 0, total_skipped_session: 0 };
7185
- if (existsSync32(paths.memoriesDir)) {
7283
+ if (existsSync33(paths.memoriesDir)) {
7186
7284
  const mems = await loadMemoriesFromDir11(paths.memoriesDir);
7187
7285
  for (const { memory: memory2 } of mems) {
7188
7286
  const fm = memory2.frontmatter;
@@ -7212,7 +7310,7 @@ async function writeRoiReport(paths, root, sinceRaw, outRelative) {
7212
7310
  ui.warn("Usage log missing or empty \u2014 report still written with partial data.");
7213
7311
  events = [];
7214
7312
  }
7215
- await mkdir12(path29.dirname(outAbs), { recursive: true });
7313
+ await mkdir12(path30.dirname(outAbs), { recursive: true });
7216
7314
  const payload = {
7217
7315
  generated_at: (/* @__PURE__ */ new Date()).toISOString(),
7218
7316
  project_root: root,
@@ -7401,9 +7499,9 @@ function summarize(name, t0, payload, notes) {
7401
7499
  }
7402
7500
 
7403
7501
  // src/commands/benchmark.ts
7404
- import { existsSync as existsSync33 } from "fs";
7502
+ import { existsSync as existsSync34 } from "fs";
7405
7503
  import { readdir as readdir3, readFile as readFile14, writeFile as writeFile19 } from "fs/promises";
7406
- import path30 from "path";
7504
+ import path31 from "path";
7407
7505
  import "commander";
7408
7506
  import { estimateTokens as estimateTokens2, findProjectRoot as findProjectRoot30 } from "@hivelore/core";
7409
7507
  function registerBenchmark(program2) {
@@ -7418,9 +7516,9 @@ function registerBenchmark(program2) {
7418
7516
  }
7419
7517
  const markdown = renderMarkdown(root, summary, rows);
7420
7518
  if (opts.out) {
7421
- const outFile = path30.isAbsolute(opts.out) ? opts.out : path30.join(root, opts.out);
7519
+ const outFile = path31.isAbsolute(opts.out) ? opts.out : path31.join(root, opts.out);
7422
7520
  await writeFile19(outFile, markdown, "utf8");
7423
- ui.success(`wrote ${path30.relative(process.cwd(), outFile)}`);
7521
+ ui.success(`wrote ${path31.relative(process.cwd(), outFile)}`);
7424
7522
  return;
7425
7523
  }
7426
7524
  console.log(markdown);
@@ -7444,19 +7542,19 @@ function registerBenchmark(program2) {
7444
7542
  }
7445
7543
  function resolveBenchmarkRoot(dir) {
7446
7544
  const candidate = dir ?? "benchmarks/agent-benchmark";
7447
- if (path30.isAbsolute(candidate)) return candidate;
7545
+ if (path31.isAbsolute(candidate)) return candidate;
7448
7546
  const projectRoot = findProjectRoot30(process.cwd());
7449
- return path30.join(projectRoot, candidate);
7547
+ return path31.join(projectRoot, candidate);
7450
7548
  }
7451
7549
  async function collectRows(root) {
7452
- if (!existsSync33(root)) throw new Error(`Benchmark directory not found: ${root}`);
7550
+ if (!existsSync34(root)) throw new Error(`Benchmark directory not found: ${root}`);
7453
7551
  const entries = await readdir3(root, { withFileTypes: true });
7454
7552
  const rows = [];
7455
7553
  for (const entry of entries) {
7456
7554
  if (!entry.isDirectory()) continue;
7457
- const fixtureDir = path30.join(root, entry.name);
7458
- const reportFile = path30.join(fixtureDir, "BENCHMARK_AGENT_REPORT.md");
7459
- if (!existsSync33(reportFile)) continue;
7555
+ const fixtureDir = path31.join(root, entry.name);
7556
+ const reportFile = path31.join(fixtureDir, "BENCHMARK_AGENT_REPORT.md");
7557
+ if (!existsSync34(reportFile)) continue;
7460
7558
  const report = await readFile14(reportFile, "utf8");
7461
7559
  rows.push(parseAgentReport(entry.name, report));
7462
7560
  }
@@ -7549,8 +7647,8 @@ function escapeRegExp(value) {
7549
7647
 
7550
7648
  // src/commands/eval.ts
7551
7649
  import { mkdir as mkdir13, readFile as readFile15, writeFile as writeFile20 } from "fs/promises";
7552
- import { existsSync as existsSync34 } from "fs";
7553
- import path31 from "path";
7650
+ import { existsSync as existsSync35 } from "fs";
7651
+ import path32 from "path";
7554
7652
  import "commander";
7555
7653
  import {
7556
7654
  aggregateRetrieval,
@@ -7578,7 +7676,7 @@ function registerEval(program2) {
7578
7676
  ).option("--spec <file>", "JSON eval spec ({ retrieval: [...], sensors: [...] })").option("--semantic-only", "self-eval probes by title alone (no anchor files) \u2014 harder retrieval", false).option("-k, --top <n>", "briefing top-k considered a hit", "8").option("--json", "emit JSON", false).option("--out <file>", "write a Markdown report").option("--fail-under <score>", "exit non-zero if the overall score is below this (0\u2013100) \u2014 for CI gates").option("--fail-under-catch-rate <pct>", "exit non-zero if sensor catch-rate is below this percentage").option("--fail-under-gate-precision <pct>", "exit non-zero if gate precision is below this percentage").option("--baseline", "save this run as the baseline (.ai/eval/baseline.json) for future --compare", false).option("--compare", "diff this run against the saved baseline and print the delta", false).option("--baseline-file <path>", "baseline file to read/write (default: .ai/eval/baseline.json)").option("--fail-on-regression", "with --compare, exit non-zero if the score dropped vs the baseline", false).option("--regression-gate", "CI-safe gate: compare against the baseline IF one exists (fail on regression), else no-op", false).option("--record", "append this run's score to .ai/.cache/eval-history.jsonl (trend the harness over time)", false).option("--trend", "print the recorded score trend (sparkline + latest/best/delta) and exit", false).option("--ref <ref>", "version/commit label stored with a --record run").option("-d, --dir <dir>", "project root").action(async (opts) => {
7579
7677
  const root = findProjectRoot31(opts.dir);
7580
7678
  const paths = resolveHaivePaths29(root);
7581
- if (!existsSync34(paths.memoriesDir)) {
7679
+ if (!existsSync35(paths.memoriesDir)) {
7582
7680
  ui.error(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
7583
7681
  process.exitCode = 1;
7584
7682
  return;
@@ -7650,7 +7748,7 @@ function registerEval(program2) {
7650
7748
  });
7651
7749
  if (!opts.json) ui.success(`Recorded eval score ${report.score}/100 to history.`);
7652
7750
  }
7653
- const baselineFile = opts.baselineFile ? path31.isAbsolute(opts.baselineFile) ? opts.baselineFile : path31.join(root, opts.baselineFile) : path31.join(root, ".ai", "eval", "baseline.json");
7751
+ const baselineFile = opts.baselineFile ? path32.isAbsolute(opts.baselineFile) ? opts.baselineFile : path32.join(root, opts.baselineFile) : path32.join(root, ".ai", "eval", "baseline.json");
7654
7752
  if (opts.baseline) {
7655
7753
  const snapshot = {
7656
7754
  saved_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -7659,18 +7757,18 @@ function registerEval(program2) {
7659
7757
  report,
7660
7758
  gate_precision: gatePrecision
7661
7759
  };
7662
- await mkdir13(path31.dirname(baselineFile), { recursive: true });
7760
+ await mkdir13(path32.dirname(baselineFile), { recursive: true });
7663
7761
  await writeFile20(baselineFile, JSON.stringify(snapshot, null, 2), "utf8");
7664
- if (!opts.json) ui.success(`Saved baseline (score ${report.score}/100) \u2192 ${path31.relative(root, baselineFile)}`);
7762
+ if (!opts.json) ui.success(`Saved baseline (score ${report.score}/100) \u2192 ${path32.relative(root, baselineFile)}`);
7665
7763
  }
7666
7764
  let delta = null;
7667
7765
  let gateDelta = null;
7668
7766
  if (opts.compare || opts.regressionGate) {
7669
- if (!existsSync34(baselineFile)) {
7767
+ if (!existsSync35(baselineFile)) {
7670
7768
  if (opts.regressionGate) {
7671
- if (!opts.json) ui.info(`No baseline at ${path31.relative(root, baselineFile)} \u2014 regression gate skipped. Run \`hivelore eval --baseline\` to enable it.`);
7769
+ if (!opts.json) ui.info(`No baseline at ${path32.relative(root, baselineFile)} \u2014 regression gate skipped. Run \`hivelore eval --baseline\` to enable it.`);
7672
7770
  } else {
7673
- ui.error(`No baseline at ${path31.relative(root, baselineFile)}. Run \`hivelore eval --baseline\` first.`);
7771
+ ui.error(`No baseline at ${path32.relative(root, baselineFile)}. Run \`hivelore eval --baseline\` first.`);
7674
7772
  process.exitCode = 1;
7675
7773
  return;
7676
7774
  }
@@ -7713,9 +7811,9 @@ function registerEval(program2) {
7713
7811
  }
7714
7812
  const md = renderMarkdown2(root, k, resolvedSpec, report, gatePrecision, authoredScore);
7715
7813
  if (opts.out) {
7716
- const outFile = path31.isAbsolute(opts.out) ? opts.out : path31.join(root, opts.out);
7814
+ const outFile = path32.isAbsolute(opts.out) ? opts.out : path32.join(root, opts.out);
7717
7815
  await writeFile20(outFile, md, "utf8");
7718
- ui.success(`wrote ${path31.relative(process.cwd(), outFile)}`);
7816
+ ui.success(`wrote ${path32.relative(process.cwd(), outFile)}`);
7719
7817
  } else {
7720
7818
  console.log(md);
7721
7819
  }
@@ -7799,13 +7897,13 @@ function countCases(spec) {
7799
7897
  }
7800
7898
  async function resolveSpec(opts, root, memoriesDir) {
7801
7899
  if (opts.spec) {
7802
- const file = path31.resolve(opts.spec);
7900
+ const file = path32.resolve(opts.spec);
7803
7901
  const raw = await readFile15(file, "utf8");
7804
7902
  const spec = JSON.parse(raw);
7805
7903
  return { spec, source: file, synthesized: 0, authored: countCases(spec) };
7806
7904
  }
7807
- const defaultSpec = path31.join(root, ".ai", "eval", "spec.json");
7808
- if (existsSync34(defaultSpec)) {
7905
+ const defaultSpec = path32.join(root, ".ai", "eval", "spec.json");
7906
+ if (existsSync35(defaultSpec)) {
7809
7907
  const raw = await readFile15(defaultSpec, "utf8");
7810
7908
  const explicit = JSON.parse(raw);
7811
7909
  const memories2 = await loadMemoriesFromDir(memoriesDir);
@@ -7932,8 +8030,8 @@ function renderMarkdown2(root, k, resolved, report, gatePrecision, authoredScore
7932
8030
 
7933
8031
  // src/commands/memory-suggest.ts
7934
8032
  import { mkdir as mkdir14, writeFile as writeFile21 } from "fs/promises";
7935
- import { existsSync as existsSync35 } from "fs";
7936
- import path32 from "path";
8033
+ import { existsSync as existsSync36 } from "fs";
8034
+ import path33 from "path";
7937
8035
  import "commander";
7938
8036
  import {
7939
8037
  MemoryTypeSchema,
@@ -8023,7 +8121,7 @@ function registerMemorySuggest(memory2) {
8023
8121
  }
8024
8122
  const created = [];
8025
8123
  const skipped = [];
8026
- const existing = existsSync35(paths.memoriesDir) ? await loadMemoriesFromDir12(paths.memoriesDir) : [];
8124
+ const existing = existsSync36(paths.memoriesDir) ? await loadMemoriesFromDir12(paths.memoriesDir) : [];
8027
8125
  for (const s of top) {
8028
8126
  const slug = slugify2(s.query);
8029
8127
  if (!slug) {
@@ -8046,13 +8144,13 @@ function registerMemorySuggest(memory2) {
8046
8144
  });
8047
8145
  const body = renderTemplate(s, fm.id, status);
8048
8146
  const file = memoryFilePath6(paths, fm.scope, fm.id, fm.module);
8049
- await mkdir14(path32.dirname(file), { recursive: true });
8050
- if (existsSync35(file)) {
8051
- skipped.push({ query: s.query, reason: `file already exists at ${path32.relative(root, file)}` });
8147
+ await mkdir14(path33.dirname(file), { recursive: true });
8148
+ if (existsSync36(file)) {
8149
+ skipped.push({ query: s.query, reason: `file already exists at ${path33.relative(root, file)}` });
8052
8150
  continue;
8053
8151
  }
8054
8152
  await writeFile21(file, serializeMemory13({ frontmatter: fm, body }), "utf8");
8055
- created.push({ id: fm.id, file: path32.relative(root, file), query: s.query });
8153
+ created.push({ id: fm.id, file: path33.relative(root, file), query: s.query });
8056
8154
  }
8057
8155
  if (opts.json) {
8058
8156
  console.log(JSON.stringify({ created, skipped }, null, 2));
@@ -8150,8 +8248,8 @@ function truncate2(text, max) {
8150
8248
  }
8151
8249
 
8152
8250
  // src/commands/memory-conflict-candidates.ts
8153
- import { existsSync as existsSync36 } from "fs";
8154
- import path33 from "path";
8251
+ import { existsSync as existsSync37 } from "fs";
8252
+ import path34 from "path";
8155
8253
  import "commander";
8156
8254
  import {
8157
8255
  findLexicalConflictPairs,
@@ -8187,9 +8285,9 @@ function registerMemoryConflictCandidates(memory2) {
8187
8285
  });
8188
8286
  }
8189
8287
  async function runConflictCandidates(opts) {
8190
- const root = path33.resolve(opts.dir ?? process.cwd());
8288
+ const root = path34.resolve(opts.dir ?? process.cwd());
8191
8289
  const paths = resolveHaivePaths31(findProjectRoot33(root));
8192
- if (!existsSync36(paths.memoriesDir)) {
8290
+ if (!existsSync37(paths.memoriesDir)) {
8193
8291
  ui.error("No memories \u2014 run `hivelore init`.");
8194
8292
  process.exitCode = 1;
8195
8293
  return;
@@ -8223,9 +8321,9 @@ async function runConflictCandidates(opts) {
8223
8321
  }
8224
8322
 
8225
8323
  // src/commands/memory-archive.ts
8226
- import { existsSync as existsSync37 } from "fs";
8324
+ import { existsSync as existsSync38 } from "fs";
8227
8325
  import { writeFile as writeFile22 } from "fs/promises";
8228
- import path34 from "path";
8326
+ import path35 from "path";
8229
8327
  import "commander";
8230
8328
  import {
8231
8329
  findProjectRoot as findProjectRoot34,
@@ -8244,7 +8342,7 @@ function registerMemoryArchive(memory2) {
8244
8342
  ).option("--since <window>", "minimum age since last read (e.g. '180d', '6m'). Default: enforcement.decayAfterDays or 180d").option("--type <type>", "limit to a memory type (default 'attempt'). Pass 'all' to scan all types.", "attempt").option("--unread", "decay by unread-age ALONE (ignore anchor status) \u2014 more aggressive corpus hygiene", false).option("--apply", "actually rewrite files (default: dry run)", false).option("--json", "emit JSON instead of human-readable output", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
8245
8343
  const root = findProjectRoot34(opts.dir);
8246
8344
  const paths = resolveHaivePaths32(root);
8247
- if (!existsSync37(paths.memoriesDir)) {
8345
+ if (!existsSync38(paths.memoriesDir)) {
8248
8346
  ui.error(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
8249
8347
  process.exitCode = 1;
8250
8348
  return;
@@ -8269,7 +8367,7 @@ function registerMemoryArchive(memory2) {
8269
8367
  if (fm.status === "deprecated" || fm.status === "rejected") continue;
8270
8368
  const retired = retirementSignal2(fm, mem.body);
8271
8369
  const hasAnyAnchor = fm.anchor.paths.length + fm.anchor.symbols.length > 0;
8272
- const allPathsGone = fm.anchor.paths.length > 0 && fm.anchor.paths.every((p) => !existsSync37(path34.join(paths.root, p)));
8370
+ const allPathsGone = fm.anchor.paths.length > 0 && fm.anchor.paths.every((p) => !existsSync38(path35.join(paths.root, p)));
8273
8371
  const isAnchorless = !hasAnyAnchor;
8274
8372
  if (!retired.retired && !opts.unread && !isAnchorless && !allPathsGone) continue;
8275
8373
  const u = getUsage8(usage, fm.id);
@@ -8344,9 +8442,9 @@ function parseDays(input) {
8344
8442
  }
8345
8443
 
8346
8444
  // src/commands/doctor.ts
8347
- import { existsSync as existsSync38, statSync as statSync2 } from "fs";
8445
+ import { existsSync as existsSync39, statSync as statSync2 } from "fs";
8348
8446
  import { readFile as readFile16, stat, writeFile as writeFile23 } from "fs/promises";
8349
- import path35 from "path";
8447
+ import path36 from "path";
8350
8448
  import { execFileSync, execSync } from "child_process";
8351
8449
  import "commander";
8352
8450
  import {
@@ -8360,7 +8458,7 @@ import {
8360
8458
  isStackPackSeed as isStackPackSeed2,
8361
8459
  loadCodeMap as loadCodeMap6,
8362
8460
  loadConfig as loadConfig10,
8363
- loadMemoriesFromDir as loadMemoriesFromDir14,
8461
+ loadMemoriesFromDirDetailed,
8364
8462
  loadUsageIndex as loadUsageIndex15,
8365
8463
  readUsageEvents as readUsageEvents3,
8366
8464
  resolveHaivePaths as resolveHaivePaths33
@@ -8375,7 +8473,7 @@ function registerDoctor(program2) {
8375
8473
  const findings = [];
8376
8474
  const repairs = [];
8377
8475
  const config = await loadConfig10(paths);
8378
- if (!existsSync38(paths.haiveDir)) {
8476
+ if (!existsSync39(paths.haiveDir)) {
8379
8477
  if (opts.json) {
8380
8478
  console.log(JSON.stringify({
8381
8479
  initialized: false,
@@ -8400,7 +8498,7 @@ function registerDoctor(program2) {
8400
8498
  })
8401
8499
  );
8402
8500
  }
8403
- if (!existsSync38(paths.projectContext)) {
8501
+ if (!existsSync39(paths.projectContext)) {
8404
8502
  findings.push({
8405
8503
  severity: "warn",
8406
8504
  code: "no-project-context",
@@ -8420,7 +8518,7 @@ function registerDoctor(program2) {
8420
8518
  });
8421
8519
  } else {
8422
8520
  const referenced = extractReferencedPaths(content);
8423
- const missing = referenced.filter((p) => !existsSync38(path35.resolve(root, p)));
8521
+ const missing = referenced.filter((p) => !existsSync39(path36.resolve(root, p)));
8424
8522
  const grounded = referenced.length - missing.length;
8425
8523
  if (referenced.length >= 3 && grounded / referenced.length < 0.5) {
8426
8524
  findings.push({
@@ -8442,13 +8540,23 @@ function registerDoctor(program2) {
8442
8540
  });
8443
8541
  }
8444
8542
  }
8445
- const memories = existsSync38(paths.memoriesDir) ? await loadMemoriesFromDir14(paths.memoriesDir) : [];
8543
+ const memoriesDetailed = existsSync39(paths.memoriesDir) ? await loadMemoriesFromDirDetailed(paths.memoriesDir) : { loaded: [], invalid: [] };
8544
+ const memories = memoriesDetailed.loaded;
8446
8545
  const now = Date.now();
8546
+ if (memoriesDetailed.invalid.length > 0) {
8547
+ const listed = memoriesDetailed.invalid.slice(0, 5).map((f) => `${path36.relative(root, f.filePath)} (${f.error})`).join("; ");
8548
+ findings.push({
8549
+ severity: "warn",
8550
+ code: "invalid-memory-files",
8551
+ message: `${memoriesDetailed.invalid.length} memory file(s) failed to parse and are INVISIBLE to briefings and the gate: ${listed}`,
8552
+ fix: "Fix the frontmatter (or delete the file) \u2014 a corrupt memory is a silently lost team lesson."
8553
+ });
8554
+ }
8447
8555
  if (memories.length === 0) {
8448
8556
  findings.push({
8449
8557
  severity: "info",
8450
8558
  code: "no-memories",
8451
- message: "No memories yet. Capture knowledge as agents work via mem_save / mem_observe / mem_tried."
8559
+ message: "No memories yet. Capture knowledge as agents work via mem_save / mem_tried."
8452
8560
  });
8453
8561
  } else {
8454
8562
  const usage = await loadUsageIndex15(paths);
@@ -8458,7 +8566,7 @@ function registerDoctor(program2) {
8458
8566
  severity: "warn",
8459
8567
  code: "stale-memories",
8460
8568
  message: `${stale.length} memor${stale.length === 1 ? "y" : "ies"} marked stale (anchored code drifted).`,
8461
- fix: "hivelore memory verify --update # re-check anchors\nhaive memory edit <id> # manually refresh body"
8569
+ fix: "hivelore memory verify --update # re-check anchors\nhivelore memory update <id> # manually refresh body"
8462
8570
  });
8463
8571
  }
8464
8572
  const proposed = memories.filter((m) => m.memory.frontmatter.status === "proposed");
@@ -8565,8 +8673,8 @@ function registerDoctor(program2) {
8565
8673
  const anchorPaths = s.paths.length > 0 ? s.paths : m.memory.frontmatter.anchor.paths;
8566
8674
  const targets = [];
8567
8675
  for (const rel of anchorPaths) {
8568
- const abs = path35.resolve(root, rel);
8569
- if (!existsSync38(abs)) continue;
8676
+ const abs = path36.resolve(root, rel);
8677
+ if (!existsSync39(abs)) continue;
8570
8678
  try {
8571
8679
  targets.push({ path: rel, content: await readFile16(abs, "utf8") });
8572
8680
  } catch {
@@ -8655,9 +8763,9 @@ function registerDoctor(program2) {
8655
8763
  }
8656
8764
  }
8657
8765
  if (config.enforcement?.requireBriefingFirst) {
8658
- const claudeSettings = path35.join(root, ".claude", "settings.local.json");
8766
+ const claudeSettings = path36.join(root, ".claude", "settings.local.json");
8659
8767
  let hasClaudeEnforcement = false;
8660
- if (existsSync38(claudeSettings)) {
8768
+ if (existsSync39(claudeSettings)) {
8661
8769
  try {
8662
8770
  const { readFile: readFile24 } = await import("fs/promises");
8663
8771
  const raw = await readFile24(claudeSettings, "utf8");
@@ -8683,7 +8791,7 @@ function registerDoctor(program2) {
8683
8791
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `hivelore init` without --manual)."
8684
8792
  });
8685
8793
  }
8686
- findings.push(...await collectInstallFindings(root, "0.33.0"));
8794
+ findings.push(...await collectInstallFindings(root, "0.34.1"));
8687
8795
  findings.push(...await collectToolchainFindings(root));
8688
8796
  try {
8689
8797
  const legacyRaw = execSync("haive-mcp --version", {
@@ -8691,7 +8799,7 @@ function registerDoctor(program2) {
8691
8799
  timeout: 3e3,
8692
8800
  stdio: ["ignore", "pipe", "ignore"]
8693
8801
  }).trim();
8694
- const cliVersion = "0.33.0";
8802
+ const cliVersion = "0.34.1";
8695
8803
  if (legacyRaw && legacyRaw !== cliVersion) {
8696
8804
  findings.push({
8697
8805
  severity: "warn",
@@ -8707,17 +8815,17 @@ npm uninstall -g @hivelore/mcp`
8707
8815
  }
8708
8816
  {
8709
8817
  const configPaths = [
8710
- path35.join(root, ".mcp.json"),
8711
- path35.join(root, ".cursor", "mcp.json"),
8712
- path35.join(root, ".vscode", "mcp.json")
8818
+ path36.join(root, ".mcp.json"),
8819
+ path36.join(root, ".cursor", "mcp.json"),
8820
+ path36.join(root, ".vscode", "mcp.json")
8713
8821
  ];
8714
8822
  const staleConfigs = [];
8715
8823
  for (const cfgPath of configPaths) {
8716
- if (!existsSync38(cfgPath)) continue;
8824
+ if (!existsSync39(cfgPath)) continue;
8717
8825
  try {
8718
8826
  const raw = await readFile16(cfgPath, "utf8");
8719
8827
  if (raw.includes('"haive-mcp"') || raw.includes("'haive-mcp'")) {
8720
- staleConfigs.push(path35.relative(root, cfgPath));
8828
+ staleConfigs.push(path36.relative(root, cfgPath));
8721
8829
  if (opts.fix && !opts.dryRun) {
8722
8830
  const updated = raw.replace(/"command"\s*:\s*"haive-mcp"/g, '"command": "hivelore"').replace(/"args"\s*:\s*\[\]/g, '"args": ["mcp", "--stdio"]');
8723
8831
  await writeFile23(cfgPath, updated, "utf8");
@@ -9010,8 +9118,8 @@ which -a hivelore haive`
9010
9118
  const missingBins = /* @__PURE__ */ new Map();
9011
9119
  const staleBins = /* @__PURE__ */ new Map();
9012
9120
  for (const rel of integrationFiles) {
9013
- const file = path35.join(root, rel);
9014
- if (!existsSync38(file)) continue;
9121
+ const file = path36.join(root, rel);
9122
+ if (!existsSync39(file)) continue;
9015
9123
  const text = await readFile16(file, "utf8").catch(() => "");
9016
9124
  for (const bin of extractAbsoluteHaiveBins(text)) {
9017
9125
  const version = versionForBinary(bin);
@@ -9044,7 +9152,7 @@ which -a hivelore haive`
9044
9152
  async function collectToolchainFindings(root) {
9045
9153
  const findings = [];
9046
9154
  const pkg = await readJson(
9047
- path35.join(root, "package.json")
9155
+ path36.join(root, "package.json")
9048
9156
  );
9049
9157
  const wantsPnpm = pkg?.packageManager?.startsWith("pnpm@") || Object.values(pkg?.scripts ?? {}).some((script) => /\bpnpm\b/.test(script));
9050
9158
  if (!wantsPnpm) return findings;
@@ -9063,10 +9171,10 @@ async function collectToolchainFindings(root) {
9063
9171
  }
9064
9172
  async function collectDistFreshnessFindings(root, expectedVersion) {
9065
9173
  const findings = [];
9066
- const isHaiveWorkspace = ["hivelore-monorepo", "haive-monorepo"].includes((await readJson(path35.join(root, "package.json")))?.name ?? "");
9174
+ const isHaiveWorkspace = ["hivelore-monorepo", "haive-monorepo"].includes((await readJson(path36.join(root, "package.json")))?.name ?? "");
9067
9175
  if (!isHaiveWorkspace) return findings;
9068
- const cliDist = path35.join(root, "packages/cli/dist/index.js");
9069
- if (!existsSync38(cliDist)) {
9176
+ const cliDist = path36.join(root, "packages/cli/dist/index.js");
9177
+ if (!existsSync39(cliDist)) {
9070
9178
  findings.push({
9071
9179
  severity: "warn",
9072
9180
  code: "workspace-dist-missing",
@@ -9090,7 +9198,7 @@ async function collectDistFreshnessFindings(root, expectedVersion) {
9090
9198
  "packages/core/src/index.ts",
9091
9199
  "packages/mcp/src/server.ts",
9092
9200
  "packages/cli/src/index.ts"
9093
- ].map((rel) => path35.join(root, rel)).filter(existsSync38);
9201
+ ].map((rel) => path36.join(root, rel)).filter(existsSync39);
9094
9202
  if (sourceFiles.length > 0) {
9095
9203
  const distMtime = statSync2(cliDist).mtimeMs;
9096
9204
  const newestSource = Math.max(...sourceFiles.map((file) => statSync2(file).mtimeMs));
@@ -9108,7 +9216,7 @@ async function collectDistFreshnessFindings(root, expectedVersion) {
9108
9216
  }
9109
9217
  async function collectWorkspaceVersionFindings(root, expectedVersion) {
9110
9218
  const findings = [];
9111
- const rootPkg = await readJson(path35.join(root, "package.json"));
9219
+ const rootPkg = await readJson(path36.join(root, "package.json"));
9112
9220
  const workspacePackages = [
9113
9221
  "packages/core/package.json",
9114
9222
  "packages/embeddings/package.json",
@@ -9117,7 +9225,7 @@ async function collectWorkspaceVersionFindings(root, expectedVersion) {
9117
9225
  ];
9118
9226
  const existing = (await Promise.all(workspacePackages.map(async (rel) => ({
9119
9227
  rel,
9120
- pkg: await readJson(path35.join(root, rel))
9228
+ pkg: await readJson(path36.join(root, rel))
9121
9229
  })))).filter((item) => item.pkg);
9122
9230
  const isHaiveWorkspace = rootPkg?.name === "hivelore-monorepo" || rootPkg?.name === "haive-monorepo" || existing.some((item) => item.pkg?.name?.startsWith("@hivelore/"));
9123
9231
  if (!isHaiveWorkspace) return findings;
@@ -9179,7 +9287,7 @@ function collectGlobalHivemoduleFindings(expectedVersion) {
9179
9287
  }
9180
9288
  }
9181
9289
  async function readJson(file) {
9182
- if (!existsSync38(file)) return null;
9290
+ if (!existsSync39(file)) return null;
9183
9291
  try {
9184
9292
  return JSON.parse(await readFile16(file, "utf8"));
9185
9293
  } catch {
@@ -9408,23 +9516,23 @@ function runCommand(cmd, args, cwd) {
9408
9516
  }
9409
9517
 
9410
9518
  // src/commands/resolve-project.ts
9411
- import path36 from "path";
9519
+ import path37 from "path";
9412
9520
  import "commander";
9413
9521
  import { resolveProjectInfo } from "@hivelore/core";
9414
9522
  function registerResolveProject(program2) {
9415
9523
  program2.command("resolve-project").description(
9416
9524
  "Print JSON for Hivelore project root resolution (HAIVE_PROJECT_ROOT, markers, .ai layout)."
9417
9525
  ).option("-d, --dir <dir>", "working directory", process.cwd()).action((opts) => {
9418
- const info = resolveProjectInfo({ cwd: path36.resolve(opts.dir) });
9526
+ const info = resolveProjectInfo({ cwd: path37.resolve(opts.dir) });
9419
9527
  console.log(JSON.stringify({ ok: true, info }, null, 2));
9420
9528
  });
9421
9529
  }
9422
9530
 
9423
9531
  // src/commands/enforce.ts
9424
9532
  import { execFile as execFile4, execFileSync as execFileSync2, spawn as spawn4 } from "child_process";
9425
- import { existsSync as existsSync40, statSync as statSync3 } from "fs";
9533
+ import { existsSync as existsSync41, statSync as statSync3 } from "fs";
9426
9534
  import { chmod, mkdir as mkdir16, readFile as readFile18, readdir as readdir4, rm as rm2, writeFile as writeFile25 } from "fs/promises";
9427
- import path38 from "path";
9535
+ import path39 from "path";
9428
9536
  import { promisify as promisify4 } from "util";
9429
9537
  import "commander";
9430
9538
  import {
@@ -9441,7 +9549,7 @@ import {
9441
9549
  isRetiredMemory as isRetiredMemory2,
9442
9550
  loadConfig as loadConfig12,
9443
9551
  detectAgentContext,
9444
- loadMemoriesFromDir as loadMemoriesFromDir15,
9552
+ loadMemoriesFromDir as loadMemoriesFromDir14,
9445
9553
  memoryMatchesAnchorPaths as memoryMatchesAnchorPaths2,
9446
9554
  readRecentBriefingMarker,
9447
9555
  recordPreventionHits,
@@ -9457,9 +9565,9 @@ import {
9457
9565
  } from "@hivelore/core";
9458
9566
 
9459
9567
  // src/utils/claude-hooks.ts
9460
- import { existsSync as existsSync39 } from "fs";
9568
+ import { existsSync as existsSync40 } from "fs";
9461
9569
  import { mkdir as mkdir15, readFile as readFile17, writeFile as writeFile24 } from "fs/promises";
9462
- import path37 from "path";
9570
+ import path38 from "path";
9463
9571
  var HAIVE_HOOK_TAG = "haive-enforcement";
9464
9572
  var POST_TOOL_USE_GROUP = {
9465
9573
  matcher: "Edit|Write|Bash",
@@ -9545,7 +9653,7 @@ function unpatchClaudeSettings(input) {
9545
9653
  async function installClaudeHooksAtPath(settingsPath) {
9546
9654
  let raw = null;
9547
9655
  let created = false;
9548
- if (existsSync39(settingsPath)) {
9656
+ if (existsSync40(settingsPath)) {
9549
9657
  try {
9550
9658
  raw = JSON.parse(await readFile17(settingsPath, "utf8"));
9551
9659
  } catch {
@@ -9555,12 +9663,12 @@ async function installClaudeHooksAtPath(settingsPath) {
9555
9663
  created = true;
9556
9664
  }
9557
9665
  const patched = patchClaudeSettings(raw);
9558
- await mkdir15(path37.dirname(settingsPath), { recursive: true });
9666
+ await mkdir15(path38.dirname(settingsPath), { recursive: true });
9559
9667
  await writeFile24(settingsPath, JSON.stringify(patched, null, 2) + "\n", "utf8");
9560
9668
  return { settingsPath, created };
9561
9669
  }
9562
9670
  async function uninstallClaudeHooksAtPath(settingsPath) {
9563
- if (!existsSync39(settingsPath)) {
9671
+ if (!existsSync40(settingsPath)) {
9564
9672
  return { settingsPath, created: false };
9565
9673
  }
9566
9674
  const raw = JSON.parse(await readFile17(settingsPath, "utf8"));
@@ -9571,9 +9679,9 @@ async function uninstallClaudeHooksAtPath(settingsPath) {
9571
9679
  function defaultClaudeSettingsPath(scope, projectRoot) {
9572
9680
  if (scope === "user") {
9573
9681
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
9574
- return path37.join(home, ".claude", "settings.json");
9682
+ return path38.join(home, ".claude", "settings.json");
9575
9683
  }
9576
- return path37.join(projectRoot, ".claude", "settings.local.json");
9684
+ return path38.join(projectRoot, ".claude", "settings.local.json");
9577
9685
  }
9578
9686
 
9579
9687
  // src/utils/command-sensors.ts
@@ -9715,7 +9823,7 @@ function registerEnforce(program2) {
9715
9823
  ui.success(`Removed Hivelore hooks from ${result.settingsPath}`);
9716
9824
  } else {
9717
9825
  const result = await installClaudeHooksAtPath(settingsPath);
9718
- ui.success(`${result.created ? "Created" : "Patched"} Claude Code hooks (${path38.relative(root, result.settingsPath) || result.settingsPath})`);
9826
+ ui.success(`${result.created ? "Created" : "Patched"} Claude Code hooks (${path39.relative(root, result.settingsPath) || result.settingsPath})`);
9719
9827
  }
9720
9828
  } catch (err) {
9721
9829
  ui.warn(`Claude Code hooks not ${opts.removeClaude ? "removed" : "installed"}: ${err instanceof Error ? err.message : String(err)}`);
@@ -9737,19 +9845,19 @@ function registerEnforce(program2) {
9737
9845
  enforce.command("cleanup").description("Remove generated Hivelore runtime/cache artifacts that should not appear in commits.").option("-d, --dir <dir>", "project root").option("--dry-run", "print what would be removed without deleting", false).action(async (opts) => {
9738
9846
  const root = findProjectRoot37(opts.dir);
9739
9847
  const paths = resolveHaivePaths35(root);
9740
- const cacheDir = path38.join(paths.haiveDir, ".cache");
9741
- if (existsSync40(cacheDir)) {
9742
- if (opts.dryRun) ui.info(`would clean ${path38.relative(root, cacheDir)} (preserving .gitignore)`);
9848
+ const cacheDir = path39.join(paths.haiveDir, ".cache");
9849
+ if (existsSync41(cacheDir)) {
9850
+ if (opts.dryRun) ui.info(`would clean ${path39.relative(root, cacheDir)} (preserving .gitignore)`);
9743
9851
  else {
9744
9852
  const removed = await cleanupCacheDir(cacheDir);
9745
- ui.success(`cleaned ${path38.relative(root, cacheDir)}${removed > 0 ? ` (${removed} item${removed === 1 ? "" : "s"} removed)` : ""}`);
9853
+ ui.success(`cleaned ${path39.relative(root, cacheDir)}${removed > 0 ? ` (${removed} item${removed === 1 ? "" : "s"} removed)` : ""}`);
9746
9854
  }
9747
9855
  }
9748
- if (existsSync40(paths.runtimeDir)) {
9749
- if (opts.dryRun) ui.info(`would clean ${path38.relative(root, paths.runtimeDir)} (preserving briefing markers)`);
9856
+ if (existsSync41(paths.runtimeDir)) {
9857
+ if (opts.dryRun) ui.info(`would clean ${path39.relative(root, paths.runtimeDir)} (preserving briefing markers)`);
9750
9858
  else {
9751
9859
  const removed = await cleanupRuntimeDir(paths.runtimeDir);
9752
- ui.success(`cleaned ${path38.relative(root, paths.runtimeDir)}${removed > 0 ? ` (${removed} item${removed === 1 ? "" : "s"} removed)` : ""}`);
9860
+ ui.success(`cleaned ${path39.relative(root, paths.runtimeDir)}${removed > 0 ? ` (${removed} item${removed === 1 ? "" : "s"} removed)` : ""}`);
9753
9861
  }
9754
9862
  }
9755
9863
  });
@@ -9793,7 +9901,7 @@ function registerEnforce(program2) {
9793
9901
  const root = resolveRoot(opts.dir, payload);
9794
9902
  if (!root) return;
9795
9903
  const paths = resolveHaivePaths35(root);
9796
- if (!existsSync40(paths.haiveDir)) return;
9904
+ if (!existsSync41(paths.haiveDir)) return;
9797
9905
  await mkdir16(paths.runtimeDir, { recursive: true });
9798
9906
  const sessionId = opts.sessionId ?? payload.session_id;
9799
9907
  const task = opts.task ?? payload.prompt ?? "Start an AI coding session in this Hivelore-initialized project.";
@@ -9856,7 +9964,7 @@ ${briefing.project_context.content.slice(0, 1800)}`);
9856
9964
  const root = resolveRoot(opts.dir, payload);
9857
9965
  if (!root) return;
9858
9966
  const paths = resolveHaivePaths35(root);
9859
- if (!existsSync40(paths.haiveDir)) return;
9967
+ if (!existsSync41(paths.haiveDir)) return;
9860
9968
  if (!isWriteLikeTool(payload)) return;
9861
9969
  const config = await loadConfig12(paths);
9862
9970
  if (config.enforcement?.requireBriefingFirst === false) return;
@@ -9921,7 +10029,7 @@ function emitPreToolUseContext(text) {
9921
10029
  async function buildFinishReport(dir) {
9922
10030
  const root = findProjectRoot37(dir);
9923
10031
  const paths = resolveHaivePaths35(root);
9924
- const initialized = existsSync40(paths.haiveDir);
10032
+ const initialized = existsSync41(paths.haiveDir);
9925
10033
  const config = initialized ? await loadConfig12(paths) : {};
9926
10034
  const mode = config.enforcement?.mode ?? "strict";
9927
10035
  const findings = [];
@@ -10113,8 +10221,8 @@ async function buildFinishReport(dir) {
10113
10221
  async function checkFailureCapture(paths, config) {
10114
10222
  const gate = config.enforcement?.failureCaptureGate ?? "warn";
10115
10223
  if (gate === "off") return [];
10116
- const obsFile = path38.join(paths.haiveDir, ".cache", "observations.jsonl");
10117
- if (!existsSync40(obsFile)) return [];
10224
+ const obsFile = path39.join(paths.haiveDir, ".cache", "observations.jsonl");
10225
+ if (!existsSync41(obsFile)) return [];
10118
10226
  const failures = [];
10119
10227
  try {
10120
10228
  const raw = await readFile18(obsFile, "utf8");
@@ -10131,7 +10239,7 @@ async function checkFailureCapture(paths, config) {
10131
10239
  return [];
10132
10240
  }
10133
10241
  if (failures.length === 0) return [];
10134
- const memories = existsSync40(paths.memoriesDir) ? await loadMemoriesFromDir15(paths.memoriesDir) : [];
10242
+ const memories = existsSync41(paths.memoriesDir) ? await loadMemoriesFromDir14(paths.memoriesDir) : [];
10135
10243
  const captureTimes = memories.filter(({ memory: memory2 }) => ["attempt", "gotcha"].includes(memory2.frontmatter.type)).map(({ memory: memory2 }) => memory2.frontmatter.created_at);
10136
10244
  const uncaptured = findUncapturedFailures(failures, captureTimes);
10137
10245
  if (uncaptured.length === 0) {
@@ -10166,7 +10274,7 @@ function finishReport(root, initialized, mode, findings, config) {
10166
10274
  async function runWithEnforcement(command, args, opts) {
10167
10275
  const root = findProjectRoot37(opts.dir);
10168
10276
  const paths = resolveHaivePaths35(root);
10169
- if (!existsSync40(paths.haiveDir)) {
10277
+ if (!existsSync41(paths.haiveDir)) {
10170
10278
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
10171
10279
  process.exit(1);
10172
10280
  }
@@ -10185,7 +10293,7 @@ async function runWithEnforcement(command, args, opts) {
10185
10293
  process.exit(2);
10186
10294
  }
10187
10295
  ui.info(`Hivelore briefing marker created for wrapped agent session: ${sessionId}`);
10188
- ui.info(`Briefing written to ${path38.relative(root, briefingFile)} and exported as HAIVE_BRIEFING_FILE`);
10296
+ ui.info(`Briefing written to ${path39.relative(root, briefingFile)} and exported as HAIVE_BRIEFING_FILE`);
10189
10297
  const child = spawn4(command, args, {
10190
10298
  cwd: root,
10191
10299
  stdio: "inherit",
@@ -10237,9 +10345,9 @@ async function writeWrapperBriefing(paths, sessionId, task) {
10237
10345
  source: "haive-run",
10238
10346
  memoryIds: briefing.memories.map((m) => m.id)
10239
10347
  });
10240
- const dir = path38.join(paths.runtimeDir, "enforcement", "briefings");
10348
+ const dir = path39.join(paths.runtimeDir, "enforcement", "briefings");
10241
10349
  await mkdir16(dir, { recursive: true });
10242
- const file = path38.join(dir, `${sessionId}.md`);
10350
+ const file = path39.join(dir, `${sessionId}.md`);
10243
10351
  const parts = [
10244
10352
  "# Hivelore Briefing",
10245
10353
  "",
@@ -10277,7 +10385,7 @@ async function checkBootstrapComplete(paths, config, productionCodeChanged) {
10277
10385
  projectContextRaw = await readFile18(paths.projectContext, "utf8");
10278
10386
  } catch {
10279
10387
  }
10280
- const memories = existsSync40(paths.memoriesDir) ? await loadMemoriesFromDir15(paths.memoriesDir) : [];
10388
+ const memories = existsSync41(paths.memoriesDir) ? await loadMemoriesFromDir14(paths.memoriesDir) : [];
10281
10389
  const codeMap = await loadCodeMap7(paths);
10282
10390
  const codeFiles = codeMap ? Object.keys(codeMap.files) : [];
10283
10391
  let existingModules = [];
@@ -10309,7 +10417,7 @@ ${renderBootstrapChecklist(assessment)}`,
10309
10417
  async function buildEnforcementReport(dir, stage, sessionId) {
10310
10418
  const root = findProjectRoot37(dir);
10311
10419
  const paths = resolveHaivePaths35(root);
10312
- const initialized = existsSync40(paths.haiveDir);
10420
+ const initialized = existsSync41(paths.haiveDir);
10313
10421
  const config = initialized ? await loadConfig12(paths) : {};
10314
10422
  if (initialized) {
10315
10423
  await applyLightweightRepairs(root, paths);
@@ -10343,7 +10451,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
10343
10451
  findings: [{ severity: "info", code: "enforcement-off", message: "Hivelore enforcement is disabled." }]
10344
10452
  });
10345
10453
  }
10346
- findings.push(...await inspectIntegrationVersions(root, "0.33.0"));
10454
+ findings.push(...await inspectIntegrationVersions(root, "0.34.1"));
10347
10455
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
10348
10456
  const hasBriefing = await hasRecentBriefingMarker(paths, sessionId);
10349
10457
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent Hivelore briefing marker exists." } : {
@@ -10446,8 +10554,8 @@ function withCategories(report) {
10446
10554
  async function hasRecentSessionRecap(paths) {
10447
10555
  const handoffAge = await handoffAgeMs(paths.root);
10448
10556
  if (handoffAge !== null && handoffAge < SESSION_RECAP_TTL_MS) return true;
10449
- if (!existsSync40(paths.memoriesDir)) return false;
10450
- const all = await loadMemoriesFromDir15(paths.memoriesDir);
10557
+ if (!existsSync41(paths.memoriesDir)) return false;
10558
+ const all = await loadMemoriesFromDir14(paths.memoriesDir);
10451
10559
  return all.some(({ memory: memory2 }) => {
10452
10560
  const fm = memory2.frontmatter;
10453
10561
  const freshnessDate = fm.verified_at ?? fm.created_at;
@@ -10455,8 +10563,8 @@ async function hasRecentSessionRecap(paths) {
10455
10563
  });
10456
10564
  }
10457
10565
  async function verifyMemoryPolicy(paths, config) {
10458
- if (!existsSync40(paths.memoriesDir)) return [];
10459
- const all = await loadMemoriesFromDir15(paths.memoriesDir);
10566
+ if (!existsSync41(paths.memoriesDir)) return [];
10567
+ const all = await loadMemoriesFromDir14(paths.memoriesDir);
10460
10568
  const findings = [];
10461
10569
  const staleImportant = [];
10462
10570
  let verified = 0;
@@ -10493,12 +10601,12 @@ async function verifyMemoryPolicy(paths, config) {
10493
10601
  return findings;
10494
10602
  }
10495
10603
  async function verifyDecisionCoverage(paths, stage, sessionId) {
10496
- if (!existsSync40(paths.memoriesDir)) return [];
10604
+ if (!existsSync41(paths.memoriesDir)) return [];
10497
10605
  const changedFiles = (await getChangedFiles(paths.root, stage)).filter((f) => !isGeneratedArtifact(f));
10498
10606
  if (changedFiles.length === 0) {
10499
10607
  return [{ severity: "info", code: "decision-coverage-no-changes", message: "No changed files to match against policy memories." }];
10500
10608
  }
10501
- const all = await loadMemoriesFromDir15(paths.memoriesDir);
10609
+ const all = await loadMemoriesFromDir14(paths.memoriesDir);
10502
10610
  const changedSet = new Set(changedFiles);
10503
10611
  const policyTypes = /* @__PURE__ */ new Set(["decision", "gotcha", "architecture", "convention"]);
10504
10612
  const relevant = all.filter(({ memory: memory2 }) => {
@@ -10527,7 +10635,7 @@ async function verifyDecisionCoverage(paths, stage, sessionId) {
10527
10635
  const consulted = new Set(marker?.memory_ids ?? []);
10528
10636
  const missing = relevant.filter(({ memory: memory2, filePath }) => {
10529
10637
  if (consulted.has(memory2.frontmatter.id)) return false;
10530
- if (changedSet.has(path38.relative(paths.root, filePath))) return false;
10638
+ if (changedSet.has(path39.relative(paths.root, filePath))) return false;
10531
10639
  return true;
10532
10640
  }).map(({ memory: memory2 }) => memory2);
10533
10641
  if (missing.length === 0) {
@@ -10592,7 +10700,7 @@ async function runPrecommitPolicy(paths, gate, stage) {
10592
10700
  (w) => w.level === "review" && !w.reasons.includes("sensor")
10593
10701
  );
10594
10702
  const REVIEW_SEEN_TTL_MS = 24 * 60 * 60 * 1e3;
10595
- const reviewSeenFile = path38.join(paths.runtimeDir, "enforcement", "review-seen.json");
10703
+ const reviewSeenFile = path39.join(paths.runtimeDir, "enforcement", "review-seen.json");
10596
10704
  let reviewSeen = {};
10597
10705
  try {
10598
10706
  reviewSeen = JSON.parse(await readFile18(reviewSeenFile, "utf8"));
@@ -10619,7 +10727,7 @@ async function runPrecommitPolicy(paths, gate, stage) {
10619
10727
  for (const [id, at] of Object.entries(reviewSeen)) {
10620
10728
  if (!Number.isFinite(Date.parse(at)) || now - Date.parse(at) >= REVIEW_SEEN_TTL_MS) delete reviewSeen[id];
10621
10729
  }
10622
- await mkdir16(path38.dirname(reviewSeenFile), { recursive: true });
10730
+ await mkdir16(path39.dirname(reviewSeenFile), { recursive: true });
10623
10731
  await writeFile25(reviewSeenFile, JSON.stringify(reviewSeen, null, 2), "utf8");
10624
10732
  } catch {
10625
10733
  }
@@ -10651,9 +10759,9 @@ async function runPrecommitPolicy(paths, gate, stage) {
10651
10759
  ];
10652
10760
  }
10653
10761
  async function runSensorGate(paths, diff) {
10654
- if (!diff || !existsSync40(paths.memoriesDir)) return [];
10762
+ if (!diff || !existsSync41(paths.memoriesDir)) return [];
10655
10763
  try {
10656
- const loaded = await loadMemoriesFromDir15(paths.memoriesDir);
10764
+ const loaded = await loadMemoriesFromDir14(paths.memoriesDir);
10657
10765
  const scannable = loaded.map((l) => l.memory).filter((m) => Boolean(m.frontmatter.sensor) && !isRetiredMemory2(m.frontmatter, m.body));
10658
10766
  if (scannable.length === 0) return [];
10659
10767
  const targets = sensorTargetsFromDiff(diff).filter((t) => isSensorScannablePath(t.path));
@@ -10766,16 +10874,16 @@ async function cleanupRuntimeDir(runtimeDir) {
10766
10874
  for (const entry of entries) {
10767
10875
  if (entry.name === ".gitignore" || entry.name === "README.md") continue;
10768
10876
  if (entry.name === "enforcement") {
10769
- removed += await cleanupEnforcementDir(path38.join(runtimeDir, entry.name));
10877
+ removed += await cleanupEnforcementDir(path39.join(runtimeDir, entry.name));
10770
10878
  continue;
10771
10879
  }
10772
- await rm2(path38.join(runtimeDir, entry.name), { recursive: true, force: true });
10880
+ await rm2(path39.join(runtimeDir, entry.name), { recursive: true, force: true });
10773
10881
  removed++;
10774
10882
  }
10775
- await writeFile25(path38.join(runtimeDir, ".gitignore"), "*\n!.gitignore\n!README.md\n", "utf8");
10776
- if (!existsSync40(path38.join(runtimeDir, "README.md"))) {
10883
+ await writeFile25(path39.join(runtimeDir, ".gitignore"), "*\n!.gitignore\n!README.md\n", "utf8");
10884
+ if (!existsSync41(path39.join(runtimeDir, "README.md"))) {
10777
10885
  await writeFile25(
10778
- path38.join(runtimeDir, "README.md"),
10886
+ path39.join(runtimeDir, "README.md"),
10779
10887
  "# .ai/.runtime \u2014 disposable local layer\n\nRuntime data is local. Hivelore cleanup preserves briefing markers so enforcement state remains valid.\n",
10780
10888
  "utf8"
10781
10889
  );
@@ -10788,10 +10896,10 @@ async function cleanupCacheDir(cacheDir) {
10788
10896
  const entries = await readdir4(cacheDir, { withFileTypes: true }).catch(() => []);
10789
10897
  for (const entry of entries) {
10790
10898
  if (entry.name === ".gitignore") continue;
10791
- await rm2(path38.join(cacheDir, entry.name), { recursive: true, force: true });
10899
+ await rm2(path39.join(cacheDir, entry.name), { recursive: true, force: true });
10792
10900
  removed++;
10793
10901
  }
10794
- await writeFile25(path38.join(cacheDir, ".gitignore"), "*\n!.gitignore\n", "utf8");
10902
+ await writeFile25(path39.join(cacheDir, ".gitignore"), "*\n!.gitignore\n", "utf8");
10795
10903
  return removed;
10796
10904
  }
10797
10905
  async function cleanupEnforcementDir(enforcementDir) {
@@ -10799,7 +10907,7 @@ async function cleanupEnforcementDir(enforcementDir) {
10799
10907
  const entries = await readdir4(enforcementDir, { withFileTypes: true }).catch(() => []);
10800
10908
  for (const entry of entries) {
10801
10909
  if (entry.name === "briefings") continue;
10802
- await rm2(path38.join(enforcementDir, entry.name), { recursive: true, force: true });
10910
+ await rm2(path39.join(enforcementDir, entry.name), { recursive: true, force: true });
10803
10911
  removed++;
10804
10912
  }
10805
10913
  return removed;
@@ -10817,8 +10925,8 @@ async function inspectIntegrationVersions(root, expectedVersion) {
10817
10925
  const missingBins = /* @__PURE__ */ new Map();
10818
10926
  const staleBins = /* @__PURE__ */ new Map();
10819
10927
  for (const rel of files) {
10820
- const file = path38.join(root, rel);
10821
- if (!existsSync40(file)) continue;
10928
+ const file = path39.join(root, rel);
10929
+ if (!existsSync41(file)) continue;
10822
10930
  const text = await readFile18(file, "utf8").catch(() => "");
10823
10931
  for (const bin of extractAbsoluteHaiveBins2(text)) {
10824
10932
  const version = versionForBinary2(bin);
@@ -10935,7 +11043,7 @@ async function resolveCiDiffRange(root) {
10935
11043
  }
10936
11044
  async function resolveGithubEventRange(root) {
10937
11045
  const eventPath = process.env.GITHUB_EVENT_PATH;
10938
- if (!eventPath || !existsSync40(eventPath)) return null;
11046
+ if (!eventPath || !existsSync41(eventPath)) return null;
10939
11047
  try {
10940
11048
  const event = JSON.parse(await readFile18(eventPath, "utf8"));
10941
11049
  const prBase = cleanGitSha(event.pull_request?.base?.sha);
@@ -11040,7 +11148,7 @@ function isShippablePath(file) {
11040
11148
  }
11041
11149
  var CI_SKIP_DIRECTIVE = /\[skip ci\]|\[ci skip\]|\[no ci\]|\[skip actions\]|\*\*\*NO_CI\*\*\*|skip-checks: *true/i;
11042
11150
  async function checkCommitMessageSkipCi(root, msgfile) {
11043
- const file = path38.isAbsolute(msgfile) ? msgfile : path38.join(root, msgfile);
11151
+ const file = path39.isAbsolute(msgfile) ? msgfile : path39.join(root, msgfile);
11044
11152
  const raw = await readFile18(file, "utf8").catch(() => "");
11045
11153
  const cleaned = raw.split("\n").filter((line) => !line.startsWith("#")).join("\n");
11046
11154
  if (!CI_SKIP_DIRECTIVE.test(cleaned)) return { block: false, message: "" };
@@ -11069,7 +11177,7 @@ async function inspectReleaseVersionState(root, upstream) {
11069
11177
  }
11070
11178
  async function readPackageVersion(root, relPath) {
11071
11179
  try {
11072
- const data = JSON.parse(await readFile18(path38.join(root, relPath), "utf8"));
11180
+ const data = JSON.parse(await readFile18(path39.join(root, relPath), "utf8"));
11073
11181
  return typeof data.version === "string" ? data.version : void 0;
11074
11182
  } catch {
11075
11183
  return void 0;
@@ -11257,8 +11365,8 @@ function buildScore(findings, threshold = 80) {
11257
11365
  };
11258
11366
  }
11259
11367
  async function installGitEnforcement(root) {
11260
- const hooksDir = path38.join(root, ".git", "hooks");
11261
- if (!existsSync40(path38.join(root, ".git"))) {
11368
+ const hooksDir = path39.join(root, ".git", "hooks");
11369
+ if (!existsSync41(path39.join(root, ".git"))) {
11262
11370
  ui.warn("No .git directory found; git enforcement hooks skipped.");
11263
11371
  return;
11264
11372
  }
@@ -11314,8 +11422,8 @@ _hivelore sync --quiet --since ORIG_HEAD || true
11314
11422
  }
11315
11423
  ];
11316
11424
  for (const hook of hooks) {
11317
- const file = path38.join(hooksDir, hook.name);
11318
- if (existsSync40(file)) {
11425
+ const file = path39.join(hooksDir, hook.name);
11426
+ if (existsSync41(file)) {
11319
11427
  const current = await readFile18(file, "utf8").catch(() => "");
11320
11428
  if (current.includes(ENFORCE_HOOK_MARKER)) {
11321
11429
  await writeFile25(file, hook.body, "utf8");
@@ -11332,9 +11440,9 @@ ${hook.body}`, "utf8");
11332
11440
  ui.success("Installed git hooks: pre-commit, pre-push, commit-msg (blocking) + post-merge, post-rewrite (sync)");
11333
11441
  }
11334
11442
  async function installCiEnforcement(root) {
11335
- const workflowPath = path38.join(root, ".github", "workflows", "haive-enforcement.yml");
11336
- await mkdir16(path38.dirname(workflowPath), { recursive: true });
11337
- if (existsSync40(workflowPath)) {
11443
+ const workflowPath = path39.join(root, ".github", "workflows", "haive-enforcement.yml");
11444
+ await mkdir16(path39.dirname(workflowPath), { recursive: true });
11445
+ if (existsSync41(workflowPath)) {
11338
11446
  ui.info("GitHub Actions enforcement workflow already exists \u2014 skipped");
11339
11447
  return;
11340
11448
  }
@@ -11365,7 +11473,7 @@ jobs:
11365
11473
  HAIVE_HEAD_SHA: \${{ github.event.pull_request.head.sha || github.sha }}
11366
11474
  run: hivelore enforce ci
11367
11475
  `, "utf8");
11368
- ui.success(`Created ${path38.relative(root, workflowPath)}`);
11476
+ ui.success(`Created ${path39.relative(root, workflowPath)}`);
11369
11477
  }
11370
11478
  function printReport(report, json, explain = false) {
11371
11479
  if (json) {
@@ -11469,15 +11577,15 @@ function extractToolPaths(payload, root) {
11469
11577
  }
11470
11578
  function normalizeToolPath(file, root) {
11471
11579
  const normalized = file.replace(/\\/g, "/");
11472
- if (!path38.isAbsolute(normalized)) return normalized.replace(/^\.\//, "");
11473
- return path38.relative(root, normalized).replace(/\\/g, "/");
11580
+ if (!path39.isAbsolute(normalized)) return normalized.replace(/^\.\//, "");
11581
+ return path39.relative(root, normalized).replace(/\\/g, "/");
11474
11582
  }
11475
11583
  async function missingRequiredMemoriesForFiles(paths, files, sessionId) {
11476
- if (!existsSync40(paths.memoriesDir)) return [];
11584
+ if (!existsSync41(paths.memoriesDir)) return [];
11477
11585
  const marker = await readRecentBriefingMarker(paths, sessionId);
11478
11586
  const consulted = new Set(marker?.memory_ids ?? []);
11479
11587
  const policyTypes = /* @__PURE__ */ new Set(["decision", "gotcha", "architecture", "convention", "attempt"]);
11480
- const all = await loadMemoriesFromDir15(paths.memoriesDir);
11588
+ const all = await loadMemoriesFromDir14(paths.memoriesDir);
11481
11589
  return all.filter(({ memory: memory2 }) => {
11482
11590
  const fm = memory2.frontmatter;
11483
11591
  if (!policyTypes.has(fm.type)) return false;
@@ -11518,7 +11626,7 @@ async function readStdin2(maxBytes) {
11518
11626
  }
11519
11627
  var ATOMIC_STAGE_EXCLUDE = ["/.usage/", "/.runtime/", "/.cache/"];
11520
11628
  async function stageResyncedArtifacts(root, paths) {
11521
- const aiRel = path38.relative(root, paths.haiveDir);
11629
+ const aiRel = path39.relative(root, paths.haiveDir);
11522
11630
  const out = await runCommand2("git", ["diff", "--name-only", "--", aiRel], root).catch(() => "");
11523
11631
  const toStage = out.split("\n").map((line) => line.trim()).filter(Boolean).filter((file) => !ATOMIC_STAGE_EXCLUDE.some((excl) => `/${file}`.includes(excl)));
11524
11632
  if (toStage.length === 0) return;
@@ -11545,9 +11653,9 @@ function runCommand2(cmd, args, cwd) {
11545
11653
  }
11546
11654
 
11547
11655
  // src/commands/release.ts
11548
- import { existsSync as existsSync41 } from "fs";
11656
+ import { existsSync as existsSync42 } from "fs";
11549
11657
  import { readFile as readFile19, writeFile as writeFile26 } from "fs/promises";
11550
- import path39 from "path";
11658
+ import path40 from "path";
11551
11659
  import "commander";
11552
11660
  import { findProjectRoot as findProjectRoot38 } from "@hivelore/core";
11553
11661
  import { execFile as execFile5 } from "child_process";
@@ -11561,7 +11669,7 @@ var VERSION_FILES2 = [
11561
11669
  "packages/embeddings/package.json"
11562
11670
  ];
11563
11671
  async function readCurrentVersion(root) {
11564
- const pkg = JSON.parse(await readFile19(path39.join(root, "package.json"), "utf8"));
11672
+ const pkg = JSON.parse(await readFile19(path40.join(root, "package.json"), "utf8"));
11565
11673
  if (!pkg.version) throw new Error("Root package.json has no version field.");
11566
11674
  return pkg.version;
11567
11675
  }
@@ -11582,8 +11690,8 @@ function registerRelease(program2) {
11582
11690
  const current = await readCurrentVersion(root);
11583
11691
  const next = nextVersion(current, spec);
11584
11692
  for (const rel of VERSION_FILES2) {
11585
- const file = path39.join(root, rel);
11586
- if (!existsSync41(file)) {
11693
+ const file = path40.join(root, rel);
11694
+ if (!existsSync42(file)) {
11587
11695
  ui.warn(`skip ${rel} (missing)`);
11588
11696
  continue;
11589
11697
  }
@@ -11596,8 +11704,8 @@ function registerRelease(program2) {
11596
11704
  }
11597
11705
  await writeFile26(file, updated, "utf8");
11598
11706
  }
11599
- const changelog = path39.join(root, "CHANGELOG.md");
11600
- if (existsSync41(changelog)) {
11707
+ const changelog = path40.join(root, "CHANGELOG.md");
11708
+ if (existsSync42(changelog)) {
11601
11709
  const raw = await readFile19(changelog, "utf8");
11602
11710
  const heading = `## [${next}]${opts.title ? ` \u2014 ${opts.title}` : ""}`;
11603
11711
  if (!raw.includes(`## [${next}]`)) {
@@ -11620,8 +11728,8 @@ ${heading}
11620
11728
  const root = findProjectRoot38(opts.dir);
11621
11729
  const version = await readCurrentVersion(root);
11622
11730
  for (const rel of VERSION_FILES2.slice(1)) {
11623
- const file = path39.join(root, rel);
11624
- if (!existsSync41(file)) continue;
11731
+ const file = path40.join(root, rel);
11732
+ if (!existsSync42(file)) continue;
11625
11733
  const v = JSON.parse(await readFile19(file, "utf8")).version;
11626
11734
  if (v !== version) {
11627
11735
  ui.error(`${rel} is at ${v}, root at ${version} \u2014 lockstep broken; run \`hivelore release bump\` first.`);
@@ -11667,9 +11775,9 @@ function registerRun(program2) {
11667
11775
 
11668
11776
  // src/commands/sensors.ts
11669
11777
  import { execFile as execFile6 } from "child_process";
11670
- import { existsSync as existsSync42 } from "fs";
11778
+ import { existsSync as existsSync43 } from "fs";
11671
11779
  import { chmod as chmod2, mkdir as mkdir17, readFile as readFile20, writeFile as writeFile27 } from "fs/promises";
11672
- import path40 from "path";
11780
+ import path41 from "path";
11673
11781
  import { promisify as promisify6 } from "util";
11674
11782
  import "commander";
11675
11783
  import {
@@ -11678,7 +11786,7 @@ import {
11678
11786
  isRetiredMemory as isRetiredMemory3,
11679
11787
  judgeProposedSensor,
11680
11788
  loadConfig as loadConfig13,
11681
- loadMemoriesFromDir as loadMemoriesFromDir16,
11789
+ loadMemoriesFromDir as loadMemoriesFromDir15,
11682
11790
  recordPreventionHits as recordPreventionHits2,
11683
11791
  resolveHaivePaths as resolveHaivePaths36,
11684
11792
  runSensors as runSensors2,
@@ -11724,7 +11832,7 @@ function registerSensors(program2) {
11724
11832
  const root = findProjectRoot39(opts.dir);
11725
11833
  const paths = resolveHaivePaths36(root);
11726
11834
  const memories = await runnableSensorMemories(paths);
11727
- const diff = opts.diffFile ? await readFile20(path40.resolve(root, opts.diffFile), "utf8") : await stagedDiff(root);
11835
+ const diff = opts.diffFile ? await readFile20(path41.resolve(root, opts.diffFile), "utf8") : await stagedDiff(root);
11728
11836
  const targets = scannableSensorTargets(diff);
11729
11837
  const hits = runSensors2(memories, targets);
11730
11838
  const config = await loadConfig13(paths);
@@ -11812,7 +11920,7 @@ function registerSensors(program2) {
11812
11920
  }
11813
11921
  const root = findProjectRoot39(opts.dir);
11814
11922
  const paths = resolveHaivePaths36(root);
11815
- const loaded = existsSync42(paths.memoriesDir) ? await loadMemoriesFromDir16(paths.memoriesDir) : [];
11923
+ const loaded = existsSync43(paths.memoriesDir) ? await loadMemoriesFromDir15(paths.memoriesDir) : [];
11816
11924
  const found = loaded.find(({ memory: memory2 }) => memory2.frontmatter.id === id);
11817
11925
  if (!found) {
11818
11926
  ui.error(`No memory found with id ${id}`);
@@ -11877,7 +11985,7 @@ function registerSensors(program2) {
11877
11985
  return;
11878
11986
  }
11879
11987
  const root2 = findProjectRoot39(opts.dir);
11880
- const { proposeSensor } = await import("./server-LZKYO5O5.js");
11988
+ const { proposeSensor } = await import("./server-FQ5C43MV.js");
11881
11989
  const out = await proposeSensor(
11882
11990
  {
11883
11991
  memory_id: id,
@@ -11920,7 +12028,7 @@ function registerSensors(program2) {
11920
12028
  }
11921
12029
  const root = findProjectRoot39(opts.dir);
11922
12030
  const paths = resolveHaivePaths36(root);
11923
- const loaded = existsSync42(paths.memoriesDir) ? await loadMemoriesFromDir16(paths.memoriesDir) : [];
12031
+ const loaded = existsSync43(paths.memoriesDir) ? await loadMemoriesFromDir15(paths.memoriesDir) : [];
11924
12032
  const found = loaded.find(({ memory: memory2 }) => memory2.frontmatter.id === id);
11925
12033
  if (!found) {
11926
12034
  ui.error(`No memory found with id ${id}`);
@@ -11974,13 +12082,13 @@ function registerSensors(program2) {
11974
12082
  const root = findProjectRoot39(opts.dir);
11975
12083
  const paths = resolveHaivePaths36(root);
11976
12084
  const rows = await sensorRows(paths);
11977
- const outDir = path40.resolve(root, opts.outDir ?? ".ai/generated");
12085
+ const outDir = path41.resolve(root, opts.outDir ?? ".ai/generated");
11978
12086
  await mkdir17(outDir, { recursive: true });
11979
- const outPath = path40.join(outDir, format === "grep" ? "haive-sensors-grep.sh" : "haive-sensors-eslint.json");
12087
+ const outPath = path41.join(outDir, format === "grep" ? "haive-sensors-grep.sh" : "haive-sensors-eslint.json");
11980
12088
  const content = format === "grep" ? renderGrepScript(rows) : JSON.stringify({ sensors: rows }, null, 2) + "\n";
11981
12089
  await writeFile27(outPath, content, "utf8");
11982
12090
  if (format === "grep") await chmod2(outPath, 493);
11983
- ui.success(`Exported ${rows.length} sensor(s): ${path40.relative(root, outPath)}`);
12091
+ ui.success(`Exported ${rows.length} sensor(s): ${path41.relative(root, outPath)}`);
11984
12092
  });
11985
12093
  }
11986
12094
  function deriveProposedMessage(body, pattern, absent) {
@@ -12013,8 +12121,8 @@ async function sensorRows(paths) {
12013
12121
  });
12014
12122
  }
12015
12123
  async function runnableSensorMemories(paths, regexOnly = true) {
12016
- if (!existsSync42(paths.memoriesDir)) return [];
12017
- const loaded = await loadMemoriesFromDir16(paths.memoriesDir);
12124
+ if (!existsSync43(paths.memoriesDir)) return [];
12125
+ const loaded = await loadMemoriesFromDir15(paths.memoriesDir);
12018
12126
  return loaded.map(({ memory: memory2 }) => memory2).filter((memory2) => {
12019
12127
  const sensor = memory2.frontmatter.sensor;
12020
12128
  if (!sensor) return false;
@@ -12055,15 +12163,15 @@ function shellQuote(value) {
12055
12163
  }
12056
12164
 
12057
12165
  // src/commands/ingest.ts
12058
- import { existsSync as existsSync43 } from "fs";
12166
+ import { existsSync as existsSync44 } from "fs";
12059
12167
  import { mkdir as mkdir18, readFile as readFile21, writeFile as writeFile28 } from "fs/promises";
12060
- import path41 from "path";
12168
+ import path42 from "path";
12061
12169
  import "commander";
12062
12170
  import {
12063
12171
  draftsFromFindings,
12064
12172
  filterNewDrafts,
12065
12173
  findProjectRoot as findProjectRoot40,
12066
- loadMemoriesFromDir as loadMemoriesFromDir17,
12174
+ loadMemoriesFromDir as loadMemoriesFromDir16,
12067
12175
  memoryFilePath as memoryFilePath7,
12068
12176
  parseFindings,
12069
12177
  resolveHaivePaths as resolveHaivePaths37,
@@ -12093,7 +12201,7 @@ function registerIngest(program2) {
12093
12201
  }
12094
12202
  const root = findProjectRoot40(opts.dir);
12095
12203
  const paths = resolveHaivePaths37(root);
12096
- if (!existsSync43(paths.haiveDir)) {
12204
+ if (!existsSync44(paths.haiveDir)) {
12097
12205
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
12098
12206
  process.exitCode = 1;
12099
12207
  return;
@@ -12114,8 +12222,8 @@ function registerIngest(program2) {
12114
12222
  process.exitCode = 1;
12115
12223
  return;
12116
12224
  }
12117
- const reportPath = path41.resolve(root, file);
12118
- if (!existsSync43(reportPath)) {
12225
+ const reportPath = path42.resolve(root, file);
12226
+ if (!existsSync44(reportPath)) {
12119
12227
  ui.error(`Report file not found: ${reportPath}`);
12120
12228
  process.exitCode = 1;
12121
12229
  return;
@@ -12147,7 +12255,7 @@ function registerIngest(program2) {
12147
12255
  process.exitCode = 1;
12148
12256
  return;
12149
12257
  }
12150
- const existing = existsSync43(paths.memoriesDir) ? await loadMemoriesFromDir17(paths.memoriesDir) : [];
12258
+ const existing = existsSync44(paths.memoriesDir) ? await loadMemoriesFromDir16(paths.memoriesDir) : [];
12151
12259
  const existingTopics = new Set(
12152
12260
  existing.map(({ memory: memory2 }) => memory2.frontmatter.topic).filter((t) => Boolean(t))
12153
12261
  );
@@ -12209,13 +12317,13 @@ function registerIngest(program2) {
12209
12317
  await writeDraft(paths, draft);
12210
12318
  created++;
12211
12319
  }
12212
- ui.success(`Created ${created} proposed memory(ies) under ${path41.relative(root, paths.memoriesDir)}/`);
12320
+ ui.success(`Created ${created} proposed memory(ies) under ${path42.relative(root, paths.memoriesDir)}/`);
12213
12321
  ui.info("Review with `hivelore memory pending`; promote sensors with `hivelore sensors promote <id> --yes`.");
12214
12322
  });
12215
12323
  }
12216
12324
  async function writeDraft(paths, draft) {
12217
12325
  const file = memoryFilePath7(paths, draft.frontmatter.scope, draft.frontmatter.id, draft.frontmatter.module);
12218
- await mkdir18(path41.dirname(file), { recursive: true });
12326
+ await mkdir18(path42.dirname(file), { recursive: true });
12219
12327
  await writeFile28(file, serializeMemory16({ frontmatter: draft.frontmatter, body: draft.body }), "utf8");
12220
12328
  return file;
12221
12329
  }
@@ -12257,13 +12365,13 @@ async function fetchSonarIssues(opts) {
12257
12365
  }
12258
12366
 
12259
12367
  // src/commands/dashboard.ts
12260
- import { existsSync as existsSync44 } from "fs";
12368
+ import { existsSync as existsSync45 } from "fs";
12261
12369
  import "commander";
12262
12370
  import {
12263
12371
  buildDashboard,
12264
12372
  findProjectRoot as findProjectRoot41,
12265
12373
  loadConfig as loadConfig14,
12266
- loadMemoriesFromDir as loadMemoriesFromDir18,
12374
+ loadMemoriesFromDir as loadMemoriesFromDir17,
12267
12375
  loadPreventionEvents as loadPreventionEvents3,
12268
12376
  loadUsageIndex as loadUsageIndex16,
12269
12377
  resolveHaivePaths as resolveHaivePaths38
@@ -12274,12 +12382,12 @@ function registerDashboard(program2) {
12274
12382
  ).option("--json", "emit the full report as JSON", false).option("--top <n>", "rows per top-list", "10").option("--dormant-days <n>", "dormancy window for impact scoring").option("-d, --dir <dir>", "project root").action(async (opts) => {
12275
12383
  const root = findProjectRoot41(opts.dir);
12276
12384
  const paths = resolveHaivePaths38(root);
12277
- if (!existsSync44(paths.haiveDir)) {
12385
+ if (!existsSync45(paths.haiveDir)) {
12278
12386
  ui.error(`No .ai/ found at ${root}. Run \`hivelore init\` first.`);
12279
12387
  process.exitCode = 1;
12280
12388
  return;
12281
12389
  }
12282
- const memories = existsSync44(paths.memoriesDir) ? await loadMemoriesFromDir18(paths.memoriesDir) : [];
12390
+ const memories = existsSync45(paths.memoriesDir) ? await loadMemoriesFromDir17(paths.memoriesDir) : [];
12283
12391
  const usage = await loadUsageIndex16(paths);
12284
12392
  const preventionEvents = await loadPreventionEvents3(paths);
12285
12393
  const config = await loadConfig14(paths);
@@ -12405,8 +12513,8 @@ function warnNum(n) {
12405
12513
  // src/commands/dev-link.ts
12406
12514
  import { execFile as execFile7 } from "child_process";
12407
12515
  import { cp, readFile as readFile22 } from "fs/promises";
12408
- import { existsSync as existsSync45 } from "fs";
12409
- import path42 from "path";
12516
+ import { existsSync as existsSync46 } from "fs";
12517
+ import path43 from "path";
12410
12518
  import { promisify as promisify7 } from "util";
12411
12519
  import "commander";
12412
12520
  import { findProjectRoot as findProjectRoot42 } from "@hivelore/core";
@@ -12415,7 +12523,7 @@ function registerDevLink(program2) {
12415
12523
  const dev = program2.commands.find((c) => c.name() === "dev") ?? program2.command("dev").description("Developer utilities for working on Hivelore itself.");
12416
12524
  dev.command("link").description("Hot-swap this repo's built dist into the global @hivelore (or legacy @hiveai) install so the global binary runs your local code.").option("-d, --dir <dir>", "repo root (default: discovered from cwd)").option("--json", "emit a machine-readable summary", false).action(async (opts) => {
12417
12525
  const root = findProjectRoot42(opts.dir);
12418
- if (!existsSync45(path42.join(root, "packages", "cli", "dist", "index.js"))) {
12526
+ if (!existsSync46(path43.join(root, "packages", "cli", "dist", "index.js"))) {
12419
12527
  ui.error(`Not the Hivelore monorepo (no packages/cli/dist) at ${root}. Run \`pnpm -r build\` first, or pass --dir.`);
12420
12528
  process.exitCode = 1;
12421
12529
  return;
@@ -12424,9 +12532,9 @@ function registerDevLink(program2) {
12424
12532
  try {
12425
12533
  globalModules = (await exec5("npm", ["root", "-g"])).stdout.trim();
12426
12534
  } catch {
12427
- globalModules = path42.join(path42.dirname(path42.dirname(process.execPath)), "lib", "node_modules");
12535
+ globalModules = path43.join(path43.dirname(path43.dirname(process.execPath)), "lib", "node_modules");
12428
12536
  }
12429
- const scopeDirs = ["@hivelore", "@hiveai"].map((scope) => path42.join(globalModules, scope)).filter((dir) => existsSync45(dir));
12537
+ const scopeDirs = ["@hivelore", "@hiveai"].map((scope) => path43.join(globalModules, scope)).filter((dir) => existsSync46(dir));
12430
12538
  if (scopeDirs.length === 0) {
12431
12539
  ui.error(`No global @hivelore (or legacy @hiveai) install under ${globalModules}. Install once with \`npm i -g @hivelore/cli\`, then re-run.`);
12432
12540
  process.exitCode = 1;
@@ -12434,24 +12542,24 @@ function registerDevLink(program2) {
12434
12542
  }
12435
12543
  const linked = [];
12436
12544
  const copyDist = async (fromPkg, toDistDir) => {
12437
- const from = path42.join(root, "packages", fromPkg, "dist");
12438
- if (!existsSync45(from) || !existsSync45(path42.dirname(toDistDir))) return;
12545
+ const from = path43.join(root, "packages", fromPkg, "dist");
12546
+ if (!existsSync46(from) || !existsSync46(path43.dirname(toDistDir))) return;
12439
12547
  await cp(from, toDistDir, { recursive: true });
12440
- linked.push(path42.relative(globalModules, toDistDir));
12548
+ linked.push(path43.relative(globalModules, toDistDir));
12441
12549
  };
12442
12550
  for (const globalHive of scopeDirs) {
12443
- const nestedScope = path42.basename(globalHive);
12551
+ const nestedScope = path43.basename(globalHive);
12444
12552
  for (const pkg of ["cli", "mcp"]) {
12445
- await copyDist(pkg, path42.join(globalHive, pkg, "dist"));
12553
+ await copyDist(pkg, path43.join(globalHive, pkg, "dist"));
12446
12554
  for (const nested of ["core", "embeddings"]) {
12447
- await copyDist(nested, path42.join(globalHive, pkg, "node_modules", nestedScope, nested, "dist"));
12555
+ await copyDist(nested, path43.join(globalHive, pkg, "node_modules", nestedScope, nested, "dist"));
12448
12556
  }
12449
12557
  }
12450
- await copyDist("core", path42.join(globalHive, "core", "dist"));
12558
+ await copyDist("core", path43.join(globalHive, "core", "dist"));
12451
12559
  }
12452
12560
  let version = "unknown";
12453
12561
  try {
12454
- version = JSON.parse(await readFile22(path42.join(root, "package.json"), "utf8")).version ?? "unknown";
12562
+ version = JSON.parse(await readFile22(path43.join(root, "package.json"), "utf8")).version ?? "unknown";
12455
12563
  } catch {
12456
12564
  }
12457
12565
  if (opts.json) {
@@ -12462,7 +12570,7 @@ function registerDevLink(program2) {
12462
12570
  ui.warn("Nothing linked \u2014 no matching dist targets were found in the global install.");
12463
12571
  return;
12464
12572
  }
12465
- ui.success(`Linked local dist (v${version}) into the global install(s): ${scopeDirs.map((d) => path42.basename(d)).join(", ")}`);
12573
+ ui.success(`Linked local dist (v${version}) into the global install(s): ${scopeDirs.map((d) => path43.basename(d)).join(", ")}`);
12466
12574
  for (const t of linked) console.log(` ${ui.dim("\u2192")} ${t}`);
12467
12575
  console.log(ui.dim("The global binary now runs your local build (git hooks + MCP included)."));
12468
12576
  });
@@ -12470,8 +12578,8 @@ function registerDevLink(program2) {
12470
12578
 
12471
12579
  // src/commands/coverage.ts
12472
12580
  import { readFile as readFile23 } from "fs/promises";
12473
- import { existsSync as existsSync46 } from "fs";
12474
- import path43 from "path";
12581
+ import { existsSync as existsSync47 } from "fs";
12582
+ import path44 from "path";
12475
12583
  import "commander";
12476
12584
  import {
12477
12585
  findCoverageGaps,
@@ -12481,7 +12589,7 @@ import {
12481
12589
  tallyHotFiles
12482
12590
  } from "@hivelore/core";
12483
12591
  async function readAgentHotFiles(root, cacheFile, sinceMs) {
12484
- if (!existsSync46(cacheFile)) return [];
12592
+ if (!existsSync47(cacheFile)) return [];
12485
12593
  const raw = await readFile23(cacheFile, "utf8").catch(() => "");
12486
12594
  const files = [];
12487
12595
  for (const line of raw.split("\n")) {
@@ -12495,7 +12603,7 @@ async function readAgentHotFiles(root, cacheFile, sinceMs) {
12495
12603
  }
12496
12604
  for (const f of obs.files ?? []) {
12497
12605
  if (typeof f !== "string" || !f) continue;
12498
- const rel = path43.isAbsolute(f) ? path43.relative(root, f) : f;
12606
+ const rel = path44.isAbsolute(f) ? path44.relative(root, f) : f;
12499
12607
  if (rel.startsWith("..")) continue;
12500
12608
  files.push(rel);
12501
12609
  }
@@ -12539,7 +12647,7 @@ function registerCoverage(program2) {
12539
12647
  }) : null;
12540
12648
  const gitHotFiles = (radar?.hotFiles ?? []).filter((h) => !isNoisePath(h.path)).map((h) => ({ path: h.path, changes: h.changes, source: "git" }));
12541
12649
  const sinceMs = Date.now() - days * 864e5;
12542
- const agentHotFiles = useAgent ? (await readAgentHotFiles(root, path43.join(paths.haiveDir, ".cache", "observations.jsonl"), sinceMs)).filter((h) => !isNoisePath(h.path)) : [];
12650
+ const agentHotFiles = useAgent ? (await readAgentHotFiles(root, path44.join(paths.haiveDir, ".cache", "observations.jsonl"), sinceMs)).filter((h) => !isNoisePath(h.path)) : [];
12543
12651
  const hotFiles = mergeHotFiles(gitHotFiles, agentHotFiles);
12544
12652
  const memories = await loadMemoriesFromDir(paths.memoriesDir);
12545
12653
  const gaps = findCoverageGaps(hotFiles, memories, { minChanges, limit });
@@ -12577,8 +12685,8 @@ function registerCoverage(program2) {
12577
12685
 
12578
12686
  // src/commands/merge-driver.ts
12579
12687
  import { execFileSync as execFileSync3 } from "child_process";
12580
- import { readFileSync, writeFileSync, existsSync as existsSync47 } from "fs";
12581
- import path44 from "path";
12688
+ import { readFileSync, writeFileSync, existsSync as existsSync48 } from "fs";
12689
+ import path45 from "path";
12582
12690
  import "commander";
12583
12691
  import { findProjectRoot as findProjectRoot44, mergeMemoryVersions } from "@hivelore/core";
12584
12692
  var GITATTRIBUTES_MARK = "# Hivelore merge driver";
@@ -12610,8 +12718,8 @@ function registerMergeDriver(program2) {
12610
12718
  process.exitCode = 1;
12611
12719
  return;
12612
12720
  }
12613
- const gaPath = path44.join(root, ".gitattributes");
12614
- let content = existsSync47(gaPath) ? readFileSync(gaPath, "utf8") : "";
12721
+ const gaPath = path45.join(root, ".gitattributes");
12722
+ let content = existsSync48(gaPath) ? readFileSync(gaPath, "utf8") : "";
12615
12723
  if (!content.includes(GITATTRIBUTES_MARK)) {
12616
12724
  if (content.length > 0 && !content.endsWith("\n")) content += "\n";
12617
12725
  content += GITATTRIBUTES_BLOCK + "\n";
@@ -12625,21 +12733,21 @@ function registerMergeDriver(program2) {
12625
12733
  }
12626
12734
 
12627
12735
  // src/commands/bridges.ts
12628
- import { existsSync as existsSync48 } from "fs";
12629
- import path45 from "path";
12736
+ import { existsSync as existsSync49 } from "fs";
12737
+ import path46 from "path";
12630
12738
  import "commander";
12631
12739
  import {
12632
12740
  findProjectRoot as findProjectRoot45,
12633
12741
  resolveHaivePaths as resolveHaivePaths40,
12634
- BRIDGE_TARGET_PATH as BRIDGE_TARGET_PATH2,
12635
- BRIDGE_TARGETS as BRIDGE_TARGETS3
12742
+ BRIDGE_TARGET_PATH as BRIDGE_TARGET_PATH3,
12743
+ BRIDGE_TARGETS as BRIDGE_TARGETS4
12636
12744
  } from "@hivelore/core";
12637
12745
  function registerBridges(program2) {
12638
12746
  const bridges = program2.command("bridges").description(
12639
12747
  "Generate native agent bridge files from the Hivelore corpus.\n Bridges inject top validated memories and block sensors into agent-harness-specific\n config files (.cursor/rules/haive-memories.mdc, .clinerules, .windsurfrules,\n .continuerules, .sourcegraph/cody-rules.md, .rules, AGENTS.md,\n .github/copilot-instructions.md).\n This is the reach differentiator vs memories.sh: our bridges carry enforcement, not just injection.\n\n Example:\n hivelore bridges sync --all\n hivelore bridges sync --only cline,windsurf\n"
12640
12748
  );
12641
12749
  bridges.command("sync").description(
12642
- "Regenerate bridge files idempotently (marker-based, preserves manual content outside markers).\n Supported targets: " + BRIDGE_TARGETS3.join(", ") + "\n"
12750
+ "Regenerate bridge files idempotently (marker-based, preserves manual content outside markers).\n Supported targets: " + BRIDGE_TARGETS4.join(", ") + "\n"
12643
12751
  ).option("--all", "generate all supported bridge targets").option(
12644
12752
  "--only <targets>",
12645
12753
  "comma-separated list of targets to generate (e.g. cline,windsurf,agents)"
@@ -12647,7 +12755,7 @@ function registerBridges(program2) {
12647
12755
  const root = findProjectRoot45(opts.dir);
12648
12756
  const paths = resolveHaivePaths40(root);
12649
12757
  const dryRun = opts.dryRun === true;
12650
- if (!existsSync48(paths.memoriesDir)) {
12758
+ if (!existsSync49(paths.memoriesDir)) {
12651
12759
  ui.warn(`No .ai/memories at ${root}. Run \`hivelore init\` first.`);
12652
12760
  process.exitCode = 1;
12653
12761
  return;
@@ -12655,18 +12763,18 @@ function registerBridges(program2) {
12655
12763
  let targets;
12656
12764
  if (opts.only) {
12657
12765
  const requested = opts.only.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
12658
- const invalid = requested.filter((t) => !BRIDGE_TARGETS3.includes(t));
12766
+ const invalid = requested.filter((t) => !BRIDGE_TARGETS4.includes(t));
12659
12767
  if (invalid.length > 0) {
12660
- ui.error(`Unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS3.join(", ")}`);
12768
+ ui.error(`Unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS4.join(", ")}`);
12661
12769
  process.exitCode = 1;
12662
12770
  return;
12663
12771
  }
12664
12772
  targets = requested;
12665
12773
  } else if (opts.all) {
12666
- targets = BRIDGE_TARGETS3;
12774
+ targets = BRIDGE_TARGETS4;
12667
12775
  } else {
12668
- targets = BRIDGE_TARGETS3.filter(
12669
- (t) => existsSync48(path45.join(root, BRIDGE_TARGET_PATH2[t]))
12776
+ targets = BRIDGE_TARGETS4.filter(
12777
+ (t) => existsSync49(path46.join(root, BRIDGE_TARGET_PATH3[t]))
12670
12778
  );
12671
12779
  if (targets.length === 0) {
12672
12780
  ui.info(
@@ -12698,7 +12806,7 @@ function registerBridges(program2) {
12698
12806
  const root = findProjectRoot45(opts.dir);
12699
12807
  const paths = resolveHaivePaths40(root);
12700
12808
  const statuses = await getBridgeFileStatuses(root, paths, {
12701
- targets: BRIDGE_TARGETS3,
12809
+ targets: BRIDGE_TARGETS4,
12702
12810
  maxMemories: Math.max(1, Number(opts.maxMemories ?? 8))
12703
12811
  });
12704
12812
  console.log(ui.bold("Hivelore bridge targets:"));
@@ -12714,7 +12822,7 @@ function registerBridges(program2) {
12714
12822
 
12715
12823
  // src/index.ts
12716
12824
  var program = new Command48();
12717
- program.name("hivelore").description("Hivelore - repo-native memory and context policy for coding-agent harnesses").version("0.33.0").option("--advanced", "show maintenance and experimental commands in help").showSuggestionAfterError(true);
12825
+ program.name("hivelore").description("Hivelore - repo-native memory and context policy for coding-agent harnesses").version("0.34.1").option("--advanced", "show maintenance and experimental commands in help").showSuggestionAfterError(true);
12718
12826
  registerInit(program);
12719
12827
  registerResolveProject(program);
12720
12828
  registerEnforce(program);