@productbrain/mcp 0.0.1-beta.7319 → 0.0.1-beta.7330

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.
@@ -41,7 +41,7 @@ import {
41
41
  trackSessionCaptureRate,
42
42
  trackWriteBackHintServed,
43
43
  trackZeroCaptureAuditFired
44
- } from "./chunk-2RHVPN24.js";
44
+ } from "./chunk-SU5XEDCF.js";
45
45
 
46
46
  // src/server.ts
47
47
  import { McpServer as McpServer2 } from "@modelcontextprotocol/sdk/server/mcp.js";
@@ -7911,10 +7911,6 @@ function formatNoticeLines(notices) {
7911
7911
  (n) => n.source === QUESTION_ACK_GATE_SOURCE_ID && n.payload ? formatQuestionAckGateBlock(n) : [`- ${safe(n.subject)} (${safe(n.change)})`]
7912
7912
  );
7913
7913
  }
7914
- function formatAdoptDiscoveryLine(display) {
7915
- if (!display) return [];
7916
- return [`- ${display} open question${display === "1" ? "" : "s"} you raised have no owner yet \u2014 use \`question action=adopt\` to route one.`];
7917
- }
7918
7914
 
7919
7915
  // src/lib/terminalStatuses.ts
7920
7916
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
@@ -12318,10 +12314,6 @@ async function handleStart2(data) {
12318
12314
  if (noticeLines.length > 0) {
12319
12315
  lines.push("", "Notices:", ...noticeLines);
12320
12316
  }
12321
- const adoptLines = formatAdoptDiscoveryLine(result2.adoptDiscoveryHint);
12322
- if (adoptLines.length > 0) {
12323
- lines.push("", ...adoptLines);
12324
- }
12325
12317
  const summary = `Session ${result2.sessionId} active. Workspace ${result2.workspaceName}. Write tools available after orient.`;
12326
12318
  return {
12327
12319
  content: [{ type: "text", text: lines.join("\n") }],
@@ -12334,8 +12326,7 @@ async function handleStart2(data) {
12334
12326
  roleName: result2.roleName,
12335
12327
  feedbackQueueNew: result2.feedbackQueueNew,
12336
12328
  feedbackOldestNewAt: result2.feedbackOldestNewAt,
12337
- notices: result2.notices ?? [],
12338
- adoptDiscoveryHint: result2.adoptDiscoveryHint
12329
+ notices: result2.notices ?? []
12339
12330
  // Finding #16: bare `parameters: {}` lets orient's schema default kick in
12340
12331
  // (action defaults to "task", which requires a `task` string) — the suggested
12341
12332
  // next-action call failed validation instead of running. `action: "start"` is
@@ -13571,45 +13562,34 @@ function registerShapeTools(server) {
13571
13562
 
13572
13563
  // src/tools/question.ts
13573
13564
  import { z as z32 } from "zod/v3";
13574
- var QUESTION_ACTIONS = ["create", "adopt", "assign", "snooze", "decline", "answer", "force-close", "list"];
13565
+ var QUESTION_ACTIONS = ["create", "assign", "answer", "force-close", "list"];
13575
13566
  var questionSchema = z32.object({
13576
13567
  action: z32.enum(QUESTION_ACTIONS).describe(
13577
- "'create': create a new routed question from text (domains come from `pb question --help` / this tool's own refusal \u2014 never hardcode a slug). 'adopt': adopt attaches routing to an existing tension or repairs a facet-less question \u2014 create is the birth path. Without adopt, a tension captured via `pb capture \"TEN: ...\"` stays invisible to routing forever. 'assign': confirm ('take it', omit toRole/toPerson) or reassign (supply toRole and/or toPerson) ownership. 'snooze': defer a routed/escalated question (max 2, then it escalates). 'decline': pass on a suggested question, or (as owner/lead) decline an owned one \u2014 reason required. 'answer': close the loop \u2014 creates the answering entry itself unless --entry is given. '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)."
13568
+ "'create': create a new routed question from text \u2014 the only birth path now; every question is born escalated to the team lead. 'assign': reassign ownership to a role (toRole required \u2014 no bare self-confirm, no toPerson). 'answer': close the loop \u2014 creates the answering entry itself unless --entry is given. '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)."
13578
13569
  ),
13579
13570
  entryId: z32.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'."),
13580
13571
  text: z32.string().max(5e3).optional().describe("'create': the question text. 'answer': the answer text (mutually exclusive with answerEntryId, max 2000 chars)."),
13581
- domain: z32.string().max(200).optional().describe("'create'/'adopt': the domain slug (see this tool's refusal for the live list)."),
13582
- blocks: z32.array(z32.string().max(200)).max(50).optional().describe("'create'/'adopt': entry ids this question is blocking (repeatable)."),
13583
- toRole: z32.string().max(200).optional().describe("'assign': reassign to this role (human ROL-nnn form or a raw entry id)."),
13584
- toPerson: z32.string().max(200).optional().describe("'assign': reassign to this person (a raw person id)."),
13585
- reason: z32.string().max(2e3).optional().describe("'decline'/'force-close': required reason."),
13572
+ blocks: z32.array(z32.string().max(200)).max(50).optional().describe("'create': entry ids this question is blocking (repeatable)."),
13573
+ toRole: z32.string().max(200).optional().describe("'assign': reassign to this role (human ROL-nnn form or a raw entry id) \u2014 required."),
13574
+ reason: z32.string().max(2e3).optional().describe("'force-close': required reason."),
13586
13575
  answerEntryId: z32.string().max(200).optional().describe("'answer': point at an already-written entry instead of supplying text (mutually exclusive with text)."),
13587
13576
  mine: z32.boolean().optional().describe("'list': true for arm C (every question YOU asked, every status). Omit/false for the ack-gate view (what you owe).")
13588
13577
  });
13589
- var createVariant = z32.object({ action: z32.literal("create"), text: z32.string().min(1).max(5e3), domain: z32.string().max(200).optional(), blocks: z32.array(z32.string().max(200)).max(50).optional() });
13590
- var adoptVariant = z32.object({ action: z32.literal("adopt"), entryId: z32.string().max(200), domain: z32.string().max(200).optional(), blocks: z32.array(z32.string().max(200)).max(50).optional() });
13591
- var assignVariant = z32.object({ action: z32.literal("assign"), entryId: z32.string().max(200), toRole: z32.string().max(200).optional(), toPerson: z32.string().max(200).optional() });
13592
- var snoozeVariant = z32.object({ action: z32.literal("snooze"), entryId: z32.string().max(200) });
13593
- var declineVariant = z32.object({ action: z32.literal("decline"), entryId: z32.string().max(200), reason: z32.string().min(1).max(2e3) });
13578
+ var createVariant = z32.object({ action: z32.literal("create"), text: z32.string().min(1).max(5e3), blocks: z32.array(z32.string().max(200)).max(50).optional() });
13579
+ var assignVariant = z32.object({ action: z32.literal("assign"), entryId: z32.string().max(200), toRole: z32.string().max(200).min(1) });
13594
13580
  var answerVariant = z32.object({ action: z32.literal("answer"), entryId: z32.string().max(200), text: z32.string().max(2e3).optional(), answerEntryId: z32.string().max(200).optional() });
13595
13581
  var forceCloseVariant = z32.object({ action: z32.literal("force-close"), entryId: z32.string().max(200), reason: z32.string().min(1).max(2e3) });
13596
13582
  var listVariant = z32.object({ action: z32.literal("list"), mine: z32.boolean().optional() });
13597
13583
  var questionActionUnion = z32.discriminatedUnion("action", [
13598
13584
  createVariant,
13599
- adoptVariant,
13600
13585
  assignVariant,
13601
- snoozeVariant,
13602
- declineVariant,
13603
13586
  answerVariant,
13604
13587
  forceCloseVariant,
13605
13588
  listVariant
13606
13589
  ]);
13607
13590
  var QUESTION_ACTION_SPECS = {
13608
- create: { params: ["text", "domain", "blocks"], description: "text is required; domain/blocks are optional." },
13609
- adopt: { params: ["entryId", "domain", "blocks"], description: "entryId is required (the already-captured tension); domain/blocks are optional." },
13610
- assign: { params: ["entryId", "toRole", "toPerson"], description: "entryId is required; omit toRole/toPerson to self-confirm, or supply one/both to reassign." },
13611
- snooze: { params: ["entryId"], description: "entryId is required." },
13612
- decline: { params: ["entryId", "reason"], description: "entryId and reason are both required." },
13591
+ create: { params: ["text", "blocks"], description: "text is required; blocks is optional." },
13592
+ assign: { params: ["entryId", "toRole"], description: "entryId and toRole are both required \u2014 assign is reassign-to-a-role only." },
13613
13593
  answer: { params: ["entryId", "text", "answerEntryId"], description: "entryId is required; supply exactly one of text or answerEntryId." },
13614
13594
  "force-close": { params: ["entryId", "reason"], description: "entryId and reason are both required." },
13615
13595
  list: { params: ["mine"], description: "mine is optional \u2014 omit/false for the ack-gate view, true for every question you asked." }
@@ -13630,114 +13610,35 @@ async function displayName(id) {
13630
13610
  return void 0;
13631
13611
  }
13632
13612
  }
13633
- async function unresolvableRoleFallback(id) {
13634
- return await displayName(id) ?? `an unresolved role (\`${id}\` \u2014 reassign it)`;
13635
- }
13636
- function domainListSuffix(domainSlugs) {
13637
- if (!domainSlugs) return "";
13638
- return domainSlugs.length > 0 ? ` Domains in this workspace: ${domainSlugs.join(", ")}.` : " No domains exist in this workspace yet.";
13639
- }
13640
- async function renderCreateAdoptConfirmation(result2, isAdopt) {
13641
- const lead = isAdopt ? `${result2.entryId} is now a routed question,` : "Question created and";
13642
- let base;
13643
- if (result2.status === "unrouted") {
13644
- const roleName = result2.suggestedRoleId ? await unresolvableRoleFallback(result2.suggestedRoleId) : result2.suggestedRoleId;
13645
- base = isAdopt ? `${lead} suggested to ${roleName}.` : `${lead} suggested to ${roleName}. Confirm with: pb question assign ${result2.entryId}`;
13646
- } else {
13647
- const leadName = result2.ownerRoleId ? await unresolvableRoleFallback(result2.ownerRoleId) : result2.ownerRoleId;
13648
- base = isAdopt ? `${result2.entryId} is now a routed question. Nothing here says who owns it, so it has gone to ${leadName}.` : `Question created. Nothing here says who owns it, so it has gone to ${leadName}.`;
13649
- }
13613
+ async function renderCreateConfirmation(result2) {
13614
+ const leadName = result2.ownerRoleId ? await displayName(result2.ownerRoleId) ?? `an unresolved role (\`${result2.ownerRoleId}\` \u2014 reassign it)` : result2.ownerRoleId;
13615
+ const base = `Question created. Nothing here says who owns it, so it has gone to ${leadName}.`;
13650
13616
  const blocksHint = " If something is blocked on this, add blocks:[<entry-id>...].";
13651
13617
  const nudge = result2.nudge ? ` ${result2.nudge}` : "";
13652
- return `${base}${domainListSuffix(result2.domainSlugs)}${blocksHint}${nudge}`;
13618
+ return `${base}${blocksHint}${nudge}`;
13653
13619
  }
13654
- async function handleQuestionCreate(text, domain, blocks) {
13620
+ async function handleQuestionCreate(text, blocks) {
13655
13621
  requireWriteAccess();
13656
13622
  try {
13657
13623
  const resolvedBlocks = blocks ? await Promise.all(blocks.map((b) => resolveEntryRef(b, "Blocked entry"))) : void 0;
13658
- const result2 = await kernelMutation("question.create", { text, domainSlug: domain, blocks: resolvedBlocks, sessionId: getAgentSessionId() ?? void 0 });
13659
- const message = await renderCreateAdoptConfirmation(result2, false);
13660
- const next = result2.status === "unrouted" ? [{ tool: "question", description: "Confirm or reassign the suggestion", parameters: { action: "assign", entryId: result2.entryId } }] : void 0;
13661
- return successResult(message, message, result2, next);
13662
- } catch (err) {
13663
- return questionErrorResult(err, "create", { text, domain, blocks });
13664
- }
13665
- }
13666
- async function handleQuestionAdopt(entryId, domain, blocks) {
13667
- requireWriteAccess();
13668
- try {
13669
- const resolvedEntryId = await resolveEntryRef(entryId, "Entry");
13670
- const resolvedBlocks = blocks ? await Promise.all(blocks.map((b) => resolveEntryRef(b, "Blocked entry"))) : void 0;
13671
- const result2 = await kernelMutation("question.adopt", { entryId: resolvedEntryId, domainSlug: domain, blocks: resolvedBlocks, sessionId: getAgentSessionId() ?? void 0 });
13672
- const message = await renderCreateAdoptConfirmation(result2, true);
13624
+ const result2 = await kernelMutation("question.create", { text, blocks: resolvedBlocks, sessionId: getAgentSessionId() ?? void 0 });
13625
+ const message = await renderCreateConfirmation(result2);
13673
13626
  return successResult(message, message, result2);
13674
13627
  } catch (err) {
13675
- return questionErrorResult(err, "adopt", { entryId, domain, blocks });
13628
+ return questionErrorResult(err, "create", { text, blocks });
13676
13629
  }
13677
13630
  }
13678
- async function handleQuestionAssign(entryId, toRole, toPerson) {
13631
+ async function handleQuestionAssign(entryId, toRole) {
13679
13632
  requireWriteAccess();
13680
13633
  try {
13681
13634
  const resolvedEntryId = await resolveEntryRef(entryId, "Entry");
13682
- const resolvedToRoleId = toRole ? await resolveEntryRef(toRole, "Role") : void 0;
13683
- const result2 = await kernelMutation("question.assign", { entryId: resolvedEntryId, toRoleId: resolvedToRoleId, toPersonId: toPerson });
13684
- const isReassign = Boolean(toRole || toPerson);
13685
- let message;
13686
- if (isReassign) {
13687
- const who = toPerson ? stripControlChars(result2.ownerPersonName ?? "") || result2.ownerPersonId || "the target" : await displayName(result2.ownerRoleId) ?? result2.ownerRoleId ?? "the target";
13688
- message = `${entryId} reassigned to ${who}. They'll see it at their next session.`;
13689
- } else {
13690
- message = `${entryId} is yours now.`;
13691
- }
13692
- return successResult(message, message, result2);
13693
- } catch (err) {
13694
- return questionErrorResult(err, "assign", { entryId, toRole, toPerson });
13695
- }
13696
- }
13697
- async function handleQuestionSnooze(entryId) {
13698
- requireWriteAccess();
13699
- try {
13700
- const resolvedEntryId = await resolveEntryRef(entryId, "Entry");
13701
- const result2 = await kernelMutation("question.snooze", { entryId: resolvedEntryId });
13702
- let message;
13703
- if (result2.snoozeUntil) {
13704
- message = `Snoozed until ${new Date(result2.snoozeUntil).toISOString().slice(0, 10)}. ${result2.snoozeCount ?? "?"} of 2 snoozes used.`;
13705
- } else if (result2.status === "escalated") {
13706
- const leadName = await displayName(result2.ownerRoleId) ?? "the team lead";
13707
- message = `You have used both snoozes on this question \u2014 it has been escalated to ${leadName}.`;
13708
- } else {
13709
- message = "No snoozes left \u2014 answer it or force-close it.";
13710
- }
13711
- return successResult(message, message, result2);
13712
- } catch (err) {
13713
- return questionErrorResult(err, "snooze", { entryId });
13714
- }
13715
- }
13716
- async function handleQuestionDecline(entryId, reason) {
13717
- requireWriteAccess();
13718
- try {
13719
- const resolvedEntryId = await resolveEntryRef(entryId, "Entry");
13720
- const result2 = await kernelMutation("question.decline", { entryId: resolvedEntryId, reason });
13721
- let message;
13722
- if (result2.status === "processed") {
13723
- message = "Declined and closed.";
13724
- } else if (result2.isRoot === true) {
13725
- message = `Declined \u2014 but ${result2.dependentsCount ?? 0} item(s) still depend on it, so it stays with you. Answer it or force-close it.`;
13726
- } else if (result2.isRoot === false) {
13727
- const leadName = await displayName(result2.ownerRoleId) ?? result2.ownerRoleId;
13728
- message = `Declined and escalated to ${leadName}.`;
13729
- } else if (result2.suggestedRoleId) {
13730
- const roleName = await displayName(result2.suggestedRoleId) ?? result2.suggestedRoleId;
13731
- message = `Passed. ${entryId} is now suggested to ${roleName}.`;
13732
- } else if (result2.ownerRoleId) {
13733
- const leadName = await displayName(result2.ownerRoleId) ?? result2.ownerRoleId;
13734
- message = `Passed. Nobody else here owns this, so it has gone to ${leadName}.`;
13735
- } else {
13736
- message = "Declined.";
13737
- }
13635
+ const resolvedToRoleId = await resolveEntryRef(toRole, "Role");
13636
+ const result2 = await kernelMutation("question.assign", { entryId: resolvedEntryId, toRoleId: resolvedToRoleId });
13637
+ const who = await displayName(result2.ownerRoleId) ?? result2.ownerRoleId ?? "the target";
13638
+ const message = `${entryId} reassigned to ${who}. They'll see it at their next session.`;
13738
13639
  return successResult(message, message, result2);
13739
13640
  } catch (err) {
13740
- return questionErrorResult(err, "decline", { entryId, reason });
13641
+ return questionErrorResult(err, "assign", { entryId, toRole });
13741
13642
  }
13742
13643
  }
13743
13644
  async function handleQuestionAnswer(entryId, text, answerEntryId) {
@@ -13754,7 +13655,7 @@ async function handleQuestionAnswer(entryId, text, answerEntryId) {
13754
13655
  const result2 = await kernelMutation("question.answer", { entryId: resolvedEntryId, text, answerEntryId: resolvedAnswerEntryId });
13755
13656
  const askerName = (result2.askerName ? stripControlChars(result2.askerName) : "") || "The asker";
13756
13657
  const pendingNote = result2.answerPending ? " The answer is a draft awaiting accept." : "";
13757
- const message = result2.idempotent ? result2.processedVia === "declined" || result2.processedVia === "force_closed" ? `${entryId} is already processed (${result2.processedVia === "declined" ? "declined" : "force-closed"}) \u2014 no change.` : `${entryId} is already answered \u2014 no change.` : `Answered. ${askerName} will see the outcome at their next session (and in pb question list --mine).${pendingNote}`;
13658
+ const message = result2.idempotent ? result2.processedVia === "force_closed" ? `${entryId} is already processed (force-closed) \u2014 no change.` : result2.processedVia === "declined" ? `${entryId} is already processed (declined) \u2014 no change.` : `${entryId} is already answered \u2014 no change.` : `Answered. ${askerName} will see the outcome at their next session (and in pb question list --mine).${pendingNote}`;
13758
13659
  return successResult(message, message, result2);
13759
13660
  } catch (err) {
13760
13661
  return questionErrorResult(err, "answer", { entryId, text, answerEntryId });
@@ -13800,18 +13701,15 @@ function questionErrorResult(err, action, params = {}) {
13800
13701
  classified.message,
13801
13702
  classified.code,
13802
13703
  classified.message,
13803
- classified.recovery ?? "Use action='create' with no --domain, or `pb question --help` / this tool's description, to find valid domains and next steps.",
13704
+ classified.recovery ?? "Use action='create', or `pb question --help` / this tool's description, to find valid next steps.",
13804
13705
  classified.availableActions ?? fallbackActions,
13805
13706
  classified.diagnostics
13806
13707
  );
13807
13708
  }
13808
13709
  function registerQuestionTools(server) {
13809
13710
  const questionHandlers = {
13810
- create: (data) => handleQuestionCreate(data.text, data.domain, data.blocks),
13811
- adopt: (data) => handleQuestionAdopt(data.entryId, data.domain, data.blocks),
13812
- assign: (data) => handleQuestionAssign(data.entryId, data.toRole, data.toPerson),
13813
- snooze: (data) => handleQuestionSnooze(data.entryId),
13814
- decline: (data) => handleQuestionDecline(data.entryId, data.reason),
13711
+ create: (data) => handleQuestionCreate(data.text, data.blocks),
13712
+ assign: (data) => handleQuestionAssign(data.entryId, data.toRole),
13815
13713
  answer: (data) => handleQuestionAnswer(data.entryId, data.text, data.answerEntryId),
13816
13714
  "force-close": (data) => handleQuestionForceClose(data.entryId, data.reason),
13817
13715
  list: (data) => handleQuestionList(data.mine)
@@ -13820,7 +13718,7 @@ function registerQuestionTools(server) {
13820
13718
  "question",
13821
13719
  {
13822
13720
  title: "Question",
13823
- description: "Routed questions \u2014 a question with no owner routes itself to the owning role, the team lead when ambiguous, and up the team-lead chain until someone owns it. Eight actions:\n\n- **create**: create a new routed question from text. Domains are discovered by using this tool \u2014 an unresolvable `domain` refusal lists the workspace's real slugs; there is no fixed list to memorize.\n- **adopt**: adopt attaches routing to an existing tension or repairs a facet-less question \u2014 create is the birth path. Without adopt, a tension captured via `capture` with `collection: tensions` stays invisible to routing forever.\n- **assign**: confirm ('take it', no `toRole`/`toPerson`) or reassign (`toRole`/`toPerson`) ownership.\n- **snooze**: defer a routed/escalated question \u2014 max 2, then it escalates to the team lead.\n- **decline**: pass on a suggested question (never closes it), or \u2014 as the owner/team lead \u2014 decline an owned one (reason required; closes it, or escalates it, depending on dependents).\n- **answer**: close the loop. Creates the answering entry itself from `text`, or points at an existing one via `answerEntryId` \u2014 never both.\n- **force-close**: Team-Lead-only escape hatch (reason required) for a question that cannot otherwise be resolved.\n- **list**: the ack-gate read model \u2014 what you owe (`mine:false`, the default), or (`mine:true`) every question you asked, including closed ones, with its outcome.\n\n`blocks` (repeatable, on create/adopt) records what a question is holding up \u2014 pass entry ids it blocks.",
13721
+ description: "Routed questions \u2014 a question is born with no owner and escalates straight to the team lead; the team lead reassigns it to a role. Five actions:\n\n- **create**: create a new routed question from text. Always born escalated to the team lead \u2014 there is no domain-owner suggestion any more.\n- **assign**: reassign ownership to a role (`toRole` required \u2014 no self-confirm, no person-only reassignment).\n- **answer**: close the loop. Creates the answering entry itself from `text`, or points at an existing one via `answerEntryId` \u2014 never both.\n- **force-close**: Team-Lead-only escape hatch (reason required) for a question that cannot otherwise be resolved.\n- **list**: the ack-gate read model \u2014 what you owe (`mine:false`, the default), or (`mine:true`) every question you asked, including closed ones, with its outcome.\n\n`blocks` (repeatable, on create) records what a question is holding up \u2014 pass entry ids it blocks.",
13824
13722
  inputSchema: questionSchema,
13825
13723
  annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false }
13826
13724
  },
@@ -14190,7 +14088,7 @@ var AGENT_CHEATSHEET = `# Product Brain \u2014 Agent Cheatsheet
14190
14088
  | \`workspace\` | Check / whoami / status / self-test, usage, governance proposals | \`action\`: check, whoami, status, audit, self-test, usage, proposals-* |
14191
14089
  | \`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 |
14192
14090
  | \`shape\` | Review / disposition write-shape (single-concern split) advisories | \`action\`: list, show, agree, dismiss |
14193
- | \`question\` | Routed questions \u2014 create/adopt, own, snooze, decline, answer, force-close, list | \`action\`: create, adopt, assign, snooze, decline, answer, force-close, list |
14091
+ | \`question\` | Routed questions \u2014 create, reassign, answer, force-close, list | \`action\`: create, assign, answer, force-close, list |
14194
14092
  | \`role\` | What a role is accountable for \u2014 owns, reports on, and (not yet computed) inherits via Team-Lead vacancy coverage | \`action\`: accountable |
14195
14093
  | \`outcome\` | Record an outcome measurement and read the ones already recorded | \`action\`: record, list, show |
14196
14094
 
@@ -14990,4 +14888,4 @@ export {
14990
14888
  createProductBrainServer,
14991
14889
  initFeatureFlags
14992
14890
  };
14993
- //# sourceMappingURL=chunk-ONWBWDTM.js.map
14891
+ //# sourceMappingURL=chunk-CPOQXPOQ.js.map