@hiveai/mcp 0.9.14 → 0.9.15

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
@@ -1394,6 +1394,7 @@ import {
1394
1394
  loadMemoriesFromDir as loadMemoriesFromDir13,
1395
1395
  loadUsageIndex as loadUsageIndex7,
1396
1396
  memoryMatchesAnchorPaths as memoryMatchesAnchorPaths2,
1397
+ pathsOverlap,
1397
1398
  queryCodeMap,
1398
1399
  resolveBriefingBudget,
1399
1400
  serializeMemory as serializeMemory9,
@@ -1702,10 +1703,14 @@ ${m.content}`).join("\n\n---\n\n"),
1702
1703
  const createdAt = loaded?.memory.frontmatter.created_at ?? (/* @__PURE__ */ new Date()).toISOString();
1703
1704
  if (isDecaying(u, createdAt)) decayWarnings.push(m.id);
1704
1705
  }
1705
- const outputMemories = input.format === "compact" ? trimmedMemories.map((m) => ({ ...m, body: compactSummary(m.body) })) : input.format === "actions" ? trimmedMemories.map((m) => ({
1706
+ const formattedMemories = input.format === "compact" ? trimmedMemories.map((m) => ({ ...m, body: compactSummary(m.body) })) : input.format === "actions" ? trimmedMemories.map((m) => ({
1706
1707
  ...m,
1707
1708
  body: extractActionsBriefBody(m.body)
1708
1709
  })) : trimmedMemories;
1710
+ const outputMemories = formattedMemories.map((m) => ({
1711
+ ...m,
1712
+ why: explainWhySurfaced(m, byId.get(m.id), input.files, inferred)
1713
+ }));
1709
1714
  let symbolLocations;
1710
1715
  const symbolsToLookup = new Set(input.symbols);
1711
1716
  for (const m of outputMemories) {
@@ -1871,6 +1876,44 @@ function compactSummary(body) {
1871
1876
  }
1872
1877
  return body.slice(0, 120);
1873
1878
  }
1879
+ function explainWhySurfaced(memory, loaded, inputFiles, inferredModules) {
1880
+ const why = [];
1881
+ const fm = loaded?.memory.frontmatter;
1882
+ if (memory.reasons.includes("anchor") && fm) {
1883
+ const matching = fm.anchor.paths.filter(
1884
+ (p) => inputFiles.length === 0 || inputFiles.some((file) => pathsOverlap(p, file))
1885
+ );
1886
+ if (matching.length > 0) {
1887
+ why.push(`Anchored to touched path${matching.length === 1 ? "" : "s"}: ${matching.slice(0, 4).join(", ")}`);
1888
+ } else if (fm.anchor.paths.length > 0) {
1889
+ why.push(`Pulled by related anchor: ${fm.anchor.paths.slice(0, 4).join(", ")}`);
1890
+ }
1891
+ if (fm.anchor.symbols.length > 0) {
1892
+ why.push(`Anchor symbol${fm.anchor.symbols.length === 1 ? "" : "s"}: ${fm.anchor.symbols.slice(0, 4).join(", ")}`);
1893
+ }
1894
+ }
1895
+ if (memory.reasons.includes("module")) {
1896
+ const moduleHints = [
1897
+ ...memory.module ? [memory.module] : [],
1898
+ ...memory.tags.filter((tag) => inferredModules.includes(tag))
1899
+ ];
1900
+ const shown = moduleHints.length > 0 ? [...new Set(moduleHints)].join(", ") : inferredModules.join(", ");
1901
+ why.push(shown ? `Matched inferred module/tag: ${shown}` : "Matched inferred module context.");
1902
+ }
1903
+ if (memory.reasons.includes("domain")) {
1904
+ why.push("Matched inferred domain from the target file paths.");
1905
+ }
1906
+ if (memory.reasons.includes("semantic")) {
1907
+ const score = memory.semantic_score !== void 0 ? ` score=${Math.round(memory.semantic_score * 100) / 100}` : "";
1908
+ why.push(`${memory.match_quality === "exact" ? "Literal task match" : "Semantic/task relevance"}${score}.`);
1909
+ }
1910
+ why.push(`Confidence: ${memory.confidence}; read ${memory.read_count} time${memory.read_count === 1 ? "" : "s"}.`);
1911
+ if (memory.type === "attempt") why.push("Failed-approach record; read before repeating the same path.");
1912
+ if (memory.status === "proposed" || memory.status === "draft") {
1913
+ why.push("Unvalidated record; use cautiously or ask a human before treating it as policy.");
1914
+ }
1915
+ return why;
1916
+ }
1874
1917
  async function trySemanticHits(ctx, task, limit) {
1875
1918
  let mod;
1876
1919
  try {
@@ -2676,7 +2719,7 @@ import {
2676
2719
  getUsage as getUsage9,
2677
2720
  loadMemoriesFromDir as loadMemoriesFromDir20,
2678
2721
  loadUsageIndex as loadUsageIndex11,
2679
- pathsOverlap,
2722
+ pathsOverlap as pathsOverlap2,
2680
2723
  tokenizeQuery as tokenizeQuery5
2681
2724
  } from "@hiveai/core";
2682
2725
  import { z as z27 } from "zod";
@@ -2712,7 +2755,7 @@ async function memConflicts(input, ctx) {
2712
2755
  const otherText = (other.memory.body + " " + fm.tags.join(" ")).toLowerCase();
2713
2756
  const reasons = [];
2714
2757
  const sim = simScores?.get(fm.id) ?? null;
2715
- const hasPathOverlap = fm.anchor.paths.some((p) => targetPaths.some((tp) => pathsOverlap(p, tp)));
2758
+ const hasPathOverlap = fm.anchor.paths.some((p) => targetPaths.some((tp) => pathsOverlap2(p, tp)));
2716
2759
  const otherTokens = new Set(tokenizeQuery5(otherText));
2717
2760
  const tokenOverlap = countIntersection(targetTokens, otherTokens);
2718
2761
  const isSemanticNeighbor = sim !== null && sim >= input.min_score;
@@ -2747,7 +2790,7 @@ async function memConflicts(input, ctx) {
2747
2790
  body_preview: other.memory.body.split("\n").slice(0, 4).join("\n").slice(0, 300),
2748
2791
  similarity: sim,
2749
2792
  reasons,
2750
- shared_paths: fm.anchor.paths.filter((p) => targetPaths.some((tp) => pathsOverlap(p, tp)))
2793
+ shared_paths: fm.anchor.paths.filter((p) => targetPaths.some((tp) => pathsOverlap2(p, tp)))
2751
2794
  });
2752
2795
  }
2753
2796
  conflicts.sort((a, b) => {
@@ -2837,10 +2880,13 @@ async function preCommitCheck(input, ctx) {
2837
2880
  const filesTouching = new Set(relevantMatches.map((m) => m.id));
2838
2881
  const staleHits = verifyResult.results.filter((r) => r.stale && filesTouching.has(r.id));
2839
2882
  const blockOn = input.block_on;
2840
- const blockingWarnings = apResult.warnings.filter(isBlockingWarning);
2883
+ const classifiedWarnings = apResult.warnings.map(classifyWarning);
2884
+ const blockingWarnings = classifiedWarnings.filter((w) => w.level === "blocking");
2885
+ const reviewWarnings = classifiedWarnings.filter((w) => w.level === "review");
2886
+ const infoWarnings = classifiedWarnings.filter((w) => w.level === "info");
2841
2887
  let should_block = false;
2842
2888
  if (blockOn !== "never") {
2843
- if (blockOn === "any" && (apResult.warnings.length > 0 || staleHits.length > 0)) should_block = true;
2889
+ if (blockOn === "any" && (blockingWarnings.length > 0 || reviewWarnings.length > 0 || staleHits.length > 0)) should_block = true;
2844
2890
  if (blockOn === "high-confidence" && (blockingWarnings.length > 0 || staleHits.length > 0)) should_block = true;
2845
2891
  }
2846
2892
  const relevant_memories = relevantMatches.slice(0, 8).map((m) => ({
@@ -2854,10 +2900,12 @@ async function preCommitCheck(input, ctx) {
2854
2900
  summary: {
2855
2901
  anti_patterns: apResult.warnings.length,
2856
2902
  blocking_warnings: blockingWarnings.length,
2903
+ review_warnings: reviewWarnings.length,
2904
+ info_warnings: infoWarnings.length,
2857
2905
  relevant_memories: relevant_memories.length,
2858
2906
  stale_anchors: staleHits.length
2859
2907
  },
2860
- warnings: apResult.warnings,
2908
+ warnings: classifiedWarnings,
2861
2909
  relevant_memories,
2862
2910
  stale_anchors: staleHits.map((r) => ({
2863
2911
  id: r.id,
@@ -2867,6 +2915,30 @@ async function preCommitCheck(input, ctx) {
2867
2915
  }))
2868
2916
  };
2869
2917
  }
2918
+ function classifyWarning(warning) {
2919
+ if (isBlockingWarning(warning)) {
2920
+ return {
2921
+ ...warning,
2922
+ level: "blocking",
2923
+ rationale: "authoritative/trusted memory plus strong semantic match to the diff (score >= 0.65)"
2924
+ };
2925
+ }
2926
+ const hasSemantic = warning.reasons.includes("semantic");
2927
+ const semanticScore = warning.semantic_score ?? 0;
2928
+ const highConfidence = warning.confidence === "authoritative" || warning.confidence === "trusted";
2929
+ if (hasSemantic && semanticScore >= 0.45 || highConfidence && warning.reasons.includes("anchor") && warning.reasons.includes("literal")) {
2930
+ return {
2931
+ ...warning,
2932
+ level: "review",
2933
+ rationale: hasSemantic ? "semantic match is plausible but below blocking threshold" : "anchored high-confidence memory also matched diff tokens, but no strong semantic proof"
2934
+ };
2935
+ }
2936
+ return {
2937
+ ...warning,
2938
+ level: "info",
2939
+ rationale: "weak signal only (literal/anchor/low semantic evidence); surfaced for audit, hidden in concise CLI output"
2940
+ };
2941
+ }
2870
2942
  function isBlockingWarning(warning) {
2871
2943
  const highConfidence = warning.confidence === "authoritative" || warning.confidence === "trusted";
2872
2944
  if (!highConfidence) return false;
@@ -3458,7 +3530,7 @@ When done, respond with: "Imported N memories: [list of IDs]" or "Nothing action
3458
3530
  // src/server.ts
3459
3531
  import { loadConfigSync } from "@hiveai/core";
3460
3532
  var SERVER_NAME = "haive";
3461
- var SERVER_VERSION = "0.9.14";
3533
+ var SERVER_VERSION = "0.9.15";
3462
3534
  function jsonResult(data) {
3463
3535
  return {
3464
3536
  content: [
@@ -3472,9 +3544,12 @@ function jsonResult(data) {
3472
3544
  var ENFORCEMENT_PROFILE_TOOLS = /* @__PURE__ */ new Set([
3473
3545
  "get_briefing",
3474
3546
  "mem_save",
3547
+ "mem_tried",
3475
3548
  "mem_search",
3549
+ "mem_get",
3476
3550
  "mem_verify",
3477
3551
  "mem_relevant_to",
3552
+ "code_map",
3478
3553
  "pre_commit_check",
3479
3554
  "mem_session_end"
3480
3555
  ]);