@productbrain/mcp 0.0.1-beta.33 → 0.0.1-beta.35

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.
@@ -2316,23 +2316,40 @@ var SHAPE_WORKFLOW = {
2316
2316
  name: "Shape a Bet",
2317
2317
  shortDescription: "Coached shaping session \u2014 problem \u2192 appetite \u2192 elements \u2192 architecture \u2192 de-risk \u2192 pitch. Uses the `facilitate` tool for scoring and Chain capture.",
2318
2318
  icon: "\u25C6",
2319
- facilitatorPreamble: `You are now in **Shaping Mode**. You are a coached shaping facilitator powered by the \`facilitate\` tool.
2319
+ facilitatorPreamble: `You are now in **Shaping Mode**. You are an **investigating** shaping facilitator powered by the \`facilitate\` tool and Cursor sub-agents.
2320
2320
 
2321
2321
  ## Your Behavior
2322
2322
 
2323
- 1. **Start with \`facilitate action=start\`.** This creates a draft bet on the Chain and returns the Studio URL + initial coaching.
2324
- 2. **Use \`facilitate action=respond\` for every user input.** Pass the user's text, the betEntryId, and the current dimension. The server scores, captures, and returns coaching.
2325
- 3. **Read the structured response carefully.** The coaching object tells you what to say next. The scorecard tells you what's missing. The overlap tells you what already exists.
2326
- 4. **One dimension at a time.** Follow the round progression below. Don't dump all dimensions at once.
2327
- 5. **Push back on vagueness.** "Who's affected?" and "What's the workaround?" are always valid questions.
2328
- 6. **Weave Chain context into coaching.** When chainSurfaced returns related entries, mention them: "The Chain has DEC-34 about this \u2014 does your solution align?"
2323
+ 1. **Start with \`facilitate action=start\`.** This creates a draft bet on the Chain and returns the Studio URL, initial coaching, and an investigationBrief.
2324
+ 2. **Investigate before asking.** At each phase transition, read the \`investigationBrief\` in the structured response. Spawn sub-agents to search the codebase and Chain. Synthesize findings into proposals. Present proposals for user reaction.
2325
+ 3. **Use \`facilitate action=respond\` for every input.** Pass the user's text, betEntryId, dimension, and the \`source\` field:
2326
+ - \`source="user"\` \u2014 user typed this directly (default, full score weight)
2327
+ - \`source="agent_proposal"\` \u2014 you generated this proposal text (discounted score)
2328
+ - \`source="user_reaction"\` \u2014 user reacting to your proposal (full score weight)
2329
+ 4. **Read the structured response carefully.** The coaching object tells you what to say next. The scorecard tells you what's missing. The investigationBrief tells you what to investigate for the next phase.
2330
+ 5. **One dimension at a time.** Follow the round progression below. Don't dump all dimensions at once.
2331
+ 6. **Push back with evidence.** Don't just ask "Who's affected?" \u2014 search the codebase for evidence and say "I found 3 workarounds in the codebase related to this. Here's what they suggest about the problem."
2329
2332
  7. **Capture elements and risks inline** using the \`capture\` parameter on respond calls. Each becomes a Chain entry with a relation to the bet.
2330
- 8. **When captureReady is true, offer to finalize** \u2014 but don't force it. The user decides when the shape is complete.
2333
+ 8. **CRITICAL: Elements, rabbit holes, and no-gos MUST use the \`capture\` parameter.** Never pass them as plain \`userInput\` without \`capture\`. Without \`capture\`, nothing is saved to the bet \u2014 the data is silently lost. Always include \`capture={type:"element"|"risk"|"noGo", name:"...", description:"..."}\` for every structured item. Each element, risk, and no-go needs its own \`respond\` call with \`capture\`.
2334
+ 9. **When captureReady is true, offer to finalize** \u2014 but don't force it. The user decides when the shape is complete.
2335
+
2336
+ ## Investigation Pattern (ENT-59)
2337
+
2338
+ At phase transitions, follow this pattern:
2339
+ 1. Read the \`investigationBrief\` from the structured response
2340
+ 2. Spawn sub-agents in parallel (max 2, 30s budget each):
2341
+ - \`explore\` sub-agent: codebase searches (files, patterns, architecture)
2342
+ - \`generalPurpose\` sub-agent: Chain searches (entries, governance, context)
2343
+ 3. Synthesize findings into a concrete proposal (cite files and entry IDs)
2344
+ 4. Present the proposal for user reaction \u2014 "Based on the codebase, I'd suggest..."
2345
+ 5. Score the user's reaction with \`source="user_reaction"\` (full weight)
2346
+
2347
+ If investigation fails or times out, continue with the conversation \u2014 the user's knowledge is always the primary input.
2331
2348
 
2332
2349
  ## DEC-56 Boundary
2333
2350
 
2334
- The **server judges** \u2014 it scores input against 6 rubric dimensions, detects overlap, checks governance alignment.
2335
- **You coach** \u2014 you interpret the structured response, synthesize naturally, follow up on weak areas, push back when shaping isn't sharp.
2351
+ The **server judges** \u2014 it scores input against 6 rubric dimensions, detects overlap, checks governance alignment. Agent-generated text is scored at ${0.6}x weight to prevent keyword inflation (RH1).
2352
+ **You coach** \u2014 you interpret the structured response, synthesize naturally, investigate proactively, propose grounded solutions, and push back when shaping isn't sharp.
2336
2353
  The \`coaching.suggestedQuestion\` is a suggestion, not a script \u2014 rephrase or skip based on conversation flow.
2337
2354
 
2338
2355
  ## Error Recovery
@@ -2349,7 +2366,8 @@ If any facilitate call fails:
2349
2366
  - Keep chat messages to 5 lines or fewer \u2014 heavy context degrades performance
2350
2367
  - Use AskQuestion for structured choices (appetite, gates)
2351
2368
  - Synthesize between phases \u2014 reflect what was decided before moving on
2352
- - If the user seems stuck, offer prompts from the coaching.suggestedQuestion`,
2369
+ - When proposing, cite evidence: "I found X in the codebase" or "The Chain has DEC-Y about this"
2370
+ - If the user seems stuck, investigate and propose rather than just asking`,
2353
2371
  rounds: [
2354
2372
  {
2355
2373
  id: "context",
@@ -2357,7 +2375,7 @@ If any facilitate call fails:
2357
2375
  label: "Gather Context",
2358
2376
  type: "open",
2359
2377
  instruction: "Before shaping, let's see what the Chain already knows. Search for related entries, business rules, and existing decisions.",
2360
- facilitatorGuidance: "Call `orient` to load workspace context. Use `entries action=search` with keywords from the user's idea. Surface related tensions, active bets, and applicable business rules. Present a 3-5 line summary: related entries (with IDs), applicable rules, existing decisions. Then transition: 'Here's what's relevant on the Chain. Now tell me more about the problem.'",
2378
+ facilitatorGuidance: "**Investigate proactively.** Spawn sub-agents in parallel: (1) `explore` agent to search the codebase for code related to the bet topic \u2014 find modules, patterns, and pain points. (2) `generalPurpose` agent to search the Chain: call `orient`, use `entries action=search` with keywords, surface related tensions, active bets, and applicable business rules. Synthesize both into a 3-5 line context brief: what the codebase reveals, what the Chain knows, what governance applies. Present with IDs and file paths. Then transition: 'Here's what I found. Does this match the problem you're seeing?'",
2361
2379
  outputSchema: {
2362
2380
  field: "context",
2363
2381
  description: "Chain context: related entries, governance, existing decisions",
@@ -2371,7 +2389,7 @@ If any facilitate call fails:
2371
2389
  label: "Frame the Problem",
2372
2390
  type: "open",
2373
2391
  instruction: "What's the problem? Who's affected? What's the workaround today? How much time is this worth?",
2374
- facilitatorGuidance: "This round covers problem_clarity AND appetite. Call `facilitate action=respond` with dimension='problem_clarity' for the problem input, then dimension='appetite' for the time budget. Push for a specific story: 'Tell me about the last time someone hit this.' Use AskQuestion for appetite: Small Batch (1-2 weeks) or Big Batch (6 weeks). When both dimensions score 6+, present the frame and ask for Frame Go confirmation. If new terms surfaced, capture them to the glossary via `capture`. If tensions surfaced, capture them too.",
2392
+ facilitatorGuidance: "This round covers problem_clarity AND appetite. If the investigationBrief has framing tasks, search the codebase for workarounds, TODOs, and hacks related to the problem \u2014 cite what you find as evidence. Call `facilitate action=respond` with dimension='problem_clarity' for the problem input, then dimension='appetite' for the time budget. Push with evidence: 'I found 3 workaround patterns in the codebase \u2014 this suggests the problem is bigger than it looks.' Use AskQuestion for appetite: Small Batch (1-2 weeks) or Big Batch (6 weeks). When both dimensions score 6+, present the frame and ask for Frame Go confirmation. If new terms surfaced, capture them to the glossary via `capture`. If tensions surfaced, capture them too.",
2375
2393
  questions: [
2376
2394
  {
2377
2395
  id: "appetite",
@@ -2404,7 +2422,7 @@ If any facilitate call fails:
2404
2422
  label: "Find the Elements",
2405
2423
  type: "open",
2406
2424
  instruction: "What are the solution elements? Think breadboard level \u2014 places, affordances, connections. What's the architecture?",
2407
- facilitatorGuidance: "Walk through the solution at breadboard level. For each element the user describes, capture it inline: `facilitate action=respond ... capture={type:'element', name:'...', description:'...'}`. Each becomes a features entry linked to the bet. For Big Batch: also cover architecture \u2014 call respond with dimension='architecture' for architecture input. Check business rules: do any elements conflict with governance surfaced in Round 1? Capture new glossary terms and decisions as they surface. Aim for 3-5 elements. When elements score 6+ (and architecture for Big Batch), present for confirmation.",
2425
+ facilitatorGuidance: "**Investigate first.** Read the investigationBrief. Spawn sub-agents to search the codebase for affected modules, existing architecture patterns, and API boundaries. Synthesize findings into 3-5 proposed solution elements at breadboard level, citing specific files and modules. Present proposals for user reaction: 'Based on the codebase, here are the elements I'd suggest.' For each confirmed element, capture with its own respond call: `facilitate action=respond betEntryId='...' dimension='elements' source='user_reaction' userInput='...' capture={type:'element', name:'Element Name', description:'What it does'}`. Without the `capture` parameter, the element is NOT saved to the bet \u2014 you will get a WARNING if you forget. Each captured element becomes a features entry linked to the bet via part_of. For Big Batch: also investigate architecture \u2014 search for layer boundaries and dependency directions, then propose architecture. Call respond with dimension='architecture' for architecture input (no capture needed \u2014 free-form text). Check business rules: do any elements conflict with governance surfaced in Round 1? Capture new glossary terms and decisions as they surface. Aim for 3-5 elements. When elements score 6+ (and architecture for Big Batch), present for confirmation.",
2408
2426
  outputSchema: {
2409
2427
  field: "elements",
2410
2428
  description: "Core solution elements and architecture",
@@ -2419,7 +2437,7 @@ If any facilitate call fails:
2419
2437
  label: "De-risk \u2014 Rabbit Holes & No-Gos",
2420
2438
  type: "open",
2421
2439
  instruction: "What could go wrong? What are we NOT building? Walk through the solution slowly and find the risks.",
2422
- facilitatorGuidance: "Hunt rabbit holes: 'Does this require new technical work?' 'Are we assuming a design solution exists?' For each risk, capture it inline: `facilitate action=respond ... capture={type:'risk', name:'...', description:'...', theme:'implementation'}`. Each becomes a tensions entry linked to the bet. Push for mitigations \u2014 every risk needs a patch or explicit acceptance. Then declare no-gos: 'What are we explicitly NOT building?' Update the bet with no-gos via `capture={type:'noGo', ...}`. When risks score 6+ and boundaries score 4+, present Shape Go gate: 'Is this buildable within the appetite?'",
2440
+ facilitatorGuidance: "**Investigate first.** Read the investigationBrief. Spawn sub-agents to search the codebase for fragile code, tight coupling, missing tests, performance-sensitive paths, and external dependencies near the affected modules. Propose risks with evidence: 'I found that X module has no tests and is tightly coupled to Y \u2014 this is a rabbit hole.' Every confirmed risk MUST be captured with its own respond call: `facilitate action=respond betEntryId='...' dimension='risks' source='user_reaction' userInput='...' capture={type:'risk', name:'Risk Name', description:'What could go wrong', theme:'implementation'}`. Each becomes a tensions entry linked to the bet via constrains. Push for mitigations \u2014 every risk needs a patch or explicit acceptance. Then declare no-gos: 'Based on what I've seen, I'd suggest these no-gos.' Every no-go MUST use capture: `facilitate action=respond betEntryId='...' dimension='boundaries' source='user_reaction' userInput='...' capture={type:'noGo', name:'No-Go Title', description:'Why we are not doing this'}`. Without the `capture` parameter on each call, the item is NOT saved \u2014 you will get a WARNING. When risks score 6+ and boundaries score 4+, present Shape Go gate: 'Is this buildable within the appetite?'",
2423
2441
  questions: [
2424
2442
  {
2425
2443
  id: "shape-go",
@@ -2676,6 +2694,7 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
2676
2694
  import { z as z12 } from "zod";
2677
2695
 
2678
2696
  // src/tools/facilitate-rubrics.ts
2697
+ var AGENT_DISCOUNT_FACTOR = 0.6;
2679
2698
  var DIMENSIONS = [
2680
2699
  "problem_clarity",
2681
2700
  "appetite",
@@ -3118,12 +3137,19 @@ var SCORERS = {
3118
3137
  boundaries: scoreBoundaries
3119
3138
  };
3120
3139
  function scoreDimension(dimension, ctx) {
3121
- return SCORERS[dimension](ctx);
3140
+ const raw = SCORERS[dimension](ctx);
3141
+ if (ctx.source === "agent_proposal") {
3142
+ return {
3143
+ ...raw,
3144
+ score: clamp(Math.round(raw.score * AGENT_DISCOUNT_FACTOR), 0, 10)
3145
+ };
3146
+ }
3147
+ return raw;
3122
3148
  }
3123
3149
  function scoreAll(ctx) {
3124
3150
  const results = {};
3125
3151
  for (const dim of DIMENSIONS) {
3126
- results[dim] = SCORERS[dim](ctx);
3152
+ results[dim] = scoreDimension(dim, ctx);
3127
3153
  }
3128
3154
  return results;
3129
3155
  }
@@ -3212,6 +3238,57 @@ function extractPhrase(text, maxLen) {
3212
3238
  function capitalize(s) {
3213
3239
  return s.charAt(0).toUpperCase() + s.slice(1);
3214
3240
  }
3241
+ var PHASE_INVESTIGATIONS = {
3242
+ context: (betName) => ({
3243
+ phase: "context",
3244
+ dimension: "problem_clarity",
3245
+ tasks: [
3246
+ { target: "chain", query: `Search for entries related to: ${betName}`, purpose: "Find existing tensions, decisions, and bets that overlap" },
3247
+ { target: "chain", query: "List active governance: principles, standards, business-rules", purpose: "Surface constraints the solution must honor" },
3248
+ { target: "codebase", query: `Search for code related to: ${betName}`, purpose: "Understand current implementation and pain points" }
3249
+ ],
3250
+ proposalGuidance: "Synthesize findings into a 3-5 line context brief: what the Chain knows, what the codebase reveals, what governance applies.",
3251
+ reactionPrompt: "Here's what I found. Does this match what you're seeing, or is the problem different from what the Chain suggests?"
3252
+ }),
3253
+ framing: (betName) => ({
3254
+ phase: "framing",
3255
+ dimension: "problem_clarity",
3256
+ tasks: [
3257
+ { target: "codebase", query: `Find workarounds, TODOs, or hacks related to: ${betName}`, purpose: "Surface concrete evidence of the problem" },
3258
+ { target: "chain", query: "Search for related tensions and user complaints", purpose: "Quantify how often this problem occurs" }
3259
+ ],
3260
+ proposalGuidance: "Propose a problem statement based on codebase evidence. Include who's affected and what the workaround looks like in the code.",
3261
+ reactionPrompt: "Based on the codebase, here's a draft problem statement. Does this capture it, or is the real problem different?"
3262
+ }),
3263
+ elements: (betName) => ({
3264
+ phase: "elements",
3265
+ dimension: "elements",
3266
+ tasks: [
3267
+ { target: "codebase", query: `Find modules, services, and components that would be affected by: ${betName}`, purpose: "Map the solution to existing architecture" },
3268
+ { target: "architecture", query: "Identify layer boundaries, API contracts, and dependency directions", purpose: "Ground elements in real architecture" },
3269
+ { target: "chain", query: "Check DEC-31, STA-3, and other architecture standards", purpose: "Ensure elements respect existing decisions" }
3270
+ ],
3271
+ proposalGuidance: "Propose 3-5 solution elements at breadboard level. Each element should name the layer it lives in, what it does, and how it connects to existing code.",
3272
+ reactionPrompt: "I've mapped out these solution elements based on the codebase. Which feel right? Which need adjustment?"
3273
+ }),
3274
+ derisking: (betName) => ({
3275
+ phase: "derisking",
3276
+ dimension: "risks",
3277
+ tasks: [
3278
+ { target: "codebase", query: `Find fragile code, tight coupling, or missing tests near: ${betName}`, purpose: "Surface technical risks from code" },
3279
+ { target: "codebase", query: "Check for performance-sensitive paths, database queries, and external dependencies", purpose: "Identify performance and reliability risks" },
3280
+ { target: "chain", query: "Search for related tensions and past decisions that constrain this solution", purpose: "Surface risks from existing constraints" }
3281
+ ],
3282
+ proposalGuidance: "Propose rabbit holes with severity and mitigations. Each risk should cite specific code or Chain evidence. Also propose no-gos \u2014 what should be explicitly excluded.",
3283
+ reactionPrompt: "These are the risks I found in the codebase. Are these real concerns? What am I missing?"
3284
+ }),
3285
+ validation: () => null,
3286
+ capture: () => null
3287
+ };
3288
+ function buildInvestigationBrief(phase, betName, betEntryId) {
3289
+ const builder = PHASE_INVESTIGATIONS[phase];
3290
+ return builder(betName, betEntryId);
3291
+ }
3215
3292
  function generateBuildContract(ctx) {
3216
3293
  const lines = ["## Build Contract"];
3217
3294
  const consult = [
@@ -3283,6 +3360,7 @@ var facilitateSchema = z12.object({
3283
3360
  userInput: z12.string().optional().describe("User's input text for respond action."),
3284
3361
  dimension: z12.string().optional().describe("Explicit dimension to score against (e.g. 'problem_clarity'). If omitted, inferred from scorecard."),
3285
3362
  betName: z12.string().optional().describe("Name for the bet (used in start action)."),
3363
+ source: z12.enum(["user", "agent_proposal", "user_reaction"]).default("user").optional().describe("ENT-59: Source of the input text. 'user' = typed by user (default, full score weight). 'agent_proposal' = agent-generated proposal (discounted score). 'user_reaction' = user reacting to agent proposal (full weight)."),
3286
3364
  capture: z12.object({
3287
3365
  type: z12.enum(["element", "risk", "noGo", "decision"]).describe("What to capture"),
3288
3366
  name: z12.string().describe("Entry name"),
@@ -3359,8 +3437,11 @@ function buildDirective(scorecard, phase, betEntryId, captureReady, activeDimens
3359
3437
  `1. **Go** \u2014 move to solution elements`,
3360
3438
  `2. **Refine** \u2014 something's not right, let's adjust`,
3361
3439
  ``,
3362
- `If Go: ask "What are the solution pieces? Think breadboard \u2014 places, affordances, connections."`,
3363
- `Then call \`facilitate action=respond betEntryId="${b}" dimension="elements"\` with their answer.`,
3440
+ `If Go: **investigate first** \u2014 use the investigationBrief in the structured response to search the codebase and Chain.`,
3441
+ `Spawn sub-agents to explore the codebase for affected modules, existing architecture, and related patterns.`,
3442
+ `Then propose 3-5 solution elements grounded in what you found.`,
3443
+ `Present proposals for user reaction: "Based on the codebase, here are the elements I'd suggest. Which feel right?"`,
3444
+ `For each confirmed element, call \`facilitate action=respond betEntryId="${b}" dimension="elements" source="user_reaction"\` with the user's reaction.`,
3364
3445
  `If Refine: ask what needs adjusting, then call respond with dimension="problem_clarity" or "appetite".`
3365
3446
  ].join("\n");
3366
3447
  }
@@ -3392,6 +3473,17 @@ function buildDirective(scorecard, phase, betEntryId, captureReady, activeDimens
3392
3473
  }
3393
3474
  if (nextDimension && nextDimension !== activeDimension) {
3394
3475
  const nextLabel = DIMENSION_LABELS[nextDimension];
3476
+ const investigationPhases = ["elements", "architecture", "risks", "boundaries"];
3477
+ const shouldInvestigate = investigationPhases.includes(nextDimension);
3478
+ if (shouldInvestigate) {
3479
+ return [
3480
+ `Briefly synthesize what was just covered (2 lines max), then move to **${nextLabel}**.`,
3481
+ `**Investigate first:** Use the investigationBrief to search the codebase and Chain before asking the user.`,
3482
+ `Spawn sub-agents to gather evidence, then propose findings for user reaction.`,
3483
+ `After the user reacts, call \`facilitate action=respond betEntryId="${b}" dimension="${nextDimension}" source="user_reaction"\` with their reaction.`,
3484
+ `If the user provides their own input instead, call with source="user".`
3485
+ ].join("\n");
3486
+ }
3395
3487
  return [
3396
3488
  `Briefly synthesize what was just covered (2 lines max), then move to **${nextLabel}**.`,
3397
3489
  `Ask ONE open question about ${nextLabel.toLowerCase()}. Keep it to 3 lines.`,
@@ -3499,7 +3591,7 @@ async function loadSessionDrafts(betEntryId, betInternalId) {
3499
3591
  return [];
3500
3592
  }
3501
3593
  }
3502
- function buildScoringContext(userInput, betData, constellation, overlapIds, chainSurfaced = [], activeDimension) {
3594
+ function buildScoringContext(userInput, betData, constellation, overlapIds, chainSurfaced = [], activeDimension, source = "user") {
3503
3595
  const str = (key) => betData[key] ?? "";
3504
3596
  const accParts = [
3505
3597
  str("problem"),
@@ -3539,7 +3631,8 @@ function buildScoringContext(userInput, betData, constellation, overlapIds, chai
3539
3631
  noGoCount,
3540
3632
  governanceCount,
3541
3633
  decisionCount: constellation.decisionCount,
3542
- hasArchitectureText
3634
+ hasArchitectureText,
3635
+ source
3543
3636
  };
3544
3637
  }
3545
3638
  async function searchOverlap(text) {
@@ -3632,6 +3725,12 @@ async function handleStart2(args) {
3632
3725
  status: "draft",
3633
3726
  data: {
3634
3727
  problem: "",
3728
+ appetite: "",
3729
+ elements: "",
3730
+ rabbitHoles: "",
3731
+ noGos: "",
3732
+ architecture: "",
3733
+ buildContract: "",
3635
3734
  description: `Shaping session for: ${betName}`,
3636
3735
  status: "shaping",
3637
3736
  shapingSessionActive: true
@@ -3652,6 +3751,10 @@ async function handleStart2(args) {
3652
3751
  }
3653
3752
  const studioUrl = buildStudioUrl(wsCtx.workspaceSlug, betEntryId);
3654
3753
  const response = emptyResponse(betEntryId, studioUrl);
3754
+ const investigationBrief = buildInvestigationBrief("context", betName, betEntryId);
3755
+ if (investigationBrief) {
3756
+ response.investigationBrief = investigationBrief;
3757
+ }
3655
3758
  const output = [
3656
3759
  `# Shaping Session Started`,
3657
3760
  "",
@@ -3665,9 +3768,10 @@ async function handleStart2(args) {
3665
3768
  "",
3666
3769
  "---",
3667
3770
  "## Agent Directive",
3668
- "Present the workspace context above, then ask the user ONE open question at a time.",
3669
- "Start with: **What's not working well? Describe the problem \u2014 who's affected, and what's the workaround today?**",
3670
- "Do NOT list multiple questions as bullets. Ask ONE question, wait for the answer.",
3771
+ "**Investigate first** \u2014 before asking the user, use the investigationBrief to search the codebase and Chain for context related to this bet.",
3772
+ "Spawn sub-agents: one `explore` agent to search the codebase, one `generalPurpose` agent to search the Chain.",
3773
+ "Synthesize findings into a 3-5 line context brief, then present to the user.",
3774
+ "After presenting context, ask: **What's not working well? Describe the problem \u2014 who's affected, and what's the workaround today?**",
3671
3775
  "Keep your message to 5 lines or fewer. Heavy context degrades the shaping experience.",
3672
3776
  `After the user responds, call \`facilitate action=respond betEntryId="${betEntryId}" dimension="problem_clarity"\` with their answer as userInput.`
3673
3777
  ].filter(Boolean).join("\n");
@@ -3678,7 +3782,8 @@ async function handleStart2(args) {
3678
3782
  }
3679
3783
  async function handleRespond(args) {
3680
3784
  requireWriteAccess();
3681
- const { userInput, betEntryId: argBetId, dimension: argDimension, capture: captureArg } = args;
3785
+ const { userInput, betEntryId: argBetId, dimension: argDimension, capture: captureArg, source: argSource } = args;
3786
+ const source = argSource ?? "user";
3682
3787
  if (!userInput) {
3683
3788
  return {
3684
3789
  content: [{ type: "text", text: "`userInput` is required for respond action." }]
@@ -3695,7 +3800,7 @@ async function handleRespond(args) {
3695
3800
  const [betEntry, constellation, overlap, chainSurfaced] = await Promise.all([
3696
3801
  loadBetEntry(argBetId),
3697
3802
  loadConstellationState(argBetId),
3698
- searchOverlap(userInput),
3803
+ captureArg ? Promise.resolve([]) : searchOverlap(userInput),
3699
3804
  gatherChainContext(userInput)
3700
3805
  ]);
3701
3806
  if (!betEntry) {
@@ -3843,7 +3948,7 @@ async function handleRespond(args) {
3843
3948
  if (argDimension && DIMENSIONS.includes(argDimension)) {
3844
3949
  activeDimension = argDimension;
3845
3950
  } else {
3846
- const prelim = buildScoringContext(userInput, refreshedData, refreshedConstellation, overlapIds, chainSurfaced);
3951
+ const prelim = buildScoringContext(userInput, refreshedData, refreshedConstellation, overlapIds, chainSurfaced, void 0, source);
3847
3952
  activeDimension = inferActiveDimension(buildScorecard(prelim), isSmallBatch);
3848
3953
  }
3849
3954
  const scoringCtx = buildScoringContext(
@@ -3852,7 +3957,8 @@ async function handleRespond(args) {
3852
3957
  refreshedConstellation,
3853
3958
  overlapIds,
3854
3959
  chainSurfaced,
3855
- activeDimension
3960
+ activeDimension,
3961
+ source
3856
3962
  );
3857
3963
  const dimensionResult = scoreDimension(activeDimension, scoringCtx);
3858
3964
  const scorecard = buildScorecard(scoringCtx);
@@ -3869,10 +3975,7 @@ async function handleRespond(args) {
3869
3975
  };
3870
3976
  persist("problem_clarity", "problem", 50);
3871
3977
  persist("appetite", "appetite", 20);
3872
- persist("elements", "elements", 50);
3873
3978
  persist("architecture", "architecture", 50);
3874
- persist("risks", "rabbitHoles", 50);
3875
- persist("boundaries", "noGos", 20);
3876
3979
  if (overlapIds.length > 0 && !refreshedData._overlapIds) {
3877
3980
  fieldUpdates._overlapIds = overlapIds.join(",");
3878
3981
  }
@@ -3906,7 +4009,7 @@ async function handleRespond(args) {
3906
4009
  const dims = activeDimensions(isSmallBatch);
3907
4010
  const captureReady = completed.length >= (isSmallBatch ? 3 : 4) && dims.every((d) => scorecard[d] > 0);
3908
4011
  const observation = dimensionResult.satisfied.length > 0 ? `${DIMENSION_LABELS[activeDimension]}: ${dimensionResult.satisfied.join("; ")}` : `${DIMENSION_LABELS[activeDimension]}: needs more detail`;
3909
- const pushback = overlap.length > 0 ? `${overlap[0].summary} already exists on the Chain. How does your bet differ?` : dimensionResult.missing.length > 0 ? dimensionResult.missing[0] : "";
4012
+ const pushback = !captureArg && overlap.length > 0 ? `${overlap[0].summary} already exists on the Chain. How does your bet differ?` : dimensionResult.missing.length > 0 ? dimensionResult.missing[0] : "";
3910
4013
  const suggestedQuestion = dimensionResult.missing.length > 1 ? dimensionResult.missing[1] : dimensionResult.missing.length > 0 ? dimensionResult.missing[0] : `${DIMENSION_LABELS[nextDimension]} is next \u2014 ready to move on?`;
3911
4014
  const wsCtx = await getWorkspaceContext();
3912
4015
  const studioUrl = buildStudioUrl(wsCtx.workspaceSlug, argBetId);
@@ -3922,6 +4025,8 @@ async function handleRespond(args) {
3922
4025
  }
3923
4026
  const suggested = suggestCaptures(scoringCtx, activeDimension);
3924
4027
  const sessionDrafts = await loadSessionDrafts(argBetId, refreshedBet?._id ?? betEntry._id);
4028
+ const betName = refreshedData.description ?? betEntry.name;
4029
+ const investigationBrief = buildInvestigationBrief(phase, betName, argBetId) ?? void 0;
3925
4030
  const response = {
3926
4031
  phase,
3927
4032
  phaseLabel: PHASE_LABELS[phase],
@@ -3951,12 +4056,21 @@ async function handleRespond(args) {
3951
4056
  activeDimension,
3952
4057
  suggestedOrder: dims
3953
4058
  },
3954
- buildContract
4059
+ buildContract,
4060
+ investigationBrief
4061
+ };
4062
+ const STRUCTURED_DIMS = {
4063
+ elements: "element",
4064
+ risks: "risk",
4065
+ boundaries: "noGo"
3955
4066
  };
4067
+ const expectedCaptureType = STRUCTURED_DIMS[activeDimension];
4068
+ const dataLossWarning = expectedCaptureType && !captureArg ? `**WARNING:** You discussed ${activeDimension} but did not use the \`capture\` parameter \u2014 nothing was saved to the bet. Re-send with \`capture={type:"${expectedCaptureType}", name:"...", description:"..."}\` to persist this.` : "";
3956
4069
  const directive = buildDirective(scorecard, phase, argBetId, captureReady, activeDimension, nextDimension);
3957
4070
  const summaryParts = [
3958
4071
  `# ${PHASE_LABELS[phase]} \u2014 ${DIMENSION_LABELS[activeDimension]}`,
3959
4072
  "",
4073
+ dataLossWarning,
3960
4074
  `**Score:** ${scorecard[activeDimension]}/10 | **Phase:** ${PHASE_LABELS[phase]}`,
3961
4075
  observation,
3962
4076
  pushback ? `**Pushback:** ${pushback}` : "",
@@ -3969,7 +4083,13 @@ async function handleRespond(args) {
3969
4083
  directive ? `
3970
4084
  ---
3971
4085
  ## Agent Directive
3972
- ${directive}` : ""
4086
+ ${directive}` : "",
4087
+ investigationBrief ? `
4088
+ ## Investigation Brief
4089
+ ${investigationBrief.tasks.map((t) => `- **${t.target}:** ${t.query} \u2014 ${t.purpose}`).join("\n")}
4090
+
4091
+ **Proposal guidance:** ${investigationBrief.proposalGuidance}
4092
+ **Reaction prompt:** ${investigationBrief.reactionPrompt}` : ""
3973
4093
  ];
3974
4094
  return {
3975
4095
  content: [{ type: "text", text: summaryParts.filter(Boolean).join("\n") }],
@@ -6983,6 +7103,12 @@ function registerHealthTools(server) {
6983
7103
  async ({ mode = "full", task } = {}) => {
6984
7104
  const errors = [];
6985
7105
  const agentSessionId = getAgentSessionId();
7106
+ if (isSessionOriented() && mode === "brief" && !task) {
7107
+ return {
7108
+ content: [{ type: "text", text: "Already oriented. Session active, writes unlocked. Use `orient mode='full'` or `orient task='...'` for full context." }],
7109
+ structuredContent: { alreadyOriented: true, sessionId: agentSessionId }
7110
+ };
7111
+ }
6986
7112
  let wsCtx = null;
6987
7113
  try {
6988
7114
  wsCtx = await getWorkspaceContext();
@@ -8082,8 +8208,13 @@ Each scored 0-10 by the server:
8082
8208
 
8083
8209
  2. **Respond (repeat):** \`facilitate action=respond betEntryId="..." userInput="<user's input>"\`
8084
8210
  Optionally add \`dimension="problem_clarity"\` to target a specific dimension.
8085
- Optionally add \`capture={type:"element", name:"...", description:"..."}\` to capture inline.
8086
- The server scores, searches for overlap, captures to Chain, and returns coaching.
8211
+
8212
+ **CRITICAL \u2014 Capture is REQUIRED for structured items:**
8213
+ Elements, risks, and no-gos MUST include the \`capture\` parameter. Without it, nothing is saved to the bet \u2014 the data is silently lost and you will receive a WARNING.
8214
+ - Elements: \`capture={type:"element", name:"...", description:"..."}\`
8215
+ - Risks: \`capture={type:"risk", name:"...", description:"...", theme:"implementation"}\`
8216
+ - No-gos: \`capture={type:"noGo", name:"...", description:"..."}\`
8217
+ Each element, risk, and no-go needs its own \`respond\` call with \`capture\`.
8087
8218
 
8088
8219
  3. **Score (anytime):** \`facilitate action=score betEntryId="..."\`
8089
8220
  Check the scorecard without advancing.
@@ -8345,7 +8476,7 @@ If ready, ask the user to confirm. If not, suggest specific improvements.
8345
8476
  }
8346
8477
 
8347
8478
  // src/server.ts
8348
- var SERVER_VERSION = "0.7.1";
8479
+ var SERVER_VERSION = "0.7.2";
8349
8480
  var INSTRUCTIONS = [
8350
8481
  "Product Brain \u2014 the single source of truth for product knowledge.",
8351
8482
  "Terminology, standards, and core data all live here \u2014 no need to check external docs.",
@@ -8456,4 +8587,4 @@ export {
8456
8587
  SERVER_VERSION,
8457
8588
  createProductBrainServer
8458
8589
  };
8459
- //# sourceMappingURL=chunk-CWNAQXZX.js.map
8590
+ //# sourceMappingURL=chunk-HTL6Y2AO.js.map