@hivelore/mcp 0.42.1 → 0.44.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/README.md +1 -1
- package/dist/index.js +132 -42
- package/dist/index.js.map +1 -1
- package/dist/server.d.ts +26 -7
- package/dist/server.js +134 -43
- package/dist/server.js.map +1 -1
- package/package.json +21 -4
package/dist/server.d.ts
CHANGED
|
@@ -192,6 +192,8 @@ declare const GetBriefingZod: z.ZodObject<{
|
|
|
192
192
|
semantic: z.ZodDefault<z.ZodBoolean>;
|
|
193
193
|
include_stale: z.ZodDefault<z.ZodBoolean>;
|
|
194
194
|
track: z.ZodDefault<z.ZodBoolean>;
|
|
195
|
+
memory_scopes: z.ZodOptional<z.ZodArray<z.ZodEnum<["personal", "team", "module", "shared"]>, "many">>;
|
|
196
|
+
deterministic: z.ZodOptional<z.ZodBoolean>;
|
|
195
197
|
format: z.ZodDefault<z.ZodEnum<["full", "compact", "actions"]>>;
|
|
196
198
|
symbols: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
197
199
|
min_semantic_score: z.ZodDefault<z.ZodNumber>;
|
|
@@ -210,6 +212,8 @@ declare const GetBriefingZod: z.ZodObject<{
|
|
|
210
212
|
min_semantic_score: number;
|
|
211
213
|
task?: string | undefined;
|
|
212
214
|
dedupe_project_context?: boolean | undefined;
|
|
215
|
+
memory_scopes?: ("personal" | "team" | "module" | "shared")[] | undefined;
|
|
216
|
+
deterministic?: boolean | undefined;
|
|
213
217
|
budget_preset?: "quick" | "balanced" | "deep" | undefined;
|
|
214
218
|
}, {
|
|
215
219
|
symbols?: string[] | undefined;
|
|
@@ -224,6 +228,8 @@ declare const GetBriefingZod: z.ZodObject<{
|
|
|
224
228
|
semantic?: boolean | undefined;
|
|
225
229
|
include_stale?: boolean | undefined;
|
|
226
230
|
track?: boolean | undefined;
|
|
231
|
+
memory_scopes?: ("personal" | "team" | "module" | "shared")[] | undefined;
|
|
232
|
+
deterministic?: boolean | undefined;
|
|
227
233
|
min_semantic_score?: number | undefined;
|
|
228
234
|
budget_preset?: "quick" | "balanced" | "deep" | undefined;
|
|
229
235
|
}>;
|
|
@@ -359,6 +365,7 @@ interface AntiPatternsCheckInput {
|
|
|
359
365
|
limit: number;
|
|
360
366
|
semantic: boolean;
|
|
361
367
|
min_semantic_score?: number;
|
|
368
|
+
track?: boolean;
|
|
362
369
|
}
|
|
363
370
|
interface AntiPatternsWarning {
|
|
364
371
|
id: string;
|
|
@@ -509,6 +516,8 @@ declare const ProposeSensorInputSchema: {
|
|
|
509
516
|
memory_id: z.ZodString;
|
|
510
517
|
kind: z.ZodDefault<z.ZodEnum<["regex", "ast", "shell", "test"]>>;
|
|
511
518
|
pattern: z.ZodOptional<z.ZodString>;
|
|
519
|
+
rule: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
520
|
+
language: z.ZodOptional<z.ZodString>;
|
|
512
521
|
command: z.ZodOptional<z.ZodString>;
|
|
513
522
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
514
523
|
absent: z.ZodOptional<z.ZodString>;
|
|
@@ -561,22 +570,25 @@ interface AstScanResult {
|
|
|
561
570
|
matches: AstMatch[];
|
|
562
571
|
detail?: string;
|
|
563
572
|
}
|
|
573
|
+
type AstRule = Record<string, unknown>;
|
|
564
574
|
declare function astEngineAvailable(): Promise<boolean>;
|
|
565
575
|
/** Map a file extension to a built-in ast-grep language. Unknown → null (unsupported, warn only). */
|
|
566
|
-
declare function astLangForPath(filePath: string):
|
|
576
|
+
declare function astLangForPath(filePath: string, explicitLanguage?: string): string | null;
|
|
567
577
|
/**
|
|
568
578
|
* Run one AST pattern (with optional `absent` sub-pattern) over a file's FULL content.
|
|
569
579
|
* A match is suppressed when `absent` matches INSIDE the matched node — the structural version of
|
|
570
580
|
* the regex `absent` window: the required companion lives in the call's own arguments.
|
|
571
581
|
*/
|
|
572
|
-
declare function runAstPattern(content: string, filePath: string, pattern
|
|
582
|
+
declare function runAstPattern(content: string, filePath: string, pattern?: string, absent?: string, rule?: AstRule, language?: string): Promise<AstScanResult>;
|
|
573
583
|
/**
|
|
574
584
|
* Gate-side evaluation: matches on the full content, FIRES only when a match intersects the added
|
|
575
585
|
* lines (introduction, not mere presence). `addedLines` empty/undefined = validation mode (any
|
|
576
586
|
* match counts — used for silent-on-current / fires-on-bad checks).
|
|
577
587
|
*/
|
|
578
588
|
declare function runAstSensorOnContent(input: {
|
|
579
|
-
pattern
|
|
589
|
+
pattern?: string;
|
|
590
|
+
rule?: AstRule;
|
|
591
|
+
language?: string;
|
|
580
592
|
absent?: string;
|
|
581
593
|
content: string;
|
|
582
594
|
filePath: string;
|
|
@@ -593,8 +605,10 @@ declare const MemTriedInputSchema: {
|
|
|
593
605
|
paths: z.ZodDefault<z.ZodArray<z.ZodString, "many">>;
|
|
594
606
|
author: z.ZodOptional<z.ZodString>;
|
|
595
607
|
sensor: z.ZodOptional<z.ZodObject<{
|
|
596
|
-
kind: z.ZodDefault<z.ZodEnum<["regex", "shell", "test"]>>;
|
|
608
|
+
kind: z.ZodDefault<z.ZodEnum<["regex", "ast", "shell", "test"]>>;
|
|
597
609
|
pattern: z.ZodOptional<z.ZodString>;
|
|
610
|
+
rule: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
611
|
+
language: z.ZodOptional<z.ZodString>;
|
|
598
612
|
command: z.ZodOptional<z.ZodString>;
|
|
599
613
|
timeout_ms: z.ZodOptional<z.ZodNumber>;
|
|
600
614
|
absent: z.ZodOptional<z.ZodString>;
|
|
@@ -604,10 +618,12 @@ declare const MemTriedInputSchema: {
|
|
|
604
618
|
red_ref: z.ZodOptional<z.ZodString>;
|
|
605
619
|
bad_example: z.ZodOptional<z.ZodString>;
|
|
606
620
|
}, "strip", z.ZodTypeAny, {
|
|
607
|
-
kind: "regex" | "shell" | "test";
|
|
621
|
+
kind: "regex" | "ast" | "shell" | "test";
|
|
608
622
|
severity: "warn" | "block";
|
|
609
623
|
pattern?: string | undefined;
|
|
610
624
|
message?: string | undefined;
|
|
625
|
+
rule?: Record<string, unknown> | undefined;
|
|
626
|
+
language?: string | undefined;
|
|
611
627
|
command?: string | undefined;
|
|
612
628
|
timeout_ms?: number | undefined;
|
|
613
629
|
absent?: string | undefined;
|
|
@@ -617,7 +633,9 @@ declare const MemTriedInputSchema: {
|
|
|
617
633
|
}, {
|
|
618
634
|
pattern?: string | undefined;
|
|
619
635
|
message?: string | undefined;
|
|
620
|
-
kind?: "regex" | "shell" | "test" | undefined;
|
|
636
|
+
kind?: "regex" | "ast" | "shell" | "test" | undefined;
|
|
637
|
+
rule?: Record<string, unknown> | undefined;
|
|
638
|
+
language?: string | undefined;
|
|
621
639
|
command?: string | undefined;
|
|
622
640
|
timeout_ms?: number | undefined;
|
|
623
641
|
absent?: string | undefined;
|
|
@@ -817,5 +835,6 @@ declare function printHaiveMcpVersion(): void;
|
|
|
817
835
|
declare function runHaiveMcpStdio(options: {
|
|
818
836
|
root?: string;
|
|
819
837
|
}): Promise<void>;
|
|
838
|
+
declare function writeMcpRuntimeMarker(context: HaiveContext): Promise<void>;
|
|
820
839
|
|
|
821
|
-
export { type AnchorFrameworkGroup, type AntiPatternsCheckInput, type AntiPatternsCheckOutput, type AstMatch, type AstScanResult, type BriefingOutput, type CodeMapInput, type CodeMapToolOutput, type CodeSearchInput, type CodeSearchOutput, ENFORCEMENT_PROFILE_TOOLS, EXPERIMENTAL_PROFILE_TOOLS, type GetBriefingInput, type GetRecapInput, type GetRecapOutput, MAINTENANCE_PROFILE_TOOLS, type MemConflictCandidatesInput, type MemDistillInput, type MemDistillOutput, type MemRelevantToInput, type MemRelevantToOutput, type MemResolveProjectInput, type MemSuggestTopicInput, type MemTimelineInput, type MemTriedOutput, type PreCommitCheckInput, type PreCommitCheckOutput, type ProposeSensorOutput, SERVER_NAME, SERVER_VERSION, type ScaffoldTestOutput, TOOL_PROFILES, type ToolProfile, antiPatternsCheck, astEngineAvailable, astLangForPath, codeMapTool, codeSearch, createHaiveServer, detectTestFrameworkForPaths, detectTestFrameworksForAnchors, getAllowedToolsForProfile, getBriefing, getRecap, memConflictCandidates, memDistill, memRelevantTo, memResolveProject, memSuggestTopic, memTimeline, memTried, parseMcpCliArgs, preCommitCheck, printHaiveMcpVersion, proposeSensor, readPresumedCorrectTargets, runAstPattern, runAstSensorOnContent, runHaiveMcpStdio, scaffoldTest };
|
|
840
|
+
export { type AnchorFrameworkGroup, type AntiPatternsCheckInput, type AntiPatternsCheckOutput, type AstMatch, type AstScanResult, type BriefingOutput, type CodeMapInput, type CodeMapToolOutput, type CodeSearchInput, type CodeSearchOutput, ENFORCEMENT_PROFILE_TOOLS, EXPERIMENTAL_PROFILE_TOOLS, type GetBriefingInput, type GetRecapInput, type GetRecapOutput, MAINTENANCE_PROFILE_TOOLS, type MemConflictCandidatesInput, type MemDistillInput, type MemDistillOutput, type MemRelevantToInput, type MemRelevantToOutput, type MemResolveProjectInput, type MemSuggestTopicInput, type MemTimelineInput, type MemTriedOutput, type PreCommitCheckInput, type PreCommitCheckOutput, type ProposeSensorOutput, SERVER_NAME, SERVER_VERSION, type ScaffoldTestOutput, TOOL_PROFILES, type ToolProfile, antiPatternsCheck, astEngineAvailable, astLangForPath, codeMapTool, codeSearch, createHaiveServer, detectTestFrameworkForPaths, detectTestFrameworksForAnchors, getAllowedToolsForProfile, getBriefing, getRecap, memConflictCandidates, memDistill, memRelevantTo, memResolveProject, memSuggestTopic, memTimeline, memTried, parseMcpCliArgs, preCommitCheck, printHaiveMcpVersion, proposeSensor, readPresumedCorrectTargets, runAstPattern, runAstSensorOnContent, runHaiveMcpStdio, scaffoldTest, writeMcpRuntimeMarker };
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/server.ts
|
|
2
2
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { mkdir as mkdir8, writeFile as writeFile15 } from "fs/promises";
|
|
5
|
+
import path15 from "path";
|
|
4
6
|
|
|
5
7
|
// src/context.ts
|
|
6
8
|
import { findProjectRoot, resolveHaivePaths } from "@hivelore/core";
|
|
@@ -1132,7 +1134,7 @@ import {
|
|
|
1132
1134
|
import { z as z16 } from "zod";
|
|
1133
1135
|
|
|
1134
1136
|
// src/tools/propose-sensor.ts
|
|
1135
|
-
import {
|
|
1137
|
+
import { execFileSync } from "child_process";
|
|
1136
1138
|
import { readFile as readFile3, writeFile as writeFile8 } from "fs/promises";
|
|
1137
1139
|
import { existsSync as existsSync15, rmSync, symlinkSync } from "fs";
|
|
1138
1140
|
import os from "os";
|
|
@@ -1152,10 +1154,32 @@ import { z as z15 } from "zod";
|
|
|
1152
1154
|
// src/ast-sensors.ts
|
|
1153
1155
|
import path5 from "path";
|
|
1154
1156
|
var cachedEngine;
|
|
1157
|
+
var registeredDynamicLanguages = /* @__PURE__ */ new Set();
|
|
1158
|
+
async function loadDynamicLanguages(engine) {
|
|
1159
|
+
const registrations = {};
|
|
1160
|
+
const candidates = [
|
|
1161
|
+
["python", () => import("@ast-grep/lang-python")],
|
|
1162
|
+
["go", () => import("@ast-grep/lang-go")],
|
|
1163
|
+
["rust", () => import("@ast-grep/lang-rust")],
|
|
1164
|
+
["java", () => import("@ast-grep/lang-java")]
|
|
1165
|
+
];
|
|
1166
|
+
for (const [name, load] of candidates) {
|
|
1167
|
+
try {
|
|
1168
|
+
const mod = await load();
|
|
1169
|
+
registrations[name] = mod.default;
|
|
1170
|
+
registeredDynamicLanguages.add(name);
|
|
1171
|
+
} catch {
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
if (Object.keys(registrations).length > 0) {
|
|
1175
|
+
engine.registerDynamicLanguage(registrations);
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1155
1178
|
async function loadAstEngine() {
|
|
1156
1179
|
if (cachedEngine !== void 0) return cachedEngine;
|
|
1157
1180
|
try {
|
|
1158
1181
|
cachedEngine = await import("@ast-grep/napi");
|
|
1182
|
+
await loadDynamicLanguages(cachedEngine);
|
|
1159
1183
|
} catch {
|
|
1160
1184
|
cachedEngine = null;
|
|
1161
1185
|
}
|
|
@@ -1164,11 +1188,22 @@ async function loadAstEngine() {
|
|
|
1164
1188
|
async function astEngineAvailable() {
|
|
1165
1189
|
return await loadAstEngine() !== null;
|
|
1166
1190
|
}
|
|
1167
|
-
function astLangForPath(filePath) {
|
|
1191
|
+
function astLangForPath(filePath, explicitLanguage) {
|
|
1192
|
+
if (explicitLanguage) {
|
|
1193
|
+
const normalized = explicitLanguage.toLowerCase();
|
|
1194
|
+
if (["typescript", "tsx", "javascript", "html", "css"].includes(normalized)) {
|
|
1195
|
+
return normalized === "typescript" ? "TypeScript" : normalized === "tsx" ? "Tsx" : normalized === "javascript" ? "JavaScript" : normalized[0].toUpperCase() + normalized.slice(1);
|
|
1196
|
+
}
|
|
1197
|
+
return registeredDynamicLanguages.has(normalized) ? normalized : null;
|
|
1198
|
+
}
|
|
1168
1199
|
const ext = path5.extname(filePath).toLowerCase();
|
|
1169
1200
|
if (ext === ".ts" || ext === ".mts" || ext === ".cts") return "TypeScript";
|
|
1170
1201
|
if (ext === ".tsx") return "Tsx";
|
|
1171
1202
|
if (ext === ".js" || ext === ".jsx" || ext === ".mjs" || ext === ".cjs") return "JavaScript";
|
|
1203
|
+
if (ext === ".py" && registeredDynamicLanguages.has("python")) return "python";
|
|
1204
|
+
if (ext === ".go" && registeredDynamicLanguages.has("go")) return "go";
|
|
1205
|
+
if (ext === ".rs" && registeredDynamicLanguages.has("rust")) return "rust";
|
|
1206
|
+
if (ext === ".java" && registeredDynamicLanguages.has("java")) return "java";
|
|
1172
1207
|
return null;
|
|
1173
1208
|
}
|
|
1174
1209
|
function absentPresentInNode(node, absent) {
|
|
@@ -1183,12 +1218,12 @@ function absentPresentInNode(node, absent) {
|
|
|
1183
1218
|
return text.includes(absent);
|
|
1184
1219
|
}
|
|
1185
1220
|
}
|
|
1186
|
-
async function runAstPattern(content, filePath, pattern, absent) {
|
|
1221
|
+
async function runAstPattern(content, filePath, pattern, absent, rule, language) {
|
|
1187
1222
|
const engine = await loadAstEngine();
|
|
1188
1223
|
if (!engine) return { status: "engine-missing", matches: [] };
|
|
1189
|
-
const langName = astLangForPath(filePath);
|
|
1224
|
+
const langName = astLangForPath(filePath, language);
|
|
1190
1225
|
if (!langName) return { status: "unsupported-language", matches: [] };
|
|
1191
|
-
const lang = engine.Lang[langName];
|
|
1226
|
+
const lang = langName in engine.Lang ? engine.Lang[langName] : langName;
|
|
1192
1227
|
let root;
|
|
1193
1228
|
try {
|
|
1194
1229
|
root = engine.parse(lang, content).root();
|
|
@@ -1197,7 +1232,9 @@ async function runAstPattern(content, filePath, pattern, absent) {
|
|
|
1197
1232
|
}
|
|
1198
1233
|
let nodes;
|
|
1199
1234
|
try {
|
|
1200
|
-
|
|
1235
|
+
const matcher = rule ? { rule: pattern ? { all: [{ pattern }, rule] } : rule } : pattern;
|
|
1236
|
+
if (!matcher) return { status: "invalid-pattern", matches: [], detail: "missing pattern/rule" };
|
|
1237
|
+
nodes = root.findAll(matcher);
|
|
1201
1238
|
} catch (err) {
|
|
1202
1239
|
return { status: "invalid-pattern", matches: [], detail: String(err).slice(0, 200) };
|
|
1203
1240
|
}
|
|
@@ -1214,7 +1251,7 @@ async function runAstPattern(content, filePath, pattern, absent) {
|
|
|
1214
1251
|
return { status: "ok", matches };
|
|
1215
1252
|
}
|
|
1216
1253
|
async function runAstSensorOnContent(input) {
|
|
1217
|
-
const scan = await runAstPattern(input.content, input.filePath, input.pattern, input.absent);
|
|
1254
|
+
const scan = await runAstPattern(input.content, input.filePath, input.pattern, input.absent, input.rule, input.language);
|
|
1218
1255
|
if (scan.status !== "ok" || !input.addedLines || input.addedLines.size === 0) return scan;
|
|
1219
1256
|
const added = input.addedLines;
|
|
1220
1257
|
return {
|
|
@@ -1234,7 +1271,9 @@ var ProposeSensorInputSchema = {
|
|
|
1234
1271
|
kind: z15.enum(["regex", "ast", "shell", "test"]).default("regex").describe(
|
|
1235
1272
|
"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."
|
|
1236
1273
|
),
|
|
1237
|
-
pattern: z15.string().optional().describe("kind=regex: regex matching the
|
|
1274
|
+
pattern: z15.string().optional().describe("kind=regex: regex matching the faulty usage; kind=ast: optional structural pattern (may be combined with `rule`)."),
|
|
1275
|
+
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."),
|
|
1276
|
+
language: z15.string().optional().describe("kind=ast: explicit built-in/dynamic language name for non-standard file extensions."),
|
|
1238
1277
|
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."),
|
|
1239
1278
|
timeout_ms: z15.number().int().positive().optional().describe("kind=shell|test: max runtime before the executor kills the command (default 120000)."),
|
|
1240
1279
|
absent: z15.string().optional().describe(
|
|
@@ -1265,7 +1304,7 @@ async function readPresumedCorrectTargets(root, relPaths) {
|
|
|
1265
1304
|
const targets = [];
|
|
1266
1305
|
for (const rel of relPaths) {
|
|
1267
1306
|
try {
|
|
1268
|
-
const content =
|
|
1307
|
+
const content = execFileSync("git", ["show", `HEAD:./${rel}`], {
|
|
1269
1308
|
cwd: root,
|
|
1270
1309
|
encoding: "utf8",
|
|
1271
1310
|
maxBuffer: 10 * 1024 * 1024,
|
|
@@ -1286,7 +1325,7 @@ async function readPresumedCorrectTargets(root, relPaths) {
|
|
|
1286
1325
|
}
|
|
1287
1326
|
function runCommandForValidation(command, root, timeoutMs = 12e4) {
|
|
1288
1327
|
try {
|
|
1289
|
-
|
|
1328
|
+
execFileSync("bash", ["-c", command], {
|
|
1290
1329
|
cwd: root,
|
|
1291
1330
|
timeout: timeoutMs,
|
|
1292
1331
|
maxBuffer: 8 * 1024 * 1024,
|
|
@@ -1311,7 +1350,7 @@ function proveRedOnIncident(command, root, redRef, timeoutMs) {
|
|
|
1311
1350
|
let added = false;
|
|
1312
1351
|
try {
|
|
1313
1352
|
try {
|
|
1314
|
-
|
|
1353
|
+
execFileSync("git", ["worktree", "add", "--detach", worktree, redRef], {
|
|
1315
1354
|
cwd: root,
|
|
1316
1355
|
stdio: ["ignore", "pipe", "pipe"],
|
|
1317
1356
|
timeout: 6e4
|
|
@@ -1338,7 +1377,7 @@ function proveRedOnIncident(command, root, redRef, timeoutMs) {
|
|
|
1338
1377
|
} finally {
|
|
1339
1378
|
if (added) {
|
|
1340
1379
|
try {
|
|
1341
|
-
|
|
1380
|
+
execFileSync("git", ["worktree", "remove", "--force", worktree], { cwd: root, stdio: "ignore", timeout: 6e4 });
|
|
1342
1381
|
} catch {
|
|
1343
1382
|
try {
|
|
1344
1383
|
rmSync(worktree, { recursive: true, force: true });
|
|
@@ -1378,13 +1417,13 @@ async function proposeSensor(input, ctx) {
|
|
|
1378
1417
|
};
|
|
1379
1418
|
}
|
|
1380
1419
|
} else if (kind === "ast") {
|
|
1381
|
-
if (!input.pattern?.trim()) {
|
|
1420
|
+
if (!input.pattern?.trim() && !input.rule) {
|
|
1382
1421
|
return {
|
|
1383
1422
|
accepted: false,
|
|
1384
1423
|
memory_id: input.memory_id,
|
|
1385
1424
|
severity: input.severity,
|
|
1386
1425
|
reason: "invalid-pattern",
|
|
1387
|
-
guidance: "kind=ast requires a `pattern`
|
|
1426
|
+
guidance: "kind=ast requires a structural `pattern` or a full ast-grep `rule` object.",
|
|
1388
1427
|
self_check: { silent_on_current: false, fires_on_bad: null, fired_on: [] }
|
|
1389
1428
|
};
|
|
1390
1429
|
}
|
|
@@ -1405,7 +1444,7 @@ async function proposeSensor(input, ctx) {
|
|
|
1405
1444
|
}
|
|
1406
1445
|
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}.` : "";
|
|
1407
1446
|
if (kind === "ast") {
|
|
1408
|
-
const pattern = input.pattern
|
|
1447
|
+
const pattern = input.pattern?.trim();
|
|
1409
1448
|
if (!await astEngineAvailable() && input.severity === "block") {
|
|
1410
1449
|
return {
|
|
1411
1450
|
accepted: false,
|
|
@@ -1416,7 +1455,7 @@ async function proposeSensor(input, ctx) {
|
|
|
1416
1455
|
self_check: { silent_on_current: false, fires_on_bad: null, fired_on: [] }
|
|
1417
1456
|
};
|
|
1418
1457
|
}
|
|
1419
|
-
const brittleAst = sensorPatternBrittleness(pattern);
|
|
1458
|
+
const brittleAst = pattern ? sensorPatternBrittleness(pattern) : null;
|
|
1420
1459
|
if (brittleAst && input.severity === "block") {
|
|
1421
1460
|
return {
|
|
1422
1461
|
accepted: false,
|
|
@@ -1431,7 +1470,7 @@ async function proposeSensor(input, ctx) {
|
|
|
1431
1470
|
const currentTargetsAst = await readPresumedCorrectTargets(ctx.paths.root, anchorPathsAst);
|
|
1432
1471
|
const firedOnAst = [];
|
|
1433
1472
|
for (const target of currentTargetsAst) {
|
|
1434
|
-
const scan = await runAstSensorOnContent({ pattern, absent: input.absent, content: target.content, filePath: target.path });
|
|
1473
|
+
const scan = await runAstSensorOnContent({ pattern, rule: input.rule, language: input.language, absent: input.absent, content: target.content, filePath: target.path });
|
|
1435
1474
|
if (scan.status === "invalid-pattern") {
|
|
1436
1475
|
return {
|
|
1437
1476
|
accepted: false,
|
|
@@ -1460,10 +1499,10 @@ async function proposeSensor(input, ctx) {
|
|
|
1460
1499
|
];
|
|
1461
1500
|
let firesOnBadAst = null;
|
|
1462
1501
|
if (badExamplesAst.length > 0 && await astEngineAvailable()) {
|
|
1463
|
-
const exampleLang = anchorPathsAst.find((p) => astLangForPath(p) !== null) ?? "example.tsx";
|
|
1502
|
+
const exampleLang = anchorPathsAst.find((p) => astLangForPath(p, input.language) !== null) ?? "example.tsx";
|
|
1464
1503
|
firesOnBadAst = false;
|
|
1465
1504
|
for (const example of badExamplesAst) {
|
|
1466
|
-
const scan = await runAstSensorOnContent({ pattern, absent: input.absent, content: example, filePath: exampleLang });
|
|
1505
|
+
const scan = await runAstSensorOnContent({ pattern, rule: input.rule, language: input.language, absent: input.absent, content: example, filePath: exampleLang });
|
|
1467
1506
|
if (scan.status === "ok" && scan.matches.length > 0) {
|
|
1468
1507
|
firesOnBadAst = true;
|
|
1469
1508
|
break;
|
|
@@ -1482,10 +1521,12 @@ async function proposeSensor(input, ctx) {
|
|
|
1482
1521
|
}
|
|
1483
1522
|
const sensorAst = {
|
|
1484
1523
|
kind: "ast",
|
|
1485
|
-
pattern,
|
|
1524
|
+
...pattern ? { pattern } : {},
|
|
1525
|
+
...input.rule ? { rule: input.rule } : {},
|
|
1526
|
+
...input.language ? { language: input.language } : {},
|
|
1486
1527
|
...input.absent ? { absent: input.absent } : {},
|
|
1487
1528
|
paths: anchorPathsAst,
|
|
1488
|
-
message: input.message?.trim() || deriveMessage(found.memory.body, pattern, input.absent),
|
|
1529
|
+
message: input.message?.trim() || deriveMessage(found.memory.body, pattern ?? "AST rule", input.absent),
|
|
1489
1530
|
...input.incident?.trim() ? { incident: input.incident.trim() } : {},
|
|
1490
1531
|
severity: input.severity,
|
|
1491
1532
|
autogen: false,
|
|
@@ -1548,6 +1589,16 @@ ${verdictCmd.detail}`,
|
|
|
1548
1589
|
self_check: { silent_on_current: false, fires_on_bad: null, fired_on: anchorPathsCmd }
|
|
1549
1590
|
};
|
|
1550
1591
|
}
|
|
1592
|
+
if (input.severity === "block" && !input.red_ref?.trim()) {
|
|
1593
|
+
return {
|
|
1594
|
+
accepted: false,
|
|
1595
|
+
memory_id: input.memory_id,
|
|
1596
|
+
severity: input.severity,
|
|
1597
|
+
reason: "red-required",
|
|
1598
|
+
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.",
|
|
1599
|
+
self_check: { silent_on_current: true, fires_on_bad: null, fired_on: [] }
|
|
1600
|
+
};
|
|
1601
|
+
}
|
|
1551
1602
|
const sensorCmd = {
|
|
1552
1603
|
kind,
|
|
1553
1604
|
command: input.command.trim(),
|
|
@@ -1569,7 +1620,7 @@ ${verdictCmd.detail}`,
|
|
|
1569
1620
|
accepted: true,
|
|
1570
1621
|
memory_id: input.memory_id,
|
|
1571
1622
|
severity: input.severity,
|
|
1572
|
-
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." : "
|
|
1623
|
+
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,
|
|
1573
1624
|
self_check: { silent_on_current: verdictCmd.status === "passed", fires_on_bad: redProven ? true : null, fired_on: [] },
|
|
1574
1625
|
file_path: found.filePath
|
|
1575
1626
|
};
|
|
@@ -1638,8 +1689,10 @@ var MemTriedInputSchema = {
|
|
|
1638
1689
|
paths: z16.array(z16.string()).default([]).describe("Anchor file paths this applies to"),
|
|
1639
1690
|
author: z16.string().optional().describe("Author handle or email"),
|
|
1640
1691
|
sensor: z16.object({
|
|
1641
|
-
kind: z16.enum(["regex", "shell", "test"]).default("regex").describe("regex pattern, or a shell/test
|
|
1642
|
-
pattern: z16.string().optional().describe("kind=regex:
|
|
1692
|
+
kind: z16.enum(["regex", "ast", "shell", "test"]).default("regex").describe("regex/AST pattern, or a shell/test command"),
|
|
1693
|
+
pattern: z16.string().optional().describe("kind=regex|ast: pattern matching the faulty usage"),
|
|
1694
|
+
rule: z16.record(z16.unknown()).optional().describe("kind=ast: full ast-grep Rule object"),
|
|
1695
|
+
language: z16.string().optional().describe("kind=ast: explicit built-in/dynamic language"),
|
|
1643
1696
|
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)"),
|
|
1644
1697
|
timeout_ms: z16.number().int().positive().optional().describe("kind=shell|test: max runtime (default 120000)"),
|
|
1645
1698
|
absent: z16.string().optional().describe("kind=regex: regex marking CORRECT usage nearby \u2014 excludes it from firing"),
|
|
@@ -1689,6 +1742,8 @@ async function memTried(input, ctx) {
|
|
|
1689
1742
|
memory_id: frontmatter.id,
|
|
1690
1743
|
kind: input.sensor.kind ?? "regex",
|
|
1691
1744
|
pattern: input.sensor.pattern,
|
|
1745
|
+
rule: input.sensor.rule,
|
|
1746
|
+
language: input.sensor.language,
|
|
1692
1747
|
command: input.sensor.command,
|
|
1693
1748
|
timeout_ms: input.sensor.timeout_ms,
|
|
1694
1749
|
absent: input.sensor.absent,
|
|
@@ -1991,7 +2046,7 @@ import {
|
|
|
1991
2046
|
import { mkdir as mkdir6, writeFile as writeFile12, rm } from "fs/promises";
|
|
1992
2047
|
import { existsSync as existsSync19 } from "fs";
|
|
1993
2048
|
import path10 from "path";
|
|
1994
|
-
import { execSync
|
|
2049
|
+
import { execSync } from "child_process";
|
|
1995
2050
|
function pendingDistillPath(ctx) {
|
|
1996
2051
|
return path10.join(ctx.paths.haiveDir, ".cache", "pending-distill.json");
|
|
1997
2052
|
}
|
|
@@ -2034,7 +2089,7 @@ var SessionTracker = class {
|
|
|
2034
2089
|
}
|
|
2035
2090
|
let gitDiff;
|
|
2036
2091
|
try {
|
|
2037
|
-
const raw =
|
|
2092
|
+
const raw = execSync("git diff HEAD", {
|
|
2038
2093
|
cwd: this.ctx.paths.root,
|
|
2039
2094
|
timeout: 5e3,
|
|
2040
2095
|
encoding: "utf8",
|
|
@@ -2066,7 +2121,7 @@ var SessionTracker = class {
|
|
|
2066
2121
|
const triedThreads = this.events.filter((e) => e.tool === "mem_tried").map((e) => e.summary ?? "").filter(Boolean);
|
|
2067
2122
|
let diffStat;
|
|
2068
2123
|
try {
|
|
2069
|
-
diffStat =
|
|
2124
|
+
diffStat = execSync("git diff --stat HEAD", {
|
|
2070
2125
|
cwd: this.ctx.paths.root,
|
|
2071
2126
|
timeout: 5e3,
|
|
2072
2127
|
encoding: "utf8",
|
|
@@ -2478,6 +2533,8 @@ var GetBriefingInputSchema = {
|
|
|
2478
2533
|
),
|
|
2479
2534
|
include_stale: z20.boolean().default(false).describe("Include stale memories (excluded by default \u2014 they may be outdated)"),
|
|
2480
2535
|
track: z20.boolean().default(true).describe("Increment read_count on returned memories"),
|
|
2536
|
+
memory_scopes: z20.array(z20.enum(["personal", "team", "module", "shared"])).optional().describe("Restrict the candidate corpus to selected scopes. Omit to include every scope."),
|
|
2537
|
+
deterministic: z20.boolean().optional().describe("Ignore machine-local usage/impact signals so repeated evaluations rank the shared corpus reproducibly."),
|
|
2481
2538
|
format: z20.enum(["full", "compact", "actions"]).default("full").describe(
|
|
2482
2539
|
"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."
|
|
2483
2540
|
),
|
|
@@ -2506,9 +2563,11 @@ async function getBriefing(input, ctx) {
|
|
|
2506
2563
|
let searchMode = "literal";
|
|
2507
2564
|
let usage = { version: 1, updated_at: "", by_id: {} };
|
|
2508
2565
|
let byId = /* @__PURE__ */ new Map();
|
|
2566
|
+
const allowedScopes = input.memory_scopes ? new Set(input.memory_scopes) : null;
|
|
2567
|
+
const scopeAllowed = (loaded) => allowedScopes === null || allowedScopes.has(loaded.memory.frontmatter.scope);
|
|
2509
2568
|
let lastSession;
|
|
2510
2569
|
if (existsSync22(ctx.paths.memoriesDir)) {
|
|
2511
|
-
const allLoaded = await loadMemoriesFromDir17(ctx.paths.memoriesDir);
|
|
2570
|
+
const allLoaded = (await loadMemoriesFromDir17(ctx.paths.memoriesDir)).filter(scopeAllowed);
|
|
2512
2571
|
const recaps = allLoaded.filter(({ memory }) => memory.frontmatter.type === "session_recap").sort(
|
|
2513
2572
|
(a, b) => new Date(b.memory.frontmatter.created_at).getTime() - new Date(a.memory.frontmatter.created_at).getTime()
|
|
2514
2573
|
);
|
|
@@ -2541,10 +2600,11 @@ async function getBriefing(input, ctx) {
|
|
|
2541
2600
|
if (memoryHasExcludedTag(memory.frontmatter, excludeTags)) return false;
|
|
2542
2601
|
return true;
|
|
2543
2602
|
});
|
|
2544
|
-
usage = await loadUsageIndex8(ctx.paths);
|
|
2603
|
+
usage = input.deterministic ? { version: 1, updated_at: "", by_id: {} } : await loadUsageIndex8(ctx.paths);
|
|
2545
2604
|
byId = new Map(allMemories.map((m) => [m.memory.frontmatter.id, m]));
|
|
2546
|
-
const
|
|
2547
|
-
|
|
2605
|
+
const semanticEnabled = input.semantic && input.deterministic !== true;
|
|
2606
|
+
const semanticHits = input.task && semanticEnabled ? await trySemanticHits(ctx, input.task, allMemories.length * 2) : null;
|
|
2607
|
+
if (input.task && semanticEnabled) {
|
|
2548
2608
|
searchMode = semanticHits ? "semantic" : "literal_fallback";
|
|
2549
2609
|
}
|
|
2550
2610
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -2880,7 +2940,7 @@ ${m.content}`).join("\n\n---\n\n"),
|
|
|
2880
2940
|
}
|
|
2881
2941
|
}
|
|
2882
2942
|
if (existsSync22(ctx.paths.memoriesDir)) {
|
|
2883
|
-
const allMems = await loadMemoriesFromDir17(ctx.paths.memoriesDir);
|
|
2943
|
+
const allMems = (await loadMemoriesFromDir17(ctx.paths.memoriesDir)).filter(scopeAllowed);
|
|
2884
2944
|
for (const { memory } of allMems) {
|
|
2885
2945
|
const fm = memory.frontmatter;
|
|
2886
2946
|
if (!fm.requires_human_approval) continue;
|
|
@@ -2937,7 +2997,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
2937
2997
|
pcRaw = await readFile7(ctx.paths.projectContext, "utf8");
|
|
2938
2998
|
} catch {
|
|
2939
2999
|
}
|
|
2940
|
-
const allForBootstrap = existsSync22(ctx.paths.memoriesDir) ? await loadMemoriesFromDir17(ctx.paths.memoriesDir) : [];
|
|
3000
|
+
const allForBootstrap = existsSync22(ctx.paths.memoriesDir) ? (await loadMemoriesFromDir17(ctx.paths.memoriesDir)).filter(scopeAllowed) : [];
|
|
2941
3001
|
const cmForBootstrap = await loadCodeMap(ctx.paths);
|
|
2942
3002
|
let existingModules = [];
|
|
2943
3003
|
try {
|
|
@@ -2948,7 +3008,7 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
|
|
|
2948
3008
|
const bootstrap = assessBootstrapState({
|
|
2949
3009
|
projectContextRaw: pcRaw,
|
|
2950
3010
|
memories: allForBootstrap,
|
|
2951
|
-
codeFiles: cmForBootstrap ? Object.keys(cmForBootstrap.files) : [],
|
|
3011
|
+
codeFiles: cmForBootstrap ? Object.keys(cmForBootstrap.files).filter((file) => existsSync22(path13.join(ctx.paths.root, file))) : [],
|
|
2952
3012
|
existingModules
|
|
2953
3013
|
});
|
|
2954
3014
|
if (bootstrap.state !== "ready" && bootstrap.metrics.mainAreas > 0) {
|
|
@@ -3139,7 +3199,7 @@ function oneLine(value) {
|
|
|
3139
3199
|
return value.replace(/\s+/g, " ").replace(/"/g, '\\"').trim().slice(0, 120);
|
|
3140
3200
|
}
|
|
3141
3201
|
function serverVersion() {
|
|
3142
|
-
return true ? "0.
|
|
3202
|
+
return true ? "0.44.0" : "dev";
|
|
3143
3203
|
}
|
|
3144
3204
|
|
|
3145
3205
|
// src/tools/code-map.ts
|
|
@@ -3425,7 +3485,8 @@ var AntiPatternsCheckInputSchema = {
|
|
|
3425
3485
|
),
|
|
3426
3486
|
min_semantic_score: z26.number().min(0).max(1).default(0.45).describe(
|
|
3427
3487
|
"Minimum cosine score for semantic-only anti-pattern hits. Anchor/literal matches still surface. Default 0.45 keeps broad, weakly-related memories out of review noise."
|
|
3428
|
-
)
|
|
3488
|
+
),
|
|
3489
|
+
track: z26.boolean().default(true).describe("Record real prevention outcomes. Set false for eval/selftest probes so synthetic cases never inflate ROI.")
|
|
3429
3490
|
};
|
|
3430
3491
|
function tokenizeDiffForLiteral(diff) {
|
|
3431
3492
|
const lines = diff.split("\n");
|
|
@@ -3618,7 +3679,9 @@ async function antiPatternsCheck(input, ctx) {
|
|
|
3618
3679
|
}).slice(0, input.limit);
|
|
3619
3680
|
const isHardBlockCatch = (w) => w.reasons.includes("sensor");
|
|
3620
3681
|
const strongCatches = warnings.filter(isHardBlockCatch);
|
|
3621
|
-
|
|
3682
|
+
if (input.track !== false) {
|
|
3683
|
+
await recordPreventionHits(ctx.paths, strongCatches.map((w) => w.id), "anti-pattern");
|
|
3684
|
+
}
|
|
3622
3685
|
return {
|
|
3623
3686
|
scanned: negative.length,
|
|
3624
3687
|
warnings
|
|
@@ -4312,6 +4375,7 @@ ${template}\`\`\`
|
|
|
4312
4375
|
// src/prompts/bootstrap-repo.ts
|
|
4313
4376
|
import { readFile as readFile8, readdir as readdir5 } from "fs/promises";
|
|
4314
4377
|
import { existsSync as existsSync29 } from "fs";
|
|
4378
|
+
import path14 from "path";
|
|
4315
4379
|
import {
|
|
4316
4380
|
assessBootstrapState as assessBootstrapState2,
|
|
4317
4381
|
loadCodeMap as loadCodeMap4,
|
|
@@ -4339,7 +4403,7 @@ async function currentAssessment(ctx) {
|
|
|
4339
4403
|
return assessBootstrapState2({
|
|
4340
4404
|
projectContextRaw,
|
|
4341
4405
|
memories,
|
|
4342
|
-
codeFiles: codeMap ? Object.keys(codeMap.files) : [],
|
|
4406
|
+
codeFiles: codeMap ? Object.keys(codeMap.files).filter((file) => existsSync29(path14.join(ctx.paths.root, file))) : [],
|
|
4343
4407
|
existingModules
|
|
4344
4408
|
});
|
|
4345
4409
|
}
|
|
@@ -4399,13 +4463,14 @@ Main code areas detected: ${areas}
|
|
|
4399
4463
|
import { z as z35 } from "zod";
|
|
4400
4464
|
var PostTaskArgsSchema = {
|
|
4401
4465
|
task_summary: z35.string().optional().describe("One sentence describing what you just did"),
|
|
4402
|
-
files_touched: z35.
|
|
4466
|
+
files_touched: z35.string().optional().describe("Files you created or modified during the task, as CSV or a JSON array string")
|
|
4403
4467
|
};
|
|
4404
4468
|
function postTaskPrompt(args, ctx) {
|
|
4405
4469
|
const taskLine = args.task_summary ? `
|
|
4406
4470
|
Task just completed: **${args.task_summary}**` : "";
|
|
4407
|
-
const
|
|
4408
|
-
|
|
4471
|
+
const filesTouched = parsePromptFilesTouched(args.files_touched);
|
|
4472
|
+
const filesLine = filesTouched.length > 0 ? `
|
|
4473
|
+
Files touched: ${filesTouched.map((f) => `\`${f}\``).join(", ")}` : "";
|
|
4409
4474
|
const text = `You have just finished a task. Before closing this session, take 60 seconds to capture what you learned.
|
|
4410
4475
|
${taskLine}${filesLine}
|
|
4411
4476
|
|
|
@@ -4494,6 +4559,20 @@ When done, respond with a brief summary: "Saved N memories: [list of IDs]. Sessi
|
|
|
4494
4559
|
]
|
|
4495
4560
|
};
|
|
4496
4561
|
}
|
|
4562
|
+
function parsePromptFilesTouched(input) {
|
|
4563
|
+
const raw = input?.trim();
|
|
4564
|
+
if (!raw) return [];
|
|
4565
|
+
if (raw.startsWith("[")) {
|
|
4566
|
+
try {
|
|
4567
|
+
const parsed = JSON.parse(raw);
|
|
4568
|
+
if (Array.isArray(parsed)) {
|
|
4569
|
+
return parsed.filter((value) => typeof value === "string").map((value) => value.trim()).filter(Boolean);
|
|
4570
|
+
}
|
|
4571
|
+
} catch {
|
|
4572
|
+
}
|
|
4573
|
+
}
|
|
4574
|
+
return raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
4575
|
+
}
|
|
4497
4576
|
|
|
4498
4577
|
// src/prompts/import-docs.ts
|
|
4499
4578
|
import { z as z36 } from "zod";
|
|
@@ -4567,7 +4646,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
|
|
|
4567
4646
|
// src/server.ts
|
|
4568
4647
|
import { hasRecentBriefingMarker, loadConfigSync } from "@hivelore/core";
|
|
4569
4648
|
var SERVER_NAME = "hivelore";
|
|
4570
|
-
var SERVER_VERSION = "0.
|
|
4649
|
+
var SERVER_VERSION = "0.44.0";
|
|
4571
4650
|
function jsonResult(data) {
|
|
4572
4651
|
return {
|
|
4573
4652
|
content: [
|
|
@@ -5506,11 +5585,22 @@ function printHaiveMcpVersion() {
|
|
|
5506
5585
|
}
|
|
5507
5586
|
async function runHaiveMcpStdio(options) {
|
|
5508
5587
|
const { server, context } = createHaiveServer({ root: options.root, env: process.env });
|
|
5588
|
+
await writeMcpRuntimeMarker(context).catch(() => {
|
|
5589
|
+
});
|
|
5509
5590
|
console.error(
|
|
5510
5591
|
`[haive-mcp] starting server v${SERVER_VERSION} (project root: ${context.paths.root})`
|
|
5511
5592
|
);
|
|
5512
5593
|
await server.connect(new StdioServerTransport());
|
|
5513
5594
|
}
|
|
5595
|
+
async function writeMcpRuntimeMarker(context) {
|
|
5596
|
+
await mkdir8(context.paths.runtimeDir, { recursive: true });
|
|
5597
|
+
await writeFile15(path15.join(context.paths.runtimeDir, "mcp-server.json"), JSON.stringify({
|
|
5598
|
+
version: SERVER_VERSION,
|
|
5599
|
+
pid: process.pid,
|
|
5600
|
+
started_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5601
|
+
command: "hivelore mcp --stdio"
|
|
5602
|
+
}, null, 2), "utf8");
|
|
5603
|
+
}
|
|
5514
5604
|
export {
|
|
5515
5605
|
ENFORCEMENT_PROFILE_TOOLS,
|
|
5516
5606
|
EXPERIMENTAL_PROFILE_TOOLS,
|
|
@@ -5544,6 +5634,7 @@ export {
|
|
|
5544
5634
|
runAstPattern,
|
|
5545
5635
|
runAstSensorOnContent,
|
|
5546
5636
|
runHaiveMcpStdio,
|
|
5547
|
-
scaffoldTest
|
|
5637
|
+
scaffoldTest,
|
|
5638
|
+
writeMcpRuntimeMarker
|
|
5548
5639
|
};
|
|
5549
5640
|
//# sourceMappingURL=server.js.map
|