@productbrain/mcp 0.0.1-beta.11437 → 0.0.1-beta.11441

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.
@@ -34,7 +34,7 @@ import {
34
34
  runWithToolContext,
35
35
  setSessionOriented,
36
36
  startAgentSession
37
- } from "./chunk-QUM6WNMF.js";
37
+ } from "./chunk-LELPZ5YE.js";
38
38
 
39
39
  // src/server.ts
40
40
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -190,6 +190,81 @@ function orientationRefusalResult(err, lines) {
190
190
  }
191
191
  var ORIENT_REQUIRED_NOTE = "workflow checkpoints and organisation-structure writes (membership, ownership, parent) still require an oriented session.";
192
192
 
193
+ // src/lib/spineRungs.ts
194
+ var SPINE_RUNG_SEQUENCE = [
195
+ { relationType: "validates", targetKey: "key_result", gapIfMissing: "key_result_missing" },
196
+ { relationType: "part_of", targetKey: "objective", gapIfMissing: "objective_missing" },
197
+ { relationType: "part_of", targetKey: "strategy", gapIfMissing: "strategy_missing" },
198
+ { relationType: "part_of", targetKey: "vision", gapIfMissing: "vision_missing" },
199
+ { relationType: "part_of", targetKey: "purpose", gapIfMissing: "purpose_missing" }
200
+ ];
201
+
202
+ // src/lib/checklist.ts
203
+ var FIRST_SPINE_SUBJECT = "work_package";
204
+ var kindWord = (kind) => kind.replace(/_/g, " ");
205
+ var withArticle = (word) => `${/^[aeiou]/.test(word) ? "an" : "a"} ${word}`;
206
+ var spineSubject = (kind) => {
207
+ const words = withArticle(kindWord(kind));
208
+ return words[0].toUpperCase() + words.slice(1);
209
+ };
210
+ function rungLine(rung) {
211
+ const index = SPINE_RUNG_SEQUENCE.findIndex((spec) => spec.targetKey === rung);
212
+ if (index < 0) return null;
213
+ const { relationType: relationType2, targetKey } = SPINE_RUNG_SEQUENCE[index];
214
+ const parent = `an accepted ${kindWord(targetKey)}`;
215
+ const subject = spineSubject(index === 0 ? FIRST_SPINE_SUBJECT : SPINE_RUNG_SEQUENCE[index - 1].targetKey);
216
+ return relationType2 === "part_of" ? `${subject} hangs on ${parent} with ${relationType2}.` : `${subject} ${relationType2} ${parent}.`;
217
+ }
218
+ var SPINE_RUNG_LINES = SPINE_RUNG_SEQUENCE.map((spec) => rungLine(spec.targetKey));
219
+ var SPINE_LINKS_LINES = [
220
+ `Spine links run child to parent, each ${SPINE_RUNG_SEQUENCE[SPINE_RUNG_SEQUENCE.length - 1].relationType} the level above.`,
221
+ `${spineSubject(FIRST_SPINE_SUBJECT)} ${SPINE_RUNG_SEQUENCE[0].relationType} ${withArticle(kindWord(SPINE_RUNG_SEQUENCE[0].targetKey))}; informs joins no levels.`,
222
+ "Before accepting a spine entry, preflight it: it names what blocks."
223
+ ];
224
+ var CHECKLIST_LINES = {
225
+ purpose: {
226
+ stranger_test: "Explain it so a stranger knows why this company exists",
227
+ specificity: "Say what would be missing from the world without this company",
228
+ not_a_platitude: "Say something a reasonable company would not also claim",
229
+ beneficiary_named: "Name who it is for: people, a community or part of the world, specific enough to say who it is not for",
230
+ durable_not_dated: "Leave out dates and planning cycles; those belong on goals"
231
+ },
232
+ vision: {
233
+ specificity: "Say what will be different, in words only this product could use",
234
+ beneficiary: "Name who it is for: people, a community or part of the world, specific enough to say who it is not for",
235
+ falsifiability: "Choose a direction a reasonable rival would reject",
236
+ stranger_test: "Explain it so a stranger knows what will be different, and for whom"
237
+ },
238
+ strategy: {
239
+ coherent_narrative: "Connect the diagnosis, the policy and the first actions",
240
+ decisiveness: "Say what you will not do",
241
+ time_bounded: "Name a horizon: a date, a duration or a milestone"
242
+ },
243
+ objective: {
244
+ outcome_not_activity: "State what will be true once it is met, not the work to do",
245
+ serves_strategy: "Say what must be true for the strategy to succeed",
246
+ observable: "Make it something a reader could see has happened"
247
+ },
248
+ key_result: {
249
+ measurable: "Name a measure and the target value or state",
250
+ bounded: "Say by when, or how often, the measure is read",
251
+ moves_the_objective: "Pick a result that shows the objective is happening, not that work was done"
252
+ },
253
+ /** One line per spine rung, keyed by the rung it reaches: rungLine, in SPINE_RUNG_SEQUENCE order (TASK-1026). */
254
+ strategy_link: Object.fromEntries(SPINE_RUNG_SEQUENCE.map((spec) => [spec.targetKey, rungLine(spec.targetKey)]))
255
+ };
256
+ var MARK = { met: "[x]", not_yet: "[ ]", judging: "[~]" };
257
+ function renderChecklist(canonicalKey, criteria, judging) {
258
+ const lines = CHECKLIST_LINES[canonicalKey];
259
+ if (!lines) return null;
260
+ return criteria.filter((c) => lines[c.id] !== void 0).map((c) => {
261
+ const state = !c.passed ? "not_yet" : judging ? "judging" : "met";
262
+ const still = state === "judging" ? " (still judging)" : "";
263
+ const missing = state === "not_yet" && c.missing ? ` \u2014 missing: ${c.missing}` : "";
264
+ return `${MARK[state]} ${lines[c.id]}${still}${missing}`;
265
+ });
266
+ }
267
+
193
268
  // src/lib/createEntryPreviewResult.ts
194
269
  async function resolvePreviewPreflight(result2, links) {
195
270
  if (!links?.length) return result2.preflight;
@@ -729,81 +804,6 @@ function buildCaptureForRealNextAction(payload) {
729
804
  }];
730
805
  }
731
806
 
732
- // src/lib/spineRungs.ts
733
- var SPINE_RUNG_SEQUENCE = [
734
- { relationType: "validates", targetKey: "key_result", gapIfMissing: "key_result_missing" },
735
- { relationType: "part_of", targetKey: "objective", gapIfMissing: "objective_missing" },
736
- { relationType: "part_of", targetKey: "strategy", gapIfMissing: "strategy_missing" },
737
- { relationType: "part_of", targetKey: "vision", gapIfMissing: "vision_missing" },
738
- { relationType: "part_of", targetKey: "purpose", gapIfMissing: "purpose_missing" }
739
- ];
740
-
741
- // src/lib/checklist.ts
742
- var FIRST_SPINE_SUBJECT = "work_package";
743
- var kindWord = (kind) => kind.replace(/_/g, " ");
744
- var withArticle = (word) => `${/^[aeiou]/.test(word) ? "an" : "a"} ${word}`;
745
- var spineSubject = (kind) => {
746
- const words = withArticle(kindWord(kind));
747
- return words[0].toUpperCase() + words.slice(1);
748
- };
749
- function rungLine(rung) {
750
- const index = SPINE_RUNG_SEQUENCE.findIndex((spec) => spec.targetKey === rung);
751
- if (index < 0) return null;
752
- const { relationType: relationType2, targetKey } = SPINE_RUNG_SEQUENCE[index];
753
- const parent = `an accepted ${kindWord(targetKey)}`;
754
- const subject = spineSubject(index === 0 ? FIRST_SPINE_SUBJECT : SPINE_RUNG_SEQUENCE[index - 1].targetKey);
755
- return relationType2 === "part_of" ? `${subject} hangs on ${parent} with ${relationType2}.` : `${subject} ${relationType2} ${parent}.`;
756
- }
757
- var SPINE_RUNG_LINES = SPINE_RUNG_SEQUENCE.map((spec) => rungLine(spec.targetKey));
758
- var SPINE_LINKS_LINES = [
759
- `Spine links run child to parent, each ${SPINE_RUNG_SEQUENCE[SPINE_RUNG_SEQUENCE.length - 1].relationType} the level above.`,
760
- `${spineSubject(FIRST_SPINE_SUBJECT)} ${SPINE_RUNG_SEQUENCE[0].relationType} ${withArticle(kindWord(SPINE_RUNG_SEQUENCE[0].targetKey))}; informs joins no levels.`,
761
- "Before accepting a spine entry, preflight it: it names what blocks."
762
- ];
763
- var CHECKLIST_LINES = {
764
- purpose: {
765
- stranger_test: "Explain it so a stranger knows why this company exists",
766
- specificity: "Say what would be missing from the world without this company",
767
- not_a_platitude: "Say something a reasonable company would not also claim",
768
- beneficiary_named: "Name who it is for: people, a community or part of the world, specific enough to say who it is not for",
769
- durable_not_dated: "Leave out dates and planning cycles; those belong on goals"
770
- },
771
- vision: {
772
- specificity: "Say what will be different, in words only this product could use",
773
- beneficiary: "Name who it is for: people, a community or part of the world, specific enough to say who it is not for",
774
- falsifiability: "Choose a direction a reasonable rival would reject",
775
- stranger_test: "Explain it so a stranger knows what will be different, and for whom"
776
- },
777
- strategy: {
778
- coherent_narrative: "Connect the diagnosis, the policy and the first actions",
779
- decisiveness: "Say what you will not do",
780
- time_bounded: "Name a horizon: a date, a duration or a milestone"
781
- },
782
- objective: {
783
- outcome_not_activity: "State what will be true once it is met, not the work to do",
784
- serves_strategy: "Say what must be true for the strategy to succeed",
785
- observable: "Make it something a reader could see has happened"
786
- },
787
- key_result: {
788
- measurable: "Name a measure and the target value or state",
789
- bounded: "Say by when, or how often, the measure is read",
790
- moves_the_objective: "Pick a result that shows the objective is happening, not that work was done"
791
- },
792
- /** One line per spine rung, keyed by the rung it reaches: rungLine, in SPINE_RUNG_SEQUENCE order (TASK-1026). */
793
- strategy_link: Object.fromEntries(SPINE_RUNG_SEQUENCE.map((spec) => [spec.targetKey, rungLine(spec.targetKey)]))
794
- };
795
- var MARK = { met: "[x]", not_yet: "[ ]", judging: "[~]" };
796
- function renderChecklist(canonicalKey, criteria, judging) {
797
- const lines = CHECKLIST_LINES[canonicalKey];
798
- if (!lines) return null;
799
- return criteria.filter((c) => lines[c.id] !== void 0).map((c) => {
800
- const state = !c.passed ? "not_yet" : judging ? "judging" : "met";
801
- const still = state === "judging" ? " (still judging)" : "";
802
- const missing = state === "not_yet" && c.missing ? ` \u2014 missing: ${c.missing}` : "";
803
- return `${MARK[state]} ${lines[c.id]}${still}${missing}`;
804
- });
805
- }
806
-
807
807
  // src/lib/rubricFormatting.ts
808
808
  function verdictQualityPhrase(result2) {
809
809
  const v = result2?.verdict;
@@ -10324,6 +10324,7 @@ function formatNoticeLines(notices) {
10324
10324
  }
10325
10325
 
10326
10326
  // src/tools/session.ts
10327
+ var START_PREFLIGHT_NEXT = 'Next: context action=preflight collection=<kind> links=[{"type":"part_of","entryId":"<PARENT-ID>"}]';
10327
10328
  var SESSION_ACTIONS = [
10328
10329
  "start",
10329
10330
  "close",
@@ -10458,6 +10459,7 @@ async function handleStart2(data) {
10458
10459
  surface: "mcp",
10459
10460
  sessionStart: true
10460
10461
  }));
10462
+ lines.push("", ...SPINE_LINKS_LINES, ...result2.briefing?.firstReply ? [] : [START_PREFLIGHT_NEXT]);
10461
10463
  const summary = `Session ${result2.sessionId} active. Workspace ${result2.workspaceName}. Pass sessionId="${result2.sessionId}" on every write. Orient with a task first; workflow checkpoints and organisation-structure writes still require it.`;
10462
10464
  return {
10463
10465
  content: [{ type: "text", text: lines.join("\n") }],
@@ -12136,6 +12138,8 @@ var INSTRUCTIONS = [
12136
12138
  "Pass the `sessionId` that `session action=start` returned on every write: the connection does not remember it.",
12137
12139
  "Use `capture` to create an entry and read its reply: it lands as a draft, except a question, which is born open and needs no `entries action=commit`.",
12138
12140
  "Link entries with `relations action=create` \u2014 a relation is written only when you ask, with exactly the verb you send.",
12141
+ ...SPINE_LINKS_LINES,
12142
+ // TASK-1022 (WP-862): the spine grammar session start prints, a backup for the clients that load instructions
12139
12143
  "Finish with `session action=wrapup-review`, then `session action=close`.",
12140
12144
  "If the work falls outside the active work packages, name the gap and ask the user before designing it."
12141
12145
  ].join("\n");
@@ -12208,4 +12212,4 @@ export {
12208
12212
  SERVER_VERSION,
12209
12213
  createProductBrainServer
12210
12214
  };
12211
- //# sourceMappingURL=chunk-W3Y4VS6E.js.map
12215
+ //# sourceMappingURL=chunk-CY37RSBU.js.map