@productbrain/mcp 0.0.1-beta.135 → 0.0.1-beta.139

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.
@@ -996,326 +996,6 @@ var FIELD_TYPE_DEFAULTS = {
996
996
  "date": null
997
997
  };
998
998
 
999
- // src/lib/collectionRoutingClassifier.ts
1000
- var CLASSIFIABLE_COLLECTIONS = [
1001
- "decisions",
1002
- "tensions",
1003
- "glossary",
1004
- "insights",
1005
- "features",
1006
- "architecture",
1007
- "business-rules",
1008
- // tracking-events: removed (Tier 1 Hierarchy — 0 entries, collection deprecated)
1009
- "landscape",
1010
- "standards",
1011
- "principles",
1012
- "assumptions",
1013
- "work-packages",
1014
- "patterns",
1015
- // BET-274: Capabilities collection
1016
- "capabilities"
1017
- ];
1018
- var SIGNAL_WEIGHT = 10;
1019
- var MIN_SCORE_FLOOR = 10;
1020
- var MAX_MATCHES_PER_SIGNAL = 2;
1021
- var MAX_REASON_COUNT = 3;
1022
- var ENTRY_ID_PATTERN = /\b[A-Z]{2,}-\d+\b/g;
1023
- var COLLECTION_SIGNALS = {
1024
- decisions: [
1025
- "decide",
1026
- "decision",
1027
- "chose",
1028
- "chosen",
1029
- "choice",
1030
- "resolved",
1031
- "we will",
1032
- "we should",
1033
- "approved",
1034
- "replaces",
1035
- "instead of",
1036
- "go with",
1037
- "criteria",
1038
- "adopted",
1039
- "reposition",
1040
- "scoring framework",
1041
- "review",
1042
- // BET-124: tune recall 35%→≥50% — match abstained/misclassified fixture entries
1043
- "guard level",
1044
- "mcp-native",
1045
- "pure functions",
1046
- "intentional debt",
1047
- "read allowlist",
1048
- "safe-by-default",
1049
- "map ingredients",
1050
- "never per-seat",
1051
- "neighborhood-first",
1052
- "locked at",
1053
- "ssot"
1054
- ],
1055
- tensions: [
1056
- "problem",
1057
- "issue",
1058
- "blocked",
1059
- "blocker",
1060
- "friction",
1061
- "pain",
1062
- "bottleneck",
1063
- "struggle",
1064
- "missing",
1065
- "breaks",
1066
- "regression",
1067
- "unclear",
1068
- "no way to",
1069
- "scope creep",
1070
- "coupled",
1071
- "trapped",
1072
- "ambiguous",
1073
- "no batch",
1074
- "undetectable",
1075
- "coordination gap",
1076
- // BET-124: tune recall 40%→≥50% — match abstained/misclassified fixture entries
1077
- "methodology wall",
1078
- "feature flag gap",
1079
- "doesn't bridge",
1080
- "cap limits",
1081
- "trapped in",
1082
- "no pan",
1083
- "no zoom",
1084
- "no interaction",
1085
- "accuracy regression",
1086
- "response bloat"
1087
- ],
1088
- glossary: [
1089
- "definition",
1090
- "define",
1091
- "term",
1092
- "means",
1093
- "refers to",
1094
- "defined as",
1095
- "is a term for",
1096
- "is called",
1097
- "vocabulary",
1098
- "terminology",
1099
- "a governance mechanism",
1100
- "a workspace",
1101
- "a tracked",
1102
- "the atom",
1103
- "the action of",
1104
- "the versioned",
1105
- "a field on",
1106
- "one of the",
1107
- "a constraint on",
1108
- "a hard data",
1109
- "a single",
1110
- // BET-124: tune recall 46.7%→≥50% — definitional language, name-is-term pattern
1111
- "constraint"
1112
- ],
1113
- insights: [
1114
- "insight",
1115
- "learned",
1116
- "observed",
1117
- "trend",
1118
- "found that",
1119
- "discovery",
1120
- "validates",
1121
- "validated",
1122
- "saturates",
1123
- "convergence",
1124
- "signals from",
1125
- "signals",
1126
- "converge",
1127
- "tam",
1128
- // BET-124: tune recall 26.7%→≥40% — research/data/learning language
1129
- "thesis",
1130
- "decay",
1131
- "learnings",
1132
- "aha moment",
1133
- "data informs"
1134
- ],
1135
- features: [
1136
- "feature",
1137
- "capability",
1138
- "user can",
1139
- "navigation",
1140
- "palette",
1141
- "modal",
1142
- "smart capture",
1143
- "suggest-links",
1144
- "command palette",
1145
- "auto-commit",
1146
- "collection-optional",
1147
- "organisation intelligence",
1148
- "consolidation"
1149
- ],
1150
- architecture: [
1151
- "architecture",
1152
- "layer",
1153
- "data model",
1154
- "infrastructure",
1155
- "system design",
1156
- "l1",
1157
- "l2",
1158
- "l3",
1159
- "l4",
1160
- "l5",
1161
- "l6",
1162
- "l7",
1163
- "guard infrastructure",
1164
- "data layer",
1165
- "intelligence layer",
1166
- "mcp layer",
1167
- "core layer"
1168
- ],
1169
- "business-rules": [
1170
- "guard",
1171
- "enforce",
1172
- "integrity",
1173
- "prevents",
1174
- "excludes",
1175
- "permitted",
1176
- "policy",
1177
- "feature gate",
1178
- "must not",
1179
- "only permitted",
1180
- "closed enum",
1181
- "write guard",
1182
- "never imports",
1183
- "requires active session",
1184
- "readiness excludes"
1185
- ],
1186
- // tracking-events: removed (Tier 1 Hierarchy — 0 entries, collection deprecated)
1187
- landscape: [
1188
- "competitor",
1189
- "alternative tool",
1190
- "alternative platform",
1191
- "competing product",
1192
- "landscape",
1193
- "comparison"
1194
- ],
1195
- standards: [
1196
- "standard",
1197
- "convention",
1198
- "trunk-based",
1199
- "alignment-first",
1200
- "structured bet",
1201
- "system fixes",
1202
- "patches"
1203
- ],
1204
- principles: [
1205
- "we believe",
1206
- "principle",
1207
- "compounds",
1208
- "philosophy",
1209
- "simplicity compounds",
1210
- "trust through",
1211
- "evidence over",
1212
- "compensate for",
1213
- "honest by default"
1214
- ],
1215
- assumptions: [
1216
- "assume",
1217
- "assumption",
1218
- "hypothesis",
1219
- "untested",
1220
- "we think",
1221
- "we assume",
1222
- "needs validation"
1223
- ],
1224
- patterns: [
1225
- "pattern",
1226
- "anti-pattern",
1227
- "best practice",
1228
- "reusable solution",
1229
- "design pattern",
1230
- "recurring solution",
1231
- "template",
1232
- "proven approach"
1233
- ],
1234
- capabilities: [
1235
- "capability",
1236
- "capabilities",
1237
- "can do",
1238
- "supply-side",
1239
- "product capability",
1240
- "what the product does",
1241
- "mature",
1242
- "emerging",
1243
- "declining",
1244
- "platform capability",
1245
- "infrastructure capability"
1246
- ],
1247
- "work-packages": [
1248
- "appetite",
1249
- "elements",
1250
- "no-gos",
1251
- "no gos",
1252
- "problem",
1253
- "solution",
1254
- "done when",
1255
- "doneWhen",
1256
- "rabbit hole",
1257
- "rabbit holes",
1258
- "build sequence",
1259
- "build contract",
1260
- "slice",
1261
- "bet",
1262
- "shaping",
1263
- "shape up"
1264
- ]
1265
- };
1266
- function escapeRegExp(text) {
1267
- return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1268
- }
1269
- function countSignalMatches(text, signal) {
1270
- const trimmed = signal.trim().toLowerCase();
1271
- if (!trimmed) return 0;
1272
- const words = trimmed.split(/\s+/).map(escapeRegExp);
1273
- const pattern = `\\b${words.join("\\s+")}\\b`;
1274
- const regex = new RegExp(pattern, "g");
1275
- const matches = text.match(regex);
1276
- return matches?.length ?? 0;
1277
- }
1278
- function classifyCollection(name, description) {
1279
- const text = `${name} ${description}`.replace(ENTRY_ID_PATTERN, "").toLowerCase();
1280
- const rawScores = [];
1281
- for (const collection of CLASSIFIABLE_COLLECTIONS) {
1282
- const signals = COLLECTION_SIGNALS[collection];
1283
- const reasons = [];
1284
- let score = 0;
1285
- for (const signal of signals) {
1286
- const matches = countSignalMatches(text, signal);
1287
- if (matches <= 0) continue;
1288
- const cappedMatches = Math.min(matches, MAX_MATCHES_PER_SIGNAL);
1289
- score += cappedMatches * SIGNAL_WEIGHT;
1290
- if (reasons.length < MAX_REASON_COUNT) {
1291
- const capNote = matches > cappedMatches ? ` (capped at ${cappedMatches})` : "";
1292
- reasons.push(`matched "${signal}" x${matches}${capNote}`);
1293
- }
1294
- }
1295
- rawScores.push({ collection, score, reasons });
1296
- }
1297
- rawScores.sort((left, right) => right.score - left.score);
1298
- const top = rawScores[0];
1299
- const second = rawScores[1];
1300
- if (!top || top.score < MIN_SCORE_FLOOR) return null;
1301
- const margin = Math.max(0, top.score - (second?.score ?? 0));
1302
- if (margin === 0 && top.score <= MIN_SCORE_FLOOR) return null;
1303
- const baseConfidence = Math.min(90, top.score);
1304
- const confidence = Math.min(99, baseConfidence + Math.min(20, margin));
1305
- return {
1306
- collection: top.collection,
1307
- topConfidence: confidence,
1308
- confidence,
1309
- reasons: top.reasons,
1310
- scoreMargin: margin,
1311
- candidates: rawScores.filter((candidate) => candidate.score > 0).slice(0, 3).map((candidate) => ({
1312
- collection: candidate.collection,
1313
- signalScore: Math.min(99, candidate.score),
1314
- confidence: Math.min(99, candidate.score)
1315
- }))
1316
- };
1317
- }
1318
-
1319
999
  // src/tools/smart-capture.ts
1320
1000
  function normalizeMatchText(value) {
1321
1001
  return value.toLowerCase().replace(/[^a-z0-9]+/g, " ").replace(/\s+/g, " ").trim();
@@ -2021,7 +1701,9 @@ var batchCaptureSchema = z2.object({
2021
1701
  description: z2.string().describe("Full context / definition"),
2022
1702
  entryId: entryIdSchema,
2023
1703
  data: z2.record(z2.unknown()).optional().describe("Explicit field values (e.g. urgency, status, assignee). Merged with inferred values; user-provided wins."),
2024
- canonicalKey: z2.string().optional().describe("Semantic type (e.g. 'decision', 'tension', 'work_package'). Enables work-package redirect in createEntry when collection is 'chains'.")
1704
+ canonicalKey: z2.string().optional().describe("Semantic type (e.g. 'decision', 'tension', 'work_package'). Enables work-package redirect in createEntry when collection is 'chains'."),
1705
+ sourceRef: z2.string().optional().describe("URI or path of the source document backing this entry (e.g. 'meeting-2026-03-28.md', 'import://batch-5'). Stored as top-level entry field, not in data."),
1706
+ sourceExcerpt: z2.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Stored as top-level entry field, not in data.")
2025
1707
  })).min(1).max(50).describe("Array of entries to capture"),
2026
1708
  autoCommit: z2.boolean().optional().describe(
2027
1709
  "If true, commits created entries immediately after linking. If omitted, Open mode workspaces commit by default and consensus/role modes stay draft-first."
@@ -3198,7 +2880,9 @@ Use \`entries action=get\` to inspect the existing entry, or \`update-entry\` to
3198
2880
  data,
3199
2881
  createdBy,
3200
2882
  sessionId: agentId ?? void 0,
3201
- canonicalKey: entry.canonicalKey ?? void 0
2883
+ canonicalKey: entry.canonicalKey ?? void 0,
2884
+ ...entry.sourceRef ? { sourceRef: entry.sourceRef } : {},
2885
+ ...entry.sourceExcerpt ? { sourceExcerpt: entry.sourceExcerpt } : {}
3202
2886
  });
3203
2887
  const internalId = result.docId;
3204
2888
  const finalEntryId = result.entryId;
@@ -3777,7 +3461,9 @@ var updateEntrySchema = z3.object({
3777
3461
  order: z3.number().optional().describe("New sort order"),
3778
3462
  canonicalKey: z3.string().optional().describe("Semantic type (e.g. 'decision', 'tension'). Only changeable on draft/uncommitted entries."),
3779
3463
  autoPublish: z3.boolean().optional().default(false).describe("Only true when user explicitly asks to publish. Default false = draft. Never auto-publish without user confirmation."),
3780
- changeNote: z3.string().optional().describe("Strongly recommended: short human-readable rationale for WHY this change was made (e.g. 'Aligned description with F1-themed copy per BET-238'). Surfaces in activity feed and pb get. If omitted, falls back to session purpose or auto-generated field summary.")
3464
+ changeNote: z3.string().optional().describe("Strongly recommended: short human-readable rationale for WHY this change was made (e.g. 'Aligned description with F1-themed copy per BET-238'). Surfaces in activity feed and pb get. If omitted, falls back to session purpose or auto-generated field summary."),
3465
+ sourceRef: z3.string().optional().describe("URI or path of the source document backing this entry. Write-once: can only be set if currently empty."),
3466
+ sourceExcerpt: z3.string().optional().describe("Verbatim excerpt from the source that backs this entry's claims. Write-once: can only be set if currently empty.")
3781
3467
  });
3782
3468
  var getHistorySchema = z3.object({
3783
3469
  entryId: z3.string().describe("Entry ID, e.g. 'T-SUPPLIER', 'BR-001'")
@@ -3794,7 +3480,7 @@ function registerKnowledgeTools(server) {
3794
3480
  inputSchema: updateEntrySchema,
3795
3481
  annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false }
3796
3482
  },
3797
- withEnvelope(async ({ entryId, name, status: rawStatus, workflowStatus: rawWorkflowStatus, data, order, canonicalKey, autoPublish, changeNote }) => {
3483
+ withEnvelope(async ({ entryId, name, status: rawStatus, workflowStatus: rawWorkflowStatus, data, order, canonicalKey, autoPublish, changeNote, sourceRef, sourceExcerpt }) => {
3798
3484
  requireWriteAccess();
3799
3485
  const PROMOTED_FIELDS = ["status", "workflowStatus", "name", "order", "canonicalKey"];
3800
3486
  const topLevelByField = { status: rawStatus, workflowStatus: rawWorkflowStatus, name, order, canonicalKey };
@@ -3833,7 +3519,9 @@ function registerKnowledgeTools(server) {
3833
3519
  canonicalKey,
3834
3520
  autoPublish,
3835
3521
  changeNote,
3836
- changedBy: getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0
3522
+ changedBy: getAgentSessionId() ? `agent:${getAgentSessionId()}` : void 0,
3523
+ ...sourceRef ? { sourceRef } : {},
3524
+ ...sourceExcerpt ? { sourceExcerpt } : {}
3837
3525
  });
3838
3526
  const id = updateResult.id;
3839
3527
  await recordSessionActivity({ entryModified: id });
@@ -6154,7 +5842,7 @@ function formatTimeAgo(ms) {
6154
5842
 
6155
5843
  // src/tools/collections.ts
6156
5844
  import { z as z8 } from "zod";
6157
- var COLLECTIONS_ACTIONS = ["list", "create", "update", "describe"];
5845
+ var COLLECTIONS_ACTIONS = ["list", "create", "update", "describe", "audit"];
6158
5846
  var qualityCriterionSchema = z8.object({
6159
5847
  field: z8.string().describe("Entry data field key this criterion applies to, e.g. 'description', 'owner'"),
6160
5848
  rule: z8.enum(["required", "min_length", "pattern"]).describe("'required': field must be non-empty (blocks commit). 'min_length': minimum string length (warns). 'pattern': regex match (warns)."),
@@ -6180,7 +5868,7 @@ var fieldSchema = z8.object({
6180
5868
  });
6181
5869
  var collectionsSchema = z8.object({
6182
5870
  action: z8.enum(COLLECTIONS_ACTIONS).describe(
6183
- "'list': browse all collections. 'create': create a new collection. 'update': update an existing collection. 'describe': full documentation for one collection \u2014 fields, option guides, usage guidance, examples."
5871
+ "'list': browse all collections. 'create': create a new collection. 'update': update an existing collection. 'describe': full documentation for one collection \u2014 fields, option guides, usage guidance, examples. 'audit': health report for all collections \u2014 missing classification, icon, displayHint coverage, and field schema gaps."
6184
5872
  ),
6185
5873
  slug: z8.string().optional().describe("URL-safe identifier for create/update, e.g. 'glossary', 'tech-debt'"),
6186
5874
  name: z8.string().optional().describe("Display name for create, or new name for update"),
@@ -6203,7 +5891,7 @@ function registerCollectionsTools(server) {
6203
5891
  "collections",
6204
5892
  {
6205
5893
  title: "Collections",
6206
- description: "Manage knowledge collections. Four actions:\n\n- **list**: Browse all collections \u2014 glossary, business rules, tracking events, etc. Returns slug, name, description, and field schema. Use before capture to see what exists.\n- **describe**: Full documentation for a single collection. Returns field help text, option decision guides, usage guidance, examples, and cross-references. Use when you need to understand a collection's purpose, field semantics, or option values.\n- **create**: Create a new collection. Provide slug, name, and field schema. Use when setting up a workspace or tracking a new type of knowledge.\n- **update**: Update an existing collection's name, description, purpose, icon, navGroup, or fields. Only provide the fields you want to change.",
5894
+ description: "Manage knowledge collections. Four actions:\n\n- **list**: Browse all collections \u2014 glossary, business rules, tracking events, etc. Returns slug, name, description, and field schema. Use before capture to see what exists.\n- **describe**: Full documentation for a single collection. Returns field help text, option decision guides, usage guidance, examples, and cross-references. Use when you need to understand a collection's purpose, field semantics, or option values.\n- **create**: Create a new collection. Provide slug, name, and field schema. Use when setting up a workspace or tracking a new type of knowledge.\n- **update**: Update an existing collection's name, description, purpose, icon, navGroup, or fields. Only provide the fields you want to change.\n- **audit**: Health report for all workspace collections. Checks classification metadata, icon presence, displayHint coverage per field, and field schema gaps vs system definitions. Returns total collections, count with issues, and per-collection issue list.",
6207
5895
  inputSchema: collectionsSchema,
6208
5896
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
6209
5897
  },
@@ -6237,6 +5925,9 @@ function registerCollectionsTools(server) {
6237
5925
  }
6238
5926
  return handleUpdate(slug, name, description, purpose, icon, navGroup, fields, { defaultCanonicalKey, defaultWorkflowStatus, validWorkflowStatuses, classificationCheck, classificationPriority, qualityCriteria, usageGuidance });
6239
5927
  }
5928
+ if (action === "audit") {
5929
+ return handleAudit();
5930
+ }
6240
5931
  return unknownAction(action, COLLECTIONS_ACTIONS);
6241
5932
  });
6242
5933
  })
@@ -6465,6 +6156,44 @@ Use \`collections action=list\` to verify the result.`
6465
6156
  )
6466
6157
  };
6467
6158
  }
6159
+ async function handleAudit() {
6160
+ const data = await mcpQuery("chain.auditCollections");
6161
+ const lines = [];
6162
+ lines.push(`# Collection Audit Report`);
6163
+ lines.push(`
6164
+ **Total:** ${data.total} \xB7 **Healthy:** ${data.healthy} \xB7 **With issues:** ${data.withIssues}`);
6165
+ if (data.withIssues === 0) {
6166
+ lines.push(`
6167
+ All collections are healthy.`);
6168
+ } else {
6169
+ const problematic = data.collections.filter((c) => c.issues.length > 0);
6170
+ lines.push(`
6171
+ ## Collections With Issues
6172
+ `);
6173
+ for (const col of problematic) {
6174
+ const icon = col.icon ?? "\u2014";
6175
+ lines.push(`### ${icon} ${col.name} (\`${col.slug}\`) \u2014 ${col.issues.length} issue(s)`);
6176
+ for (const issue of col.issues) {
6177
+ lines.push(`- **[${issue.code}]** ${issue.message}`);
6178
+ }
6179
+ lines.push("");
6180
+ }
6181
+ }
6182
+ const healthyCollections = data.collections.filter((c) => c.issues.length === 0);
6183
+ if (healthyCollections.length > 0) {
6184
+ lines.push(`
6185
+ ## Healthy Collections
6186
+ `);
6187
+ lines.push(healthyCollections.map((c) => `- ${c.icon ?? "\u2014"} \`${c.slug}\``).join("\n"));
6188
+ }
6189
+ return {
6190
+ content: [{ type: "text", text: lines.join("\n") }],
6191
+ structuredContent: success(
6192
+ `Audit complete. ${data.total} collections: ${data.healthy} healthy, ${data.withIssues} with issues.`,
6193
+ data
6194
+ )
6195
+ };
6196
+ }
6468
6197
 
6469
6198
  // src/tools/labels.ts
6470
6199
  import { z as z9 } from "zod";
@@ -6603,14 +6332,7 @@ import { z as z10 } from "zod";
6603
6332
  // src/lib/coherence/data.ts
6604
6333
  var REGISTRY_MANIFEST = [
6605
6334
  // ── Canonical UI registries ──────────────────────────────────────
6606
- {
6607
- id: "ui-colors",
6608
- path: "src/lib/utils/collection-colors.ts",
6609
- exportName: "COLLECTION_COLORS",
6610
- description: "CSS color mapping for UI components",
6611
- expectedCoverage: "curated",
6612
- keyExtraction: "object-keys"
6613
- },
6335
+ // BET-143 Slice 4: ui-colors removed — color is now a field on collection docs (schema.ts).
6614
6336
  {
6615
6337
  id: "routes",
6616
6338
  path: "src/lib/navigation.ts",
@@ -6627,56 +6349,11 @@ var REGISTRY_MANIFEST = [
6627
6349
  expectedCoverage: "curated",
6628
6350
  keyExtraction: "object-keys"
6629
6351
  },
6630
- {
6631
- id: "sidebar-collections",
6632
- path: "src/lib/navigation.ts",
6633
- exportName: "SIDEBAR_COLLECTION_SLUGS",
6634
- description: "Collection slugs with dedicated sidebar entries",
6635
- expectedCoverage: "subset",
6636
- keyExtraction: "set-values"
6637
- },
6638
- {
6639
- id: "display-fields",
6640
- path: "src/lib/components/EntryPreviewModal.svelte",
6641
- exportName: "DISPLAY_FIELDS",
6642
- description: "Fields displayed in entry preview modal per collection",
6643
- expectedCoverage: "curated",
6644
- keyExtraction: "object-keys"
6645
- },
6646
- // ── Brain Chat registries ────────────────────────────────────────
6647
- {
6648
- id: "brain-colors",
6649
- path: "src/lib/components/brain/brain-types.ts",
6650
- exportName: "COLLECTION_COLORS",
6651
- description: "Brain Chat collection color palette",
6652
- expectedCoverage: "subset",
6653
- keyExtraction: "object-keys"
6654
- },
6655
- {
6656
- id: "brain-icons",
6657
- path: "src/lib/components/brain/brain-types.ts",
6658
- exportName: "COLLECTION_ICONS",
6659
- description: "Brain Chat collection icons",
6660
- expectedCoverage: "subset",
6661
- keyExtraction: "object-keys"
6662
- },
6352
+ // BET-280 S3: display-fields removed — DISPLAY_FIELDS constant deleted, field display is now schema-driven.
6353
+ // BET-280 S3: brain-icons removed — COLLECTION_ICONS unexported, getCollectionIcon() is a local rendering fallback only.
6663
6354
  // ── Graph visualization registries ───────────────────────────────
6664
- {
6665
- id: "graph-colors",
6666
- path: "src/lib/utils/graphToVisNetwork.ts",
6667
- exportName: "GRAPH_COLLECTION_COLORS",
6668
- description: "Graph visualization hex color palette",
6669
- expectedCoverage: "subset",
6670
- keyExtraction: "object-keys"
6671
- },
6672
- {
6673
- id: "graph-type-colors",
6674
- path: "src/lib/components/graph/graph.types.ts",
6675
- exportName: "COLLECTION_COLORS",
6676
- description: "Chain Graph collection colors (distinct palette)",
6677
- expectedCoverage: "subset",
6678
- keyExtraction: "object-keys"
6679
- },
6355
+ // BET-143 Slice 4: graph-colors and graph-type-colors removed.
6356
+ // Graph rendering uses local fallback palettes (canvas needs resolved hex/CSS vars, not DB reads).
6680
6357
  // ── Cortex registries ────────────────────────────────────────────
6681
6358
  {
6682
6359
  id: "renderers",
@@ -6698,71 +6375,17 @@ var REGISTRY_MANIFEST = [
6698
6375
  // TEN-598: default-collections removed. Collection definitions live in system_collection_definitions (DB).
6699
6376
  ];
6700
6377
  var COLLECTION_REGISTRY_RULES = [
6701
- // ── Coverage: downstream registries should cover important collections ──
6702
- {
6703
- id: "coverage-ui-colors",
6704
- type: "coverage",
6705
- description: "UI colors should cover collections that have sidebar routes",
6706
- subject: "ui-colors",
6707
- reference: "routes"
6708
- },
6709
6378
  // ── Subset: specialized registries should only reference known collections ──
6710
- {
6711
- id: "subset-brain-colors",
6712
- type: "subset",
6713
- description: "Brain colors should only reference classified collections",
6714
- subject: "brain-colors",
6715
- reference: "classification-map"
6716
- },
6717
- {
6718
- id: "subset-brain-icons",
6719
- type: "subset",
6720
- description: "Brain icons should only reference classified collections",
6721
- subject: "brain-icons",
6722
- reference: "classification-map"
6723
- },
6379
+ // BET-143 Slice 4: brain-colors, graph-colors, graph-type-colors rules removed —
6380
+ // those registries were deleted when color moved to collection docs.
6381
+ // BET-280 S3: brain-icons rule removed — COLLECTION_ICONS unexported, no longer a registry.
6382
+ // BET-280 S3: display-fields rule removed DISPLAY_FIELDS deleted, field display is schema-driven.
6724
6383
  {
6725
6384
  id: "subset-renderers",
6726
6385
  type: "subset",
6727
6386
  description: "Renderers should only reference classified collections",
6728
6387
  subject: "renderers",
6729
6388
  reference: "classification-map"
6730
- },
6731
- {
6732
- id: "subset-display-fields",
6733
- type: "subset",
6734
- description: "Display fields should only reference classified collections",
6735
- subject: "display-fields",
6736
- reference: "classification-map"
6737
- },
6738
- {
6739
- id: "subset-graph-colors",
6740
- type: "subset",
6741
- description: "Graph colors should only reference classified collections",
6742
- subject: "graph-colors",
6743
- reference: "classification-map"
6744
- },
6745
- {
6746
- id: "subset-graph-type-colors",
6747
- type: "subset",
6748
- description: "Graph type colors should only reference classified collections",
6749
- subject: "graph-type-colors",
6750
- reference: "classification-map"
6751
- },
6752
- // ── Implication: presence in one registry implies presence in another ──
6753
- {
6754
- id: "implication-routes-need-colors",
6755
- type: "implication",
6756
- description: "Collections with routes should also have UI colors",
6757
- subject: "routes",
6758
- reference: "ui-colors"
6759
- },
6760
- {
6761
- id: "implication-sidebar-needs-route",
6762
- type: "implication",
6763
- description: "Sidebar collections should have a route defined",
6764
- subject: "sidebar-collections",
6765
- reference: "routes"
6766
6389
  }
6767
6390
  ];
6768
6391
 
@@ -13323,9 +12946,23 @@ function extractSessionEntryIds(priorSessions) {
13323
12946
  }
13324
12947
  return { all, lastSessionOnly };
13325
12948
  }
12949
+ var VALID_TASK_DOMAINS = [
12950
+ "auth",
12951
+ "governance",
12952
+ "architecture",
12953
+ "product",
12954
+ "data-foundation",
12955
+ "chainwork",
12956
+ "capture-pipeline",
12957
+ "ingestion",
12958
+ "intelligence-and-operations",
12959
+ "review-and-learning",
12960
+ "general"
12961
+ ];
13326
12962
  var orientSchema = z22.object({
13327
12963
  mode: z22.enum(["full", "brief"]).optional().default("full").describe("full = full context (default). brief = compact summary for mid-session re-orientation."),
13328
- task: z22.string().optional().describe("Natural-language task description for task-scoped context. When provided, orient returns scored, relevant entries for the task.")
12964
+ task: z22.string().optional().describe("Natural-language task description for task-scoped context. When provided, orient returns scored, relevant entries for the task."),
12965
+ scope: z22.enum(VALID_TASK_DOMAINS).optional().describe(`Optional domain scope to filter governance to entries relevant for this domain. Valid values: ${VALID_TASK_DOMAINS.join(", ")}.`)
13329
12966
  });
13330
12967
  function taskGroundingWarningLines(task, hasTaskGrounding = false) {
13331
12968
  if (hasTaskGrounding) return [];
@@ -13351,12 +12988,15 @@ function registerOrientTool(server) {
13351
12988
  "orient",
13352
12989
  {
13353
12990
  title: "Orient \u2014 Start Here",
13354
- description: "The single entry point for starting a session. Returns workspace context with a single recommended next action for low-readiness workspaces, or a standup-style briefing for established workspaces.\n\nUse this FIRST. One call to orient replaces 3\u20135 individual tool calls.\n\nCompleting orientation unlocks write tools for the active session.\n\n**mode:** `full` (default) returns full context. `brief` returns only vision, bet/tension counts, readiness, active bet names, and last-session summary \u2014 use for mid-session re-orientation.\n\n**task:** Optional natural-language task description. When provided, returns task-scoped context (scored, relevant entries) in addition to standard orient sections.",
12991
+ description: "The single entry point for starting a session. Returns workspace context with a single recommended next action for low-readiness workspaces, or a standup-style briefing for established workspaces.\n\nUse this FIRST. One call to orient replaces 3\u20135 individual tool calls.\n\nCompleting orientation unlocks write tools for the active session.\n\n**mode:** `full` (default) returns full context. `brief` returns only vision, bet/tension counts, readiness, active bet names, and last-session summary \u2014 use for mid-session re-orientation.\n\n**task:** Optional natural-language task description. When provided, returns task-scoped context (scored, relevant entries) in addition to standard orient sections.\n\n**scope:** Optional domain scope. Filters governance entries to those relevant for the specified domain. Valid values: auth, governance, architecture, product, data-foundation, chainwork, capture-pipeline, ingestion, intelligence-and-operations, review-and-learning, general.",
13355
12992
  inputSchema: orientSchema,
13356
12993
  annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
13357
12994
  },
13358
- withEnvelope(async ({ mode = "full", task } = {}) => {
12995
+ withEnvelope(async ({ mode = "full", task, scope }) => {
13359
12996
  const errors = [];
12997
+ if (scope && !task) {
12998
+ errors.push("--scope requires --task to filter governance. Scope was ignored.");
12999
+ }
13360
13000
  const agentSessionId = getAgentSessionId();
13361
13001
  if (isSessionOriented() && mode === "brief" && !task) {
13362
13002
  return {
@@ -13397,6 +13037,7 @@ function registerOrientTool(server) {
13397
13037
  try {
13398
13038
  const orientArgs = {};
13399
13039
  if (task) orientArgs.task = task;
13040
+ if (scope) orientArgs.scope = scope;
13400
13041
  if (sessionEntryIds.length > 0) orientArgs.sessionEntryIds = sessionEntryIds;
13401
13042
  if (lastSessionOnly.length > 0) orientArgs.lastSessionEntryIds = lastSessionOnly;
13402
13043
  orientEntries = await mcpQuery("chain.getOrientEntries", orientArgs);
@@ -14043,16 +13684,15 @@ function buildSessionSummary(log) {
14043
13684
  }
14044
13685
  return lines.join("\n");
14045
13686
  }
14046
- function computeOrganisationHealth(entries) {
13687
+ function computeOrganisationHealth(entries, classifications) {
14047
13688
  let agreements = 0;
14048
13689
  let disagreements = 0;
14049
13690
  let abstentions = 0;
14050
13691
  const flagMap = /* @__PURE__ */ new Map();
14051
- for (const entry of entries) {
14052
- const slug = entry.collectionSlug ?? entry.collection ?? "unknown";
14053
- const description = typeof entry.data?.description === "string" ? entry.data.description : "";
14054
- const result = classifyCollection(entry.name, description);
14055
- if (!result) {
13692
+ for (let i = 0; i < entries.length; i++) {
13693
+ const slug = entries[i].collectionSlug ?? entries[i].collection ?? "unknown";
13694
+ const result = classifications[i];
13695
+ if (!result?.collection) {
14056
13696
  abstentions++;
14057
13697
  continue;
14058
13698
  }
@@ -14092,7 +13732,15 @@ async function fetchOrganisationHealth() {
14092
13732
  try {
14093
13733
  const allEntries = await mcpQuery("chain.listEntries", { status: "active" });
14094
13734
  if (!allEntries || allEntries.length === 0) return null;
14095
- return computeOrganisationHealth(allEntries);
13735
+ const classifyInput = allEntries.map((e) => ({
13736
+ name: e.name ?? "",
13737
+ description: typeof e.data?.description === "string" ? e.data.description : ""
13738
+ }));
13739
+ const classifications = await mcpQuery(
13740
+ "chain.batchClassifyHeuristic",
13741
+ { entries: classifyInput }
13742
+ );
13743
+ return computeOrganisationHealth(allEntries, classifications);
14096
13744
  } catch (err) {
14097
13745
  process.stderr.write(`[MCP] fetchOrganisationHealth failed: ${err.message}
14098
13746
  `);
@@ -14260,7 +13908,7 @@ async function handleWorkspaceStatus() {
14260
13908
  )
14261
13909
  };
14262
13910
  }
14263
- async function handleAudit(limit) {
13911
+ async function handleAudit2(limit) {
14264
13912
  const log = getAuditLog();
14265
13913
  const recent = log.slice(-limit);
14266
13914
  if (recent.length === 0) {
@@ -14453,7 +14101,7 @@ function registerHealthTools(server) {
14453
14101
  if (action === "check") return handleHealthCheck();
14454
14102
  if (action === "whoami") return handleWhoami();
14455
14103
  if (action === "status") return handleWorkspaceStatus();
14456
- if (action === "audit") return handleAudit(limit ?? 20);
14104
+ if (action === "audit") return handleAudit2(limit ?? 20);
14457
14105
  if (action === "self-test") return handleSelfTest();
14458
14106
  return unknownAction(action, HEALTH_ACTIONS);
14459
14107
  });
@@ -15464,4 +15112,4 @@ export {
15464
15112
  SERVER_VERSION,
15465
15113
  createProductBrainServer
15466
15114
  };
15467
- //# sourceMappingURL=chunk-OQM6LBPX.js.map
15115
+ //# sourceMappingURL=chunk-CDBSOVW7.js.map