@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.
- package/dist/{chunk-ONWBWDTM.js → chunk-CPOQXPOQ.js} +32 -134
- package/dist/{chunk-ONWBWDTM.js.map → chunk-CPOQXPOQ.js.map} +1 -1
- package/dist/{chunk-2RHVPN24.js → chunk-SU5XEDCF.js} +1 -4
- package/dist/chunk-SU5XEDCF.js.map +1 -0
- package/dist/cli/index.js +1 -1
- package/dist/http.js +2 -2
- package/dist/index.js +2 -2
- package/dist/{setup-XUZMANEX.js → setup-UNAVGLP5.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-2RHVPN24.js.map +0 -1
- /package/dist/{setup-XUZMANEX.js.map → setup-UNAVGLP5.js.map} +0 -0
|
@@ -41,7 +41,7 @@ import {
|
|
|
41
41
|
trackSessionCaptureRate,
|
|
42
42
|
trackWriteBackHintServed,
|
|
43
43
|
trackZeroCaptureAuditFired
|
|
44
|
-
} from "./chunk-
|
|
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", "
|
|
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
|
|
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
|
-
|
|
13582
|
-
|
|
13583
|
-
|
|
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),
|
|
13590
|
-
var
|
|
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", "
|
|
13609
|
-
|
|
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
|
|
13634
|
-
|
|
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}${
|
|
13618
|
+
return `${base}${blocksHint}${nudge}`;
|
|
13653
13619
|
}
|
|
13654
|
-
async function handleQuestionCreate(text,
|
|
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,
|
|
13659
|
-
const message = await
|
|
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, "
|
|
13628
|
+
return questionErrorResult(err, "create", { text, blocks });
|
|
13676
13629
|
}
|
|
13677
13630
|
}
|
|
13678
|
-
async function handleQuestionAssign(entryId, toRole
|
|
13631
|
+
async function handleQuestionAssign(entryId, toRole) {
|
|
13679
13632
|
requireWriteAccess();
|
|
13680
13633
|
try {
|
|
13681
13634
|
const resolvedEntryId = await resolveEntryRef(entryId, "Entry");
|
|
13682
|
-
const resolvedToRoleId =
|
|
13683
|
-
const result2 = await kernelMutation("question.assign", { entryId: resolvedEntryId, toRoleId: resolvedToRoleId
|
|
13684
|
-
const
|
|
13685
|
-
|
|
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, "
|
|
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 === "
|
|
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'
|
|
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.
|
|
13811
|
-
|
|
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
|
|
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
|
|
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-
|
|
14891
|
+
//# sourceMappingURL=chunk-CPOQXPOQ.js.map
|