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