@productbrain/mcp 0.0.1-beta.9927 → 0.0.1-beta.9944

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.
@@ -47,7 +47,7 @@ import {
47
47
 
48
48
  // src/server.ts
49
49
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
50
- import { z as z35 } from "zod/v3";
50
+ import { z as z34 } from "zod/v3";
51
51
 
52
52
  // src/lib/mcpGatewayClientMessages.ts
53
53
  function agentSessionNotActiveMessage(status2) {
@@ -6842,20 +6842,6 @@ function formatWhatNeedsAttentionBrief(wna) {
6842
6842
  const lines = ["**What needs attention:**", ...bullets.map((b) => `- ${b}`), ""];
6843
6843
  return lines;
6844
6844
  }
6845
- function formatShapeAdvisorySummaryLine(sas) {
6846
- const sourceEntries = sas ? Object.entries(sas.candidateRateBySource ?? {}) : [];
6847
- if (!sas || sas.compoundTotal === 0 && sourceEntries.length === 0) return void 0;
6848
- const counts = sas?.candidateCountBySource ?? {};
6849
- const candidatePart = sourceEntries.length > 0 ? ` candidateRateBySource: ${sourceEntries.map(([src, rate]) => `${src} ${rate !== null ? `${Math.round(rate * 100)}%` : "n/a"}${counts[src] !== void 0 ? ` (n=${counts[src]})` : ""}`).join(", ")}.` : "";
6850
- const truncatedNote = sas.scanTruncated ? " [truncated \u2014 more rows exist in this window than were scanned]" : "";
6851
- if (sas.compoundTotal === 0) {
6852
- return `Shape advisories (${sas.windowDays}d): 0 compound.${truncatedNote}${candidatePart}`;
6853
- }
6854
- const agentPart = `${sas.precisionAgent !== null ? `${Math.round(sas.precisionAgent * 100)}%` : "n/a"} (n=${sas.precisionAgentN})`;
6855
- const humanPart = sas.precisionHumanN > 0 ? `${Math.round((sas.precisionHuman ?? 0) * 100)}% (n=${sas.precisionHumanN})` : sas.precisionHumanNote ?? "no human verdicts yet";
6856
- const pendingRatePart = sas.pendingRate !== null ? ` (${Math.round(sas.pendingRate * 100)}% pending)` : "";
6857
- return `Shape advisories (${sas.windowDays}d): ${sas.pendingCount} pending / ${sas.compoundTotal} compound${pendingRatePart} \u2014 precisionAgent ${agentPart}, precisionHuman ${humanPart}.${truncatedNote}${candidatePart}`;
6858
- }
6859
6845
 
6860
6846
  // src/lib/ruleListRender.ts
6861
6847
  var NO_ACTING_ROLE_LINE = "(Team and role lists not served: this read has no acting role, because no active session with a role was found. Start a session, then orient again.)";
@@ -7387,8 +7373,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
7387
7373
  lines.push(`Trust: ${tm.verified} verified, ${tm.unverified} unverified, ${tm.noStatus} no-status (${tm.total}${capNote} scanned).`);
7388
7374
  }
7389
7375
  }
7390
- const briefShapeLine = formatShapeAdvisorySummaryLine(orientView?.shapeAdvisorySummary);
7391
- if (briefShapeLine) lines.push(briefShapeLine);
7392
7376
  const briefWna = formatWhatNeedsAttentionBrief(orientView?.whatNeedsAttention);
7393
7377
  if (briefWna.length > 0) {
7394
7378
  lines.push("");
@@ -7490,8 +7474,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
7490
7474
  orientationStatus: orientationStatus2,
7491
7475
  nextStep: taskAsked ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
7492
7476
  ...orientView?._budget ? { _budget: orientView._budget } : {},
7493
- ...orientView?.shapeAdvisorySummary ? { shapeAdvisorySummary: orientView.shapeAdvisorySummary } : {},
7494
- // WP-560/TEN-2532 (Codex P2): text-parity, not text-only
7495
7477
  // WP-622 follow-up (Copilot review PR #601, post-merge): brief structuredContent parity with full mode.
7496
7478
  ...orientView?.strategyHighlights?.length ? { strategyHighlights: orientView.strategyHighlights } : {},
7497
7479
  ...orientView?.strategicSpine ? { strategicSpine: orientView.strategicSpine } : {},
@@ -7632,8 +7614,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
7632
7614
  lines.push("");
7633
7615
  }
7634
7616
  }
7635
- const taskShapeLine = formatShapeAdvisorySummaryLine(orientView.shapeAdvisorySummary);
7636
- if (taskShapeLine) lines.push(taskShapeLine, "");
7637
7617
  }
7638
7618
  if (fullCoherence) {
7639
7619
  lines.push(...fullCoherence.lines);
@@ -7737,8 +7717,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
7737
7717
  lines.push("");
7738
7718
  }
7739
7719
  }
7740
- const noTaskShapeLine = formatShapeAdvisorySummaryLine(orientView?.shapeAdvisorySummary);
7741
- if (noTaskShapeLine) lines.push(noTaskShapeLine, "");
7742
7720
  if (fullCoherence) {
7743
7721
  lines.push(...fullCoherence.lines);
7744
7722
  }
@@ -7850,8 +7828,6 @@ async function _handleOrient({ mode = "full", tier, task, startupSignals, invoca
7850
7828
  orientationStatus,
7851
7829
  nextStep: taskAsked ? void 0 : 'Run `orient task="describe the work"` before substantive work.',
7852
7830
  ...orientView?._budget ? { _budget: orientView._budget } : {},
7853
- // WP-560/TEN-2532 (Codex P2): shape-advisory line must reach structuredContent, not just text.
7854
- ...orientView?.shapeAdvisorySummary ? { shapeAdvisorySummary: orientView.shapeAdvisorySummary } : {},
7855
7831
  // WP-622 (Copilot review PR #601 P2): was dropped from the full-mode machine payload.
7856
7832
  ...orientView?.strategyHighlights?.length ? { strategyHighlights: orientView.strategyHighlights } : {},
7857
7833
  ...orientView?.strategicSpine ? { strategicSpine: orientView.strategicSpine } : {},
@@ -11694,200 +11670,27 @@ function registerFeedbackTool(server) {
11694
11670
  }));
11695
11671
  }
11696
11672
 
11697
- // src/tools/shape.ts
11698
- import { z as z30 } from "zod/v3";
11699
- var SHAPE_ACTIONS = ["list", "show", "agree", "dismiss"];
11700
- var LIST_DISPOSITIONS = ["pending", "agreed", "dismissed", "expired"];
11701
- var LIST_OUTCOMES = ["not_candidate", "atomic", "compound", "unavailable"];
11702
- var shapeSchema = z30.object({
11703
- action: z30.enum(SHAPE_ACTIONS).describe(
11704
- "'list': list shape advisories for this workspace, latest per subject. 'show': show one shape advisory by id. 'agree': agree with a compound advisory's split verdict. 'dismiss': dismiss a compound advisory's split verdict."
11705
- ),
11706
- disposition: z30.enum(LIST_DISPOSITIONS).optional().describe(
11707
- "For 'list': filter by disposition. Omitting both disposition and outcome defaults to the actionable set (disposition:pending, outcome:compound)."
11708
- ),
11709
- outcome: z30.enum(LIST_OUTCOMES).optional().describe(
11710
- "For 'list': filter by outcome. Omitting both disposition and outcome defaults to the actionable set (disposition:pending, outcome:compound)."
11711
- ),
11712
- limit: z30.number().min(1).max(200).optional().describe("For 'list': max rows (default 50, max 200)."),
11713
- rowId: z30.string().max(200).optional().describe("For 'show'/'agree'/'dismiss': the advisory row id."),
11714
- reason: z30.string().max(1e3).optional().describe("For 'agree'/'dismiss': optional reason (capped at 1000 chars).")
11715
- });
11716
- var shapeListVariant = z30.object({
11717
- action: z30.literal("list"),
11718
- disposition: z30.enum(LIST_DISPOSITIONS).optional(),
11719
- outcome: z30.enum(LIST_OUTCOMES).optional(),
11720
- limit: z30.number().min(1).max(200).optional()
11721
- });
11722
- var shapeShowVariant = z30.object({ action: z30.literal("show"), rowId: z30.string().max(200) });
11723
- var shapeAgreeVariant = z30.object({ action: z30.literal("agree"), rowId: z30.string().max(200), reason: z30.string().max(1e3).optional() });
11724
- var shapeDismissVariant = z30.object({ action: z30.literal("dismiss"), rowId: z30.string().max(200), reason: z30.string().max(1e3).optional() });
11725
- var shapeActionUnion = z30.discriminatedUnion("action", [
11726
- shapeListVariant,
11727
- shapeShowVariant,
11728
- shapeAgreeVariant,
11729
- shapeDismissVariant
11730
- ]);
11731
- var SHAPE_ACTION_SPECS = {
11732
- list: { params: ["disposition", "outcome", "limit"], description: "All params optional; no filters defaults to disposition:pending + outcome:compound." },
11733
- show: { params: ["rowId"], description: "rowId is required." },
11734
- agree: { params: ["rowId", "reason"], description: "rowId is required; reason is optional." },
11735
- dismiss: { params: ["rowId", "reason"], description: "rowId is required; reason is optional." }
11736
- };
11737
- async function handleShapeList(disposition, outcome, limit) {
11738
- const noFiltersGiven = disposition === void 0 && outcome === void 0;
11739
- const effectiveDisposition = disposition ?? (noFiltersGiven ? "pending" : void 0);
11740
- const effectiveOutcome = outcome ?? (noFiltersGiven ? "compound" : void 0);
11741
- const workspaceId = await getWorkspaceId();
11742
- const envelope = await kernelCallEnvelope("chain.shapeAdvisories", {
11743
- ...effectiveDisposition ? { disposition: effectiveDisposition } : {},
11744
- ...effectiveOutcome ? { outcome: effectiveOutcome } : {},
11745
- ...limit ? { limit } : {},
11746
- workspaceId
11747
- });
11748
- const items = envelope.data;
11749
- const truncated = Boolean(envelope._meta?.truncated);
11750
- const truncationNote = "Note: this list may be incomplete \u2014 the scan stopped at its safety bound before finding every match. Narrow disposition/outcome or raise limit and re-run.";
11751
- if (items.length === 0) {
11752
- return successResult(
11753
- truncated ? `No shape advisories match.
11754
-
11755
- ${truncationNote}` : "No shape advisories match.",
11756
- truncated ? "No shape advisories found (result may be incomplete \u2014 safety bound reached)." : "No shape advisories found.",
11757
- { items: [], count: 0, truncated }
11758
- );
11759
- }
11760
- const lines = ["# Shape Advisories", ""];
11761
- for (const item of items) {
11762
- const verdict = item.outcome === "unavailable" && item.unavailableReason ? `unavailable(${item.unavailableReason})` : item.outcome;
11763
- lines.push(`- \`${item.id}\` \u2014 ${item.subjectEntryId} \xB7 ${verdict} \xB7 disposition:${item.disposition} \xB7 ${item.source}`);
11764
- }
11765
- if (truncated) lines.push("", truncationNote);
11766
- return successResult(
11767
- lines.join("\n"),
11768
- `Found ${items.length} shape advisor${items.length === 1 ? "y" : "ies"}.${truncated ? " (list may be incomplete \u2014 safety bound reached)" : ""}`,
11769
- { items, count: items.length, truncated },
11770
- [{ tool: "shape", description: "Show one advisory in full", parameters: { action: "show", rowId: items[0].id } }]
11771
- );
11772
- }
11773
- function renderShapeAdvisoryText(item) {
11774
- const lines = [
11775
- `# ${item.id}`,
11776
- `- Subject: ${item.subjectEntryId} (${item.collectionSlug})`,
11777
- `- Outcome: ${item.outcome}`,
11778
- `- Disposition: ${item.disposition}`,
11779
- `- Source: ${item.source}`
11780
- ];
11781
- if (item.proposedAtoms?.length) {
11782
- lines.push("", `Proposed split (${item.proposedAtoms.length} atom(s)):`);
11783
- item.proposedAtoms.forEach((atom, idx) => {
11784
- lines.push(` [${idx}] ${atom.title} \u2014 ${atom.concern}`);
11785
- lines.push(` "${atom.bodyExcerpt}"`);
11786
- if (atom.suggestedCollection) lines.push(` suggested collection: ${atom.suggestedCollection}`);
11787
- });
11788
- }
11789
- if (item.proposedLinks?.length) {
11790
- lines.push("", "Proposed links:");
11791
- for (const link of item.proposedLinks) {
11792
- const from = link.fromIdx === -1 ? "original" : `[${link.fromIdx}]`;
11793
- lines.push(` ${from} --${link.relation}--> [${link.toIdx}]`);
11794
- }
11795
- }
11796
- if (item.dispositionReason) lines.push("", `- Disposition reason: ${item.dispositionReason}`);
11797
- return lines.join("\n");
11798
- }
11799
- async function handleShapeShow(rowId) {
11800
- const item = await kernelQuery("chain.showShapeAdvisory", { rowId });
11801
- if (!item) {
11802
- return failureResult(
11803
- `Advisory '${rowId}' not found (missing, or belongs to a different workspace).`,
11804
- "NOT_FOUND",
11805
- `Advisory '${rowId}' not found.`,
11806
- "Use action=list to find valid ids.",
11807
- [{ tool: "shape", description: "List advisories", parameters: { action: "list" } }]
11808
- );
11809
- }
11810
- return successResult(
11811
- renderShapeAdvisoryText(item),
11812
- `Advisory ${item.id}: ${item.outcome}, disposition:${item.disposition}.`,
11813
- item
11814
- );
11815
- }
11816
- async function handleShapeDisposition(disposition, rowId, reason) {
11817
- requireWriteAccess();
11818
- try {
11819
- const result2 = await kernelMutation("chain.dispositionShapeAdvisory", {
11820
- rowId,
11821
- disposition,
11822
- ...reason ? { dispositionReason: reason } : {}
11823
- });
11824
- return successResult(
11825
- `Advisory ${result2.rowId} dispositioned: ${result2.disposition}.`,
11826
- `Advisory dispositioned: ${result2.disposition}.`,
11827
- result2
11828
- );
11829
- } catch (err) {
11830
- const classified = classifyError(err);
11831
- const isNotFound = classified.code === "NOT_FOUND";
11832
- return failureResult(
11833
- classified.message,
11834
- classified.code,
11835
- classified.message,
11836
- isNotFound ? "Use action=list to find valid ids." : classified.recovery ?? "Use action=show to check the advisory's current outcome/disposition.",
11837
- isNotFound ? [{ tool: "shape", description: "List advisories", parameters: { action: "list" } }] : classified.availableActions ?? [{ tool: "shape", description: "Show the advisory", parameters: { action: "show", rowId } }],
11838
- classified.diagnostics
11839
- );
11840
- }
11841
- }
11842
- function registerShapeTools(server) {
11843
- const shapeHandlers = {
11844
- list: (data) => handleShapeList(data.disposition, data.outcome, data.limit),
11845
- show: (data) => handleShapeShow(data.rowId),
11846
- agree: (data) => handleShapeDisposition("agreed", data.rowId, data.reason),
11847
- dismiss: (data) => handleShapeDisposition("dismissed", data.rowId, data.reason)
11848
- };
11849
- server.registerTool(
11850
- "shape",
11851
- {
11852
- title: "Shape",
11853
- description: "Review and disposition shape-advisory (single-concern split) suggestions for this workspace. Four actions:\n\n- **list**: List shape advisories, latest per subject (filter by disposition/outcome).\n- **show**: Show one shape advisory in full by id.\n- **agree**: Agree with a compound advisory's split verdict.\n- **dismiss**: Dismiss a compound advisory's split verdict.",
11854
- inputSchema: shapeSchema,
11855
- // Mixed read/write noun (§3 R3): agree/dismiss write; list/show read.
11856
- annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false }
11857
- },
11858
- thinWrapper(async (args) => {
11859
- const parsed = parseOrFail(shapeSchema, args);
11860
- if (!parsed.ok) return parsed.result;
11861
- const { action } = parsed.data;
11862
- return runWithToolContext(
11863
- { tool: "shape", action },
11864
- () => dispatchDiscriminated("shape", shapeActionUnion, parsed.data, SHAPE_ACTION_SPECS, shapeHandlers)
11865
- );
11866
- })
11867
- );
11868
- }
11869
-
11870
11673
  // src/tools/question.ts
11871
- import { z as z31 } from "zod/v3";
11674
+ import { z as z30 } from "zod/v3";
11872
11675
  var QUESTION_ACTIONS = ["create", "assign", "answer", "force-close", "list"];
11873
- var questionSchema = z31.object({
11874
- action: z31.enum(QUESTION_ACTIONS).describe(
11676
+ var questionSchema = z30.object({
11677
+ action: z30.enum(QUESTION_ACTIONS).describe(
11875
11678
  "'create': create a new routed question from text \u2014 the dedicated birth action; every question is born escalated to the team lead (generic entry creation and move-and-retype also pair a routing facet). 'assign': reassign ownership to a role (toRole required \u2014 no bare self-confirm, no toPerson). 'answer': close the loop \u2014 writes the answer on the question and moves it to answered; --entry links an existing decision instead. 'force-close': Team-Lead-only escape hatch \u2014 reason required. 'list': the ack-gate read model \u2014 what you owe (or, with mine:true, every question you asked, including closed ones)."
11876
11679
  ),
11877
- entryId: z31.string().max(200).optional().describe("Target question's id (human TEN-nnn form or a raw entry id). Required for every action except 'create'/'list'."),
11878
- text: z31.string().max(5e3).optional().describe("'create': the question text. 'answer': the answer text (mutually exclusive with answerEntryId, max 2000 chars)."),
11879
- blocks: z31.array(z31.string().max(200)).max(50).optional().describe("'create': entry ids this question is blocking (repeatable)."),
11880
- toRole: z31.string().max(200).optional().describe("'assign': reassign to this role (human ROL-nnn form or a raw entry id) \u2014 required."),
11881
- reason: z31.string().max(2e3).optional().describe("'force-close': required reason."),
11882
- answerEntryId: z31.string().max(200).optional().describe("'answer': point at an already-written entry instead of supplying text (mutually exclusive with text)."),
11883
- mine: z31.boolean().optional().describe("'list': true for arm C (every question YOU asked, every status). Omit/false for the ack-gate view (what you owe).")
11680
+ entryId: z30.string().max(200).optional().describe("Target question's id (human TEN-nnn form or a raw entry id). Required for every action except 'create'/'list'."),
11681
+ text: z30.string().max(5e3).optional().describe("'create': the question text. 'answer': the answer text (mutually exclusive with answerEntryId, max 2000 chars)."),
11682
+ blocks: z30.array(z30.string().max(200)).max(50).optional().describe("'create': entry ids this question is blocking (repeatable)."),
11683
+ toRole: z30.string().max(200).optional().describe("'assign': reassign to this role (human ROL-nnn form or a raw entry id) \u2014 required."),
11684
+ reason: z30.string().max(2e3).optional().describe("'force-close': required reason."),
11685
+ answerEntryId: z30.string().max(200).optional().describe("'answer': point at an already-written entry instead of supplying text (mutually exclusive with text)."),
11686
+ mine: z30.boolean().optional().describe("'list': true for arm C (every question YOU asked, every status). Omit/false for the ack-gate view (what you owe).")
11884
11687
  });
11885
- var createVariant = z31.object({ action: z31.literal("create"), text: z31.string().min(1).max(5e3), blocks: z31.array(z31.string().max(200)).max(50).optional() });
11886
- var assignVariant = z31.object({ action: z31.literal("assign"), entryId: z31.string().max(200), toRole: z31.string().max(200).min(1) });
11887
- var answerVariant = z31.object({ action: z31.literal("answer"), entryId: z31.string().max(200), text: z31.string().max(2e3).optional(), answerEntryId: z31.string().max(200).optional() });
11888
- var forceCloseVariant = z31.object({ action: z31.literal("force-close"), entryId: z31.string().max(200), reason: z31.string().min(1).max(2e3) });
11889
- var listVariant = z31.object({ action: z31.literal("list"), mine: z31.boolean().optional() });
11890
- var questionActionUnion = z31.discriminatedUnion("action", [
11688
+ var createVariant = z30.object({ action: z30.literal("create"), text: z30.string().min(1).max(5e3), blocks: z30.array(z30.string().max(200)).max(50).optional() });
11689
+ var assignVariant = z30.object({ action: z30.literal("assign"), entryId: z30.string().max(200), toRole: z30.string().max(200).min(1) });
11690
+ var answerVariant = z30.object({ action: z30.literal("answer"), entryId: z30.string().max(200), text: z30.string().max(2e3).optional(), answerEntryId: z30.string().max(200).optional() });
11691
+ var forceCloseVariant = z30.object({ action: z30.literal("force-close"), entryId: z30.string().max(200), reason: z30.string().min(1).max(2e3) });
11692
+ var listVariant = z30.object({ action: z30.literal("list"), mine: z30.boolean().optional() });
11693
+ var questionActionUnion = z30.discriminatedUnion("action", [
11891
11694
  createVariant,
11892
11695
  assignVariant,
11893
11696
  answerVariant,
@@ -12041,47 +11844,47 @@ function registerQuestionTools(server) {
12041
11844
  }
12042
11845
 
12043
11846
  // src/tools/role.ts
12044
- import { z as z32 } from "zod/v3";
11847
+ import { z as z31 } from "zod/v3";
12045
11848
  var ROLE_ACTIONS = ["accountable", "seat", "unseat"];
12046
- var roleSchema = z32.object({
12047
- action: z32.enum(ROLE_ACTIONS).describe(
11849
+ var roleSchema = z31.object({
11850
+ action: z31.enum(ROLE_ACTIONS).describe(
12048
11851
  "'accountable': what this role owns (explicit), reports on (reporting), and \u2014 not yet computed \u2014 inherits via Team-Lead vacancy coverage. 'seat': put a person in this role. 'unseat': take this role from a person."
12049
11852
  ),
12050
- roleId: z32.string().max(200).optional().describe("The role, by the human chain id `chain.getEntry` or `pb get` would print for it, or a raw entry id."),
12051
- canonicalKey: z32.string().max(200).optional().describe("'accountable': narrow to one kind (e.g. objective, key_result, tension)."),
12052
- limit: z32.number().int().positive().max(200).optional().describe("'accountable': max explicit-list rows per page (default and maximum 200)."),
12053
- cursor: z32.number().optional().describe("'accountable': continue the explicit list from an earlier truncated page's nextCursor."),
12054
- person: z32.string().max(200).optional().describe(
11853
+ roleId: z31.string().max(200).optional().describe("The role, by the human chain id `chain.getEntry` or `pb get` would print for it, or a raw entry id."),
11854
+ canonicalKey: z31.string().max(200).optional().describe("'accountable': narrow to one kind (e.g. objective, key_result, tension)."),
11855
+ limit: z31.number().int().positive().max(200).optional().describe("'accountable': max explicit-list rows per page (default and maximum 200)."),
11856
+ cursor: z31.number().optional().describe("'accountable': continue the explicit list from an earlier truncated page's nextCursor."),
11857
+ person: z31.string().max(200).optional().describe(
12055
11858
  "'seat' / 'unseat': an existing person, by person id or exact email. For 'seat', give this or newPersonName, not both."
12056
11859
  ),
12057
- newPersonName: z32.string().max(120).optional().describe(
11860
+ newPersonName: z31.string().max(120).optional().describe(
12058
11861
  "'seat': the name of a person who has no login yet; a placeholder person is created once and reused for the same exact name. Refused when the name belongs to someone with an account."
12059
11862
  ),
12060
- teamId: z32.string().max(200).optional().describe(
11863
+ teamId: z31.string().max(200).optional().describe(
12061
11864
  "'seat' / 'unseat': the team, by chain id or entry id. Only needed for Team Lead, which lives in every team; any other role is seated in its home team."
12062
11865
  )
12063
11866
  });
12064
- var accountableVariant = z32.object({
12065
- action: z32.literal("accountable"),
12066
- roleId: z32.string().max(200),
12067
- canonicalKey: z32.string().max(200).optional(),
12068
- limit: z32.number().int().positive().max(200).optional(),
12069
- cursor: z32.number().optional()
11867
+ var accountableVariant = z31.object({
11868
+ action: z31.literal("accountable"),
11869
+ roleId: z31.string().max(200),
11870
+ canonicalKey: z31.string().max(200).optional(),
11871
+ limit: z31.number().int().positive().max(200).optional(),
11872
+ cursor: z31.number().optional()
12070
11873
  });
12071
- var seatVariant = z32.object({
12072
- action: z32.literal("seat"),
12073
- roleId: z32.string().max(200),
12074
- person: z32.string().max(200).optional(),
12075
- newPersonName: z32.string().max(120).optional(),
12076
- teamId: z32.string().max(200).optional()
11874
+ var seatVariant = z31.object({
11875
+ action: z31.literal("seat"),
11876
+ roleId: z31.string().max(200),
11877
+ person: z31.string().max(200).optional(),
11878
+ newPersonName: z31.string().max(120).optional(),
11879
+ teamId: z31.string().max(200).optional()
12077
11880
  });
12078
- var unseatVariant = z32.object({
12079
- action: z32.literal("unseat"),
12080
- roleId: z32.string().max(200),
12081
- person: z32.string().max(200),
12082
- teamId: z32.string().max(200).optional()
11881
+ var unseatVariant = z31.object({
11882
+ action: z31.literal("unseat"),
11883
+ roleId: z31.string().max(200),
11884
+ person: z31.string().max(200),
11885
+ teamId: z31.string().max(200).optional()
12083
11886
  });
12084
- var roleActionUnion = z32.discriminatedUnion("action", [accountableVariant, seatVariant, unseatVariant]);
11887
+ var roleActionUnion = z31.discriminatedUnion("action", [accountableVariant, seatVariant, unseatVariant]);
12085
11888
  var ROLE_ACTION_SPECS = {
12086
11889
  accountable: { params: ["roleId", "canonicalKey", "limit", "cursor"], description: "roleId is required; canonicalKey/limit/cursor are optional." },
12087
11890
  seat: { params: ["roleId", "person", "newPersonName", "teamId"], description: "roleId is required, plus exactly one of person or newPersonName; teamId only for Team Lead." },
@@ -12209,49 +12012,49 @@ function registerRoleTools(server) {
12209
12012
  }
12210
12013
 
12211
12014
  // src/tools/outcome.ts
12212
- import { z as z33 } from "zod/v3";
12015
+ import { z as z32 } from "zod/v3";
12213
12016
  var OUTCOME_ACTIONS = ["record", "list", "show"];
12214
12017
  var READING_KINDS = ["measurement", "estimate", "correction"];
12215
- var outcomeSchema = z33.object({
12216
- action: z33.enum(OUTCOME_ACTIONS).describe(
12018
+ var outcomeSchema = z32.object({
12019
+ action: z32.enum(OUTCOME_ACTIONS).describe(
12217
12020
  "'record': record a reading (evidence, not a verdict). 'list': list readings, newest first. 'show': the derived view \u2014 current, progress, pace, staleness, recorded completion."
12218
12021
  ),
12219
- entryId: z33.string().max(200).optional().describe("The key result (or other outcome-bearing) entry, by its chain id. Required for all three actions."),
12022
+ entryId: z32.string().max(200).optional().describe("The key result (or other outcome-bearing) entry, by its chain id. Required for all three actions."),
12220
12023
  // PR #858 review round 3 (Codex P2, PRRT_kwDORS4ils6gXHj9): a JSON number that overflows to
12221
12024
  // `Infinity` (e.g. `1e400`) parses fine in JS and passes a plain `z.number()`, but
12222
12025
  // `callGateway()` serializes it with `JSON.stringify`, which turns `Infinity` into `null` —
12223
12026
  // the backend's `v.number()` validator then rejects a call this tool's own schema accepted.
12224
12027
  // `.finite()` rejects it here, matching the explicit finite-value checks the CLI/other outcome
12225
12028
  // entry surfaces already use.
12226
- value: z33.number().finite().optional().describe("'record': the measured value. Required for 'record'."),
12227
- valueText: z33.string().max(500).optional().describe("'record': verbatim as-reported form when the source was not clean, e.g. '~62%'. Display only."),
12228
- asOf: z33.string().max(64).optional().describe("'record': when the world was in this state, as a parseable date (default: now). Back-dating a backfill is legitimate \u2014 it shows up as asOf earlier than recordedAt."),
12229
- kind: z33.enum(READING_KINDS).optional().describe("'record': measurement | estimate | correction (default: measurement)."),
12230
- correctsReadingId: z33.string().max(200).optional().describe("'record': required with kind='correction' \u2014 the reading id this replaces. Refused if that row is already superseded."),
12231
- recordedByRoleId: z33.string().max(200).optional().describe("'record': the accountable role (default: the entry's reporterRoleId, then its owning role)."),
12232
- note: z33.string().max(2e3).optional().describe("'record': free-text note recorded with the reading."),
12233
- source: z33.string().max(500).optional().describe("'record': where the number came from \u2014 a dashboard name, a query, a URL."),
12234
- limit: z33.number().int().positive().max(200).optional().describe("'list': max rows to return (default and maximum 200).")
12029
+ value: z32.number().finite().optional().describe("'record': the measured value. Required for 'record'."),
12030
+ valueText: z32.string().max(500).optional().describe("'record': verbatim as-reported form when the source was not clean, e.g. '~62%'. Display only."),
12031
+ asOf: z32.string().max(64).optional().describe("'record': when the world was in this state, as a parseable date (default: now). Back-dating a backfill is legitimate \u2014 it shows up as asOf earlier than recordedAt."),
12032
+ kind: z32.enum(READING_KINDS).optional().describe("'record': measurement | estimate | correction (default: measurement)."),
12033
+ correctsReadingId: z32.string().max(200).optional().describe("'record': required with kind='correction' \u2014 the reading id this replaces. Refused if that row is already superseded."),
12034
+ recordedByRoleId: z32.string().max(200).optional().describe("'record': the accountable role (default: the entry's reporterRoleId, then its owning role)."),
12035
+ note: z32.string().max(2e3).optional().describe("'record': free-text note recorded with the reading."),
12036
+ source: z32.string().max(500).optional().describe("'record': where the number came from \u2014 a dashboard name, a query, a URL."),
12037
+ limit: z32.number().int().positive().max(200).optional().describe("'list': max rows to return (default and maximum 200).")
12235
12038
  });
12236
- var recordVariant = z33.object({
12237
- action: z33.literal("record"),
12238
- entryId: z33.string().max(200),
12239
- value: z33.number().finite(),
12240
- valueText: z33.string().max(500).optional(),
12241
- asOf: z33.string().max(64).optional(),
12242
- kind: z33.enum(READING_KINDS).optional(),
12243
- correctsReadingId: z33.string().max(200).optional(),
12244
- recordedByRoleId: z33.string().max(200).optional(),
12245
- note: z33.string().max(2e3).optional(),
12246
- source: z33.string().max(500).optional()
12039
+ var recordVariant = z32.object({
12040
+ action: z32.literal("record"),
12041
+ entryId: z32.string().max(200),
12042
+ value: z32.number().finite(),
12043
+ valueText: z32.string().max(500).optional(),
12044
+ asOf: z32.string().max(64).optional(),
12045
+ kind: z32.enum(READING_KINDS).optional(),
12046
+ correctsReadingId: z32.string().max(200).optional(),
12047
+ recordedByRoleId: z32.string().max(200).optional(),
12048
+ note: z32.string().max(2e3).optional(),
12049
+ source: z32.string().max(500).optional()
12247
12050
  });
12248
- var listVariant2 = z33.object({
12249
- action: z33.literal("list"),
12250
- entryId: z33.string().max(200),
12251
- limit: z33.number().int().positive().max(200).optional()
12051
+ var listVariant2 = z32.object({
12052
+ action: z32.literal("list"),
12053
+ entryId: z32.string().max(200),
12054
+ limit: z32.number().int().positive().max(200).optional()
12252
12055
  });
12253
- var showVariant = z33.object({ action: z33.literal("show"), entryId: z33.string().max(200) });
12254
- var outcomeActionUnion = z33.discriminatedUnion("action", [recordVariant, listVariant2, showVariant]);
12056
+ var showVariant = z32.object({ action: z32.literal("show"), entryId: z32.string().max(200) });
12057
+ var outcomeActionUnion = z32.discriminatedUnion("action", [recordVariant, listVariant2, showVariant]);
12255
12058
  var OUTCOME_ACTION_SPECS = {
12256
12059
  record: {
12257
12060
  params: ["entryId", "value", "valueText", "asOf", "kind", "correctsReadingId", "recordedByRoleId", "note", "source"],
@@ -12785,7 +12588,7 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
12785
12588
  }
12786
12589
 
12787
12590
  // src/prompts/index.ts
12788
- import { z as z34 } from "zod/v3";
12591
+ import { z as z33 } from "zod/v3";
12789
12592
  async function buildReviewAgainstRulesPrompt(domain) {
12790
12593
  const entries = await kernelQuery("chain.listEntries", { collectionSlug: "rules" });
12791
12594
  const rules = entries.slice(0, 50);
@@ -12867,27 +12670,27 @@ function registerPrompts(server) {
12867
12670
  server.prompt(
12868
12671
  "review-against-rules",
12869
12672
  "Review code or a design decision against the rules, focused on a given area. Fetches the rules and asks you to do a structured compliance review.",
12870
- { domain: z34.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
12673
+ { domain: z33.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
12871
12674
  async ({ domain }) => buildReviewAgainstRulesPrompt(domain)
12872
12675
  );
12873
12676
  server.prompt(
12874
12677
  "name-check",
12875
12678
  "Check variable names, field names, or API names against the glossary for terminology alignment. Flags drift from canonical terms.",
12876
- { names: z34.string().describe("Comma-separated list of names to check (e.g. 'user_id, workspace_id, entry_status')") },
12679
+ { names: z33.string().describe("Comma-separated list of names to check (e.g. 'user_id, workspace_id, entry_status')") },
12877
12680
  async ({ names }) => buildNameCheckPrompt(names)
12878
12681
  );
12879
12682
  server.prompt(
12880
12683
  "draft-decision-record",
12881
12684
  "Draft a structured decision record from a description of what was decided. Includes context from recent decisions and relevant rules.",
12882
- { context: z34.string().describe("Description of the decision (e.g. 'We decided to keep one body field per entry because...')") },
12685
+ { context: z33.string().describe("Description of the decision (e.g. 'We decided to keep one body field per entry because...')") },
12883
12686
  async ({ context }) => buildDraftDecisionRecordPrompt(context)
12884
12687
  );
12885
12688
  server.prompt(
12886
12689
  "draft-rule-from-context",
12887
12690
  "Draft a new business rule from an observation or discovery made while coding. Fetches existing rules for the domain to ensure consistency.",
12888
12691
  {
12889
- observation: z34.string().describe("What you observed or discovered (e.g. 'A workspace can have more than one owner role')"),
12890
- domain: z34.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
12692
+ observation: z33.string().describe("What you observed or discovered (e.g. 'A workspace can have more than one owner role')"),
12693
+ domain: z33.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
12891
12694
  },
12892
12695
  async ({ observation, domain }) => buildDraftRuleFromContextPrompt(observation, domain)
12893
12696
  );
@@ -12983,7 +12786,7 @@ var INSTRUCTIONS = [
12983
12786
  "Finish with `session action=wrapup-review`, then `session action=close`.",
12984
12787
  "If the work falls outside the active work packages, name the gap and ask the user before designing it."
12985
12788
  ].join("\n");
12986
- var sessionIdArg = z35.string().max(200).optional().describe(
12789
+ var sessionIdArg = z34.string().max(200).optional().describe(
12987
12790
  "The sessionId `session action=start` returned. Pass it on every write: the connection does not remember your session between calls."
12988
12791
  );
12989
12792
  function acceptSessionIdOnEveryTool(server) {
@@ -13036,7 +12839,6 @@ function createProductBrainServer() {
13036
12839
  registerWorkflowTools(server);
13037
12840
  registerWorkspaceTools(server);
13038
12841
  registerFeedbackTool(server);
13039
- registerShapeTools(server);
13040
12842
  registerQuestionTools(server);
13041
12843
  registerRoleTools(server);
13042
12844
  registerPeopleTools(server);
@@ -13076,4 +12878,4 @@ export {
13076
12878
  createProductBrainServer,
13077
12879
  initFeatureFlags
13078
12880
  };
13079
- //# sourceMappingURL=chunk-OQ5VWMAU.js.map
12881
+ //# sourceMappingURL=chunk-LPGWKTO5.js.map