@productbrain/mcp 0.0.1-beta.2744 → 0.0.1-beta.2771

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.
@@ -40,7 +40,7 @@ import {
40
40
  trackSessionCaptureRate,
41
41
  trackWriteBackHintServed,
42
42
  trackZeroCaptureAuditFired
43
- } from "./chunk-UCYQNZOC.js";
43
+ } from "./chunk-6XYRKXER.js";
44
44
 
45
45
  // src/server.ts
46
46
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -8108,7 +8108,7 @@ var startPbSchema = z13.object({
8108
8108
  // capability that does not exist and would diverge start_pb from orient.
8109
8109
  });
8110
8110
  var PB_SETUP_SKILL_ENTRY_ID = "SKILL-pb-setup";
8111
- var FEEDBACK_HINT = "Friction or ideas? Use `feedback action=submit` \u2014 describe how pb behaved, not your workspace content. Seconds, it reaches the builders.";
8111
+ var FEEDBACK_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.";
8112
8112
  async function tryMarkOriented(agentSessionId, coherenceSnapshot) {
8113
8113
  if (!agentSessionId) return { oriented: false, orientationStatus: "no_session" };
8114
8114
  try {
@@ -12395,9 +12395,9 @@ async function handleStart2() {
12395
12395
  );
12396
12396
  if (result2.feedbackQueueNew && result2.feedbackQueueNew > 0) {
12397
12397
  const ageDays = result2.feedbackOldestNewAt ? Math.max(0, Math.floor((Date.now() - result2.feedbackOldestNewAt) / 864e5)) : null;
12398
- lines.push(`Feedback queue: ${result2.feedbackQueueNew} new (oldest ${ageDays === null ? "unknown" : `${ageDays}d`}) \u2014 feedback action=list`);
12398
+ lines.push(`Feedback queue: ${result2.feedbackQueueNew} new (oldest ${ageDays === null ? "unknown" : `${ageDays}d`}) \u2014 feedback action=queue`);
12399
12399
  }
12400
- lines.push("Friction or ideas? Use `feedback action=submit` \u2014 describe how pb behaved, not your workspace content. Seconds, it reaches the builders.");
12400
+ lines.push("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.");
12401
12401
  const summary = `Session ${result2.sessionId} active. Workspace ${result2.workspaceName}. Write tools available after orient.`;
12402
12402
  return {
12403
12403
  content: [{ type: "text", text: lines.join("\n") }],
@@ -14495,12 +14495,16 @@ import { z as z27 } from "zod/v3";
14495
14495
 
14496
14496
  // src/lib/productFeedbackConstants.ts
14497
14497
  var PRODUCT_FEEDBACK_CATEGORIES = ["bug", "friction", "idea", "praise", "other"];
14498
- var PRODUCT_FEEDBACK_STATUSES = ["new", "triaged", "planned", "resolved", "dismissed"];
14498
+ var PRODUCT_FEEDBACK_STATUSES = ["new", "triaged", "planned", "resolved", "dismissed", "screening"];
14499
+ var VENDOR_SETTABLE_STATUSES = PRODUCT_FEEDBACK_STATUSES.filter(
14500
+ (status2) => status2 !== "screening"
14501
+ );
14499
14502
 
14500
14503
  // src/tools/feedback.ts
14501
- var actions = ["submit", "list", "note", "group", "status"];
14504
+ var actions = ["submit", "list", "queue", "note", "group", "status"];
14502
14505
  var category = z27.enum(PRODUCT_FEEDBACK_CATEGORIES);
14503
14506
  var status = z27.enum(PRODUCT_FEEDBACK_STATUSES);
14507
+ var vendorStatus = z27.enum(VENDOR_SETTABLE_STATUSES);
14504
14508
  var GATEWAY_MAX_STRING_BYTES = 10240;
14505
14509
  var utf8Bytes = (value) => new TextEncoder().encode(value).length;
14506
14510
  var fitsGatewayBytes = (value) => utf8Bytes(value) <= GATEWAY_MAX_STRING_BYTES;
@@ -14510,37 +14514,40 @@ var byteLimitMessage = (field) => ({
14510
14514
  var MESSAGE_DISPLAY_LIMIT = 1e3;
14511
14515
  var FULL_MESSAGE_MAX_LIMIT = 5;
14512
14516
  var feedbackSchema = z27.object({
14513
- action: z27.enum(actions).describe("submit requires message; list accepts filters; note requires feedbackId+note; group requires feedbackIds+groupId (null clears); status requires feedbackId+status."),
14517
+ action: z27.enum(actions).describe("submit requires message; list returns your own workspace's feedback (all statuses); queue is the vendor triage queue (system admins only) and accepts filters; note requires feedbackId+note; group requires feedbackIds+groupId (null clears); status requires feedbackId+status."),
14514
14518
  message: z27.string().max(1e4).optional().describe("Required for submit: the product feedback text (max 10,000 chars and 10,240 UTF-8 bytes)."),
14515
- category: category.optional().describe("Submit/list category; submit defaults to other."),
14519
+ category: category.optional().describe("Submit/queue category; submit defaults to other."),
14516
14520
  command: z27.string().max(1e3).optional().describe("Optional submit command context; argument values are scrubbed server-side."),
14517
14521
  route: z27.string().max(500).optional().describe("Optional submit route context."),
14518
14522
  client: z27.string().max(100).optional().describe("Optional submit client label."),
14519
14523
  feedbackId: z27.string().max(200).optional().describe("Required for note/status: target feedback ID."),
14520
14524
  feedbackIds: z27.array(z27.string().max(200)).max(100).optional().describe("Required for group: 1\u2013100 target feedback IDs."),
14521
14525
  note: z27.string().max(4e3).optional().describe("Required for note: replacement triage note (max 10,240 UTF-8 bytes)."),
14522
- status: status.optional().describe("List filter or required status action value."),
14523
- groupId: z27.string().max(200).nullable().optional().describe("Group filter, or required group destination; null explicitly clears grouping."),
14524
- workspaceId: z27.string().max(200).optional().describe("Vendor-only list filter; omitted means all workspaces."),
14525
- since: z27.number().optional().describe("Vendor list lower createdAt window bound (inclusive) in epoch milliseconds."),
14526
- before: z27.number().optional().describe("Vendor list upper createdAt window bound (exclusive) in epoch milliseconds. A time-window FILTER, not the pager \u2014 use cursor to page."),
14527
- limit: z27.number().int().min(1).max(100).optional().describe("Vendor list row limit, default 50, maximum 100."),
14528
- cursor: z27.string().max(2e3).optional().describe("Opaque pagination cursor from a previous list response (continueCursor); omit for the first page."),
14529
- full: z27.boolean().optional().describe(`List only: return untruncated messages; allowed only when limit <= ${FULL_MESSAGE_MAX_LIMIT}.`)
14526
+ status: status.optional().describe("list/queue filter (any status, including 'screening'); the status action's required target value excludes 'screening' (system-only)."),
14527
+ groupId: z27.string().min(1).max(200).nullable().optional().describe("Group filter, or required group destination; null explicitly clears grouping."),
14528
+ workspaceId: z27.string().max(200).optional().describe("Queue-only filter (vendor cross-workspace triage); omitted means all workspaces. Has no effect on list \u2014 your own workspace is always injected server-side."),
14529
+ since: z27.number().optional().describe("Queue-only lower createdAt window bound (inclusive) in epoch milliseconds."),
14530
+ before: z27.number().optional().describe("Queue-only upper createdAt window bound (exclusive) in epoch milliseconds. A time-window FILTER, not the pager \u2014 use cursor to page."),
14531
+ limit: z27.number().int().min(1).max(100).optional().describe("list/queue row limit, default 50, maximum 100."),
14532
+ cursor: z27.string().max(2e3).optional().describe("Opaque pagination cursor from a previous list/queue response (continueCursor); omit for the first page."),
14533
+ full: z27.boolean().optional().describe(`list/queue only: return untruncated messages; allowed only when limit <= ${FULL_MESSAGE_MAX_LIMIT}.`)
14530
14534
  });
14531
14535
  var union = z27.discriminatedUnion("action", [
14532
14536
  z27.object({ action: z27.literal("submit"), message: z27.string().min(1).max(1e4).refine(fitsGatewayBytes, byteLimitMessage("message")), category: category.optional(), command: z27.string().max(1e3).optional(), route: z27.string().max(500).optional(), client: z27.string().max(100).optional() }),
14533
- z27.object({ action: z27.literal("list"), status: status.optional(), category: category.optional(), groupId: z27.string().max(200).optional(), workspaceId: z27.string().max(200).optional(), since: z27.number().optional(), before: z27.number().optional(), limit: z27.number().int().min(1).max(100).optional(), cursor: z27.string().max(2e3).optional(), full: z27.boolean().optional() }),
14537
+ z27.object({ action: z27.literal("list"), status: status.optional(), limit: z27.number().int().min(1).max(100).optional(), cursor: z27.string().max(2e3).optional(), full: z27.boolean().optional() }),
14538
+ z27.object({ action: z27.literal("queue"), status: status.optional(), category: category.optional(), groupId: z27.string().min(1).max(200).optional(), workspaceId: z27.string().max(200).optional(), since: z27.number().optional(), before: z27.number().optional(), limit: z27.number().int().min(1).max(100).optional(), cursor: z27.string().max(2e3).optional(), full: z27.boolean().optional() }),
14534
14539
  z27.object({ action: z27.literal("note"), feedbackId: z27.string().min(1).max(200), note: z27.string().max(4e3).refine(fitsGatewayBytes, byteLimitMessage("note")) }),
14535
- z27.object({ action: z27.literal("group"), feedbackIds: z27.array(z27.string().min(1).max(200)).min(1).max(100), groupId: z27.string().max(200).nullable() }),
14536
- z27.object({ action: z27.literal("status"), feedbackId: z27.string().min(1).max(200), status })
14540
+ z27.object({ action: z27.literal("group"), feedbackIds: z27.array(z27.string().min(1).max(200)).min(1).max(100), groupId: z27.string().min(1).max(200).nullable() }),
14541
+ z27.object({ action: z27.literal("status"), feedbackId: z27.string().min(1).max(200), status: vendorStatus })
14537
14542
  ]);
14538
14543
  var specs = {
14539
14544
  submit: { params: ["message", "category", "command", "route", "client"], description: "message is required; category defaults to other." },
14540
- list: { params: ["status", "category", "groupId", "workspaceId", "since", "before", "limit", "cursor", "full"], description: "Vendor queue filters are optional; status defaults to new; cursor pages, full lifts message truncation for limit <= 5." },
14545
+ // Own-workspace read-back (spec: WP-494 §5) — the member default; vendor queue is the `queue` action.
14546
+ list: { params: ["status", "limit", "cursor", "full"], description: "Your workspace's own feedback \u2014 all statuses by default (including screening); cursor pages, full lifts message truncation for limit <= 5. No vendor gate." },
14547
+ queue: { params: ["status", "category", "groupId", "workspaceId", "since", "before", "limit", "cursor", "full"], description: "Vendor cross-workspace triage queue (system admins only); filters are optional, status defaults to new; cursor pages, full lifts message truncation for limit <= 5." },
14541
14548
  note: { params: ["feedbackId", "note"], description: "feedbackId and note are required." },
14542
14549
  group: { params: ["feedbackIds", "groupId"], description: "feedbackIds and groupId are required; null clears a group." },
14543
- status: { params: ["feedbackId", "status"], description: "feedbackId and status are required." }
14550
+ status: { params: ["feedbackId", "status"], description: "feedbackId and status are required; status cannot be set to 'screening' (system-only)." }
14544
14551
  };
14545
14552
  function result(action, data) {
14546
14553
  const summary = action === "submit" ? "Feedback submitted." : `Feedback ${action} complete.`;
@@ -14612,17 +14619,34 @@ function registerFeedbackTool(server) {
14612
14619
  context: { command: data.command, route: data.route, client: data.client ?? "mcp" }
14613
14620
  }));
14614
14621
  },
14622
+ // WP-494 §5 (TEN-2742): own-workspace read-back — the default verb. NO vendor/triage
14623
+ // gate: it's a member query (`feedback.listOwn`), a read-scoped key passes, and the
14624
+ // gateway force-injects the caller's own workspaceId regardless of anything sent here.
14615
14625
  list: async ({ action: _action, full, cursor, ...data }) => {
14626
+ const wantFull = full === true;
14627
+ if (wantFull && (data.limit ?? 50) > FULL_MESSAGE_MAX_LIMIT) {
14628
+ throw new Error(`full=true returns untruncated messages and is only allowed with limit <= ${FULL_MESSAGE_MAX_LIMIT}; re-fetch the target rows with a smaller limit (page with cursor).`);
14629
+ }
14630
+ const page = normalizeListPage(await kernelCall("feedback.listOwn", {
14631
+ ...data,
14632
+ cursor: cursor ?? null
14633
+ }));
14634
+ return result("list", { ...page, items: truncateListItems(page.items, wantFull) });
14635
+ },
14636
+ // WP-494 §5: the vendor cross-workspace triage queue — takes over `list`'s old
14637
+ // behavior verbatim, including the triage-session gate and every existing filter.
14638
+ queue: async ({ action: _action, full, cursor, groupId, ...data }) => {
14616
14639
  const wantFull = full === true;
14617
14640
  if (wantFull && (data.limit ?? 50) > FULL_MESSAGE_MAX_LIMIT) {
14618
14641
  throw new Error(`full=true returns untruncated messages and is only allowed with limit <= ${FULL_MESSAGE_MAX_LIMIT}; re-fetch the target rows with a smaller limit (page with cursor).`);
14619
14642
  }
14620
14643
  const page = normalizeListPage(await kernelCall("feedback.list", {
14621
14644
  ...data,
14645
+ ...groupId !== void 0 ? { groupId } : {},
14622
14646
  cursor: cursor ?? null,
14623
14647
  sessionId: requireTriageSessionId()
14624
14648
  }));
14625
- return result("list", { ...page, items: truncateListItems(page.items, wantFull) });
14649
+ return result("queue", { ...page, items: truncateListItems(page.items, wantFull) });
14626
14650
  },
14627
14651
  note: async ({ action: _action, ...data }) => result("note", await kernelCall("feedback.note", { ...data, sessionId: requireTriageSessionId() })),
14628
14652
  group: async ({ action: _action, ...data }) => groupResult(await kernelCall("feedback.group", { ...data, sessionId: requireTriageSessionId() })),
@@ -14630,7 +14654,7 @@ function registerFeedbackTool(server) {
14630
14654
  };
14631
14655
  server.registerTool("feedback", {
14632
14656
  title: "Feedback \u2014 Submit & Triage",
14633
- description: "Submit Product Brain feedback from any agent, including with a read-only key and no session. Vendor operators can also list, note, group, and change queue status.",
14657
+ description: "Submit Product Brain feedback from any agent, including with a read-only key and no session. list reads back your own workspace's feedback (all statuses, no gate). Vendor operators can also queue (triage), note, group, and change queue status.",
14634
14658
  inputSchema: feedbackSchema,
14635
14659
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: false }
14636
14660
  }, thinWrapper(async (args) => {
@@ -14645,6 +14669,53 @@ import { existsSync as existsSync3 } from "fs";
14645
14669
  import { dirname, join, resolve as resolve4 } from "path";
14646
14670
  import { fileURLToPath } from "url";
14647
14671
  import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
14672
+
14673
+ // src/resources/agentCheatsheet.ts
14674
+ var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
14675
+
14676
+ ## Core Tools (Serves 11 default compound tools; 3 more (chain, chain-review, map) behind PB_MODULES=gitchain)
14677
+ | Tool | Purpose | Key params |
14678
+ |---|---|---|
14679
+ | \`orient\` | Workspace context, governance, active bets, session start | \`action\`: start, task, record-activation |
14680
+ | \`capture\` | Create entry (draft), single or batch | \`collection\`, \`name\`, \`description\`, optional \`data\` / \`items[]\` |
14681
+ | \`entries\` | List / get / batch / search / update / commit / history / move / verify | \`action\` + \`entryId\` / \`query\` / \`collection\` |
14682
+ | \`relations\` | Create / batch-create / dismiss / delete / find / suggest links | \`action\` + \`from\`, \`to\`, \`type\` or \`entryId\` |
14683
+ | \`context\` | Gather related knowledge, last-verified brief | \`action\` + \`entryId\` or \`task\` |
14684
+ | \`collections\` | List / create / update collections, manage labels | \`action\` |
14685
+ | \`quality\` | Score an entry, verify the Chain, audit a bet | \`action\`: check, re-evaluate, verify-chain, audit |
14686
+ | \`session\` | Start / close, wrapup, resume, constellation accept | \`action\`: start, close, status, wrapup-review, wrapup-commit, resume, commit-constellation |
14687
+ | \`workflows\` | Run workflows, checkpoint, load a skill | \`action\`: list, start, checkpoint, get-run, load-skill |
14688
+ | \`workspace\` | Check / whoami / status / self-test, usage, governance proposals | \`action\`: check, whoami, status, audit, self-test, usage, proposals-* |
14689
+ | \`feedback\` | Submit product feedback (any key, no session required); \`list\` reads back your own workspace's feedback (no gate); vendor triage: queue / note / group / status | \`action\`: submit, list, queue, note, group, status |
14690
+
14691
+ ## Collection Prefixes
14692
+ GLO (glossary), BR (business-rules), PRI (principles), STD (standards),
14693
+ DEC (decisions), STR (strategy), TEN (tensions), FEAT (features),
14694
+ BET (bets), INS (insights), ARCH (architecture), TEAM (teams),
14695
+ ROL (roles), MAP (maps), MTRC (tracking-events), ST (semantic-types)
14696
+
14697
+ ## Valid Relation Types (21)
14698
+ informs, governs, surfaces_tension_in, defines_term_for, belongs_to,
14699
+ references, related_to, fills_slot, commits_to, informed_by, depends_on,
14700
+ conflicts_with, confused_with, replaces, part_of, constrains,
14701
+ governed_by, alternative_to, has_proposal, requests_promotion_of, resolves
14702
+
14703
+ ## Lifecycle Status
14704
+ All entries: \`draft\` | \`active\` | \`deprecated\` | \`archived\`
14705
+
14706
+ ## Workflow Status (per collection)
14707
+ - **tensions:** open \u2192 processing \u2192 decided \u2192 closed
14708
+ - **decisions:** pending \u2192 decided
14709
+ - **bets:** shaped \u2192 bet \u2192 building \u2192 shipped
14710
+ - **business-rules:** active | conflict | review
14711
+
14712
+ ## Key Patterns
14713
+ - **Capture flow:** \`capture\` \u2192 \`relations action=suggest\` \u2192 \`relations action=batch-create\` \u2192 \`entries action=commit\`
14714
+ - Use \`workflowStatus\` (not \`status\`) for domain workflow state
14715
+ - \`data\` param is merged (not replaced) \u2014 safe for partial updates
14716
+ `;
14717
+
14718
+ // src/resources/index.ts
14648
14719
  var MODULE_DIR = dirname(fileURLToPath(import.meta.url));
14649
14720
  var UI_VIEW_BASE_CANDIDATES = [
14650
14721
  resolve4(MODULE_DIR, "views"),
@@ -14747,49 +14818,6 @@ Browse: \`entries action=list collection=tracking-events\`.`
14747
14818
  );
14748
14819
  return sections.join("\n\n---\n\n");
14749
14820
  }
14750
- var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
14751
-
14752
- ## Core Tools (Serves 11 default compound tools; 3 more (chain, chain-review, map) behind PB_MODULES=gitchain)
14753
- | Tool | Purpose | Key params |
14754
- |---|---|---|
14755
- | \`orient\` | Workspace context, governance, active bets, session start | \`action\`: start, task, record-activation |
14756
- | \`capture\` | Create entry (draft), single or batch | \`collection\`, \`name\`, \`description\`, optional \`data\` / \`items[]\` |
14757
- | \`entries\` | List / get / batch / search / update / commit / history / move / verify | \`action\` + \`entryId\` / \`query\` / \`collection\` |
14758
- | \`relations\` | Create / batch-create / dismiss / delete / find / suggest links | \`action\` + \`from\`, \`to\`, \`type\` or \`entryId\` |
14759
- | \`context\` | Gather related knowledge, last-verified brief | \`action\` + \`entryId\` or \`task\` |
14760
- | \`collections\` | List / create / update collections, manage labels | \`action\` |
14761
- | \`quality\` | Score an entry, verify the Chain, audit a bet | \`action\`: check, re-evaluate, verify-chain, audit |
14762
- | \`session\` | Start / close, wrapup, resume, constellation accept | \`action\`: start, close, status, wrapup-review, wrapup-commit, resume, commit-constellation |
14763
- | \`workflows\` | Run workflows, checkpoint, load a skill | \`action\`: list, start, checkpoint, get-run, load-skill |
14764
- | \`workspace\` | Check / whoami / status / self-test, usage, governance proposals | \`action\`: check, whoami, status, audit, self-test, usage, proposals-* |
14765
- | \`feedback\` | Submit product feedback (any key, no session required); vendor triage: list / note / group / status | \`action\`: submit, list, note, group, status |
14766
-
14767
- ## Collection Prefixes
14768
- GLO (glossary), BR (business-rules), PRI (principles), STD (standards),
14769
- DEC (decisions), STR (strategy), TEN (tensions), FEAT (features),
14770
- BET (bets), INS (insights), ARCH (architecture), TEAM (teams),
14771
- ROL (roles), MAP (maps), MTRC (tracking-events), ST (semantic-types)
14772
-
14773
- ## Valid Relation Types (21)
14774
- informs, governs, surfaces_tension_in, defines_term_for, belongs_to,
14775
- references, related_to, fills_slot, commits_to, informed_by, depends_on,
14776
- conflicts_with, confused_with, replaces, part_of, constrains,
14777
- governed_by, alternative_to, has_proposal, requests_promotion_of, resolves
14778
-
14779
- ## Lifecycle Status
14780
- All entries: \`draft\` | \`active\` | \`deprecated\` | \`archived\`
14781
-
14782
- ## Workflow Status (per collection)
14783
- - **tensions:** open \u2192 processing \u2192 decided \u2192 closed
14784
- - **decisions:** pending \u2192 decided
14785
- - **bets:** shaped \u2192 bet \u2192 building \u2192 shipped
14786
- - **business-rules:** active | conflict | review
14787
-
14788
- ## Key Patterns
14789
- - **Capture flow:** \`capture\` \u2192 \`relations action=suggest\` \u2192 \`relations action=batch-create\` \u2192 \`entries action=commit\`
14790
- - Use \`workflowStatus\` (not \`status\`) for domain workflow state
14791
- - \`data\` param is merged (not replaced) \u2014 safe for partial updates
14792
- `;
14793
14821
  function registerResources(server) {
14794
14822
  server.resource(
14795
14823
  "agent-cheatsheet",
@@ -15564,4 +15592,4 @@ export {
15564
15592
  createProductBrainServer,
15565
15593
  initFeatureFlags
15566
15594
  };
15567
- //# sourceMappingURL=chunk-PU2BI5UU.js.map
15595
+ //# sourceMappingURL=chunk-VVC5Z5E5.js.map