@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.
- package/dist/{chunk-EJ7A4IKD.js → chunk-FXDGOBPT.js} +97 -38
- package/dist/chunk-FXDGOBPT.js.map +1 -0
- package/dist/index.js +169 -37
- package/dist/index.js.map +1 -1
- package/dist/{server-PZWIQUU7.js → server-WW6JHBYY.js} +2 -2
- package/package.json +9 -5
- package/dist/chunk-EJ7A4IKD.js.map +0 -1
- /package/dist/{server-PZWIQUU7.js.map → server-WW6JHBYY.js.map} +0 -0
|
@@ -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 {
|
|
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
|
|
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
|
-
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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`
|
|
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
|
|
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." : "
|
|
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
|
|
1769
|
-
pattern: z16.string().optional().describe("kind=regex:
|
|
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 =
|
|
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 =
|
|
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
|
|
2560
|
-
|
|
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.
|
|
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.
|
|
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-
|
|
5521
|
+
//# sourceMappingURL=chunk-FXDGOBPT.js.map
|