@productbrain/mcp 0.0.1-beta.8647 → 0.0.1-beta.8658

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.
@@ -7658,7 +7658,10 @@ function formatBriefingLines(view) {
7658
7658
  if (f.spineUnavailable) lines.push("Objective: unavailable \u2014 the objectives read failed; orient again to retry.");
7659
7659
  if (f.truncated) lines.push("(A bounded read hit its cap: a fact above may be missing or not the current one.)");
7660
7660
  const ruleLines = formatRuleListsLines(view.ruleLists);
7661
- if (ruleLines.length > 0) lines.push("", "Rules:", ...ruleLines);
7661
+ const rl = view.ruleLists;
7662
+ const ruleRows = rl ? rl.everyone.rows.length + (rl.team?.rows.length ?? 0) + rl.role.rows.length : 0;
7663
+ if (ruleRows === 0 && view.rulesEmptyLine) lines.push("", view.rulesEmptyLine, ...ruleLines);
7664
+ else if (ruleLines.length > 0) lines.push("", "Rules:", ...ruleLines);
7662
7665
  const questions = view.openQuestions ?? [];
7663
7666
  if (questions.length > 0) {
7664
7667
  lines.push("", `Open questions (${questions.length}) \u2014 they need you before you continue; answer with ${BRIEFING_ANSWER_COMMANDS[view.surface]}:`);
@@ -13718,42 +13721,16 @@ Write via \`update\`: \`draft\` | \`archived\` (\`accepted\` via \`commit\`, nev
13718
13721
  `;
13719
13722
 
13720
13723
  // src/resources/orientationMarkdown.ts
13721
- function buildOrientationMarkdown(collections, standards, businessRules, principles, directionLines) {
13722
- const sections = ["# Product Brain \u2014 Orientation"];
13723
- if (directionLines && directionLines.length > 0) {
13724
- sections.push(directionLines.join("\n"));
13724
+ function buildOrientationMarkdown(collections, briefingLines) {
13725
+ if (briefingLines.length === 0) {
13726
+ throw new Error("buildOrientationMarkdown: briefingLines is empty \u2014 pass the rendered briefing or the read-failed marker line");
13725
13727
  }
13728
+ const sections = ["# Product Brain \u2014 Orientation", briefingLines.join("\n")];
13726
13729
  sections.push(
13727
13730
  "## About Product Brain (PB)\nPB is a knowledge management system used by many product teams. This section describes how PB works \u2014 not your product.\n\n### How PB Organizes Its Tools\n- **Tools** = actions with side-effects or dynamic computation (capture, accept, search).\n- **Resources** = stable, read-only data (orientation, terminology, collection schemas).\n- **Prompts** = multi-step choreography (workflows, guided capture, deep dives).\n- Every tool, resource, and prompt works for ANY workspace \u2014 no bespoke logic.\n- Resource templates (URI params) serve workspace-specific data through generic patterns.\n- Compound tools with `action` enums keep the tool count minimal.\n\n" + DATA_HANDLING_SECTION
13728
13731
  );
13729
- const wsRules = [];
13730
- for (const p of principles ?? []) {
13731
- wsRules.push({ id: p.entryId ?? "", name: p.name, severity: p.data?.severity ?? void 0, source: "principles" });
13732
- }
13733
- for (const s of standards ?? []) {
13734
- wsRules.push({ id: s.entryId ?? "", name: s.name, severity: s.data?.severity ?? void 0, source: "standards" });
13735
- }
13736
- for (const r of businessRules ?? []) {
13737
- wsRules.push({ id: r.entryId ?? "", name: r.name, severity: r.data?.severity ?? void 0, source: "rules" });
13738
- }
13739
- if (wsRules.length > 0) {
13740
- const ruleLines = wsRules.map((r) => {
13741
- const sev = r.severity ? ` [${r.severity}]` : "";
13742
- return `- **${r.id}**: ${r.name}${sev}`;
13743
- }).join("\n");
13744
- sections.push(
13745
- `## Your Workspace Principles & Rules (${wsRules.length} active)
13746
- These are principles, standards, and rules your team has accepted onto the Chain. Respect them during implementation.
13747
-
13748
- ` + ruleLines + '\n\nUse `entries action=get entryId="<ID>"` to drill into any rule before making changes in that area.'
13749
- );
13750
- } else {
13751
- sections.push(
13752
- "## Your Workspace Principles & Rules\nNo active principles, standards, or rules on the Chain yet.\nUse `capture` with collection `principles`, `standards`, or `rules` to add your team's guardrails.\nOnce accepted, they appear here at orient time \u2014 so every agent session starts with your rules visible."
13753
- );
13754
- }
13755
13732
  sections.push(
13756
- "## Core Product Architecture\nThe Chain is a versioned, connected, compounding knowledge base \u2014 the SSOT for a product team.\nEverything on the Chain is one of **two primitives**:\n\n- **Entry** (atom) \u2014 a discrete knowledge unit: target audience, business rule, glossary term, metric, tension. Lives in a collection.\n- **Process** (authored) \u2014 a narrative chain with named links (Strategy Coherence, IDM Proposal). Content is inline text. Collection: `chains`.\n\nEntries are atoms. Processes author narrative from atoms.\nBoth share the same versioning, branching, gating, and relation system.\n\nThe Chain compounds: each new relation makes entries discoverable from more starting points \u2192 context gathering returns richer results \u2192 AI processes have more context \u2192 quality scores improve \u2192 next accept is smarter than the last."
13733
+ "## Core Product Architecture\nThe Chain is a versioned, connected, compounding knowledge base \u2014 the SSOT for a product team.\nEverything on the Chain is one of **two primitives**:\n\n- **Entry** (atom) \u2014 a discrete knowledge unit: target audience, rule, glossary term, metric, tension. Lives in a collection.\n- **Process** (authored) \u2014 a narrative chain with named links (Strategy Coherence, IDM Proposal). Content is inline text. Collection: `chains`.\n\nEntries are atoms. Processes author narrative from atoms.\nBoth share the same versioning, branching, gating, and relation system.\n\nThe Chain compounds: each new relation makes entries discoverable from more starting points \u2192 context gathering returns richer results \u2192 AI processes have more context \u2192 quality scores improve \u2192 next accept is smarter than the last."
13757
13734
  );
13758
13735
  sections.push(
13759
13736
  "## Architecture\n```\nCursor (stdio) \u2192 MCP Server (mcp-server/src/index.ts)\n \u2192 POST /api/aki with Bearer token\n \u2192 Convex HTTP Action (convex/http.ts)\n \u2192 internalQuery / internalMutation (convex/agentKnowledge/*)\n \u2192 Convex DB (workspace-scoped)\n```\nSecurity: API key auth on every request, workspace-scoped data, internal functions blocked from external clients.\nKey files: `packages/mcp-server/src/client.ts` (HTTP client + audit), `convex/schema.ts` (schema)."
@@ -13776,13 +13753,8 @@ Tags for filtering (e.g. \`severity:high\`), relations via \`entryRelations\`, v
13776
13753
  "## Data Model\nCould not load collections \u2014 use `collections action=list` to browse manually."
13777
13754
  );
13778
13755
  }
13779
- const rulesCount = businessRules ? `${businessRules.length} entries` : "not loaded \u2014 collection may not exist yet";
13780
13756
  sections.push(
13781
- `## Rules
13782
- Collection: \`rules\` (${rulesCount}).
13783
- Find rules: \`entries action=search\` for text search, \`entries action=list collection=rules\` to browse.
13784
- Check compliance: use the \`review-against-rules\` prompt (pass a domain).
13785
- Draft a new rule: use the \`draft-rule-from-context\` prompt.`
13757
+ '## Rules\nThe rules that bind you are in the briefing above, each with its why. A rule on no list binds nobody.\nOpen one: `entries action=get entryId="<ID>"`. Find one: `entries action=search query="<noun>"`.\nDraft a new rule: use the `draft-rule-from-context` prompt.'
13786
13758
  );
13787
13759
  sections.push(
13788
13760
  "## Knowledge Graph\nEntries are connected via typed relations (`entryRelations` table). Relations are bidirectional and collection-agnostic \u2014 any entry can link to any other entry.\n\n**Recommended relation types** (extensible \u2014 any string accepted):\n- `governs` \u2014 a rule constrains behavior of a feature\n- `defines_term_for` \u2014 a glossary term is canonical vocabulary for a feature/area\n- `belongs_to` \u2014 a feature belongs to a product area or parent concept (typed successor: `anchored_to`)\n- `informs` \u2014 a decision or insight informs a feature\n- `surfaces_tension_in` \u2014 a tension exists within a feature area\n- `related_to`, `depends_on`, `replaces`, `conflicts_with`, `references`, `confused_with`\n\nEach relation type is defined as a glossary entry (prefix `GT-REL-*`) to prevent terminology drift.\n\n**Tools:**\n- `context action=gather` \u2014 get the full context around any entry (multi-hop graph traversal)\n- `relations action=suggest` \u2014 discover potential connections for an entry\n- `relations action=create` \u2014 create a typed link between two entries\n- `relations action=find` \u2014 list direct relations for an entry\n\n**Convention:** When creating or updating entries in governed collections, always use `relations action=suggest` to discover and create relevant relations."
@@ -13802,8 +13774,7 @@ All other collections use the \`ENT-{random}\` fallback profile.
13802
13774
  **Prompts** (invoke via MCP prompt protocol):
13803
13775
  - \`name-check\` \u2014 verify a name against glossary conventions
13804
13776
  - \`draft-decision-record\` \u2014 scaffold a decision entry
13805
- - \`review-against-rules\` \u2014 check work against business rules for a domain
13806
- - \`draft-rule-from-context\` \u2014 create a new business rule from context
13777
+ - \`draft-rule-from-context\` \u2014 create a new rule from context
13807
13778
 
13808
13779
  Use \`quality action=check\` to score existing entries retroactively.
13809
13780
  Use \`entries action=update\` for post-creation adjustments (status changes, field updates, deprecation).`
@@ -13814,11 +13785,8 @@ Use \`entries action=update\` for post-creation adjustments (status changes, fie
13814
13785
  return sections.join("\n\n---\n\n");
13815
13786
  }
13816
13787
  async function buildOrientationResourceText(kernelQuery2, agentSessionId) {
13817
- const [collectionsResult, standardsResult, rulesResult, principlesResult, orientViewResult] = await Promise.allSettled([
13788
+ const [collectionsResult, orientViewResult] = await Promise.allSettled([
13818
13789
  kernelQuery2("chain.listCollections"),
13819
- kernelQuery2("chain.listEntries", { collectionSlug: "standards" }),
13820
- kernelQuery2("chain.listEntries", { collectionSlug: "rules" }),
13821
- kernelQuery2("chain.listEntries", { collectionSlug: "principles" }),
13822
13790
  kernelQuery2("chain.getOrientView", {
13823
13791
  tier: "summary",
13824
13792
  invocationPath: "unknown",
@@ -13826,20 +13794,17 @@ async function buildOrientationResourceText(kernelQuery2, agentSessionId) {
13826
13794
  })
13827
13795
  ]);
13828
13796
  const collections = collectionsResult.status === "fulfilled" ? collectionsResult.value : null;
13829
- const standards = standardsResult.status === "fulfilled" ? standardsResult.value : null;
13830
- const businessRules = rulesResult.status === "fulfilled" ? rulesResult.value : null;
13831
- const principles = principlesResult.status === "fulfilled" ? principlesResult.value : null;
13832
- let directionLines;
13797
+ let briefingLines;
13833
13798
  if (orientViewResult.status === "rejected") {
13834
13799
  const reason = orientViewResult.reason instanceof Error ? orientViewResult.reason.message : String(orientViewResult.reason);
13835
13800
  const normalized = sanitizeSingleLineField(reason);
13836
13801
  const truncated = normalized.length > 120 ? `${normalized.slice(0, 120)}\u2026` : normalized;
13837
- directionLines = [`_Strategic context unavailable: the spine read failed (${truncated})_`];
13802
+ briefingLines = [`_Briefing unavailable: the orient read failed (${truncated}); purpose, objective and the rules that bind you are not shown. Read this resource again or run orient to retry._`];
13838
13803
  } else {
13839
13804
  const orientView = orientViewResult.value;
13840
- directionLines = buildOrientBriefingLines(orientView, { everyoneOnly: !agentSessionId });
13805
+ briefingLines = buildOrientBriefingLines(orientView, { everyoneOnly: !agentSessionId });
13841
13806
  }
13842
- return buildOrientationMarkdown(collections, standards, businessRules, principles, directionLines);
13807
+ return buildOrientationMarkdown(collections, briefingLines);
13843
13808
  }
13844
13809
 
13845
13810
  // src/resources/terminologyResource.ts
@@ -14468,4 +14433,4 @@ export {
14468
14433
  createProductBrainServer,
14469
14434
  initFeatureFlags
14470
14435
  };
14471
- //# sourceMappingURL=chunk-JSKIMDXR.js.map
14436
+ //# sourceMappingURL=chunk-WKSQMKMW.js.map