@productbrain/mcp 0.0.1-beta.2394 → 0.0.1-beta.2407

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.
@@ -39,7 +39,7 @@ import {
39
39
  trackSessionCaptureRate,
40
40
  trackWriteBackHintServed,
41
41
  trackZeroCaptureAuditFired
42
- } from "./chunk-DIMIOMXU.js";
42
+ } from "./chunk-PXHW2YGB.js";
43
43
 
44
44
  // src/server.ts
45
45
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -1606,7 +1606,7 @@ ${groundingReport.governance.map((g) => `- **${g.entryId}** ${g.name} [${g.colle
1606
1606
  // accepted shape as the CLI dying between create and re-eval).
1607
1607
  ...links && links.length > 0 ? { deferLLMSchedule: true } : {}
1608
1608
  });
1609
- if (result2?.preview) {
1609
+ if (result2 && "preview" in result2 && result2.preview) {
1610
1610
  const hasGrounding = groundingReport.related.length > 0 || groundingReport.duplicates.length > 0 || groundingReport.governance.length > 0;
1611
1611
  const groundingSummary = hasGrounding ? `
1612
1612
 
@@ -1647,16 +1647,17 @@ No DB writes \u2014 call without \`preview:true\` to capture for real.${result2.
1647
1647
  structuredContent: previewEnvelope
1648
1648
  };
1649
1649
  }
1650
- internalId = result2.docId;
1651
- finalEntryId = result2.entryId;
1652
- entryWarnings.push(...result2.warnings ?? []);
1653
- normalizationMeta = result2.normalization;
1654
- relationSuggestionsFromCreate = result2.relationSuggestions ?? [];
1655
- formativeHints = result2.qualityHints ?? [];
1656
- authorityDomainFromCreate = result2.authorityDomain;
1657
- coachingFromCreate = result2.coaching;
1658
- resolveGapsForEntry(name, result2.entryId);
1659
- if (result2.status === "active") {
1650
+ const created = result2;
1651
+ internalId = created.docId;
1652
+ finalEntryId = created.entryId;
1653
+ entryWarnings.push(...created.warnings ?? []);
1654
+ normalizationMeta = created.normalization;
1655
+ relationSuggestionsFromCreate = created.relationSuggestions ?? [];
1656
+ formativeHints = created.qualityHints ?? [];
1657
+ authorityDomainFromCreate = created.authorityDomain;
1658
+ coachingFromCreate = created.coaching;
1659
+ resolveGapsForEntry(name, created.entryId);
1660
+ if (created.status === "active") {
1660
1661
  wasAutoCommittedServerSide = true;
1661
1662
  }
1662
1663
  } catch (error) {
@@ -1932,11 +1933,11 @@ Use \`entries action=get\` to inspect the existing entry, or \`entries action=up
1932
1933
  const refusalReason = coherencyRefusalReason(commitResult);
1933
1934
  if (refusalReason) {
1934
1935
  commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
1935
- commitRefusal = commitResult?.refusal ?? null;
1936
+ commitRefusal = commitResultField(commitResult, "refusal") ?? null;
1936
1937
  finalStatus = "draft_on_failure";
1937
1938
  } else {
1938
- finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
1939
- contradictionAdvisory = commitResult?.contradictionAdvisory ?? null;
1939
+ finalStatus = commitResultField(commitResult, "status") === "proposal_created" ? "proposed" : "committed";
1940
+ contradictionAdvisory = commitResultField(commitResult, "contradictionAdvisory") ?? null;
1940
1941
  if (finalStatus === "committed") {
1941
1942
  await recordSessionActivity({ entryModified: internalId });
1942
1943
  trackChainEntryCommitted(wsCtx.workspaceId, {
@@ -2642,11 +2643,11 @@ async function handleBatchCapture(server, { entries, autoCommit, preview }) {
2642
2643
  const refusalReason = coherencyRefusalReason(commitResult);
2643
2644
  if (refusalReason) {
2644
2645
  commitError = `coherency gate refused this accept \u2014 ${refusalReason}`;
2645
- commitRefusal = commitResult?.refusal ?? void 0;
2646
+ commitRefusal = commitResultField(commitResult, "refusal") ?? void 0;
2646
2647
  finalStatus = "draft_on_failure";
2647
2648
  } else {
2648
- finalStatus = commitResult?.status === "proposal_created" ? "proposed" : "committed";
2649
- contradictionAdvisory = commitResult?.contradictionAdvisory ?? void 0;
2649
+ finalStatus = commitResultField(commitResult, "status") === "proposal_created" ? "proposed" : "committed";
2650
+ contradictionAdvisory = commitResultField(commitResult, "contradictionAdvisory") ?? void 0;
2650
2651
  if (finalStatus === "committed") {
2651
2652
  await recordSessionActivity({ entryModified: internalId });
2652
2653
  trackChainEntryCommitted(wsCtx.workspaceId, {
@@ -2948,8 +2949,15 @@ _Use \`entries action=move\` to correct any misclassified entries._`);
2948
2949
  };
2949
2950
  }
2950
2951
  function coherencyRefusalReason(commitResult) {
2951
- if (commitResult?.status !== "coherency_refused") return null;
2952
- return commitResult.refusal?.reason ?? "refused by the coherency gate";
2952
+ if (!commitResult || typeof commitResult !== "object" || !("status" in commitResult) || commitResult.status !== "coherency_refused") {
2953
+ return null;
2954
+ }
2955
+ const refusal = "refusal" in commitResult ? commitResult.refusal : void 0;
2956
+ return refusal?.reason ?? "refused by the coherency gate";
2957
+ }
2958
+ function commitResultField(commitResult, field) {
2959
+ if (!commitResult || typeof commitResult !== "object" || !(field in commitResult)) return void 0;
2960
+ return commitResult[field];
2953
2961
  }
2954
2962
  async function recordCommitFailure({
2955
2963
  entryId,
@@ -3362,17 +3370,17 @@ async function handleUpdateEntry({ entryId, name, status: rawStatus, workflowSta
3362
3370
  responseLines.push("");
3363
3371
  responseLines.push(deprecationWarning);
3364
3372
  }
3365
- if (updateResult.normalizationWarnings.length > 0) {
3373
+ if ((updateResult.normalizationWarnings ?? []).length > 0) {
3366
3374
  responseLines.push("");
3367
3375
  responseLines.push("\u26A0\uFE0F **Normalization warnings:**");
3368
- for (const warning of updateResult.normalizationWarnings) {
3376
+ for (const warning of updateResult.normalizationWarnings ?? []) {
3369
3377
  responseLines.push(` - ${warning}`);
3370
3378
  }
3371
3379
  }
3372
- if (updateResult.validationWarnings.length > 0) {
3380
+ if ((updateResult.validationWarnings ?? []).length > 0) {
3373
3381
  responseLines.push("");
3374
3382
  responseLines.push("\u26A0\uFE0F **Validation warnings:**");
3375
- for (const warning of updateResult.validationWarnings) {
3383
+ for (const warning of updateResult.validationWarnings ?? []) {
3376
3384
  responseLines.push(` - ${warning}`);
3377
3385
  }
3378
3386
  }
@@ -3394,10 +3402,10 @@ async function handleUpdateEntry({ entryId, name, status: rawStatus, workflowSta
3394
3402
  rejected: updateResult.normalization.rejected
3395
3403
  }
3396
3404
  },
3397
- ...updateResult.normalizationWarnings.length > 0 && {
3405
+ ...(updateResult.normalizationWarnings ?? []).length > 0 && {
3398
3406
  normalizationWarnings: updateResult.normalizationWarnings
3399
3407
  },
3400
- ...updateResult.validationWarnings.length > 0 && {
3408
+ ...(updateResult.validationWarnings ?? []).length > 0 && {
3401
3409
  validationWarnings: updateResult.validationWarnings
3402
3410
  }
3403
3411
  }, next)
@@ -3412,7 +3420,8 @@ async function handleGetHistory({ entryId }) {
3412
3420
  { entryId, eventCount: 0, events: [] }
3413
3421
  );
3414
3422
  }
3415
- const formatted = history.map((h) => {
3423
+ const formatted = history.map((rawH) => {
3424
+ const h = rawH;
3416
3425
  const date = new Date(h.timestamp).toISOString();
3417
3426
  const changes = h.changes ? ` \u2014 ${JSON.stringify(h.changes)}` : "";
3418
3427
  const qualifier = h.legacyQualifier ? ` [${h.legacyQualifier}]` : "";
@@ -3971,28 +3980,29 @@ async function handleVerifyChain(server, { collection, mode }) {
3971
3980
  for (const [eid, driftedFields] of driftedByEntry) {
3972
3981
  const entry = scopedEntries.find((e) => (e.entryId ?? e.name) === eid);
3973
3982
  if (!entry?.entryId) continue;
3983
+ const targetEntryId = entry.entryId;
3974
3984
  const updated = (entry.data?.codeMapping ?? []).map(
3975
3985
  (cm) => cm.status === "aligned" && driftedFields.has(cm.field) ? { ...cm, status: "drifted" } : cm
3976
3986
  );
3977
3987
  const updateResult = await kernelMutation("chain.updateEntry", {
3978
- entryId: entry.entryId,
3988
+ entryId: targetEntryId,
3979
3989
  data: { codeMapping: updated }
3980
3990
  });
3981
3991
  if (updateResult.outcome === "refused") {
3982
3992
  fixRefusals.push({
3983
- entryId: entry.entryId,
3993
+ entryId: targetEntryId,
3984
3994
  reason: updateResult.refusal?.reason ?? "coherency gate refused this update"
3985
3995
  });
3986
3996
  continue;
3987
3997
  }
3988
3998
  if (updateResult.normalizationWarnings.length > 0 || updateResult.validationWarnings.length > 0) {
3989
3999
  fixUpdateWarnings.push({
3990
- entryId: entry.entryId,
4000
+ entryId: targetEntryId,
3991
4001
  normalizationWarnings: updateResult.normalizationWarnings,
3992
4002
  validationWarnings: updateResult.validationWarnings
3993
4003
  });
3994
4004
  }
3995
- fixes.push(entry.entryId);
4005
+ fixes.push(targetEntryId);
3996
4006
  }
3997
4007
  }
3998
4008
  const verified = mappingChecks.filter((c) => c.result === "verified").length;
@@ -5586,7 +5596,7 @@ Use \`relations action=suggest\` to discover potential connections.`
5586
5596
  }
5587
5597
  const byCollection2 = /* @__PURE__ */ new Map();
5588
5598
  for (const entry of result3.context) {
5589
- const key = entry.collectionName;
5599
+ const key = entry.collectionName ?? "Uncategorized";
5590
5600
  if (!byCollection2.has(key)) byCollection2.set(key, []);
5591
5601
  byCollection2.get(key).push(entry);
5592
5602
  }
@@ -5680,7 +5690,7 @@ _This helps future sessions start with better constraints and context._`
5680
5690
  const hasBindingGovernance = bindingGovernanceCollections.some((bucket) => bucket.entries.length > 0) || result3.bindingGovernance.principles.length > 0 || result3.bindingGovernance.standards.length > 0 || result3.bindingGovernance.businessRules.length > 0;
5681
5691
  const byCollection2 = /* @__PURE__ */ new Map();
5682
5692
  for (const entry of result3.supportingContext) {
5683
- const key = entry.collectionName;
5693
+ const key = entry.collectionName ?? "Uncategorized";
5684
5694
  if (!byCollection2.has(key)) byCollection2.set(key, []);
5685
5695
  byCollection2.get(key).push(entry);
5686
5696
  }
@@ -5857,7 +5867,7 @@ Use \`relations action=suggest\` to discover potential connections, or \`relatio
5857
5867
  }
5858
5868
  const byCollection = /* @__PURE__ */ new Map();
5859
5869
  for (const entry of result2.related) {
5860
- const key = entry.collectionName;
5870
+ const key = entry.collectionName ?? "Uncategorized";
5861
5871
  if (!byCollection.has(key)) byCollection.set(key, []);
5862
5872
  byCollection.get(key).push(entry);
5863
5873
  }
@@ -5951,7 +5961,7 @@ Add journey steps via MCP: \`map action=slot.add mapEntryId="${mapEntryId}" slot
5951
5961
  lines.push("");
5952
5962
  const byCollection = /* @__PURE__ */ new Map();
5953
5963
  for (const entry of result2.context) {
5954
- const key = entry.collectionName;
5964
+ const key = entry.collectionName ?? "Uncategorized";
5955
5965
  if (!byCollection.has(key)) byCollection.set(key, []);
5956
5966
  byCollection.get(key).push(entry);
5957
5967
  }
@@ -8293,7 +8303,9 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
8293
8303
  let openTensions = [];
8294
8304
  try {
8295
8305
  const tensions = await kernelQuery("chain.listEntries", { collectionSlug: "tensions" });
8296
- openTensions = (tensions ?? []).filter((e) => e.workflowStatus === "open");
8306
+ openTensions = (tensions ?? []).filter(
8307
+ (e) => e.workflowStatus === "open"
8308
+ );
8297
8309
  } catch {
8298
8310
  }
8299
8311
  let readiness = null;
@@ -11657,7 +11669,7 @@ async function suggestLinksForEntries(entries) {
11657
11669
  for (const result2 of results) {
11658
11670
  if (result2.status !== "fulfilled") continue;
11659
11671
  const { entry, suggestions: entrySuggestions } = result2.value;
11660
- for (const s of entrySuggestions.slice(0, 2)) {
11672
+ for (const s of entrySuggestions.filter((x) => x.entryId != null).slice(0, 2)) {
11661
11673
  suggestions.push({
11662
11674
  fromEntryId: entry.entryId,
11663
11675
  toEntryId: s.entryId,
@@ -11710,7 +11722,8 @@ async function runWrapupReview() {
11710
11722
  const verdict = data.qualityVerdicts[draft.entryId];
11711
11723
  const conns = data.connectionCounts[draft.entryId] ?? 0;
11712
11724
  const qualityStr = verdict ? `${verdict.passed ? "Pass" : "Needs work"} (${verdict.source})` : "\u2014";
11713
- const coaching = verdict?.weakest ? verdict.weakest.hint : "\u2014";
11725
+ const weakest = verdict?.weakest;
11726
+ const coaching = weakest ? weakest.hint : "\u2014";
11714
11727
  lines.push(`| \`${draft.entryId}\` ${draft.name} | ${draft.collection} | ${qualityStr} | ${conns} | ${coaching} |`);
11715
11728
  }
11716
11729
  lines.push("");
@@ -11880,15 +11893,16 @@ async function runWrapupCommitAll(data, cachedSuggestions) {
11880
11893
  author: `agent:${sessionId}`,
11881
11894
  sessionId
11882
11895
  });
11883
- if (result2?.status === "coherency_refused") {
11896
+ if (result2 && "status" in result2 && result2.status === "coherency_refused") {
11897
+ const refusal = "refusal" in result2 ? result2.refusal : void 0;
11884
11898
  results.push({
11885
11899
  entryId: draft.entryId,
11886
11900
  ok: false,
11887
- error: `coherency gate refused this accept \u2014 ${result2.refusal?.reason ?? "refused by the coherency gate"}`
11901
+ error: `coherency gate refused this accept \u2014 ${refusal?.reason ?? "refused by the coherency gate"}`
11888
11902
  });
11889
11903
  continue;
11890
11904
  }
11891
- const proposed = result2?.status === "proposal_created";
11905
+ const proposed = !!(result2 && "status" in result2 && result2.status === "proposal_created");
11892
11906
  if (!proposed) {
11893
11907
  await recordSessionActivity({ entryModified: draft.docId });
11894
11908
  trackChainEntryCommitted(wsCtx.workspaceId, {
@@ -13720,13 +13734,13 @@ async function handleMapSuggest({ mapEntryId, slotId, query }) {
13720
13734
  for (const sid of emptySlots) {
13721
13735
  const def = slotDefs.find((s) => s.id === sid);
13722
13736
  const searchQuery = query ?? def?.label ?? sid;
13723
- const results = await kernelQuery("knowledge.search", {
13724
- query: searchQuery,
13725
- limit: 5
13737
+ const allResults = await kernelQuery("chain.searchEntries", {
13738
+ query: searchQuery
13726
13739
  });
13727
- if (results && results.length > 0) {
13740
+ const results = (allResults ?? []).slice(0, 5);
13741
+ if (results.length > 0) {
13728
13742
  const items = results.map(
13729
- (r) => ` - **${r.name}** (\`${r.entryId}\`, ${r.collectionName ?? "unknown"}) \u2014 ${r.status}`
13743
+ (r) => ` - **${r.name}** (\`${r.entryId}\`, ${r.collectionSlug ?? "unknown"}) \u2014 ${r.status}`
13730
13744
  );
13731
13745
  suggestions.push(
13732
13746
  `### ${def?.label ?? sid}
@@ -14001,7 +14015,8 @@ async function fetchOrganisationHealth() {
14001
14015
  { fields: ["name", "description", "collectionSlug"] }
14002
14016
  );
14003
14017
  if (!allEntries || allEntries.length === 0) return null;
14004
- const classifyInput = allEntries.map((e) => ({
14018
+ const projectedEntries = allEntries;
14019
+ const classifyInput = projectedEntries.map((e) => ({
14005
14020
  name: e.name ?? "",
14006
14021
  description: typeof e.description === "string" ? e.description : ""
14007
14022
  }));
@@ -14009,7 +14024,7 @@ async function fetchOrganisationHealth() {
14009
14024
  "chain.batchClassifyHeuristic",
14010
14025
  { entries: classifyInput }
14011
14026
  );
14012
- return computeOrganisationHealth(allEntries, classifications);
14027
+ return computeOrganisationHealth(projectedEntries, classifications);
14013
14028
  } catch (err) {
14014
14029
  process.stderr.write(`[MCP] fetchOrganisationHealth failed: ${err.message}
14015
14030
  `);
@@ -14914,7 +14929,18 @@ function registerResources(server) {
14914
14929
  return {
14915
14930
  contents: [{
14916
14931
  uri: uri.href,
14917
- text: buildOrientationMarkdown(collections, trackingEvents, standards, businessRules, principles),
14932
+ // `chain.listEntries`'s real return is a union (raw EntryDoc[] vs Record<string,
14933
+ // unknown>[] depending on field projection, see wrapup.ts's own doc comment on this
14934
+ // recurring residual) — `EntryListItem` only reads a documented subset of fields
14935
+ // present on both union branches; cast rather than widen the render helper's
14936
+ // signature to the full server union (PR #395, Lane C S3b annotation pass).
14937
+ text: buildOrientationMarkdown(
14938
+ collections,
14939
+ trackingEvents,
14940
+ standards,
14941
+ businessRules,
14942
+ principles
14943
+ ),
14918
14944
  mimeType: "text/markdown"
14919
14945
  }]
14920
14946
  };
@@ -15124,7 +15150,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
15124
15150
  ];
15125
15151
  const byCollection = /* @__PURE__ */ new Map();
15126
15152
  for (const entry of result2.related ?? []) {
15127
- const key = entry.collectionName;
15153
+ const key = entry.collectionName ?? "Uncategorized";
15128
15154
  if (!byCollection.has(key)) byCollection.set(key, []);
15129
15155
  byCollection.get(key).push(entry);
15130
15156
  }
@@ -15227,7 +15253,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
15227
15253
  ];
15228
15254
  for (const entry of results) {
15229
15255
  const id = entry.entryId ? `**${entry.entryId}:** ` : "";
15230
- const coll = entry.collectionName ?? entry.collectionSlug ?? "";
15256
+ const coll = entry.collectionSlug ?? "";
15231
15257
  lines.push(`- ${id}${entry.name} [${coll}] (${entry.status})`);
15232
15258
  }
15233
15259
  return {
@@ -15646,4 +15672,4 @@ export {
15646
15672
  createProductBrainServer,
15647
15673
  initFeatureFlags
15648
15674
  };
15649
- //# sourceMappingURL=chunk-Y52AWERD.js.map
15675
+ //# sourceMappingURL=chunk-DDZACG3Y.js.map