@hiveai/cli 0.18.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1378,14 +1378,15 @@ async function reportIndexStatus(root, paths, asJson) {
1378
1378
 
1379
1379
  // src/commands/init.ts
1380
1380
  import { execFile as execFile2 } from "child_process";
1381
- import { mkdir as mkdir5, readFile as readFile5, readdir as readdir2, writeFile as writeFile6 } from "fs/promises";
1382
- import { existsSync as existsSync10 } from "fs";
1383
- import path10 from "path";
1381
+ import { mkdir as mkdir6, readFile as readFile6, readdir as readdir2, writeFile as writeFile7 } from "fs/promises";
1382
+ import { existsSync as existsSync11 } from "fs";
1383
+ import path11 from "path";
1384
1384
  import { spawnSync as spawnSync3 } from "child_process";
1385
1385
  import { promisify as promisify2 } from "util";
1386
1386
  import "commander";
1387
1387
  import {
1388
1388
  AUTOPILOT_DEFAULTS as AUTOPILOT_DEFAULTS2,
1389
+ BRIDGE_TARGETS,
1389
1390
  buildCodeMap as buildCodeMap3,
1390
1391
  buildFrontmatter as buildFrontmatter2,
1391
1392
  detectStacksFromManifests,
@@ -1397,20 +1398,101 @@ import {
1397
1398
  serializeMemory as serializeMemory3
1398
1399
  } from "@hiveai/core";
1399
1400
 
1401
+ // src/utils/bridge-files.ts
1402
+ import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
1403
+ import { existsSync as existsSync6 } from "fs";
1404
+ import path6 from "path";
1405
+ import {
1406
+ BRIDGE_MARKERS,
1407
+ generateBridges,
1408
+ isRetiredMemory,
1409
+ loadMemoriesFromDir as loadMemoriesFromDir4
1410
+ } from "@hiveai/core";
1411
+ async function writeBridgeFiles(root, paths, opts) {
1412
+ const result = { created: [], updated: [], unchanged: [] };
1413
+ if (!existsSync6(paths.memoriesDir)) return result;
1414
+ const allLoaded = await loadMemoriesFromDir4(paths.memoriesDir);
1415
+ const memories = allLoaded.map((l) => l.memory).filter((m) => !isRetiredMemory(m.frontmatter, m.body));
1416
+ const sensors = [];
1417
+ for (const m of memories) {
1418
+ const sensor = m.frontmatter.sensor;
1419
+ if (!sensor || sensor.severity !== "block") continue;
1420
+ sensors.push({
1421
+ id: m.frontmatter.id,
1422
+ severity: "block",
1423
+ message: sensor.message,
1424
+ ...sensor.pattern ? { pattern: sensor.pattern } : {},
1425
+ paths: sensor.paths.length > 0 ? sensor.paths : m.frontmatter.anchor.paths
1426
+ });
1427
+ }
1428
+ const maxMemories = Math.max(1, opts.maxMemories ?? 8);
1429
+ const outputs = generateBridges(memories, sensors, { maxMemories, targets: opts.targets });
1430
+ for (const output of outputs) {
1431
+ const targetFile = path6.join(root, output.path);
1432
+ const fileExists = existsSync6(targetFile);
1433
+ if (opts.onlyExisting && !fileExists) continue;
1434
+ if (opts.dryRun) {
1435
+ (fileExists ? result.updated : result.created).push(output.path);
1436
+ continue;
1437
+ }
1438
+ await mkdir2(path6.dirname(targetFile), { recursive: true });
1439
+ if (!fileExists) {
1440
+ await writeFile3(targetFile, output.content, "utf8");
1441
+ result.created.push(output.path);
1442
+ continue;
1443
+ }
1444
+ let existing = (await readFile3(targetFile, "utf8")).replace(/\r\n/g, "\n");
1445
+ const withMemories = replaceMarkerBlock(
1446
+ existing,
1447
+ BRIDGE_MARKERS.memoriesStart,
1448
+ BRIDGE_MARKERS.memoriesEnd,
1449
+ extractMarkerBlock(output.content, BRIDGE_MARKERS.memoriesStart, BRIDGE_MARKERS.memoriesEnd)
1450
+ );
1451
+ const sensorsBlockContent = extractMarkerBlock(
1452
+ output.content,
1453
+ BRIDGE_MARKERS.sensorsStart,
1454
+ BRIDGE_MARKERS.sensorsEnd
1455
+ );
1456
+ const withSensors = sensorsBlockContent ? replaceMarkerBlock(withMemories, BRIDGE_MARKERS.sensorsStart, BRIDGE_MARKERS.sensorsEnd, sensorsBlockContent) : withMemories;
1457
+ if (withSensors === existing) {
1458
+ result.unchanged.push(output.path);
1459
+ continue;
1460
+ }
1461
+ await writeFile3(targetFile, withSensors, "utf8");
1462
+ result.updated.push(output.path);
1463
+ }
1464
+ return result;
1465
+ }
1466
+ function extractMarkerBlock(text, startMarker, endMarker) {
1467
+ const startIdx = text.indexOf(startMarker);
1468
+ const endIdx = text.indexOf(endMarker);
1469
+ if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return null;
1470
+ return text.slice(startIdx, endIdx + endMarker.length);
1471
+ }
1472
+ function replaceMarkerBlock(existing, startMarker, endMarker, replacement) {
1473
+ if (!replacement) return existing;
1474
+ const startIdx = existing.indexOf(startMarker);
1475
+ const endIdx = existing.indexOf(endMarker);
1476
+ if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) {
1477
+ return existing + (existing.endsWith("\n") ? "" : "\n") + "\n" + replacement + "\n";
1478
+ }
1479
+ return existing.slice(0, startIdx) + replacement + existing.slice(endIdx + endMarker.length);
1480
+ }
1481
+
1400
1482
  // src/commands/agent.ts
1401
1483
  import { spawnSync as spawnSync2 } from "child_process";
1402
- import { existsSync as existsSync7 } from "fs";
1403
- import { mkdir as mkdir3, writeFile as writeFile4 } from "fs/promises";
1484
+ import { existsSync as existsSync8 } from "fs";
1485
+ import { mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
1404
1486
  import os2 from "os";
1405
- import path7 from "path";
1487
+ import path8 from "path";
1406
1488
  import { createInterface } from "readline/promises";
1407
1489
  import "commander";
1408
1490
  import { findProjectRoot as findProjectRoot6, resolveHaivePaths as resolveHaivePaths5 } from "@hiveai/core";
1409
1491
 
1410
1492
  // src/commands/init-mcp-setup.ts
1411
- import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir2 } from "fs/promises";
1412
- import { existsSync as existsSync6 } from "fs";
1413
- import path6 from "path";
1493
+ import { readFile as readFile4, writeFile as writeFile4, mkdir as mkdir3 } from "fs/promises";
1494
+ import { existsSync as existsSync7 } from "fs";
1495
+ import path7 from "path";
1414
1496
  import os from "os";
1415
1497
  var HOME = os.homedir();
1416
1498
  var HAIVE_MCP_ENTRY = {
@@ -1425,38 +1507,38 @@ function projectMcpEntry(root) {
1425
1507
  };
1426
1508
  }
1427
1509
  function cursorMcpPath() {
1428
- return path6.join(HOME, ".cursor", "mcp.json");
1510
+ return path7.join(HOME, ".cursor", "mcp.json");
1429
1511
  }
1430
1512
  async function configureCursor() {
1431
1513
  const mcpPath = cursorMcpPath();
1432
- const cursorDir = path6.join(HOME, ".cursor");
1433
- if (!existsSync6(cursorDir)) return { client: "Cursor", status: "not_installed" };
1514
+ const cursorDir = path7.join(HOME, ".cursor");
1515
+ if (!existsSync7(cursorDir)) return { client: "Cursor", status: "not_installed" };
1434
1516
  let config = {};
1435
- if (existsSync6(mcpPath)) {
1517
+ if (existsSync7(mcpPath)) {
1436
1518
  try {
1437
- config = JSON.parse(await readFile3(mcpPath, "utf8"));
1519
+ config = JSON.parse(await readFile4(mcpPath, "utf8"));
1438
1520
  } catch {
1439
1521
  }
1440
1522
  }
1441
1523
  config.mcpServers ??= {};
1442
1524
  if (config.mcpServers["haive"]) return { client: "Cursor", status: "already_configured" };
1443
1525
  config.mcpServers["haive"] = HAIVE_MCP_ENTRY;
1444
- await mkdir2(cursorDir, { recursive: true });
1445
- await writeFile3(mcpPath, JSON.stringify(config, null, 2), "utf8");
1526
+ await mkdir3(cursorDir, { recursive: true });
1527
+ await writeFile4(mcpPath, JSON.stringify(config, null, 2), "utf8");
1446
1528
  return { client: "Cursor", status: "configured", path: mcpPath };
1447
1529
  }
1448
1530
  function vscodeMcpPath() {
1449
1531
  const candidates = [
1450
- path6.join(HOME, ".config", "Code", "User", "mcp.json"),
1532
+ path7.join(HOME, ".config", "Code", "User", "mcp.json"),
1451
1533
  // Linux
1452
- path6.join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
1534
+ path7.join(HOME, "Library", "Application Support", "Code", "User", "mcp.json"),
1453
1535
  // macOS
1454
- path6.join(HOME, "AppData", "Roaming", "Code", "User", "mcp.json"),
1536
+ path7.join(HOME, "AppData", "Roaming", "Code", "User", "mcp.json"),
1455
1537
  // Windows
1456
- path6.join(HOME, ".config", "Code - Insiders", "User", "mcp.json")
1538
+ path7.join(HOME, ".config", "Code - Insiders", "User", "mcp.json")
1457
1539
  ];
1458
1540
  for (const c of candidates) {
1459
- if (existsSync6(path6.dirname(c))) return c;
1541
+ if (existsSync7(path7.dirname(c))) return c;
1460
1542
  }
1461
1543
  return null;
1462
1544
  }
@@ -1464,51 +1546,51 @@ async function configureVSCode() {
1464
1546
  const mcpPath = vscodeMcpPath();
1465
1547
  if (!mcpPath) return { client: "VS Code", status: "not_installed" };
1466
1548
  let config = {};
1467
- if (existsSync6(mcpPath)) {
1549
+ if (existsSync7(mcpPath)) {
1468
1550
  try {
1469
- config = JSON.parse(await readFile3(mcpPath, "utf8"));
1551
+ config = JSON.parse(await readFile4(mcpPath, "utf8"));
1470
1552
  } catch {
1471
1553
  }
1472
1554
  }
1473
1555
  config.servers ??= {};
1474
1556
  if (config.servers["haive"]) return { client: "VS Code", status: "already_configured" };
1475
1557
  config.servers["haive"] = { ...HAIVE_MCP_ENTRY, type: "stdio" };
1476
- await mkdir2(path6.dirname(mcpPath), { recursive: true });
1477
- await writeFile3(mcpPath, JSON.stringify(config, null, 2), "utf8");
1558
+ await mkdir3(path7.dirname(mcpPath), { recursive: true });
1559
+ await writeFile4(mcpPath, JSON.stringify(config, null, 2), "utf8");
1478
1560
  return { client: "VS Code", status: "configured", path: mcpPath };
1479
1561
  }
1480
1562
  function claudeConfigPath() {
1481
- const p = path6.join(HOME, ".claude.json");
1482
- if (existsSync6(p)) return p;
1483
- const p2 = path6.join(HOME, ".config", "claude", "claude.json");
1484
- if (existsSync6(path6.dirname(p2))) return p2;
1563
+ const p = path7.join(HOME, ".claude.json");
1564
+ if (existsSync7(p)) return p;
1565
+ const p2 = path7.join(HOME, ".config", "claude", "claude.json");
1566
+ if (existsSync7(path7.dirname(p2))) return p2;
1485
1567
  return null;
1486
1568
  }
1487
1569
  async function configureClaude() {
1488
- const cfgPath = claudeConfigPath() ?? path6.join(HOME, ".claude.json");
1489
- if (!existsSync6(cfgPath) && !existsSync6(path6.join(HOME, ".claude"))) {
1570
+ const cfgPath = claudeConfigPath() ?? path7.join(HOME, ".claude.json");
1571
+ if (!existsSync7(cfgPath) && !existsSync7(path7.join(HOME, ".claude"))) {
1490
1572
  return { client: "Claude Code", status: "not_installed" };
1491
1573
  }
1492
1574
  let config = {};
1493
- if (existsSync6(cfgPath)) {
1575
+ if (existsSync7(cfgPath)) {
1494
1576
  try {
1495
- config = JSON.parse(await readFile3(cfgPath, "utf8"));
1577
+ config = JSON.parse(await readFile4(cfgPath, "utf8"));
1496
1578
  } catch {
1497
1579
  }
1498
1580
  }
1499
1581
  config.mcpServers ??= {};
1500
1582
  if (config.mcpServers["haive"]) return { client: "Claude Code", status: "already_configured" };
1501
1583
  config.mcpServers["haive"] = { ...HAIVE_MCP_ENTRY, type: "stdio" };
1502
- await writeFile3(cfgPath, JSON.stringify(config, null, 2), "utf8");
1584
+ await writeFile4(cfgPath, JSON.stringify(config, null, 2), "utf8");
1503
1585
  return { client: "Claude Code", status: "configured", path: cfgPath };
1504
1586
  }
1505
1587
  function windsurfMcpPath() {
1506
1588
  const candidates = [
1507
- path6.join(HOME, ".codeium", "windsurf", "mcp_config.json"),
1508
- path6.join(HOME, ".windsurf", "mcp.json")
1589
+ path7.join(HOME, ".codeium", "windsurf", "mcp_config.json"),
1590
+ path7.join(HOME, ".windsurf", "mcp.json")
1509
1591
  ];
1510
1592
  for (const c of candidates) {
1511
- if (existsSync6(path6.dirname(c))) return c;
1593
+ if (existsSync7(path7.dirname(c))) return c;
1512
1594
  }
1513
1595
  return null;
1514
1596
  }
@@ -1516,17 +1598,17 @@ async function configureWindsurf() {
1516
1598
  const mcpPath = windsurfMcpPath();
1517
1599
  if (!mcpPath) return { client: "Windsurf", status: "not_installed" };
1518
1600
  let config = {};
1519
- if (existsSync6(mcpPath)) {
1601
+ if (existsSync7(mcpPath)) {
1520
1602
  try {
1521
- config = JSON.parse(await readFile3(mcpPath, "utf8"));
1603
+ config = JSON.parse(await readFile4(mcpPath, "utf8"));
1522
1604
  } catch {
1523
1605
  }
1524
1606
  }
1525
1607
  config.mcpServers ??= {};
1526
1608
  if (config.mcpServers["haive"]) return { client: "Windsurf", status: "already_configured" };
1527
1609
  config.mcpServers["haive"] = HAIVE_MCP_ENTRY;
1528
- await mkdir2(path6.dirname(mcpPath), { recursive: true });
1529
- await writeFile3(mcpPath, JSON.stringify(config, null, 2), "utf8");
1610
+ await mkdir3(path7.dirname(mcpPath), { recursive: true });
1611
+ await writeFile4(mcpPath, JSON.stringify(config, null, 2), "utf8");
1530
1612
  return { client: "Windsurf", status: "configured", path: mcpPath };
1531
1613
  }
1532
1614
  async function autoConfigureMcpClients() {
@@ -1546,51 +1628,51 @@ async function configureProjectMcpClients(root) {
1546
1628
  const entry = projectMcpEntry(root);
1547
1629
  const results = [];
1548
1630
  try {
1549
- const cursorPath = path6.join(root, ".cursor", "mcp.json");
1631
+ const cursorPath = path7.join(root, ".cursor", "mcp.json");
1550
1632
  let config = {};
1551
- if (existsSync6(cursorPath)) {
1633
+ if (existsSync7(cursorPath)) {
1552
1634
  try {
1553
- config = JSON.parse(await readFile3(cursorPath, "utf8"));
1635
+ config = JSON.parse(await readFile4(cursorPath, "utf8"));
1554
1636
  } catch {
1555
1637
  }
1556
1638
  }
1557
1639
  config.mcpServers ??= {};
1558
1640
  config.mcpServers["haive"] = entry;
1559
- await mkdir2(path6.dirname(cursorPath), { recursive: true });
1560
- await writeFile3(cursorPath, JSON.stringify(config, null, 2) + "\n", "utf8");
1641
+ await mkdir3(path7.dirname(cursorPath), { recursive: true });
1642
+ await writeFile4(cursorPath, JSON.stringify(config, null, 2) + "\n", "utf8");
1561
1643
  results.push({ client: "Cursor (project)", status: "configured", path: cursorPath });
1562
1644
  } catch (err) {
1563
1645
  results.push({ client: "Cursor (project)", status: "error", error: String(err) });
1564
1646
  }
1565
1647
  try {
1566
- const vscodePath = path6.join(root, ".vscode", "mcp.json");
1648
+ const vscodePath = path7.join(root, ".vscode", "mcp.json");
1567
1649
  let config = {};
1568
- if (existsSync6(vscodePath)) {
1650
+ if (existsSync7(vscodePath)) {
1569
1651
  try {
1570
- config = JSON.parse(await readFile3(vscodePath, "utf8"));
1652
+ config = JSON.parse(await readFile4(vscodePath, "utf8"));
1571
1653
  } catch {
1572
1654
  }
1573
1655
  }
1574
1656
  config.servers ??= {};
1575
1657
  config.servers["haive"] = { ...entry, type: "stdio" };
1576
- await mkdir2(path6.dirname(vscodePath), { recursive: true });
1577
- await writeFile3(vscodePath, JSON.stringify(config, null, 2) + "\n", "utf8");
1658
+ await mkdir3(path7.dirname(vscodePath), { recursive: true });
1659
+ await writeFile4(vscodePath, JSON.stringify(config, null, 2) + "\n", "utf8");
1578
1660
  results.push({ client: "VS Code (workspace)", status: "configured", path: vscodePath });
1579
1661
  } catch (err) {
1580
1662
  results.push({ client: "VS Code (workspace)", status: "error", error: String(err) });
1581
1663
  }
1582
1664
  try {
1583
- const mcpPath = path6.join(root, ".mcp.json");
1665
+ const mcpPath = path7.join(root, ".mcp.json");
1584
1666
  let config = {};
1585
- if (existsSync6(mcpPath)) {
1667
+ if (existsSync7(mcpPath)) {
1586
1668
  try {
1587
- config = JSON.parse(await readFile3(mcpPath, "utf8"));
1669
+ config = JSON.parse(await readFile4(mcpPath, "utf8"));
1588
1670
  } catch {
1589
1671
  }
1590
1672
  }
1591
1673
  config.mcpServers ??= {};
1592
1674
  config.mcpServers["haive"] = { ...entry, type: "stdio" };
1593
- await writeFile3(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf8");
1675
+ await writeFile4(mcpPath, JSON.stringify(config, null, 2) + "\n", "utf8");
1594
1676
  results.push({ client: "Claude Code (project)", status: "configured", path: mcpPath });
1595
1677
  } catch (err) {
1596
1678
  results.push({ client: "Claude Code (project)", status: "error", error: String(err) });
@@ -1656,9 +1738,9 @@ async function detectAgentMode(dir) {
1656
1738
  const root = findProjectRoot6(dir);
1657
1739
  const paths = resolveHaivePaths5(root);
1658
1740
  const projectMcp = [
1659
- { client: "Claude Code", path: path7.join(root, ".mcp.json"), present: existsSync7(path7.join(root, ".mcp.json")) },
1660
- { client: "Cursor", path: path7.join(root, ".cursor", "mcp.json"), present: existsSync7(path7.join(root, ".cursor", "mcp.json")) },
1661
- { client: "VS Code", path: path7.join(root, ".vscode", "mcp.json"), present: existsSync7(path7.join(root, ".vscode", "mcp.json")) }
1741
+ { client: "Claude Code", path: path8.join(root, ".mcp.json"), present: existsSync8(path8.join(root, ".mcp.json")) },
1742
+ { client: "Cursor", path: path8.join(root, ".cursor", "mcp.json"), present: existsSync8(path8.join(root, ".cursor", "mcp.json")) },
1743
+ { client: "VS Code", path: path8.join(root, ".vscode", "mcp.json"), present: existsSync8(path8.join(root, ".vscode", "mcp.json")) }
1662
1744
  ];
1663
1745
  const installedAgents = [
1664
1746
  { agent: "Codex", command: "codex", installed: commandExists("codex"), mcp_configured: codexMcpConfigured() },
@@ -1673,7 +1755,7 @@ async function detectAgentMode(dir) {
1673
1755
  const recommendedCommand = recommendedMode === "mcp" ? "Restart your AI client, then call get_briefing before editing." : recommendedMode === "wrapped" && wrapperAgent ? `haive run -- ${wrapperAgent.command}` : 'haive briefing --task "..." --files "..."';
1674
1756
  return {
1675
1757
  root,
1676
- initialized: existsSync7(paths.haiveDir),
1758
+ initialized: existsSync8(paths.haiveDir),
1677
1759
  project_mcp: projectMcp,
1678
1760
  installed_agents: installedAgents,
1679
1761
  recommended_mode: recommendedMode,
@@ -1681,9 +1763,9 @@ async function detectAgentMode(dir) {
1681
1763
  };
1682
1764
  }
1683
1765
  async function writeAgentModeRecord(paths, detection, skippedReason) {
1684
- const dir = path7.join(paths.runtimeDir, "enforcement");
1685
- await mkdir3(dir, { recursive: true });
1686
- const file = path7.join(dir, "agent-mode.json");
1766
+ const dir = path8.join(paths.runtimeDir, "enforcement");
1767
+ await mkdir4(dir, { recursive: true });
1768
+ const file = path8.join(dir, "agent-mode.json");
1687
1769
  const record = {
1688
1770
  selected_mode: detection.recommended_mode,
1689
1771
  recommended_command: detection.recommended_command,
@@ -1696,7 +1778,7 @@ async function writeAgentModeRecord(paths, detection, skippedReason) {
1696
1778
  ...skippedReason ? [skippedReason] : []
1697
1779
  ]
1698
1780
  };
1699
- await writeFile4(file, JSON.stringify(record, null, 2) + "\n", "utf8");
1781
+ await writeFile5(file, JSON.stringify(record, null, 2) + "\n", "utf8");
1700
1782
  return file;
1701
1783
  }
1702
1784
  async function confirmGlobalSetup() {
@@ -1724,7 +1806,7 @@ async function configureCodexIfAvailable(root) {
1724
1806
  "mcp",
1725
1807
  "--stdio"
1726
1808
  ], { encoding: "utf8" });
1727
- if (result.status === 0) return { client: "Codex", status: "configured", path: path7.join(os2.homedir(), ".codex", "config.toml") };
1809
+ if (result.status === 0) return { client: "Codex", status: "configured", path: path8.join(os2.homedir(), ".codex", "config.toml") };
1728
1810
  return { client: "Codex", status: "error", error: result.stderr || result.stdout || "codex mcp add failed" };
1729
1811
  }
1730
1812
  function commandExists(command) {
@@ -1751,7 +1833,7 @@ function printDetection(detection, json) {
1751
1833
  console.log(ui.dim(` root: ${detection.root}`));
1752
1834
  console.log(`${detection.initialized ? ui.green("\u2713") : ui.red("\u2717")} project initialized`);
1753
1835
  for (const cfg of detection.project_mcp) {
1754
- console.log(`${cfg.present ? ui.green("\u2713") : ui.yellow("\u2022")} ${cfg.client} project MCP ${ui.dim(path7.relative(detection.root, cfg.path))}`);
1836
+ console.log(`${cfg.present ? ui.green("\u2713") : ui.yellow("\u2022")} ${cfg.client} project MCP ${ui.dim(path8.relative(detection.root, cfg.path))}`);
1755
1837
  }
1756
1838
  for (const agent of detection.installed_agents) {
1757
1839
  const marker = agent.installed ? ui.green("\u2713") : ui.dim("\u2022");
@@ -1779,9 +1861,9 @@ function printSetupResult(result) {
1779
1861
  }
1780
1862
 
1781
1863
  // src/commands/init-bootstrap.ts
1782
- import { readdir, readFile as readFile4 } from "fs/promises";
1783
- import { existsSync as existsSync8, readdirSync } from "fs";
1784
- import path8 from "path";
1864
+ import { readdir, readFile as readFile5 } from "fs/promises";
1865
+ import { existsSync as existsSync9, readdirSync } from "fs";
1866
+ import path9 from "path";
1785
1867
  var IGNORE_DIRS = /* @__PURE__ */ new Set([
1786
1868
  "node_modules",
1787
1869
  "dist",
@@ -1867,12 +1949,12 @@ function detectKeyDeps(allDeps) {
1867
1949
  return KEY_DEPS.filter((d) => allDeps[d] !== void 0);
1868
1950
  }
1869
1951
  function detectLanguage(root) {
1870
- if (existsSync8(path8.join(root, "tsconfig.json"))) return "TypeScript";
1871
- if (existsSync8(path8.join(root, "pyproject.toml")) || existsSync8(path8.join(root, "setup.py"))) return "Python";
1872
- if (existsSync8(path8.join(root, "go.mod"))) return "Go";
1873
- if (existsSync8(path8.join(root, "pom.xml")) || existsSync8(path8.join(root, "build.gradle"))) return "Java/Kotlin";
1874
- if (existsSync8(path8.join(root, "Cargo.toml"))) return "Rust";
1875
- if (existsSync8(path8.join(root, "package.json"))) {
1952
+ if (existsSync9(path9.join(root, "tsconfig.json"))) return "TypeScript";
1953
+ if (existsSync9(path9.join(root, "pyproject.toml")) || existsSync9(path9.join(root, "setup.py"))) return "Python";
1954
+ if (existsSync9(path9.join(root, "go.mod"))) return "Go";
1955
+ if (existsSync9(path9.join(root, "pom.xml")) || existsSync9(path9.join(root, "build.gradle"))) return "Java/Kotlin";
1956
+ if (existsSync9(path9.join(root, "Cargo.toml"))) return "Rust";
1957
+ if (existsSync9(path9.join(root, "package.json"))) {
1876
1958
  return hasSourceWithExt(root, [".ts", ".tsx", ".mts", ".cts"]) ? "TypeScript" : "JavaScript";
1877
1959
  }
1878
1960
  return "Unknown";
@@ -1892,7 +1974,7 @@ function hasSourceWithExt(root, exts) {
1892
1974
  if (depth <= 0) return false;
1893
1975
  for (const entry of entries) {
1894
1976
  if (entry.isDirectory() && !IGNORE_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
1895
- if (scanDir(path8.join(dir, entry.name), depth - 1)) return true;
1977
+ if (scanDir(path9.join(dir, entry.name), depth - 1)) return true;
1896
1978
  }
1897
1979
  }
1898
1980
  return false;
@@ -1913,7 +1995,7 @@ function detectProjectType(frameworks, scripts, isMonorepo) {
1913
1995
  if (frameworks.includes("Express") || frameworks.includes("Fastify") || frameworks.includes("Hono")) return "Backend API";
1914
1996
  if (frameworks.includes("React") || frameworks.includes("Vue") || frameworks.includes("Svelte")) return "Frontend SPA";
1915
1997
  if (scripts["build"] && !scripts["dev"]) return "CLI tool / library";
1916
- if (existsSync8("pom.xml")) return "Java backend";
1998
+ if (existsSync9("pom.xml")) return "Java backend";
1917
1999
  return "Application";
1918
2000
  }
1919
2001
  async function scanDirs(root, maxDepth = 2) {
@@ -1929,9 +2011,9 @@ async function scanDirs(root, maxDepth = 2) {
1929
2011
  for (const entry of entries) {
1930
2012
  if (!entry.isDirectory()) continue;
1931
2013
  if (IGNORE_DIRS.has(entry.name) || entry.name.startsWith(".")) continue;
1932
- const rel = path8.relative(root, path8.join(dir, entry.name));
2014
+ const rel = path9.relative(root, path9.join(dir, entry.name));
1933
2015
  results.push(rel);
1934
- await walk(path8.join(dir, entry.name), depth + 1);
2016
+ await walk(path9.join(dir, entry.name), depth + 1);
1935
2017
  }
1936
2018
  }
1937
2019
  await walk(root, 0);
@@ -2048,10 +2130,10 @@ function readmeExcerpt(readme) {
2048
2130
  }
2049
2131
  async function generateBootstrapContext(root) {
2050
2132
  let pkg = {};
2051
- const pkgPath = path8.join(root, "package.json");
2052
- if (existsSync8(pkgPath)) {
2133
+ const pkgPath = path9.join(root, "package.json");
2134
+ if (existsSync9(pkgPath)) {
2053
2135
  try {
2054
- pkg = JSON.parse(await readFile4(pkgPath, "utf8"));
2136
+ pkg = JSON.parse(await readFile5(pkgPath, "utf8"));
2055
2137
  } catch {
2056
2138
  }
2057
2139
  }
@@ -2061,14 +2143,14 @@ async function generateBootstrapContext(root) {
2061
2143
  const language = detectLanguage(root);
2062
2144
  const isMonorepo = pkg.workspaces !== void 0 && (Array.isArray(pkg.workspaces) ? pkg.workspaces.length > 0 : true);
2063
2145
  const projectType = detectProjectType(frameworks, pkg.scripts ?? {}, isMonorepo);
2064
- const projectName = pkg.name ?? path8.basename(root);
2146
+ const projectName = pkg.name ?? path9.basename(root);
2065
2147
  const projectDesc = pkg.description ?? "";
2066
2148
  let readmeSummary = "";
2067
2149
  for (const name of ["README.md", "readme.md", "README"]) {
2068
- const p = path8.join(root, name);
2069
- if (existsSync8(p)) {
2150
+ const p = path9.join(root, name);
2151
+ if (existsSync9(p)) {
2070
2152
  try {
2071
- const content = await readFile4(p, "utf8");
2153
+ const content = await readFile5(p, "utf8");
2072
2154
  readmeSummary = readmeExcerpt(content);
2073
2155
  break;
2074
2156
  } catch {
@@ -2132,9 +2214,9 @@ async function generateBootstrapContext(root) {
2132
2214
  }
2133
2215
 
2134
2216
  // src/commands/init-stack-packs.ts
2135
- import { mkdir as mkdir4, writeFile as writeFile5 } from "fs/promises";
2136
- import { existsSync as existsSync9 } from "fs";
2137
- import path9 from "path";
2217
+ import { mkdir as mkdir5, writeFile as writeFile6 } from "fs/promises";
2218
+ import { existsSync as existsSync10 } from "fs";
2219
+ import path10 from "path";
2138
2220
  import {
2139
2221
  buildFrontmatter,
2140
2222
  memoryFilePath,
@@ -3213,7 +3295,7 @@ function autoDetectStacks(deps) {
3213
3295
  async function seedStackPack(haivePaths, stack) {
3214
3296
  const memories = PACKS[stack];
3215
3297
  if (!memories) return { memories: 0, sensors: 0 };
3216
- await mkdir4(haivePaths.teamDir, { recursive: true });
3298
+ await mkdir5(haivePaths.teamDir, { recursive: true });
3217
3299
  let memCount = 0;
3218
3300
  let sensorCount = 0;
3219
3301
  for (const mem of memories) {
@@ -3238,12 +3320,12 @@ async function seedStackPack(haivePaths, stack) {
3238
3320
  ...sensor ? { sensor } : {}
3239
3321
  });
3240
3322
  const filePath = memoryFilePath(haivePaths, "team", fm.id);
3241
- if (existsSync9(filePath)) continue;
3323
+ if (existsSync10(filePath)) continue;
3242
3324
  const content = serializeMemory2({ frontmatter: fm, body: `${mem.body}
3243
3325
 
3244
3326
  ${SEED_FOOTER(stack)}` });
3245
- await mkdir4(path9.dirname(filePath), { recursive: true });
3246
- await writeFile5(filePath, content, "utf8");
3327
+ await mkdir5(path10.dirname(filePath), { recursive: true });
3328
+ await writeFile6(filePath, content, "utf8");
3247
3329
  memCount++;
3248
3330
  if (sensor) sensorCount++;
3249
3331
  }
@@ -3252,7 +3334,7 @@ ${SEED_FOOTER(stack)}` });
3252
3334
 
3253
3335
  // src/commands/init.ts
3254
3336
  var execFileAsync = promisify2(execFile2);
3255
- var HAIVE_GITHUB_ACTION_REF = `v${"0.18.0"}`;
3337
+ var HAIVE_GITHUB_ACTION_REF = `v${"0.19.0"}`;
3256
3338
  var PROJECT_CONTEXT_TEMPLATE = `# Project context
3257
3339
 
3258
3340
  > Generated by \`haive init\`. Run \`haive init --bootstrap\` to auto-fill from your codebase,
@@ -3274,28 +3356,6 @@ TODO \u2014 domain terms and what they mean here.
3274
3356
  ## Gotchas
3275
3357
  TODO \u2014 known traps, surprising behavior, things newcomers stub their toes on.
3276
3358
  `;
3277
- var BRIDGE_BODY = `<!-- hAIve bridge file \u2014 do not edit by hand. -->
3278
-
3279
- This repo uses **hAIve** for shared context. The map:
3280
-
3281
- - \`.ai/project-context.md\` \u2014 project overview, architecture, conventions.
3282
- - \`.ai/memories/\` \u2014 decisions, gotchas, conventions, failed attempts (personal/team/module).
3283
- - The breadcrumbs injected below (if any) are the top current memories.
3284
-
3285
- ## Working through hAIve
3286
-
3287
- 1. **Before editing** for a goal, call \`get_briefing\` (task + files/symbols) to load ranked context \u2014 or \`mem_relevant_to\` if project context is already loaded this session.
3288
- 2. **When an approach fails**, call \`mem_tried\` right away so the next agent skips the dead end.
3289
- 3. **Before closing** a substantive session, run the \`post_task\` prompt to capture what was learned.
3290
- 4. **Before final response**, run \`haive enforce finish\`. If it blocks, commit/push, bump/tag shippable releases, wait for GitHub Actions to pass when applicable, then rerun it.
3291
-
3292
- If the haive MCP server is not available, tell the developer rather than silently skipping it.
3293
-
3294
- ## Safety
3295
-
3296
- - If \`get_briefing\` returns \`action_required\`, surface each item to the developer (use its \`developer_message\`) and wait for confirmation before changing code.
3297
- - Never act autonomously on a cross-repo breaking change (dep bump, contract/API diff) \u2014 ask first.
3298
- `;
3299
3359
  var CURSOR_HAIVE_RULE_MDC = `---
3300
3360
  description: Require hAIve MCP (get_briefing / mem_relevant_to) before substantive repo edits
3301
3361
  alwaysApply: true
@@ -3465,7 +3525,12 @@ jobs:
3465
3525
  function registerInit(program2) {
3466
3526
  program2.command("init").description(
3467
3527
  "Initialize a hAIve 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."
3468
- ).option("-d, --dir <dir>", "project root", process.cwd()).option("--no-bridges", "do not generate CLAUDE.md / AGENTS.md / .cursorrules / copilot-instructions.md / .cursor/rules/haive-mcp-required.mdc").option("--with-ci", "write a GitHub Actions workflow (.github/workflows/haive-sync.yml) \u2014 included automatically in autopilot mode").option(
3528
+ ).option("-d, --dir <dir>", "project root", process.cwd()).option("--no-bridges", "do not generate any native agent bridge files").option(
3529
+ "--bridge-targets <list>",
3530
+ `which agent bridges to generate: 'all' (default) | comma-list.
3531
+ Available: ${BRIDGE_TARGETS.join(", ")}. Each carries top memories + block sensors.`,
3532
+ "all"
3533
+ ).option("--with-ci", "write a GitHub Actions workflow (.github/workflows/haive-sync.yml) \u2014 included automatically in autopilot mode").option(
3469
3534
  "--manual",
3470
3535
  "opt out of autopilot: memories require manual approval, no auto-session recap, no auto-context"
3471
3536
  ).option(
@@ -3497,7 +3562,7 @@ function registerInit(program2) {
3497
3562
  "approve user-level AI client configuration prompts during agent setup",
3498
3563
  false
3499
3564
  ).option("--json", "emit a machine-readable summary on stdout (human logs go to stderr)", false).action(async (opts) => {
3500
- const root = path10.resolve(opts.dir);
3565
+ const root = path11.resolve(opts.dir);
3501
3566
  const paths = resolveHaivePaths6(root);
3502
3567
  const autopilot = opts.manual !== true;
3503
3568
  const json = opts.json === true;
@@ -3513,35 +3578,36 @@ function registerInit(program2) {
3513
3578
  gitSeedsWritten: 0,
3514
3579
  gitCommitsScanned: 0,
3515
3580
  gitRevertsFound: 0,
3516
- gitRecurring: 0
3581
+ gitRecurring: 0,
3582
+ bridgesWritten: 0
3517
3583
  };
3518
- if (existsSync10(paths.haiveDir)) {
3584
+ if (existsSync11(paths.haiveDir)) {
3519
3585
  ui.warn(`.ai/ already exists at ${paths.haiveDir} \u2014 leaving existing files in place.`);
3520
3586
  }
3521
- await mkdir5(paths.personalDir, { recursive: true });
3522
- await mkdir5(paths.teamDir, { recursive: true });
3523
- await mkdir5(paths.moduleDir, { recursive: true });
3524
- await mkdir5(paths.modulesContextDir, { recursive: true });
3587
+ await mkdir6(paths.personalDir, { recursive: true });
3588
+ await mkdir6(paths.teamDir, { recursive: true });
3589
+ await mkdir6(paths.moduleDir, { recursive: true });
3590
+ await mkdir6(paths.modulesContextDir, { recursive: true });
3525
3591
  await ensureAiRuntimeLayout(paths.runtimeDir);
3526
- await ensureAiCacheLayout(path10.join(paths.haiveDir, ".cache"));
3527
- if (!existsSync10(paths.projectContext)) {
3592
+ await ensureAiCacheLayout(path11.join(paths.haiveDir, ".cache"));
3593
+ if (!existsSync11(paths.projectContext)) {
3528
3594
  if (wantBootstrap) {
3529
3595
  ui.info("Bootstrapping project context from local files\u2026");
3530
3596
  try {
3531
3597
  const context = await generateBootstrapContext(root);
3532
- await writeFile6(paths.projectContext, context, "utf8");
3598
+ await writeFile7(paths.projectContext, context, "utf8");
3533
3599
  ui.success("Created .ai/project-context.md (auto-bootstrapped from local files)");
3534
3600
  } catch (err) {
3535
3601
  ui.warn(`Bootstrap failed (${String(err)}) \u2014 writing default template instead`);
3536
- await writeFile6(paths.projectContext, PROJECT_CONTEXT_TEMPLATE, "utf8");
3602
+ await writeFile7(paths.projectContext, PROJECT_CONTEXT_TEMPLATE, "utf8");
3537
3603
  }
3538
3604
  } else {
3539
- await writeFile6(paths.projectContext, PROJECT_CONTEXT_TEMPLATE, "utf8");
3540
- ui.success(`Created ${path10.relative(root, paths.projectContext)}`);
3605
+ await writeFile7(paths.projectContext, PROJECT_CONTEXT_TEMPLATE, "utf8");
3606
+ ui.success(`Created ${path11.relative(root, paths.projectContext)}`);
3541
3607
  }
3542
3608
  }
3543
- const configExists = existsSync10(
3544
- path10.join(paths.haiveDir, "haive.config.json")
3609
+ const configExists = existsSync11(
3610
+ path11.join(paths.haiveDir, "haive.config.json")
3545
3611
  );
3546
3612
  if (!configExists) {
3547
3613
  await saveConfig2(paths, autopilot ? AUTOPILOT_DEFAULTS2 : { autopilot: false });
@@ -3549,13 +3615,6 @@ function registerInit(program2) {
3549
3615
  `Created .ai/haive.config.json (mode: ${autopilot ? "autopilot" : "standard"})`
3550
3616
  );
3551
3617
  }
3552
- if (opts.bridges) {
3553
- await writeBridge(root, "CLAUDE.md");
3554
- await writeBridge(root, "AGENTS.md");
3555
- await writeBridge(root, ".cursorrules");
3556
- await writeBridge(root, path10.join(".github", "copilot-instructions.md"));
3557
- await writeCursorHaiveRule(root);
3558
- }
3559
3618
  const stacksToSeed = await resolveStacksToSeed(root, wantStack);
3560
3619
  if (stacksToSeed.length > 0) {
3561
3620
  let totalSeeded = 0;
@@ -3597,15 +3656,31 @@ function registerInit(program2) {
3597
3656
  ui.info("Git seeding: no revert/hotfix signals found \u2014 run `haive memory seed-git` later.");
3598
3657
  }
3599
3658
  }
3659
+ if (opts.bridges) {
3660
+ const targets = resolveBridgeTargets(opts.bridgeTargets);
3661
+ const res = await writeBridgeFiles(root, paths, { targets });
3662
+ await writeCursorHaiveRule(root);
3663
+ const made = res.created.length + res.updated.length;
3664
+ report.bridgesWritten = made;
3665
+ if (res.created.length > 0) {
3666
+ ui.success(`Generated ${res.created.length} agent bridge(s): ${res.created.join(", ")}`);
3667
+ }
3668
+ if (res.updated.length > 0) {
3669
+ ui.info(`Refreshed ${res.updated.length} existing bridge(s): ${res.updated.join(", ")}`);
3670
+ }
3671
+ if (made === 0) {
3672
+ ui.info("Bridges already up to date.");
3673
+ }
3674
+ }
3600
3675
  const wantCi = opts.withCi || autopilot;
3601
3676
  if (wantCi) {
3602
- const ciPath = path10.join(root, ".github", "workflows", "haive-sync.yml");
3603
- if (existsSync10(ciPath)) {
3677
+ const ciPath = path11.join(root, ".github", "workflows", "haive-sync.yml");
3678
+ if (existsSync11(ciPath)) {
3604
3679
  ui.info("CI workflow already exists \u2014 skipped");
3605
3680
  } else {
3606
- await mkdir5(path10.dirname(ciPath), { recursive: true });
3607
- await writeFile6(ciPath, CI_WORKFLOW, "utf8");
3608
- ui.success(`Created ${path10.relative(root, ciPath)}`);
3681
+ await mkdir6(path11.dirname(ciPath), { recursive: true });
3682
+ await writeFile7(ciPath, CI_WORKFLOW, "utf8");
3683
+ ui.success(`Created ${path11.relative(root, ciPath)}`);
3609
3684
  }
3610
3685
  }
3611
3686
  if (autopilot) {
@@ -3645,7 +3720,7 @@ function registerInit(program2) {
3645
3720
  interactive: process.stdin.isTTY
3646
3721
  });
3647
3722
  for (const r of agentSetup.project_results) {
3648
- if (r.status === "configured" && r.path) ui.success(`haive MCP project config written (${path10.relative(root, r.path)})`);
3723
+ if (r.status === "configured" && r.path) ui.success(`haive MCP project config written (${path11.relative(root, r.path)})`);
3649
3724
  else if (r.status === "error") ui.warn(`${r.client}: ${r.error}`);
3650
3725
  }
3651
3726
  for (const r of agentSetup.global_results) {
@@ -3682,6 +3757,7 @@ function registerInit(program2) {
3682
3757
  git_seeds_written: report.gitSeedsWritten,
3683
3758
  git_recurring: report.gitRecurring,
3684
3759
  bridges: opts.bridges !== false,
3760
+ bridges_written: report.bridgesWritten,
3685
3761
  ci: opts.withCi || autopilot
3686
3762
  }, null, 2));
3687
3763
  return;
@@ -3743,57 +3819,57 @@ async function autoDetectStacksFromRoot(root) {
3743
3819
  let requirementsTxt;
3744
3820
  let goMod;
3745
3821
  let pomXml;
3746
- const pkgPath = path10.join(root, "package.json");
3747
- if (existsSync10(pkgPath)) {
3822
+ const pkgPath = path11.join(root, "package.json");
3823
+ if (existsSync11(pkgPath)) {
3748
3824
  try {
3749
- const pkg = JSON.parse(await readFile5(pkgPath, "utf8"));
3825
+ const pkg = JSON.parse(await readFile6(pkgPath, "utf8"));
3750
3826
  packageJsonDeps = { ...pkg.dependencies ?? {}, ...pkg.devDependencies ?? {} };
3751
3827
  } catch {
3752
3828
  }
3753
3829
  }
3754
3830
  for (const name of ["requirements.txt", "requirements/base.txt", "requirements/prod.txt"]) {
3755
- const reqPath = path10.join(root, name);
3756
- if (existsSync10(reqPath)) {
3831
+ const reqPath = path11.join(root, name);
3832
+ if (existsSync11(reqPath)) {
3757
3833
  try {
3758
- requirementsTxt = await readFile5(reqPath, "utf8");
3834
+ requirementsTxt = await readFile6(reqPath, "utf8");
3759
3835
  break;
3760
3836
  } catch {
3761
3837
  }
3762
3838
  }
3763
3839
  }
3764
- const goModPath = path10.join(root, "go.mod");
3765
- if (existsSync10(goModPath)) {
3840
+ const goModPath = path11.join(root, "go.mod");
3841
+ if (existsSync11(goModPath)) {
3766
3842
  try {
3767
- goMod = await readFile5(goModPath, "utf8");
3843
+ goMod = await readFile6(goModPath, "utf8");
3768
3844
  } catch {
3769
3845
  }
3770
3846
  }
3771
- const pomPath = path10.join(root, "pom.xml");
3772
- if (existsSync10(pomPath)) {
3847
+ const pomPath = path11.join(root, "pom.xml");
3848
+ if (existsSync11(pomPath)) {
3773
3849
  try {
3774
- pomXml = await readFile5(pomPath, "utf8");
3850
+ pomXml = await readFile6(pomPath, "utf8");
3775
3851
  } catch {
3776
3852
  }
3777
3853
  }
3778
3854
  let composerJson;
3779
- const composerPath = path10.join(root, "composer.json");
3780
- if (existsSync10(composerPath)) {
3855
+ const composerPath = path11.join(root, "composer.json");
3856
+ if (existsSync11(composerPath)) {
3781
3857
  try {
3782
- composerJson = await readFile5(composerPath, "utf8");
3858
+ composerJson = await readFile6(composerPath, "utf8");
3783
3859
  } catch {
3784
3860
  }
3785
3861
  }
3786
3862
  let gemfile;
3787
- const gemfilePath = path10.join(root, "Gemfile");
3788
- if (existsSync10(gemfilePath)) {
3863
+ const gemfilePath = path11.join(root, "Gemfile");
3864
+ if (existsSync11(gemfilePath)) {
3789
3865
  try {
3790
- gemfile = await readFile5(gemfilePath, "utf8");
3866
+ gemfile = await readFile6(gemfilePath, "utf8");
3791
3867
  } catch {
3792
3868
  }
3793
3869
  }
3794
- const hasDockerfile = existsSync10(path10.join(root, "Dockerfile"));
3795
- const hasTurboJson = existsSync10(path10.join(root, "turbo.json"));
3796
- const hasNxJson = existsSync10(path10.join(root, "nx.json"));
3870
+ const hasDockerfile = existsSync11(path11.join(root, "Dockerfile"));
3871
+ const hasTurboJson = existsSync11(path11.join(root, "turbo.json"));
3872
+ const hasNxJson = existsSync11(path11.join(root, "nx.json"));
3797
3873
  let hasCsproj = false;
3798
3874
  try {
3799
3875
  const entries = await readdir2(root);
@@ -3845,9 +3921,9 @@ async function seedFromGitHistory(root, paths, limit) {
3845
3921
  _Seeded from git ${p.kind} commit ${p.source_sha}. Review and validate (or delete) \u2014 not yet authoritative._
3846
3922
  `;
3847
3923
  const file = memoryFilePath2(paths, fm.scope, fm.id, fm.module);
3848
- if (existsSync10(file)) continue;
3849
- await mkdir5(path10.dirname(file), { recursive: true });
3850
- await writeFile6(file, serializeMemory3({ frontmatter: fm, body }), "utf8");
3924
+ if (existsSync11(file)) continue;
3925
+ await mkdir6(path11.dirname(file), { recursive: true });
3926
+ await writeFile7(file, serializeMemory3({ frontmatter: fm, body }), "utf8");
3851
3927
  written++;
3852
3928
  }
3853
3929
  return { scanned: commits.length, found: proposals.length, recurring, written };
@@ -3886,6 +3962,9 @@ function printInitReport(r) {
3886
3962
  if (r.totalMemories > 0) {
3887
3963
  lines.push(` Total ready : ${r.totalMemories} lesson(s), ${r.totalSensors} sensor(s) \u2014 0 written by hand`);
3888
3964
  }
3965
+ if (r.bridgesWritten > 0) {
3966
+ lines.push(` Reach : ${r.bridgesWritten} agent bridge(s) generated (Cursor, Cline, Copilot, Roo, Gemini, \u2026)`);
3967
+ }
3889
3968
  if (lines.length === 0) return;
3890
3969
  const width = Math.max(...lines.map((l) => l.length), 44);
3891
3970
  const bar = "\u2500".repeat(width + 2);
@@ -3900,29 +3979,30 @@ function printInitReport(r) {
3900
3979
  console.log(ui.dim(" Review draft seeds: haive memory pending (validate or delete each one)"));
3901
3980
  }
3902
3981
  console.log(
3903
- ui.dim(" Reach: every agent gets this corpus \u2014 run `haive bridges sync --all` (Cursor, Cline, Windsurf, Roo, Gemini, Copilot, \u2026)")
3982
+ ui.dim(" Reach: bridges auto-refresh on `haive sync`; regenerate any time with `haive bridges sync --all`.")
3904
3983
  );
3905
3984
  }
3906
3985
  async function writeCursorHaiveRule(root) {
3907
3986
  const relPath = ".cursor/rules/haive-mcp-required.mdc";
3908
- const target = path10.join(root, relPath);
3909
- if (existsSync10(target)) {
3987
+ const target = path11.join(root, relPath);
3988
+ if (existsSync11(target)) {
3910
3989
  ui.info(`Cursor rule ${relPath} already exists \u2014 skipped`);
3911
3990
  return;
3912
3991
  }
3913
- await mkdir5(path10.dirname(target), { recursive: true });
3914
- await writeFile6(target, CURSOR_HAIVE_RULE_MDC, "utf8");
3992
+ await mkdir6(path11.dirname(target), { recursive: true });
3993
+ await writeFile7(target, CURSOR_HAIVE_RULE_MDC, "utf8");
3915
3994
  ui.success(`Created Cursor rule ${relPath}`);
3916
3995
  }
3917
- async function writeBridge(root, relPath) {
3918
- const target = path10.join(root, relPath);
3919
- if (existsSync10(target)) {
3920
- ui.info(`Bridge ${relPath} already exists \u2014 skipped`);
3921
- return;
3996
+ function resolveBridgeTargets(opt) {
3997
+ const raw = (opt ?? "all").trim().toLowerCase();
3998
+ if (raw === "" || raw === "all") return [...BRIDGE_TARGETS];
3999
+ const requested = raw.split(",").map((t) => t.trim()).filter(Boolean);
4000
+ const valid = requested.filter((t) => BRIDGE_TARGETS.includes(t));
4001
+ const invalid = requested.filter((t) => !BRIDGE_TARGETS.includes(t));
4002
+ if (invalid.length > 0) {
4003
+ ui.warn(`Ignoring unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS.join(", ")}`);
3922
4004
  }
3923
- await mkdir5(path10.dirname(target), { recursive: true });
3924
- await writeFile6(target, BRIDGE_BODY, "utf8");
3925
- ui.success(`Created bridge ${relPath}`);
4005
+ return valid.length > 0 ? valid : [...BRIDGE_TARGETS];
3926
4006
  }
3927
4007
  var RUNTIME_README_BODY = `# .ai/.runtime \u2014 disposable local layer
3928
4008
 
@@ -3937,50 +4017,50 @@ var RUNTIME_GITIGNORE_BODY = `*
3937
4017
  !README.md
3938
4018
  `;
3939
4019
  async function ensureAiRuntimeLayout(runtimeDir) {
3940
- await mkdir5(runtimeDir, { recursive: true });
3941
- const gi = path10.join(runtimeDir, ".gitignore");
3942
- if (!existsSync10(gi)) {
3943
- await writeFile6(gi, RUNTIME_GITIGNORE_BODY, "utf8");
4020
+ await mkdir6(runtimeDir, { recursive: true });
4021
+ const gi = path11.join(runtimeDir, ".gitignore");
4022
+ if (!existsSync11(gi)) {
4023
+ await writeFile7(gi, RUNTIME_GITIGNORE_BODY, "utf8");
3944
4024
  }
3945
- const readme = path10.join(runtimeDir, "README.md");
3946
- if (!existsSync10(readme)) {
3947
- await writeFile6(readme, RUNTIME_README_BODY, "utf8");
4025
+ const readme = path11.join(runtimeDir, "README.md");
4026
+ if (!existsSync11(readme)) {
4027
+ await writeFile7(readme, RUNTIME_README_BODY, "utf8");
3948
4028
  }
3949
4029
  }
3950
4030
  async function ensureAiCacheLayout(cacheDir) {
3951
- await mkdir5(cacheDir, { recursive: true });
3952
- const gi = path10.join(cacheDir, ".gitignore");
3953
- if (!existsSync10(gi)) {
3954
- await writeFile6(gi, "*\n!.gitignore\n", "utf8");
4031
+ await mkdir6(cacheDir, { recursive: true });
4032
+ const gi = path11.join(cacheDir, ".gitignore");
4033
+ if (!existsSync11(gi)) {
4034
+ await writeFile7(gi, "*\n!.gitignore\n", "utf8");
3955
4035
  }
3956
4036
  }
3957
4037
  async function ensureGitignoreEntries(root, patterns) {
3958
4038
  try {
3959
- const gitignorePath = path10.join(root, ".gitignore");
4039
+ const gitignorePath = path11.join(root, ".gitignore");
3960
4040
  let existing = "";
3961
- if (existsSync10(gitignorePath)) {
3962
- existing = await readFile5(gitignorePath, "utf8");
4041
+ if (existsSync11(gitignorePath)) {
4042
+ existing = await readFile6(gitignorePath, "utf8");
3963
4043
  }
3964
4044
  const lines = existing.split("\n");
3965
4045
  const missing = patterns.filter((p) => !lines.some((l) => l.trim() === p));
3966
4046
  if (missing.length === 0) return;
3967
4047
  const toAppend = (existing.endsWith("\n") || existing === "" ? "" : "\n") + "# hAIve project-level MCP configs (machine-specific absolute paths)\n" + missing.join("\n") + "\n";
3968
- await writeFile6(gitignorePath, existing + toAppend, "utf8");
4048
+ await writeFile7(gitignorePath, existing + toAppend, "utf8");
3969
4049
  } catch {
3970
4050
  }
3971
4051
  }
3972
4052
 
3973
4053
  // src/commands/install-hooks.ts
3974
- import { mkdir as mkdir7, writeFile as writeFile8, chmod, readFile as readFile7 } from "fs/promises";
3975
- import { existsSync as existsSync12 } from "fs";
3976
- import path12 from "path";
4054
+ import { mkdir as mkdir8, writeFile as writeFile9, chmod, readFile as readFile8 } from "fs/promises";
4055
+ import { existsSync as existsSync13 } from "fs";
4056
+ import path13 from "path";
3977
4057
  import "commander";
3978
4058
  import { findProjectRoot as findProjectRoot8 } from "@hiveai/core";
3979
4059
 
3980
4060
  // src/utils/claude-hooks.ts
3981
- import { existsSync as existsSync11 } from "fs";
3982
- import { mkdir as mkdir6, readFile as readFile6, writeFile as writeFile7 } from "fs/promises";
3983
- import path11 from "path";
4061
+ import { existsSync as existsSync12 } from "fs";
4062
+ import { mkdir as mkdir7, readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
4063
+ import path12 from "path";
3984
4064
  var HAIVE_HOOK_TAG = "haive-enforcement";
3985
4065
  var POST_TOOL_USE_GROUP = {
3986
4066
  matcher: "Edit|Write|Bash",
@@ -4066,9 +4146,9 @@ function unpatchClaudeSettings(input) {
4066
4146
  async function installClaudeHooksAtPath(settingsPath) {
4067
4147
  let raw = null;
4068
4148
  let created = false;
4069
- if (existsSync11(settingsPath)) {
4149
+ if (existsSync12(settingsPath)) {
4070
4150
  try {
4071
- raw = JSON.parse(await readFile6(settingsPath, "utf8"));
4151
+ raw = JSON.parse(await readFile7(settingsPath, "utf8"));
4072
4152
  } catch {
4073
4153
  throw new Error(`${settingsPath} exists but is not valid JSON. Fix it manually first.`);
4074
4154
  }
@@ -4076,25 +4156,25 @@ async function installClaudeHooksAtPath(settingsPath) {
4076
4156
  created = true;
4077
4157
  }
4078
4158
  const patched = patchClaudeSettings(raw);
4079
- await mkdir6(path11.dirname(settingsPath), { recursive: true });
4080
- await writeFile7(settingsPath, JSON.stringify(patched, null, 2) + "\n", "utf8");
4159
+ await mkdir7(path12.dirname(settingsPath), { recursive: true });
4160
+ await writeFile8(settingsPath, JSON.stringify(patched, null, 2) + "\n", "utf8");
4081
4161
  return { settingsPath, created };
4082
4162
  }
4083
4163
  async function uninstallClaudeHooksAtPath(settingsPath) {
4084
- if (!existsSync11(settingsPath)) {
4164
+ if (!existsSync12(settingsPath)) {
4085
4165
  return { settingsPath, created: false };
4086
4166
  }
4087
- const raw = JSON.parse(await readFile6(settingsPath, "utf8"));
4167
+ const raw = JSON.parse(await readFile7(settingsPath, "utf8"));
4088
4168
  const cleaned = unpatchClaudeSettings(raw);
4089
- await writeFile7(settingsPath, JSON.stringify(cleaned, null, 2) + "\n", "utf8");
4169
+ await writeFile8(settingsPath, JSON.stringify(cleaned, null, 2) + "\n", "utf8");
4090
4170
  return { settingsPath, created: false };
4091
4171
  }
4092
4172
  function defaultClaudeSettingsPath(scope, projectRoot) {
4093
4173
  if (scope === "user") {
4094
4174
  const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
4095
- return path11.join(home, ".claude", "settings.json");
4175
+ return path12.join(home, ".claude", "settings.json");
4096
4176
  }
4097
- return path11.join(projectRoot, ".claude", "settings.local.json");
4177
+ return path12.join(projectRoot, ".claude", "settings.local.json");
4098
4178
  }
4099
4179
 
4100
4180
  // src/commands/install-hooks.ts
@@ -4151,27 +4231,27 @@ fi
4151
4231
  ];
4152
4232
  async function installGitHooks(opts) {
4153
4233
  const root = findProjectRoot8(opts.dir);
4154
- const gitDir = path12.join(root, ".git");
4155
- if (!existsSync12(gitDir)) {
4234
+ const gitDir = path13.join(root, ".git");
4235
+ if (!existsSync13(gitDir)) {
4156
4236
  ui.error(`No .git directory at ${root}.`);
4157
4237
  process.exitCode = 1;
4158
4238
  return;
4159
4239
  }
4160
- const hooksDir = path12.join(gitDir, "hooks");
4161
- await mkdir7(hooksDir, { recursive: true });
4240
+ const hooksDir = path13.join(gitDir, "hooks");
4241
+ await mkdir8(hooksDir, { recursive: true });
4162
4242
  let installed = 0;
4163
4243
  let skipped = 0;
4164
4244
  for (const { name, body } of HOOKS) {
4165
- const file = path12.join(hooksDir, name);
4166
- if (existsSync12(file) && !opts.force) {
4167
- const existing = await readFile7(file, "utf8");
4245
+ const file = path13.join(hooksDir, name);
4246
+ if (existsSync13(file) && !opts.force) {
4247
+ const existing = await readFile8(file, "utf8");
4168
4248
  if (!existing.includes(HOOK_MARKER)) {
4169
4249
  ui.warn(`${name} already exists and was not written by hAIve. Re-run with --force to overwrite.`);
4170
4250
  skipped++;
4171
4251
  continue;
4172
4252
  }
4173
4253
  }
4174
- await writeFile8(file, body, "utf8");
4254
+ await writeFile9(file, body, "utf8");
4175
4255
  await chmod(file, 493);
4176
4256
  installed++;
4177
4257
  }
@@ -4226,9 +4306,9 @@ function registerInstallHooks(program2) {
4226
4306
  }
4227
4307
 
4228
4308
  // src/commands/observe.ts
4229
- import { appendFile, mkdir as mkdir8 } from "fs/promises";
4230
- import { existsSync as existsSync13 } from "fs";
4231
- import path13 from "path";
4309
+ import { appendFile, mkdir as mkdir9 } from "fs/promises";
4310
+ import { existsSync as existsSync14 } from "fs";
4311
+ import path14 from "path";
4232
4312
  import "commander";
4233
4313
  import { findProjectRoot as findProjectRoot9, resolveHaivePaths as resolveHaivePaths7 } from "@hiveai/core";
4234
4314
  var MAX_STDIN_BYTES = 256 * 1024;
@@ -4335,7 +4415,7 @@ function registerObserve(program2) {
4335
4415
  })();
4336
4416
  if (!root) return;
4337
4417
  const paths = resolveHaivePaths7(root);
4338
- if (!existsSync13(paths.haiveDir)) return;
4418
+ if (!existsSync14(paths.haiveDir)) return;
4339
4419
  const failureHint = detectFailure(payload);
4340
4420
  const observation = {
4341
4421
  ts: (/* @__PURE__ */ new Date()).toISOString(),
@@ -4346,10 +4426,10 @@ function registerObserve(program2) {
4346
4426
  files: extractFiles(payload),
4347
4427
  ...failureHint ? { failure_hint: true } : {}
4348
4428
  };
4349
- const cacheDir = path13.join(paths.haiveDir, ".cache");
4350
- await mkdir8(cacheDir, { recursive: true });
4429
+ const cacheDir = path14.join(paths.haiveDir, ".cache");
4430
+ await mkdir9(cacheDir, { recursive: true });
4351
4431
  await appendFile(
4352
- path13.join(cacheDir, "observations.jsonl"),
4432
+ path14.join(cacheDir, "observations.jsonl"),
4353
4433
  JSON.stringify(observation) + "\n",
4354
4434
  "utf8"
4355
4435
  );
@@ -4366,16 +4446,16 @@ import { findProjectRoot as findProjectRoot11 } from "@hiveai/core";
4366
4446
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4367
4447
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4368
4448
  import { findProjectRoot as findProjectRoot10, resolveHaivePaths as resolveHaivePaths8 } from "@hiveai/core";
4369
- import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
4370
- import { existsSync as existsSync14 } from "fs";
4371
- import path14 from "path";
4449
+ import { mkdir as mkdir10, writeFile as writeFile10 } from "fs/promises";
4450
+ import { existsSync as existsSync15 } from "fs";
4451
+ import path15 from "path";
4372
4452
  import { z } from "zod";
4373
- import { readFile as readFile8, readdir as readdir3 } from "fs/promises";
4453
+ import { readFile as readFile9, readdir as readdir3 } from "fs/promises";
4374
4454
  import { existsSync as existsSync22 } from "fs";
4375
4455
  import path22 from "path";
4376
4456
  import { z as z2 } from "zod";
4377
4457
  import { existsSync as existsSync32 } from "fs";
4378
- import { loadMemoriesFromDir as loadMemoriesFromDir4 } from "@hiveai/core";
4458
+ import { loadMemoriesFromDir as loadMemoriesFromDir5 } from "@hiveai/core";
4379
4459
  import { z as z3 } from "zod";
4380
4460
  import { createHash } from "crypto";
4381
4461
  import { mkdir as mkdir22, writeFile as writeFile22 } from "fs/promises";
@@ -4416,7 +4496,7 @@ import { z as z6 } from "zod";
4416
4496
  import { writeFile as writeFile42 } from "fs/promises";
4417
4497
  import { existsSync as existsSync72 } from "fs";
4418
4498
  import {
4419
- loadMemoriesFromDir as loadMemoriesFromDir5,
4499
+ loadMemoriesFromDir as loadMemoriesFromDir52,
4420
4500
  loadUsageIndex as loadUsageIndex22,
4421
4501
  recordRejection,
4422
4502
  saveUsageIndex,
@@ -4486,7 +4566,7 @@ import {
4486
4566
  } from "@hiveai/core";
4487
4567
  import { z as z14 } from "zod";
4488
4568
  import { mkdir as mkdir32, writeFile as writeFile82 } from "fs/promises";
4489
- import { existsSync as existsSync15 } from "fs";
4569
+ import { existsSync as existsSync152 } from "fs";
4490
4570
  import path52 from "path";
4491
4571
  import {
4492
4572
  buildFrontmatter as buildFrontmatter22,
@@ -4507,7 +4587,7 @@ import {
4507
4587
  serializeMemory as serializeMemory8
4508
4588
  } from "@hiveai/core";
4509
4589
  import { z as z16 } from "zod";
4510
- import { mkdir as mkdir52, writeFile as writeFile10 } from "fs/promises";
4590
+ import { mkdir as mkdir52, writeFile as writeFile102 } from "fs/promises";
4511
4591
  import { existsSync as existsSync17 } from "fs";
4512
4592
  import path72 from "path";
4513
4593
  import {
@@ -4552,7 +4632,7 @@ import {
4552
4632
  inferModulesFromPaths as inferModulesFromPaths2,
4553
4633
  isAutoPromoteEligible,
4554
4634
  isDecaying,
4555
- isRetiredMemory,
4635
+ isRetiredMemory as isRetiredMemory2,
4556
4636
  literalMatchesAllTokens as literalMatchesAllTokens22,
4557
4637
  literalMatchesAnyToken as literalMatchesAnyToken22,
4558
4638
  loadCodeMap as loadCodeMap5,
@@ -4617,7 +4697,7 @@ import {
4617
4697
  deriveConfidence as deriveConfidence6,
4618
4698
  diffHasDistinctiveOverlap,
4619
4699
  getUsage as getUsage8,
4620
- isRetiredMemory as isRetiredMemory2,
4700
+ isRetiredMemory as isRetiredMemory22,
4621
4701
  loadMemoriesFromDir as loadMemoriesFromDir19,
4622
4702
  loadUsageIndex as loadUsageIndex10,
4623
4703
  literalMatchesAnyToken as literalMatchesAnyToken3,
@@ -4703,15 +4783,15 @@ var BootstrapProjectSaveInputSchema = {
4703
4783
  overwrite: z.boolean().default(false).describe("Overwrite an existing file instead of failing")
4704
4784
  };
4705
4785
  async function bootstrapProjectSave(input, ctx) {
4706
- const target = input.module ? path14.join(ctx.paths.modulesContextDir, input.module, "context.md") : ctx.paths.projectContext;
4707
- const exists = existsSync14(target);
4786
+ const target = input.module ? path15.join(ctx.paths.modulesContextDir, input.module, "context.md") : ctx.paths.projectContext;
4787
+ const exists = existsSync15(target);
4708
4788
  if (exists && !input.overwrite) {
4709
4789
  throw new Error(
4710
4790
  `${target} already exists. Pass overwrite=true to replace it.`
4711
4791
  );
4712
4792
  }
4713
- await mkdir9(path14.dirname(target), { recursive: true });
4714
- await writeFile9(target, input.content, "utf8");
4793
+ await mkdir10(path15.dirname(target), { recursive: true });
4794
+ await writeFile10(target, input.content, "utf8");
4715
4795
  return {
4716
4796
  file_path: target,
4717
4797
  action: exists ? "overwritten" : "created"
@@ -4724,14 +4804,14 @@ var GetProjectContextInputSchema = {
4724
4804
  async function getProjectContext(input, ctx) {
4725
4805
  const out = { root_context: null };
4726
4806
  if (existsSync22(ctx.paths.projectContext)) {
4727
- out.root_context = await readFile8(ctx.paths.projectContext, "utf8");
4807
+ out.root_context = await readFile9(ctx.paths.projectContext, "utf8");
4728
4808
  }
4729
4809
  if (input.module) {
4730
4810
  const modFile = path22.join(ctx.paths.modulesContextDir, input.module, "context.md");
4731
4811
  if (existsSync22(modFile)) {
4732
4812
  out.module_context = {
4733
4813
  name: input.module,
4734
- content: await readFile8(modFile, "utf8")
4814
+ content: await readFile9(modFile, "utf8")
4735
4815
  };
4736
4816
  }
4737
4817
  }
@@ -4758,7 +4838,7 @@ async function memList(input, ctx) {
4758
4838
  if (!existsSync32(ctx.paths.memoriesDir)) {
4759
4839
  return { memories: [] };
4760
4840
  }
4761
- const all = await loadMemoriesFromDir4(ctx.paths.memoriesDir);
4841
+ const all = await loadMemoriesFromDir5(ctx.paths.memoriesDir);
4762
4842
  const filtered = all.filter(({ memory: memory2 }) => {
4763
4843
  const fm = memory2.frontmatter;
4764
4844
  if (input.scope && fm.scope !== input.scope) return false;
@@ -5252,7 +5332,7 @@ async function memReject(input, ctx) {
5252
5332
  if (!existsSync72(ctx.paths.memoriesDir)) {
5253
5333
  throw new Error(`No .ai/memories at ${ctx.paths.root}.`);
5254
5334
  }
5255
- const memories = await loadMemoriesFromDir5(ctx.paths.memoriesDir);
5335
+ const memories = await loadMemoriesFromDir52(ctx.paths.memoriesDir);
5256
5336
  const loaded = memories.find((m) => m.memory.frontmatter.id === input.id);
5257
5337
  if (!loaded) throw new Error(`No memory with id "${input.id}".`);
5258
5338
  await writeFile42(
@@ -5645,7 +5725,7 @@ var MemTriedInputSchema = {
5645
5725
  author: z15.string().optional().describe("Author handle or email")
5646
5726
  };
5647
5727
  async function memTried(input, ctx) {
5648
- if (!existsSync15(ctx.paths.haiveDir)) {
5728
+ if (!existsSync152(ctx.paths.haiveDir)) {
5649
5729
  throw new Error(`No .ai/ directory at ${ctx.paths.root}. Run 'haive init' first.`);
5650
5730
  }
5651
5731
  const slug = input.what.toLowerCase().replace(/[^a-z0-9\s]/g, "").trim().split(/\s+/).slice(0, 5).join("-");
@@ -5671,7 +5751,7 @@ async function memTried(input, ctx) {
5671
5751
  }
5672
5752
  const file = memoryFilePath22(ctx.paths, frontmatter.scope, frontmatter.id, frontmatter.module);
5673
5753
  await mkdir32(path52.dirname(file), { recursive: true });
5674
- if (existsSync15(file)) {
5754
+ if (existsSync152(file)) {
5675
5755
  throw new Error(`Memory already exists at ${file}`);
5676
5756
  }
5677
5757
  await writeFile82(file, serializeMemory7({ frontmatter, body }), "utf8");
@@ -5805,7 +5885,7 @@ async function memObserve(input, ctx) {
5805
5885
  if (existsSync17(file)) {
5806
5886
  throw new Error(`Memory already exists at ${file}`);
5807
5887
  }
5808
- await writeFile10(file, serializeMemory9({ frontmatter, body }), "utf8");
5888
+ await writeFile102(file, serializeMemory9({ frontmatter, body }), "utf8");
5809
5889
  return { id: frontmatter.id, scope: frontmatter.scope, file_path: file };
5810
5890
  }
5811
5891
  function pendingDistillPath(ctx) {
@@ -6257,7 +6337,7 @@ async function getBriefing(input, ctx) {
6257
6337
  const s = memory2.frontmatter.status;
6258
6338
  if (s === "rejected" || s === "deprecated") return false;
6259
6339
  if (!input.include_stale && s === "stale") return false;
6260
- if (!input.include_stale && isRetiredMemory(memory2.frontmatter, memory2.body)) return false;
6340
+ if (!input.include_stale && isRetiredMemory2(memory2.frontmatter, memory2.body)) return false;
6261
6341
  if (memory2.frontmatter.type === "session_recap") return false;
6262
6342
  return true;
6263
6343
  });
@@ -7125,7 +7205,7 @@ async function antiPatternsCheck(input, ctx) {
7125
7205
  const t = memory2.frontmatter.type;
7126
7206
  if (t !== "attempt" && t !== "gotcha") return false;
7127
7207
  const s = memory2.frontmatter.status;
7128
- return s !== "rejected" && s !== "deprecated" && s !== "stale" && !isRetiredMemory2(memory2.frontmatter, memory2.body);
7208
+ return s !== "rejected" && s !== "deprecated" && s !== "stale" && !isRetiredMemory22(memory2.frontmatter, memory2.body);
7129
7209
  });
7130
7210
  if (negative.length === 0) {
7131
7211
  return { scanned: 0, warnings: [], notice: "No attempt/gotcha memories found yet." };
@@ -8491,7 +8571,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
8491
8571
  };
8492
8572
  }
8493
8573
  var SERVER_NAME = "haive";
8494
- var SERVER_VERSION = "0.18.0";
8574
+ var SERVER_VERSION = "0.19.0";
8495
8575
  function jsonResult(data) {
8496
8576
  return {
8497
8577
  content: [
@@ -9523,8 +9603,8 @@ function registerMcp(program2) {
9523
9603
 
9524
9604
  // src/commands/sync.ts
9525
9605
  import { spawnSync as spawnSync4 } from "child_process";
9526
- import { readFile as readFile10, writeFile as writeFile16, mkdir as mkdir11 } from "fs/promises";
9527
- import { existsSync as existsSync34 } from "fs";
9606
+ import { readFile as readFile10, writeFile as writeFile15, mkdir as mkdir11 } from "fs/promises";
9607
+ import { existsSync as existsSync33 } from "fs";
9528
9608
  import path16 from "path";
9529
9609
  import "commander";
9530
9610
  import {
@@ -9537,7 +9617,7 @@ import {
9537
9617
  isStackPackSeed,
9538
9618
  loadCodeMap as loadCodeMap6,
9539
9619
  loadConfig as loadConfig4,
9540
- loadMemoriesFromDir as loadMemoriesFromDir26,
9620
+ loadMemoriesFromDir as loadMemoriesFromDir25,
9541
9621
  loadUsageIndex as loadUsageIndex13,
9542
9622
  pullCrossRepoSources,
9543
9623
  resolveHaivePaths as resolveHaivePaths9,
@@ -9547,90 +9627,7 @@ import {
9547
9627
  verifyAnchor as verifyAnchor2,
9548
9628
  watchContracts
9549
9629
  } from "@hiveai/core";
9550
- import { BRIDGE_TARGETS } from "@hiveai/core";
9551
-
9552
- // src/utils/bridge-files.ts
9553
- import { mkdir as mkdir10, readFile as readFile9, writeFile as writeFile15 } from "fs/promises";
9554
- import { existsSync as existsSync33 } from "fs";
9555
- import path15 from "path";
9556
- import {
9557
- BRIDGE_MARKERS,
9558
- generateBridges,
9559
- isRetiredMemory as isRetiredMemory3,
9560
- loadMemoriesFromDir as loadMemoriesFromDir25
9561
- } from "@hiveai/core";
9562
- async function writeBridgeFiles(root, paths, opts) {
9563
- const result = { created: [], updated: [], unchanged: [] };
9564
- if (!existsSync33(paths.memoriesDir)) return result;
9565
- const allLoaded = await loadMemoriesFromDir25(paths.memoriesDir);
9566
- const memories = allLoaded.map((l) => l.memory).filter((m) => !isRetiredMemory3(m.frontmatter, m.body));
9567
- const sensors = [];
9568
- for (const m of memories) {
9569
- const sensor = m.frontmatter.sensor;
9570
- if (!sensor || sensor.severity !== "block") continue;
9571
- sensors.push({
9572
- id: m.frontmatter.id,
9573
- severity: "block",
9574
- message: sensor.message,
9575
- ...sensor.pattern ? { pattern: sensor.pattern } : {},
9576
- paths: sensor.paths.length > 0 ? sensor.paths : m.frontmatter.anchor.paths
9577
- });
9578
- }
9579
- const maxMemories = Math.max(1, opts.maxMemories ?? 8);
9580
- const outputs = generateBridges(memories, sensors, { maxMemories, targets: opts.targets });
9581
- for (const output of outputs) {
9582
- const targetFile = path15.join(root, output.path);
9583
- const fileExists = existsSync33(targetFile);
9584
- if (opts.onlyExisting && !fileExists) continue;
9585
- if (opts.dryRun) {
9586
- (fileExists ? result.updated : result.created).push(output.path);
9587
- continue;
9588
- }
9589
- await mkdir10(path15.dirname(targetFile), { recursive: true });
9590
- if (!fileExists) {
9591
- await writeFile15(targetFile, output.content, "utf8");
9592
- result.created.push(output.path);
9593
- continue;
9594
- }
9595
- let existing = (await readFile9(targetFile, "utf8")).replace(/\r\n/g, "\n");
9596
- const withMemories = replaceMarkerBlock(
9597
- existing,
9598
- BRIDGE_MARKERS.memoriesStart,
9599
- BRIDGE_MARKERS.memoriesEnd,
9600
- extractMarkerBlock(output.content, BRIDGE_MARKERS.memoriesStart, BRIDGE_MARKERS.memoriesEnd)
9601
- );
9602
- const sensorsBlockContent = extractMarkerBlock(
9603
- output.content,
9604
- BRIDGE_MARKERS.sensorsStart,
9605
- BRIDGE_MARKERS.sensorsEnd
9606
- );
9607
- const withSensors = sensorsBlockContent ? replaceMarkerBlock(withMemories, BRIDGE_MARKERS.sensorsStart, BRIDGE_MARKERS.sensorsEnd, sensorsBlockContent) : withMemories;
9608
- if (withSensors === existing) {
9609
- result.unchanged.push(output.path);
9610
- continue;
9611
- }
9612
- await writeFile15(targetFile, withSensors, "utf8");
9613
- result.updated.push(output.path);
9614
- }
9615
- return result;
9616
- }
9617
- function extractMarkerBlock(text, startMarker, endMarker) {
9618
- const startIdx = text.indexOf(startMarker);
9619
- const endIdx = text.indexOf(endMarker);
9620
- if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return null;
9621
- return text.slice(startIdx, endIdx + endMarker.length);
9622
- }
9623
- function replaceMarkerBlock(existing, startMarker, endMarker, replacement) {
9624
- if (!replacement) return existing;
9625
- const startIdx = existing.indexOf(startMarker);
9626
- const endIdx = existing.indexOf(endMarker);
9627
- if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) {
9628
- return existing + (existing.endsWith("\n") ? "" : "\n") + "\n" + replacement + "\n";
9629
- }
9630
- return existing.slice(0, startIdx) + replacement + existing.slice(endIdx + endMarker.length);
9631
- }
9632
-
9633
- // src/commands/sync.ts
9630
+ import { BRIDGE_TARGETS as BRIDGE_TARGETS2 } from "@hiveai/core";
9634
9631
  var BRIDGE_START = "<!-- haive:memories-start -->";
9635
9632
  var BRIDGE_END = "<!-- haive:memories-end -->";
9636
9633
  function registerSync(program2) {
@@ -9645,7 +9642,7 @@ function registerSync(program2) {
9645
9642
  ).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) => {
9646
9643
  const root = findProjectRoot12(opts.dir);
9647
9644
  const paths = resolveHaivePaths9(root);
9648
- if (!existsSync34(paths.memoriesDir)) {
9645
+ if (!existsSync33(paths.memoriesDir)) {
9649
9646
  if (!opts.quiet) ui.warn(`No .ai/memories at ${root}. Run \`haive init\` first.`);
9650
9647
  process.exitCode = 1;
9651
9648
  return;
@@ -9664,12 +9661,12 @@ function registerSync(program2) {
9664
9661
  let promoted = 0;
9665
9662
  let autoApproved = 0;
9666
9663
  if (opts.verify !== false) {
9667
- const memories = await loadMemoriesFromDir26(paths.memoriesDir);
9664
+ const memories = await loadMemoriesFromDir25(paths.memoriesDir);
9668
9665
  for (const { memory: memory2, filePath } of memories) {
9669
9666
  if (memory2.frontmatter.type === "session_recap") {
9670
9667
  if (memory2.frontmatter.status === "stale") {
9671
9668
  if (!dryRun) {
9672
- await writeFile16(
9669
+ await writeFile15(
9673
9670
  filePath,
9674
9671
  serializeMemory13({
9675
9672
  frontmatter: {
@@ -9694,7 +9691,7 @@ function registerSync(program2) {
9694
9691
  if (result.stale) {
9695
9692
  if (memory2.frontmatter.status !== "stale") {
9696
9693
  if (!dryRun) {
9697
- await writeFile16(
9694
+ await writeFile15(
9698
9695
  filePath,
9699
9696
  serializeMemory13({
9700
9697
  frontmatter: {
@@ -9712,7 +9709,7 @@ function registerSync(program2) {
9712
9709
  }
9713
9710
  } else if (memory2.frontmatter.status === "stale") {
9714
9711
  if (!dryRun) {
9715
- await writeFile16(
9712
+ await writeFile15(
9716
9713
  filePath,
9717
9714
  serializeMemory13({
9718
9715
  frontmatter: {
@@ -9731,7 +9728,7 @@ function registerSync(program2) {
9731
9728
  }
9732
9729
  }
9733
9730
  if (opts.promote !== false) {
9734
- const memories = await loadMemoriesFromDir26(paths.memoriesDir);
9731
+ const memories = await loadMemoriesFromDir25(paths.memoriesDir);
9735
9732
  const usage = await loadUsageIndex13(paths);
9736
9733
  const nowMs = Date.now();
9737
9734
  for (const { memory: memory2, filePath } of memories) {
@@ -9742,7 +9739,7 @@ function registerSync(program2) {
9742
9739
  maxRejections: DEFAULT_AUTO_PROMOTE_RULE2.maxRejections
9743
9740
  })) {
9744
9741
  if (!dryRun) {
9745
- await writeFile16(
9742
+ await writeFile15(
9746
9743
  filePath,
9747
9744
  serializeMemory13({ frontmatter: { ...fm, status: "validated" }, body: memory2.body }),
9748
9745
  "utf8"
@@ -9755,7 +9752,7 @@ function registerSync(program2) {
9755
9752
  const ageHours = (nowMs - new Date(fm.created_at).getTime()) / (1e3 * 60 * 60);
9756
9753
  if (ageHours >= autoApproveDelayHours) {
9757
9754
  if (!dryRun) {
9758
- await writeFile16(
9755
+ await writeFile15(
9759
9756
  filePath,
9760
9757
  serializeMemory13({
9761
9758
  frontmatter: {
@@ -9783,7 +9780,7 @@ function registerSync(program2) {
9783
9780
  for (const repair of repairs) log(ui.dim(`autopilot: ${repair.message}`));
9784
9781
  }
9785
9782
  const sinceReport = opts.since ? collectSinceChanges(root, opts.since) : null;
9786
- const draftMemories = (await loadMemoriesFromDir26(paths.memoriesDir)).filter(
9783
+ const draftMemories = (await loadMemoriesFromDir25(paths.memoriesDir)).filter(
9787
9784
  (m) => m.memory.frontmatter.status === "draft"
9788
9785
  );
9789
9786
  const draftCount = draftMemories.length;
@@ -9806,14 +9803,14 @@ function registerSync(program2) {
9806
9803
  } else {
9807
9804
  const agentsMd = path16.join(root, "AGENTS.md");
9808
9805
  bridgeTargets = [path16.join(root, "CLAUDE.md")];
9809
- if (existsSync34(agentsMd)) bridgeTargets.push(agentsMd);
9806
+ if (existsSync33(agentsMd)) bridgeTargets.push(agentsMd);
9810
9807
  }
9811
9808
  for (const bridgeFile of bridgeTargets) {
9812
9809
  await injectBridge(bridgeFile, paths.memoriesDir, maxInject, root, opts.quiet);
9813
9810
  }
9814
9811
  }
9815
9812
  if (opts.noBridges !== true) {
9816
- const nativeTargets = BRIDGE_TARGETS.filter(
9813
+ const nativeTargets = BRIDGE_TARGETS2.filter(
9817
9814
  (t) => t !== "claude" && t !== "agents"
9818
9815
  );
9819
9816
  try {
@@ -9849,7 +9846,7 @@ function registerSync(program2) {
9849
9846
  }
9850
9847
  }
9851
9848
  if (!opts.quiet) {
9852
- const allForDecay = await loadMemoriesFromDir26(paths.memoriesDir);
9849
+ const allForDecay = await loadMemoriesFromDir25(paths.memoriesDir);
9853
9850
  const usageForDecay = await loadUsageIndex13(paths);
9854
9851
  const decaying = allForDecay.filter(({ memory: memory2 }) => {
9855
9852
  const fm = memory2.frontmatter;
@@ -9939,7 +9936,7 @@ Wait for **explicit confirmation** before acting.
9939
9936
  if (!dryRun) {
9940
9937
  const teamDir = path16.join(paths.memoriesDir, "team");
9941
9938
  await mkdir11(teamDir, { recursive: true });
9942
- await writeFile16(
9939
+ await writeFile15(
9943
9940
  path16.join(teamDir, `${fm.id}.md`),
9944
9941
  serializeMemory13({ frontmatter: { ...fm, requires_human_approval: true }, body }),
9945
9942
  "utf8"
@@ -10008,7 +10005,7 @@ Wait for **explicit confirmation** before acting.
10008
10005
  if (!dryRun) {
10009
10006
  const teamDir = path16.join(paths.memoriesDir, "team");
10010
10007
  await mkdir11(teamDir, { recursive: true });
10011
- await writeFile16(
10008
+ await writeFile15(
10012
10009
  path16.join(teamDir, `${fm.id}.md`),
10013
10010
  serializeMemory13({ frontmatter: { ...fm, requires_human_approval: true }, body }),
10014
10011
  "utf8"
@@ -10100,8 +10097,8 @@ function bridgeSummaryLine(body) {
10100
10097
  return oneLine.length > 140 ? oneLine.slice(0, 137) + "\u2026" : oneLine;
10101
10098
  }
10102
10099
  async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
10103
- if (!existsSync34(memoriesDir)) return;
10104
- const all = await loadMemoriesFromDir26(memoriesDir);
10100
+ if (!existsSync33(memoriesDir)) return;
10101
+ const all = await loadMemoriesFromDir25(memoriesDir);
10105
10102
  const top = all.filter(({ memory: memory2 }) => {
10106
10103
  const s = memory2.frontmatter.status;
10107
10104
  if (memory2.frontmatter.type === "session_recap") return false;
@@ -10126,7 +10123,7 @@ async function injectBridge(bridgeFile, memoriesDir, maxMemories, root, quiet) {
10126
10123
  ` + block + `
10127
10124
 
10128
10125
  ${BRIDGE_END}`;
10129
- const fileExists = existsSync34(bridgeFile);
10126
+ const fileExists = existsSync33(bridgeFile);
10130
10127
  let existing = fileExists ? await readFile10(bridgeFile, "utf8") : "";
10131
10128
  existing = existing.replace(/\r\n/g, "\n");
10132
10129
  const startIdx = existing.indexOf(BRIDGE_START);
@@ -10148,7 +10145,7 @@ ${BRIDGE_END}`;
10148
10145
  }
10149
10146
  updated = existing + (existing.endsWith("\n") ? "" : "\n") + "\n" + injected + "\n";
10150
10147
  }
10151
- await writeFile16(bridgeFile, updated, "utf8");
10148
+ await writeFile15(bridgeFile, updated, "utf8");
10152
10149
  if (!quiet) {
10153
10150
  console.log(
10154
10151
  ui.dim(`bridge: injected ${top.length} memor${top.length === 1 ? "y" : "ies"} into ${path16.relative(root, bridgeFile)}`)
@@ -10176,8 +10173,8 @@ function collectSinceChanges(root, ref) {
10176
10173
 
10177
10174
  // src/commands/memory-add.ts
10178
10175
  import { createHash as createHash2 } from "crypto";
10179
- import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile17 } from "fs/promises";
10180
- import { existsSync as existsSync35 } from "fs";
10176
+ import { mkdir as mkdir12, readFile as readFile11, writeFile as writeFile16 } from "fs/promises";
10177
+ import { existsSync as existsSync34 } from "fs";
10181
10178
  import path17 from "path";
10182
10179
  import "commander";
10183
10180
  import {
@@ -10185,7 +10182,7 @@ import {
10185
10182
  findProjectRoot as findProjectRoot13,
10186
10183
  inferModulesFromPaths as inferModulesFromPaths3,
10187
10184
  loadConfig as loadConfig5,
10188
- loadMemoriesFromDir as loadMemoriesFromDir27,
10185
+ loadMemoriesFromDir as loadMemoriesFromDir26,
10189
10186
  memoryFilePath as memoryFilePath7,
10190
10187
  resolveHaivePaths as resolveHaivePaths10,
10191
10188
  serializeMemory as serializeMemory14,
@@ -10219,7 +10216,7 @@ function registerMemoryAdd(memory2) {
10219
10216
  ).requiredOption("--type <type>", "skill | convention | decision | gotcha | architecture | glossary | attempt").option("--slug <slug>", "short kebab-case identifier used in the file name (auto-derived from --title/--body when omitted)").option("--title <text>", "memory title \u2014 becomes the first heading of the body").option("--scope <scope>", "personal | team | module (default: config default; team in autopilot)").option("--module <name>", "module name (required when scope=module)").option("--tags <csv>", "comma-separated tags for easier retrieval").option("--domain <domain>", "domain (e.g. transactions)").option("--author <author>", "author email or handle").option("--paths <csv>", "anchor to source files \u2014 used for staleness detection by haive sync").option("--files <csv>", "alias for --paths (matches the MCP `files` parameter)").option("--symbols <csv>", "anchor to specific symbols (class/function names)").option("--commit <sha>", "anchor to a specific commit SHA").option("--body <text>", "memory body content (Markdown) \u2014 overrides --title default body").option("--body-file <path>", "read memory body from a Markdown file \u2014 for long content").option("--no-auto-tag", "disable automatic tag suggestions inferred from anchor paths").option("--topic <key>", "stable key for upsert: if a memory with this topic+scope already exists, update it in-place (revision_count++)").option("--activation-keyword <csv>", "skill only: comma-separated keywords that trigger progressive disclosure of this skill").option("--activation-glob <csv>", "skill only: comma-separated path globs that trigger this skill").option("--activation-always", "skill only: always surface this skill (no triggers needed)").option("-d, --dir <dir>", "project root").action(async (opts) => {
10220
10217
  const root = findProjectRoot13(opts.dir);
10221
10218
  const paths = resolveHaivePaths10(root);
10222
- if (!existsSync35(paths.haiveDir)) {
10219
+ if (!existsSync34(paths.haiveDir)) {
10223
10220
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
10224
10221
  process.exitCode = 1;
10225
10222
  return;
@@ -10236,7 +10233,7 @@ function registerMemoryAdd(memory2) {
10236
10233
  const inferredTags = autoTagsEnabled ? inferModulesFromPaths3(anchorPaths) : [];
10237
10234
  const mergedTags = Array.from(/* @__PURE__ */ new Set([...userTags, ...inferredTags]));
10238
10235
  if (anchorPaths.length > 0) {
10239
- const missing = anchorPaths.filter((p) => !existsSync35(path17.resolve(root, p)));
10236
+ const missing = anchorPaths.filter((p) => !existsSync34(path17.resolve(root, p)));
10240
10237
  if (missing.length > 0) {
10241
10238
  ui.warn(`Anchor path${missing.length > 1 ? "s" : ""} not found in project:`);
10242
10239
  for (const p of missing) ui.warn(` \u2717 ${p}`);
@@ -10249,7 +10246,7 @@ function registerMemoryAdd(memory2) {
10249
10246
  const slug = slugify(opts.slug ?? opts.title ?? opts.topic ?? opts.body ?? `${opts.type}-memory`);
10250
10247
  let body;
10251
10248
  if (opts.bodyFile !== void 0) {
10252
- if (!existsSync35(opts.bodyFile)) {
10249
+ if (!existsSync34(opts.bodyFile)) {
10253
10250
  ui.error(`--body-file not found: ${opts.bodyFile}`);
10254
10251
  process.exitCode = 1;
10255
10252
  return;
@@ -10265,9 +10262,9 @@ TODO \u2014 write the memory body.
10265
10262
  `;
10266
10263
  }
10267
10264
  const scope = opts.scope ?? config.defaultScope ?? "personal";
10268
- if (existsSync35(paths.memoriesDir)) {
10265
+ if (existsSync34(paths.memoriesDir)) {
10269
10266
  const incomingHash = createHash2("sha256").update(body.trim()).digest("hex").slice(0, 12);
10270
- const allForHash = await loadMemoriesFromDir27(paths.memoriesDir);
10267
+ const allForHash = await loadMemoriesFromDir26(paths.memoriesDir);
10271
10268
  const hashDup = allForHash.find(
10272
10269
  ({ memory: memory3 }) => createHash2("sha256").update(memory3.body.trim()).digest("hex").slice(0, 12) === incomingHash && memory3.frontmatter.scope === scope
10273
10270
  );
@@ -10278,8 +10275,8 @@ TODO \u2014 write the memory body.
10278
10275
  return;
10279
10276
  }
10280
10277
  }
10281
- if (opts.topic && existsSync35(paths.memoriesDir)) {
10282
- const existing = await loadMemoriesFromDir27(paths.memoriesDir);
10278
+ if (opts.topic && existsSync34(paths.memoriesDir)) {
10279
+ const existing = await loadMemoriesFromDir26(paths.memoriesDir);
10283
10280
  const topicMatch = existing.find(
10284
10281
  ({ memory: memory3 }) => memory3.frontmatter.topic === opts.topic && memory3.frontmatter.scope === scope && (!opts.module || memory3.frontmatter.module === opts.module)
10285
10282
  );
@@ -10299,7 +10296,7 @@ TODO \u2014 write the memory body.
10299
10296
  };
10300
10297
  const suggestedSensor = !newFrontmatter.sensor ? suggestSensorForCliMemory(opts.type, body, newFrontmatter.anchor.paths) : null;
10301
10298
  if (suggestedSensor) newFrontmatter.sensor = suggestedSensor;
10302
- await writeFile17(topicMatch.filePath, serializeMemory14({ frontmatter: newFrontmatter, body }), "utf8");
10299
+ await writeFile16(topicMatch.filePath, serializeMemory14({ frontmatter: newFrontmatter, body }), "utf8");
10303
10300
  ui.success(`Updated (topic upsert) ${path17.relative(root, topicMatch.filePath)}`);
10304
10301
  ui.info(`id=${fm.id} revision=${revisionCount}`);
10305
10302
  if (suggestedSensor) ui.info(`sensor=regex warn autogen pattern=${JSON.stringify(suggestedSensor.pattern)}`);
@@ -10325,13 +10322,13 @@ TODO \u2014 write the memory body.
10325
10322
  });
10326
10323
  const file = memoryFilePath7(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
10327
10324
  await mkdir12(path17.dirname(file), { recursive: true });
10328
- if (existsSync35(file)) {
10325
+ if (existsSync34(file)) {
10329
10326
  ui.error(`Memory already exists at ${file}`);
10330
10327
  process.exitCode = 1;
10331
10328
  return;
10332
10329
  }
10333
- if (existsSync35(paths.memoriesDir)) {
10334
- const existing = await loadMemoriesFromDir27(paths.memoriesDir);
10330
+ if (existsSync34(paths.memoriesDir)) {
10331
+ const existing = await loadMemoriesFromDir26(paths.memoriesDir);
10335
10332
  const slugTokens = slug.toLowerCase().split(/[-_\s]+/).filter(Boolean);
10336
10333
  const similar = existing.filter(({ memory: memory3 }) => {
10337
10334
  const id = memory3.frontmatter.id.toLowerCase();
@@ -10342,7 +10339,7 @@ TODO \u2014 write the memory body.
10342
10339
  ui.warn("Consider updating one of these with `haive memory update` instead.");
10343
10340
  }
10344
10341
  }
10345
- await writeFile17(file, serializeMemory14({ frontmatter, body }), "utf8");
10342
+ await writeFile16(file, serializeMemory14({ frontmatter, body }), "utf8");
10346
10343
  ui.success(`Created ${path17.relative(root, file)}`);
10347
10344
  ui.info(`id=${frontmatter.id} scope=${frontmatter.scope} status=${frontmatter.status}`);
10348
10345
  if (frontmatter.sensor?.autogen) {
@@ -10422,14 +10419,14 @@ function slugify(value) {
10422
10419
  }
10423
10420
 
10424
10421
  // src/commands/memory-list.ts
10425
- import { existsSync as existsSync36 } from "fs";
10422
+ import { existsSync as existsSync35 } from "fs";
10426
10423
  import path18 from "path";
10427
10424
  import "commander";
10428
10425
  import { findProjectRoot as findProjectRoot14, resolveHaivePaths as resolveHaivePaths11 } from "@hiveai/core";
10429
10426
 
10430
10427
  // src/utils/fs.ts
10431
10428
  import {
10432
- loadMemoriesFromDir as loadMemoriesFromDir28,
10429
+ loadMemoriesFromDir as loadMemoriesFromDir27,
10433
10430
  loadMemory,
10434
10431
  listMarkdownFilesRecursive
10435
10432
  } from "@hiveai/core";
@@ -10439,12 +10436,12 @@ function registerMemoryList(memory2) {
10439
10436
  memory2.command("list").description("List memories with optional filters").option("--scope <scope>", "personal | team | module").option("--type <type>", "filter by type").option("--tag <tag>", "filter by tag").option("--module <name>", "filter by module name").option("--status <csv>", "filter by status (draft,proposed,validated,stale,rejected,deprecated)").option("--show-rejected", "include rejected memories (hidden by default)").option("--limit <n>", "max memories to display").option("-d, --dir <dir>", "project root").action(async (opts) => {
10440
10437
  const root = findProjectRoot14(opts.dir);
10441
10438
  const paths = resolveHaivePaths11(root);
10442
- if (!existsSync36(paths.memoriesDir)) {
10439
+ if (!existsSync35(paths.memoriesDir)) {
10443
10440
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`haive init\` first.`);
10444
10441
  process.exitCode = 1;
10445
10442
  return;
10446
10443
  }
10447
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
10444
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
10448
10445
  const statusFilter = opts.status ? opts.status.split(",").map((s) => s.trim()) : null;
10449
10446
  const limit = opts.limit ? Math.max(1, parseInt(opts.limit, 10)) : void 0;
10450
10447
  const filtered = all.filter((m) => {
@@ -10513,8 +10510,8 @@ function matchesFilters(loaded, opts) {
10513
10510
  }
10514
10511
 
10515
10512
  // src/commands/memory-promote.ts
10516
- import { mkdir as mkdir13, unlink as unlink2, writeFile as writeFile18 } from "fs/promises";
10517
- import { existsSync as existsSync37 } from "fs";
10513
+ import { mkdir as mkdir13, unlink as unlink2, writeFile as writeFile17 } from "fs/promises";
10514
+ import { existsSync as existsSync36 } from "fs";
10518
10515
  import path19 from "path";
10519
10516
  import "commander";
10520
10517
  import {
@@ -10527,12 +10524,12 @@ function registerMemoryPromote(memory2) {
10527
10524
  memory2.command("promote <id>").description("Promote a personal memory to team scope (status -> proposed)").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
10528
10525
  const root = findProjectRoot15(opts.dir);
10529
10526
  const paths = resolveHaivePaths12(root);
10530
- if (!existsSync37(paths.memoriesDir)) {
10527
+ if (!existsSync36(paths.memoriesDir)) {
10531
10528
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`haive init\` first.`);
10532
10529
  process.exitCode = 1;
10533
10530
  return;
10534
10531
  }
10535
- const teamAndModule = await loadMemoriesFromDir28(paths.memoriesDir);
10532
+ const teamAndModule = await loadMemoriesFromDir27(paths.memoriesDir);
10536
10533
  const alreadyShared = teamAndModule.find(
10537
10534
  (m) => m.memory.frontmatter.id === id && (m.memory.frontmatter.scope === "team" || m.memory.frontmatter.scope === "module")
10538
10535
  );
@@ -10546,7 +10543,7 @@ function registerMemoryPromote(memory2) {
10546
10543
  }
10547
10544
  return;
10548
10545
  }
10549
- const all = await loadMemoriesFromDir28(paths.personalDir);
10546
+ const all = await loadMemoriesFromDir27(paths.personalDir);
10550
10547
  const found = all.find((m) => m.memory.frontmatter.id === id);
10551
10548
  if (!found) {
10552
10549
  ui.error(`No personal memory with id "${id}". (Promotion only applies to personal scope.)`);
@@ -10563,7 +10560,7 @@ function registerMemoryPromote(memory2) {
10563
10560
  };
10564
10561
  const newPath = memoryFilePath8(paths, "team", updated.frontmatter.id);
10565
10562
  await mkdir13(path19.dirname(newPath), { recursive: true });
10566
- await writeFile18(newPath, serializeMemory15(updated), "utf8");
10563
+ await writeFile17(newPath, serializeMemory15(updated), "utf8");
10567
10564
  await unlink2(found.filePath);
10568
10565
  ui.success(`Promoted ${id} to team scope (status=proposed)`);
10569
10566
  ui.info(`Now at ${path19.relative(root, newPath)}`);
@@ -10572,8 +10569,8 @@ function registerMemoryPromote(memory2) {
10572
10569
  }
10573
10570
 
10574
10571
  // src/commands/memory-approve.ts
10575
- import { existsSync as existsSync38 } from "fs";
10576
- import { writeFile as writeFile19 } from "fs/promises";
10572
+ import { existsSync as existsSync37 } from "fs";
10573
+ import { writeFile as writeFile18 } from "fs/promises";
10577
10574
  import path20 from "path";
10578
10575
  import "commander";
10579
10576
  import {
@@ -10585,12 +10582,12 @@ function registerMemoryApprove(memory2) {
10585
10582
  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) => {
10586
10583
  const root = findProjectRoot16(opts.dir);
10587
10584
  const paths = resolveHaivePaths13(root);
10588
- if (!existsSync38(paths.memoriesDir)) {
10585
+ if (!existsSync37(paths.memoriesDir)) {
10589
10586
  ui.error(`No .ai/memories at ${root}.`);
10590
10587
  process.exitCode = 1;
10591
10588
  return;
10592
10589
  }
10593
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
10590
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
10594
10591
  if (opts.all || opts.pending) {
10595
10592
  const candidates = all.filter((m) => {
10596
10593
  const s = m.memory.frontmatter.status;
@@ -10607,7 +10604,7 @@ function registerMemoryApprove(memory2) {
10607
10604
  frontmatter: { ...found2.memory.frontmatter, status: "validated" },
10608
10605
  body: found2.memory.body
10609
10606
  };
10610
- await writeFile19(found2.filePath, serializeMemory16(next2), "utf8");
10607
+ await writeFile18(found2.filePath, serializeMemory16(next2), "utf8");
10611
10608
  count++;
10612
10609
  }
10613
10610
  ui.success(`Approved ${count} memor${count === 1 ? "y" : "ies"} (status=validated)`);
@@ -10636,15 +10633,15 @@ function registerMemoryApprove(memory2) {
10636
10633
  frontmatter: { ...found.memory.frontmatter, status: "validated" },
10637
10634
  body: found.memory.body
10638
10635
  };
10639
- await writeFile19(found.filePath, serializeMemory16(next), "utf8");
10636
+ await writeFile18(found.filePath, serializeMemory16(next), "utf8");
10640
10637
  ui.success(`Approved ${id} (status=validated)`);
10641
10638
  ui.info(path20.relative(root, found.filePath));
10642
10639
  });
10643
10640
  }
10644
10641
 
10645
10642
  // src/commands/memory-update.ts
10646
- import { readFile as readFile12, writeFile as writeFile20 } from "fs/promises";
10647
- import { existsSync as existsSync39 } from "fs";
10643
+ import { readFile as readFile12, writeFile as writeFile19 } from "fs/promises";
10644
+ import { existsSync as existsSync38 } from "fs";
10648
10645
  import path21 from "path";
10649
10646
  import "commander";
10650
10647
  import {
@@ -10656,12 +10653,12 @@ function registerMemoryUpdate(memory2) {
10656
10653
  memory2.command("update <id>").description("Update body, tags, or anchor of an existing memory (preserves id and usage history)").option("--type <type>", "change the memory type (convention | decision | gotcha | architecture | glossary | skill | attempt)").option("--title <text>", "new title \u2014 replaces the first heading of the body").option("--body <text>", "new Markdown body \u2014 replaces the existing body").option("--body-file <path>", "read new body from a Markdown file \u2014 for long content").option("--tags <csv>", "new tags, comma-separated \u2014 fully replaces existing tags").option("--paths <csv>", "new anchor paths, comma-separated").option("--files <csv>", "alias for --paths (matches the MCP `files` parameter)").option("--symbols <csv>", "new anchor symbols, comma-separated").option("--commit <sha>", "new anchor commit SHA").option("--domain <domain>", "new domain label").option("--author <author>", "new author handle or email").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
10657
10654
  const root = findProjectRoot17(opts.dir);
10658
10655
  const paths = resolveHaivePaths14(root);
10659
- if (!existsSync39(paths.memoriesDir)) {
10656
+ if (!existsSync38(paths.memoriesDir)) {
10660
10657
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
10661
10658
  process.exitCode = 1;
10662
10659
  return;
10663
10660
  }
10664
- const memories = await loadMemoriesFromDir28(paths.memoriesDir);
10661
+ const memories = await loadMemoriesFromDir27(paths.memoriesDir);
10665
10662
  const loaded = memories.find((m) => m.memory.frontmatter.id === id);
10666
10663
  if (!loaded) {
10667
10664
  ui.error(`No memory with id "${id}".`);
@@ -10698,7 +10695,7 @@ function registerMemoryUpdate(memory2) {
10698
10695
  if (opts.author !== void 0) updated.push("author");
10699
10696
  let newBody;
10700
10697
  if (opts.bodyFile !== void 0) {
10701
- if (!existsSync39(opts.bodyFile)) {
10698
+ if (!existsSync38(opts.bodyFile)) {
10702
10699
  ui.error(`--body-file not found: ${opts.bodyFile}`);
10703
10700
  process.exitCode = 1;
10704
10701
  return;
@@ -10719,7 +10716,7 @@ function registerMemoryUpdate(memory2) {
10719
10716
  ui.warn("Nothing to update \u2014 provide at least one option.");
10720
10717
  return;
10721
10718
  }
10722
- await writeFile20(
10719
+ await writeFile19(
10723
10720
  loaded.filePath,
10724
10721
  serializeMemory17({ frontmatter: newFrontmatter, body: newBody }),
10725
10722
  "utf8"
@@ -10743,8 +10740,8 @@ function parseCsv3(value) {
10743
10740
  }
10744
10741
 
10745
10742
  // src/commands/memory-auto-promote.ts
10746
- import { writeFile as writeFile21 } from "fs/promises";
10747
- import { existsSync as existsSync40 } from "fs";
10743
+ import { writeFile as writeFile20 } from "fs/promises";
10744
+ import { existsSync as existsSync39 } from "fs";
10748
10745
  import path23 from "path";
10749
10746
  import "commander";
10750
10747
  import {
@@ -10764,7 +10761,7 @@ function registerMemoryAutoPromote(memory2) {
10764
10761
  ).option("--apply", "actually write status=validated to disk (default: dry-run)").option("-d, --dir <dir>", "project root").action(async (opts) => {
10765
10762
  const root = findProjectRoot18(opts.dir);
10766
10763
  const paths = resolveHaivePaths15(root);
10767
- if (!existsSync40(paths.memoriesDir)) {
10764
+ if (!existsSync39(paths.memoriesDir)) {
10768
10765
  ui.error(`No .ai/memories at ${root}.`);
10769
10766
  process.exitCode = 1;
10770
10767
  return;
@@ -10773,7 +10770,7 @@ function registerMemoryAutoPromote(memory2) {
10773
10770
  minReads: Number(opts.minReads ?? DEFAULT_AUTO_PROMOTE_RULE3.minReads),
10774
10771
  maxRejections: Number(opts.maxRejections ?? DEFAULT_AUTO_PROMOTE_RULE3.maxRejections)
10775
10772
  };
10776
- const memories = await loadMemoriesFromDir28(paths.memoriesDir);
10773
+ const memories = await loadMemoriesFromDir27(paths.memoriesDir);
10777
10774
  const usage = await loadUsageIndex14(paths);
10778
10775
  const eligible = memories.filter(
10779
10776
  ({ memory: memory3 }) => isAutoPromoteEligible3(memory3.frontmatter, getUsage12(usage, memory3.frontmatter.id), rule)
@@ -10796,7 +10793,7 @@ function registerMemoryAutoPromote(memory2) {
10796
10793
  frontmatter: { ...mem.frontmatter, status: "validated" },
10797
10794
  body: mem.body
10798
10795
  };
10799
- await writeFile21(filePath, serializeMemory18(next), "utf8");
10796
+ await writeFile20(filePath, serializeMemory18(next), "utf8");
10800
10797
  written++;
10801
10798
  }
10802
10799
  }
@@ -10807,7 +10804,7 @@ function registerMemoryAutoPromote(memory2) {
10807
10804
 
10808
10805
  // src/commands/memory-edit.ts
10809
10806
  import { spawn as spawn3 } from "child_process";
10810
- import { existsSync as existsSync41 } from "fs";
10807
+ import { existsSync as existsSync40 } from "fs";
10811
10808
  import { readFile as readFile13 } from "fs/promises";
10812
10809
  import path24 from "path";
10813
10810
  import "commander";
@@ -10820,12 +10817,12 @@ function registerMemoryEdit(memory2) {
10820
10817
  memory2.command("edit <id>").description("Open a memory in $EDITOR and re-validate when you save").option("-e, --editor <cmd>", "editor command (defaults to $EDITOR or 'vi')").option("-d, --dir <dir>", "project root").action(async (id, opts) => {
10821
10818
  const root = findProjectRoot19(opts.dir);
10822
10819
  const paths = resolveHaivePaths16(root);
10823
- if (!existsSync41(paths.memoriesDir)) {
10820
+ if (!existsSync40(paths.memoriesDir)) {
10824
10821
  ui.error(`No .ai/memories at ${root}.`);
10825
10822
  process.exitCode = 1;
10826
10823
  return;
10827
10824
  }
10828
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
10825
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
10829
10826
  const found = all.find((m) => m.memory.frontmatter.id === id);
10830
10827
  if (!found) {
10831
10828
  ui.error(`No memory with id "${id}".`);
@@ -10860,7 +10857,7 @@ function runEditor(editor, file) {
10860
10857
  }
10861
10858
 
10862
10859
  // src/commands/memory-for-files.ts
10863
- import { existsSync as existsSync43 } from "fs";
10860
+ import { existsSync as existsSync41 } from "fs";
10864
10861
  import path25 from "path";
10865
10862
  import "commander";
10866
10863
  import {
@@ -10876,12 +10873,12 @@ function registerMemoryForFiles(memory2) {
10876
10873
  memory2.command("for-files <files...>").description("Show memories relevant to the given files (anchor overlap, module, domain)").option("-d, --dir <dir>", "project root").action(async (files, opts) => {
10877
10874
  const root = findProjectRoot20(opts.dir);
10878
10875
  const paths = resolveHaivePaths17(root);
10879
- if (!existsSync43(paths.memoriesDir)) {
10876
+ if (!existsSync41(paths.memoriesDir)) {
10880
10877
  ui.error(`No .ai/memories at ${root}.`);
10881
10878
  process.exitCode = 1;
10882
10879
  return;
10883
10880
  }
10884
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
10881
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
10885
10882
  const usage = await loadUsageIndex15(paths);
10886
10883
  const inferred = inferModulesFromPaths4(files);
10887
10884
  const byAnchor = [];
@@ -10988,7 +10985,7 @@ function printGroup(root, label, loaded, usage) {
10988
10985
  }
10989
10986
 
10990
10987
  // src/commands/memory-hot.ts
10991
- import { existsSync as existsSync44 } from "fs";
10988
+ import { existsSync as existsSync43 } from "fs";
10992
10989
  import path26 from "path";
10993
10990
  import "commander";
10994
10991
  import {
@@ -11003,13 +11000,13 @@ function registerMemoryHot(memory2) {
11003
11000
  ).option("--threshold <n>", "minimum read_count to qualify (default: 3)", "3").option("--status <status>", "limit to one status (default: draft + proposed)").option("-d, --dir <dir>", "project root").action(async (opts) => {
11004
11001
  const root = findProjectRoot21(opts.dir);
11005
11002
  const paths = resolveHaivePaths18(root);
11006
- if (!existsSync44(paths.memoriesDir)) {
11003
+ if (!existsSync43(paths.memoriesDir)) {
11007
11004
  ui.error(`No .ai/memories at ${root}.`);
11008
11005
  process.exitCode = 1;
11009
11006
  return;
11010
11007
  }
11011
11008
  const threshold = Math.max(1, Number(opts.threshold ?? 3));
11012
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11009
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11013
11010
  const usage = await loadUsageIndex16(paths);
11014
11011
  const candidates = all.filter(({ memory: mem }) => {
11015
11012
  const fm = mem.frontmatter;
@@ -11041,8 +11038,8 @@ function registerMemoryHot(memory2) {
11041
11038
  }
11042
11039
 
11043
11040
  // src/commands/memory-tried.ts
11044
- import { mkdir as mkdir14, writeFile as writeFile23 } from "fs/promises";
11045
- import { existsSync as existsSync45 } from "fs";
11041
+ import { mkdir as mkdir14, writeFile as writeFile21 } from "fs/promises";
11042
+ import { existsSync as existsSync44 } from "fs";
11046
11043
  import path27 from "path";
11047
11044
  import "commander";
11048
11045
  import {
@@ -11072,7 +11069,7 @@ function registerMemoryTried(memory2) {
11072
11069
  ).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("-d, --dir <dir>", "project root").action(async (opts) => {
11073
11070
  const root = findProjectRoot22(opts.dir);
11074
11071
  const paths = resolveHaivePaths19(root);
11075
- if (!existsSync45(paths.haiveDir)) {
11072
+ if (!existsSync44(paths.haiveDir)) {
11076
11073
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
11077
11074
  process.exitCode = 1;
11078
11075
  return;
@@ -11100,12 +11097,12 @@ function registerMemoryTried(memory2) {
11100
11097
  }
11101
11098
  const file = memoryFilePath9(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
11102
11099
  await mkdir14(path27.dirname(file), { recursive: true });
11103
- if (existsSync45(file)) {
11100
+ if (existsSync44(file)) {
11104
11101
  ui.error(`Memory already exists at ${file}`);
11105
11102
  process.exitCode = 1;
11106
11103
  return;
11107
11104
  }
11108
- await writeFile23(file, serializeMemory19({ frontmatter, body }), "utf8");
11105
+ await writeFile21(file, serializeMemory19({ frontmatter, body }), "utf8");
11109
11106
  ui.success(`Recorded: ${path27.relative(root, file)}`);
11110
11107
  ui.info(`id=${frontmatter.id} type=attempt status=validated (auto-approved)`);
11111
11108
  if (sensor) ui.info(`sensor=regex warn autogen pattern=${JSON.stringify(sensor.pattern)}`);
@@ -11118,7 +11115,7 @@ function parseCsv4(value) {
11118
11115
 
11119
11116
  // src/commands/memory-seed.ts
11120
11117
  import { readFile as readFile14 } from "fs/promises";
11121
- import { existsSync as existsSync46 } from "fs";
11118
+ import { existsSync as existsSync45 } from "fs";
11122
11119
  import path28 from "path";
11123
11120
  import "commander";
11124
11121
  import {
@@ -11158,7 +11155,7 @@ function registerMemorySeed(memory2) {
11158
11155
  }
11159
11156
  return;
11160
11157
  }
11161
- if (!existsSync46(paths.haiveDir)) {
11158
+ if (!existsSync45(paths.haiveDir)) {
11162
11159
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
11163
11160
  process.exitCode = 1;
11164
11161
  return;
@@ -11214,7 +11211,7 @@ function registerMemorySeed(memory2) {
11214
11211
  }
11215
11212
 
11216
11213
  // src/commands/memory-pending.ts
11217
- import { existsSync as existsSync47 } from "fs";
11214
+ import { existsSync as existsSync46 } from "fs";
11218
11215
  import path29 from "path";
11219
11216
  import "commander";
11220
11217
  import {
@@ -11227,12 +11224,12 @@ function registerMemoryPending(memory2) {
11227
11224
  memory2.command("pending").description("List draft and proposed memories awaiting review (sorted by reads desc).\n\n draft = created but not yet activated \xB7 proposed = promoted, awaiting team validation").option("--scope <scope>", "filter by scope (personal | team | module)").option("-d, --dir <dir>", "project root").action(async (opts) => {
11228
11225
  const root = findProjectRoot24(opts.dir);
11229
11226
  const paths = resolveHaivePaths21(root);
11230
- if (!existsSync47(paths.memoriesDir)) {
11227
+ if (!existsSync46(paths.memoriesDir)) {
11231
11228
  ui.error(`No .ai/memories at ${root}.`);
11232
11229
  process.exitCode = 1;
11233
11230
  return;
11234
11231
  }
11235
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11232
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11236
11233
  const usage = await loadUsageIndex17(paths);
11237
11234
  const filterFn = ({ memory: mem }) => {
11238
11235
  if (mem.frontmatter.status !== "proposed" && mem.frontmatter.status !== "draft") return false;
@@ -11285,7 +11282,7 @@ function registerMemoryPending(memory2) {
11285
11282
  }
11286
11283
 
11287
11284
  // src/commands/memory-query.ts
11288
- import { existsSync as existsSync48 } from "fs";
11285
+ import { existsSync as existsSync47 } from "fs";
11289
11286
  import path30 from "path";
11290
11287
  import "commander";
11291
11288
  import {
@@ -11302,7 +11299,7 @@ function registerMemoryQuery(memory2) {
11302
11299
  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) => {
11303
11300
  const root = findProjectRoot25(opts.dir);
11304
11301
  const paths = resolveHaivePaths22(root);
11305
- if (!existsSync48(paths.memoriesDir)) {
11302
+ if (!existsSync47(paths.memoriesDir)) {
11306
11303
  ui.error(`No memories directory at ${paths.memoriesDir}. Run \`haive init\` first.`);
11307
11304
  process.exitCode = 1;
11308
11305
  return;
@@ -11313,7 +11310,7 @@ function registerMemoryQuery(memory2) {
11313
11310
  return;
11314
11311
  }
11315
11312
  const statusFilter = opts.status ? opts.status.split(",").map((s) => s.trim()) : null;
11316
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11313
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11317
11314
  const passesFilters2 = (mem) => {
11318
11315
  const fm = mem.frontmatter;
11319
11316
  if (opts.scope && fm.scope !== opts.scope) return false;
@@ -11360,8 +11357,8 @@ ${top.length} of ${matches.length} match${matches.length === 1 ? "" : "es"}`)
11360
11357
  }
11361
11358
 
11362
11359
  // src/commands/memory-reject.ts
11363
- import { writeFile as writeFile24 } from "fs/promises";
11364
- import { existsSync as existsSync49 } from "fs";
11360
+ import { writeFile as writeFile23 } from "fs/promises";
11361
+ import { existsSync as existsSync48 } from "fs";
11365
11362
  import "commander";
11366
11363
  import {
11367
11364
  findProjectRoot as findProjectRoot26,
@@ -11375,19 +11372,19 @@ function registerMemoryReject(memory2) {
11375
11372
  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) => {
11376
11373
  const root = findProjectRoot26(opts.dir);
11377
11374
  const paths = resolveHaivePaths23(root);
11378
- if (!existsSync49(paths.memoriesDir)) {
11375
+ if (!existsSync48(paths.memoriesDir)) {
11379
11376
  ui.error(`No .ai/memories at ${root}.`);
11380
11377
  process.exitCode = 1;
11381
11378
  return;
11382
11379
  }
11383
- const memories = await loadMemoriesFromDir28(paths.memoriesDir);
11380
+ const memories = await loadMemoriesFromDir27(paths.memoriesDir);
11384
11381
  const loaded = memories.find((m) => m.memory.frontmatter.id === id);
11385
11382
  if (!loaded) {
11386
11383
  ui.error(`No memory with id "${id}".`);
11387
11384
  process.exitCode = 1;
11388
11385
  return;
11389
11386
  }
11390
- await writeFile24(
11387
+ await writeFile23(
11391
11388
  loaded.filePath,
11392
11389
  serializeMemory20({
11393
11390
  frontmatter: {
@@ -11411,7 +11408,7 @@ function registerMemoryReject(memory2) {
11411
11408
  }
11412
11409
 
11413
11410
  // src/commands/memory-rm.ts
11414
- import { existsSync as existsSync50 } from "fs";
11411
+ import { existsSync as existsSync49 } from "fs";
11415
11412
  import { unlink as unlink3 } from "fs/promises";
11416
11413
  import path31 from "path";
11417
11414
  import { createInterface as createInterface2 } from "readline/promises";
@@ -11426,12 +11423,12 @@ function registerMemoryRm(memory2) {
11426
11423
  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) => {
11427
11424
  const root = findProjectRoot27(opts.dir);
11428
11425
  const paths = resolveHaivePaths24(root);
11429
- if (!existsSync50(paths.memoriesDir)) {
11426
+ if (!existsSync49(paths.memoriesDir)) {
11430
11427
  ui.error(`No .ai/memories at ${root}.`);
11431
11428
  process.exitCode = 1;
11432
11429
  return;
11433
11430
  }
11434
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11431
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11435
11432
  const found = all.find((m) => m.memory.frontmatter.id === id);
11436
11433
  if (!found) {
11437
11434
  ui.error(`No memory with id "${id}".`);
@@ -11462,7 +11459,7 @@ function registerMemoryRm(memory2) {
11462
11459
  }
11463
11460
 
11464
11461
  // src/commands/memory-show.ts
11465
- import { existsSync as existsSync51 } from "fs";
11462
+ import { existsSync as existsSync50 } from "fs";
11466
11463
  import { readFile as readFile15 } from "fs/promises";
11467
11464
  import path33 from "path";
11468
11465
  import "commander";
@@ -11477,12 +11474,12 @@ function registerMemoryShow(memory2) {
11477
11474
  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) => {
11478
11475
  const root = findProjectRoot28(opts.dir);
11479
11476
  const paths = resolveHaivePaths25(root);
11480
- if (!existsSync51(paths.memoriesDir)) {
11477
+ if (!existsSync50(paths.memoriesDir)) {
11481
11478
  ui.error(`No .ai/memories at ${root}.`);
11482
11479
  process.exitCode = 1;
11483
11480
  return;
11484
11481
  }
11485
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11482
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11486
11483
  const found = all.find((m) => m.memory.frontmatter.id === id);
11487
11484
  if (!found) {
11488
11485
  ui.error(`No memory with id "${id}".`);
@@ -11521,7 +11518,7 @@ function registerMemoryShow(memory2) {
11521
11518
  }
11522
11519
 
11523
11520
  // src/commands/memory-stats.ts
11524
- import { existsSync as existsSync53 } from "fs";
11521
+ import { existsSync as existsSync51 } from "fs";
11525
11522
  import path34 from "path";
11526
11523
  import "commander";
11527
11524
  import {
@@ -11535,12 +11532,12 @@ function registerMemoryStats(memory2) {
11535
11532
  memory2.command("stats").description("Show usage stats and confidence levels per memory").option("--id <id>", "show stats for a single memory id").option("-d, --dir <dir>", "project root").action(async (opts) => {
11536
11533
  const root = findProjectRoot29(opts.dir);
11537
11534
  const paths = resolveHaivePaths26(root);
11538
- if (!existsSync53(paths.memoriesDir)) {
11535
+ if (!existsSync51(paths.memoriesDir)) {
11539
11536
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
11540
11537
  process.exitCode = 1;
11541
11538
  return;
11542
11539
  }
11543
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11540
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11544
11541
  const usage = await loadUsageIndex21(paths);
11545
11542
  const target = opts.id ? all.filter((m) => m.memory.frontmatter.id === opts.id) : all;
11546
11543
  if (target.length === 0) {
@@ -11566,7 +11563,7 @@ function registerMemoryStats(memory2) {
11566
11563
  }
11567
11564
 
11568
11565
  // src/commands/memory-impact.ts
11569
- import { existsSync as existsSync54 } from "fs";
11566
+ import { existsSync as existsSync53 } from "fs";
11570
11567
  import "commander";
11571
11568
  import {
11572
11569
  compareImpact,
@@ -11583,12 +11580,12 @@ function registerMemoryImpact(memory2) {
11583
11580
  ).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) => {
11584
11581
  const root = findProjectRoot30(opts.dir);
11585
11582
  const paths = resolveHaivePaths27(root);
11586
- if (!existsSync54(paths.memoriesDir)) {
11583
+ if (!existsSync53(paths.memoriesDir)) {
11587
11584
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
11588
11585
  process.exitCode = 1;
11589
11586
  return;
11590
11587
  }
11591
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11588
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11592
11589
  const usageIndex = await loadUsageIndex23(paths);
11593
11590
  let rows = all.filter((m) => !opts.id || m.memory.frontmatter.id === opts.id).map(({ memory: mem }) => {
11594
11591
  const fm = mem.frontmatter;
@@ -11654,8 +11651,8 @@ function pad(value, width) {
11654
11651
  }
11655
11652
 
11656
11653
  // src/commands/memory-feedback.ts
11657
- import { existsSync as existsSync55 } from "fs";
11658
- import { writeFile as writeFile25 } from "fs/promises";
11654
+ import { existsSync as existsSync54 } from "fs";
11655
+ import { writeFile as writeFile24 } from "fs/promises";
11659
11656
  import "commander";
11660
11657
  import {
11661
11658
  applyFeedbackAdjustment as applyFeedbackAdjustment2,
@@ -11681,12 +11678,12 @@ function registerMemoryFeedback(memory2) {
11681
11678
  }
11682
11679
  const root = findProjectRoot31(opts.dir);
11683
11680
  const paths = resolveHaivePaths28(root);
11684
- if (!existsSync55(paths.memoriesDir)) {
11681
+ if (!existsSync54(paths.memoriesDir)) {
11685
11682
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
11686
11683
  process.exitCode = 1;
11687
11684
  return;
11688
11685
  }
11689
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11686
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11690
11687
  const target = all.find((m) => m.memory.frontmatter.id === id);
11691
11688
  if (!target) {
11692
11689
  ui.error(`No memory with id '${id}'.`);
@@ -11703,7 +11700,7 @@ function registerMemoryFeedback(memory2) {
11703
11700
  const adjustedFrontmatter = applyFeedbackAdjustment2(target.memory.frontmatter, adjustment);
11704
11701
  if (adjustedFrontmatter !== target.memory.frontmatter) {
11705
11702
  target.memory.frontmatter = adjustedFrontmatter;
11706
- await writeFile25(target.filePath, serializeMemory21(target.memory), "utf8");
11703
+ await writeFile24(target.filePath, serializeMemory21(target.memory), "utf8");
11707
11704
  }
11708
11705
  const impact = computeImpact4(target.memory.frontmatter, usage);
11709
11706
  if (opts.json) {
@@ -11721,8 +11718,8 @@ function registerMemoryFeedback(memory2) {
11721
11718
  }
11722
11719
 
11723
11720
  // src/commands/memory-verify.ts
11724
- import { writeFile as writeFile26 } from "fs/promises";
11725
- import { existsSync as existsSync56 } from "fs";
11721
+ import { writeFile as writeFile25 } from "fs/promises";
11722
+ import { existsSync as existsSync55 } from "fs";
11726
11723
  import path35 from "path";
11727
11724
  import "commander";
11728
11725
  import {
@@ -11737,7 +11734,7 @@ function registerMemoryVerify(memory2) {
11737
11734
  ).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) => {
11738
11735
  const root = findProjectRoot32(opts.dir);
11739
11736
  const paths = resolveHaivePaths29(root);
11740
- if (!existsSync56(paths.memoriesDir)) {
11737
+ if (!existsSync55(paths.memoriesDir)) {
11741
11738
  if (opts.json) {
11742
11739
  console.log(JSON.stringify({ error: "not-initialized", root }, null, 2));
11743
11740
  } else {
@@ -11746,7 +11743,7 @@ function registerMemoryVerify(memory2) {
11746
11743
  process.exitCode = 1;
11747
11744
  return;
11748
11745
  }
11749
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
11746
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
11750
11747
  const targets = opts.id ? all.filter((m) => m.memory.frontmatter.id === opts.id) : all;
11751
11748
  if (opts.id && targets.length === 0) {
11752
11749
  if (opts.json) {
@@ -11795,7 +11792,7 @@ function registerMemoryVerify(memory2) {
11795
11792
  }
11796
11793
  if (opts.update) {
11797
11794
  const next = applyVerification2(mem, result);
11798
- await writeFile26(filePath, serializeMemory23(next), "utf8");
11795
+ await writeFile25(filePath, serializeMemory23(next), "utf8");
11799
11796
  updated++;
11800
11797
  }
11801
11798
  }
@@ -11858,7 +11855,7 @@ function applyVerification2(mem, result) {
11858
11855
 
11859
11856
  // src/commands/memory-import.ts
11860
11857
  import { readFile as readFile16 } from "fs/promises";
11861
- import { existsSync as existsSync57 } from "fs";
11858
+ import { existsSync as existsSync56 } from "fs";
11862
11859
  import "commander";
11863
11860
  import {
11864
11861
  findProjectRoot as findProjectRoot33,
@@ -11870,12 +11867,12 @@ function registerMemoryImport(memory2) {
11870
11867
  ).requiredOption("--from <file>", "Markdown/text file to import from").option("--scope <scope>", "personal | team (default: team)", "team").option("-d, --dir <dir>", "project root").action(async (opts) => {
11871
11868
  const root = findProjectRoot33(opts.dir);
11872
11869
  const paths = resolveHaivePaths30(root);
11873
- if (!existsSync57(paths.haiveDir)) {
11870
+ if (!existsSync56(paths.haiveDir)) {
11874
11871
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
11875
11872
  process.exitCode = 1;
11876
11873
  return;
11877
11874
  }
11878
- if (!existsSync57(opts.from)) {
11875
+ if (!existsSync56(opts.from)) {
11879
11876
  ui.error(`File not found: ${opts.from}`);
11880
11877
  process.exitCode = 1;
11881
11878
  return;
@@ -11908,8 +11905,8 @@ function registerMemoryImport(memory2) {
11908
11905
  }
11909
11906
 
11910
11907
  // src/commands/memory-import-changelog.ts
11911
- import { existsSync as existsSync58 } from "fs";
11912
- import { readFile as readFile17, mkdir as mkdir15, writeFile as writeFile27 } from "fs/promises";
11908
+ import { existsSync as existsSync57 } from "fs";
11909
+ import { readFile as readFile17, mkdir as mkdir15, writeFile as writeFile26 } from "fs/promises";
11913
11910
  import path36 from "path";
11914
11911
  import "commander";
11915
11912
  import {
@@ -11983,7 +11980,7 @@ function registerMemoryImportChangelog(memory2) {
11983
11980
  const root = findProjectRoot34(opts.dir);
11984
11981
  const paths = resolveHaivePaths31(root);
11985
11982
  const changelogPath = path36.resolve(root, opts.fromChangelog);
11986
- if (!existsSync58(changelogPath)) {
11983
+ if (!existsSync57(changelogPath)) {
11987
11984
  ui.error(`CHANGELOG not found: ${changelogPath}`);
11988
11985
  process.exitCode = 1;
11989
11986
  return;
@@ -12046,7 +12043,7 @@ function registerMemoryImportChangelog(memory2) {
12046
12043
  paths: [path36.relative(root, changelogPath)],
12047
12044
  topic: `changelog-${pkgName}-${entry.version}`
12048
12045
  });
12049
- await writeFile27(
12046
+ await writeFile26(
12050
12047
  path36.join(teamDir, `${fm.id}.md`),
12051
12048
  serializeMemory24({ frontmatter: fm, body: lines.join("\n") }),
12052
12049
  "utf8"
@@ -12070,15 +12067,15 @@ ${ui.bold(`Imported ${saved} changelog entr${saved === 1 ? "y" : "ies"} from ${p
12070
12067
  }
12071
12068
 
12072
12069
  // src/commands/memory-digest.ts
12073
- import { existsSync as existsSync59 } from "fs";
12074
- import { writeFile as writeFile28 } from "fs/promises";
12070
+ import { existsSync as existsSync58 } from "fs";
12071
+ import { writeFile as writeFile27 } from "fs/promises";
12075
12072
  import path37 from "path";
12076
12073
  import "commander";
12077
12074
  import {
12078
12075
  deriveConfidence as deriveConfidence12,
12079
12076
  findProjectRoot as findProjectRoot35,
12080
12077
  getUsage as getUsage20,
12081
- loadMemoriesFromDir as loadMemoriesFromDir29,
12078
+ loadMemoriesFromDir as loadMemoriesFromDir28,
12082
12079
  loadUsageIndex as loadUsageIndex25,
12083
12080
  resolveHaivePaths as resolveHaivePaths32
12084
12081
  } from "@hiveai/core";
@@ -12095,7 +12092,7 @@ function registerMemoryDigest(program2) {
12095
12092
  ).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) => {
12096
12093
  const root = findProjectRoot35(opts.dir);
12097
12094
  const paths = resolveHaivePaths32(root);
12098
- if (!existsSync59(paths.memoriesDir)) {
12095
+ if (!existsSync58(paths.memoriesDir)) {
12099
12096
  ui.error("No .ai/memories found. Run `haive init` first.");
12100
12097
  process.exitCode = 1;
12101
12098
  return;
@@ -12103,7 +12100,7 @@ function registerMemoryDigest(program2) {
12103
12100
  const days = Math.max(1, Number(opts.days ?? 7));
12104
12101
  const scopeFilter = opts.scope ?? "team";
12105
12102
  const cutoff = new Date(Date.now() - days * 24 * 60 * 60 * 1e3);
12106
- const all = await loadMemoriesFromDir29(paths.memoriesDir);
12103
+ const all = await loadMemoriesFromDir28(paths.memoriesDir);
12107
12104
  const usage = await loadUsageIndex25(paths);
12108
12105
  const recent = all.filter(({ memory: mem }) => {
12109
12106
  const fm = mem.frontmatter;
@@ -12168,7 +12165,7 @@ function registerMemoryDigest(program2) {
12168
12165
  const digest = lines.join("\n");
12169
12166
  if (opts.out) {
12170
12167
  const outPath = path37.resolve(process.cwd(), opts.out);
12171
- await writeFile28(outPath, digest, "utf8");
12168
+ await writeFile27(outPath, digest, "utf8");
12172
12169
  ui.success(`Digest written to ${opts.out} (${recent.length} memor${recent.length === 1 ? "y" : "ies"})`);
12173
12170
  } else {
12174
12171
  console.log(digest);
@@ -12177,15 +12174,15 @@ function registerMemoryDigest(program2) {
12177
12174
  }
12178
12175
 
12179
12176
  // src/commands/session-end.ts
12180
- import { writeFile as writeFile29, mkdir as mkdir16, readFile as readFile18, rm as rm2 } from "fs/promises";
12181
- import { existsSync as existsSync60 } from "fs";
12177
+ import { writeFile as writeFile28, mkdir as mkdir16, readFile as readFile18, rm as rm2 } from "fs/promises";
12178
+ import { existsSync as existsSync59 } from "fs";
12182
12179
  import { spawn as spawn4 } from "child_process";
12183
12180
  import path38 from "path";
12184
12181
  import "commander";
12185
12182
  import {
12186
12183
  buildFrontmatter as buildFrontmatter10,
12187
12184
  findProjectRoot as findProjectRoot36,
12188
- loadMemoriesFromDir as loadMemoriesFromDir30,
12185
+ loadMemoriesFromDir as loadMemoriesFromDir29,
12189
12186
  loadPreventionEvents as loadPreventionEvents2,
12190
12187
  loadUsageIndex as loadUsageIndex26,
12191
12188
  memoryFilePath as memoryFilePath10,
@@ -12196,7 +12193,7 @@ import {
12196
12193
  } from "@hiveai/core";
12197
12194
  async function buildAutoRecap(paths) {
12198
12195
  const obsFile = path38.join(paths.haiveDir, ".cache", "observations.jsonl");
12199
- if (!existsSync60(obsFile)) return await buildGitAutoRecap(paths);
12196
+ if (!existsSync59(obsFile)) return await buildGitAutoRecap(paths);
12200
12197
  const raw = await readFile18(obsFile, "utf8").catch(() => "");
12201
12198
  if (!raw.trim()) return await buildGitAutoRecap(paths);
12202
12199
  const lines = raw.split("\n").filter(Boolean);
@@ -12365,7 +12362,7 @@ function runGit(cwd, args) {
12365
12362
  }
12366
12363
  async function observationStart(paths) {
12367
12364
  const obsFile = path38.join(paths.haiveDir, ".cache", "observations.jsonl");
12368
- if (!existsSync60(obsFile)) return null;
12365
+ if (!existsSync59(obsFile)) return null;
12369
12366
  const raw = await readFile18(obsFile, "utf8").catch(() => "");
12370
12367
  let first = null;
12371
12368
  for (const line of raw.split("\n")) {
@@ -12381,7 +12378,7 @@ async function observationStart(paths) {
12381
12378
  }
12382
12379
  async function printCaughtForYou(paths, since, quiet) {
12383
12380
  if (quiet) return;
12384
- const memories = existsSync60(paths.memoriesDir) ? await loadMemoriesFromDir30(paths.memoriesDir) : [];
12381
+ const memories = existsSync59(paths.memoriesDir) ? await loadMemoriesFromDir29(paths.memoriesDir) : [];
12385
12382
  const usage = await loadUsageIndex26(paths);
12386
12383
  const events = await loadPreventionEvents2(paths);
12387
12384
  const summary = summarizeCaughtForYou(events, memories, usage, {
@@ -12419,7 +12416,7 @@ function registerSessionEnd(session2) {
12419
12416
  ).option("--goal <text>", "what you were trying to accomplish (1\u20132 sentences)").option("--accomplished <text>", "what was actually done (bullet list recommended)").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) => {
12420
12417
  const root = findProjectRoot36(opts.dir);
12421
12418
  const paths = resolveHaivePaths33(root);
12422
- if (!existsSync60(paths.haiveDir)) {
12419
+ if (!existsSync59(paths.haiveDir)) {
12423
12420
  if (opts.auto || opts.quiet) return;
12424
12421
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
12425
12422
  process.exitCode = 1;
@@ -12453,7 +12450,7 @@ function registerSessionEnd(session2) {
12453
12450
  });
12454
12451
  const topic = recapTopic2(scope, opts.module);
12455
12452
  const filesTouched = parseCsv5(resolvedFiles).map((p) => normalizeAnchorPath(root, p));
12456
- const missingPaths = filesTouched.filter((p) => !existsSync60(path38.resolve(root, p)));
12453
+ const missingPaths = filesTouched.filter((p) => !existsSync59(path38.resolve(root, p)));
12457
12454
  if (missingPaths.length > 0 && !opts.quiet) {
12458
12455
  ui.warn(`Anchor path${missingPaths.length > 1 ? "s" : ""} not found in project (will be stale):`);
12459
12456
  for (const p of missingPaths) ui.warn(` \u2717 ${p}`);
@@ -12461,11 +12458,11 @@ function registerSessionEnd(session2) {
12461
12458
  const cleanupObservations = async () => {
12462
12459
  if (!opts.auto) return;
12463
12460
  const obsFile = path38.join(paths.haiveDir, ".cache", "observations.jsonl");
12464
- if (existsSync60(obsFile)) await rm2(obsFile).catch(() => {
12461
+ if (existsSync59(obsFile)) await rm2(obsFile).catch(() => {
12465
12462
  });
12466
12463
  };
12467
- if (existsSync60(paths.memoriesDir)) {
12468
- const existing = await loadMemoriesFromDir30(paths.memoriesDir);
12464
+ if (existsSync59(paths.memoriesDir)) {
12465
+ const existing = await loadMemoriesFromDir29(paths.memoriesDir);
12469
12466
  const topicMatch = existing.find(
12470
12467
  ({ memory: memory2 }) => memory2.frontmatter.topic === topic && memory2.frontmatter.scope === scope && (!opts.module || memory2.frontmatter.module === opts.module)
12471
12468
  );
@@ -12481,7 +12478,7 @@ function registerSessionEnd(session2) {
12481
12478
  paths: filesTouched.length ? filesTouched : fm.anchor.paths
12482
12479
  }
12483
12480
  };
12484
- await writeFile29(topicMatch.filePath, serializeMemory25({ frontmatter: newFrontmatter, body }), "utf8");
12481
+ await writeFile28(topicMatch.filePath, serializeMemory25({ frontmatter: newFrontmatter, body }), "utf8");
12485
12482
  await cleanupObservations();
12486
12483
  if (!opts.quiet) {
12487
12484
  ui.success(`Session recap updated (revision #${revisionCount})`);
@@ -12504,7 +12501,7 @@ function registerSessionEnd(session2) {
12504
12501
  });
12505
12502
  const file = memoryFilePath10(paths, frontmatter.scope, frontmatter.id, frontmatter.module);
12506
12503
  await mkdir16(path38.dirname(file), { recursive: true });
12507
- await writeFile29(file, serializeMemory25({ frontmatter, body }), "utf8");
12504
+ await writeFile28(file, serializeMemory25({ frontmatter, body }), "utf8");
12508
12505
  await cleanupObservations();
12509
12506
  if (!opts.quiet) {
12510
12507
  ui.success(`Session recap created`);
@@ -12528,7 +12525,7 @@ function normalizeAnchorPath(root, filePath) {
12528
12525
  }
12529
12526
 
12530
12527
  // src/commands/snapshot.ts
12531
- import { existsSync as existsSync61 } from "fs";
12528
+ import { existsSync as existsSync60 } from "fs";
12532
12529
  import { readdir as readdir4 } from "fs/promises";
12533
12530
  import path39 from "path";
12534
12531
  import "commander";
@@ -12563,14 +12560,14 @@ function registerSnapshot(program2) {
12563
12560
  ).option("--diff", "compare the contract against its stored snapshot").option("--list", "list all stored contract snapshots").option("-d, --dir <dir>", "project root").action(async (opts) => {
12564
12561
  const root = findProjectRoot37(opts.dir);
12565
12562
  const paths = resolveHaivePaths34(root);
12566
- if (!existsSync61(paths.haiveDir)) {
12563
+ if (!existsSync60(paths.haiveDir)) {
12567
12564
  ui.error("No .ai/ found. Run `haive init` first.");
12568
12565
  process.exitCode = 1;
12569
12566
  return;
12570
12567
  }
12571
12568
  if (opts.list) {
12572
12569
  const contractsDir = path39.join(paths.haiveDir, "contracts");
12573
- if (!existsSync61(contractsDir)) {
12570
+ if (!existsSync60(contractsDir)) {
12574
12571
  console.log(ui.dim("No contract snapshots found."));
12575
12572
  return;
12576
12573
  }
@@ -12694,15 +12691,15 @@ function detectFormat(filePath) {
12694
12691
  }
12695
12692
 
12696
12693
  // src/commands/hub.ts
12697
- import { existsSync as existsSync63 } from "fs";
12698
- import { mkdir as mkdir17, readFile as readFile19, writeFile as writeFile30, copyFile } from "fs/promises";
12694
+ import { existsSync as existsSync61 } from "fs";
12695
+ import { mkdir as mkdir17, readFile as readFile19, writeFile as writeFile29, copyFile } from "fs/promises";
12699
12696
  import path40 from "path";
12700
12697
  import { spawnSync as spawnSync5 } from "child_process";
12701
12698
  import "commander";
12702
12699
  import {
12703
12700
  findProjectRoot as findProjectRoot38,
12704
12701
  loadConfig as loadConfig8,
12705
- loadMemoriesFromDir as loadMemoriesFromDir31,
12702
+ loadMemoriesFromDir as loadMemoriesFromDir30,
12706
12703
  resolveHaivePaths as resolveHaivePaths35,
12707
12704
  saveConfig as saveConfig3,
12708
12705
  serializeMemory as serializeMemory26
@@ -12728,7 +12725,7 @@ function registerHub(program2) {
12728
12725
  }
12729
12726
  const sharedDir = path40.join(absPath, ".ai", "memories", "shared");
12730
12727
  await mkdir17(sharedDir, { recursive: true });
12731
- await writeFile30(
12728
+ await writeFile29(
12732
12729
  path40.join(absPath, ".ai", "README.md"),
12733
12730
  `# hAIve Team Knowledge Hub
12734
12731
 
@@ -12750,7 +12747,7 @@ haive hub pull # import into a project
12750
12747
  `,
12751
12748
  "utf8"
12752
12749
  );
12753
- await writeFile30(
12750
+ await writeFile29(
12754
12751
  path40.join(absPath, ".gitignore"),
12755
12752
  ".ai/.cache/\n.ai/memories/personal/\n",
12756
12753
  "utf8"
@@ -12796,7 +12793,7 @@ Next steps:
12796
12793
  return;
12797
12794
  }
12798
12795
  const hubRoot = path40.resolve(root, config.hubPath);
12799
- if (!existsSync63(hubRoot)) {
12796
+ if (!existsSync61(hubRoot)) {
12800
12797
  ui.error(`Hub not found at ${hubRoot}. Run \`haive hub init ${config.hubPath}\` first.`);
12801
12798
  process.exitCode = 1;
12802
12799
  return;
@@ -12804,7 +12801,7 @@ Next steps:
12804
12801
  const projectName = path40.basename(root);
12805
12802
  const destDir = path40.join(hubRoot, ".ai", "memories", "shared", projectName);
12806
12803
  await mkdir17(destDir, { recursive: true });
12807
- const all = await loadMemoriesFromDir31(paths.memoriesDir);
12804
+ const all = await loadMemoriesFromDir30(paths.memoriesDir);
12808
12805
  const shared = all.filter(
12809
12806
  ({ memory: memory2 }) => memory2.frontmatter.scope === "shared" && memory2.frontmatter.status !== "rejected" && memory2.frontmatter.status !== "deprecated" && // Don't push imported memories (avoid echo loops)
12810
12807
  !memory2.frontmatter.tags.some((t) => t.startsWith("cross-repo:"))
@@ -12822,7 +12819,7 @@ Next steps:
12822
12819
  const fm = memory2.frontmatter;
12823
12820
  const fileName = `${fm.id}.md`;
12824
12821
  const destPath = path40.join(destDir, fileName);
12825
- await writeFile30(destPath, serializeMemory26(memory2), "utf8");
12822
+ await writeFile29(destPath, serializeMemory26(memory2), "utf8");
12826
12823
  pushed++;
12827
12824
  }
12828
12825
  console.log(ui.green(`\u2713 Pushed ${pushed} shared memor${pushed === 1 ? "y" : "ies"} to hub`));
@@ -12866,7 +12863,7 @@ Next steps:
12866
12863
  }
12867
12864
  const hubRoot = path40.resolve(root, config.hubPath);
12868
12865
  const hubSharedDir = path40.join(hubRoot, ".ai", "memories", "shared");
12869
- if (!existsSync63(hubSharedDir)) {
12866
+ if (!existsSync61(hubSharedDir)) {
12870
12867
  ui.warn("Hub has no shared memories yet. Run `haive hub push` from other projects first.");
12871
12868
  return;
12872
12869
  }
@@ -12921,7 +12918,7 @@ Next steps:
12921
12918
  ` hubPath: ${config.hubPath ? ui.green(config.hubPath) : ui.dim("not configured")}`
12922
12919
  );
12923
12920
  const sharedDir = path40.join(paths.memoriesDir, "shared");
12924
- if (existsSync63(sharedDir)) {
12921
+ if (existsSync61(sharedDir)) {
12925
12922
  const { readdir: readdir7 } = await import("fs/promises");
12926
12923
  const sources = (await readdir7(sharedDir, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);
12927
12924
  console.log(`
@@ -12933,7 +12930,7 @@ Next steps:
12933
12930
  } else {
12934
12931
  console.log(ui.dim(" No imported shared memories yet."));
12935
12932
  }
12936
- const all = await loadMemoriesFromDir31(paths.memoriesDir);
12933
+ const all = await loadMemoriesFromDir30(paths.memoriesDir);
12937
12934
  const outgoing = all.filter(
12938
12935
  ({ memory: memory2 }) => memory2.frontmatter.scope === "shared" && !memory2.frontmatter.tags.some((t) => t.startsWith("cross-repo:"))
12939
12936
  );
@@ -12943,20 +12940,20 @@ Next steps:
12943
12940
  console.log(ui.dim(" Run `haive hub push` to publish them to the hub."));
12944
12941
  }
12945
12942
  void readFile19;
12946
- void writeFile30;
12943
+ void writeFile29;
12947
12944
  void saveConfig3;
12948
12945
  });
12949
12946
  }
12950
12947
 
12951
12948
  // src/commands/stats.ts
12952
12949
  import "commander";
12953
- import { existsSync as existsSync64 } from "fs";
12954
- import { mkdir as mkdir18, writeFile as writeFile31 } from "fs/promises";
12950
+ import { existsSync as existsSync63 } from "fs";
12951
+ import { mkdir as mkdir18, writeFile as writeFile30 } from "fs/promises";
12955
12952
  import path41 from "path";
12956
12953
  import {
12957
12954
  aggregateUsage,
12958
12955
  findProjectRoot as findProjectRoot39,
12959
- loadMemoriesFromDir as loadMemoriesFromDir33,
12956
+ loadMemoriesFromDir as loadMemoriesFromDir31,
12960
12957
  loadUsageIndex as loadUsageIndex27,
12961
12958
  parseSince,
12962
12959
  readUsageEvents as readUsageEvents2,
@@ -13028,8 +13025,8 @@ async function writeRoiReport(paths, root, sinceRaw, outRelative) {
13028
13025
  const size = await usageLogSize(paths);
13029
13026
  let events = await readUsageEvents2(paths);
13030
13027
  let memoryCount = { team: 0, personal: 0, total_skipped_session: 0 };
13031
- if (existsSync64(paths.memoriesDir)) {
13032
- const mems = await loadMemoriesFromDir33(paths.memoriesDir);
13028
+ if (existsSync63(paths.memoriesDir)) {
13029
+ const mems = await loadMemoriesFromDir31(paths.memoriesDir);
13033
13030
  for (const { memory: memory2 } of mems) {
13034
13031
  const fm = memory2.frontmatter;
13035
13032
  if (fm.type === "session_recap") memoryCount.total_skipped_session++;
@@ -13071,7 +13068,7 @@ async function writeRoiReport(paths, root, sinceRaw, outRelative) {
13071
13068
  top_memory_reads: memoryHitsLeader,
13072
13069
  roi_hints: roiHints
13073
13070
  };
13074
- await writeFile31(outAbs, JSON.stringify(payload, null, 2), "utf8");
13071
+ await writeFile30(outAbs, JSON.stringify(payload, null, 2), "utf8");
13075
13072
  ui.success(`Wrote ROI / usage rollup \u2192 ${outAbs}`);
13076
13073
  }
13077
13074
  async function renderMemoryHits(paths, opts) {
@@ -13248,8 +13245,8 @@ function summarize(name, t0, payload, notes) {
13248
13245
  }
13249
13246
 
13250
13247
  // src/commands/benchmark.ts
13251
- import { existsSync as existsSync65 } from "fs";
13252
- import { readdir as readdir5, readFile as readFile20, writeFile as writeFile33 } from "fs/promises";
13248
+ import { existsSync as existsSync64 } from "fs";
13249
+ import { readdir as readdir5, readFile as readFile20, writeFile as writeFile31 } from "fs/promises";
13253
13250
  import path43 from "path";
13254
13251
  import "commander";
13255
13252
  import { estimateTokens as estimateTokens4, findProjectRoot as findProjectRoot41 } from "@hiveai/core";
@@ -13266,7 +13263,7 @@ function registerBenchmark(program2) {
13266
13263
  const markdown = renderMarkdown(root, summary, rows);
13267
13264
  if (opts.out) {
13268
13265
  const outFile = path43.isAbsolute(opts.out) ? opts.out : path43.join(root, opts.out);
13269
- await writeFile33(outFile, markdown, "utf8");
13266
+ await writeFile31(outFile, markdown, "utf8");
13270
13267
  ui.success(`wrote ${path43.relative(process.cwd(), outFile)}`);
13271
13268
  return;
13272
13269
  }
@@ -13296,14 +13293,14 @@ function resolveBenchmarkRoot(dir) {
13296
13293
  return path43.join(projectRoot, candidate);
13297
13294
  }
13298
13295
  async function collectRows(root) {
13299
- if (!existsSync65(root)) throw new Error(`Benchmark directory not found: ${root}`);
13296
+ if (!existsSync64(root)) throw new Error(`Benchmark directory not found: ${root}`);
13300
13297
  const entries = await readdir5(root, { withFileTypes: true });
13301
13298
  const rows = [];
13302
13299
  for (const entry of entries) {
13303
13300
  if (!entry.isDirectory()) continue;
13304
13301
  const fixtureDir = path43.join(root, entry.name);
13305
13302
  const reportFile = path43.join(fixtureDir, "BENCHMARK_AGENT_REPORT.md");
13306
- if (!existsSync65(reportFile)) continue;
13303
+ if (!existsSync64(reportFile)) continue;
13307
13304
  const report = await readFile20(reportFile, "utf8");
13308
13305
  rows.push(parseAgentReport(entry.name, report));
13309
13306
  }
@@ -13393,8 +13390,8 @@ function escapeRegExp(value) {
13393
13390
  }
13394
13391
 
13395
13392
  // src/commands/eval.ts
13396
- import { mkdir as mkdir19, readFile as readFile21, writeFile as writeFile34 } from "fs/promises";
13397
- import { existsSync as existsSync66 } from "fs";
13393
+ import { mkdir as mkdir19, readFile as readFile21, writeFile as writeFile33 } from "fs/promises";
13394
+ import { existsSync as existsSync65 } from "fs";
13398
13395
  import path44 from "path";
13399
13396
  import "commander";
13400
13397
  import {
@@ -13422,7 +13419,7 @@ function registerEval(program2) {
13422
13419
  ).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) => {
13423
13420
  const root = findProjectRoot42(opts.dir);
13424
13421
  const paths = resolveHaivePaths38(root);
13425
- if (!existsSync66(paths.memoriesDir)) {
13422
+ if (!existsSync65(paths.memoriesDir)) {
13426
13423
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
13427
13424
  process.exitCode = 1;
13428
13425
  return;
@@ -13501,13 +13498,13 @@ function registerEval(program2) {
13501
13498
  gate_precision: gatePrecision
13502
13499
  };
13503
13500
  await mkdir19(path44.dirname(baselineFile), { recursive: true });
13504
- await writeFile34(baselineFile, JSON.stringify(snapshot, null, 2), "utf8");
13501
+ await writeFile33(baselineFile, JSON.stringify(snapshot, null, 2), "utf8");
13505
13502
  if (!opts.json) ui.success(`Saved baseline (score ${report.score}/100) \u2192 ${path44.relative(root, baselineFile)}`);
13506
13503
  }
13507
13504
  let delta = null;
13508
13505
  let gateDelta = null;
13509
13506
  if (opts.compare || opts.regressionGate) {
13510
- if (!existsSync66(baselineFile)) {
13507
+ if (!existsSync65(baselineFile)) {
13511
13508
  if (opts.regressionGate) {
13512
13509
  if (!opts.json) ui.info(`No baseline at ${path44.relative(root, baselineFile)} \u2014 regression gate skipped. Run \`haive eval --baseline\` to enable it.`);
13513
13510
  } else {
@@ -13545,7 +13542,7 @@ function registerEval(program2) {
13545
13542
  const md = renderMarkdown2(root, k, resolvedSpec.source, report, gatePrecision);
13546
13543
  if (opts.out) {
13547
13544
  const outFile = path44.isAbsolute(opts.out) ? opts.out : path44.join(root, opts.out);
13548
- await writeFile34(outFile, md, "utf8");
13545
+ await writeFile33(outFile, md, "utf8");
13549
13546
  ui.success(`wrote ${path44.relative(process.cwd(), outFile)}`);
13550
13547
  } else {
13551
13548
  console.log(md);
@@ -13632,10 +13629,10 @@ async function resolveSpec(opts, root, memoriesDir) {
13632
13629
  return { spec: JSON.parse(raw), source: file };
13633
13630
  }
13634
13631
  const defaultSpec = path44.join(root, ".ai", "eval", "spec.json");
13635
- if (existsSync66(defaultSpec)) {
13632
+ if (existsSync65(defaultSpec)) {
13636
13633
  const raw = await readFile21(defaultSpec, "utf8");
13637
13634
  const explicit = JSON.parse(raw);
13638
- const memories2 = await loadMemoriesFromDir28(memoriesDir);
13635
+ const memories2 = await loadMemoriesFromDir27(memoriesDir);
13639
13636
  const synthesized = synthesizeSelfEvalCases(memories2, { includeFiles: !opts.semanticOnly });
13640
13637
  return {
13641
13638
  spec: {
@@ -13645,7 +13642,7 @@ async function resolveSpec(opts, root, memoriesDir) {
13645
13642
  source: ".ai/eval/spec.json + synthesized anchored retrieval"
13646
13643
  };
13647
13644
  }
13648
- const memories = await loadMemoriesFromDir28(memoriesDir);
13645
+ const memories = await loadMemoriesFromDir27(memoriesDir);
13649
13646
  return {
13650
13647
  spec: { retrieval: synthesizeSelfEvalCases(memories, { includeFiles: !opts.semanticOnly }) },
13651
13648
  source: "synthesized anchored retrieval"
@@ -13743,8 +13740,8 @@ function renderMarkdown2(root, k, source, report, gatePrecision) {
13743
13740
  }
13744
13741
 
13745
13742
  // src/commands/memory-suggest.ts
13746
- import { mkdir as mkdir20, writeFile as writeFile35 } from "fs/promises";
13747
- import { existsSync as existsSync67 } from "fs";
13743
+ import { mkdir as mkdir20, writeFile as writeFile34 } from "fs/promises";
13744
+ import { existsSync as existsSync66 } from "fs";
13748
13745
  import path45 from "path";
13749
13746
  import "commander";
13750
13747
  import {
@@ -13752,7 +13749,7 @@ import {
13752
13749
  buildFrontmatter as buildFrontmatter11,
13753
13750
  findProjectRoot as findProjectRoot43,
13754
13751
  loadConfig as loadConfig10,
13755
- loadMemoriesFromDir as loadMemoriesFromDir34,
13752
+ loadMemoriesFromDir as loadMemoriesFromDir33,
13756
13753
  memoryFilePath as memoryFilePath11,
13757
13754
  parseSince as parseSince2,
13758
13755
  readUsageEvents as readUsageEvents3,
@@ -13823,7 +13820,7 @@ function registerMemorySuggest(memory2) {
13823
13820
  }
13824
13821
  const created = [];
13825
13822
  const skipped = [];
13826
- const existing = existsSync67(paths.memoriesDir) ? await loadMemoriesFromDir34(paths.memoriesDir) : [];
13823
+ const existing = existsSync66(paths.memoriesDir) ? await loadMemoriesFromDir33(paths.memoriesDir) : [];
13827
13824
  for (const s of top) {
13828
13825
  const slug = slugify2(s.query);
13829
13826
  if (!slug) {
@@ -13847,11 +13844,11 @@ function registerMemorySuggest(memory2) {
13847
13844
  const body = renderTemplate(s, fm.id, status);
13848
13845
  const file = memoryFilePath11(paths, fm.scope, fm.id, fm.module);
13849
13846
  await mkdir20(path45.dirname(file), { recursive: true });
13850
- if (existsSync67(file)) {
13847
+ if (existsSync66(file)) {
13851
13848
  skipped.push({ query: s.query, reason: `file already exists at ${path45.relative(root, file)}` });
13852
13849
  continue;
13853
13850
  }
13854
- await writeFile35(file, serializeMemory27({ frontmatter: fm, body }), "utf8");
13851
+ await writeFile34(file, serializeMemory27({ frontmatter: fm, body }), "utf8");
13855
13852
  created.push({ id: fm.id, file: path45.relative(root, file), query: s.query });
13856
13853
  }
13857
13854
  if (opts.json) {
@@ -13950,8 +13947,8 @@ function truncate2(text, max) {
13950
13947
  }
13951
13948
 
13952
13949
  // src/commands/memory-archive.ts
13953
- import { existsSync as existsSync68 } from "fs";
13954
- import { writeFile as writeFile36 } from "fs/promises";
13950
+ import { existsSync as existsSync67 } from "fs";
13951
+ import { writeFile as writeFile35 } from "fs/promises";
13955
13952
  import path46 from "path";
13956
13953
  import "commander";
13957
13954
  import {
@@ -13959,7 +13956,7 @@ import {
13959
13956
  getUsage as getUsage21,
13960
13957
  retirementSignal as retirementSignal2,
13961
13958
  loadConfig as loadConfig11,
13962
- loadMemoriesFromDir as loadMemoriesFromDir35,
13959
+ loadMemoriesFromDir as loadMemoriesFromDir34,
13963
13960
  loadUsageIndex as loadUsageIndex29,
13964
13961
  resolveHaivePaths as resolveHaivePaths40,
13965
13962
  serializeMemory as serializeMemory28
@@ -13971,7 +13968,7 @@ function registerMemoryArchive(memory2) {
13971
13968
  ).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) => {
13972
13969
  const root = findProjectRoot44(opts.dir);
13973
13970
  const paths = resolveHaivePaths40(root);
13974
- if (!existsSync68(paths.memoriesDir)) {
13971
+ if (!existsSync67(paths.memoriesDir)) {
13975
13972
  ui.error(`No .ai/memories at ${root}. Run \`haive init\` first.`);
13976
13973
  process.exitCode = 1;
13977
13974
  return;
@@ -13985,7 +13982,7 @@ function registerMemoryArchive(memory2) {
13985
13982
  return;
13986
13983
  }
13987
13984
  const cutoff = Date.now() - minDays * MS_PER_DAY2;
13988
- const all = await loadMemoriesFromDir35(paths.memoriesDir);
13985
+ const all = await loadMemoriesFromDir34(paths.memoriesDir);
13989
13986
  const usage = await loadUsageIndex29(paths);
13990
13987
  const typeFilter = opts.type === "all" ? null : opts.type ?? "attempt";
13991
13988
  const candidates = [];
@@ -13996,7 +13993,7 @@ function registerMemoryArchive(memory2) {
13996
13993
  if (fm.status === "deprecated" || fm.status === "rejected") continue;
13997
13994
  const retired = retirementSignal2(fm, mem.body);
13998
13995
  const hasAnyAnchor = fm.anchor.paths.length + fm.anchor.symbols.length > 0;
13999
- const allPathsGone = fm.anchor.paths.length > 0 && fm.anchor.paths.every((p) => !existsSync68(path46.join(paths.root, p)));
13996
+ const allPathsGone = fm.anchor.paths.length > 0 && fm.anchor.paths.every((p) => !existsSync67(path46.join(paths.root, p)));
14000
13997
  const isAnchorless = !hasAnyAnchor;
14001
13998
  if (!retired.retired && !opts.unread && !isAnchorless && !allPathsGone) continue;
14002
13999
  const u = getUsage21(usage, fm.id);
@@ -14045,7 +14042,7 @@ function registerMemoryArchive(memory2) {
14045
14042
  if (!found) continue;
14046
14043
  const fm = { ...found.memory.frontmatter, status: "deprecated" };
14047
14044
  try {
14048
- await writeFile36(c.filePath, serializeMemory28({ frontmatter: fm, body: found.memory.body }), "utf8");
14045
+ await writeFile35(c.filePath, serializeMemory28({ frontmatter: fm, body: found.memory.body }), "utf8");
14049
14046
  archived++;
14050
14047
  } catch (err) {
14051
14048
  if (!opts.json) {
@@ -14071,8 +14068,8 @@ function parseDays(input) {
14071
14068
  }
14072
14069
 
14073
14070
  // src/commands/doctor.ts
14074
- import { existsSync as existsSync69, statSync as statSync2 } from "fs";
14075
- import { readFile as readFile23, stat, writeFile as writeFile37 } from "fs/promises";
14071
+ import { existsSync as existsSync68, statSync as statSync2 } from "fs";
14072
+ import { readFile as readFile23, stat, writeFile as writeFile36 } from "fs/promises";
14076
14073
  import path47 from "path";
14077
14074
  import { execFileSync, execSync as execSync3 } from "child_process";
14078
14075
  import "commander";
@@ -14083,7 +14080,7 @@ import {
14083
14080
  isStackPackSeed as isStackPackSeed2,
14084
14081
  loadCodeMap as loadCodeMap7,
14085
14082
  loadConfig as loadConfig12,
14086
- loadMemoriesFromDir as loadMemoriesFromDir36,
14083
+ loadMemoriesFromDir as loadMemoriesFromDir35,
14087
14084
  loadUsageIndex as loadUsageIndex30,
14088
14085
  readUsageEvents as readUsageEvents4,
14089
14086
  resolveHaivePaths as resolveHaivePaths41
@@ -14098,7 +14095,7 @@ function registerDoctor(program2) {
14098
14095
  const findings = [];
14099
14096
  const repairs = [];
14100
14097
  const config = await loadConfig12(paths);
14101
- if (!existsSync69(paths.haiveDir)) {
14098
+ if (!existsSync68(paths.haiveDir)) {
14102
14099
  findings.push({
14103
14100
  severity: "error",
14104
14101
  code: "not-initialized",
@@ -14119,7 +14116,7 @@ function registerDoctor(program2) {
14119
14116
  })
14120
14117
  );
14121
14118
  }
14122
- if (!existsSync69(paths.projectContext)) {
14119
+ if (!existsSync68(paths.projectContext)) {
14123
14120
  findings.push({
14124
14121
  severity: "warn",
14125
14122
  code: "no-project-context",
@@ -14148,7 +14145,7 @@ function registerDoctor(program2) {
14148
14145
  });
14149
14146
  }
14150
14147
  }
14151
- const memories = existsSync69(paths.memoriesDir) ? await loadMemoriesFromDir36(paths.memoriesDir) : [];
14148
+ const memories = existsSync68(paths.memoriesDir) ? await loadMemoriesFromDir35(paths.memoriesDir) : [];
14152
14149
  const now = Date.now();
14153
14150
  if (memories.length === 0) {
14154
14151
  findings.push({
@@ -14300,7 +14297,7 @@ function registerDoctor(program2) {
14300
14297
  if (config.enforcement?.requireBriefingFirst) {
14301
14298
  const claudeSettings = path47.join(root, ".claude", "settings.local.json");
14302
14299
  let hasClaudeEnforcement = false;
14303
- if (existsSync69(claudeSettings)) {
14300
+ if (existsSync68(claudeSettings)) {
14304
14301
  try {
14305
14302
  const { readFile: readFile28 } = await import("fs/promises");
14306
14303
  const raw = await readFile28(claudeSettings, "utf8");
@@ -14326,7 +14323,7 @@ function registerDoctor(program2) {
14326
14323
  fix: "Edit .ai/haive.config.json: set autoSessionEnd: true (or re-run `haive init` without --manual)."
14327
14324
  });
14328
14325
  }
14329
- findings.push(...await collectInstallFindings(root, "0.18.0"));
14326
+ findings.push(...await collectInstallFindings(root, "0.19.0"));
14330
14327
  findings.push(...await collectToolchainFindings(root));
14331
14328
  try {
14332
14329
  const legacyRaw = execSync3("haive-mcp --version", {
@@ -14334,7 +14331,7 @@ function registerDoctor(program2) {
14334
14331
  timeout: 3e3,
14335
14332
  stdio: ["ignore", "pipe", "ignore"]
14336
14333
  }).trim();
14337
- const cliVersion = "0.18.0";
14334
+ const cliVersion = "0.19.0";
14338
14335
  if (legacyRaw && legacyRaw !== cliVersion) {
14339
14336
  findings.push({
14340
14337
  severity: "warn",
@@ -14356,14 +14353,14 @@ npm uninstall -g @hiveai/mcp`
14356
14353
  ];
14357
14354
  const staleConfigs = [];
14358
14355
  for (const cfgPath of configPaths) {
14359
- if (!existsSync69(cfgPath)) continue;
14356
+ if (!existsSync68(cfgPath)) continue;
14360
14357
  try {
14361
14358
  const raw = await readFile23(cfgPath, "utf8");
14362
14359
  if (raw.includes('"haive-mcp"') || raw.includes("'haive-mcp'")) {
14363
14360
  staleConfigs.push(path47.relative(root, cfgPath));
14364
14361
  if (opts.fix && !opts.dryRun) {
14365
14362
  const updated = raw.replace(/"command"\s*:\s*"haive-mcp"/g, '"command": "haive"').replace(/"args"\s*:\s*\[\]/g, '"args": ["mcp", "--stdio"]');
14366
- await writeFile37(cfgPath, updated, "utf8");
14363
+ await writeFile36(cfgPath, updated, "utf8");
14367
14364
  }
14368
14365
  }
14369
14366
  } catch {
@@ -14652,7 +14649,7 @@ which -a haive`
14652
14649
  ];
14653
14650
  for (const rel of integrationFiles) {
14654
14651
  const file = path47.join(root, rel);
14655
- if (!existsSync69(file)) continue;
14652
+ if (!existsSync68(file)) continue;
14656
14653
  const text = await readFile23(file, "utf8").catch(() => "");
14657
14654
  for (const bin of extractAbsoluteHaiveBins(text)) {
14658
14655
  const version = versionForBinary(bin);
@@ -14700,7 +14697,7 @@ async function collectDistFreshnessFindings(root, expectedVersion) {
14700
14697
  const isHaiveWorkspace = (await readJson(path47.join(root, "package.json")))?.name === "haive-monorepo";
14701
14698
  if (!isHaiveWorkspace) return findings;
14702
14699
  const cliDist = path47.join(root, "packages/cli/dist/index.js");
14703
- if (!existsSync69(cliDist)) {
14700
+ if (!existsSync68(cliDist)) {
14704
14701
  findings.push({
14705
14702
  severity: "warn",
14706
14703
  code: "workspace-dist-missing",
@@ -14724,7 +14721,7 @@ async function collectDistFreshnessFindings(root, expectedVersion) {
14724
14721
  "packages/core/src/index.ts",
14725
14722
  "packages/mcp/src/server.ts",
14726
14723
  "packages/cli/src/index.ts"
14727
- ].map((rel) => path47.join(root, rel)).filter(existsSync69);
14724
+ ].map((rel) => path47.join(root, rel)).filter(existsSync68);
14728
14725
  if (sourceFiles.length > 0) {
14729
14726
  const distMtime = statSync2(cliDist).mtimeMs;
14730
14727
  const newestSource = Math.max(...sourceFiles.map((file) => statSync2(file).mtimeMs));
@@ -14813,7 +14810,7 @@ function collectGlobalHivemoduleFindings(expectedVersion) {
14813
14810
  }
14814
14811
  }
14815
14812
  async function readJson(file) {
14816
- if (!existsSync69(file)) return null;
14813
+ if (!existsSync68(file)) return null;
14817
14814
  try {
14818
14815
  return JSON.parse(await readFile23(file, "utf8"));
14819
14816
  } catch {
@@ -14884,11 +14881,11 @@ function extractAbsoluteHaiveBins(text) {
14884
14881
  }
14885
14882
 
14886
14883
  // src/commands/playback.ts
14887
- import { existsSync as existsSync70 } from "fs";
14884
+ import { existsSync as existsSync69 } from "fs";
14888
14885
  import "commander";
14889
14886
  import {
14890
14887
  findProjectRoot as findProjectRoot46,
14891
- loadMemoriesFromDir as loadMemoriesFromDir37,
14888
+ loadMemoriesFromDir as loadMemoriesFromDir36,
14892
14889
  parseSince as parseSince3,
14893
14890
  readUsageEvents as readUsageEvents5,
14894
14891
  resolveHaivePaths as resolveHaivePaths42
@@ -14914,7 +14911,7 @@ function registerPlayback(program2) {
14914
14911
  const filtered = cutoff > 0 ? events.filter((e) => Date.parse(e.at) >= cutoff) : events;
14915
14912
  const gapMs = Math.max(1, parseInt(opts.sessionGap ?? "30", 10)) * MS_PER_MINUTE;
14916
14913
  const sessions = bucketSessions(filtered, gapMs);
14917
- const all = existsSync70(paths.memoriesDir) ? await loadMemoriesFromDir37(paths.memoriesDir) : [];
14914
+ const all = existsSync69(paths.memoriesDir) ? await loadMemoriesFromDir36(paths.memoriesDir) : [];
14918
14915
  const memByCreatedAt = all.filter(({ memory: memory2 }) => memory2.frontmatter.type !== "session_recap").map(({ memory: memory2 }) => ({ id: memory2.frontmatter.id, at: Date.parse(memory2.frontmatter.created_at) })).sort((a, b) => a.at - b.at);
14919
14916
  const enriched = sessions.map((s, i) => {
14920
14917
  const startMs = Date.parse(s.start);
@@ -15156,11 +15153,11 @@ function runCommand3(cmd, args, cwd) {
15156
15153
  }
15157
15154
 
15158
15155
  // src/commands/welcome.ts
15159
- import { existsSync as existsSync71 } from "fs";
15156
+ import { existsSync as existsSync70 } from "fs";
15160
15157
  import "commander";
15161
15158
  import {
15162
15159
  findProjectRoot as findProjectRoot48,
15163
- loadMemoriesFromDir as loadMemoriesFromDir38,
15160
+ loadMemoriesFromDir as loadMemoriesFromDir37,
15164
15161
  resolveHaivePaths as resolveHaivePaths44
15165
15162
  } from "@hiveai/core";
15166
15163
  var TYPE_RANK = {
@@ -15178,12 +15175,12 @@ function registerWelcome(program2) {
15178
15175
  ).option("--limit <n>", "maximum memories listed", "20").option("-d, --dir <dir>", "project root").action(async (opts) => {
15179
15176
  const root = findProjectRoot48(opts.dir);
15180
15177
  const paths = resolveHaivePaths44(root);
15181
- if (!existsSync71(paths.memoriesDir)) {
15178
+ if (!existsSync70(paths.memoriesDir)) {
15182
15179
  ui.error(`No memories at ${paths.memoriesDir}. Run 'haive init' first.`);
15183
15180
  process.exitCode = 1;
15184
15181
  return;
15185
15182
  }
15186
- const all = await loadMemoriesFromDir38(paths.memoriesDir);
15183
+ const all = await loadMemoriesFromDir37(paths.memoriesDir);
15187
15184
  const team = all.filter(
15188
15185
  ({ memory: memory2 }) => memory2.frontmatter.scope === "team" && memory2.frontmatter.status !== "rejected" && memory2.frontmatter.status !== "deprecated" && memory2.frontmatter.status !== "stale" && memory2.frontmatter.type !== "session_recap"
15189
15186
  );
@@ -15269,7 +15266,7 @@ function registerResolveProject(program2) {
15269
15266
  }
15270
15267
 
15271
15268
  // src/commands/runtime-journal.ts
15272
- import { existsSync as existsSync73 } from "fs";
15269
+ import { existsSync as existsSync71 } from "fs";
15273
15270
  import path49 from "path";
15274
15271
  import "commander";
15275
15272
  import {
@@ -15295,7 +15292,7 @@ function registerRuntime(program2) {
15295
15292
  const root = path49.resolve(opts.dir ?? process.cwd());
15296
15293
  const paths = resolveHaivePaths45(findProjectRoot49(root));
15297
15294
  const limit = Math.min(500, Math.max(1, parseInt(opts.limit, 10) || 30));
15298
- if (!existsSync73(paths.haiveDir)) {
15295
+ if (!existsSync71(paths.haiveDir)) {
15299
15296
  ui.error("No .ai/ \u2014 run `haive init` first.");
15300
15297
  process.exitCode = 1;
15301
15298
  return;
@@ -15310,7 +15307,7 @@ function registerRuntime(program2) {
15310
15307
  }
15311
15308
 
15312
15309
  // src/commands/memory-timeline.ts
15313
- import { existsSync as existsSync74 } from "fs";
15310
+ import { existsSync as existsSync73 } from "fs";
15314
15311
  import path50 from "path";
15315
15312
  import "commander";
15316
15313
  import {
@@ -15329,13 +15326,13 @@ function registerMemoryTimeline(memory2) {
15329
15326
  }
15330
15327
  const root = path50.resolve(opts.dir ?? process.cwd());
15331
15328
  const paths = resolveHaivePaths46(findProjectRoot50(root));
15332
- if (!existsSync74(paths.memoriesDir)) {
15329
+ if (!existsSync73(paths.memoriesDir)) {
15333
15330
  ui.error("No memories \u2014 run `haive init`.");
15334
15331
  process.exitCode = 1;
15335
15332
  return;
15336
15333
  }
15337
15334
  const limit = Math.min(100, Math.max(1, parseInt(opts.limit, 10) || 30));
15338
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
15335
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
15339
15336
  const { entries, notice } = collectTimelineEntries2(all, {
15340
15337
  memoryId: opts.id,
15341
15338
  topic: opts.topic,
@@ -15347,7 +15344,7 @@ function registerMemoryTimeline(memory2) {
15347
15344
  }
15348
15345
 
15349
15346
  // src/commands/memory-conflict-candidates.ts
15350
- import { existsSync as existsSync75 } from "fs";
15347
+ import { existsSync as existsSync74 } from "fs";
15351
15348
  import path51 from "path";
15352
15349
  import "commander";
15353
15350
  import {
@@ -15372,7 +15369,7 @@ function registerMemoryConflictCandidates(memory2) {
15372
15369
  ).option("--min-jaccard <x>", "minimum Jaccard for lexical pairs", "0.45").option("--max-pairs <n>", "cap lexical pairs", "20").option("--max-scan <n>", "max memories scanned (lexical)", "500").option("--max-topic-pairs <n>", "cap topic/status pairs", "20").action(async (opts) => {
15373
15370
  const root = path51.resolve(opts.dir ?? process.cwd());
15374
15371
  const paths = resolveHaivePaths47(findProjectRoot51(root));
15375
- if (!existsSync75(paths.memoriesDir)) {
15372
+ if (!existsSync74(paths.memoriesDir)) {
15376
15373
  ui.error("No memories \u2014 run `haive init`.");
15377
15374
  process.exitCode = 1;
15378
15375
  return;
@@ -15382,7 +15379,7 @@ function registerMemoryConflictCandidates(memory2) {
15382
15379
  const maxPairs = Math.min(100, Math.max(1, parseInt(opts.maxPairs, 10) || 20));
15383
15380
  const maxScan = Math.min(2e3, Math.max(1, parseInt(opts.maxScan, 10) || 500));
15384
15381
  const maxTopicPairs = Math.min(100, Math.max(1, parseInt(opts.maxTopicPairs, 10) || 20));
15385
- const all = await loadMemoriesFromDir28(paths.memoriesDir);
15382
+ const all = await loadMemoriesFromDir27(paths.memoriesDir);
15386
15383
  const lexical = findLexicalConflictPairs2(all, {
15387
15384
  sinceDays,
15388
15385
  types: parseTypes(opts.types),
@@ -15408,8 +15405,8 @@ function registerMemoryConflictCandidates(memory2) {
15408
15405
 
15409
15406
  // src/commands/enforce.ts
15410
15407
  import { execFileSync as execFileSync2, spawn as spawn6 } from "child_process";
15411
- import { existsSync as existsSync76, statSync as statSync3 } from "fs";
15412
- import { chmod as chmod2, mkdir as mkdir21, readFile as readFile24, readdir as readdir6, rm as rm3, writeFile as writeFile38 } from "fs/promises";
15408
+ import { existsSync as existsSync75, statSync as statSync3 } from "fs";
15409
+ import { chmod as chmod2, mkdir as mkdir21, readFile as readFile24, readdir as readdir6, rm as rm3, writeFile as writeFile37 } from "fs/promises";
15413
15410
  import path53 from "path";
15414
15411
  import "commander";
15415
15412
  import {
@@ -15419,7 +15416,7 @@ import {
15419
15416
  hasRecentBriefingMarker as hasRecentBriefingMarker2,
15420
15417
  isFreshIsoDate,
15421
15418
  loadConfig as loadConfig14,
15422
- loadMemoriesFromDir as loadMemoriesFromDir39,
15419
+ loadMemoriesFromDir as loadMemoriesFromDir38,
15423
15420
  memoryMatchesAnchorPaths as memoryMatchesAnchorPaths6,
15424
15421
  readRecentBriefingMarker,
15425
15422
  resolveBriefingBudget as resolveBriefingBudget3,
@@ -15484,14 +15481,14 @@ function registerEnforce(program2) {
15484
15481
  const root = findProjectRoot52(opts.dir);
15485
15482
  const paths = resolveHaivePaths48(root);
15486
15483
  const cacheDir = path53.join(paths.haiveDir, ".cache");
15487
- if (existsSync76(cacheDir)) {
15484
+ if (existsSync75(cacheDir)) {
15488
15485
  if (opts.dryRun) ui.info(`would clean ${path53.relative(root, cacheDir)} (preserving .gitignore)`);
15489
15486
  else {
15490
15487
  const removed = await cleanupCacheDir(cacheDir);
15491
15488
  ui.success(`cleaned ${path53.relative(root, cacheDir)}${removed > 0 ? ` (${removed} item${removed === 1 ? "" : "s"} removed)` : ""}`);
15492
15489
  }
15493
15490
  }
15494
- if (existsSync76(paths.runtimeDir)) {
15491
+ if (existsSync75(paths.runtimeDir)) {
15495
15492
  if (opts.dryRun) ui.info(`would clean ${path53.relative(root, paths.runtimeDir)} (preserving briefing markers)`);
15496
15493
  else {
15497
15494
  const removed = await cleanupRuntimeDir(paths.runtimeDir);
@@ -15529,7 +15526,7 @@ function registerEnforce(program2) {
15529
15526
  const root = resolveRoot(opts.dir, payload);
15530
15527
  if (!root) return;
15531
15528
  const paths = resolveHaivePaths48(root);
15532
- if (!existsSync76(paths.haiveDir)) return;
15529
+ if (!existsSync75(paths.haiveDir)) return;
15533
15530
  await mkdir21(paths.runtimeDir, { recursive: true });
15534
15531
  const sessionId = opts.sessionId ?? payload.session_id;
15535
15532
  const task = opts.task ?? payload.prompt ?? "Start an AI coding session in this hAIve-initialized project.";
@@ -15592,7 +15589,7 @@ ${briefing.project_context.content.slice(0, 1800)}`);
15592
15589
  const root = resolveRoot(opts.dir, payload);
15593
15590
  if (!root) return;
15594
15591
  const paths = resolveHaivePaths48(root);
15595
- if (!existsSync76(paths.haiveDir)) return;
15592
+ if (!existsSync75(paths.haiveDir)) return;
15596
15593
  if (!isWriteLikeTool(payload)) return;
15597
15594
  const config = await loadConfig14(paths);
15598
15595
  if (config.enforcement?.requireBriefingFirst === false) return;
@@ -15657,7 +15654,7 @@ function emitPreToolUseContext(text) {
15657
15654
  async function buildFinishReport(dir) {
15658
15655
  const root = findProjectRoot52(dir);
15659
15656
  const paths = resolveHaivePaths48(root);
15660
- const initialized = existsSync76(paths.haiveDir);
15657
+ const initialized = existsSync75(paths.haiveDir);
15661
15658
  const config = initialized ? await loadConfig14(paths) : {};
15662
15659
  const mode = config.enforcement?.mode ?? "strict";
15663
15660
  const findings = [];
@@ -15849,7 +15846,7 @@ async function checkFailureCapture(paths, config) {
15849
15846
  const gate = config.enforcement?.failureCaptureGate ?? "warn";
15850
15847
  if (gate === "off") return [];
15851
15848
  const obsFile = path53.join(paths.haiveDir, ".cache", "observations.jsonl");
15852
- if (!existsSync76(obsFile)) return [];
15849
+ if (!existsSync75(obsFile)) return [];
15853
15850
  const failures = [];
15854
15851
  try {
15855
15852
  const raw = await readFile24(obsFile, "utf8");
@@ -15866,7 +15863,7 @@ async function checkFailureCapture(paths, config) {
15866
15863
  return [];
15867
15864
  }
15868
15865
  if (failures.length === 0) return [];
15869
- const memories = existsSync76(paths.memoriesDir) ? await loadMemoriesFromDir39(paths.memoriesDir) : [];
15866
+ const memories = existsSync75(paths.memoriesDir) ? await loadMemoriesFromDir38(paths.memoriesDir) : [];
15870
15867
  const captureTimes = memories.filter(({ memory: memory2 }) => ["attempt", "gotcha"].includes(memory2.frontmatter.type)).map(({ memory: memory2 }) => memory2.frontmatter.created_at);
15871
15868
  const uncaptured = findUncapturedFailures(failures, captureTimes);
15872
15869
  if (uncaptured.length === 0) {
@@ -15901,7 +15898,7 @@ function finishReport(root, initialized, mode, findings, config) {
15901
15898
  async function runWithEnforcement(command, args, opts) {
15902
15899
  const root = findProjectRoot52(opts.dir);
15903
15900
  const paths = resolveHaivePaths48(root);
15904
- if (!existsSync76(paths.haiveDir)) {
15901
+ if (!existsSync75(paths.haiveDir)) {
15905
15902
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
15906
15903
  process.exit(1);
15907
15904
  }
@@ -15990,13 +15987,13 @@ async function writeWrapperBriefing(paths, sessionId, task) {
15990
15987
  if (briefing.setup_warnings.length > 0) {
15991
15988
  parts.push("", "## Setup Warnings", ...briefing.setup_warnings.map((w) => `- ${w}`));
15992
15989
  }
15993
- await writeFile38(file, parts.join("\n") + "\n", "utf8");
15990
+ await writeFile37(file, parts.join("\n") + "\n", "utf8");
15994
15991
  return file;
15995
15992
  }
15996
15993
  async function buildEnforcementReport(dir, stage, sessionId) {
15997
15994
  const root = findProjectRoot52(dir);
15998
15995
  const paths = resolveHaivePaths48(root);
15999
- const initialized = existsSync76(paths.haiveDir);
15996
+ const initialized = existsSync75(paths.haiveDir);
16000
15997
  const config = initialized ? await loadConfig14(paths) : {};
16001
15998
  if (initialized) {
16002
15999
  await applyLightweightRepairs(root, paths);
@@ -16030,7 +16027,7 @@ async function buildEnforcementReport(dir, stage, sessionId) {
16030
16027
  findings: [{ severity: "info", code: "enforcement-off", message: "hAIve enforcement is disabled." }]
16031
16028
  });
16032
16029
  }
16033
- findings.push(...await inspectIntegrationVersions(root, "0.18.0"));
16030
+ findings.push(...await inspectIntegrationVersions(root, "0.19.0"));
16034
16031
  if (config.enforcement?.requireBriefingFirst !== false && stage !== "ci") {
16035
16032
  const hasBriefing = await hasRecentBriefingMarker2(paths, sessionId);
16036
16033
  findings.push(hasBriefing ? { severity: "ok", code: "briefing-loaded", message: "A recent hAIve briefing marker exists." } : {
@@ -16100,8 +16097,8 @@ function withCategories(report) {
16100
16097
  };
16101
16098
  }
16102
16099
  async function hasRecentSessionRecap(paths) {
16103
- if (!existsSync76(paths.memoriesDir)) return false;
16104
- const all = await loadMemoriesFromDir39(paths.memoriesDir);
16100
+ if (!existsSync75(paths.memoriesDir)) return false;
16101
+ const all = await loadMemoriesFromDir38(paths.memoriesDir);
16105
16102
  return all.some(({ memory: memory2 }) => {
16106
16103
  const fm = memory2.frontmatter;
16107
16104
  const freshnessDate = fm.verified_at ?? fm.created_at;
@@ -16109,8 +16106,8 @@ async function hasRecentSessionRecap(paths) {
16109
16106
  });
16110
16107
  }
16111
16108
  async function verifyMemoryPolicy(paths, config) {
16112
- if (!existsSync76(paths.memoriesDir)) return [];
16113
- const all = await loadMemoriesFromDir39(paths.memoriesDir);
16109
+ if (!existsSync75(paths.memoriesDir)) return [];
16110
+ const all = await loadMemoriesFromDir38(paths.memoriesDir);
16114
16111
  const findings = [];
16115
16112
  const staleImportant = [];
16116
16113
  let verified = 0;
@@ -16147,12 +16144,12 @@ async function verifyMemoryPolicy(paths, config) {
16147
16144
  return findings;
16148
16145
  }
16149
16146
  async function verifyDecisionCoverage(paths, stage, sessionId) {
16150
- if (!existsSync76(paths.memoriesDir)) return [];
16147
+ if (!existsSync75(paths.memoriesDir)) return [];
16151
16148
  const changedFiles = (await getChangedFiles(paths.root, stage)).filter((f) => !isGeneratedArtifact(f));
16152
16149
  if (changedFiles.length === 0) {
16153
16150
  return [{ severity: "info", code: "decision-coverage-no-changes", message: "No changed files to match against policy memories." }];
16154
16151
  }
16155
- const all = await loadMemoriesFromDir39(paths.memoriesDir);
16152
+ const all = await loadMemoriesFromDir38(paths.memoriesDir);
16156
16153
  const policyTypes = /* @__PURE__ */ new Set(["decision", "gotcha", "architecture", "convention"]);
16157
16154
  const relevant = all.map(({ memory: memory2 }) => memory2).filter((memory2) => {
16158
16155
  const fm = memory2.frontmatter;
@@ -16267,9 +16264,9 @@ async function cleanupRuntimeDir(runtimeDir) {
16267
16264
  await rm3(path53.join(runtimeDir, entry.name), { recursive: true, force: true });
16268
16265
  removed++;
16269
16266
  }
16270
- await writeFile38(path53.join(runtimeDir, ".gitignore"), "*\n!.gitignore\n!README.md\n", "utf8");
16271
- if (!existsSync76(path53.join(runtimeDir, "README.md"))) {
16272
- await writeFile38(
16267
+ await writeFile37(path53.join(runtimeDir, ".gitignore"), "*\n!.gitignore\n!README.md\n", "utf8");
16268
+ if (!existsSync75(path53.join(runtimeDir, "README.md"))) {
16269
+ await writeFile37(
16273
16270
  path53.join(runtimeDir, "README.md"),
16274
16271
  "# .ai/.runtime \u2014 disposable local layer\n\nRuntime data is local. hAIve cleanup preserves briefing markers so enforcement state remains valid.\n",
16275
16272
  "utf8"
@@ -16286,7 +16283,7 @@ async function cleanupCacheDir(cacheDir) {
16286
16283
  await rm3(path53.join(cacheDir, entry.name), { recursive: true, force: true });
16287
16284
  removed++;
16288
16285
  }
16289
- await writeFile38(path53.join(cacheDir, ".gitignore"), "*\n!.gitignore\n", "utf8");
16286
+ await writeFile37(path53.join(cacheDir, ".gitignore"), "*\n!.gitignore\n", "utf8");
16290
16287
  return removed;
16291
16288
  }
16292
16289
  async function cleanupEnforcementDir(enforcementDir) {
@@ -16311,7 +16308,7 @@ async function inspectIntegrationVersions(root, expectedVersion) {
16311
16308
  const findings = [];
16312
16309
  for (const rel of files) {
16313
16310
  const file = path53.join(root, rel);
16314
- if (!existsSync76(file)) continue;
16311
+ if (!existsSync75(file)) continue;
16315
16312
  const text = await readFile24(file, "utf8").catch(() => "");
16316
16313
  for (const bin of extractAbsoluteHaiveBins2(text)) {
16317
16314
  const version = versionForBinary2(bin);
@@ -16421,7 +16418,7 @@ async function resolveCiDiffRange(root) {
16421
16418
  }
16422
16419
  async function resolveGithubEventRange(root) {
16423
16420
  const eventPath = process.env.GITHUB_EVENT_PATH;
16424
- if (!eventPath || !existsSync76(eventPath)) return null;
16421
+ if (!eventPath || !existsSync75(eventPath)) return null;
16425
16422
  try {
16426
16423
  const event = JSON.parse(await readFile24(eventPath, "utf8"));
16427
16424
  const prBase = cleanGitSha(event.pull_request?.base?.sha);
@@ -16744,7 +16741,7 @@ function buildScore(findings, threshold = 80) {
16744
16741
  }
16745
16742
  async function installGitEnforcement(root) {
16746
16743
  const hooksDir = path53.join(root, ".git", "hooks");
16747
- if (!existsSync76(path53.join(root, ".git"))) {
16744
+ if (!existsSync75(path53.join(root, ".git"))) {
16748
16745
  ui.warn("No .git directory found; git enforcement hooks skipped.");
16749
16746
  return;
16750
16747
  }
@@ -16774,17 +16771,17 @@ haive enforce commit-msg "$1" --dir . || exit $?
16774
16771
  ];
16775
16772
  for (const hook of hooks) {
16776
16773
  const file = path53.join(hooksDir, hook.name);
16777
- if (existsSync76(file)) {
16774
+ if (existsSync75(file)) {
16778
16775
  const current = await readFile24(file, "utf8").catch(() => "");
16779
16776
  if (current.includes(ENFORCE_HOOK_MARKER)) {
16780
- await writeFile38(file, hook.body, "utf8");
16777
+ await writeFile37(file, hook.body, "utf8");
16781
16778
  } else {
16782
- await writeFile38(file, `${current.trimEnd()}
16779
+ await writeFile37(file, `${current.trimEnd()}
16783
16780
 
16784
16781
  ${hook.body}`, "utf8");
16785
16782
  }
16786
16783
  } else {
16787
- await writeFile38(file, hook.body, "utf8");
16784
+ await writeFile37(file, hook.body, "utf8");
16788
16785
  }
16789
16786
  await chmod2(file, 493);
16790
16787
  }
@@ -16793,11 +16790,11 @@ ${hook.body}`, "utf8");
16793
16790
  async function installCiEnforcement(root) {
16794
16791
  const workflowPath = path53.join(root, ".github", "workflows", "haive-enforcement.yml");
16795
16792
  await mkdir21(path53.dirname(workflowPath), { recursive: true });
16796
- if (existsSync76(workflowPath)) {
16793
+ if (existsSync75(workflowPath)) {
16797
16794
  ui.info("GitHub Actions enforcement workflow already exists \u2014 skipped");
16798
16795
  return;
16799
16796
  }
16800
- await writeFile38(workflowPath, `name: haive-enforcement
16797
+ await writeFile37(workflowPath, `name: haive-enforcement
16801
16798
 
16802
16799
  on:
16803
16800
  pull_request:
@@ -16932,11 +16929,11 @@ function normalizeToolPath(file, root) {
16932
16929
  return path53.relative(root, normalized).replace(/\\/g, "/");
16933
16930
  }
16934
16931
  async function missingRequiredMemoriesForFiles(paths, files, sessionId) {
16935
- if (!existsSync76(paths.memoriesDir)) return [];
16932
+ if (!existsSync75(paths.memoriesDir)) return [];
16936
16933
  const marker = await readRecentBriefingMarker(paths, sessionId);
16937
16934
  const consulted = new Set(marker?.memory_ids ?? []);
16938
16935
  const policyTypes = /* @__PURE__ */ new Set(["decision", "gotcha", "architecture", "convention", "attempt"]);
16939
- const all = await loadMemoriesFromDir39(paths.memoriesDir);
16936
+ const all = await loadMemoriesFromDir38(paths.memoriesDir);
16940
16937
  return all.filter(({ memory: memory2 }) => {
16941
16938
  const fm = memory2.frontmatter;
16942
16939
  if (!policyTypes.has(fm.type)) return false;
@@ -17017,17 +17014,17 @@ function registerRun(program2) {
17017
17014
 
17018
17015
  // src/commands/sensors.ts
17019
17016
  import { execFile as execFile3 } from "child_process";
17020
- import { existsSync as existsSync77 } from "fs";
17021
- import { chmod as chmod3, mkdir as mkdir23, readFile as readFile25, writeFile as writeFile39 } from "fs/promises";
17017
+ import { existsSync as existsSync76 } from "fs";
17018
+ import { chmod as chmod3, mkdir as mkdir23, readFile as readFile25, writeFile as writeFile38 } from "fs/promises";
17022
17019
  import path54 from "path";
17023
17020
  import { promisify as promisify3 } from "util";
17024
17021
  import "commander";
17025
17022
  import {
17026
17023
  appendPreventionEvent as appendPreventionEvent2,
17027
17024
  findProjectRoot as findProjectRoot53,
17028
- isRetiredMemory as isRetiredMemory4,
17025
+ isRetiredMemory as isRetiredMemory3,
17029
17026
  loadConfig as loadConfig15,
17030
- loadMemoriesFromDir as loadMemoriesFromDir40,
17027
+ loadMemoriesFromDir as loadMemoriesFromDir39,
17031
17028
  loadUsageIndex as loadUsageIndex31,
17032
17029
  recordPrevention as recordPrevention2,
17033
17030
  resolveHaivePaths as resolveHaivePaths49,
@@ -17157,7 +17154,7 @@ function registerSensors(program2) {
17157
17154
  }
17158
17155
  const root = findProjectRoot53(opts.dir);
17159
17156
  const paths = resolveHaivePaths49(root);
17160
- const loaded = existsSync77(paths.memoriesDir) ? await loadMemoriesFromDir40(paths.memoriesDir) : [];
17157
+ const loaded = existsSync76(paths.memoriesDir) ? await loadMemoriesFromDir39(paths.memoriesDir) : [];
17161
17158
  const found = loaded.find(({ memory: memory2 }) => memory2.frontmatter.id === id);
17162
17159
  if (!found) {
17163
17160
  ui.error(`No memory found with id ${id}`);
@@ -17177,7 +17174,7 @@ function registerSensors(program2) {
17177
17174
  },
17178
17175
  body: found.memory.body
17179
17176
  };
17180
- await writeFile39(found.filePath, serializeMemory29(next), "utf8");
17177
+ await writeFile38(found.filePath, serializeMemory29(next), "utf8");
17181
17178
  ui.success(`Updated ${id}: sensor severity=${severity}`);
17182
17179
  if (sensor.pattern) ui.info(`pattern=${JSON.stringify(sensor.pattern)}`);
17183
17180
  ui.info(`message=${sensor.message}`);
@@ -17196,7 +17193,7 @@ function registerSensors(program2) {
17196
17193
  await mkdir23(outDir, { recursive: true });
17197
17194
  const outPath = path54.join(outDir, format === "grep" ? "haive-sensors-grep.sh" : "haive-sensors-eslint.json");
17198
17195
  const content = format === "grep" ? renderGrepScript(rows) : JSON.stringify({ sensors: rows }, null, 2) + "\n";
17199
- await writeFile39(outPath, content, "utf8");
17196
+ await writeFile38(outPath, content, "utf8");
17200
17197
  if (format === "grep") await chmod3(outPath, 493);
17201
17198
  ui.success(`Exported ${rows.length} sensor(s): ${path54.relative(root, outPath)}`);
17202
17199
  });
@@ -17219,13 +17216,13 @@ async function sensorRows(paths) {
17219
17216
  });
17220
17217
  }
17221
17218
  async function runnableSensorMemories(paths, regexOnly = true) {
17222
- if (!existsSync77(paths.memoriesDir)) return [];
17223
- const loaded = await loadMemoriesFromDir40(paths.memoriesDir);
17219
+ if (!existsSync76(paths.memoriesDir)) return [];
17220
+ const loaded = await loadMemoriesFromDir39(paths.memoriesDir);
17224
17221
  return loaded.map(({ memory: memory2 }) => memory2).filter((memory2) => {
17225
17222
  const sensor = memory2.frontmatter.sensor;
17226
17223
  if (!sensor) return false;
17227
17224
  if (regexOnly && sensor.kind !== "regex") return false;
17228
- return !isRetiredMemory4(memory2.frontmatter, memory2.body);
17225
+ return !isRetiredMemory3(memory2.frontmatter, memory2.body);
17229
17226
  });
17230
17227
  }
17231
17228
  async function runCommandSensor(spec, root) {
@@ -17269,15 +17266,15 @@ function shellQuote(value) {
17269
17266
  }
17270
17267
 
17271
17268
  // src/commands/ingest.ts
17272
- import { existsSync as existsSync78 } from "fs";
17273
- import { mkdir as mkdir24, readFile as readFile26, writeFile as writeFile40 } from "fs/promises";
17269
+ import { existsSync as existsSync77 } from "fs";
17270
+ import { mkdir as mkdir24, readFile as readFile26, writeFile as writeFile39 } from "fs/promises";
17274
17271
  import path55 from "path";
17275
17272
  import "commander";
17276
17273
  import {
17277
17274
  draftsFromFindings as draftsFromFindings2,
17278
17275
  filterNewDrafts as filterNewDrafts2,
17279
17276
  findProjectRoot as findProjectRoot54,
17280
- loadMemoriesFromDir as loadMemoriesFromDir41,
17277
+ loadMemoriesFromDir as loadMemoriesFromDir40,
17281
17278
  memoryFilePath as memoryFilePath12,
17282
17279
  parseFindings as parseFindings2,
17283
17280
  resolveHaivePaths as resolveHaivePaths50,
@@ -17307,7 +17304,7 @@ function registerIngest(program2) {
17307
17304
  }
17308
17305
  const root = findProjectRoot54(opts.dir);
17309
17306
  const paths = resolveHaivePaths50(root);
17310
- if (!existsSync78(paths.haiveDir)) {
17307
+ if (!existsSync77(paths.haiveDir)) {
17311
17308
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
17312
17309
  process.exitCode = 1;
17313
17310
  return;
@@ -17329,7 +17326,7 @@ function registerIngest(program2) {
17329
17326
  return;
17330
17327
  }
17331
17328
  const reportPath = path55.resolve(root, file);
17332
- if (!existsSync78(reportPath)) {
17329
+ if (!existsSync77(reportPath)) {
17333
17330
  ui.error(`Report file not found: ${reportPath}`);
17334
17331
  process.exitCode = 1;
17335
17332
  return;
@@ -17358,7 +17355,7 @@ function registerIngest(program2) {
17358
17355
  process.exitCode = 1;
17359
17356
  return;
17360
17357
  }
17361
- const existing = existsSync78(paths.memoriesDir) ? await loadMemoriesFromDir41(paths.memoriesDir) : [];
17358
+ const existing = existsSync77(paths.memoriesDir) ? await loadMemoriesFromDir40(paths.memoriesDir) : [];
17362
17359
  const existingTopics = new Set(
17363
17360
  existing.map(({ memory: memory2 }) => memory2.frontmatter.topic).filter((t) => Boolean(t))
17364
17361
  );
@@ -17424,7 +17421,7 @@ function registerIngest(program2) {
17424
17421
  async function writeDraft2(paths, draft) {
17425
17422
  const file = memoryFilePath12(paths, draft.frontmatter.scope, draft.frontmatter.id, draft.frontmatter.module);
17426
17423
  await mkdir24(path55.dirname(file), { recursive: true });
17427
- await writeFile40(file, serializeMemory30({ frontmatter: draft.frontmatter, body: draft.body }), "utf8");
17424
+ await writeFile39(file, serializeMemory30({ frontmatter: draft.frontmatter, body: draft.body }), "utf8");
17428
17425
  return file;
17429
17426
  }
17430
17427
  async function fetchSonarIssues(opts) {
@@ -17465,13 +17462,13 @@ async function fetchSonarIssues(opts) {
17465
17462
  }
17466
17463
 
17467
17464
  // src/commands/dashboard.ts
17468
- import { existsSync as existsSync79 } from "fs";
17465
+ import { existsSync as existsSync78 } from "fs";
17469
17466
  import "commander";
17470
17467
  import {
17471
17468
  buildDashboard,
17472
17469
  findProjectRoot as findProjectRoot55,
17473
17470
  loadConfig as loadConfig16,
17474
- loadMemoriesFromDir as loadMemoriesFromDir43,
17471
+ loadMemoriesFromDir as loadMemoriesFromDir41,
17475
17472
  loadPreventionEvents as loadPreventionEvents4,
17476
17473
  loadUsageIndex as loadUsageIndex33,
17477
17474
  resolveHaivePaths as resolveHaivePaths51
@@ -17482,12 +17479,12 @@ function registerDashboard(program2) {
17482
17479
  ).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) => {
17483
17480
  const root = findProjectRoot55(opts.dir);
17484
17481
  const paths = resolveHaivePaths51(root);
17485
- if (!existsSync79(paths.haiveDir)) {
17482
+ if (!existsSync78(paths.haiveDir)) {
17486
17483
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
17487
17484
  process.exitCode = 1;
17488
17485
  return;
17489
17486
  }
17490
- const memories = existsSync79(paths.memoriesDir) ? await loadMemoriesFromDir43(paths.memoriesDir) : [];
17487
+ const memories = existsSync78(paths.memoriesDir) ? await loadMemoriesFromDir41(paths.memoriesDir) : [];
17491
17488
  const usage = await loadUsageIndex33(paths);
17492
17489
  const preventionEvents = await loadPreventionEvents4(paths);
17493
17490
  const config = await loadConfig16(paths);
@@ -17601,7 +17598,7 @@ function warnNum(n) {
17601
17598
  // src/commands/dev-link.ts
17602
17599
  import { execFile as execFile4 } from "child_process";
17603
17600
  import { cp, readFile as readFile27 } from "fs/promises";
17604
- import { existsSync as existsSync80 } from "fs";
17601
+ import { existsSync as existsSync79 } from "fs";
17605
17602
  import path56 from "path";
17606
17603
  import { promisify as promisify4 } from "util";
17607
17604
  import "commander";
@@ -17611,7 +17608,7 @@ function registerDevLink(program2) {
17611
17608
  const dev = program2.commands.find((c) => c.name() === "dev") ?? program2.command("dev").description("Developer utilities for working on hAIve itself.");
17612
17609
  dev.command("link").description("Hot-swap this repo's built dist into the global @hiveai install so `haive` 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) => {
17613
17610
  const root = findProjectRoot56(opts.dir);
17614
- if (!existsSync80(path56.join(root, "packages", "cli", "dist", "index.js"))) {
17611
+ if (!existsSync79(path56.join(root, "packages", "cli", "dist", "index.js"))) {
17615
17612
  ui.error(`Not the hAIve monorepo (no packages/cli/dist) at ${root}. Run \`pnpm -r build\` first, or pass --dir.`);
17616
17613
  process.exitCode = 1;
17617
17614
  return;
@@ -17623,7 +17620,7 @@ function registerDevLink(program2) {
17623
17620
  globalModules = path56.join(path56.dirname(path56.dirname(process.execPath)), "lib", "node_modules");
17624
17621
  }
17625
17622
  const globalHive = path56.join(globalModules, "@hiveai");
17626
- if (!existsSync80(globalHive)) {
17623
+ if (!existsSync79(globalHive)) {
17627
17624
  ui.error(`No global @hiveai install at ${globalHive}. Install once with \`npm i -g @hiveai/cli\`, then re-run.`);
17628
17625
  process.exitCode = 1;
17629
17626
  return;
@@ -17631,7 +17628,7 @@ function registerDevLink(program2) {
17631
17628
  const linked = [];
17632
17629
  const copyDist = async (fromPkg, toDistDir) => {
17633
17630
  const from = path56.join(root, "packages", fromPkg, "dist");
17634
- if (!existsSync80(from) || !existsSync80(path56.dirname(toDistDir))) return;
17631
+ if (!existsSync79(from) || !existsSync79(path56.dirname(toDistDir))) return;
17635
17632
  await cp(from, toDistDir, { recursive: true });
17636
17633
  linked.push(path56.relative(globalModules, toDistDir));
17637
17634
  };
@@ -17690,7 +17687,7 @@ function registerCoverage(program2) {
17690
17687
  maxHotFiles: 500
17691
17688
  });
17692
17689
  const hotFiles = radar.hotFiles.filter((h) => !isNoisePath(h.path)).map((h) => ({ path: h.path, changes: h.changes }));
17693
- const memories = await loadMemoriesFromDir28(paths.memoriesDir);
17690
+ const memories = await loadMemoriesFromDir27(paths.memoriesDir);
17694
17691
  const gaps = findCoverageGaps(hotFiles, memories, { minChanges, limit });
17695
17692
  if (opts.json) {
17696
17693
  console.log(JSON.stringify({ root, scanned_hot_files: hotFiles.length, gaps }, null, 2));
@@ -17718,7 +17715,7 @@ function registerCoverage(program2) {
17718
17715
 
17719
17716
  // src/commands/merge-driver.ts
17720
17717
  import { execFileSync as execFileSync3 } from "child_process";
17721
- import { readFileSync, writeFileSync, existsSync as existsSync81 } from "fs";
17718
+ import { readFileSync, writeFileSync, existsSync as existsSync80 } from "fs";
17722
17719
  import path57 from "path";
17723
17720
  import "commander";
17724
17721
  import { findProjectRoot as findProjectRoot58, mergeMemoryVersions } from "@hiveai/core";
@@ -17752,7 +17749,7 @@ function registerMergeDriver(program2) {
17752
17749
  return;
17753
17750
  }
17754
17751
  const gaPath = path57.join(root, ".gitattributes");
17755
- let content = existsSync81(gaPath) ? readFileSync(gaPath, "utf8") : "";
17752
+ let content = existsSync80(gaPath) ? readFileSync(gaPath, "utf8") : "";
17756
17753
  if (!content.includes(GITATTRIBUTES_MARK)) {
17757
17754
  if (content.length > 0 && !content.endsWith("\n")) content += "\n";
17758
17755
  content += GITATTRIBUTES_BLOCK + "\n";
@@ -17766,8 +17763,8 @@ function registerMergeDriver(program2) {
17766
17763
  }
17767
17764
 
17768
17765
  // src/commands/memory-resolve-conflict.ts
17769
- import { writeFile as writeFile41 } from "fs/promises";
17770
- import { existsSync as existsSync83 } from "fs";
17766
+ import { writeFile as writeFile40 } from "fs/promises";
17767
+ import { existsSync as existsSync81 } from "fs";
17771
17768
  import "commander";
17772
17769
  import {
17773
17770
  findProjectRoot as findProjectRoot59,
@@ -17779,12 +17776,12 @@ function registerMemoryResolveConflict(memory2) {
17779
17776
  memory2.command("resolve-conflict <id_a> <id_b>").description("Resolve a contradiction: keep the stronger memory, deprecate (supersede) the other").option("--yes", "apply the resolution (without this, only previews it)", false).option("--json", "emit JSON", false).option("-d, --dir <dir>", "project root").action(async (idA, idB, opts) => {
17780
17777
  const root = findProjectRoot59(opts.dir);
17781
17778
  const paths = resolveHaivePaths53(root);
17782
- if (!existsSync83(paths.memoriesDir)) {
17779
+ if (!existsSync81(paths.memoriesDir)) {
17783
17780
  ui.error(`No .ai/memories at ${root}.`);
17784
17781
  process.exitCode = 1;
17785
17782
  return;
17786
17783
  }
17787
- const memories = await loadMemoriesFromDir28(paths.memoriesDir);
17784
+ const memories = await loadMemoriesFromDir27(paths.memoriesDir);
17788
17785
  const a = memories.find((m) => m.memory.frontmatter.id === idA);
17789
17786
  const b = memories.find((m) => m.memory.frontmatter.id === idB);
17790
17787
  if (!a || !b) {
@@ -17806,7 +17803,7 @@ function registerMemoryResolveConflict(memory2) {
17806
17803
  if (!opts.json) ui.info("Preview only \u2014 re-run with --yes to apply.");
17807
17804
  return;
17808
17805
  }
17809
- await writeFile41(
17806
+ await writeFile40(
17810
17807
  loser.filePath,
17811
17808
  serializeMemory31({
17812
17809
  frontmatter: {
@@ -17825,8 +17822,8 @@ function registerMemoryResolveConflict(memory2) {
17825
17822
 
17826
17823
  // src/commands/memory-seed-git.ts
17827
17824
  import { execFile as execFile5 } from "child_process";
17828
- import { mkdir as mkdir25, writeFile as writeFile43 } from "fs/promises";
17829
- import { existsSync as existsSync84 } from "fs";
17825
+ import { mkdir as mkdir25, writeFile as writeFile41 } from "fs/promises";
17826
+ import { existsSync as existsSync83 } from "fs";
17830
17827
  import path58 from "path";
17831
17828
  import { promisify as promisify5 } from "util";
17832
17829
  import "commander";
@@ -17843,7 +17840,7 @@ function registerMemorySeedGit(memory2) {
17843
17840
  memory2.command("seed-git").description("Propose draft `attempt` seeds from revert/hotfix commits in git history (cold-start)").option("--apply", "write the proposed seeds as draft memories (default: preview only)", false).option("--limit <n>", "max seeds to propose", "20").option("--days <n>", "git-history lookback window in days", "365").option("--scope <scope>", "personal | team", "team").option("--json", "emit JSON", false).option("-d, --dir <dir>", "project root").action(async (opts) => {
17844
17841
  const root = findProjectRoot60(opts.dir);
17845
17842
  const paths = resolveHaivePaths54(root);
17846
- if (!existsSync84(paths.haiveDir)) {
17843
+ if (!existsSync83(paths.haiveDir)) {
17847
17844
  ui.error(`No .ai/ found at ${root}. Run \`haive init\` first.`);
17848
17845
  process.exitCode = 1;
17849
17846
  return;
@@ -17888,9 +17885,9 @@ function registerMemorySeedGit(memory2) {
17888
17885
  _Seeded from git ${p.kind} commit ${p.source_sha}. Review and validate (or delete) \u2014 not yet authoritative._
17889
17886
  `;
17890
17887
  const file = memoryFilePath13(paths, fm.scope, fm.id, fm.module);
17891
- if (existsSync84(file)) continue;
17888
+ if (existsSync83(file)) continue;
17892
17889
  await mkdir25(path58.dirname(file), { recursive: true });
17893
- await writeFile43(file, serializeMemory33({ frontmatter: fm, body }), "utf8");
17890
+ await writeFile41(file, serializeMemory33({ frontmatter: fm, body }), "utf8");
17894
17891
  written += 1;
17895
17892
  }
17896
17893
  if (!opts.json) {
@@ -17921,21 +17918,21 @@ async function readCommits(root, days) {
17921
17918
  }
17922
17919
 
17923
17920
  // src/commands/bridges.ts
17924
- import { existsSync as existsSync85 } from "fs";
17921
+ import { existsSync as existsSync84 } from "fs";
17925
17922
  import path59 from "path";
17926
17923
  import "commander";
17927
17924
  import {
17928
17925
  findProjectRoot as findProjectRoot61,
17929
17926
  resolveHaivePaths as resolveHaivePaths55,
17930
17927
  BRIDGE_TARGET_PATH as BRIDGE_TARGET_PATH2,
17931
- BRIDGE_TARGETS as BRIDGE_TARGETS2
17928
+ BRIDGE_TARGETS as BRIDGE_TARGETS3
17932
17929
  } from "@hiveai/core";
17933
17930
  function registerBridges(program2) {
17934
17931
  const bridges = program2.command("bridges").description(
17935
17932
  "Generate native agent bridge files from the hAIve 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 haive bridges sync --all\n haive bridges sync --only cline,windsurf\n"
17936
17933
  );
17937
17934
  bridges.command("sync").description(
17938
- "Regenerate bridge files idempotently (marker-based, preserves manual content outside markers).\n Supported targets: " + BRIDGE_TARGETS2.join(", ") + "\n"
17935
+ "Regenerate bridge files idempotently (marker-based, preserves manual content outside markers).\n Supported targets: " + BRIDGE_TARGETS3.join(", ") + "\n"
17939
17936
  ).option("--all", "generate all supported bridge targets").option(
17940
17937
  "--only <targets>",
17941
17938
  "comma-separated list of targets to generate (e.g. cline,windsurf,agents)"
@@ -17943,7 +17940,7 @@ function registerBridges(program2) {
17943
17940
  const root = findProjectRoot61(opts.dir);
17944
17941
  const paths = resolveHaivePaths55(root);
17945
17942
  const dryRun = opts.dryRun === true;
17946
- if (!existsSync85(paths.memoriesDir)) {
17943
+ if (!existsSync84(paths.memoriesDir)) {
17947
17944
  ui.warn(`No .ai/memories at ${root}. Run \`haive init\` first.`);
17948
17945
  process.exitCode = 1;
17949
17946
  return;
@@ -17951,18 +17948,18 @@ function registerBridges(program2) {
17951
17948
  let targets;
17952
17949
  if (opts.only) {
17953
17950
  const requested = opts.only.split(",").map((t) => t.trim().toLowerCase()).filter(Boolean);
17954
- const invalid = requested.filter((t) => !BRIDGE_TARGETS2.includes(t));
17951
+ const invalid = requested.filter((t) => !BRIDGE_TARGETS3.includes(t));
17955
17952
  if (invalid.length > 0) {
17956
- ui.error(`Unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS2.join(", ")}`);
17953
+ ui.error(`Unknown bridge target(s): ${invalid.join(", ")}. Valid: ${BRIDGE_TARGETS3.join(", ")}`);
17957
17954
  process.exitCode = 1;
17958
17955
  return;
17959
17956
  }
17960
17957
  targets = requested;
17961
17958
  } else if (opts.all) {
17962
- targets = BRIDGE_TARGETS2;
17959
+ targets = BRIDGE_TARGETS3;
17963
17960
  } else {
17964
- targets = BRIDGE_TARGETS2.filter(
17965
- (t) => existsSync85(path59.join(root, BRIDGE_TARGET_PATH2[t]))
17961
+ targets = BRIDGE_TARGETS3.filter(
17962
+ (t) => existsSync84(path59.join(root, BRIDGE_TARGET_PATH2[t]))
17966
17963
  );
17967
17964
  if (targets.length === 0) {
17968
17965
  ui.info(
@@ -17989,9 +17986,9 @@ function registerBridges(program2) {
17989
17986
  bridges.command("list").description("List bridge targets and their status in this project").option("-d, --dir <dir>", "project root").action(async (opts) => {
17990
17987
  const root = findProjectRoot61(opts.dir);
17991
17988
  console.log(ui.bold("hAIve bridge targets:"));
17992
- for (const target of BRIDGE_TARGETS2) {
17989
+ for (const target of BRIDGE_TARGETS3) {
17993
17990
  const relPath = BRIDGE_TARGET_PATH2[target];
17994
- const exists = existsSync85(path59.join(root, relPath));
17991
+ const exists = existsSync84(path59.join(root, relPath));
17995
17992
  const marker = exists ? ui.dim("\u2713") : ui.dim("\xB7");
17996
17993
  console.log(` ${marker} ${target.padEnd(10)} ${relPath}${exists ? "" : " (not present)"}`);
17997
17994
  }
@@ -18002,7 +17999,7 @@ function registerBridges(program2) {
18002
17999
 
18003
18000
  // src/index.ts
18004
18001
  var program = new Command64();
18005
- program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.18.0").option("--advanced", "show maintenance and experimental commands in help");
18002
+ program.name("haive").description("hAIve - repo-native memory and context policy for coding-agent harnesses").version("0.19.0").option("--advanced", "show maintenance and experimental commands in help");
18006
18003
  registerInit(program);
18007
18004
  registerWelcome(program);
18008
18005
  registerResolveProject(program);