@hivelore/cli 0.42.1 → 0.43.2

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.
@@ -133,7 +133,7 @@ import {
133
133
  suggestSensorSeed as suggestSensorSeed2
134
134
  } from "@hivelore/core";
135
135
  import { z as z16 } from "zod";
136
- import { execSync } from "child_process";
136
+ import { execFileSync } from "child_process";
137
137
  import { readFile as readFile3, writeFile as writeFile8 } from "fs/promises";
138
138
  import { existsSync as existsSync15, rmSync, symlinkSync } from "fs";
139
139
  import os from "os";
@@ -193,7 +193,7 @@ import {
193
193
  import { mkdir as mkdir6, writeFile as writeFile12, rm } from "fs/promises";
194
194
  import { existsSync as existsSync19 } from "fs";
195
195
  import path10 from "path";
196
- import { execSync as execSync2 } from "child_process";
196
+ import { execSync } from "child_process";
197
197
  import { readFile as readFile7, writeFile as writeFile14, readdir as readdir4 } from "fs/promises";
198
198
  import { existsSync as existsSync22 } from "fs";
199
199
  import path13 from "path";
@@ -305,6 +305,7 @@ import { z as z32 } from "zod";
305
305
  import { z as z33 } from "zod";
306
306
  import { readFile as readFile8, readdir as readdir5 } from "fs/promises";
307
307
  import { existsSync as existsSync29 } from "fs";
308
+ import path14 from "path";
308
309
  import {
309
310
  assessBootstrapState as assessBootstrapState2,
310
311
  loadCodeMap as loadCodeMap4,
@@ -1283,10 +1284,32 @@ async function memApprove(input, ctx) {
1283
1284
  };
1284
1285
  }
1285
1286
  var cachedEngine;
1287
+ var registeredDynamicLanguages = /* @__PURE__ */ new Set();
1288
+ async function loadDynamicLanguages(engine) {
1289
+ const registrations = {};
1290
+ const candidates = [
1291
+ ["python", () => import("@ast-grep/lang-python")],
1292
+ ["go", () => import("@ast-grep/lang-go")],
1293
+ ["rust", () => import("@ast-grep/lang-rust")],
1294
+ ["java", () => import("@ast-grep/lang-java")]
1295
+ ];
1296
+ for (const [name, load] of candidates) {
1297
+ try {
1298
+ const mod = await load();
1299
+ registrations[name] = mod.default;
1300
+ registeredDynamicLanguages.add(name);
1301
+ } catch {
1302
+ }
1303
+ }
1304
+ if (Object.keys(registrations).length > 0) {
1305
+ engine.registerDynamicLanguage(registrations);
1306
+ }
1307
+ }
1286
1308
  async function loadAstEngine() {
1287
1309
  if (cachedEngine !== void 0) return cachedEngine;
1288
1310
  try {
1289
1311
  cachedEngine = await import("@ast-grep/napi");
1312
+ await loadDynamicLanguages(cachedEngine);
1290
1313
  } catch {
1291
1314
  cachedEngine = null;
1292
1315
  }
@@ -1295,11 +1318,22 @@ async function loadAstEngine() {
1295
1318
  async function astEngineAvailable() {
1296
1319
  return await loadAstEngine() !== null;
1297
1320
  }
1298
- function astLangForPath(filePath) {
1321
+ function astLangForPath(filePath, explicitLanguage) {
1322
+ if (explicitLanguage) {
1323
+ const normalized = explicitLanguage.toLowerCase();
1324
+ if (["typescript", "tsx", "javascript", "html", "css"].includes(normalized)) {
1325
+ return normalized === "typescript" ? "TypeScript" : normalized === "tsx" ? "Tsx" : normalized === "javascript" ? "JavaScript" : normalized[0].toUpperCase() + normalized.slice(1);
1326
+ }
1327
+ return registeredDynamicLanguages.has(normalized) ? normalized : null;
1328
+ }
1299
1329
  const ext = path5.extname(filePath).toLowerCase();
1300
1330
  if (ext === ".ts" || ext === ".mts" || ext === ".cts") return "TypeScript";
1301
1331
  if (ext === ".tsx") return "Tsx";
1302
1332
  if (ext === ".js" || ext === ".jsx" || ext === ".mjs" || ext === ".cjs") return "JavaScript";
1333
+ if (ext === ".py" && registeredDynamicLanguages.has("python")) return "python";
1334
+ if (ext === ".go" && registeredDynamicLanguages.has("go")) return "go";
1335
+ if (ext === ".rs" && registeredDynamicLanguages.has("rust")) return "rust";
1336
+ if (ext === ".java" && registeredDynamicLanguages.has("java")) return "java";
1303
1337
  return null;
1304
1338
  }
1305
1339
  function absentPresentInNode(node, absent) {
@@ -1314,12 +1348,12 @@ function absentPresentInNode(node, absent) {
1314
1348
  return text.includes(absent);
1315
1349
  }
1316
1350
  }
1317
- async function runAstPattern(content, filePath, pattern, absent) {
1351
+ async function runAstPattern(content, filePath, pattern, absent, rule, language) {
1318
1352
  const engine = await loadAstEngine();
1319
1353
  if (!engine) return { status: "engine-missing", matches: [] };
1320
- const langName = astLangForPath(filePath);
1354
+ const langName = astLangForPath(filePath, language);
1321
1355
  if (!langName) return { status: "unsupported-language", matches: [] };
1322
- const lang = engine.Lang[langName];
1356
+ const lang = langName in engine.Lang ? engine.Lang[langName] : langName;
1323
1357
  let root;
1324
1358
  try {
1325
1359
  root = engine.parse(lang, content).root();
@@ -1328,7 +1362,9 @@ async function runAstPattern(content, filePath, pattern, absent) {
1328
1362
  }
1329
1363
  let nodes;
1330
1364
  try {
1331
- nodes = root.findAll(pattern);
1365
+ const matcher = rule ? { rule: pattern ? { all: [{ pattern }, rule] } : rule } : pattern;
1366
+ if (!matcher) return { status: "invalid-pattern", matches: [], detail: "missing pattern/rule" };
1367
+ nodes = root.findAll(matcher);
1332
1368
  } catch (err) {
1333
1369
  return { status: "invalid-pattern", matches: [], detail: String(err).slice(0, 200) };
1334
1370
  }
@@ -1345,7 +1381,7 @@ async function runAstPattern(content, filePath, pattern, absent) {
1345
1381
  return { status: "ok", matches };
1346
1382
  }
1347
1383
  async function runAstSensorOnContent(input) {
1348
- const scan = await runAstPattern(input.content, input.filePath, input.pattern, input.absent);
1384
+ const scan = await runAstPattern(input.content, input.filePath, input.pattern, input.absent, input.rule, input.language);
1349
1385
  if (scan.status !== "ok" || !input.addedLines || input.addedLines.size === 0) return scan;
1350
1386
  const added = input.addedLines;
1351
1387
  return {
@@ -1363,7 +1399,9 @@ var ProposeSensorInputSchema = {
1363
1399
  kind: z15.enum(["regex", "ast", "shell", "test"]).default("regex").describe(
1364
1400
  "regex = pattern matched on added diff lines (default). ast = an ast-grep STRUCTURAL pattern (e.g. 'stripe.paymentIntents.create($$$)') matched on the AST of changed files \u2014 comments and strings can never false-positive; `absent` is a sub-pattern that must be missing INSIDE the match (requires the optional @ast-grep/napi engine). shell|test = a COMMAND the gate runs when the diff touches the sensor's paths \u2014 routes the team's own oracle (an existing test, an invariant script) to this lesson. Command sensors only execute where enforcement.runCommandSensors=true."
1365
1401
  ),
1366
- pattern: z15.string().optional().describe("kind=regex: regex matching the FAULTY usage (the risky call/token), e.g. 'stripe\\.paymentIntents\\.create'."),
1402
+ pattern: z15.string().optional().describe("kind=regex: regex matching the faulty usage; kind=ast: optional structural pattern (may be combined with `rule`)."),
1403
+ rule: z15.record(z15.unknown()).optional().describe("kind=ast: full ast-grep Rule object (kind/inside/has/not/all/any/etc.). May be used alone or combined with pattern."),
1404
+ language: z15.string().optional().describe("kind=ast: explicit built-in/dynamic language name for non-standard file extensions."),
1367
1405
  command: z15.string().optional().describe("kind=shell|test: command to execute (e.g. 'npx vitest run tests/payments/refund.spec.ts'). Non-zero exit = the lesson fires."),
1368
1406
  timeout_ms: z15.number().int().positive().optional().describe("kind=shell|test: max runtime before the executor kills the command (default 120000)."),
1369
1407
  absent: z15.string().optional().describe(
@@ -1394,7 +1432,7 @@ async function readPresumedCorrectTargets(root, relPaths) {
1394
1432
  const targets = [];
1395
1433
  for (const rel of relPaths) {
1396
1434
  try {
1397
- const content = execSync(`git show ${JSON.stringify(`HEAD:./${rel}`)}`, {
1435
+ const content = execFileSync("git", ["show", `HEAD:./${rel}`], {
1398
1436
  cwd: root,
1399
1437
  encoding: "utf8",
1400
1438
  maxBuffer: 10 * 1024 * 1024,
@@ -1415,7 +1453,7 @@ async function readPresumedCorrectTargets(root, relPaths) {
1415
1453
  }
1416
1454
  function runCommandForValidation(command, root, timeoutMs = 12e4) {
1417
1455
  try {
1418
- execSync(`bash -c ${JSON.stringify(command)}`, {
1456
+ execFileSync("bash", ["-c", command], {
1419
1457
  cwd: root,
1420
1458
  timeout: timeoutMs,
1421
1459
  maxBuffer: 8 * 1024 * 1024,
@@ -1440,7 +1478,7 @@ function proveRedOnIncident(command, root, redRef, timeoutMs) {
1440
1478
  let added = false;
1441
1479
  try {
1442
1480
  try {
1443
- execSync(`git worktree add --detach ${JSON.stringify(worktree)} ${JSON.stringify(redRef)}`, {
1481
+ execFileSync("git", ["worktree", "add", "--detach", worktree, redRef], {
1444
1482
  cwd: root,
1445
1483
  stdio: ["ignore", "pipe", "pipe"],
1446
1484
  timeout: 6e4
@@ -1467,7 +1505,7 @@ function proveRedOnIncident(command, root, redRef, timeoutMs) {
1467
1505
  } finally {
1468
1506
  if (added) {
1469
1507
  try {
1470
- execSync(`git worktree remove --force ${JSON.stringify(worktree)}`, { cwd: root, stdio: "ignore", timeout: 6e4 });
1508
+ execFileSync("git", ["worktree", "remove", "--force", worktree], { cwd: root, stdio: "ignore", timeout: 6e4 });
1471
1509
  } catch {
1472
1510
  try {
1473
1511
  rmSync(worktree, { recursive: true, force: true });
@@ -1507,13 +1545,13 @@ async function proposeSensor(input, ctx) {
1507
1545
  };
1508
1546
  }
1509
1547
  } else if (kind === "ast") {
1510
- if (!input.pattern?.trim()) {
1548
+ if (!input.pattern?.trim() && !input.rule) {
1511
1549
  return {
1512
1550
  accepted: false,
1513
1551
  memory_id: input.memory_id,
1514
1552
  severity: input.severity,
1515
1553
  reason: "invalid-pattern",
1516
- guidance: "kind=ast requires a `pattern` (an ast-grep structural pattern).",
1554
+ guidance: "kind=ast requires a structural `pattern` or a full ast-grep `rule` object.",
1517
1555
  self_check: { silent_on_current: false, fires_on_bad: null, fired_on: [] }
1518
1556
  };
1519
1557
  }
@@ -1534,7 +1572,7 @@ async function proposeSensor(input, ctx) {
1534
1572
  }
1535
1573
  const personalScopeNudge = found.memory.frontmatter.scope === "personal" ? ` Note: this lesson is personal-scoped, so the sensor guards only YOUR machine (personal memories are gitignored). Promote it so the gate travels with the repo: hivelore memory promote ${input.memory_id}.` : "";
1536
1574
  if (kind === "ast") {
1537
- const pattern = input.pattern.trim();
1575
+ const pattern = input.pattern?.trim();
1538
1576
  if (!await astEngineAvailable() && input.severity === "block") {
1539
1577
  return {
1540
1578
  accepted: false,
@@ -1545,7 +1583,7 @@ async function proposeSensor(input, ctx) {
1545
1583
  self_check: { silent_on_current: false, fires_on_bad: null, fired_on: [] }
1546
1584
  };
1547
1585
  }
1548
- const brittleAst = sensorPatternBrittleness(pattern);
1586
+ const brittleAst = pattern ? sensorPatternBrittleness(pattern) : null;
1549
1587
  if (brittleAst && input.severity === "block") {
1550
1588
  return {
1551
1589
  accepted: false,
@@ -1560,7 +1598,7 @@ async function proposeSensor(input, ctx) {
1560
1598
  const currentTargetsAst = await readPresumedCorrectTargets(ctx.paths.root, anchorPathsAst);
1561
1599
  const firedOnAst = [];
1562
1600
  for (const target of currentTargetsAst) {
1563
- const scan = await runAstSensorOnContent({ pattern, absent: input.absent, content: target.content, filePath: target.path });
1601
+ const scan = await runAstSensorOnContent({ pattern, rule: input.rule, language: input.language, absent: input.absent, content: target.content, filePath: target.path });
1564
1602
  if (scan.status === "invalid-pattern") {
1565
1603
  return {
1566
1604
  accepted: false,
@@ -1589,10 +1627,10 @@ async function proposeSensor(input, ctx) {
1589
1627
  ];
1590
1628
  let firesOnBadAst = null;
1591
1629
  if (badExamplesAst.length > 0 && await astEngineAvailable()) {
1592
- const exampleLang = anchorPathsAst.find((p) => astLangForPath(p) !== null) ?? "example.tsx";
1630
+ const exampleLang = anchorPathsAst.find((p) => astLangForPath(p, input.language) !== null) ?? "example.tsx";
1593
1631
  firesOnBadAst = false;
1594
1632
  for (const example of badExamplesAst) {
1595
- const scan = await runAstSensorOnContent({ pattern, absent: input.absent, content: example, filePath: exampleLang });
1633
+ const scan = await runAstSensorOnContent({ pattern, rule: input.rule, language: input.language, absent: input.absent, content: example, filePath: exampleLang });
1596
1634
  if (scan.status === "ok" && scan.matches.length > 0) {
1597
1635
  firesOnBadAst = true;
1598
1636
  break;
@@ -1611,10 +1649,12 @@ async function proposeSensor(input, ctx) {
1611
1649
  }
1612
1650
  const sensorAst = {
1613
1651
  kind: "ast",
1614
- pattern,
1652
+ ...pattern ? { pattern } : {},
1653
+ ...input.rule ? { rule: input.rule } : {},
1654
+ ...input.language ? { language: input.language } : {},
1615
1655
  ...input.absent ? { absent: input.absent } : {},
1616
1656
  paths: anchorPathsAst,
1617
- message: input.message?.trim() || deriveMessage(found.memory.body, pattern, input.absent),
1657
+ message: input.message?.trim() || deriveMessage(found.memory.body, pattern ?? "AST rule", input.absent),
1618
1658
  ...input.incident?.trim() ? { incident: input.incident.trim() } : {},
1619
1659
  severity: input.severity,
1620
1660
  autogen: false,
@@ -1677,6 +1717,16 @@ ${verdictCmd.detail}`,
1677
1717
  self_check: { silent_on_current: false, fires_on_bad: null, fired_on: anchorPathsCmd }
1678
1718
  };
1679
1719
  }
1720
+ if (input.severity === "block" && !input.red_ref?.trim()) {
1721
+ return {
1722
+ accepted: false,
1723
+ memory_id: input.memory_id,
1724
+ severity: input.severity,
1725
+ reason: "red-required",
1726
+ guidance: "A blocking shell/test sensor requires `red_ref`: the oracle must PASS on the current tree and FAIL on the pre-fix incident state. Pass the incident commit/ref, or propose the sensor at warn severity until RED can be proven.",
1727
+ self_check: { silent_on_current: true, fires_on_bad: null, fired_on: [] }
1728
+ };
1729
+ }
1680
1730
  const sensorCmd = {
1681
1731
  kind,
1682
1732
  command: input.command.trim(),
@@ -1698,7 +1748,7 @@ ${verdictCmd.detail}`,
1698
1748
  accepted: true,
1699
1749
  memory_id: input.memory_id,
1700
1750
  severity: input.severity,
1701
- guidance: (verdictCmd.status === "passed" ? "Command oracle passes on the current tree; the gate now runs it when the diff touches the sensor's paths (requires enforcement.runCommandSensors=true)." : `Accepted at warn severity, but note: ${verdictCmd.status} on the current tree (${verdictCmd.detail}).`) + (redProven ? " RED proven: the oracle demonstrably FAILS on the incident state (red_ref) \u2014 recorded as red_proven." : " Tip: pass red_ref (the pre-fix commit) to PROVE the oracle catches the incident, not merely that it passes today.") + (pendingTests.length > 0 ? ` Note: the routed test is still a PENDING stub (${pendingTests.join(", ")}) \u2014 it passes on anything; write the assertion to make this oracle real.` : "") + personalScopeNudge,
1751
+ guidance: (verdictCmd.status === "passed" ? "Command oracle passes on the current tree; the gate now runs it when the diff touches the sensor's paths (requires enforcement.runCommandSensors=true)." : `Accepted at warn severity, but note: ${verdictCmd.status} on the current tree (${verdictCmd.detail}).`) + (redProven ? " RED proven: the oracle demonstrably FAILS on the incident state (red_ref) \u2014 recorded as red_proven." : " This warn-only oracle is not RED-proven; pass red_ref before promoting it to block.") + (pendingTests.length > 0 ? ` Note: the routed test is still a PENDING stub (${pendingTests.join(", ")}) \u2014 it passes on anything; write the assertion to make this oracle real.` : "") + personalScopeNudge,
1702
1752
  self_check: { silent_on_current: verdictCmd.status === "passed", fires_on_bad: redProven ? true : null, fired_on: [] },
1703
1753
  file_path: found.filePath
1704
1754
  };
@@ -1765,8 +1815,10 @@ var MemTriedInputSchema = {
1765
1815
  paths: z16.array(z16.string()).default([]).describe("Anchor file paths this applies to"),
1766
1816
  author: z16.string().optional().describe("Author handle or email"),
1767
1817
  sensor: z16.object({
1768
- kind: z16.enum(["regex", "shell", "test"]).default("regex").describe("regex pattern, or a shell/test COMMAND the gate executes (behaviour bridge)"),
1769
- pattern: z16.string().optional().describe("kind=regex: regex matching the FAULTY usage (added diff lines)"),
1818
+ kind: z16.enum(["regex", "ast", "shell", "test"]).default("regex").describe("regex/AST pattern, or a shell/test command"),
1819
+ pattern: z16.string().optional().describe("kind=regex|ast: pattern matching the faulty usage"),
1820
+ rule: z16.record(z16.unknown()).optional().describe("kind=ast: full ast-grep Rule object"),
1821
+ language: z16.string().optional().describe("kind=ast: explicit built-in/dynamic language"),
1770
1822
  command: z16.string().optional().describe("kind=shell|test: command the gate runs when the diff touches the sensor's paths (non-zero exit = lesson fires)"),
1771
1823
  timeout_ms: z16.number().int().positive().optional().describe("kind=shell|test: max runtime (default 120000)"),
1772
1824
  absent: z16.string().optional().describe("kind=regex: regex marking CORRECT usage nearby \u2014 excludes it from firing"),
@@ -1816,6 +1868,8 @@ async function memTried(input, ctx) {
1816
1868
  memory_id: frontmatter.id,
1817
1869
  kind: input.sensor.kind ?? "regex",
1818
1870
  pattern: input.sensor.pattern,
1871
+ rule: input.sensor.rule,
1872
+ language: input.sensor.language,
1819
1873
  command: input.sensor.command,
1820
1874
  timeout_ms: input.sensor.timeout_ms,
1821
1875
  absent: input.sensor.absent,
@@ -2109,7 +2163,7 @@ var SessionTracker = class {
2109
2163
  }
2110
2164
  let gitDiff;
2111
2165
  try {
2112
- const raw = execSync2("git diff HEAD", {
2166
+ const raw = execSync("git diff HEAD", {
2113
2167
  cwd: this.ctx.paths.root,
2114
2168
  timeout: 5e3,
2115
2169
  encoding: "utf8",
@@ -2141,7 +2195,7 @@ var SessionTracker = class {
2141
2195
  const triedThreads = this.events.filter((e) => e.tool === "mem_tried").map((e) => e.summary ?? "").filter(Boolean);
2142
2196
  let diffStat;
2143
2197
  try {
2144
- diffStat = execSync2("git diff --stat HEAD", {
2198
+ diffStat = execSync("git diff --stat HEAD", {
2145
2199
  cwd: this.ctx.paths.root,
2146
2200
  timeout: 5e3,
2147
2201
  encoding: "utf8",
@@ -2491,6 +2545,8 @@ var GetBriefingInputSchema = {
2491
2545
  ),
2492
2546
  include_stale: z20.boolean().default(false).describe("Include stale memories (excluded by default \u2014 they may be outdated)"),
2493
2547
  track: z20.boolean().default(true).describe("Increment read_count on returned memories"),
2548
+ memory_scopes: z20.array(z20.enum(["personal", "team", "module", "shared"])).optional().describe("Restrict the candidate corpus to selected scopes. Omit to include every scope."),
2549
+ deterministic: z20.boolean().optional().describe("Ignore machine-local usage/impact signals so repeated evaluations rank the shared corpus reproducibly."),
2494
2550
  format: z20.enum(["full", "compact", "actions"]).default("full").describe(
2495
2551
  "Output format: 'full' returns memory bodies (honors token budget via truncation); 'compact' returns a 1-line summary per memory (call mem_get for detail); 'actions' squeezes bodies to actionable bullet lines \u2014 fewer tokens vs full."
2496
2552
  ),
@@ -2519,9 +2575,11 @@ async function getBriefing(input, ctx) {
2519
2575
  let searchMode = "literal";
2520
2576
  let usage = { version: 1, updated_at: "", by_id: {} };
2521
2577
  let byId = /* @__PURE__ */ new Map();
2578
+ const allowedScopes = input.memory_scopes ? new Set(input.memory_scopes) : null;
2579
+ const scopeAllowed = (loaded) => allowedScopes === null || allowedScopes.has(loaded.memory.frontmatter.scope);
2522
2580
  let lastSession;
2523
2581
  if (existsSync22(ctx.paths.memoriesDir)) {
2524
- const allLoaded = await loadMemoriesFromDir17(ctx.paths.memoriesDir);
2582
+ const allLoaded = (await loadMemoriesFromDir17(ctx.paths.memoriesDir)).filter(scopeAllowed);
2525
2583
  const recaps = allLoaded.filter(({ memory }) => memory.frontmatter.type === "session_recap").sort(
2526
2584
  (a, b) => new Date(b.memory.frontmatter.created_at).getTime() - new Date(a.memory.frontmatter.created_at).getTime()
2527
2585
  );
@@ -2554,10 +2612,11 @@ async function getBriefing(input, ctx) {
2554
2612
  if (memoryHasExcludedTag(memory.frontmatter, excludeTags)) return false;
2555
2613
  return true;
2556
2614
  });
2557
- usage = await loadUsageIndex8(ctx.paths);
2615
+ usage = input.deterministic ? { version: 1, updated_at: "", by_id: {} } : await loadUsageIndex8(ctx.paths);
2558
2616
  byId = new Map(allMemories.map((m) => [m.memory.frontmatter.id, m]));
2559
- const semanticHits = input.task && input.semantic ? await trySemanticHits(ctx, input.task, allMemories.length * 2) : null;
2560
- if (input.task && input.semantic) {
2617
+ const semanticEnabled = input.semantic && input.deterministic !== true;
2618
+ const semanticHits = input.task && semanticEnabled ? await trySemanticHits(ctx, input.task, allMemories.length * 2) : null;
2619
+ if (input.task && semanticEnabled) {
2561
2620
  searchMode = semanticHits ? "semantic" : "literal_fallback";
2562
2621
  }
2563
2622
  const seen = /* @__PURE__ */ new Map();
@@ -2893,7 +2952,7 @@ ${m.content}`).join("\n\n---\n\n"),
2893
2952
  }
2894
2953
  }
2895
2954
  if (existsSync22(ctx.paths.memoriesDir)) {
2896
- const allMems = await loadMemoriesFromDir17(ctx.paths.memoriesDir);
2955
+ const allMems = (await loadMemoriesFromDir17(ctx.paths.memoriesDir)).filter(scopeAllowed);
2897
2956
  for (const { memory } of allMems) {
2898
2957
  const fm = memory.frontmatter;
2899
2958
  if (!fm.requires_human_approval) continue;
@@ -2950,7 +3009,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
2950
3009
  pcRaw = await readFile7(ctx.paths.projectContext, "utf8");
2951
3010
  } catch {
2952
3011
  }
2953
- const allForBootstrap = existsSync22(ctx.paths.memoriesDir) ? await loadMemoriesFromDir17(ctx.paths.memoriesDir) : [];
3012
+ const allForBootstrap = existsSync22(ctx.paths.memoriesDir) ? (await loadMemoriesFromDir17(ctx.paths.memoriesDir)).filter(scopeAllowed) : [];
2954
3013
  const cmForBootstrap = await loadCodeMap(ctx.paths);
2955
3014
  let existingModules = [];
2956
3015
  try {
@@ -2961,7 +3020,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
2961
3020
  const bootstrap = assessBootstrapState({
2962
3021
  projectContextRaw: pcRaw,
2963
3022
  memories: allForBootstrap,
2964
- codeFiles: cmForBootstrap ? Object.keys(cmForBootstrap.files) : [],
3023
+ codeFiles: cmForBootstrap ? Object.keys(cmForBootstrap.files).filter((file) => existsSync22(path13.join(ctx.paths.root, file))) : [],
2965
3024
  existingModules
2966
3025
  });
2967
3026
  if (bootstrap.state !== "ready" && bootstrap.metrics.mainAreas > 0) {
@@ -3152,7 +3211,7 @@ function oneLine(value) {
3152
3211
  return value.replace(/\s+/g, " ").replace(/"/g, '\\"').trim().slice(0, 120);
3153
3212
  }
3154
3213
  function serverVersion() {
3155
- return true ? "0.42.1" : "dev";
3214
+ return true ? "0.43.2" : "dev";
3156
3215
  }
3157
3216
  var CodeMapInputSchema = {
3158
3217
  file: z21.string().optional().describe("Filter to files whose path contains this substring"),
@@ -4260,7 +4319,7 @@ async function currentAssessment(ctx) {
4260
4319
  return assessBootstrapState2({
4261
4320
  projectContextRaw,
4262
4321
  memories,
4263
- codeFiles: codeMap ? Object.keys(codeMap.files) : [],
4322
+ codeFiles: codeMap ? Object.keys(codeMap.files).filter((file) => existsSync29(path14.join(ctx.paths.root, file))) : [],
4264
4323
  existingModules
4265
4324
  });
4266
4325
  }
@@ -4479,7 +4538,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
4479
4538
  };
4480
4539
  }
4481
4540
  var SERVER_NAME = "hivelore";
4482
- var SERVER_VERSION = "0.42.1";
4541
+ var SERVER_VERSION = "0.43.2";
4483
4542
  function jsonResult(data) {
4484
4543
  return {
4485
4544
  content: [
@@ -5459,4 +5518,4 @@ export {
5459
5518
  printHaiveMcpVersion,
5460
5519
  runHaiveMcpStdio
5461
5520
  };
5462
- //# sourceMappingURL=chunk-EJ7A4IKD.js.map
5521
+ //# sourceMappingURL=chunk-FXDGOBPT.js.map