@productbrain/mcp 0.0.1-beta.28 → 0.0.1-beta.29

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.
@@ -454,7 +454,6 @@ var COMMON_CHECKS = {
454
454
  };
455
455
  var PROFILES = /* @__PURE__ */ new Map([
456
456
  ["tensions", {
457
- idPrefix: "TEN",
458
457
  governedDraft: false,
459
458
  descriptionField: "description",
460
459
  defaults: [
@@ -506,7 +505,6 @@ var PROFILES = /* @__PURE__ */ new Map([
506
505
  ]
507
506
  }],
508
507
  ["business-rules", {
509
- idPrefix: "SOS",
510
508
  governedDraft: true,
511
509
  descriptionField: "description",
512
510
  defaults: [
@@ -543,7 +541,6 @@ var PROFILES = /* @__PURE__ */ new Map([
543
541
  ]
544
542
  }],
545
543
  ["glossary", {
546
- idPrefix: "GT",
547
544
  governedDraft: true,
548
545
  descriptionField: "canonical",
549
546
  defaults: [
@@ -589,7 +586,6 @@ var PROFILES = /* @__PURE__ */ new Map([
589
586
  ]
590
587
  }],
591
588
  ["decisions", {
592
- idPrefix: "DEC",
593
589
  governedDraft: false,
594
590
  descriptionField: "rationale",
595
591
  defaults: [
@@ -625,7 +621,6 @@ var PROFILES = /* @__PURE__ */ new Map([
625
621
  ]
626
622
  }],
627
623
  ["features", {
628
- idPrefix: "FEAT",
629
624
  governedDraft: false,
630
625
  descriptionField: "description",
631
626
  defaults: [],
@@ -650,7 +645,6 @@ var PROFILES = /* @__PURE__ */ new Map([
650
645
  ]
651
646
  }],
652
647
  ["audiences", {
653
- idPrefix: "AUD",
654
648
  governedDraft: false,
655
649
  descriptionField: "description",
656
650
  defaults: [],
@@ -669,7 +663,6 @@ var PROFILES = /* @__PURE__ */ new Map([
669
663
  ]
670
664
  }],
671
665
  ["strategy", {
672
- idPrefix: "STR",
673
666
  governedDraft: true,
674
667
  descriptionField: "description",
675
668
  defaults: [],
@@ -683,7 +676,6 @@ var PROFILES = /* @__PURE__ */ new Map([
683
676
  ]
684
677
  }],
685
678
  ["maps", {
686
- idPrefix: "MAP",
687
679
  governedDraft: false,
688
680
  descriptionField: "description",
689
681
  defaults: [],
@@ -694,7 +686,6 @@ var PROFILES = /* @__PURE__ */ new Map([
694
686
  ]
695
687
  }],
696
688
  ["chains", {
697
- idPrefix: "CHN",
698
689
  governedDraft: false,
699
690
  descriptionField: "description",
700
691
  defaults: [],
@@ -705,7 +696,6 @@ var PROFILES = /* @__PURE__ */ new Map([
705
696
  ]
706
697
  }],
707
698
  ["standards", {
708
- idPrefix: "STD",
709
699
  governedDraft: true,
710
700
  descriptionField: "description",
711
701
  defaults: [],
@@ -718,7 +708,6 @@ var PROFILES = /* @__PURE__ */ new Map([
718
708
  ]
719
709
  }],
720
710
  ["tracking-events", {
721
- idPrefix: "TE",
722
711
  governedDraft: false,
723
712
  descriptionField: "description",
724
713
  defaults: [],
@@ -730,7 +719,6 @@ var PROFILES = /* @__PURE__ */ new Map([
730
719
  }]
731
720
  ]);
732
721
  var FALLBACK_PROFILE = {
733
- idPrefix: "ENT",
734
722
  governedDraft: false,
735
723
  descriptionField: "description",
736
724
  defaults: [],
@@ -742,15 +730,6 @@ var FALLBACK_PROFILE = {
742
730
  COMMON_CHECKS.hasType
743
731
  ]
744
732
  };
745
- function generateEntryId(prefix) {
746
- const effectivePrefix = prefix || "ENT";
747
- const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
748
- let suffix = "";
749
- for (let i = 0; i < 6; i++) {
750
- suffix += chars[Math.floor(Math.random() * chars.length)];
751
- }
752
- return `${effectivePrefix}-${suffix}`;
753
- }
754
733
  function extractSearchTerms(name, description) {
755
734
  const text = `${name} ${description}`;
756
735
  return text.replace(/[^\w\s]/g, " ").split(/\s+/).filter((w) => w.length > 3).slice(0, 8).join(" ");
@@ -988,13 +967,13 @@ Or use \`list-collections\` to see available collections.`
988
967
  }
989
968
  data[profile.descriptionField || "description"] = description;
990
969
  const status = GOVERNED_COLLECTIONS.has(collection) ? "draft" : "draft";
991
- const finalEntryId = entryId ?? generateEntryId(profile.idPrefix);
970
+ let finalEntryId;
992
971
  let internalId;
993
972
  try {
994
973
  const agentId = getAgentSessionId();
995
- internalId = await mcpMutation("chain.createEntry", {
974
+ const result = await mcpMutation("chain.createEntry", {
996
975
  collectionSlug: collection,
997
- entryId: finalEntryId || void 0,
976
+ entryId: entryId ?? void 0,
998
977
  name,
999
978
  status,
1000
979
  data,
@@ -1002,6 +981,8 @@ Or use \`list-collections\` to see available collections.`
1002
981
  createdBy: agentId ? `agent:${agentId}` : "capture",
1003
982
  sessionId: agentId ?? void 0
1004
983
  });
984
+ internalId = result.docId;
985
+ finalEntryId = result.entryId;
1005
986
  await recordSessionActivity({ entryCreated: internalId });
1006
987
  } catch (error) {
1007
988
  const msg = error instanceof Error ? error.message : String(error);
@@ -1105,6 +1086,17 @@ Use \`get-entry\` to inspect the existing entry, or \`update-entry\` to modify i
1105
1086
  if (contradictionWarnings.length > 0) {
1106
1087
  await recordSessionActivity({ contradictionWarning: true });
1107
1088
  }
1089
+ let coachingSection = "";
1090
+ try {
1091
+ const verdictResult = await withTimeout(
1092
+ mcpMutation("quality.evaluateAtCapture", { entryId: finalEntryId }),
1093
+ 6e3
1094
+ );
1095
+ if (verdictResult?.verdict && verdictResult.verdict.tier !== "passive" && verdictResult.verdict.criteria.length > 0) {
1096
+ coachingSection = formatRubricCoaching(verdictResult);
1097
+ }
1098
+ } catch {
1099
+ }
1108
1100
  const wsCtx = await getWorkspaceContext();
1109
1101
  const lines = [
1110
1102
  `# Captured: ${finalEntryId || name}`,
@@ -1156,6 +1148,10 @@ Use \`get-entry\` to inspect the existing entry, or \`update-entry\` to modify i
1156
1148
  }
1157
1149
  lines.push("Run gather-context on these entries before committing.");
1158
1150
  }
1151
+ if (coachingSection) {
1152
+ lines.push("");
1153
+ lines.push(coachingSection);
1154
+ }
1159
1155
  lines.push("");
1160
1156
  lines.push("## Next Steps");
1161
1157
  const eid = finalEntryId || "(check entry ID)";
@@ -1211,7 +1207,6 @@ Use \`get-entry\` to inspect the existing entry, or \`update-entry\` to modify i
1211
1207
  results.push({ name: entry.name, collection: entry.collection, entryId: "", ok: false, autoLinks: 0, error: `Collection "${entry.collection}" not found` });
1212
1208
  continue;
1213
1209
  }
1214
- const finalEntryId = entry.entryId ?? generateEntryId(profile.idPrefix);
1215
1210
  const data = {};
1216
1211
  const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
1217
1212
  for (const field of col.fields ?? []) {
@@ -1248,15 +1243,17 @@ Use \`get-entry\` to inspect the existing entry, or \`update-entry\` to modify i
1248
1243
  data[profile.descriptionField || "description"] = entry.description;
1249
1244
  }
1250
1245
  try {
1251
- const internalId = await mcpMutation("chain.createEntry", {
1246
+ const result = await mcpMutation("chain.createEntry", {
1252
1247
  collectionSlug: entry.collection,
1253
- entryId: finalEntryId,
1248
+ entryId: entry.entryId ?? void 0,
1254
1249
  name: entry.name,
1255
1250
  status: "draft",
1256
1251
  data,
1257
1252
  createdBy,
1258
1253
  sessionId: agentId ?? void 0
1259
1254
  });
1255
+ const internalId = result.docId;
1256
+ const finalEntryId = result.entryId;
1260
1257
  let autoLinkCount = 0;
1261
1258
  const searchQuery = extractSearchTerms(entry.name, entry.description);
1262
1259
  if (searchQuery) {
@@ -1292,7 +1289,7 @@ Use \`get-entry\` to inspect the existing entry, or \`update-entry\` to modify i
1292
1289
  await recordSessionActivity({ entryCreated: internalId });
1293
1290
  } catch (error) {
1294
1291
  const msg = error instanceof Error ? error.message : String(error);
1295
- results.push({ name: entry.name, collection: entry.collection, entryId: finalEntryId, ok: false, autoLinks: 0, error: msg });
1292
+ results.push({ name: entry.name, collection: entry.collection, entryId: "", ok: false, autoLinks: 0, error: msg });
1296
1293
  }
1297
1294
  }
1298
1295
  const created = results.filter((r) => r.ok);
@@ -1372,6 +1369,13 @@ ${linkHints}`;
1372
1369
  } catch {
1373
1370
  }
1374
1371
  }
1372
+ try {
1373
+ const verdict = await mcpQuery("quality.getLatestVerdictForEntry", { entryId });
1374
+ if (verdict && verdict.criteria?.length > 0) {
1375
+ result.text += "\n\n" + formatRubricVerdictSection(verdict);
1376
+ }
1377
+ } catch {
1378
+ }
1375
1379
  return { content: [{ type: "text", text: result.text }] };
1376
1380
  }
1377
1381
  );
@@ -1500,6 +1504,74 @@ async function runContradictionCheck(name, description) {
1500
1504
  }
1501
1505
  return warnings;
1502
1506
  }
1507
+ function withTimeout(promise, ms) {
1508
+ return Promise.race([
1509
+ promise,
1510
+ new Promise(
1511
+ (_, reject) => setTimeout(() => reject(new Error("quality coaching timeout")), ms)
1512
+ )
1513
+ ]);
1514
+ }
1515
+ function formatRubricCoaching(result) {
1516
+ const { verdict, rogerMartin } = result;
1517
+ if (!verdict || verdict.criteria.length === 0) return "";
1518
+ const lines = ["## Semantic Quality"];
1519
+ const failed = (verdict.criteria ?? []).filter((c) => !c.passed);
1520
+ const total = verdict.criteria?.length ?? 0;
1521
+ const passedCount = total - failed.length;
1522
+ if (verdict.passed) {
1523
+ lines.push(`All ${total} rubric criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier).`);
1524
+ } else {
1525
+ lines.push(`${passedCount}/${total} criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier)`);
1526
+ lines.push("");
1527
+ for (const c of verdict.criteria) {
1528
+ const icon = c.passed ? "[x]" : "[ ]";
1529
+ const extra = c.passed ? "" : ` \u2014 ${c.hint}`;
1530
+ lines.push(`${icon} ${c.id}${extra}`);
1531
+ }
1532
+ if (verdict.weakest) {
1533
+ lines.push("");
1534
+ lines.push(`**Coaching hint:** ${verdict.weakest.hint}`);
1535
+ lines.push(`_Question to consider:_ ${verdict.weakest.questionTemplate}`);
1536
+ }
1537
+ }
1538
+ if (rogerMartin) {
1539
+ lines.push("");
1540
+ lines.push("### Roger Martin Test");
1541
+ if (rogerMartin.isStrategicChoice) {
1542
+ lines.push("This principle passes \u2014 the opposite is a reasonable strategic choice.");
1543
+ } else {
1544
+ lines.push(`This principle may not be a strategic choice. ${rogerMartin.reasoning}`);
1545
+ if (rogerMartin.suggestion) {
1546
+ lines.push(`_Suggestion:_ ${rogerMartin.suggestion}`);
1547
+ }
1548
+ }
1549
+ }
1550
+ return lines.join("\n");
1551
+ }
1552
+ function formatRubricVerdictSection(verdict) {
1553
+ if (!verdict || !verdict.criteria || verdict.criteria.length === 0) return "";
1554
+ const lines = ["## Semantic Quality"];
1555
+ const failed = verdict.criteria.filter((c) => !c.passed);
1556
+ const total = verdict.criteria.length;
1557
+ const passedCount = total - failed.length;
1558
+ if (failed.length === 0) {
1559
+ lines.push(`All ${total} rubric criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier, ${verdict.source} evaluation).`);
1560
+ } else {
1561
+ lines.push(`${passedCount}/${total} criteria pass for \`${verdict.canonicalKey}\` (${verdict.tier} tier, ${verdict.source} evaluation)`);
1562
+ lines.push("");
1563
+ for (const c of verdict.criteria) {
1564
+ const icon = c.passed ? "[x]" : "[ ]";
1565
+ const extra = c.passed ? "" : ` \u2014 ${c.hint}`;
1566
+ lines.push(`${icon} ${c.id}${extra}`);
1567
+ }
1568
+ if (verdict.weakest) {
1569
+ lines.push("");
1570
+ lines.push(`**Top improvement:** ${verdict.weakest.hint}`);
1571
+ }
1572
+ }
1573
+ return lines.join("\n");
1574
+ }
1503
1575
 
1504
1576
  export {
1505
1577
  runWithAuth,
@@ -1524,6 +1596,7 @@ export {
1524
1596
  formatQualityReport,
1525
1597
  checkEntryQuality,
1526
1598
  registerSmartCaptureTools,
1527
- runContradictionCheck
1599
+ runContradictionCheck,
1600
+ formatRubricCoaching
1528
1601
  };
1529
- //# sourceMappingURL=chunk-UZDFQUAR.js.map
1602
+ //# sourceMappingURL=chunk-CKXLZBWQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tools/smart-capture.ts","../src/auth.ts","../src/client.ts"],"sourcesContent":["/**\n * Smart capture — ARCH-node-mcp (Core layer)\n * Chain: FEAT-MCP-001 (MCP Server), ARCH-flow-smart-capture\n * Rules: SOS-016 (governed draft-first), SOS-015 (unique IDs within scope)\n */\n\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { mcpQuery, mcpMutation, getWorkspaceContext, requireWriteAccess, recordSessionActivity, getAgentSessionId } from \"../client.js\";\n\n// ── Collection Workflow Profiles ────────────────────────────────────────────\n\ninterface FieldDefault {\n key: string;\n value: unknown | \"today\" | \"infer\";\n}\n\ninterface QualityCheck {\n id: string;\n label: string;\n check: (ctx: CaptureContext) => boolean;\n suggestion?: (ctx: CaptureContext) => string;\n}\n\ninterface CollectionProfile {\n governedDraft: boolean;\n defaults: FieldDefault[];\n descriptionField: string;\n recommendedRelationTypes: string[];\n qualityChecks: QualityCheck[];\n inferField?: (ctx: CaptureContext) => Record<string, unknown>;\n}\n\ninterface CaptureContext {\n collection: string;\n name: string;\n description: string;\n context?: string;\n data: Record<string, unknown>;\n entryId: string;\n canonicalKey?: string;\n linksCreated: LinkResult[];\n linksSuggested: LinkSuggestion[];\n collectionFields: Array<{ key: string; type: string; required?: boolean }>;\n}\n\ninterface LinkResult {\n targetEntryId: string;\n targetName: string;\n targetCollection: string;\n relationType: string;\n}\n\ninterface LinkSuggestion {\n entryId?: string;\n name: string;\n collection: string;\n reason: string;\n preview: string;\n}\n\nconst AREA_KEYWORDS: Record<string, string[]> = {\n \"Architecture\": [\"convex\", \"schema\", \"database\", \"migration\", \"api\", \"backend\", \"infrastructure\", \"scaling\", \"performance\"],\n \"Chain\": [\"knowledge\", \"glossary\", \"entry\", \"collection\", \"terminology\", \"drift\", \"graph\", \"chain\", \"commit\"],\n \"AI & MCP Integration\": [\"mcp\", \"ai\", \"cursor\", \"agent\", \"tool\", \"llm\", \"prompt\", \"context\"],\n \"Developer Experience\": [\"dx\", \"developer\", \"ide\", \"workflow\", \"friction\", \"ceremony\"],\n \"Governance & Decision-Making\": [\"governance\", \"decision\", \"rule\", \"policy\", \"compliance\", \"approval\"],\n \"Analytics & Tracking\": [\"analytics\", \"posthog\", \"tracking\", \"event\", \"metric\", \"funnel\"],\n \"Security\": [\"security\", \"auth\", \"api key\", \"permission\", \"access\", \"token\"],\n};\n\nfunction inferArea(text: string): string {\n const lower = text.toLowerCase();\n let bestArea = \"\";\n let bestScore = 0;\n for (const [area, keywords] of Object.entries(AREA_KEYWORDS)) {\n const score = keywords.filter((kw) => lower.includes(kw)).length;\n if (score > bestScore) {\n bestScore = score;\n bestArea = area;\n }\n }\n return bestArea;\n}\n\nfunction inferDomain(text: string): string {\n return inferArea(text) || \"\";\n}\n\nconst COMMON_CHECKS: Record<string, QualityCheck> = {\n clearName: {\n id: \"clear-name\",\n label: \"Clear, specific name (not vague)\",\n check: (ctx) => ctx.name.length > 10 && ![\"new tension\", \"new entry\", \"untitled\", \"test\"].includes(ctx.name.toLowerCase()),\n suggestion: () => \"Rename to something specific — describe the actual problem or concept.\",\n },\n hasDescription: {\n id: \"has-description\",\n label: \"Description provided (>50 chars)\",\n check: (ctx) => ctx.description.length > 50,\n suggestion: () => \"Add a fuller description explaining context and impact.\",\n },\n hasRelations: {\n id: \"has-relations\",\n label: \"At least 1 relation created\",\n check: (ctx) => ctx.linksCreated.length >= 1,\n suggestion: () => \"Use `suggest-links` and `relate-entries` to add more connections.\",\n },\n diverseRelations: {\n id: \"diverse-relations\",\n label: \"Relations span multiple collections\",\n check: (ctx) => {\n const colls = new Set(ctx.linksCreated.map((l) => l.targetCollection));\n return colls.size >= 2;\n },\n suggestion: () => \"Try linking to entries in different collections (glossary, business-rules, strategy).\",\n },\n hasType: {\n id: \"has-type\",\n label: \"Has canonical type\",\n check: (ctx) => !!ctx.data?.canonicalKey || !!ctx.canonicalKey,\n suggestion: () => \"Classify this entry with a canonical type for better context assembly. Use update-entry to set canonicalKey.\",\n },\n};\n\nconst PROFILES: Map<string, CollectionProfile> = new Map([\n [\"tensions\", {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [\n { key: \"priority\", value: \"medium\" },\n { key: \"date\", value: \"today\" },\n { key: \"raised\", value: \"infer\" },\n { key: \"severity\", value: \"infer\" },\n ],\n recommendedRelationTypes: [\"surfaces_tension_in\", \"references\", \"belongs_to\", \"related_to\"],\n inferField: (ctx: CaptureContext) => {\n const fields: Record<string, unknown> = {};\n const text = `${ctx.name} ${ctx.description}`;\n const area = inferArea(text);\n if (area) fields.raised = area;\n if (text.toLowerCase().includes(\"critical\") || text.toLowerCase().includes(\"blocker\")) {\n fields.severity = \"critical\";\n } else if (text.toLowerCase().includes(\"bottleneck\") || text.toLowerCase().includes(\"scaling\") || text.toLowerCase().includes(\"breaking\")) {\n fields.severity = \"high\";\n } else {\n fields.severity = \"medium\";\n }\n if (area) fields.affectedArea = area;\n return fields;\n },\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n {\n id: \"has-severity\",\n label: \"Severity specified\",\n check: (ctx) => !!ctx.data.severity && ctx.data.severity !== \"\",\n suggestion: (ctx) => {\n const text = `${ctx.name} ${ctx.description}`.toLowerCase();\n const inferred = text.includes(\"critical\") ? \"critical\" : text.includes(\"bottleneck\") ? \"high\" : \"medium\";\n return `Set severity — suggest: ${inferred} (based on description keywords).`;\n },\n },\n {\n id: \"has-affected-area\",\n label: \"Affected area identified\",\n check: (ctx) => !!ctx.data.affectedArea && ctx.data.affectedArea !== \"\",\n suggestion: (ctx) => {\n const area = inferArea(`${ctx.name} ${ctx.description}`);\n return area\n ? `Set affectedArea — suggest: \"${area}\" (inferred from content).`\n : \"Specify which product area or domain this tension impacts.\";\n },\n },\n ],\n }],\n\n [\"business-rules\", {\n governedDraft: true,\n descriptionField: \"description\",\n defaults: [\n { key: \"severity\", value: \"medium\" },\n { key: \"domain\", value: \"infer\" },\n ],\n recommendedRelationTypes: [\"governs\", \"references\", \"conflicts_with\", \"related_to\"],\n inferField: (ctx: CaptureContext) => {\n const fields: Record<string, unknown> = {};\n const domain = inferDomain(`${ctx.name} ${ctx.description}`);\n if (domain) fields.domain = domain;\n return fields;\n },\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n {\n id: \"has-rationale\",\n label: \"Rationale provided\",\n check: (ctx) => typeof ctx.data.rationale === \"string\" && ctx.data.rationale.length > 10,\n suggestion: () => \"Add a rationale explaining why this rule exists via `update-entry`.\",\n },\n {\n id: \"has-domain\",\n label: \"Domain specified\",\n check: (ctx) => !!ctx.data.domain && ctx.data.domain !== \"\",\n suggestion: (ctx) => {\n const domain = inferDomain(`${ctx.name} ${ctx.description}`);\n return domain\n ? `Set domain — suggest: \"${domain}\" (inferred from content).`\n : \"Specify the business domain this rule belongs to.\";\n },\n },\n ],\n }],\n\n [\"glossary\", {\n governedDraft: true,\n descriptionField: \"canonical\",\n defaults: [\n { key: \"category\", value: \"infer\" },\n ],\n recommendedRelationTypes: [\"defines_term_for\", \"confused_with\", \"related_to\", \"references\"],\n inferField: (ctx: CaptureContext) => {\n const fields: Record<string, unknown> = {};\n const area = inferArea(`${ctx.name} ${ctx.description}`);\n if (area) {\n const categoryMap: Record<string, string> = {\n \"Architecture\": \"Platform & Architecture\",\n \"Chain\": \"Knowledge Management\",\n \"AI & MCP Integration\": \"AI & Developer Tools\",\n \"Developer Experience\": \"AI & Developer Tools\",\n \"Governance & Decision-Making\": \"Governance & Process\",\n \"Analytics & Tracking\": \"Platform & Architecture\",\n \"Security\": \"Platform & Architecture\",\n };\n fields.category = categoryMap[area] ?? \"\";\n }\n return fields;\n },\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasType,\n {\n id: \"has-canonical\",\n label: \"Canonical definition provided (>20 chars)\",\n check: (ctx) => {\n const canonical = ctx.data.canonical;\n return typeof canonical === \"string\" && canonical.length > 20;\n },\n suggestion: () => \"Add a clear canonical definition — this is the single source of truth for this term.\",\n },\n COMMON_CHECKS.hasRelations,\n {\n id: \"has-category\",\n label: \"Category assigned\",\n check: (ctx) => !!ctx.data.category && ctx.data.category !== \"\",\n suggestion: () => \"Assign a category (e.g., 'Platform & Architecture', 'Governance & Process').\",\n },\n ],\n }],\n\n [\"decisions\", {\n governedDraft: false,\n descriptionField: \"rationale\",\n defaults: [\n { key: \"date\", value: \"today\" },\n { key: \"decidedBy\", value: \"infer\" },\n ],\n recommendedRelationTypes: [\"informs\", \"references\", \"replaces\", \"related_to\"],\n inferField: (ctx: CaptureContext) => {\n const fields: Record<string, unknown> = {};\n const area = inferArea(`${ctx.name} ${ctx.description}`);\n if (area) fields.decidedBy = area;\n return fields;\n },\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasType,\n {\n id: \"has-rationale\",\n label: \"Rationale provided (>30 chars)\",\n check: (ctx) => {\n const rationale = ctx.data.rationale;\n return typeof rationale === \"string\" && rationale.length > 30;\n },\n suggestion: () => \"Explain why this decision was made — what was considered and rejected?\",\n },\n COMMON_CHECKS.hasRelations,\n {\n id: \"has-date\",\n label: \"Decision date recorded\",\n check: (ctx) => !!ctx.data.date && ctx.data.date !== \"\",\n suggestion: () => \"Record when this decision was made.\",\n },\n ],\n }],\n\n [\"features\", {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [] as FieldDefault[],\n recommendedRelationTypes: [\"belongs_to\", \"depends_on\", \"surfaces_tension_in\", \"related_to\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n {\n id: \"has-owner\",\n label: \"Owner assigned\",\n check: (ctx: CaptureContext) => !!ctx.data.owner && ctx.data.owner !== \"\",\n suggestion: () => \"Assign an owner team or product area.\",\n },\n {\n id: \"has-rationale\",\n label: \"Rationale documented\",\n check: (ctx: CaptureContext) => !!ctx.data.rationale && String(ctx.data.rationale).length > 20,\n suggestion: () => \"Explain why this feature matters — what problem does it solve?\",\n },\n ],\n } satisfies CollectionProfile],\n\n [\"audiences\", {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"fills_slot\", \"informs\", \"related_to\", \"references\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n {\n id: \"has-behaviors\",\n label: \"Behaviors described\",\n check: (ctx) => typeof ctx.data.behaviors === \"string\" && ctx.data.behaviors.length > 20,\n suggestion: () => \"Describe how this audience segment behaves — what do they do, what tools do they use?\",\n },\n ],\n }],\n\n [\"strategy\", {\n governedDraft: true,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"informs\", \"governs\", \"belongs_to\", \"related_to\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n COMMON_CHECKS.diverseRelations,\n ],\n }],\n\n [\"maps\", {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"fills_slot\", \"references\", \"related_to\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n ],\n }],\n\n [\"chains\", {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"informs\", \"references\", \"related_to\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n ],\n }],\n\n [\"standards\", {\n governedDraft: true,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"governs\", \"defines_term_for\", \"references\", \"related_to\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n ],\n }],\n\n [\"tracking-events\", {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"references\", \"belongs_to\", \"related_to\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n ],\n }],\n]);\n\nconst FALLBACK_PROFILE: CollectionProfile = {\n governedDraft: false,\n descriptionField: \"description\",\n defaults: [],\n recommendedRelationTypes: [\"related_to\", \"references\"],\n qualityChecks: [\n COMMON_CHECKS.clearName,\n COMMON_CHECKS.hasDescription,\n COMMON_CHECKS.hasRelations,\n COMMON_CHECKS.hasType,\n ],\n};\n\n// ── Auto-Linking Logic ──────────────────────────────────────────────────────\n\nfunction extractSearchTerms(name: string, description: string): string {\n const text = `${name} ${description}`;\n return text\n .replace(/[^\\w\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 3)\n .slice(0, 8)\n .join(\" \");\n}\n\ninterface LinkConfidenceResult {\n score: number;\n reason: string;\n}\n\nfunction computeLinkConfidence(\n candidate: { name: string; data?: any; entryId?: string },\n sourceName: string,\n sourceDescription: string,\n sourceCollection: string,\n candidateCollection: string,\n): LinkConfidenceResult {\n const text = `${sourceName} ${sourceDescription}`.toLowerCase();\n const candidateName = candidate.name.toLowerCase();\n let score = 0;\n const reasons: string[] = [];\n\n if (text.includes(candidateName) && candidateName.length > 3) {\n score += 40;\n reasons.push(\"name match\");\n }\n\n const candidateWords = candidateName.split(/\\s+/).filter((w) => w.length > 3);\n const matchingWords = candidateWords.filter((w) => text.includes(w));\n const wordScore = (matchingWords.length / Math.max(candidateWords.length, 1)) * 30;\n score += wordScore;\n if (matchingWords.length > 0) {\n reasons.push(`word overlap (${matchingWords.slice(0, 3).join(\", \")})`);\n }\n\n const HUB_COLLECTIONS = new Set([\"strategy\", \"features\"]);\n if (HUB_COLLECTIONS.has(candidateCollection)) {\n score += 15;\n reasons.push(\"hub collection\");\n }\n\n if (candidateCollection !== sourceCollection) {\n score += 10;\n reasons.push(\"cross-collection\");\n }\n\n const finalScore = Math.min(score, 100);\n const reason = reasons.length > 0 ? reasons.join(\" + \") : \"low relevance\";\n return { score: finalScore, reason };\n}\n\ninterface RelationTypeResult {\n type: string;\n reason: string;\n}\n\nfunction inferRelationType(\n sourceCollection: string,\n targetCollection: string,\n profile: CollectionProfile,\n): RelationTypeResult {\n const typeMap: Record<string, Record<string, string>> = {\n tensions: {\n glossary: \"surfaces_tension_in\",\n \"business-rules\": \"references\",\n strategy: \"belongs_to\",\n features: \"surfaces_tension_in\",\n decisions: \"references\",\n },\n \"business-rules\": {\n glossary: \"references\",\n features: \"governs\",\n strategy: \"belongs_to\",\n tensions: \"references\",\n },\n glossary: {\n features: \"defines_term_for\",\n \"business-rules\": \"references\",\n strategy: \"references\",\n },\n decisions: {\n features: \"informs\",\n \"business-rules\": \"references\",\n strategy: \"references\",\n tensions: \"references\",\n },\n };\n\n const mapped = typeMap[sourceCollection]?.[targetCollection];\n const type = mapped ?? profile.recommendedRelationTypes[0] ?? \"related_to\";\n const reason = mapped\n ? `collection pair (${sourceCollection} → ${targetCollection})`\n : `profile default (${profile.recommendedRelationTypes[0] ?? \"related_to\"})`;\n return { type, reason };\n}\n\n// ── Quality Scoring ─────────────────────────────────────────────────────────\n\ninterface QualityResult {\n score: number;\n maxScore: number;\n checks: Array<{ id: string; label: string; passed: boolean; suggestion?: string }>;\n}\n\nfunction scoreQuality(ctx: CaptureContext, profile: CollectionProfile): QualityResult {\n const checks = profile.qualityChecks.map((qc) => {\n const passed = qc.check(ctx);\n return {\n id: qc.id,\n label: qc.label,\n passed,\n suggestion: passed ? undefined : qc.suggestion?.(ctx),\n };\n });\n\n const passed = checks.filter((c) => c.passed).length;\n const total = checks.length;\n const score = total > 0 ? Math.round((passed / total) * 10) : 10;\n\n return { score, maxScore: 10, checks };\n}\n\nexport function formatQualityReport(result: QualityResult): string {\n const failed = result.checks.filter((c) => !c.passed);\n const reason = failed.length > 0\n ? ` because ${failed.map((c) => c.suggestion ?? c.label.toLowerCase()).join(\"; \")}`\n : \"\";\n const lines: string[] = [`## Quality: ${result.score}/${result.maxScore}${reason}`];\n for (const check of result.checks) {\n const icon = check.passed ? \"[x]\" : \"[ ]\";\n const suggestion = check.passed ? \"\" : ` — ${check.suggestion ?? check.label}`;\n lines.push(`${icon} ${check.label}${suggestion}`);\n }\n return lines.join(\"\\n\");\n}\n\n// ── Exported: quality-check for existing entries ────────────────────────────\n\nexport async function checkEntryQuality(entryId: string): Promise<{ text: string; quality: QualityResult }> {\n const entry = await mcpQuery<any>(\"chain.getEntry\", { entryId });\n if (!entry) {\n return {\n text: `Entry \\`${entryId}\\` not found. Try search to find the right ID.`,\n quality: { score: 0, maxScore: 10, checks: [] },\n };\n }\n\n const collections = await mcpQuery<any[]>(\"chain.listCollections\");\n const collMap = new Map<string, string>();\n for (const c of collections) collMap.set(c._id, c.slug);\n const collectionSlug = collMap.get(entry.collectionId) ?? \"unknown\";\n\n const profile = PROFILES.get(collectionSlug) ?? FALLBACK_PROFILE;\n\n const relations = await mcpQuery<any[]>(\"chain.listEntryRelations\", { entryId });\n const linksCreated: LinkResult[] = [];\n for (const r of relations) {\n const otherId = r.fromId === entry._id ? r.toId : r.fromId;\n linksCreated.push({\n targetEntryId: otherId,\n targetName: \"\",\n targetCollection: \"\",\n relationType: r.type,\n });\n }\n\n const descField = profile.descriptionField;\n const description = typeof entry.data?.[descField] === \"string\" ? entry.data[descField] : \"\";\n\n const ctx: CaptureContext = {\n collection: collectionSlug,\n name: entry.name,\n description,\n data: entry.data ?? {},\n entryId: entry.entryId ?? \"\",\n canonicalKey: entry.canonicalKey,\n linksCreated,\n linksSuggested: [],\n collectionFields: [],\n };\n\n const quality = scoreQuality(ctx, profile);\n\n const lines: string[] = [\n `# Quality Check: ${entry.entryId ?? entry.name}`,\n `**${entry.name}** in \\`${collectionSlug}\\` [${entry.status}]`,\n \"\",\n formatQualityReport(quality),\n ];\n\n if (quality.score < 10) {\n const failedChecks = quality.checks.filter((c) => !c.passed && c.suggestion);\n if (failedChecks.length > 0) {\n lines.push(\"\");\n lines.push(`_To improve: use \\`update-entry\\` to fill missing fields, or \\`relate-entries\\` to add connections._`);\n }\n }\n\n return { text: lines.join(\"\\n\"), quality };\n}\n\n// ── Tool Registration ───────────────────────────────────────────────────────\n\nconst GOVERNED_COLLECTIONS = new Set([\n \"glossary\", \"business-rules\", \"principles\", \"standards\", \"strategy\", \"features\",\n]);\n\nconst AUTO_LINK_CONFIDENCE_THRESHOLD = 35;\nconst MAX_AUTO_LINKS = 5;\nconst MAX_SUGGESTIONS = 5;\n\nexport function registerSmartCaptureTools(server: McpServer) {\n\n server.registerTool(\n \"capture\",\n {\n title: \"Capture\",\n description:\n \"The single tool for creating knowledge entries. Creates an entry, auto-links related entries, \" +\n \"and returns a quality scorecard — all in one call. \" +\n \"Provide a collection, name, and description — everything else is inferred or auto-filled.\\n\\n\" +\n \"Supported collections with smart profiles: tensions, business-rules, glossary, decisions, features, \" +\n \"audiences, strategy, standards, maps, chains, tracking-events.\\n\" +\n \"All other collections get an ENT-{random} ID and sensible defaults.\\n\\n\" +\n \"**Explicit data:** When you know the schema, pass `data: { field: value }` to set fields directly. \" +\n \"Top-level `name` and `description` always win for those fields. `data` wins over inference for all other fields.\\n\\n\" +\n \"Always creates as 'draft' for governed collections. Use `update-entry` for post-creation adjustments.\",\n inputSchema: {\n collection: z.string().describe(\"Collection slug, e.g. 'tensions', 'business-rules', 'glossary', 'decisions'\"),\n name: z.string().describe(\"Display name — be specific (e.g. 'Convex adjacency list won't scale for graph traversal')\"),\n description: z.string().describe(\"Full context — what's happening, why it matters, what you observed\"),\n context: z.string().optional().describe(\"Optional additional context (e.g. 'Observed during gather-context calls taking 700ms+')\"),\n entryId: z.string().optional().describe(\"Optional custom entry ID (e.g. 'TEN-my-id'). Auto-generated if omitted.\"),\n canonicalKey: z.string().optional().describe(\"Semantic type (e.g. 'decision', 'tension', 'vision'). Auto-assigned from collection if omitted.\"),\n data: z.record(z.unknown()).optional().describe(\"Explicit field values when you know the schema (e.g. canonical_key, cardinality_rule, required_fields). Merged with inferred values; user-provided wins.\"),\n },\n annotations: { destructiveHint: false },\n },\n async ({ collection, name, description, context, entryId, canonicalKey, data: userData }) => {\n requireWriteAccess();\n\n const profile = PROFILES.get(collection) ?? FALLBACK_PROFILE;\n\n const col = await mcpQuery<any>(\"chain.getCollection\", { slug: collection });\n if (!col) {\n const displayName = collection.split(\"-\").map((w: string) => w.charAt(0).toUpperCase() + w.slice(1)).join(\" \");\n return {\n content: [{\n type: \"text\" as const,\n text:\n `Collection \\`${collection}\\` not found.\\n\\n` +\n `**To create it**, run:\\n` +\n `\\`\\`\\`\\ncreate-collection slug=\"${collection}\" name=\"${displayName}\" description=\"...\"\\n\\`\\`\\`\\n\\n` +\n `Or use \\`list-collections\\` to see available collections.`,\n }],\n };\n }\n\n // 2. Build data with profile defaults + inference\n const data: Record<string, unknown> = {};\n const today = new Date().toISOString().split(\"T\")[0];\n\n for (const field of col.fields ?? []) {\n const key = field.key as string;\n if (key === profile.descriptionField) {\n data[key] = description;\n } else if (field.type === \"array\" || field.type === \"multi-select\") {\n data[key] = [];\n } else if (field.type === \"select\") {\n // Skip — empty string is not a valid option for select fields\n } else {\n data[key] = \"\";\n }\n }\n\n for (const def of profile.defaults) {\n if (def.value === \"today\") {\n data[def.key] = today;\n } else if (def.value !== \"infer\") {\n data[def.key] = def.value;\n }\n }\n\n if (profile.inferField) {\n const inferred = profile.inferField({\n collection, name, description, context, data, entryId: \"\",\n linksCreated: [], linksSuggested: [], collectionFields: col.fields ?? [],\n });\n for (const [key, val] of Object.entries(inferred)) {\n if (val !== undefined && val !== \"\") {\n data[key] = val;\n }\n }\n }\n\n // Merge user-provided data (wins over inference for those fields)\n if (userData && typeof userData === \"object\") {\n for (const [key, val] of Object.entries(userData)) {\n if (key !== \"name\") data[key] = val;\n }\n }\n\n // Top-level description always wins\n data[profile.descriptionField || \"description\"] = description;\n\n // 3. Determine status\n const status = GOVERNED_COLLECTIONS.has(collection) ? \"draft\" : \"draft\";\n\n // 4. Create entry (Convex generates sequential ID when entryId not provided)\n let finalEntryId: string;\n let internalId: string;\n try {\n const agentId = getAgentSessionId();\n const result = await mcpMutation<{ docId: string; entryId: string }>(\"chain.createEntry\", {\n collectionSlug: collection,\n entryId: entryId ?? undefined,\n name,\n status,\n data,\n canonicalKey,\n createdBy: agentId ? `agent:${agentId}` : \"capture\",\n sessionId: agentId ?? undefined,\n });\n internalId = result.docId;\n finalEntryId = result.entryId;\n\n await recordSessionActivity({ entryCreated: internalId });\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n if (msg.includes(\"Duplicate\") || msg.includes(\"already exists\")) {\n return {\n content: [{\n type: \"text\" as const,\n text: `# Cannot Capture — Duplicate Detected\\n\\n${msg}\\n\\nUse \\`get-entry\\` to inspect the existing entry, or \\`update-entry\\` to modify it.`,\n }],\n };\n }\n throw error;\n }\n\n // 6. Discover and auto-link related entries\n const linksCreated: LinkResult[] = [];\n const linksSuggested: LinkSuggestion[] = [];\n\n const searchQuery = extractSearchTerms(name, description);\n if (searchQuery) {\n const [searchResults, allCollections] = await Promise.all([\n mcpQuery<any[]>(\"chain.searchEntries\", { query: searchQuery }),\n mcpQuery<any[]>(\"chain.listCollections\"),\n ]);\n\n const collMap = new Map<string, string>();\n for (const c of allCollections) collMap.set(c._id, c.slug);\n\n const candidates = (searchResults ?? [])\n .filter((r) => r.entryId !== finalEntryId && r._id !== internalId)\n .map((r) => {\n const conf = computeLinkConfidence(r, name, description, collection, collMap.get(r.collectionId) ?? \"unknown\");\n return {\n ...r,\n collSlug: collMap.get(r.collectionId) ?? \"unknown\",\n confidence: conf.score,\n confidenceReason: conf.reason,\n };\n })\n .sort((a, b) => b.confidence - a.confidence);\n\n // Auto-link high-confidence matches\n for (const c of candidates) {\n if (linksCreated.length >= MAX_AUTO_LINKS) break;\n if (c.confidence < AUTO_LINK_CONFIDENCE_THRESHOLD) break;\n if (!c.entryId || !finalEntryId) continue;\n\n const { type: relationType, reason: relationReason } = inferRelationType(collection, c.collSlug, profile);\n try {\n await mcpMutation(\"chain.createEntryRelation\", {\n fromEntryId: finalEntryId,\n toEntryId: c.entryId,\n type: relationType,\n });\n linksCreated.push({\n targetEntryId: c.entryId,\n targetName: c.name,\n targetCollection: c.collSlug,\n relationType,\n linkReason: `confidence ${c.confidence} (${(c as any).confidenceReason}) + ${relationReason}`,\n });\n } catch {\n // Relation creation failed (e.g. entry not found) — skip silently\n }\n }\n\n // Collect suggestions for remaining candidates\n const linkedIds = new Set(linksCreated.map((l) => l.targetEntryId));\n for (const c of candidates) {\n if (linksSuggested.length >= MAX_SUGGESTIONS) break;\n if (linkedIds.has(c.entryId)) continue;\n if (c.confidence < 10) continue;\n\n const preview = extractPreview(c.data, 80);\n const reason = c.confidence >= AUTO_LINK_CONFIDENCE_THRESHOLD\n ? \"high relevance (already linked)\"\n : `\"${c.name.toLowerCase().split(/\\s+/).filter((w: string) => `${name} ${description}`.toLowerCase().includes(w) && w.length > 3).slice(0, 2).join('\", \"')}\" appears in content`;\n\n linksSuggested.push({\n entryId: c.entryId,\n name: c.name,\n collection: c.collSlug,\n reason,\n preview,\n });\n }\n }\n\n // 7. Score quality\n const captureCtx: CaptureContext = {\n collection,\n name,\n description,\n context,\n data,\n entryId: finalEntryId,\n canonicalKey,\n linksCreated,\n linksSuggested,\n collectionFields: col.fields ?? [],\n };\n const quality = scoreQuality(captureCtx, profile);\n\n // 8. Cardinality check for singleton types\n let cardinalityWarning: string | null = null;\n const resolvedCK = canonicalKey ?? (captureCtx as any).canonicalKey;\n if (resolvedCK) {\n try {\n const check = await mcpQuery<any>(\"chain.checkCardinalityWarning\", {\n canonicalKey: resolvedCK,\n });\n if (check?.warning) {\n cardinalityWarning = check.warning;\n }\n } catch {\n // Advisory — capture succeeds without cardinality check\n }\n }\n\n // 9. Keyword contradiction check against governance entries\n const contradictionWarnings = await runContradictionCheck(name, description);\n if (contradictionWarnings.length > 0) {\n await recordSessionActivity({ contradictionWarning: true });\n }\n\n // 10. Quality coaching (rubric-based semantic evaluation)\n let coachingSection = \"\";\n try {\n const verdictResult = await withTimeout(\n mcpMutation<any>(\"quality.evaluateAtCapture\", { entryId: finalEntryId }),\n 6000,\n );\n if (verdictResult?.verdict && verdictResult.verdict.tier !== \"passive\" && verdictResult.verdict.criteria.length > 0) {\n coachingSection = formatRubricCoaching(verdictResult);\n }\n } catch {\n // Quality coaching is advisory — capture succeeds without it\n }\n\n // 11. Format response\n const wsCtx = await getWorkspaceContext();\n const lines: string[] = [\n `# Captured: ${finalEntryId || name}`,\n `**${name}** added to \\`${collection}\\` as \\`${status}\\``,\n `**Workspace:** ${wsCtx.workspaceSlug} (${wsCtx.workspaceId})`,\n ];\n\n if (linksCreated.length > 0) {\n lines.push(\"\");\n lines.push(`## Auto-linked (${linksCreated.length})`);\n for (const link of linksCreated) {\n const reason = (link as any).linkReason ? ` — because ${(link as any).linkReason}` : \"\";\n lines.push(`- -> **${link.relationType}** ${link.targetEntryId}: ${link.targetName} [${link.targetCollection}]${reason}`);\n }\n }\n\n if (linksSuggested.length > 0) {\n lines.push(\"\");\n lines.push(\"## Suggested links (review and use relate-entries)\");\n for (let i = 0; i < linksSuggested.length; i++) {\n const s = linksSuggested[i];\n const preview = s.preview ? ` — ${s.preview}` : \"\";\n lines.push(`${i + 1}. **${s.entryId ?? \"(no ID)\"}**: ${s.name} [${s.collection}]${preview}`);\n }\n }\n\n lines.push(\"\");\n lines.push(formatQualityReport(quality));\n\n const failedChecks = quality.checks.filter((c) => !c.passed);\n if (failedChecks.length > 0) {\n lines.push(\"\");\n lines.push(`_To improve: \\`update-entry entryId=\"${finalEntryId}\"\\` to fill missing fields._`);\n }\n\n // Strategy-link warning for bet/goal (ENT-ldomlr: Intelligence Surface)\n const isBetOrGoal =\n collection === \"bets\" ||\n resolvedCK === \"bet\" ||\n resolvedCK === \"goal\";\n const hasStrategyLink = linksCreated.some((l) => l.targetCollection === \"strategy\");\n if (isBetOrGoal && !hasStrategyLink) {\n lines.push(\"\");\n lines.push(\n `**Strategy link:** This ${collection === \"bets\" ? \"bet\" : \"goal\"} doesn't connect to any strategy entry. Consider linking before commit. Use \\`suggest-links entryId=\"${finalEntryId}\"\\` to find strategy entries to connect to.`\n );\n await recordSessionActivity({ strategyLinkWarnedForEntryId: internalId });\n }\n\n // Cardinality warning for singleton types (DEC-zcuhvb)\n if (cardinalityWarning) {\n lines.push(\"\");\n lines.push(`**Cardinality warning:** ${cardinalityWarning}`);\n }\n\n // Contradiction warnings — exact format per spec\n if (contradictionWarnings.length > 0) {\n lines.push(\"\");\n lines.push(\"⚠ Contradiction check: proposed entry matched existing governance entries:\");\n for (const w of contradictionWarnings) {\n lines.push(`- ${w.name} (${w.collection}, ${w.entryId}) — has 'governs' relation to ${w.governsCount} entries`);\n }\n lines.push(\"Run gather-context on these entries before committing.\");\n }\n\n // Rubric coaching (assertive/nudge only)\n if (coachingSection) {\n lines.push(\"\");\n lines.push(coachingSection);\n }\n\n // Next steps: guide the agent to connect and commit\n lines.push(\"\");\n lines.push(\"## Next Steps\");\n const eid = finalEntryId || \"(check entry ID)\";\n lines.push(`1. **Connect it:** \\`suggest-links entryId=\"${eid}\"\\` — discover what this should link to`);\n lines.push(`2. **Commit it:** \\`commit-entry entryId=\"${eid}\"\\` — promote from draft to SSOT on the Chain`);\n if (failedChecks.length > 0) {\n lines.push(`3. **Improve quality:** \\`update-entry entryId=\"${eid}\"\\` — fill missing fields`);\n }\n\n // Advisory: workspace readiness hints (never blocking)\n try {\n const readiness = await mcpQuery<any>(\"chain.workspaceReadiness\");\n if (readiness && readiness.gaps && readiness.gaps.length > 0) {\n const topGaps = readiness.gaps.slice(0, 2);\n lines.push(\"\");\n lines.push(`## Workspace Readiness: ${readiness.score}%`);\n for (const gap of topGaps) {\n lines.push(`- _${gap.label}:_ ${gap.guidance}`);\n }\n }\n } catch {\n // Readiness check is advisory — capture works without it\n }\n\n return { content: [{ type: \"text\" as const, text: lines.join(\"\\n\") }] };\n }\n );\n\n // ── Batch Capture Tool ─────────────────────────────────────────────────\n\n server.registerTool(\n \"batch-capture\",\n {\n title: \"Batch Capture\",\n description:\n \"Create multiple knowledge entries in one call. Ideal for workspace setup, document ingestion, \" +\n \"or any scenario where you need to capture many entries at once.\\n\\n\" +\n \"Each entry is created independently — if one fails, the others still succeed. \" +\n \"Returns a compact summary instead of per-entry quality scorecards.\\n\\n\" +\n \"Auto-linking runs per entry but contradiction checks and readiness hints are skipped for speed. \" +\n \"Use `quality-check` on individual entries afterward if needed.\",\n inputSchema: {\n entries: z.array(z.object({\n collection: z.string().describe(\"Collection slug\"),\n name: z.string().describe(\"Display name\"),\n description: z.string().describe(\"Full context / definition\"),\n entryId: z.string().optional().describe(\"Optional custom entry ID\"),\n })).min(1).max(50).describe(\"Array of entries to capture\"),\n },\n annotations: { destructiveHint: false },\n },\n async ({ entries }) => {\n requireWriteAccess();\n\n const agentId = getAgentSessionId();\n const createdBy = agentId ? `agent:${agentId}` : \"capture\";\n\n const results: Array<{\n name: string;\n collection: string;\n entryId: string;\n ok: boolean;\n autoLinks: number;\n error?: string;\n }> = [];\n\n const allCollections = await mcpQuery<any[]>(\"chain.listCollections\");\n const collCache = new Map<string, any>();\n for (const c of allCollections) collCache.set(c.slug, c);\n const collIdToSlug = new Map<string, string>();\n for (const c of allCollections) collIdToSlug.set(c._id, c.slug);\n\n for (const entry of entries) {\n const profile = PROFILES.get(entry.collection) ?? FALLBACK_PROFILE;\n const col = collCache.get(entry.collection);\n\n if (!col) {\n results.push({ name: entry.name, collection: entry.collection, entryId: \"\", ok: false, autoLinks: 0, error: `Collection \"${entry.collection}\" not found` });\n continue;\n }\n\n const data: Record<string, unknown> = {};\n const today = new Date().toISOString().split(\"T\")[0];\n\n for (const field of col.fields ?? []) {\n const key = field.key as string;\n if (key === profile.descriptionField) {\n data[key] = entry.description;\n } else if (field.type === \"array\" || field.type === \"multi-select\") {\n data[key] = [];\n } else if (field.type === \"select\") {\n // Skip — empty string is not a valid option for select fields\n } else {\n data[key] = \"\";\n }\n }\n\n for (const def of profile.defaults) {\n if (def.value === \"today\") data[def.key] = today;\n else if (def.value !== \"infer\") data[def.key] = def.value;\n }\n\n if (profile.inferField) {\n const inferred = profile.inferField({\n collection: entry.collection, name: entry.name, description: entry.description,\n data, entryId: \"\", linksCreated: [], linksSuggested: [], collectionFields: col.fields ?? [],\n });\n for (const [key, val] of Object.entries(inferred)) {\n if (val !== undefined && val !== \"\") data[key] = val;\n }\n }\n\n if (!data[profile.descriptionField] && !data.description && !data.canonical) {\n data[profile.descriptionField || \"description\"] = entry.description;\n }\n\n try {\n const result = await mcpMutation<{ docId: string; entryId: string }>(\"chain.createEntry\", {\n collectionSlug: entry.collection,\n entryId: entry.entryId ?? undefined,\n name: entry.name,\n status: \"draft\",\n data,\n createdBy,\n sessionId: agentId ?? undefined,\n });\n const internalId = result.docId;\n const finalEntryId = result.entryId;\n\n let autoLinkCount = 0;\n const searchQuery = extractSearchTerms(entry.name, entry.description);\n if (searchQuery) {\n try {\n const searchResults = await mcpQuery<any[]>(\"chain.searchEntries\", { query: searchQuery });\n const candidates = (searchResults ?? [])\n .filter((r) => r.entryId !== finalEntryId)\n .map((r) => {\n const conf = computeLinkConfidence(r, entry.name, entry.description, entry.collection, collIdToSlug.get(r.collectionId) ?? \"unknown\");\n return {\n ...r,\n collSlug: collIdToSlug.get(r.collectionId) ?? \"unknown\",\n confidence: conf.score,\n };\n })\n .sort((a, b) => b.confidence - a.confidence);\n\n for (const c of candidates) {\n if (autoLinkCount >= MAX_AUTO_LINKS) break;\n if (c.confidence < AUTO_LINK_CONFIDENCE_THRESHOLD) break;\n if (!c.entryId) continue;\n const { type: relationType } = inferRelationType(entry.collection, c.collSlug, profile);\n try {\n await mcpMutation(\"chain.createEntryRelation\", {\n fromEntryId: finalEntryId,\n toEntryId: c.entryId,\n type: relationType,\n });\n autoLinkCount++;\n } catch { /* skip failed link */ }\n }\n } catch { /* search failed; entry still created */ }\n }\n\n results.push({ name: entry.name, collection: entry.collection, entryId: finalEntryId, ok: true, autoLinks: autoLinkCount });\n await recordSessionActivity({ entryCreated: internalId });\n } catch (error: unknown) {\n const msg = error instanceof Error ? error.message : String(error);\n results.push({ name: entry.name, collection: entry.collection, entryId: \"\", ok: false, autoLinks: 0, error: msg });\n }\n }\n\n const created = results.filter((r) => r.ok);\n const failed = results.filter((r) => !r.ok);\n const totalAutoLinks = created.reduce((sum, r) => sum + r.autoLinks, 0);\n\n const byCollection = new Map<string, number>();\n for (const r of created) {\n byCollection.set(r.collection, (byCollection.get(r.collection) ?? 0) + 1);\n }\n\n const lines: string[] = [\n `# Batch Capture Complete`,\n `**${created.length}** created, **${failed.length}** failed out of ${entries.length} total.`,\n `**Auto-links created:** ${totalAutoLinks}`,\n \"\",\n ];\n\n if (byCollection.size > 0) {\n lines.push(\"## By Collection\");\n for (const [col, count] of byCollection) {\n lines.push(`- \\`${col}\\`: ${count} entries`);\n }\n lines.push(\"\");\n }\n\n if (created.length > 0) {\n lines.push(\"## Created\");\n for (const r of created) {\n const linkNote = r.autoLinks > 0 ? ` (${r.autoLinks} auto-links)` : \"\";\n lines.push(`- **${r.entryId}**: ${r.name} [${r.collection}]${linkNote}`);\n }\n }\n\n if (failed.length > 0) {\n lines.push(\"\");\n lines.push(\"## Failed\");\n for (const r of failed) {\n lines.push(`- ${r.name} [${r.collection}]: _${r.error}_`);\n }\n }\n\n const entryIds = created.map((r) => r.entryId);\n if (entryIds.length > 0) {\n lines.push(\"\");\n lines.push(\"## Next Steps\");\n lines.push(`- **Connect:** Run \\`suggest-links\\` on key entries to build the knowledge graph`);\n lines.push(`- **Commit:** Use \\`commit-entry\\` to promote drafts to SSOT`);\n lines.push(`- **Quality:** Run \\`quality-check\\` on individual entries to assess completeness`);\n }\n\n return { content: [{ type: \"text\" as const, text: lines.join(\"\\n\") }] };\n }\n );\n\n // ── Quality Check Tool ──────────────────────────────────────────────────\n\n server.registerTool(\n \"quality-check\",\n {\n title: \"Quality Check\",\n description:\n \"Score an existing knowledge entry against collection-specific quality criteria. \" +\n \"Returns a scorecard (X/10) with specific, actionable suggestions for improvement — \" +\n \"including concrete link suggestions from graph analysis when relations are missing.\\n\\n\" +\n \"Checks: name clarity, description completeness, relation connectedness, and collection-specific fields.\\n\\n\" +\n \"Use after creating entries to assess their quality, or to audit existing entries.\",\n inputSchema: {\n entryId: z.string().describe(\"Entry ID to check, e.g. 'TEN-graph-db', 'GT-019', 'SOS-006'\"),\n },\n annotations: { readOnlyHint: true },\n },\n async ({ entryId }) => {\n const result = await checkEntryQuality(entryId);\n\n // If relations are missing, offer graph-aware suggestions\n const needsRelations = result.quality.checks.some(\n (c) => !c.passed && (c.id === \"has-relations\" || c.id === \"diverse-relations\"),\n );\n\n if (needsRelations) {\n try {\n const suggestions = await mcpQuery<any>(\"chain.graphSuggestLinks\", {\n entryId,\n maxHops: 2,\n limit: 3,\n });\n\n if (suggestions?.suggestions?.length > 0) {\n const linkHints = suggestions.suggestions\n .map((s: any) => ` → \\`relate-entries from='${entryId}' to='${s.entryId}' type='${s.recommendedRelationType}'\\` — ${s.name} [${s.collectionSlug}] (${s.score}/100)`)\n .join(\"\\n\");\n\n result.text += `\\n\\n## Suggested Links to Improve Quality\\n${linkHints}`;\n }\n } catch {\n // Graph suggestions failed — quality check still works without them\n }\n }\n\n // Surface cached rubric verdicts (SOS-e4r5cn: capability + visibility)\n try {\n const verdict = await mcpQuery<any>(\"quality.getLatestVerdictForEntry\", { entryId });\n if (verdict && verdict.criteria?.length > 0) {\n result.text += \"\\n\\n\" + formatRubricVerdictSection(verdict);\n }\n } catch {\n // Rubric verdicts are advisory — quality check works without them\n }\n\n return { content: [{ type: \"text\" as const, text: result.text }] };\n }\n );\n}\n\n// ── Helpers ────────────────────────────────────────────────────────────────\n\nfunction extractPreview(data: any, maxLen: number): string {\n if (!data || typeof data !== \"object\") return \"\";\n const raw = data.description ?? data.canonical ?? data.detail ?? data.rule ?? \"\";\n if (typeof raw !== \"string\" || !raw) return \"\";\n return raw.length > maxLen ? raw.substring(0, maxLen) + \"...\" : raw;\n}\n\n// Stop words excluded from noun phrase extraction\nconst STOP_WORDS = new Set([\n \"the\", \"and\", \"for\", \"are\", \"but\", \"not\", \"you\", \"all\", \"can\", \"has\", \"her\",\n \"was\", \"one\", \"our\", \"out\", \"day\", \"had\", \"hot\", \"how\", \"its\", \"may\", \"new\",\n \"now\", \"old\", \"see\", \"way\", \"who\", \"did\", \"get\", \"let\", \"say\", \"she\", \"too\",\n \"use\", \"from\", \"have\", \"been\", \"each\", \"that\", \"this\", \"with\", \"will\", \"they\",\n \"what\", \"when\", \"make\", \"like\", \"long\", \"look\", \"many\", \"some\", \"them\", \"than\",\n \"most\", \"only\", \"over\", \"such\", \"into\", \"also\", \"back\", \"just\", \"much\", \"must\",\n \"name\", \"very\", \"your\", \"after\", \"which\", \"their\", \"about\", \"would\", \"there\",\n \"should\", \"could\", \"other\", \"these\", \"first\", \"being\", \"those\", \"still\", \"where\",\n]);\n\n/**\n * Keyword contradiction check against governance entries.\n * Extracts terms 4+ chars, searches architecture and business-rules,\n * checks for 'governs' relations, returns formatted warnings.\n * Non-blocking — never throws, never prevents the operation.\n */\nexport interface ContradictionWarning {\n entryId: string;\n name: string;\n collection: string;\n governsCount: number;\n}\n\nexport async function runContradictionCheck(\n name: string,\n description: string,\n): Promise<ContradictionWarning[]> {\n const warnings: ContradictionWarning[] = [];\n try {\n const text = `${name} ${description}`.toLowerCase();\n const keyTerms = text\n .split(/\\s+/)\n .filter((w) => w.length >= 4 && !STOP_WORDS.has(w))\n .slice(0, 8);\n\n if (keyTerms.length === 0) return warnings;\n\n const searchQuery = keyTerms.slice(0, 3).join(\" \");\n const [govResults, archResults] = await Promise.all([\n mcpQuery<any[]>(\"chain.searchEntries\", { query: searchQuery, collectionSlug: \"business-rules\" }),\n mcpQuery<any[]>(\"chain.searchEntries\", { query: searchQuery, collectionSlug: \"architecture\" }),\n ]);\n\n const allGov = [...(govResults ?? []), ...(archResults ?? [])].slice(0, 5);\n\n for (const entry of allGov) {\n const entryText = `${entry.name} ${entry.data?.description ?? \"\"}`.toLowerCase();\n const matched = keyTerms.filter((t) => entryText.includes(t));\n if (matched.length < 2) continue;\n\n // Check for 'governs' relations\n let governsCount = 0;\n try {\n const relations = await mcpQuery<any[]>(\"chain.listEntryRelations\", {\n entryId: entry.entryId,\n });\n governsCount = (relations ?? []).filter((r: any) => r.type === \"governs\").length;\n } catch { /* non-critical */ }\n\n warnings.push({\n entryId: entry.entryId ?? \"\",\n name: entry.name,\n collection: entry.collectionSlug ?? \"\",\n governsCount,\n });\n }\n } catch {\n // Contradiction check is advisory — never blocks the operation\n }\n return warnings;\n}\n\n// ── Quality Coaching Helpers ──────────────────────────────────────────────\n\nfunction withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {\n return Promise.race([\n promise,\n new Promise<T>((_, reject) =>\n setTimeout(() => reject(new Error(\"quality coaching timeout\")), ms),\n ),\n ]);\n}\n\n/**\n * Format a full quality coaching result (from evaluateAtCapture / evaluateAtCommit)\n * for inclusion in MCP capture/commit responses.\n */\nexport function formatRubricCoaching(result: any): string {\n const { verdict, rogerMartin } = result;\n if (!verdict || verdict.criteria.length === 0) return \"\";\n\n const lines: string[] = [\"## Semantic Quality\"];\n const failed = (verdict.criteria ?? []).filter((c: any) => !c.passed);\n const total = verdict.criteria?.length ?? 0;\n const passedCount = total - failed.length;\n\n if (verdict.passed) {\n lines.push(`All ${total} rubric criteria pass for \\`${verdict.canonicalKey}\\` (${verdict.tier} tier).`);\n } else {\n lines.push(`${passedCount}/${total} criteria pass for \\`${verdict.canonicalKey}\\` (${verdict.tier} tier)`);\n lines.push(\"\");\n for (const c of verdict.criteria) {\n const icon = c.passed ? \"[x]\" : \"[ ]\";\n const extra = c.passed ? \"\" : ` — ${c.hint}`;\n lines.push(`${icon} ${c.id}${extra}`);\n }\n\n if (verdict.weakest) {\n lines.push(\"\");\n lines.push(`**Coaching hint:** ${verdict.weakest.hint}`);\n lines.push(`_Question to consider:_ ${verdict.weakest.questionTemplate}`);\n }\n }\n\n if (rogerMartin) {\n lines.push(\"\");\n lines.push(\"### Roger Martin Test\");\n if (rogerMartin.isStrategicChoice) {\n lines.push(\"This principle passes — the opposite is a reasonable strategic choice.\");\n } else {\n lines.push(`This principle may not be a strategic choice. ${rogerMartin.reasoning}`);\n if (rogerMartin.suggestion) {\n lines.push(`_Suggestion:_ ${rogerMartin.suggestion}`);\n }\n }\n }\n\n return lines.join(\"\\n\");\n}\n\n/**\n * Format a cached rubric verdict section for quality-check responses.\n * SOS-e4r5cn: capability and visibility must ship together.\n */\nfunction formatRubricVerdictSection(verdict: any): string {\n if (!verdict || !verdict.criteria || verdict.criteria.length === 0) return \"\";\n\n const lines: string[] = [\"## Semantic Quality\"];\n const failed = verdict.criteria.filter((c: any) => !c.passed);\n const total = verdict.criteria.length;\n const passedCount = total - failed.length;\n\n if (failed.length === 0) {\n lines.push(`All ${total} rubric criteria pass for \\`${verdict.canonicalKey}\\` (${verdict.tier} tier, ${verdict.source} evaluation).`);\n } else {\n lines.push(`${passedCount}/${total} criteria pass for \\`${verdict.canonicalKey}\\` (${verdict.tier} tier, ${verdict.source} evaluation)`);\n lines.push(\"\");\n for (const c of verdict.criteria) {\n const icon = c.passed ? \"[x]\" : \"[ ]\";\n const extra = c.passed ? \"\" : ` — ${c.hint}`;\n lines.push(`${icon} ${c.id}${extra}`);\n }\n\n if (verdict.weakest) {\n lines.push(\"\");\n lines.push(`**Top improvement:** ${verdict.weakest.hint}`);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * Request-scoped auth for HTTP transport mode.\n *\n * stdio: API key from PRODUCTBRAIN_API_KEY env, one user per process.\n * http: API key from Bearer header per request, many users per process.\n *\n * AsyncLocalStorage propagates the token through the async call chain\n * so client.ts resolves the correct API key and state per request.\n */\n\nimport { AsyncLocalStorage } from \"node:async_hooks\";\n\n// ── Request Context ─────────────────────────────────────────────────────\n\ninterface RequestAuth {\n apiKey: string;\n}\n\nconst requestStore = new AsyncLocalStorage<RequestAuth>();\n\nexport function runWithAuth<T>(auth: RequestAuth, fn: () => T | Promise<T>): T | Promise<T> {\n return requestStore.run(auth, fn);\n}\n\nexport function getRequestApiKey(): string | undefined {\n return requestStore.getStore()?.apiKey;\n}\n\n// ── Per-Key State (HTTP mode) ───────────────────────────────────────────\n\nexport interface KeyState {\n workspaceId: string | null;\n workspaceSlug: string | null;\n workspaceName: string | null;\n workspaceCreatedAt: number | null;\n agentSessionId: string | null;\n apiKeyId: string | null;\n apiKeyScope: \"read\" | \"readwrite\";\n sessionOriented: boolean;\n sessionClosed: boolean;\n lastAccess: number;\n}\n\nconst SESSION_TTL_MS = 30 * 60 * 1000;\nconst MAX_KEYS = 100;\nconst keyStateMap = new Map<string, KeyState>();\n\nfunction newKeyState(): KeyState {\n return {\n workspaceId: null,\n workspaceSlug: null,\n workspaceName: null,\n workspaceCreatedAt: null,\n agentSessionId: null,\n apiKeyId: null,\n apiKeyScope: \"readwrite\",\n sessionOriented: false,\n sessionClosed: false,\n lastAccess: Date.now(),\n };\n}\n\nexport function getKeyState(apiKey: string): KeyState {\n let s = keyStateMap.get(apiKey);\n if (!s) {\n s = newKeyState();\n keyStateMap.set(apiKey, s);\n evictStale();\n }\n s.lastAccess = Date.now();\n return s;\n}\n\nfunction evictStale(): void {\n if (keyStateMap.size <= MAX_KEYS) return;\n const now = Date.now();\n for (const [key, s] of keyStateMap) {\n if (now - s.lastAccess > SESSION_TTL_MS) keyStateMap.delete(key);\n }\n if (keyStateMap.size > MAX_KEYS) {\n const sorted = [...keyStateMap.entries()].sort((a, b) => a[1].lastAccess - b[1].lastAccess);\n for (let i = 0; i < sorted.length - MAX_KEYS; i++) {\n keyStateMap.delete(sorted[i][0]);\n }\n }\n}\n","/**\n * MCP client — communicates with the Convex HTTP Action gateway.\n *\n * Dual mode:\n * stdio — single user, API key from env, module-level state\n * http — multi-user, API key from AsyncLocalStorage, per-key state\n *\n * Configuration:\n * PRODUCTBRAIN_API_KEY — pb_sk_* key (stdio mode; http mode gets it per-request)\n * CONVEX_SITE_URL — (optional) Convex deployment URL, defaults to cloud\n */\n\nimport { trackToolCall } from \"./analytics.js\";\nimport { getRequestApiKey, getKeyState, type KeyState } from \"./auth.js\";\n\nconst DEFAULT_CLOUD_URL = \"https://trustworthy-kangaroo-277.convex.site\";\n\n// ─── Read Cache (Batch A: sub-200ms repeat calls) ─────────────────────\n\nconst CACHE_TTL_MS = 60_000; // 60s per plan\nconst CACHEABLE_FNS = [\n \"chain.getOrientEntries\",\n \"chain.gatherContext\",\n \"chain.graphGatherContext\",\n \"chain.taskAwareGatherContext\",\n \"chain.assembleBuildContext\",\n] as const;\n\nfunction isCacheable(fn: string): boolean {\n return (CACHEABLE_FNS as readonly string[]).includes(fn);\n}\n\nconst READ_PATTERN =\n /^(chain\\.(get|list|search|batchGet|gather|graph|task|assemble|workspace|score|absence)|maps\\.(get|list)|gitchain\\.(get|list|diff|history|runGate))/i;\n\nfunction isWrite(fn: string): boolean {\n if (fn.startsWith(\"agent.\")) return false;\n return !READ_PATTERN.test(fn);\n}\n\ninterface CacheEntry<T> {\n data: T;\n expiresAt: number;\n}\n\nconst readCache = new Map<string, CacheEntry<unknown>>();\n\nfunction cacheKey(fn: string, args: Record<string, unknown>): string {\n return `${fn}:${JSON.stringify(args)}`;\n}\n\nfunction getCached<T>(fn: string, args: Record<string, unknown>): T | undefined {\n if (!isCacheable(fn)) return undefined;\n const key = cacheKey(fn, args);\n const entry = readCache.get(key) as CacheEntry<T> | undefined;\n if (!entry || Date.now() > entry.expiresAt) {\n if (entry) readCache.delete(key);\n return undefined;\n }\n return entry.data;\n}\n\nfunction setCached<T>(fn: string, args: Record<string, unknown>, data: T): void {\n if (!isCacheable(fn)) return;\n const key = cacheKey(fn, args);\n readCache.set(key, { data, expiresAt: Date.now() + CACHE_TTL_MS });\n}\n\nfunction invalidateReadCache(): void {\n readCache.clear();\n}\n\n// ─── State Management ─────────────────────────────────────────────────\n\nconst _stdioState: KeyState = {\n workspaceId: null,\n workspaceSlug: null,\n workspaceName: null,\n workspaceCreatedAt: null,\n agentSessionId: null,\n apiKeyId: null,\n apiKeyScope: \"readwrite\",\n sessionOriented: false,\n sessionClosed: false,\n lastAccess: 0,\n};\n\n/**\n * Returns the active client state.\n * stdio: module-level singleton. http: per-API-key state from AsyncLocalStorage.\n */\nfunction state(): KeyState {\n const reqKey = getRequestApiKey();\n if (reqKey) return getKeyState(reqKey);\n return _stdioState;\n}\n\n/**\n * Returns the active API key (request-scoped in HTTP mode, env in stdio mode).\n */\nfunction getActiveApiKey(): string {\n const fromRequest = getRequestApiKey();\n if (fromRequest) return fromRequest;\n const fromEnv = process.env.PRODUCTBRAIN_API_KEY;\n if (!fromEnv) throw new Error(\"No API key available — set PRODUCTBRAIN_API_KEY or provide Bearer token\");\n return fromEnv;\n}\n\n// ─── Agent Session State ──────────────────────────────────────────────\n\nexport function getAgentSessionId(): string | null {\n return state().agentSessionId;\n}\n\nexport function isSessionOriented(): boolean {\n return state().sessionOriented;\n}\n\nexport function setSessionOriented(value: boolean): void {\n state().sessionOriented = value;\n}\n\nexport function getApiKeyScope(): \"read\" | \"readwrite\" {\n return state().apiKeyScope;\n}\n\nexport function isSessionClosed(): boolean {\n return state().sessionClosed;\n}\n\nexport interface AgentSessionStartResult {\n sessionId: string;\n initiatedBy: string;\n toolsScope: \"read\" | \"readwrite\";\n workspaceName: string;\n superseded: {\n previousSessionId: string;\n startedAt: string;\n initiatedBy: string;\n } | null;\n}\n\n/**\n * Start an agent session. Creates a session record in Convex.\n * toolsScope is derived server-side from the API key — not passed as a parameter.\n * If an active session exists, it gets superseded.\n */\nexport async function startAgentSession(): Promise<AgentSessionStartResult> {\n const workspaceId = await getWorkspaceId();\n const s = state();\n if (!s.apiKeyId) {\n throw new Error(\"Cannot start session: API key ID not resolved. Ensure workspace resolution completed.\");\n }\n\n const result = await mcpCall<AgentSessionStartResult>(\"agent.startSession\", {\n workspaceId,\n apiKeyId: s.apiKeyId,\n });\n\n s.agentSessionId = result.sessionId;\n s.apiKeyScope = result.toolsScope;\n s.sessionOriented = false;\n s.sessionClosed = false;\n\n return result;\n}\n\n/**\n * Close the current agent session. After this, write tools are blocked\n * even if the MCP connection stays open.\n */\nexport async function closeAgentSession(): Promise<void> {\n const s = state();\n if (!s.agentSessionId) return;\n try {\n await mcpCall(\"agent.closeSession\", {\n sessionId: s.agentSessionId,\n status: \"closed\",\n });\n } finally {\n s.sessionClosed = true;\n s.agentSessionId = null;\n s.sessionOriented = false;\n }\n}\n\n/**\n * Mark current session as orphaned (used on disconnect/crash).\n */\nexport async function orphanAgentSession(): Promise<void> {\n const s = state();\n if (!s.agentSessionId) return;\n try {\n await mcpCall(\"agent.closeSession\", {\n sessionId: s.agentSessionId,\n status: \"orphaned\",\n });\n } catch {\n // Best-effort on disconnect\n } finally {\n s.agentSessionId = null;\n s.sessionOriented = false;\n }\n}\n\n/**\n * Touch the session to update lastToolCallAt. Fire-and-forget.\n */\nexport function touchSessionActivity(): void {\n const s = state();\n if (!s.agentSessionId) return;\n mcpCall(\"agent.touchSession\", {\n sessionId: s.agentSessionId,\n }).catch(() => {\n // Non-critical\n });\n}\n\n/**\n * Record structured activity on the current session.\n */\nexport async function recordSessionActivity(activity: {\n entryCreated?: string;\n entryModified?: string;\n relationCreated?: boolean;\n gateFailure?: boolean;\n contradictionWarning?: boolean;\n strategyLinkWarnedForEntryId?: string;\n}): Promise<void> {\n const s = state();\n if (!s.agentSessionId) return;\n try {\n await mcpCall(\"agent.recordActivity\", {\n sessionId: s.agentSessionId,\n ...activity,\n });\n } catch {\n // Non-critical — don't fail the tool call over activity tracking\n }\n}\n\n// ─── Audit ────────────────────────────────────────────────────────────\n\nexport interface AuditEntry {\n ts: string;\n fn: string;\n workspace: string;\n status: \"ok\" | \"error\";\n durationMs: number;\n error?: string;\n}\n\nconst AUDIT_BUFFER_SIZE = 50;\nconst auditBuffer: AuditEntry[] = [];\n\n/**\n * Bootstrap for stdio mode: validate PRODUCTBRAIN_API_KEY and default CONVEX_SITE_URL.\n * Must be called once before any mcpCall.\n */\nexport function bootstrap(): void {\n const pbKey = process.env.PRODUCTBRAIN_API_KEY;\n if (!pbKey?.startsWith(\"pb_sk_\")) {\n throw new Error(\n \"PRODUCTBRAIN_API_KEY is required and must start with 'pb_sk_'. \" +\n \"Generate one at Settings > API Keys in the Product OS UI.\"\n );\n }\n process.env.CONVEX_SITE_URL ??= process.env.PRODUCTBRAIN_URL ?? DEFAULT_CLOUD_URL;\n}\n\n/**\n * Bootstrap for HTTP mode: only set CONVEX_SITE_URL.\n * API key validation happens per-request via Bearer token.\n */\nexport function bootstrapHttp(): void {\n process.env.CONVEX_SITE_URL ??= process.env.PRODUCTBRAIN_URL ?? DEFAULT_CLOUD_URL;\n}\n\n/** @deprecated Use bootstrap() instead. Alias kept for callers in transition. */\nexport const bootstrapCloudMode = bootstrap;\n\nfunction getEnv(key: string): string {\n const value = process.env[key];\n if (!value) throw new Error(`${key} environment variable is required`);\n return value;\n}\n\nfunction shouldLogAudit(status: \"ok\" | \"error\"): boolean {\n return status === \"error\" || process.env.MCP_DEBUG === \"1\";\n}\n\nfunction audit(fn: string, status: \"ok\" | \"error\", durationMs: number, errorMsg?: string): void {\n const ts = new Date().toISOString();\n const workspace = state().workspaceId ?? \"unresolved\";\n\n const entry: AuditEntry = { ts, fn, workspace, status, durationMs };\n if (errorMsg) entry.error = errorMsg;\n auditBuffer.push(entry);\n if (auditBuffer.length > AUDIT_BUFFER_SIZE) auditBuffer.shift();\n\n trackToolCall(fn, status, durationMs, workspace, errorMsg);\n\n if (!shouldLogAudit(status)) return;\n\n const base = `[MCP-AUDIT] ${ts} fn=${fn} workspace=${workspace} status=${status} duration=${durationMs}ms`;\n if (status === \"error\" && errorMsg) {\n process.stderr.write(`${base} error=${JSON.stringify(errorMsg)}\\n`);\n } else {\n process.stderr.write(`${base}\\n`);\n }\n}\n\nexport function getAuditLog(): readonly AuditEntry[] {\n return auditBuffer;\n}\n\n// ─── HTTP Client ──────────────────────────────────────────────────────\n\n/**\n * Low-level call to the HTTP Action gateway.\n * Workspace scoping is enforced server-side from the API key — callers\n * don't need to (and can't) override the workspace.\n *\n * Read cache: orient and gather-context responses are cached for 60s.\n * Cache is invalidated on any write (safe-by-default: everything not\n * matching a known read pattern is treated as a write).\n */\nexport async function mcpCall<T>(fn: string, args: Record<string, unknown> = {}): Promise<T> {\n const cached = getCached<T>(fn, args);\n if (cached !== undefined) {\n return cached;\n }\n\n const siteUrl = getEnv(\"CONVEX_SITE_URL\").replace(/\\/$/, \"\");\n const apiKey = getActiveApiKey();\n\n const start = Date.now();\n\n let res: Response;\n try {\n res = await fetch(`${siteUrl}/api/mcp`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${apiKey}`,\n },\n body: JSON.stringify({ fn, args }),\n });\n } catch (err: any) {\n audit(fn, \"error\", Date.now() - start, err.message);\n throw new Error(`MCP call \"${fn}\" network error: ${err.message}`);\n }\n\n const json = (await res.json()) as { data?: T; error?: string };\n\n if (!res.ok || json.error) {\n audit(fn, \"error\", Date.now() - start, json.error);\n throw new Error(`MCP call \"${fn}\" failed (${res.status}): ${json.error ?? \"unknown error\"}`);\n }\n\n audit(fn, \"ok\", Date.now() - start);\n\n const data = json.data as T;\n if (isWrite(fn)) {\n invalidateReadCache();\n } else {\n setCached(fn, args, data);\n }\n\n const s = state();\n if (s.agentSessionId && fn !== \"agent.touchSession\" && fn !== \"agent.startSession\") {\n touchSessionActivity();\n }\n\n return data;\n}\n\n// ─── Workspace Resolution ─────────────────────────────────────────────\n\nconst resolveInFlightMap = new Map<string, Promise<string>>();\n\nexport async function getWorkspaceId(): Promise<string> {\n const s = state();\n if (s.workspaceId) return s.workspaceId;\n\n const apiKey = getActiveApiKey();\n const existing = resolveInFlightMap.get(apiKey);\n if (existing) return existing;\n\n const promise = resolveWorkspaceWithRetry().finally(() => resolveInFlightMap.delete(apiKey));\n resolveInFlightMap.set(apiKey, promise);\n return promise;\n}\n\nasync function resolveWorkspaceWithRetry(maxRetries = 2): Promise<string> {\n let lastError: Error | null = null;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n const workspace = await mcpCall<{\n _id: string;\n name: string;\n slug: string;\n createdAt?: number;\n keyScope?: string;\n keyId?: string;\n } | null>(\"resolveWorkspace\", {});\n\n if (!workspace) {\n throw new Error(\n \"API key is valid but no workspace is associated. \" +\n \"Run `npx productbrain setup` or regenerate your key.\"\n );\n }\n\n const s = state();\n s.workspaceId = workspace._id;\n s.workspaceSlug = workspace.slug;\n s.workspaceName = workspace.name;\n s.workspaceCreatedAt = workspace.createdAt ?? null;\n if (workspace.keyScope) s.apiKeyScope = workspace.keyScope as \"read\" | \"readwrite\";\n if (workspace.keyId) s.apiKeyId = workspace.keyId;\n return s.workspaceId;\n } catch (err: any) {\n lastError = err;\n const isTransient = /network error|fetch failed|ECONNREFUSED|ETIMEDOUT/i.test(err.message);\n if (!isTransient || attempt === maxRetries) break;\n const delay = 1000 * (attempt + 1);\n process.stderr.write(\n `[MCP] Workspace resolution failed (attempt ${attempt + 1}/${maxRetries + 1}), retrying in ${delay}ms...\\n`\n );\n await new Promise((r) => setTimeout(r, delay));\n }\n }\n\n throw lastError!;\n}\n\nexport interface WorkspaceContext {\n workspaceId: string;\n workspaceSlug: string;\n workspaceName: string;\n createdAt: number | null;\n}\n\nexport async function getWorkspaceContext(): Promise<WorkspaceContext> {\n const workspaceId = await getWorkspaceId();\n const s = state();\n return {\n workspaceId,\n workspaceSlug: s.workspaceSlug ?? \"unknown\",\n workspaceName: s.workspaceName ?? \"unknown\",\n createdAt: s.workspaceCreatedAt,\n };\n}\n\nexport async function mcpQuery<T>(fn: string, args: Record<string, unknown> = {}): Promise<T> {\n const workspaceId = await getWorkspaceId();\n return mcpCall<T>(fn, { ...args, workspaceId });\n}\n\nexport async function mcpMutation<T>(fn: string, args: Record<string, unknown> = {}): Promise<T> {\n const workspaceId = await getWorkspaceId();\n return mcpCall<T>(fn, { ...args, workspaceId });\n}\n\n/**\n * Gate check: throws if no active, oriented session exists.\n *\n * Used for read tools that require session context per SOS-iszqu7:\n * structured Chain data for agent consumption requires an active session.\n * Lighter than requireWriteAccess — does not check key scope.\n */\nexport function requireActiveSession(): void {\n const s = state();\n\n if (!s.agentSessionId) {\n throw new Error(\n \"Active session required (SOS-iszqu7). Call `agent-start` then `orient` first.\"\n );\n }\n\n if (s.sessionClosed) {\n throw new Error(\n \"Session has been closed (SOS-iszqu7). Start a new session with `agent-start`.\"\n );\n }\n\n if (!s.sessionOriented) {\n throw new Error(\n \"Orientation required before accessing build context (SOS-iszqu7). Call `orient` first.\"\n );\n }\n}\n\n/**\n * Gate check: throws if the agent is not allowed to write.\n *\n * Enforces:\n * 1. Session must exist (always required — no REQUIRE_AGENT_SESSION flag)\n * 2. Session must not be closed\n * 3. Session must be oriented\n * 4. Key scope must be readwrite\n */\nexport function requireWriteAccess(): void {\n const s = state();\n\n if (!s.agentSessionId) {\n throw new Error(\n \"Agent session required for write operations. Call `agent-start` first.\"\n );\n }\n\n if (s.sessionClosed) {\n throw new Error(\n \"Agent session has been closed. Write tools are no longer available.\"\n );\n }\n\n if (!s.sessionOriented) {\n throw new Error(\n \"Orientation required before writing to the Chain. Call 'orient' first.\"\n );\n }\n\n if (s.apiKeyScope === \"read\") {\n throw new Error(\n \"This API key has read-only scope. Write tools are not available.\"\n );\n }\n}\n\n/**\n * Recover session orientation state from Convex on restart.\n * If the session is active and oriented in Convex, restore local state.\n */\nexport async function recoverSessionState(): Promise<void> {\n const s = state();\n if (!s.workspaceId) return;\n try {\n const session = await mcpCall<{\n _id: string;\n status: string;\n oriented: boolean;\n toolsScope: string;\n } | null>(\"agent.getActiveSession\", { workspaceId: s.workspaceId });\n\n if (session && session.status === \"active\") {\n s.agentSessionId = session._id;\n s.sessionOriented = session.oriented;\n s.apiKeyScope = session.toolsScope as \"read\" | \"readwrite\";\n s.sessionClosed = false;\n }\n } catch {\n // Recovery is best-effort\n }\n}\n"],"mappings":"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","names":["passed"]}