@hiveai/mcp 0.15.0 → 0.18.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
@@ -670,15 +670,19 @@ async function memReject(input, ctx) {
670
670
 
671
671
  // src/tools/mem-feedback.ts
672
672
  import {
673
+ applyFeedbackAdjustment,
673
674
  computeImpact,
674
675
  getUsage as getUsage2,
675
676
  loadMemoriesFromDir as loadMemoriesFromDir6,
676
677
  loadUsageIndex as loadUsageIndex3,
677
678
  recordApplied,
678
679
  recordRejection as recordRejection2,
679
- saveUsageIndex as saveUsageIndex2
680
+ recommendFeedbackAdjustment,
681
+ saveUsageIndex as saveUsageIndex2,
682
+ serializeMemory as serializeMemory4
680
683
  } from "@hiveai/core";
681
684
  import { existsSync as existsSync8 } from "fs";
685
+ import { writeFile as writeFile5 } from "fs/promises";
682
686
  import { z as z8 } from "zod";
683
687
  var MemFeedbackInputSchema = {
684
688
  id: z8.string().min(1).describe("Full memory id the feedback is about"),
@@ -704,6 +708,12 @@ async function memFeedback(input, ctx) {
704
708
  }
705
709
  await saveUsageIndex2(ctx.paths, index);
706
710
  const usage = getUsage2(index, input.id);
711
+ const adjustment = input.outcome === "rejected" ? recommendFeedbackAdjustment(target.memory.frontmatter, usage) : { action: "none", reason: "No automatic adjustment needed." };
712
+ const adjustedFrontmatter = applyFeedbackAdjustment(target.memory.frontmatter, adjustment);
713
+ if (adjustedFrontmatter !== target.memory.frontmatter) {
714
+ target.memory.frontmatter = adjustedFrontmatter;
715
+ await writeFile5(target.filePath, serializeMemory4(target.memory), "utf8");
716
+ }
707
717
  const impact = computeImpact(target.memory.frontmatter, usage);
708
718
  return {
709
719
  ok: true,
@@ -714,7 +724,8 @@ async function memFeedback(input, ctx) {
714
724
  applied_count: usage.applied_count,
715
725
  rejected_count: usage.rejected_count
716
726
  },
717
- impact: { score: impact.score, tier: impact.tier, signals: impact.signals }
727
+ impact: { score: impact.score, tier: impact.tier, signals: impact.signals },
728
+ feedback_adjustment: adjustment
718
729
  };
719
730
  }
720
731
 
@@ -954,9 +965,9 @@ async function memDelete(input, ctx) {
954
965
  }
955
966
 
956
967
  // src/tools/mem-update.ts
957
- import { writeFile as writeFile5 } from "fs/promises";
968
+ import { writeFile as writeFile6 } from "fs/promises";
958
969
  import { existsSync as existsSync12 } from "fs";
959
- import { loadMemoriesFromDir as loadMemoriesFromDir10, serializeMemory as serializeMemory4 } from "@hiveai/core";
970
+ import { loadMemoriesFromDir as loadMemoriesFromDir10, serializeMemory as serializeMemory5 } from "@hiveai/core";
960
971
  import { z as z12 } from "zod";
961
972
  var MemUpdateInputSchema = {
962
973
  id: z12.string().min(1).describe("Id of the memory to update"),
@@ -1005,9 +1016,9 @@ async function memUpdate(input, ctx) {
1005
1016
  if (updated_fields.length === 0) {
1006
1017
  throw new Error("No fields to update \u2014 provide at least one of: body, tags, paths, symbols, commit, domain, author.");
1007
1018
  }
1008
- await writeFile5(
1019
+ await writeFile6(
1009
1020
  loaded.filePath,
1010
- serializeMemory4({ frontmatter: newFrontmatter, body: newBody }),
1021
+ serializeMemory5({ frontmatter: newFrontmatter, body: newBody }),
1011
1022
  "utf8"
1012
1023
  );
1013
1024
  return { id: input.id, file_path: loaded.filePath, updated_fields };
@@ -1057,11 +1068,11 @@ async function memPending(input, ctx) {
1057
1068
  }
1058
1069
 
1059
1070
  // src/tools/mem-approve.ts
1060
- import { writeFile as writeFile6 } from "fs/promises";
1071
+ import { writeFile as writeFile7 } from "fs/promises";
1061
1072
  import { existsSync as existsSync14 } from "fs";
1062
1073
  import {
1063
1074
  loadMemoriesFromDir as loadMemoriesFromDir12,
1064
- serializeMemory as serializeMemory5
1075
+ serializeMemory as serializeMemory6
1065
1076
  } from "@hiveai/core";
1066
1077
  import { z as z14 } from "zod";
1067
1078
  var MemApproveInputSchema = {
@@ -1079,7 +1090,7 @@ async function memApprove(input, ctx) {
1079
1090
  frontmatter: { ...found.memory.frontmatter, status: "validated" },
1080
1091
  body: found.memory.body
1081
1092
  };
1082
- await writeFile6(found.filePath, serializeMemory5(next), "utf8");
1093
+ await writeFile7(found.filePath, serializeMemory6(next), "utf8");
1083
1094
  return {
1084
1095
  id: input.id,
1085
1096
  previous_status: previous,
@@ -1089,13 +1100,13 @@ async function memApprove(input, ctx) {
1089
1100
  }
1090
1101
 
1091
1102
  // src/tools/mem-tried.ts
1092
- import { mkdir as mkdir3, writeFile as writeFile7 } from "fs/promises";
1103
+ import { mkdir as mkdir3, writeFile as writeFile8 } from "fs/promises";
1093
1104
  import { existsSync as existsSync15 } from "fs";
1094
1105
  import path5 from "path";
1095
1106
  import {
1096
1107
  buildFrontmatter as buildFrontmatter2,
1097
1108
  memoryFilePath as memoryFilePath2,
1098
- serializeMemory as serializeMemory6,
1109
+ serializeMemory as serializeMemory7,
1099
1110
  suggestSensorFromMemory as suggestSensorFromMemory2
1100
1111
  } from "@hiveai/core";
1101
1112
  import { z as z15 } from "zod";
@@ -1139,13 +1150,13 @@ async function memTried(input, ctx) {
1139
1150
  if (existsSync15(file)) {
1140
1151
  throw new Error(`Memory already exists at ${file}`);
1141
1152
  }
1142
- await writeFile7(file, serializeMemory6({ frontmatter, body }), "utf8");
1153
+ await writeFile8(file, serializeMemory7({ frontmatter, body }), "utf8");
1143
1154
  return { id: frontmatter.id, scope: frontmatter.scope, file_path: file };
1144
1155
  }
1145
1156
 
1146
1157
  // src/tools/ingest-findings.ts
1147
1158
  import { existsSync as existsSync16 } from "fs";
1148
- import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile8 } from "fs/promises";
1159
+ import { mkdir as mkdir4, readFile as readFile3, writeFile as writeFile9 } from "fs/promises";
1149
1160
  import path6 from "path";
1150
1161
  import {
1151
1162
  draftsFromFindings,
@@ -1153,7 +1164,7 @@ import {
1153
1164
  loadMemoriesFromDir as loadMemoriesFromDir13,
1154
1165
  memoryFilePath as memoryFilePath3,
1155
1166
  parseFindings,
1156
- serializeMemory as serializeMemory7
1167
+ serializeMemory as serializeMemory8
1157
1168
  } from "@hiveai/core";
1158
1169
  import { z as z16 } from "zod";
1159
1170
  var IngestFindingsInputSchema = {
@@ -1230,19 +1241,19 @@ async function writeDraft(ctx, draft) {
1230
1241
  draft.frontmatter.module
1231
1242
  );
1232
1243
  await mkdir4(path6.dirname(file), { recursive: true });
1233
- await writeFile8(file, serializeMemory7({ frontmatter: draft.frontmatter, body: draft.body }), "utf8");
1244
+ await writeFile9(file, serializeMemory8({ frontmatter: draft.frontmatter, body: draft.body }), "utf8");
1234
1245
  return file;
1235
1246
  }
1236
1247
 
1237
1248
  // src/tools/mem-observe.ts
1238
- import { mkdir as mkdir5, writeFile as writeFile9 } from "fs/promises";
1249
+ import { mkdir as mkdir5, writeFile as writeFile10 } from "fs/promises";
1239
1250
  import { existsSync as existsSync17 } from "fs";
1240
1251
  import path7 from "path";
1241
1252
  import {
1242
1253
  buildFrontmatter as buildFrontmatter3,
1243
1254
  isLikelyGuessable,
1244
1255
  memoryFilePath as memoryFilePath4,
1245
- serializeMemory as serializeMemory8
1256
+ serializeMemory as serializeMemory9
1246
1257
  } from "@hiveai/core";
1247
1258
  import { z as z17 } from "zod";
1248
1259
  var MemObserveInputSchema = {
@@ -1296,19 +1307,19 @@ async function memObserve(input, ctx) {
1296
1307
  if (existsSync17(file)) {
1297
1308
  throw new Error(`Memory already exists at ${file}`);
1298
1309
  }
1299
- await writeFile9(file, serializeMemory8({ frontmatter, body }), "utf8");
1310
+ await writeFile10(file, serializeMemory9({ frontmatter, body }), "utf8");
1300
1311
  return { id: frontmatter.id, scope: frontmatter.scope, file_path: file };
1301
1312
  }
1302
1313
 
1303
1314
  // src/tools/mem-session-end.ts
1304
- import { writeFile as writeFile11, mkdir as mkdir7 } from "fs/promises";
1315
+ import { writeFile as writeFile12, mkdir as mkdir7 } from "fs/promises";
1305
1316
  import { existsSync as existsSync19 } from "fs";
1306
1317
  import path9 from "path";
1307
1318
  import {
1308
1319
  buildFrontmatter as buildFrontmatter4,
1309
1320
  loadMemoriesFromDir as loadMemoriesFromDir14,
1310
1321
  memoryFilePath as memoryFilePath5,
1311
- serializeMemory as serializeMemory9
1322
+ serializeMemory as serializeMemory10
1312
1323
  } from "@hiveai/core";
1313
1324
  import { z as z18 } from "zod";
1314
1325
 
@@ -1318,7 +1329,7 @@ import {
1318
1329
  appendRuntimeJournalEntry,
1319
1330
  loadConfig as loadConfig2
1320
1331
  } from "@hiveai/core";
1321
- import { mkdir as mkdir6, writeFile as writeFile10, rm } from "fs/promises";
1332
+ import { mkdir as mkdir6, writeFile as writeFile11, rm } from "fs/promises";
1322
1333
  import { existsSync as existsSync18 } from "fs";
1323
1334
  import path8 from "path";
1324
1335
  import { execSync } from "child_process";
@@ -1417,7 +1428,7 @@ var SessionTracker = class {
1417
1428
  };
1418
1429
  const cacheDir = path8.join(this.ctx.paths.haiveDir, ".cache");
1419
1430
  await mkdir6(cacheDir, { recursive: true });
1420
- await writeFile10(
1431
+ await writeFile11(
1421
1432
  pendingDistillPath(this.ctx),
1422
1433
  JSON.stringify(payload, null, 2) + "\n",
1423
1434
  "utf8"
@@ -1523,9 +1534,9 @@ async function memSessionEnd(input, ctx) {
1523
1534
  paths: normalizedFiles.length ? normalizedFiles : fm.anchor.paths
1524
1535
  }
1525
1536
  };
1526
- await writeFile11(
1537
+ await writeFile12(
1527
1538
  topicMatch.filePath,
1528
- serializeMemory9({ frontmatter: newFrontmatter, body }),
1539
+ serializeMemory10({ frontmatter: newFrontmatter, body }),
1529
1540
  "utf8"
1530
1541
  );
1531
1542
  await clearPendingDistill(ctx);
@@ -1554,7 +1565,7 @@ async function memSessionEnd(input, ctx) {
1554
1565
  frontmatter.module
1555
1566
  );
1556
1567
  await mkdir7(path9.dirname(file), { recursive: true });
1557
- await writeFile11(file, serializeMemory9({ frontmatter, body }), "utf8");
1568
+ await writeFile12(file, serializeMemory10({ frontmatter, body }), "utf8");
1558
1569
  await clearPendingDistill(ctx);
1559
1570
  return {
1560
1571
  id: frontmatter.id,
@@ -1566,15 +1577,17 @@ async function memSessionEnd(input, ctx) {
1566
1577
  }
1567
1578
 
1568
1579
  // src/tools/get-briefing.ts
1569
- import { readFile as readFile5, writeFile as writeFile12 } from "fs/promises";
1580
+ import { readFile as readFile5, writeFile as writeFile13 } from "fs/promises";
1570
1581
  import { existsSync as existsSync21 } from "fs";
1571
1582
  import {
1572
1583
  allocateBudget,
1584
+ briefingProofLine,
1573
1585
  computeImpact as computeImpact2,
1574
1586
  DEFAULT_AUTO_PROMOTE_RULE,
1575
1587
  deriveConfidence as deriveConfidence4,
1576
1588
  estimateTokens,
1577
1589
  evaluateSkillActivation,
1590
+ compactAutoRecapBody,
1578
1591
  extractActionsBriefBody,
1579
1592
  getUsage as getUsage6,
1580
1593
  inferModulesFromPaths as inferModulesFromPaths2,
@@ -1587,6 +1600,7 @@ import {
1587
1600
  loadConfig as loadConfig3,
1588
1601
  hashProjectContext,
1589
1602
  loadMemoriesFromDir as loadMemoriesFromDir15,
1603
+ loadPreventionEvents,
1590
1604
  loadUsageIndex as loadUsageIndex8,
1591
1605
  memoryMatchesAnchorPaths as memoryMatchesAnchorPaths2,
1592
1606
  projectContextRecentlyEmitted,
@@ -1594,7 +1608,7 @@ import {
1594
1608
  recordProjectContextEmission,
1595
1609
  queryCodeMap,
1596
1610
  resolveBriefingBudget,
1597
- serializeMemory as serializeMemory10,
1611
+ serializeMemory as serializeMemory11,
1598
1612
  specificityScore,
1599
1613
  GUESSABLE_THRESHOLD,
1600
1614
  tokenizeQuery as tokenizeQuery2,
@@ -1608,7 +1622,12 @@ import { z as z19 } from "zod";
1608
1622
  import { readdir as readdir3, readFile as readFile4 } from "fs/promises";
1609
1623
  import { existsSync as existsSync20 } from "fs";
1610
1624
  import path10 from "path";
1611
- import { isGlobPath, isStackPackSeed, pathsOverlap } from "@hiveai/core";
1625
+ import {
1626
+ classifyMemoryPriority as coreClassifyPriority,
1627
+ isGlobPath,
1628
+ pathsOverlap,
1629
+ priorityRank as corePriorityRank
1630
+ } from "@hiveai/core";
1612
1631
  function compactSummary(body) {
1613
1632
  for (const line of body.split("\n")) {
1614
1633
  const trimmed = line.replace(/^#+\s*/, "").trim();
@@ -1626,21 +1645,23 @@ function classifyMemoryPriority(memory, loaded, inputFiles, inputSymbols) {
1626
1645
  (sym) => inputSymbols.some((wanted) => wanted.toLowerCase() === sym.toLowerCase())
1627
1646
  )
1628
1647
  );
1629
- const strongSemantic = (memory.semantic_score ?? 0) >= 0.65;
1630
- const usefulSemantic = (memory.semantic_score ?? 0) >= 0.35;
1631
- if (fm?.requires_human_approval || directAnchor || directSymbol || memory.type === "attempt" && (memory.match_quality === "exact" || strongSemantic) || memory.type === "skill" && (memory.match_quality === "exact" || strongSemantic)) {
1632
- return "must_read";
1633
- }
1634
- if (isStackPackSeed(fm)) {
1635
- return "background";
1636
- }
1637
- if (memory.type === "skill" || memory.reasons.includes("module") || memory.reasons.includes("domain") || memory.match_quality === "exact" || usefulSemantic) {
1638
- return "useful";
1639
- }
1640
- return "background";
1648
+ const semantic = memory.semantic_score ?? 0;
1649
+ return coreClassifyPriority({
1650
+ type: memory.type,
1651
+ tags: fm?.tags ?? memory.tags ?? [],
1652
+ requiresHumanApproval: Boolean(fm?.requires_human_approval),
1653
+ directAnchor,
1654
+ directSymbol,
1655
+ exactTaskMatch: memory.match_quality === "exact",
1656
+ strongSemantic: semantic >= 0.65,
1657
+ usefulSemantic: semantic >= 0.35,
1658
+ moduleOrDomainMatch: memory.reasons.includes("module") || memory.reasons.includes("domain"),
1659
+ tagTaskMatch: false
1660
+ // MCP ranking doesn't use a separate tag-token signal
1661
+ });
1641
1662
  }
1642
1663
  function priorityRank(priority) {
1643
- return priority === "must_read" ? 3 : priority === "useful" ? 2 : 1;
1664
+ return corePriorityRank(priority);
1644
1665
  }
1645
1666
  function classifyBriefingQuality(memories, context) {
1646
1667
  const mustRead = memories.filter((m) => m.priority === "must_read").length;
@@ -1809,7 +1830,9 @@ async function getBriefing(input, ctx) {
1809
1830
  id: fm.id,
1810
1831
  scope: fm.scope,
1811
1832
  revision_count: fm.revision_count ?? 0,
1812
- body: r.memory.body
1833
+ // Auto-generated recaps are low-signal tool dumps — compact them so they inform without
1834
+ // dominating the briefing head. Human/post_task recaps pass through unchanged.
1835
+ body: compactAutoRecapBody(r.memory.body)
1813
1836
  };
1814
1837
  }
1815
1838
  const allMemories = allLoaded.filter(({ memory }) => {
@@ -1961,7 +1984,7 @@ async function getBriefing(input, ctx) {
1961
1984
  if (!isAutoPromoteEligible(loaded.memory.frontmatter, u, rule)) continue;
1962
1985
  const newFm = { ...loaded.memory.frontmatter, status: "validated" };
1963
1986
  try {
1964
- await writeFile12(loaded.filePath, serializeMemory10({ frontmatter: newFm, body: loaded.memory.body }), "utf8");
1987
+ await writeFile13(loaded.filePath, serializeMemory11({ frontmatter: newFm, body: loaded.memory.body }), "utf8");
1965
1988
  m.status = "validated";
1966
1989
  m.confidence = "trusted";
1967
1990
  } catch {
@@ -2232,6 +2255,10 @@ When done, call \`mem_session_end\` to acknowledge \u2014 this clears the pendin
2232
2255
  "No team-specific policy matched these files/task \u2014 nothing here a capable model can't infer. The auto-generated project context was trimmed to keep this briefing near-zero-cost; proceed with normal Read/Grep."
2233
2256
  );
2234
2257
  }
2258
+ if (outputMemories.length > 0 && existsSync21(ctx.paths.haiveDir)) {
2259
+ const proof = briefingProofLine(await loadPreventionEvents(ctx.paths));
2260
+ if (proof) hints.push(proof);
2261
+ }
2235
2262
  if (existsSync21(ctx.paths.haiveDir)) {
2236
2263
  await writeBriefingMarker(ctx.paths, {
2237
2264
  sessionId: process.env.HAIVE_SESSION_ID,
@@ -2641,6 +2668,7 @@ import { existsSync as existsSync25 } from "fs";
2641
2668
  import {
2642
2669
  addedLinesFromDiff,
2643
2670
  appendPreventionEvent,
2671
+ BRIDGE_TARGET_PATH,
2644
2672
  buildDocFrequency,
2645
2673
  CODE_STOPWORDS,
2646
2674
  deriveConfidence as deriveConfidence6,
@@ -2682,6 +2710,44 @@ function tokenizeDiffForLiteral(diff) {
2682
2710
  const wordTokens = source.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 4 && !CODE_STOPWORDS.has(t));
2683
2711
  return [.../* @__PURE__ */ new Set([...wsTokens, ...wordTokens])];
2684
2712
  }
2713
+ var HAIVE_GENERATED_FILES = /* @__PURE__ */ new Set([
2714
+ ...Object.values(BRIDGE_TARGET_PATH),
2715
+ // .clinerules, .windsurfrules, .continuerules, .rules, AGENTS.md, .github/copilot-instructions.md, .sourcegraph/cody-rules.md
2716
+ "CLAUDE.md",
2717
+ ".cursorrules",
2718
+ ".gitignore",
2719
+ ".mcp.json",
2720
+ ".cursor/mcp.json",
2721
+ ".vscode/mcp.json"
2722
+ ]);
2723
+ function isHaiveOwnedPath(p) {
2724
+ if (p.startsWith(".ai/")) return true;
2725
+ if (HAIVE_GENERATED_FILES.has(p)) return true;
2726
+ if (p.startsWith(".cursor/rules/")) return true;
2727
+ if (/^\.github\/workflows\/haive-.*\.ya?ml$/.test(p)) return true;
2728
+ return false;
2729
+ }
2730
+ function stripAiDirHunks(diff) {
2731
+ if (!diff.includes("diff --git")) return diff;
2732
+ const out = [];
2733
+ let block = [];
2734
+ let keep = true;
2735
+ const flush = () => {
2736
+ if (keep) out.push(...block);
2737
+ block = [];
2738
+ keep = true;
2739
+ };
2740
+ for (const line of diff.split("\n")) {
2741
+ if (line.startsWith("diff --git ")) {
2742
+ flush();
2743
+ const target = line.match(/ b\/(.+)$/)?.[1] ?? "";
2744
+ keep = !isHaiveOwnedPath(target);
2745
+ }
2746
+ block.push(line);
2747
+ }
2748
+ flush();
2749
+ return out.join("\n");
2750
+ }
2685
2751
  async function antiPatternsCheck(input, ctx) {
2686
2752
  if (!input.diff && input.paths.length === 0) {
2687
2753
  return {
@@ -2737,10 +2803,11 @@ async function antiPatternsCheck(input, ctx) {
2737
2803
  }
2738
2804
  }
2739
2805
  }
2740
- if (input.diff) {
2741
- const tokens = tokenizeDiffForLiteral(input.diff);
2742
- const added = addedLinesFromDiff(input.diff);
2743
- const addedText = added.trim().length > 0 ? added : input.diff;
2806
+ const scanDiff = input.diff ? stripAiDirHunks(input.diff) : input.diff;
2807
+ if (scanDiff) {
2808
+ const tokens = tokenizeDiffForLiteral(scanDiff);
2809
+ const added = addedLinesFromDiff(scanDiff);
2810
+ const addedText = added.trim().length > 0 ? added : scanDiff;
2744
2811
  if (tokens.length > 0) {
2745
2812
  for (const { memory } of negative) {
2746
2813
  if (literalMatchesAnyToken3(memory, tokens)) {
@@ -2753,11 +2820,13 @@ async function antiPatternsCheck(input, ctx) {
2753
2820
  }
2754
2821
  }
2755
2822
  }
2756
- if (input.diff) {
2757
- const added = addedLinesFromDiff(input.diff);
2758
- const diffTargets = sensorTargetsFromDiff(input.diff);
2823
+ if (scanDiff) {
2824
+ const added = addedLinesFromDiff(scanDiff);
2825
+ const diffTargets = sensorTargetsFromDiff(scanDiff);
2759
2826
  const hasFileTargets = diffTargets.some((target) => target.path.length > 0);
2760
- const targets = diffTargets.length > 0 && hasFileTargets ? diffTargets : input.paths.length > 0 ? input.paths.map((p) => ({ path: p, content: added.trim().length > 0 ? added : input.diff })) : [{ path: "", content: added.trim().length > 0 ? added : input.diff }];
2827
+ const codePaths = input.paths.filter((p) => !isHaiveOwnedPath(p));
2828
+ const fallbackContent = added.trim().length > 0 ? added : scanDiff;
2829
+ const targets = diffTargets.length > 0 && hasFileTargets ? diffTargets : codePaths.length > 0 ? codePaths.map((p) => ({ path: p, content: fallbackContent })) : [{ path: "", content: fallbackContent }];
2761
2830
  const hits = runSensors(negative.map(({ memory }) => memory), targets);
2762
2831
  for (const hit of hits) {
2763
2832
  const found = negative.find(({ memory }) => memory.frontmatter.id === hit.memory_id);
@@ -2770,10 +2839,10 @@ async function antiPatternsCheck(input, ctx) {
2770
2839
  }
2771
2840
  }
2772
2841
  }
2773
- if (input.semantic && input.diff) {
2842
+ if (input.semantic && scanDiff) {
2774
2843
  try {
2775
2844
  const mod = await import("@hiveai/embeddings");
2776
- const result = await mod.semanticSearch(ctx.paths, input.diff, { limit: input.limit * 2 });
2845
+ const result = await mod.semanticSearch(ctx.paths, scanDiff, { limit: input.limit * 2 });
2777
2846
  if (result) {
2778
2847
  const negativeIds = new Set(negative.map(({ memory }) => memory.frontmatter.id));
2779
2848
  for (const hit of result.hits) {
@@ -2795,7 +2864,7 @@ async function antiPatternsCheck(input, ctx) {
2795
2864
  return score(b) - score(a);
2796
2865
  }).slice(0, input.limit);
2797
2866
  const strongCatches = warnings.filter(
2798
- (w) => w.reasons.includes("sensor") || w.distinctive_literal === true || w.reasons.includes("anchor") && w.reasons.includes("literal")
2867
+ (w) => w.reasons.includes("sensor") || w.reasons.includes("anchor") && w.reasons.includes("literal")
2799
2868
  );
2800
2869
  if (strongCatches.length > 0) {
2801
2870
  const recordedIds = [];
@@ -3420,7 +3489,9 @@ function classifyWarning(warning, paths, anchoredBlocks = false) {
3420
3489
  repair_command: repairCommand
3421
3490
  };
3422
3491
  }
3423
- if (hasSemantic && semanticScore >= 0.45 || highConfidence && warning.reasons.includes("anchor") && warning.reasons.includes("literal")) {
3492
+ const corroborated = warning.reasons.includes("anchor") || warning.distinctive_literal === true;
3493
+ const semanticReviewFloor = corroborated ? 0.45 : 0.6;
3494
+ if (hasSemantic && semanticScore >= semanticReviewFloor || highConfidence && warning.reasons.includes("anchor") && warning.reasons.includes("literal")) {
3424
3495
  return {
3425
3496
  ...warning,
3426
3497
  level: "review",
@@ -3553,7 +3624,7 @@ function repairTargetPathForWarning(warning, paths) {
3553
3624
  }
3554
3625
 
3555
3626
  // src/tools/pattern-detect.ts
3556
- import { mkdir as mkdir8, writeFile as writeFile13 } from "fs/promises";
3627
+ import { mkdir as mkdir8, writeFile as writeFile14 } from "fs/promises";
3557
3628
  import { existsSync as existsSync29 } from "fs";
3558
3629
  import path12 from "path";
3559
3630
  import { execSync as execSync2 } from "child_process";
@@ -3561,7 +3632,7 @@ import {
3561
3632
  buildFrontmatter as buildFrontmatter5,
3562
3633
  memoryFilePath as memoryFilePath6,
3563
3634
  readUsageEvents,
3564
- serializeMemory as serializeMemory11
3635
+ serializeMemory as serializeMemory12
3565
3636
  } from "@hiveai/core";
3566
3637
  import { z as z31 } from "zod";
3567
3638
  var CONFIG_PATTERNS = [
@@ -3722,9 +3793,9 @@ async function patternDetect(input, ctx) {
3722
3793
  );
3723
3794
  if (existsSync29(file)) continue;
3724
3795
  await mkdir8(path12.dirname(file), { recursive: true });
3725
- await writeFile13(
3796
+ await writeFile14(
3726
3797
  file,
3727
- serializeMemory11({ frontmatter: fm, body: match.proposed_body }),
3798
+ serializeMemory12({ frontmatter: fm, body: match.proposed_body }),
3728
3799
  "utf8"
3729
3800
  );
3730
3801
  savedIds.push(fm.id);
@@ -4150,7 +4221,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
4150
4221
  // src/server.ts
4151
4222
  import { hasRecentBriefingMarker, loadConfigSync } from "@hiveai/core";
4152
4223
  var SERVER_NAME = "haive";
4153
- var SERVER_VERSION = "0.15.0";
4224
+ var SERVER_VERSION = "0.18.0";
4154
4225
  function jsonResult(data) {
4155
4226
  return {
4156
4227
  content: [