@productbrain/mcp 0.0.1-beta.5884 → 0.0.1-beta.5894

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.
@@ -8734,6 +8734,16 @@ function formatShapeAdvisorySummaryLine(sas) {
8734
8734
  return `Shape advisories (${sas.windowDays}d): ${sas.pendingCount} pending / ${sas.compoundTotal} compound${pendingRatePart} \u2014 precisionAgent ${agentPart}, precisionHuman ${humanPart}.${truncatedNote}${candidatePart}`;
8735
8735
  }
8736
8736
 
8737
+ // src/lib/strip.ts
8738
+ var ANSI_AND_CONTROL_RE = /\x1b\[[0-9;]*[A-Za-z]|\x1b\][^\x07]*\x07|\x1b[^[\]0-9;A-Za-z]?|[\x00-\x08\x0b-\x1f\x7f]/g;
8739
+ function stripControlChars(str) {
8740
+ if (!str) return str;
8741
+ return str.replace(ANSI_AND_CONTROL_RE, "");
8742
+ }
8743
+ function sanitizeSingleLineField(str) {
8744
+ return stripControlChars(str).replace(/\s+/g, " ").trim();
8745
+ }
8746
+
8737
8747
  // src/tools/orient-rituals.ts
8738
8748
  function buildRitualsSurfaceLines(view, opts) {
8739
8749
  const lines = [""];
@@ -8748,6 +8758,43 @@ function buildRitualsSurfaceLines(view, opts) {
8748
8758
  if (view?.atCapLine) lines.push(view.atCapLine);
8749
8759
  return lines;
8750
8760
  }
8761
+ function buildDirectionLines(view) {
8762
+ const purpose = view?.strategicContext?.purpose;
8763
+ const vision = view?.strategicContext?.vision;
8764
+ const strategy = (view?.strategyHighlights ?? []).filter(
8765
+ (e) => typeof e === "object" && e != null && typeof e.name === "string" && e.name.length > 0
8766
+ );
8767
+ if (!purpose && !vision && strategy.length === 0) return [];
8768
+ const lines = ["## Strategic Context"];
8769
+ if (purpose) lines.push(`**Purpose:** ${stripControlChars(purpose)}`);
8770
+ if (vision) lines.push(`**Vision:** ${stripControlChars(vision)}`);
8771
+ for (const row of strategy) {
8772
+ const mark = provenanceMark(row.provenance);
8773
+ const anchorSuffix = row.anchoredBy ? ` (${stripControlChars(row.anchoredBy)})` : "";
8774
+ const preview = typeof row.preview === "string" && row.preview ? ` \u2014 ${stripControlChars(row.preview)}` : "";
8775
+ lines.push(`**Strategy:** ${mark}${stripControlChars(row.name)}${anchorSuffix}${preview}`);
8776
+ }
8777
+ return lines;
8778
+ }
8779
+ async function fetchAndRenderOpenerDirection(kernelQuery2, errors, session) {
8780
+ let view = null;
8781
+ let fetchFailed = false;
8782
+ try {
8783
+ view = await kernelQuery2("chain.getOrientView", {
8784
+ tier: "standard",
8785
+ invocationPath: "session-start",
8786
+ // Stamps this call onto the current session/conversation/task (same as every other
8787
+ // chain.getOrientView caller) so recordOrientMetric's orientCallCount/billing rollup sees it.
8788
+ ...session?.agentSessionId ? { sessionId: session.agentSessionId } : {},
8789
+ ...session?.conversationId ? { conversationId: session.conversationId } : {},
8790
+ ...session?.task ? { task: session.task } : {}
8791
+ });
8792
+ } catch (e) {
8793
+ fetchFailed = true;
8794
+ errors.push(`Direction unavailable: ${e instanceof Error ? e.message : String(e)}`);
8795
+ }
8796
+ return [...buildDirectionLines(view), ...buildRitualsSurfaceLines(view, { fetchFailed: fetchFailed || view?.fetchFailed === true })];
8797
+ }
8751
8798
  async function buildAlreadyOrientedResult(kernelQuery2, agentSessionId, taskGroundingWarningLines2) {
8752
8799
  let ritualsFetchFailed = false;
8753
8800
  let rituals = null;
@@ -8900,9 +8947,9 @@ async function loadSkillBody(entryId) {
8900
8947
  }
8901
8948
 
8902
8949
  // src/lib/sessionNotices.ts
8903
- var ANSI_AND_CONTROL_RE = /\x1b\[[0-9;]*[A-Za-z]|\x1b\][^\x07]*\x07|\x1b[^[\]0-9;A-Za-z]?|[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
8950
+ var ANSI_AND_CONTROL_RE2 = /\x1b\[[0-9;]*[A-Za-z]|\x1b\][^\x07]*\x07|\x1b[^[\]0-9;A-Za-z]?|[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
8904
8951
  function safe(str) {
8905
- return str ? str.replace(ANSI_AND_CONTROL_RE, "") : "";
8952
+ return str ? str.replace(ANSI_AND_CONTROL_RE2, "") : "";
8906
8953
  }
8907
8954
  var FEEDBACK_SUBMIT_HINT = "Friction or ideas? Use `feedback action=submit` \u2014 describe how pb behaved, not your workspace content. Once screening completes, it enters the builders' triage queue.";
8908
8955
  function nextActionForVerb(verb, args) {
@@ -9123,6 +9170,7 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
9123
9170
  lines.push("Let's get your workspace active.");
9124
9171
  lines.push("");
9125
9172
  }
9173
+ lines.push(...await fetchAndRenderOpenerDirection(kernelQuery, errors, { agentSessionId, conversationId: getConversationId(), task }));
9126
9174
  if (isLowReadiness && readiness) {
9127
9175
  const gaps = readiness.gaps ?? [];
9128
9176
  if (gaps.length > 0) {
@@ -9260,6 +9308,8 @@ async function buildOrientResponse(wsCtx, agentSessionId, errors, task) {
9260
9308
  lines.push("");
9261
9309
  lines.push(...formatRecoveryBlock(recoveryBlock));
9262
9310
  }
9311
+ lines.push(captureBehaviorNote);
9312
+ lines.push("");
9263
9313
  lines.push("**What are you working on?** Tell me and I'll load relevant governance and context.");
9264
9314
  lines.push("");
9265
9315
  }
@@ -9544,7 +9594,7 @@ function registerOrientTool(server) {
9544
9594
  "orient",
9545
9595
  {
9546
9596
  title: "Orient",
9547
- description: "Workspace orientation and session bootstrapping. Three actions:\n\n- **start**: Universal opener (absorbs `start_pb`) \u2014 say 'Start PB' to begin every session. Stage-aware: fresh workspaces (blank/seeded) get the SKILL-pb-setup body verbatim; active workspaces (grounded/connected) get a standup briefing. 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- **record-activation**: Chat-only activation receipt writer (absorbs `record_activation`) \u2014 closes the install-to-activation arc for chat-only surfaces.\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, except strategicContext vision/purpose (always server-bounded to ~200 chars + an ellipsis marker \u2014 no uncapped path at any tier). Use with deliberation.\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.\n\n**scope** (action=task): Optional domain scope filtering governance to entries relevant for the specified domain.",
9597
+ description: "Workspace orientation and session bootstrapping. Three actions:\n\n- **start**: Universal opener (absorbs `start_pb`) \u2014 say 'Start PB' to begin every session. Stage-aware: fresh workspaces (blank/seeded) get the SKILL-pb-setup body verbatim; active workspaces (grounded/connected) get a standup briefing. 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- **record-activation**: Chat-only activation receipt writer (absorbs `record_activation`) \u2014 closes the install-to-activation arc for chat-only surfaces.\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.\n\n**scope** (action=task): Optional domain scope filtering governance to entries relevant for the specified domain.",
9548
9598
  inputSchema: orientSchema,
9549
9599
  // Mixed read/write noun (§3 R3): 'start'/'record-activation' write session state.
9550
9600
  annotations: { readOnlyHint: false, idempotentHint: true, openWorldHint: false }
@@ -9700,10 +9750,9 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
9700
9750
  if (mode === "brief") {
9701
9751
  const briefStage = readiness?.stage ?? (readiness?.score != null ? readiness.score < 50 ? "seeded" : "grounded" : "unknown");
9702
9752
  lines.push(`Brain stage: ${briefStage}`);
9753
+ lines.push(...buildDirectionLines(orientView));
9703
9754
  if (orientView?.strategicContext) {
9704
9755
  const sc = orientView.strategicContext;
9705
- if (sc.vision) lines.push(`Vision: ${sc.vision}`);
9706
- if (sc.purpose) lines.push(`Purpose: ${sc.purpose}`);
9707
9756
  if (sc.productAreaCount != null && sc.productAreaCount > 0) {
9708
9757
  lines.push(`Product areas (${sc.productAreaCount}): ${(sc.productAreas ?? []).join(", ")}`);
9709
9758
  }
@@ -9713,10 +9762,6 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
9713
9762
  const wpPlural = getCollectionLabel("work_package", "plural", vocabCtx);
9714
9763
  lines.push(`${sc.activeWorkPackageCount} active ${wpPlural}, ${sc.activeTensionCount} tension(s).`);
9715
9764
  }
9716
- const briefStrategyHighlights = (orientView?.strategyHighlights ?? []).filter((e) => e != null && typeof e.name === "string" && e.name.length > 0);
9717
- if (briefStrategyHighlights.length > 0) {
9718
- lines.push(`Strategy: ${briefStrategyHighlights.map((e) => e.name + (typeof e.preview === "string" && e.preview ? ` \u2014 ${e.preview}` : "")).join(" | ")}`);
9719
- }
9720
9765
  if (orientView?.taskContext && orientView.taskContext.context.length > 0) {
9721
9766
  lines.push(`Task context: ${orientView.taskContext.totalFound} relevant entries (${orientView.taskContext.confidence} confidence).`);
9722
9767
  if (orientView.taskContext.isGroundingStub && orientView.taskContext.groundingNote) {
@@ -9909,9 +9954,8 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
9909
9954
  }
9910
9955
  let fullCoherenceSnapshot;
9911
9956
  if (isLowReadiness) {
9912
- const scLR = !task ? orientView?.strategicContext : void 0;
9913
- const scLRLines = scLR ? [scLR.vision && `**Vision:** ${scLR.vision}`, scLR.purpose && `**Purpose:** ${scLR.purpose}`].filter((l) => Boolean(l)) : [];
9914
- if (scLRLines.length > 0) lines.push("## Strategic Context", ...scLRLines, "");
9957
+ const scLRLines = buildDirectionLines(orientView);
9958
+ if (scLRLines.length > 0) lines.push(...scLRLines, "");
9915
9959
  const captureBehaviorNote = (readiness?.governanceMode ?? wsCtx?.governanceMode ?? "open") === "open" ? "_In Open mode, captures are accepted automatically unless you ask me to keep them as drafts._" : "_Everything stays as a draft until you confirm._";
9916
9960
  const gaps = readiness.gaps ?? [];
9917
9961
  if (gaps.length > 0) {
@@ -9956,11 +10000,9 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
9956
10000
  if (task) {
9957
10001
  lines.push(`**Brain stage: ${orientStage}.** Working on: **${task}**`);
9958
10002
  lines.push("");
10003
+ lines.push(...buildDirectionLines(orientView));
9959
10004
  if (orientView?.strategicContext) {
9960
10005
  const sc = orientView.strategicContext;
9961
- lines.push("## Strategic Context");
9962
- if (sc.vision) lines.push(`**Vision:** ${sc.vision}`);
9963
- if (sc.purpose) lines.push(`**Purpose:** ${sc.purpose}`);
9964
10006
  if (sc.productAreaCount != null && sc.productAreaCount > 0) lines.push(`**Product areas (${sc.productAreaCount}):** ${(sc.productAreas ?? []).join(", ")}`);
9965
10007
  if (sc.playingFieldCount != null && sc.playingFieldCount > 0) lines.push(`**Playing field (${sc.playingFieldCount}):** ${(sc.playingField ?? []).join(", ")}`);
9966
10008
  const currentWP = sc.currentWorkPackage;
@@ -10120,14 +10162,6 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
10120
10162
  fullActiveGoals.forEach((e) => lines.push(fmt(e)));
10121
10163
  lines.push("");
10122
10164
  }
10123
- const fullStrategyHighlights = orientView.strategyHighlights ?? [];
10124
- if (fullStrategyHighlights.length > 0) {
10125
- lines.push("## Strategy highlights");
10126
- lines.push("_One-sentence strategy, positioning, moat, business model, GTM \u2014 high-level strategic context._");
10127
- lines.push("");
10128
- fullStrategyHighlights.forEach((e) => lines.push(fmt(e) + (e.preview ? ` \u2014 ${e.preview}` : "")));
10129
- lines.push("");
10130
- }
10131
10165
  const fullPlayingField = orientView.playingField ?? [];
10132
10166
  if (fullPlayingField.length > 0) {
10133
10167
  lines.push("## Playing field");
@@ -10193,9 +10227,8 @@ async function _handleOrient({ mode = "full", tier, task, scope, startupSignals,
10193
10227
  } else {
10194
10228
  lines.push(`**Brain stage: ${orientStage}.**`);
10195
10229
  lines.push("");
10196
- const scNoTask = orientView?.strategicContext;
10197
- const scNoTaskLines = scNoTask ? [scNoTask.vision && `**Vision:** ${scNoTask.vision}`, scNoTask.purpose && `**Purpose:** ${scNoTask.purpose}`].filter((l) => Boolean(l)) : [];
10198
- if (scNoTaskLines.length > 0) lines.push("## Strategic Context", ...scNoTaskLines, "");
10230
+ const scNoTaskLines = buildDirectionLines(orientView);
10231
+ if (scNoTaskLines.length > 0) lines.push(...scNoTaskLines, "");
10199
10232
  lines.push(...buildRitualsSurfaceLines(orientView, { fetchFailed: orientFetchFailed || orientView?.fetchFailed === true }));
10200
10233
  if (orientView?.activeWorkPackages?.length) {
10201
10234
  lines.push("## Active work packages \u2014 current scope");
@@ -15395,18 +15428,6 @@ function registerShapeTools(server) {
15395
15428
 
15396
15429
  // src/tools/question.ts
15397
15430
  import { z as z34 } from "zod/v3";
15398
-
15399
- // src/lib/strip.ts
15400
- var ANSI_AND_CONTROL_RE2 = /\x1b\[[0-9;]*[A-Za-z]|\x1b\][^\x07]*\x07|\x1b[^[\]0-9;A-Za-z]?|[\x00-\x08\x0b-\x1f\x7f]/g;
15401
- function stripControlChars(str) {
15402
- if (!str) return str;
15403
- return str.replace(ANSI_AND_CONTROL_RE2, "");
15404
- }
15405
- function sanitizeSingleLineField(str) {
15406
- return stripControlChars(str).replace(/\s+/g, " ").trim();
15407
- }
15408
-
15409
- // src/tools/question.ts
15410
15431
  var QUESTION_ACTIONS = ["create", "adopt", "assign", "snooze", "decline", "answer", "force-close", "list"];
15411
15432
  var questionSchema = z34.object({
15412
15433
  action: z34.enum(QUESTION_ACTIONS).describe(
@@ -16912,4 +16933,4 @@ export {
16912
16933
  createProductBrainServer,
16913
16934
  initFeatureFlags
16914
16935
  };
16915
- //# sourceMappingURL=chunk-RH26YAVX.js.map
16936
+ //# sourceMappingURL=chunk-DKFYOFUN.js.map