@productbrain/mcp 0.0.1-beta.31 → 0.0.1-beta.32

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.
@@ -22,11 +22,10 @@ import {
22
22
  requireWriteAccess,
23
23
  runWithToolContext,
24
24
  setSessionOriented,
25
- setWriteToolsEnabled,
26
25
  startAgentSession,
27
26
  trackWriteTool,
28
27
  translateStaleToolNames
29
- } from "./chunk-3JSR5JCU.js";
28
+ } from "./chunk-UOT3O5FN.js";
30
29
  import {
31
30
  trackQualityCheck,
32
31
  trackQualityVerdict
@@ -126,7 +125,7 @@ ${formatted}` }]
126
125
  },
127
126
  async ({ entryId }) => {
128
127
  requireWriteAccess();
129
- const { runContradictionCheck } = await import("./smart-capture-X7BWHT4P.js");
128
+ const { runContradictionCheck } = await import("./smart-capture-6TQM35CV.js");
130
129
  const entry = await mcpQuery("chain.getEntry", { entryId });
131
130
  if (!entry) {
132
131
  return {
@@ -282,7 +281,8 @@ function registerEntriesTools(server) {
282
281
  title: "Entries",
283
282
  description: 'Read entries from the Chain. One tool for all entry reading.\n\n- **list**: Browse entries with optional filters (collection, status, tag, label). Use collections action=list first to discover slugs.\n- **get**: Fetch a single entry by ID \u2014 full record with data, labels, relations, history.\n- **batch**: Fetch multiple entries (max 20) in one call. Same shape as get per entry.\n- **search**: Full-text search across entries. Scope by collection or filter by status.\n\nUse `entries action=get entryId="..."` to fetch one. Use `entries action=search query="..."` to discover.',
284
283
  inputSchema: entriesSchema,
285
- annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
284
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
285
+ _meta: { ui: { resourceUri: "ui://entries/entry-cards.html" } }
286
286
  },
287
287
  async (args) => {
288
288
  const parsed = entriesSchema.safeParse(args);
@@ -371,6 +371,7 @@ async function handleGet(entryId) {
371
371
  name: String(e.name ?? ""),
372
372
  collection: String(e.canonicalKey ?? ""),
373
373
  status: String(e.status ?? ""),
374
+ entries: [{ entryId: e.entryId, name: e.name, status: e.status, collectionName: String(e.collectionName ?? e.canonicalKey ?? "\u2014") }],
374
375
  ...e.data && typeof e.data === "object" ? { data: e.data } : {},
375
376
  ...Array.isArray(e.relations) && e.relations.length > 0 ? {
376
377
  relations: e.relations.map((r) => ({
@@ -543,13 +544,24 @@ async function handleSearch(server, query, collection, status) {
543
544
  status: String(e.status ?? ""),
544
545
  ...e.score != null ? { score: e.score } : {}
545
546
  }));
547
+ const entriesForView = structuredResults.map((e) => ({
548
+ entryId: e.entryId,
549
+ name: e.name,
550
+ status: e.status,
551
+ collectionName: e.collection
552
+ }));
546
553
  return {
547
554
  content: [{ type: "text", text: `${header}
548
555
 
549
556
  ${formatted}
550
557
 
551
558
  ${footer}` }],
552
- structuredContent: { results: structuredResults, total: structuredResults.length, query }
559
+ structuredContent: {
560
+ results: structuredResults,
561
+ entries: entriesForView,
562
+ total: structuredResults.length,
563
+ query
564
+ }
553
565
  };
554
566
  }
555
567
 
@@ -594,7 +606,8 @@ function registerGraphTools(server) {
594
606
  title: "Graph",
595
607
  description: "Read from the knowledge graph. Two actions:\n\n- **find**: Traverse relations from a specific entry \u2014 shows incoming/outgoing connections. Use after entries action=get to explore connections. This is NOT full-text search (use entries action=search).\n- **suggest**: Discover potential relations for an entry using graph-aware intelligence. Returns ranked suggestions with confidence scores. Use relations action=create or relations action=batch-create to create the ones that make sense.",
596
608
  inputSchema: graphSchema,
597
- annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
609
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
610
+ _meta: { ui: { resourceUri: "ui://graph/constellation.html" } }
598
611
  },
599
612
  async (args) => {
600
613
  const parsed = graphSchema.safeParse(args);
@@ -686,11 +699,26 @@ async function handleFind(entryId, direction) {
686
699
  type: r.type,
687
700
  direction: r.isOutgoing ? "outgoing" : "incoming"
688
701
  }));
702
+ const nodes = [
703
+ { id: entryId, name: sourceEntry.name, collectionName: "" },
704
+ ...shown.map((r) => ({
705
+ id: r.otherEntryId ?? String(Math.random()),
706
+ name: r.otherName,
707
+ collectionName: r.colSlug
708
+ }))
709
+ ];
710
+ const edges = shown.filter((r) => r.otherEntryId).map((r) => ({
711
+ source: entryId,
712
+ target: r.otherEntryId,
713
+ type: r.type
714
+ }));
689
715
  return {
690
716
  content: [{ type: "text", text: lines.join("\n") }],
691
717
  structuredContent: {
692
718
  entryId,
693
719
  relations: structuredRelations,
720
+ nodes,
721
+ edges,
694
722
  total: relations.length
695
723
  }
696
724
  };
@@ -755,11 +783,26 @@ async function handleSuggest(entryId, limit, depth) {
755
783
  confidence: s.score,
756
784
  reason: s.reasoning
757
785
  }));
786
+ const nodes = [
787
+ { id: sourceId, name: resolved?.name ?? entryId, collectionName: "" },
788
+ ...suggestions.map((s) => ({
789
+ id: s.entryId ?? String(Math.random()),
790
+ name: s.name,
791
+ collectionName: s.collectionSlug
792
+ }))
793
+ ];
794
+ const edges = suggestions.filter((s) => s.entryId).map((s) => ({
795
+ source: sourceId,
796
+ target: s.entryId,
797
+ type: s.recommendedRelationType || "suggested"
798
+ }));
758
799
  return {
759
800
  content: [{ type: "text", text: lines.join("\n") }],
760
801
  structuredContent: {
761
802
  entryId: sourceId,
762
803
  suggestions: structuredSuggestions,
804
+ nodes,
805
+ edges,
763
806
  total: suggestions.length
764
807
  }
765
808
  };
@@ -963,7 +1006,8 @@ function registerContextTools(server) {
963
1006
  title: "Context",
964
1007
  description: "Assemble knowledge context in one call. Two actions:\n\n- **gather**: Three modes \u2014 (1) By entry: traverse the graph around a specific entry. (2) By task: auto-load relevant domain knowledge for a natural-language task. (3) Graph mode (entryId + mode='graph'): enhanced traversal with provenance paths.\n- **build**: Structured build spec for any entry \u2014 data, related entries, business rules, glossary terms, chain refs. Use when starting a build. Requires active session.",
965
1008
  inputSchema: contextSchema,
966
- annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false }
1009
+ annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
1010
+ _meta: { ui: { resourceUri: "ui://graph/constellation.html" } }
967
1011
  },
968
1012
  async (args) => {
969
1013
  const parsed = contextSchema.safeParse(args);
@@ -1048,7 +1092,24 @@ Use \`graph action=suggest\` to discover potential connections.`
1048
1092
  }
1049
1093
  lines2.push("");
1050
1094
  }
1051
- return { content: [{ type: "text", text: lines2.join("\n") }] };
1095
+ const rootId2 = result2.root.entryId ?? "root";
1096
+ const nodes2 = [
1097
+ { id: rootId2, name: result2.root.name, collectionName: "" },
1098
+ ...result2.context.map((e) => ({
1099
+ id: e.entryId ?? String(Math.random()),
1100
+ name: e.name,
1101
+ collectionName: e.collectionName
1102
+ }))
1103
+ ];
1104
+ const edges2 = result2.context.filter((e) => e.entryId).map((e) => ({
1105
+ source: rootId2,
1106
+ target: e.entryId,
1107
+ type: e.relationType
1108
+ }));
1109
+ return {
1110
+ content: [{ type: "text", text: lines2.join("\n") }],
1111
+ structuredContent: { nodes: nodes2, edges: edges2 }
1112
+ };
1052
1113
  }
1053
1114
  if (task && !entryId) {
1054
1115
  await server.sendLoggingMessage({
@@ -1101,7 +1162,15 @@ _Consider capturing domain knowledge discovered during this task via \`capture\`
1101
1162
  lines2.push("");
1102
1163
  }
1103
1164
  lines2.push(`_Use \`entries action=get\` for full details on any entry._`);
1104
- return { content: [{ type: "text", text: lines2.join("\n") }] };
1165
+ const taskEntries = result2.context.map((e) => ({
1166
+ entryId: e.entryId ?? String(Math.random()),
1167
+ name: e.name,
1168
+ collectionName: e.collectionName
1169
+ }));
1170
+ return {
1171
+ content: [{ type: "text", text: lines2.join("\n") }],
1172
+ structuredContent: { entries: taskEntries }
1173
+ };
1105
1174
  }
1106
1175
  await server.sendLoggingMessage({
1107
1176
  level: "info",
@@ -1145,7 +1214,24 @@ Use \`graph action=suggest\` to discover potential connections, or \`relations a
1145
1214
  }
1146
1215
  lines.push("");
1147
1216
  }
1148
- return { content: [{ type: "text", text: lines.join("\n") }] };
1217
+ const rootId = result.root.entryId ?? "root";
1218
+ const nodes = [
1219
+ { id: rootId, name: result.root.name, collectionName: "" },
1220
+ ...result.related.map((e) => ({
1221
+ id: e.entryId ?? String(Math.random()),
1222
+ name: e.name,
1223
+ collectionName: e.collectionName
1224
+ }))
1225
+ ];
1226
+ const edges = result.related.filter((e) => e.entryId).map((e) => ({
1227
+ source: rootId,
1228
+ target: e.entryId,
1229
+ type: e.relationType
1230
+ }));
1231
+ return {
1232
+ content: [{ type: "text", text: lines.join("\n") }],
1233
+ structuredContent: { nodes, edges }
1234
+ };
1149
1235
  }
1150
1236
  async function handleBuild(server, entryId, maxHops) {
1151
1237
  requireActiveSession();
@@ -1769,7 +1855,6 @@ async function handleStart() {
1769
1855
  ""
1770
1856
  );
1771
1857
  }
1772
- setWriteToolsEnabled(true);
1773
1858
  lines.push(
1774
1859
  `Session ${result.sessionId} active. Initiated by ${result.initiatedBy}. Workspace ${result.workspaceName}. Scope: ${result.toolsScope}. Write tools available after orient.`
1775
1860
  );
@@ -1813,7 +1898,6 @@ async function handleClose() {
1813
1898
  }
1814
1899
  }
1815
1900
  await closeAgentSession();
1816
- setWriteToolsEnabled(false);
1817
1901
  const lines = [
1818
1902
  `Session ${sessionId} closed.`,
1819
1903
  ""
@@ -2924,6 +3008,70 @@ function buildPlannedWorkSection(work, priorSessions, recoveryBlock) {
2924
3008
  return lines;
2925
3009
  }
2926
3010
 
3011
+ // src/tools/orient-shared.ts
3012
+ function runAlignmentCheck(task, activeBets, taskContextHits) {
3013
+ const betNames = activeBets.map((b) => b.name);
3014
+ const taskWords = task.toLowerCase().split(/\s+/).filter((w) => w.length > 3);
3015
+ const matchingBet = activeBets.find((b) => {
3016
+ const name = (b.name ?? "").toLowerCase();
3017
+ return taskWords.some((w) => name.includes(w));
3018
+ });
3019
+ const betHits = (taskContextHits ?? []).filter(
3020
+ (e) => e.collectionSlug === "bets"
3021
+ );
3022
+ const aligned = !!matchingBet || betHits.length > 0;
3023
+ const matchedBet = matchingBet?.name ?? betHits[0]?.name ?? null;
3024
+ return { aligned, matchedBet, betNames };
3025
+ }
3026
+ function buildAlignmentCheckLines(result) {
3027
+ const lines = ["## Alignment Check"];
3028
+ if (result.aligned) {
3029
+ lines.push(
3030
+ `Task appears related to active bet: **${result.matchedBet}**. Proceed.`
3031
+ );
3032
+ } else if (result.betNames.length === 0) {
3033
+ lines.push(
3034
+ "No active bets in workspace. Consider shaping a bet before building."
3035
+ );
3036
+ } else {
3037
+ lines.push("**This task does not match any active bet.**");
3038
+ lines.push(`Active bets: ${result.betNames.join(", ")}`);
3039
+ lines.push(
3040
+ "Stop and confirm with the user before designing. This may be out of scope."
3041
+ );
3042
+ }
3043
+ lines.push("");
3044
+ return lines;
3045
+ }
3046
+ var CORE_PROTOCOL = [
3047
+ '**Search before proposing.** Before suggesting new features, architecture, or changes, search the Chain: `entries action=search query="<relevant terms>"`. Build on what exists.',
3048
+ "**Reference by ID.** When discussing a topic that has Chain entries, cite them by entry ID (e.g. `DEC-50`, `PRI-3`). This keeps conversations grounded in shared knowledge.",
3049
+ "**Check scope.** If the proposed work doesn't fall under an active bet, stop and say so. Do not design implementation for out-of-scope work without explicit user go-ahead.",
3050
+ `**Capture continuously.** When a decision, tension, insight, or new term surfaces during work, capture it as a draft immediately. Don't defer to "later."`,
3051
+ "**Validate against governance.** Before finalizing any proposal, check it against the Workspace Governance section above. If it conflicts with a principle, standard, or business rule, flag the conflict explicitly."
3052
+ ];
3053
+ function buildOperatingProtocol(workspaceStandards) {
3054
+ const lines = [
3055
+ "## Operating Protocol",
3056
+ "_How to work in this workspace. Follow these before and during every task._",
3057
+ ""
3058
+ ];
3059
+ for (let i = 0; i < CORE_PROTOCOL.length; i++) {
3060
+ lines.push(`${i + 1}. ${CORE_PROTOCOL[i]}`);
3061
+ }
3062
+ if (workspaceStandards && workspaceStandards.length > 0) {
3063
+ lines.push("");
3064
+ lines.push("**Workspace-specific standards:**");
3065
+ for (const s of workspaceStandards) {
3066
+ const id = s.entryId ?? s.name;
3067
+ const desc = s.description ? ` \u2014 ${s.description.slice(0, 120)}${s.description.length > 120 ? "..." : ""}` : "";
3068
+ lines.push(`- \`${id}\` **${s.name}**${desc}`);
3069
+ }
3070
+ }
3071
+ lines.push("");
3072
+ return lines;
3073
+ }
3074
+
2927
3075
  // src/tools/start.ts
2928
3076
  var startSchema = z13.object({
2929
3077
  preset: z13.string().optional().describe(
@@ -3152,6 +3300,60 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors) {
3152
3300
  if (readiness) {
3153
3301
  lines.push(`Readiness: ${readiness.score}% (${readiness.passedChecks}/${readiness.totalChecks}).`);
3154
3302
  }
3303
+ let wsStandards = [];
3304
+ try {
3305
+ const govSlugs = ["principles", "standards", "business-rules"];
3306
+ const govLabels = {
3307
+ principles: "Principles",
3308
+ standards: "Standards",
3309
+ "business-rules": "Business Rules"
3310
+ };
3311
+ const govEntries = [];
3312
+ for (const slug of govSlugs) {
3313
+ const entries = await mcpQuery("chain.listEntries", { collectionSlug: slug });
3314
+ const active = (entries ?? []).filter((e) => e.status === "active" || e.status === "verified");
3315
+ if (active.length > 0) {
3316
+ govEntries.push({ slug, entries: active });
3317
+ if (slug === "standards") wsStandards = active;
3318
+ }
3319
+ }
3320
+ if (govEntries.length > 0) {
3321
+ lines.push("");
3322
+ lines.push("## Workspace Governance \u2014 constraints");
3323
+ lines.push("_These constrain what you build. If your proposal conflicts with any of these, stop and flag it._");
3324
+ lines.push("");
3325
+ for (const g of govEntries) {
3326
+ lines.push(`**${govLabels[g.slug]}:**`);
3327
+ for (const e of g.entries.slice(0, 8)) {
3328
+ lines.push(`- \`${e.entryId ?? e.name}\` ${e.name}`);
3329
+ }
3330
+ lines.push("");
3331
+ }
3332
+ }
3333
+ } catch {
3334
+ }
3335
+ let activeBets = [];
3336
+ try {
3337
+ const betEntries = await mcpQuery("chain.listEntries", { collectionSlug: "bets" });
3338
+ activeBets = (betEntries ?? []).filter((e) => e.status === "active" && e.data?.horizon === "now").slice(0, 8);
3339
+ if (activeBets.length > 0) {
3340
+ lines.push("");
3341
+ lines.push("## Active bets \u2014 current scope");
3342
+ lines.push("_These define what you're building now. Work outside these bets requires explicit user confirmation before designing._");
3343
+ lines.push("");
3344
+ for (const e of activeBets) {
3345
+ lines.push(`- \`${e.entryId ?? e.name}\` ${e.name}`);
3346
+ }
3347
+ lines.push("");
3348
+ }
3349
+ } catch {
3350
+ }
3351
+ const standardsForProtocol = wsStandards.map((e) => ({
3352
+ entryId: e.entryId,
3353
+ name: e.name,
3354
+ description: typeof e.data?.description === "string" ? e.data.description : typeof e.description === "string" ? e.description : void 0
3355
+ }));
3356
+ lines.push(...buildOperatingProtocol(standardsForProtocol));
3155
3357
  const plannedWork = await queryPlannedWork();
3156
3358
  if (hasPlannedWork(plannedWork)) {
3157
3359
  lines.push("");
@@ -5337,6 +5539,14 @@ function registerHealthTools(server) {
5337
5539
  }
5338
5540
  lines.push("");
5339
5541
  }
5542
+ if (task && orientEntries) {
5543
+ const result = runAlignmentCheck(
5544
+ task,
5545
+ orientEntries.activeBets ?? [],
5546
+ orientEntries.taskContext?.context
5547
+ );
5548
+ lines.push(...buildAlignmentCheckLines(result));
5549
+ }
5340
5550
  if (orientEntries) {
5341
5551
  const fmt = (e) => {
5342
5552
  const type = e.canonicalKey ?? "generic";
@@ -5344,7 +5554,9 @@ function registerHealthTools(server) {
5344
5554
  return `- \`${e.entryId ?? e._id}\` [${type} \xB7 ${stratum}] ${e.name}`;
5345
5555
  };
5346
5556
  if (orientEntries.activeBets?.length > 0) {
5347
- lines.push("## Active bets");
5557
+ lines.push("## Active bets \u2014 current scope");
5558
+ lines.push("_These define what you're building now. Work outside these bets requires explicit user confirmation before designing._");
5559
+ lines.push("");
5348
5560
  for (const e of orientEntries.activeBets) {
5349
5561
  lines.push(fmt(e));
5350
5562
  const tensions = e.linkedTensions;
@@ -5381,16 +5593,40 @@ function registerHealthTools(server) {
5381
5593
  orientEntries.staleEntries.forEach((e) => lines.push(fmt(e)));
5382
5594
  lines.push("");
5383
5595
  }
5384
- if (orientEntries.businessRules.length > 0) {
5385
- lines.push("## Business rules");
5386
- orientEntries.businessRules.forEach((e) => lines.push(fmt(e)));
5596
+ const hasPrinciples = orientEntries.principles?.length > 0;
5597
+ const hasStandards = orientEntries.standards?.length > 0;
5598
+ const hasBusinessRules = orientEntries.businessRules.length > 0;
5599
+ if (hasPrinciples || hasStandards || hasBusinessRules) {
5600
+ lines.push("## Workspace Governance \u2014 constraints");
5601
+ lines.push("_These constrain what you build. If your proposal conflicts with any of these, stop and flag it. Do not design around them without explicit user confirmation._");
5387
5602
  lines.push("");
5603
+ if (hasPrinciples) {
5604
+ lines.push("**Principles** \u2014 beliefs that guide decisions:");
5605
+ orientEntries.principles.forEach((e) => lines.push(fmt(e)));
5606
+ lines.push("");
5607
+ }
5608
+ if (hasStandards) {
5609
+ lines.push("**Standards** \u2014 conventions for how work is done:");
5610
+ orientEntries.standards.forEach((e) => lines.push(fmt(e)));
5611
+ lines.push("");
5612
+ }
5613
+ if (hasBusinessRules) {
5614
+ lines.push("**Business Rules** \u2014 system constraints:");
5615
+ orientEntries.businessRules.forEach((e) => lines.push(fmt(e)));
5616
+ lines.push("");
5617
+ }
5388
5618
  }
5389
5619
  if (orientEntries.architectureNotes.length > 0) {
5390
5620
  lines.push("## Architecture notes");
5391
5621
  orientEntries.architectureNotes.forEach((e) => lines.push(fmt(e)));
5392
5622
  lines.push("");
5393
5623
  }
5624
+ const standardsForProtocol = (orientEntries.standards ?? []).map((e) => ({
5625
+ entryId: e.entryId,
5626
+ name: e.name,
5627
+ description: typeof e.description === "string" ? e.description : void 0
5628
+ }));
5629
+ lines.push(...buildOperatingProtocol(standardsForProtocol));
5394
5630
  }
5395
5631
  const plannedWork = await queryPlannedWork();
5396
5632
  if (hasPlannedWork(plannedWork)) {
@@ -5457,7 +5693,13 @@ function registerHealthTools(server) {
5457
5693
  }
5458
5694
 
5459
5695
  // src/resources/index.ts
5696
+ import { readFile } from "fs/promises";
5697
+ import { join, resolve as resolve3 } from "path";
5460
5698
  import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
5699
+ var UI_VIEWS = {
5700
+ "ui://entries/entry-cards.html": "src/entry-cards/index.html",
5701
+ "ui://graph/constellation.html": "src/graph-constellation/index.html"
5702
+ };
5461
5703
  function formatEntryMarkdown(entry) {
5462
5704
  const id = entry.entryId ? `${entry.entryId}: ` : "";
5463
5705
  const lines = [`## ${id}${entry.name} [${entry.status}]`];
@@ -5830,6 +6072,23 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
5830
6072
  };
5831
6073
  }
5832
6074
  );
6075
+ const viewsBase = resolve3(process.cwd(), "packages", "mcp-views", "dist");
6076
+ for (const [uri, filePath] of Object.entries(UI_VIEWS)) {
6077
+ server.resource(`ui-view-${uri.replace(/[^a-z0-9]/gi, "-")}`, uri, async (uriObj) => {
6078
+ try {
6079
+ const html = await readFile(join(viewsBase, filePath), "utf-8");
6080
+ return { contents: [{ uri: uriObj.href, text: html, mimeType: "text/html" }] };
6081
+ } catch {
6082
+ return {
6083
+ contents: [{
6084
+ uri: uriObj.href,
6085
+ text: "View not found. Run npm run build in packages/mcp-views.",
6086
+ mimeType: "text/plain"
6087
+ }]
6088
+ };
6089
+ }
6090
+ });
6091
+ }
5833
6092
  }
5834
6093
 
5835
6094
  // src/prompts/index.ts
@@ -6110,6 +6369,75 @@ Description field: ${wf.kbOutputTemplate.descriptionField}
6110
6369
  };
6111
6370
  }
6112
6371
  );
6372
+ server.prompt(
6373
+ "shape-a-bet",
6374
+ "Choreograph shaping a product bet using the constellation capture pattern. Guides through problem framing, appetite, solution elements, risk identification, boundaries, and constellation capture. Use when the user wants to shape a bet, define a pitch, or scope work using Shape Up methodology.",
6375
+ {
6376
+ idea: z19.string().describe("Brief description of the idea or feature to shape (e.g. 'Improve the glossary editing flow')")
6377
+ },
6378
+ async ({ idea }) => {
6379
+ return {
6380
+ messages: [{
6381
+ role: "user",
6382
+ content: {
6383
+ type: "text",
6384
+ text: `# Shape a Bet: ${idea}
6385
+
6386
+ You are shaping a product bet using the **constellation capture pattern**. The bet will live on the Chain with connected elements, tensions, and decisions.
6387
+
6388
+ ## Prerequisites
6389
+ 1. **Start session** (if not already): \`session action=start\`
6390
+ 2. **Orient**: \`orient\` \u2014 loads workspace context and recent activity
6391
+
6392
+ ## Shaping Steps (execute in order)
6393
+
6394
+ ### Step 1: Problem Framing
6395
+ Discuss the problem with the user. Narrow to a specific, concrete problem statement. Capture the problem in 2\u20133 sentences.
6396
+
6397
+ ### Step 2: Set Appetite
6398
+ Agree on appetite (e.g. "2 weeks", "6 weeks"). This bounds the solution.
6399
+
6400
+ ### Step 3: Solution Elements
6401
+ Identify 3\u20135 solution elements. For each element that is a distinct feature, capture it:
6402
+ \`\`\`
6403
+ capture collection="features" name="<Element Name>" description="<What this element does>"
6404
+ \`\`\`
6405
+ Note the entryIds for relation linking.
6406
+
6407
+ ### Step 4: Rabbit Holes
6408
+ Identify risks. For each risk that is a known tension, capture or link:
6409
+ \`\`\`
6410
+ capture collection="tensions" name="<Risk>" description="<Risk, patch, mitigation>"
6411
+ \`\`\`
6412
+ Or link existing tensions.
6413
+
6414
+ ### Step 5: No-Gos
6415
+ Declare what is out of scope. List explicitly.
6416
+
6417
+ ### Step 6: Constellation Capture
6418
+ Capture the bet and connect the constellation:
6419
+ \`\`\`
6420
+ capture collection="bets" name="<Bet Name>" description="<Problem statement>" data='{"problem":"...","appetite":"...","elements":"...","rabbitHoles":"...","noGos":"..."}'
6421
+ \`\`\`
6422
+ Then create relations:
6423
+ \`\`\`
6424
+ relations action=batch-create relations=[
6425
+ {from:"<element-entry-id>",to:"<bet-entry-id>",type:"part_of"},
6426
+ {from:"<tension-entry-id>",to:"<element-or-bet-id>",type:"constrains"},
6427
+ ...
6428
+ ]
6429
+ \`\`\`
6430
+ Use \`graph action=suggest entryId="<bet-id>"\` to discover more connections.
6431
+
6432
+ ### Step 7: Present & Commit
6433
+ Show the user the captured bet and constellation. The capture response includes a **View in Studio** link for bets \u2014 share it. Only call \`commit-entry\` when the user confirms.
6434
+
6435
+ **Begin with Step 1.** Ask the user to describe the problem they want to solve.`
6436
+ }
6437
+ }]
6438
+ };
6439
+ }
6440
+ );
6113
6441
  server.prompt(
6114
6442
  "capture-and-connect",
6115
6443
  "Guided workflow: capture a knowledge entry, discover graph connections, create relations, and prepare for commit. Encodes the capture \u2192 suggest \u2192 batch-create \u2192 commit choreography as a step-by-step guide.",
@@ -6310,7 +6638,7 @@ If ready, ask the user to confirm. If not, suggest specific improvements.
6310
6638
  }
6311
6639
 
6312
6640
  // src/server.ts
6313
- var SERVER_VERSION = "0.4.0";
6641
+ var SERVER_VERSION = "0.7.0";
6314
6642
  var INSTRUCTIONS = [
6315
6643
  "Product Brain \u2014 the single source of truth for product knowledge.",
6316
6644
  "Terminology, standards, and core data all live here \u2014 no need to check external docs.",
@@ -6368,6 +6696,13 @@ var INSTRUCTIONS = [
6368
6696
  "Only call `commit-entry` when the user explicitly confirms (e.g. 'commit', 'looks good', 'yes').",
6369
6697
  "This builds trust \u2014 the Chain (main) is SSOT; nothing goes there without user consent.",
6370
6698
  "",
6699
+ "Alignment-first: before proposing or building anything, check orient's Workspace Governance",
6700
+ "and Active bets sections. These are constraints, not reference material.",
6701
+ "If the proposal conflicts with a principle, standard, or business rule \u2014 stop, flag the conflict,",
6702
+ "and get explicit user confirmation before proceeding. Do not design around governance.",
6703
+ "If the work is outside the scope of active bets \u2014 stop, name the gap, and ask the user",
6704
+ "to confirm before designing. Do not propose implementation for out-of-scope work without a go-ahead.",
6705
+ "",
6371
6706
  "Workspace setup: use `collections action=create` and `collections action=update` to shape the workspace",
6372
6707
  "structure with the user. Ask what they need to track; presets are starting points, not fixed.",
6373
6708
  "",
@@ -6406,7 +6741,6 @@ function createProductBrainServer() {
6406
6741
  registerUsageTools(server);
6407
6742
  registerResources(server);
6408
6743
  registerPrompts(server);
6409
- setWriteToolsEnabled(false);
6410
6744
  return server;
6411
6745
  }
6412
6746
 
@@ -6414,4 +6748,4 @@ export {
6414
6748
  SERVER_VERSION,
6415
6749
  createProductBrainServer
6416
6750
  };
6417
- //# sourceMappingURL=chunk-AZHB7KMP.js.map
6751
+ //# sourceMappingURL=chunk-THAYIBTL.js.map