@productbrain/mcp 0.0.1-beta.8555 → 0.0.1-beta.8563

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.
@@ -38,7 +38,7 @@ import {
38
38
  trackQualityVerdict,
39
39
  trackSessionCaptureRate,
40
40
  trackZeroCaptureAuditFired
41
- } from "./chunk-UPQW54GN.js";
41
+ } from "./chunk-FB2VAQOX.js";
42
42
 
43
43
  // src/server.ts
44
44
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -144,8 +144,8 @@ var GATE_PATTERNS = [
144
144
  {
145
145
  pattern: /orientation required|call.*orient/i,
146
146
  code: "ORIENTATION_REQUIRED",
147
- recovery: "Orient before writing.",
148
- action: { tool: "orient", description: "Orient session", parameters: {} }
147
+ recovery: "Run orient with a task, then retry.",
148
+ action: { tool: "orient", description: "Orient with a task", parameters: { action: "task" } }
149
149
  },
150
150
  {
151
151
  pattern: /read.?only.*scope/i,
@@ -154,6 +154,13 @@ var GATE_PATTERNS = [
154
154
  action: { tool: "workspace", description: "Check key scope", parameters: { action: "whoami" } }
155
155
  }
156
156
  ];
157
+ function orientationRefusal(err) {
158
+ const gate = GATE_PATTERNS.find((g) => g.code === "ORIENTATION_REQUIRED");
159
+ const mcpErr = asKernelCallError(err);
160
+ const message = mcpErr?.cleanMessage ?? (err instanceof Error ? err.message : String(err));
161
+ if (!gate || !gate.pattern.test(message)) return null;
162
+ return { code: gate.code, message, recovery: gate.recovery, availableActions: [gate.action] };
163
+ }
157
164
  function classifyError(err) {
158
165
  const message = err instanceof Error ? err.message : String(err);
159
166
  if (err instanceof GateError) {
@@ -361,6 +368,13 @@ function thinWrapper(handler) {
361
368
  }
362
369
  };
363
370
  }
371
+ function orientationRefusalResult(err, lines) {
372
+ const refused = orientationRefusal(err);
373
+ if (!refused) return null;
374
+ const text = [...lines, `**${refused.message}**`, "", refused.recovery ?? ""].join("\n");
375
+ return { content: textContent(text), structuredContent: failure(refused.code, refused.message, refused.recovery, refused.availableActions) };
376
+ }
377
+ var ORIENT_REQUIRED_NOTE = "workflow checkpoints and organisation-structure writes (membership, ownership, parent) still require an oriented session.";
364
378
 
365
379
  // src/tools/knowledge-helpers.ts
366
380
  import { z as z2 } from "zod/v3";
@@ -7506,7 +7520,6 @@ function formatWhatNeedsAttentionLines(wna) {
7506
7520
  for (const b of wna.overdueOutcomeBlockers ?? []) {
7507
7521
  const subject = b.betId ? `\`${b.betId}\` \u2192 \`${b.krId}\`` : `\`${b.krId}\``;
7508
7522
  if (b.reason === "ready-to-close") lines.push(`- ${subject} \u2014 readings say **${b.readyToClose}**. ${b.instruction ?? "Surface this to the founder; do not write the status yourself."}`);
7509
- else if (b.reason === "scheduled-date-passed" && b.scheduledVerificationDate) lines.push(`- ${subject} (${b.daysOverdue}d past its scheduled verification date \u2014 ${b.scheduledVerificationDate})`);
7510
7523
  else lines.push(`- ${subject} (${b.daysOverdue}d overdue for a reading)`);
7511
7524
  }
7512
7525
  lines.push("");
@@ -8319,7 +8332,7 @@ function taskGroundingWarningLines(task, hasTaskGrounding = false) {
8319
8332
  if (task) {
8320
8333
  return [
8321
8334
  "## Task grounding incomplete",
8322
- "_A task was provided, but task-scoped governance/context did not load. nothing in the Chain matched it._",
8335
+ "_A task was provided, but task-scoped governance/context did not load. Nothing in the Chain matched it._",
8323
8336
  "",
8324
8337
  'Refine the task and rerun `orient task="describe the work"` or use `context action="gather"` for deeper task context.',
8325
8338
  ""
@@ -8352,7 +8365,7 @@ function registerOrientTool(server) {
8352
8365
  "orient",
8353
8366
  {
8354
8367
  title: "Orient",
8355
- description: "Workspace orientation and session bootstrapping. Two actions:\n\n- **start**: Universal opener (absorbs `start_pb`) \u2014 say 'Start PB' to begin every session. Returns a standup briefing for every workspace state, fresh or active. Orients the CURRENT session \u2014 it does not create one; for writes, call `session action=start` first.\n- **task**: Task-grounded context loader (the original `orient` behavior). Use after `action=start` to load governance and context for a specific task. Completing orientation unlocks write tools.\n\n**tier** (action=task): Controls payload depth.\n- `summary` (~10 KB) \u2014 compact, calibrated for task-scoped retrieval.\n- `standard` (~256 KB) \u2014 rich, suited to workspace standups.\n- `full` \u2014 complete payload, no cap. Use with deliberation.\n\nThe spine (vision, purpose, strategy highlights) is served in full and a grounding status flags when context was reduced.\n\nDefaults: `summary` when `task` is provided; `standard` when `task` is absent. Explicit `tier` always wins.\n\n**mode** (action=task): `full` (default) returns full context. `brief` returns compact summary \u2014 mapped to tier=summary internally.",
8368
+ description: "Workspace orientation and session bootstrapping. Two actions:\n\n- **start**: Universal opener (absorbs `start_pb`) \u2014 say 'Start PB' to begin every session. Returns a standup briefing for every workspace state, fresh or active. Orients the CURRENT session \u2014 it does not create one; for writes, call `session action=start` first.\n- **task**: Task-grounded context loader (the original `orient` behavior). Use after `action=start` to load governance and context for a specific task. Orient is advice for captures, relations, accepts, ticks and questions; " + ORIENT_REQUIRED_NOTE + "\n\n**tier** (action=task): Controls payload depth.\n- `summary` (~10 KB) \u2014 compact, calibrated for task-scoped retrieval.\n- `standard` (~256 KB) \u2014 rich, suited to workspace standups.\n- `full` \u2014 complete payload, no cap. Use with deliberation.\n\nThe spine (vision, purpose, strategy highlights) is served in full and a grounding status flags when context was reduced.\n\nDefaults: `summary` when `task` is provided; `standard` when `task` is absent. Explicit `tier` always wins.\n\n**mode** (action=task): `full` (default) returns full context. `brief` returns compact summary \u2014 mapped to tier=summary internally.",
8356
8369
  inputSchema: orientSchema,
8357
8370
  // Mixed read/write noun (§3 R3): 'start' writes session state.
8358
8371
  annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: false }
@@ -8590,7 +8603,7 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
8590
8603
  } else if (agentSessionId) {
8591
8604
  orientationStatus2 = "task_required";
8592
8605
  lines.push("---");
8593
- lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
8606
+ lines.push('Workspace orientation loaded. Run `orient task="describe the work"` for task-shaped governance before substantive work; ' + ORIENT_REQUIRED_NOTE);
8594
8607
  } else {
8595
8608
  lines.push("---");
8596
8609
  lines.push("_No active agent session. Call `session action=start` to begin._");
@@ -8975,7 +8988,7 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
8975
8988
  } else if (agentSessionId) {
8976
8989
  orientationStatus = "task_required";
8977
8990
  lines.push("---");
8978
- lines.push('Workspace orientation loaded. Write tools stay locked until you run `orient task="describe the work"`.');
8991
+ lines.push('Workspace orientation loaded. Run `orient task="describe the work"` for task-shaped governance before substantive work; ' + ORIENT_REQUIRED_NOTE);
8979
8992
  } else {
8980
8993
  lines.push("---");
8981
8994
  lines.push("_No active agent session. Call `session action=start` to begin a tracked session._");
@@ -10455,6 +10468,8 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
10455
10468
  )
10456
10469
  };
10457
10470
  } catch (err) {
10471
+ const refusal = orientationRefusalResult(err, lines);
10472
+ if (refusal) return refusal;
10458
10473
  const msg = err instanceof Error ? err.message : String(err);
10459
10474
  lines.push(
10460
10475
  `**Chain accept failed**: ${msg}`,
@@ -10554,12 +10569,10 @@ This checkpoint was NOT saved. The conversation context is preserved \u2014 cont
10554
10569
  )
10555
10570
  };
10556
10571
  } catch (err) {
10572
+ const refusal = orientationRefusalResult(err, lines);
10573
+ if (refusal) return refusal;
10557
10574
  const msg = err instanceof Error ? err.message : String(err);
10558
- lines.push(
10559
- `**Checkpoint persistence failed**: ${msg}`,
10560
- "",
10561
- `The conversation context is preserved, but this round was not saved as a durable workflow checkpoint.`
10562
- );
10575
+ lines.push(`**Checkpoint persistence failed**: ${msg}`, "", "The conversation context is preserved, but this round was not saved as a durable workflow checkpoint.");
10563
10576
  return {
10564
10577
  content: [{ type: "text", text: lines.join("\n") }],
10565
10578
  structuredContent: failure(
@@ -10631,12 +10644,10 @@ async function handleFacilitatedFinalization(wf, descriptor, roundId, normalized
10631
10644
  )
10632
10645
  };
10633
10646
  } catch (err) {
10647
+ const refusal = orientationRefusalResult(err, lines);
10648
+ if (refusal) return refusal;
10634
10649
  const msg = err instanceof Error ? err.message : String(err);
10635
- lines.push(
10636
- `**Finalization failed**: ${msg}`,
10637
- "",
10638
- `The workflow output is preserved in this conversation.`
10639
- );
10650
+ lines.push(`**Finalization failed**: ${msg}`, "", "The workflow output is preserved in this conversation.");
10640
10651
  return {
10641
10652
  content: [{ type: "text", text: lines.join("\n") }],
10642
10653
  structuredContent: failure(
@@ -11995,7 +12006,7 @@ async function handleStart2(data) {
11995
12006
  const result2 = await startAgentSession(data?.role);
11996
12007
  const lines = [];
11997
12008
  lines.push(
11998
- `Session ${result2.sessionId} active. Initiated by ${result2.initiatedBy}. Workspace ${result2.workspaceName}. Scope: ${result2.toolsScope}. Write tools available after orient.`
12009
+ `Session ${result2.sessionId} active. Initiated by ${result2.initiatedBy}. Workspace ${result2.workspaceName}. Scope: ${result2.toolsScope}. Orient with a task before substantive work: it is advice for captures, relations, accepts, ticks and questions; workflow checkpoints and organisation-structure writes still require it.`
11999
12010
  );
12000
12011
  if (result2.roleEntryId) {
12001
12012
  lines.push(`Acting as role: ${result2.roleName ?? result2.roleEntryId}.`);
@@ -12007,7 +12018,7 @@ async function handleStart2(data) {
12007
12018
  }
12008
12019
  const ruleLines = formatRuleListsLines(result2.ruleLists);
12009
12020
  if (ruleLines.length > 0) lines.push("", "Rules:", ...ruleLines);
12010
- const summary = `Session ${result2.sessionId} active. Workspace ${result2.workspaceName}. Write tools available after orient.`;
12021
+ const summary = `Session ${result2.sessionId} active. Workspace ${result2.workspaceName}. Orient with a task first; workflow checkpoints and organisation-structure writes still require it.`;
12011
12022
  return {
12012
12023
  content: [{ type: "text", text: lines.join("\n") }],
12013
12024
  structuredContent: success(summary, {
@@ -14528,4 +14539,4 @@ export {
14528
14539
  createProductBrainServer,
14529
14540
  initFeatureFlags
14530
14541
  };
14531
- //# sourceMappingURL=chunk-MWNEBU4R.js.map
14542
+ //# sourceMappingURL=chunk-6OMZMXSM.js.map