@productbrain/mcp 0.0.1-beta.4721 → 0.0.1-beta.4732
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.
|
@@ -410,7 +410,8 @@ var TOOL_NAME_MIGRATIONS = /* @__PURE__ */ new Map([
|
|
|
410
410
|
["workflow-checkpoint", 'workflows action="checkpoint"'],
|
|
411
411
|
["wrapup", 'session action="wrapup-review"'],
|
|
412
412
|
["finish", 'session action="wrapup-review"'],
|
|
413
|
-
// ─── WP-484 S3 clean break: the
|
|
413
|
+
// ─── WP-484 S3 clean break: the 21 retiring standalone tool names ────────
|
|
414
|
+
// (WP-687 S2 retired the map tool and its 4 migration rows below.)
|
|
414
415
|
// Multi-action retired tools map to the FULL action menu (pipe / wildcard
|
|
415
416
|
// form), never a single default action: the coach only matches the retired
|
|
416
417
|
// NAME, so historical text like `facilitate action=commit-constellation`
|
|
@@ -436,11 +437,7 @@ var TOOL_NAME_MIGRATIONS = /* @__PURE__ */ new Map([
|
|
|
436
437
|
["audit", 'quality action="audit"'],
|
|
437
438
|
["governance-proposals", 'workspace action="proposals-list|proposals-respond|proposals-count" (list/respond/count \u2192 proposals-<same>)'],
|
|
438
439
|
["chain-version", 'chain action="version.*" (commit/list/diff/revert/history \u2192 version.<same>)'],
|
|
439
|
-
["chain-branch", 'chain-review action="branch.*" (create/list/merge/conflicts \u2192 branch.<same>)']
|
|
440
|
-
["create-audience-map-set", 'map action="create-audience-set"'],
|
|
441
|
-
["map-slot", 'map action="slot.*" (add/remove/replace/list \u2192 slot.<same>)'],
|
|
442
|
-
["map-version", 'map action="version.*" (commit/list/history \u2192 version.<same>)'],
|
|
443
|
-
["map-suggest", 'map action="suggest"']
|
|
440
|
+
["chain-branch", 'chain-review action="branch.*" (create/list/merge/conflicts \u2192 branch.<same>)']
|
|
444
441
|
]);
|
|
445
442
|
function translateStaleToolNames(text) {
|
|
446
443
|
const found = [];
|
|
@@ -6578,7 +6575,7 @@ async function handleJourneyGather(server, mapEntryId, maxHops, maxResults) {
|
|
|
6578
6575
|
|
|
6579
6576
|
_No ingredients found in this journey map._
|
|
6580
6577
|
|
|
6581
|
-
Add journey steps
|
|
6578
|
+
Add journey steps in Cortex \u2014 the \`map\` MCP tool is no longer available.`
|
|
6582
6579
|
}],
|
|
6583
6580
|
structuredContent: success(
|
|
6584
6581
|
`Journey map ${result2.map.name} has no ingredients.`,
|
|
@@ -14243,528 +14240,11 @@ function registerGitChainTools(server) {
|
|
|
14243
14240
|
);
|
|
14244
14241
|
}
|
|
14245
14242
|
|
|
14246
|
-
// src/tools/maps.ts
|
|
14247
|
-
import { z as z28 } from "zod/v3";
|
|
14248
|
-
var createAudienceMapSetSchema = z28.object({
|
|
14249
|
-
audienceEntryId: z28.string().max(200).describe("Entry ID of the audience (e.g. STR-fb7hje)"),
|
|
14250
|
-
// WP-513: team+role to create AS OWNER of (rung 2); ID or entryId (e.g. "TEAM-1"); no-op pre-rung-2.
|
|
14251
|
-
ownerTeamEntryId: z28.string().max(200).optional().describe("Team entry ID/ref to own the created maps (required once the workspace is on rung 2)"),
|
|
14252
|
-
ownerRoleEntryId: z28.string().max(200).optional().describe("Role entry ID/ref to own the created maps (required once the workspace is on rung 2)")
|
|
14253
|
-
});
|
|
14254
|
-
var mapSchema = z28.object({
|
|
14255
|
-
action: z28.enum(["create", "get", "list"]).describe("Action: create a map, get map details, or list all maps"),
|
|
14256
|
-
mapEntryId: z28.string().max(200).optional().describe("Map entry ID (for get)"),
|
|
14257
|
-
title: z28.string().max(500).optional().describe("Map title (for create)"),
|
|
14258
|
-
templateId: z28.string().max(200).optional().default("lean-canvas").describe("Template slug for create: 'lean-canvas' or any composed template"),
|
|
14259
|
-
description: z28.string().max(2e4).optional().describe("Description (for create)"),
|
|
14260
|
-
slotIds: z28.array(z28.string().max(200)).max(200).optional().describe("Slot IDs to initialize (for create; auto-populated from template if omitted)"),
|
|
14261
|
-
status: z28.string().max(200).optional().describe("Filter by status for list"),
|
|
14262
|
-
// WP-513: team+role to create AS OWNER of (rung 2, action "create" only); no-op pre-rung-2.
|
|
14263
|
-
ownerTeamEntryId: z28.string().max(200).optional().describe("Team entry ID/ref to own the created map (required once the workspace is on rung 2)"),
|
|
14264
|
-
ownerRoleEntryId: z28.string().max(200).optional().describe("Role entry ID/ref to own the created map (required once the workspace is on rung 2)")
|
|
14265
|
-
});
|
|
14266
|
-
var mapSlotSchema = z28.object({
|
|
14267
|
-
action: z28.enum(["add", "remove", "replace", "list"]).describe("Action: add/remove/replace an ingredient in a slot, or list slot contents"),
|
|
14268
|
-
mapEntryId: z28.string().max(200).describe("Map entry ID"),
|
|
14269
|
-
slotId: z28.string().max(200).optional().describe("Slot ID (e.g. 'problem', 'customer-segments')"),
|
|
14270
|
-
ingredientEntryId: z28.string().max(200).optional().describe("Ingredient entry ID to add/remove"),
|
|
14271
|
-
newIngredientEntryId: z28.string().max(200).optional().describe("New ingredient entry ID (for replace)"),
|
|
14272
|
-
label: z28.string().max(500).optional().describe("Display label override"),
|
|
14273
|
-
author: z28.string().max(200).optional().describe("Who is performing the action")
|
|
14274
|
-
});
|
|
14275
|
-
var mapVersionSchema = z28.object({
|
|
14276
|
-
action: z28.enum(["commit", "list", "history"]).describe("Action: commit the map, list commits, or view commit history"),
|
|
14277
|
-
mapEntryId: z28.string().max(200).describe("Map entry ID"),
|
|
14278
|
-
commitMessage: z28.string().max(2e3).optional().describe("Commit message (for commit action)"),
|
|
14279
|
-
author: z28.string().max(200).optional().describe("Who is committing")
|
|
14280
|
-
});
|
|
14281
|
-
var mapSuggestSchema = z28.object({
|
|
14282
|
-
mapEntryId: z28.string().max(200).describe("Map entry ID to suggest ingredients for"),
|
|
14283
|
-
slotId: z28.string().max(200).optional().describe("Specific slot to find ingredients for (or all empty slots)"),
|
|
14284
|
-
query: z28.string().max(500).optional().describe("Optional search query to narrow ingredient suggestions")
|
|
14285
|
-
});
|
|
14286
|
-
function slotSummary(slots) {
|
|
14287
|
-
return Object.entries(slots).map(([id, refs]) => {
|
|
14288
|
-
if (!refs || refs.length === 0) return ` - **${id}**: (empty)`;
|
|
14289
|
-
const items = refs.map((r) => {
|
|
14290
|
-
const name = r.ingredientName ?? r.label ?? r.entryId;
|
|
14291
|
-
const version = r.pinnedVersion ? ` v${r.pinnedVersion}` : "";
|
|
14292
|
-
const status2 = r.ingredientStatus ? ` [${r.ingredientStatus}]` : "";
|
|
14293
|
-
return `${name}${version}${status2}`;
|
|
14294
|
-
}).join(", ");
|
|
14295
|
-
return ` - **${id}**: ${items}`;
|
|
14296
|
-
}).join("\n");
|
|
14297
|
-
}
|
|
14298
|
-
async function handleCreateAudienceMapSet({ audienceEntryId, ownerTeamEntryId, ownerRoleEntryId }) {
|
|
14299
|
-
const result2 = await kernelMutation(
|
|
14300
|
-
"maps.createAudienceMapSet",
|
|
14301
|
-
{ audienceEntryId, ownerTeamEntryId, ownerRoleEntryId }
|
|
14302
|
-
);
|
|
14303
|
-
const wsCtx = await getWorkspaceContext();
|
|
14304
|
-
const lines = result2.maps.map(
|
|
14305
|
-
(m) => `- **${m.templateId}**: \`${m.mapEntryId}\``
|
|
14306
|
-
);
|
|
14307
|
-
return {
|
|
14308
|
-
content: [
|
|
14309
|
-
{
|
|
14310
|
-
type: "text",
|
|
14311
|
-
text: `# Audience Map Set Created
|
|
14312
|
-
|
|
14313
|
-
**Audience:** \`${result2.audienceEntryId}\`
|
|
14314
|
-
**Workspace:** ${wsCtx.workspaceSlug}
|
|
14315
|
-
|
|
14316
|
-
## Maps
|
|
14317
|
-
|
|
14318
|
-
${lines.join("\n")}
|
|
14319
|
-
|
|
14320
|
-
Use map action=slot.add to add ingredients. View at /empathy, /narrowing, and /jobs.`
|
|
14321
|
-
}
|
|
14322
|
-
],
|
|
14323
|
-
structuredContent: success(
|
|
14324
|
-
`Created ${result2.maps.length} audience maps for ${result2.audienceEntryId}.`,
|
|
14325
|
-
{ audienceEntryId: result2.audienceEntryId, maps: result2.maps },
|
|
14326
|
-
result2.maps.map((m) => ({
|
|
14327
|
-
tool: "map",
|
|
14328
|
-
description: `Add ingredients to ${m.templateId}`,
|
|
14329
|
-
parameters: { action: "slot.add", mapEntryId: m.mapEntryId }
|
|
14330
|
-
}))
|
|
14331
|
-
)
|
|
14332
|
-
};
|
|
14333
|
-
}
|
|
14334
|
-
async function handleMapCrud({ action, mapEntryId, title, templateId, description, slotIds, status: status2, ownerTeamEntryId, ownerRoleEntryId }) {
|
|
14335
|
-
if (action === "create") {
|
|
14336
|
-
if (!title) {
|
|
14337
|
-
return validationResult("A `title` is required to create a map.");
|
|
14338
|
-
}
|
|
14339
|
-
const result2 = await kernelMutation(
|
|
14340
|
-
"maps.createMap",
|
|
14341
|
-
{ title, templateId, description, slotIds, ownerTeamEntryId, ownerRoleEntryId }
|
|
14342
|
-
);
|
|
14343
|
-
const wsCtx = await getWorkspaceContext();
|
|
14344
|
-
return {
|
|
14345
|
-
content: [
|
|
14346
|
-
{
|
|
14347
|
-
type: "text",
|
|
14348
|
-
text: `# Map Created
|
|
14349
|
-
|
|
14350
|
-
- **Entry ID:** \`${result2.entryId}\`
|
|
14351
|
-
- **Title:** ${title}
|
|
14352
|
-
- **Template:** ${templateId}
|
|
14353
|
-
- **Status:** draft
|
|
14354
|
-
- **Workspace:** ${wsCtx.workspaceSlug} (${wsCtx.workspaceId})
|
|
14355
|
-
|
|
14356
|
-
Use \`map action=slot.add mapEntryId="${result2.entryId}" slotId="problem" ingredientEntryId="..."\` to start filling slots.`
|
|
14357
|
-
}
|
|
14358
|
-
],
|
|
14359
|
-
structuredContent: success(
|
|
14360
|
-
`Created map '${title}' (${result2.entryId}) using ${templateId} template.`,
|
|
14361
|
-
{ entryId: result2.entryId, title, templateId, status: "draft" },
|
|
14362
|
-
[{ tool: "map", description: "Add ingredient to slot", parameters: { action: "slot.add", mapEntryId: result2.entryId } }]
|
|
14363
|
-
)
|
|
14364
|
-
};
|
|
14365
|
-
}
|
|
14366
|
-
if (action === "get") {
|
|
14367
|
-
if (!mapEntryId) {
|
|
14368
|
-
return validationResult("A `mapEntryId` is required.");
|
|
14369
|
-
}
|
|
14370
|
-
const map = await kernelQuery("maps.getMap", { mapEntryId });
|
|
14371
|
-
if (!map) {
|
|
14372
|
-
return {
|
|
14373
|
-
content: [{ type: "text", text: `Map "${mapEntryId}" not found.` }],
|
|
14374
|
-
structuredContent: failure(
|
|
14375
|
-
"NOT_FOUND",
|
|
14376
|
-
`Map "${mapEntryId}" not found.`,
|
|
14377
|
-
"Use map action=list to find available maps.",
|
|
14378
|
-
[{ tool: "map", description: "List maps", parameters: { action: "list" } }]
|
|
14379
|
-
)
|
|
14380
|
-
};
|
|
14381
|
-
}
|
|
14382
|
-
return {
|
|
14383
|
-
content: [
|
|
14384
|
-
{
|
|
14385
|
-
type: "text",
|
|
14386
|
-
text: `# ${map.name}
|
|
14387
|
-
|
|
14388
|
-
- **Entry ID:** \`${map.entryId}\`
|
|
14389
|
-
- **Template:** ${map.templateName}
|
|
14390
|
-
- **Status:** ${map.status}
|
|
14391
|
-
- **Version:** ${toVersionDisplay(map.currentVersion)}
|
|
14392
|
-
- **Completion:** ${map.completionScore}% (${map.filledSlots}/${map.totalSlots} slots)
|
|
14393
|
-
|
|
14394
|
-
## Slots
|
|
14395
|
-
|
|
14396
|
-
` + slotSummary(map.slots)
|
|
14397
|
-
}
|
|
14398
|
-
],
|
|
14399
|
-
structuredContent: success(
|
|
14400
|
-
`${map.name}: ${map.completionScore}% complete (${map.filledSlots}/${map.totalSlots} slots), ${toVersionDisplay(map.currentVersion)}.`,
|
|
14401
|
-
{ entryId: map.entryId, name: map.name, templateName: map.templateName, status: map.status, completionScore: map.completionScore, filledSlots: map.filledSlots, totalSlots: map.totalSlots, version: map.currentVersion ?? null, versionDisplay: toVersionDisplay(map.currentVersion) },
|
|
14402
|
-
[{ tool: "map", description: "Manage slot ingredients", parameters: { action: "slot.list", mapEntryId } }]
|
|
14403
|
-
)
|
|
14404
|
-
};
|
|
14405
|
-
}
|
|
14406
|
-
if (action === "list") {
|
|
14407
|
-
const maps = await kernelQuery("maps.listMaps", {
|
|
14408
|
-
templateId: templateId !== "lean-canvas" ? templateId : void 0,
|
|
14409
|
-
status: status2
|
|
14410
|
-
});
|
|
14411
|
-
if (!maps || maps.length === 0) {
|
|
14412
|
-
return {
|
|
14413
|
-
content: [{ type: "text", text: 'No maps found. Create one with `map action=create title="My Canvas"`.' }],
|
|
14414
|
-
structuredContent: success(
|
|
14415
|
-
"No maps found.",
|
|
14416
|
-
{ maps: [], total: 0 },
|
|
14417
|
-
[{ tool: "map", description: "Create a map", parameters: { action: "create" } }]
|
|
14418
|
-
)
|
|
14419
|
-
};
|
|
14420
|
-
}
|
|
14421
|
-
const lines = maps.map(
|
|
14422
|
-
(m) => `- **${m.name}** (\`${m.entryId}\`) \u2014 ${m.templateId}, ${m.completionScore}% complete, ${toVersionDisplay(m.currentVersion)}`
|
|
14423
|
-
);
|
|
14424
|
-
return {
|
|
14425
|
-
content: [{ type: "text", text: `# Maps (${maps.length})
|
|
14426
|
-
|
|
14427
|
-
${lines.join("\n")}` }],
|
|
14428
|
-
structuredContent: success(
|
|
14429
|
-
`Found ${maps.length} map(s).`,
|
|
14430
|
-
{ maps: maps.map((m) => ({ entryId: m.entryId, name: m.name, templateId: m.templateId, completionScore: m.completionScore })), total: maps.length }
|
|
14431
|
-
)
|
|
14432
|
-
};
|
|
14433
|
-
}
|
|
14434
|
-
return unknownAction(action, ["create", "get", "list"]);
|
|
14435
|
-
}
|
|
14436
|
-
async function handleMapSlot({
|
|
14437
|
-
action,
|
|
14438
|
-
mapEntryId,
|
|
14439
|
-
slotId,
|
|
14440
|
-
ingredientEntryId,
|
|
14441
|
-
newIngredientEntryId,
|
|
14442
|
-
label,
|
|
14443
|
-
author
|
|
14444
|
-
}) {
|
|
14445
|
-
if (action === "list") {
|
|
14446
|
-
const map = await kernelQuery("maps.getMap", { mapEntryId });
|
|
14447
|
-
if (!map) {
|
|
14448
|
-
return {
|
|
14449
|
-
content: [{ type: "text", text: `Map "${mapEntryId}" not found.` }],
|
|
14450
|
-
structuredContent: failure(
|
|
14451
|
-
"NOT_FOUND",
|
|
14452
|
-
`Map "${mapEntryId}" not found.`,
|
|
14453
|
-
"Use map action=list to find available maps.",
|
|
14454
|
-
[{ tool: "map", description: "List maps", parameters: { action: "list" } }]
|
|
14455
|
-
)
|
|
14456
|
-
};
|
|
14457
|
-
}
|
|
14458
|
-
if (slotId && map.slots[slotId]) {
|
|
14459
|
-
const refs = map.slots[slotId];
|
|
14460
|
-
return {
|
|
14461
|
-
content: [
|
|
14462
|
-
{
|
|
14463
|
-
type: "text",
|
|
14464
|
-
text: `# Slot: ${slotId}
|
|
14465
|
-
|
|
14466
|
-
` + (refs.length === 0 ? "(empty)" : refs.map(
|
|
14467
|
-
(r) => `- **${r.ingredientName ?? r.entryId}** (\`${r.entryId}\`)${r.pinnedVersion ? ` v${r.pinnedVersion}` : ""}`
|
|
14468
|
-
).join("\n"))
|
|
14469
|
-
}
|
|
14470
|
-
],
|
|
14471
|
-
structuredContent: success(
|
|
14472
|
-
refs.length === 0 ? `Slot "${slotId}" is empty.` : `Slot "${slotId}": ${refs.length} ingredient(s).`,
|
|
14473
|
-
{ mapEntryId, slotId, ingredients: refs, count: refs.length }
|
|
14474
|
-
)
|
|
14475
|
-
};
|
|
14476
|
-
}
|
|
14477
|
-
return {
|
|
14478
|
-
content: [{ type: "text", text: `## All Slots
|
|
14479
|
-
|
|
14480
|
-
${slotSummary(map.slots)}` }],
|
|
14481
|
-
structuredContent: success(
|
|
14482
|
-
`${map.name}: ${Object.keys(map.slots).length} slots.`,
|
|
14483
|
-
{ mapEntryId, slotCount: Object.keys(map.slots).length }
|
|
14484
|
-
)
|
|
14485
|
-
};
|
|
14486
|
-
}
|
|
14487
|
-
if (action === "add") {
|
|
14488
|
-
if (!slotId || !ingredientEntryId) {
|
|
14489
|
-
return validationResult("Both `slotId` and `ingredientEntryId` are required for add.");
|
|
14490
|
-
}
|
|
14491
|
-
await kernelMutation("maps.addToSlot", { mapEntryId, slotId, ingredientEntryId, label, author });
|
|
14492
|
-
return {
|
|
14493
|
-
content: [{ type: "text", text: `Added \`${ingredientEntryId}\` to slot "${slotId}" on map \`${mapEntryId}\`.` }],
|
|
14494
|
-
structuredContent: success(
|
|
14495
|
-
`Added ${ingredientEntryId} to slot "${slotId}".`,
|
|
14496
|
-
{ mapEntryId, slotId, ingredientEntryId },
|
|
14497
|
-
[{ tool: "map", description: "View updated map", parameters: { action: "get", mapEntryId } }]
|
|
14498
|
-
)
|
|
14499
|
-
};
|
|
14500
|
-
}
|
|
14501
|
-
if (action === "remove") {
|
|
14502
|
-
if (!slotId || !ingredientEntryId) {
|
|
14503
|
-
return validationResult("Both `slotId` and `ingredientEntryId` are required for remove.");
|
|
14504
|
-
}
|
|
14505
|
-
await kernelMutation("maps.removeFromSlot", { mapEntryId, slotId, ingredientEntryId, author });
|
|
14506
|
-
return {
|
|
14507
|
-
content: [{ type: "text", text: `Removed \`${ingredientEntryId}\` from slot "${slotId}" on map \`${mapEntryId}\`.` }],
|
|
14508
|
-
structuredContent: success(
|
|
14509
|
-
`Removed ${ingredientEntryId} from slot "${slotId}".`,
|
|
14510
|
-
{ mapEntryId, slotId, ingredientEntryId },
|
|
14511
|
-
[{ tool: "map", description: "View updated map", parameters: { action: "get", mapEntryId } }]
|
|
14512
|
-
)
|
|
14513
|
-
};
|
|
14514
|
-
}
|
|
14515
|
-
if (action === "replace") {
|
|
14516
|
-
if (!slotId || !ingredientEntryId || !newIngredientEntryId) {
|
|
14517
|
-
return validationResult("`slotId`, `ingredientEntryId`, and `newIngredientEntryId` are required for replace.");
|
|
14518
|
-
}
|
|
14519
|
-
await kernelMutation("maps.replaceInSlot", { mapEntryId, slotId, oldIngredientEntryId: ingredientEntryId, newIngredientEntryId, label, author });
|
|
14520
|
-
return {
|
|
14521
|
-
content: [{ type: "text", text: `Replaced \`${ingredientEntryId}\` with \`${newIngredientEntryId}\` in slot "${slotId}".` }],
|
|
14522
|
-
structuredContent: success(
|
|
14523
|
-
`Replaced ${ingredientEntryId} with ${newIngredientEntryId} in slot "${slotId}".`,
|
|
14524
|
-
{ mapEntryId, slotId, removed: ingredientEntryId, added: newIngredientEntryId },
|
|
14525
|
-
[{ tool: "map", description: "View updated map", parameters: { action: "get", mapEntryId } }]
|
|
14526
|
-
)
|
|
14527
|
-
};
|
|
14528
|
-
}
|
|
14529
|
-
return unknownAction(action, ["add", "remove", "replace", "list"]);
|
|
14530
|
-
}
|
|
14531
|
-
async function handleMapVersion({ action, mapEntryId, commitMessage, author }) {
|
|
14532
|
-
if (action === "commit") {
|
|
14533
|
-
const result2 = await kernelMutation("maps.commitMap", {
|
|
14534
|
-
mapEntryId,
|
|
14535
|
-
commitMessage: commitMessage ?? "Map committed",
|
|
14536
|
-
author
|
|
14537
|
-
});
|
|
14538
|
-
return {
|
|
14539
|
-
content: [
|
|
14540
|
-
{
|
|
14541
|
-
type: "text",
|
|
14542
|
-
text: `# Map Committed
|
|
14543
|
-
|
|
14544
|
-
- **Version:** ${result2.version}
|
|
14545
|
-
- **Completion:** ${result2.completionScore}%
|
|
14546
|
-
- **Slots modified:** ${result2.slotsModified.length > 0 ? result2.slotsModified.join(", ") : "(none)"}
|
|
14547
|
-
|
|
14548
|
-
All ingredient references have been pinned at their current versions.`
|
|
14549
|
-
}
|
|
14550
|
-
],
|
|
14551
|
-
structuredContent: success(
|
|
14552
|
-
`Committed map ${mapEntryId} at v${result2.version} (${result2.completionScore}% complete).`,
|
|
14553
|
-
{ mapEntryId, version: result2.version, versionDisplay: toVersionDisplay(result2.version), completionScore: result2.completionScore, slotsModified: result2.slotsModified }
|
|
14554
|
-
)
|
|
14555
|
-
};
|
|
14556
|
-
}
|
|
14557
|
-
if (action === "list" || action === "history") {
|
|
14558
|
-
const commits = await kernelQuery("maps.listMapCommits", { mapEntryId });
|
|
14559
|
-
if (!commits || commits.length === 0) {
|
|
14560
|
-
return {
|
|
14561
|
-
content: [{ type: "text", text: `No commits yet for map \`${mapEntryId}\`. Use \`map action=version.commit\` to create the first snapshot.` }],
|
|
14562
|
-
structuredContent: success(
|
|
14563
|
-
`No commits yet for ${mapEntryId}.`,
|
|
14564
|
-
{ mapEntryId, commits: [], total: 0 },
|
|
14565
|
-
[{ tool: "map", description: "Commit the map", parameters: { action: "version.commit", mapEntryId } }]
|
|
14566
|
-
)
|
|
14567
|
-
};
|
|
14568
|
-
}
|
|
14569
|
-
const lines = commits.map(
|
|
14570
|
-
(c) => `- **v${c.version}** (${new Date(c.createdAt).toLocaleDateString()}) \u2014 ${c.commitMessage ?? "(no message)"} \u2014 by ${c.author}` + (c.slotsModified.length > 0 ? `
|
|
14571
|
-
Slots changed: ${c.slotsModified.join(", ")}` : "")
|
|
14572
|
-
);
|
|
14573
|
-
return {
|
|
14574
|
-
content: [{ type: "text", text: `# Map History: \`${mapEntryId}\` (${commits.length} commits)
|
|
14575
|
-
|
|
14576
|
-
${lines.join("\n")}` }],
|
|
14577
|
-
structuredContent: success(
|
|
14578
|
-
`${commits.length} commit(s) for ${mapEntryId}.`,
|
|
14579
|
-
{ mapEntryId, total: commits.length }
|
|
14580
|
-
)
|
|
14581
|
-
};
|
|
14582
|
-
}
|
|
14583
|
-
return unknownAction(action, ["commit", "list", "history"]);
|
|
14584
|
-
}
|
|
14585
|
-
async function handleMapSuggest({ mapEntryId, slotId, query }) {
|
|
14586
|
-
const map = await kernelQuery("maps.getMap", { mapEntryId });
|
|
14587
|
-
if (!map) {
|
|
14588
|
-
return {
|
|
14589
|
-
content: [{ type: "text", text: `Map "${mapEntryId}" not found.` }],
|
|
14590
|
-
structuredContent: failure(
|
|
14591
|
-
"NOT_FOUND",
|
|
14592
|
-
`Map "${mapEntryId}" not found.`,
|
|
14593
|
-
"Use map action=list to find available maps.",
|
|
14594
|
-
[{ tool: "map", description: "List maps", parameters: { action: "list" } }]
|
|
14595
|
-
)
|
|
14596
|
-
};
|
|
14597
|
-
}
|
|
14598
|
-
const emptySlots = slotId ? [slotId].filter((id) => (map.slots[id]?.length ?? 0) === 0) : Object.entries(map.slots).filter(([, refs]) => refs.length === 0).map(([id]) => id);
|
|
14599
|
-
if (emptySlots.length === 0) {
|
|
14600
|
-
const msg = slotId ? `Slot "${slotId}" already has ingredients.` : "All slots have ingredients. Nothing to suggest.";
|
|
14601
|
-
return {
|
|
14602
|
-
content: [{ type: "text", text: msg }],
|
|
14603
|
-
structuredContent: success(msg, { mapEntryId, emptySlots: 0 })
|
|
14604
|
-
};
|
|
14605
|
-
}
|
|
14606
|
-
const slotDefs = map.slotDefs ?? [];
|
|
14607
|
-
const suggestions = [];
|
|
14608
|
-
for (const sid of emptySlots) {
|
|
14609
|
-
const def = slotDefs.find((s) => s.id === sid);
|
|
14610
|
-
const searchQuery = query ?? def?.label ?? sid;
|
|
14611
|
-
const allResults = await kernelQuery("chain.searchEntries", {
|
|
14612
|
-
query: searchQuery
|
|
14613
|
-
});
|
|
14614
|
-
const results = (allResults ?? []).filter((r) => r.entryId != null).slice(0, 5);
|
|
14615
|
-
if (results.length > 0) {
|
|
14616
|
-
const items = results.map(
|
|
14617
|
-
(r) => ` - **${r.name}** (\`${r.entryId}\`, ${r.collectionSlug ?? "unknown"}) \u2014 ${r.status}`
|
|
14618
|
-
);
|
|
14619
|
-
suggestions.push(
|
|
14620
|
-
`### ${def?.label ?? sid}
|
|
14621
|
-
${def?.description ?? ""}
|
|
14622
|
-
|
|
14623
|
-
${items.join("\n")}`
|
|
14624
|
-
);
|
|
14625
|
-
} else {
|
|
14626
|
-
suggestions.push(
|
|
14627
|
-
`### ${def?.label ?? sid}
|
|
14628
|
-
_No matching entries found. Create ingredients first._`
|
|
14629
|
-
);
|
|
14630
|
-
}
|
|
14631
|
-
}
|
|
14632
|
-
return {
|
|
14633
|
-
content: [
|
|
14634
|
-
{
|
|
14635
|
-
type: "text",
|
|
14636
|
-
text: `# Ingredient Suggestions for "${map.name}"
|
|
14637
|
-
|
|
14638
|
-
` + suggestions.join("\n\n") + `
|
|
14639
|
-
|
|
14640
|
-
Use \`map action=slot.add mapEntryId="${mapEntryId}" slotId="..." ingredientEntryId="..."\` to add ingredients.`
|
|
14641
|
-
}
|
|
14642
|
-
],
|
|
14643
|
-
structuredContent: success(
|
|
14644
|
-
`Suggestions for ${emptySlots.length} empty slot(s) on "${map.name}".`,
|
|
14645
|
-
{ mapEntryId, emptySlots: emptySlots.length },
|
|
14646
|
-
[{ tool: "map", description: "Add ingredient", parameters: { action: "slot.add", mapEntryId } }]
|
|
14647
|
-
)
|
|
14648
|
-
};
|
|
14649
|
-
}
|
|
14650
|
-
var MAP_ACTIONS = [
|
|
14651
|
-
"create",
|
|
14652
|
-
"get",
|
|
14653
|
-
"list",
|
|
14654
|
-
"slot.add",
|
|
14655
|
-
"slot.remove",
|
|
14656
|
-
"slot.replace",
|
|
14657
|
-
"slot.list",
|
|
14658
|
-
"version.commit",
|
|
14659
|
-
"version.list",
|
|
14660
|
-
"version.history",
|
|
14661
|
-
"suggest",
|
|
14662
|
-
"create-audience-set"
|
|
14663
|
-
];
|
|
14664
|
-
var mapCompoundSchema = z28.object({
|
|
14665
|
-
action: z28.enum(MAP_ACTIONS).describe(
|
|
14666
|
-
"Unnamespaced: 'create'/'get'/'list' \u2014 map CRUD (the original `map` tool). 'slot.*' (add/remove/replace/list) \u2014 ingredient slot management, absorbs `map-slot`. 'version.*' (commit/list/history) \u2014 versioning, absorbs `map-version`. 'suggest' \u2014 find ingredients to fill empty slots, absorbs `map-suggest`. 'create-audience-set' \u2014 create all three audience intelligence maps at once, absorbs `create-audience-map-set`."
|
|
14667
|
-
),
|
|
14668
|
-
mapEntryId: z28.string().max(200).optional().describe("Map entry ID. Required for get and all slot.*/version.*/suggest actions."),
|
|
14669
|
-
title: z28.string().max(500).optional().describe("For 'create': map title (required)."),
|
|
14670
|
-
templateId: z28.string().max(200).optional().default("lean-canvas").describe("For 'create': template slug."),
|
|
14671
|
-
description: z28.string().max(2e4).optional().describe("For 'create': description."),
|
|
14672
|
-
slotIds: z28.array(z28.string().max(200)).max(200).optional().describe("For 'create': slot IDs to initialize."),
|
|
14673
|
-
status: z28.string().max(200).optional().describe("For 'list': filter by status."),
|
|
14674
|
-
slotId: z28.string().max(200).optional().describe("For 'slot.add'/'slot.remove'/'slot.replace': slot ID (required). For 'suggest': specific slot (optional)."),
|
|
14675
|
-
ingredientEntryId: z28.string().max(200).optional().describe("For 'slot.add'/'slot.remove'/'slot.replace': ingredient entry ID to add/remove (required)."),
|
|
14676
|
-
newIngredientEntryId: z28.string().max(200).optional().describe("For 'slot.replace': new ingredient entry ID (required)."),
|
|
14677
|
-
label: z28.string().max(500).optional().describe("For 'slot.add'/'slot.replace': display label override."),
|
|
14678
|
-
author: z28.string().max(200).optional().describe("Who is performing the action."),
|
|
14679
|
-
commitMessage: z28.string().max(2e3).optional().describe("For 'version.commit': commit message."),
|
|
14680
|
-
query: z28.string().max(500).optional().describe("For 'suggest': search query to narrow ingredient suggestions."),
|
|
14681
|
-
audienceEntryId: z28.string().max(200).optional().describe("For 'create-audience-set': audience entry ID (required)."),
|
|
14682
|
-
// WP-513 review round 3 (P1): without these here, zod strips them before mapActionUnion ever sees them.
|
|
14683
|
-
ownerTeamEntryId: z28.string().max(200).optional().describe("For 'create'/'create-audience-set': owning team (rung-2 workspaces)."),
|
|
14684
|
-
ownerRoleEntryId: z28.string().max(200).optional().describe("For 'create'/'create-audience-set': owning role (rung-2 workspaces).")
|
|
14685
|
-
});
|
|
14686
|
-
var mapCreateVariant = mapSchema.omit({ action: true }).extend({ action: z28.literal("create") });
|
|
14687
|
-
var mapGetVariant = z28.object({ action: z28.literal("get"), mapEntryId: z28.string().max(200) });
|
|
14688
|
-
var mapListVariant = z28.object({ action: z28.literal("list"), templateId: z28.string().max(200).optional(), status: z28.string().max(200).optional() });
|
|
14689
|
-
var slotBase = mapSlotSchema.omit({ action: true });
|
|
14690
|
-
var mapSlotAddVariant = slotBase.extend({ action: z28.literal("slot.add"), slotId: z28.string().max(200), ingredientEntryId: z28.string().max(200) });
|
|
14691
|
-
var mapSlotRemoveVariant = slotBase.extend({ action: z28.literal("slot.remove"), slotId: z28.string().max(200), ingredientEntryId: z28.string().max(200) });
|
|
14692
|
-
var mapSlotReplaceVariant = slotBase.extend({ action: z28.literal("slot.replace"), slotId: z28.string().max(200), ingredientEntryId: z28.string().max(200), newIngredientEntryId: z28.string().max(200) });
|
|
14693
|
-
var mapSlotListVariant = slotBase.extend({ action: z28.literal("slot.list") });
|
|
14694
|
-
var versionBase2 = mapVersionSchema.omit({ action: true });
|
|
14695
|
-
var mapVersionCommitVariant = versionBase2.extend({ action: z28.literal("version.commit") });
|
|
14696
|
-
var mapVersionListVariant = versionBase2.extend({ action: z28.literal("version.list") });
|
|
14697
|
-
var mapVersionHistoryVariant = versionBase2.extend({ action: z28.literal("version.history") });
|
|
14698
|
-
var mapSuggestVariant = mapSuggestSchema.extend({ action: z28.literal("suggest") });
|
|
14699
|
-
var mapCreateAudienceSetVariant = createAudienceMapSetSchema.extend({ action: z28.literal("create-audience-set") });
|
|
14700
|
-
var mapActionUnion = z28.discriminatedUnion("action", [
|
|
14701
|
-
mapCreateVariant,
|
|
14702
|
-
mapGetVariant,
|
|
14703
|
-
mapListVariant,
|
|
14704
|
-
mapSlotAddVariant,
|
|
14705
|
-
mapSlotRemoveVariant,
|
|
14706
|
-
mapSlotReplaceVariant,
|
|
14707
|
-
mapSlotListVariant,
|
|
14708
|
-
mapVersionCommitVariant,
|
|
14709
|
-
mapVersionListVariant,
|
|
14710
|
-
mapVersionHistoryVariant,
|
|
14711
|
-
mapSuggestVariant,
|
|
14712
|
-
mapCreateAudienceSetVariant
|
|
14713
|
-
]);
|
|
14714
|
-
var MAP_ACTION_SPECS = {
|
|
14715
|
-
create: { params: ["title", "templateId", "description", "slotIds", "ownerTeamEntryId", "ownerRoleEntryId"], description: "title is required." },
|
|
14716
|
-
get: { params: ["mapEntryId"], description: "mapEntryId is required." },
|
|
14717
|
-
list: { params: ["templateId", "status"], description: "All params optional." },
|
|
14718
|
-
"slot.add": { params: ["mapEntryId", "slotId", "ingredientEntryId", "label", "author"], description: "mapEntryId, slotId, and ingredientEntryId are required." },
|
|
14719
|
-
"slot.remove": { params: ["mapEntryId", "slotId", "ingredientEntryId", "author"], description: "mapEntryId, slotId, and ingredientEntryId are required." },
|
|
14720
|
-
"slot.replace": { params: ["mapEntryId", "slotId", "ingredientEntryId", "newIngredientEntryId", "label", "author"], description: "mapEntryId, slotId, ingredientEntryId, and newIngredientEntryId are required." },
|
|
14721
|
-
"slot.list": { params: ["mapEntryId", "slotId"], description: "mapEntryId is required." },
|
|
14722
|
-
"version.commit": { params: ["mapEntryId", "commitMessage", "author"], description: "mapEntryId is required." },
|
|
14723
|
-
"version.list": { params: ["mapEntryId"], description: "mapEntryId is required." },
|
|
14724
|
-
"version.history": { params: ["mapEntryId"], description: "mapEntryId is required." },
|
|
14725
|
-
suggest: { params: ["mapEntryId", "slotId", "query"], description: "mapEntryId is required." },
|
|
14726
|
-
"create-audience-set": { params: ["audienceEntryId", "ownerTeamEntryId", "ownerRoleEntryId"], description: "audienceEntryId is required." }
|
|
14727
|
-
};
|
|
14728
|
-
function registerMapTools(server) {
|
|
14729
|
-
const mapHandlers = {
|
|
14730
|
-
create: (data) => handleMapCrud({ ...data, action: "create" }),
|
|
14731
|
-
get: (data) => handleMapCrud({ ...data, action: "get" }),
|
|
14732
|
-
list: (data) => handleMapCrud({ ...data, action: "list" }),
|
|
14733
|
-
"slot.add": (data) => handleMapSlot({ ...data, action: "add" }),
|
|
14734
|
-
"slot.remove": (data) => handleMapSlot({ ...data, action: "remove" }),
|
|
14735
|
-
"slot.replace": (data) => handleMapSlot({ ...data, action: "replace" }),
|
|
14736
|
-
"slot.list": (data) => handleMapSlot({ ...data, action: "list" }),
|
|
14737
|
-
"version.commit": (data) => handleMapVersion({ ...data, action: "commit" }),
|
|
14738
|
-
"version.list": (data) => handleMapVersion({ ...data, action: "list" }),
|
|
14739
|
-
"version.history": (data) => handleMapVersion({ ...data, action: "history" }),
|
|
14740
|
-
suggest: (data) => handleMapSuggest(data),
|
|
14741
|
-
"create-audience-set": (data) => handleCreateAudienceMapSet(data)
|
|
14742
|
-
};
|
|
14743
|
-
server.registerTool(
|
|
14744
|
-
"map",
|
|
14745
|
-
{
|
|
14746
|
-
title: "Map",
|
|
14747
|
-
description: "Manage composed framework maps \u2014 CRUD, slot management, versioning, and suggestion. Maps assemble ingredient entries into framework slots (e.g. Lean Canvas). Module-gated (PB_MODULES=gitchain).\n\n- **create/get/list**: map CRUD.\n- **slot.add/slot.remove/slot.replace/slot.list**: ingredient slot management (absorbs `map-slot`).\n- **version.commit/version.list/version.history**: versioning (absorbs `map-version`).\n- **suggest**: find ingredients to fill empty slots (absorbs `map-suggest`).\n- **create-audience-set**: create Empathy/Narrowing/Jobs & Alternatives maps anchored to one audience entry (absorbs `create-audience-map-set`).",
|
|
14748
|
-
inputSchema: mapCompoundSchema,
|
|
14749
|
-
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
14750
|
-
},
|
|
14751
|
-
thinWrapper(async (args) => {
|
|
14752
|
-
const parsed = parseOrFail(mapCompoundSchema, args);
|
|
14753
|
-
if (!parsed.ok) return parsed.result;
|
|
14754
|
-
const { action } = parsed.data;
|
|
14755
|
-
return runWithToolContext(
|
|
14756
|
-
{ tool: "map", action },
|
|
14757
|
-
() => dispatchDiscriminated("map", mapActionUnion, parsed.data, MAP_ACTION_SPECS, mapHandlers)
|
|
14758
|
-
);
|
|
14759
|
-
})
|
|
14760
|
-
);
|
|
14761
|
-
}
|
|
14762
|
-
|
|
14763
14243
|
// src/tools/workspace.ts
|
|
14764
|
-
import { z as
|
|
14244
|
+
import { z as z30 } from "zod/v3";
|
|
14765
14245
|
|
|
14766
14246
|
// src/tools/health.ts
|
|
14767
|
-
import { z as
|
|
14247
|
+
import { z as z28 } from "zod/v3";
|
|
14768
14248
|
|
|
14769
14249
|
// src/lib/auditView.ts
|
|
14770
14250
|
async function buildTenantAuditView(limit) {
|
|
@@ -15128,65 +14608,65 @@ ${logLines.join("\n")}${seamSummaryText}` }],
|
|
|
15128
14608
|
};
|
|
15129
14609
|
}
|
|
15130
14610
|
var HEALTH_ACTIONS = ["check", "whoami", "status", "audit", "self-test"];
|
|
15131
|
-
var healthSchema =
|
|
15132
|
-
action:
|
|
14611
|
+
var healthSchema = z28.object({
|
|
14612
|
+
action: z28.enum(HEALTH_ACTIONS).describe(
|
|
15133
14613
|
"'check': connectivity and workspace stats. 'whoami': session identity. 'status': workspace readiness. 'audit': session audit log. 'self-test': validate all tool schemas."
|
|
15134
14614
|
),
|
|
15135
|
-
limit:
|
|
14615
|
+
limit: z28.number().min(1).max(50).default(20).optional().describe("For audit: how many recent calls to show (max 50)")
|
|
15136
14616
|
});
|
|
15137
|
-
var healthCheckOutputSchema =
|
|
15138
|
-
healthy:
|
|
15139
|
-
collections:
|
|
15140
|
-
entries:
|
|
15141
|
-
latencyMs:
|
|
15142
|
-
workspace:
|
|
14617
|
+
var healthCheckOutputSchema = z28.object({
|
|
14618
|
+
healthy: z28.boolean(),
|
|
14619
|
+
collections: z28.number(),
|
|
14620
|
+
entries: z28.number(),
|
|
14621
|
+
latencyMs: z28.number(),
|
|
14622
|
+
workspace: z28.string()
|
|
15143
14623
|
});
|
|
15144
|
-
var organisationHealthSchema =
|
|
15145
|
-
reviewed:
|
|
15146
|
-
agreements:
|
|
15147
|
-
disagreements:
|
|
15148
|
-
abstentions:
|
|
15149
|
-
agreementRate:
|
|
15150
|
-
flags:
|
|
15151
|
-
collection:
|
|
15152
|
-
count:
|
|
15153
|
-
suggestedCollection:
|
|
14624
|
+
var organisationHealthSchema = z28.object({
|
|
14625
|
+
reviewed: z28.number(),
|
|
14626
|
+
agreements: z28.number(),
|
|
14627
|
+
disagreements: z28.number(),
|
|
14628
|
+
abstentions: z28.number(),
|
|
14629
|
+
agreementRate: z28.number(),
|
|
14630
|
+
flags: z28.array(z28.object({
|
|
14631
|
+
collection: z28.string(),
|
|
14632
|
+
count: z28.number(),
|
|
14633
|
+
suggestedCollection: z28.string()
|
|
15154
14634
|
}))
|
|
15155
14635
|
});
|
|
15156
|
-
var healthStatusOutputSchema =
|
|
15157
|
-
stage:
|
|
15158
|
-
scoringVersion:
|
|
15159
|
-
readinessScore:
|
|
15160
|
-
activeEntries:
|
|
15161
|
-
totalRelations:
|
|
15162
|
-
orphanedEntries:
|
|
15163
|
-
gaps:
|
|
14636
|
+
var healthStatusOutputSchema = z28.object({
|
|
14637
|
+
stage: z28.enum(["blank", "seeded", "grounded", "connected"]).optional().default("seeded"),
|
|
14638
|
+
scoringVersion: z28.enum(["v1", "v2"]).optional().default("v1"),
|
|
14639
|
+
readinessScore: z28.number(),
|
|
14640
|
+
activeEntries: z28.number(),
|
|
14641
|
+
totalRelations: z28.number(),
|
|
14642
|
+
orphanedEntries: z28.number(),
|
|
14643
|
+
gaps: z28.array(z28.object({ id: z28.string(), label: z28.string(), guidance: z28.string() })),
|
|
15164
14644
|
organisationHealth: organisationHealthSchema.optional()
|
|
15165
14645
|
});
|
|
15166
|
-
var healthAuditOutputSchema =
|
|
15167
|
-
totalCalls:
|
|
15168
|
-
calls:
|
|
15169
|
-
tool:
|
|
15170
|
-
action:
|
|
15171
|
-
timestamp:
|
|
15172
|
-
durationMs:
|
|
14646
|
+
var healthAuditOutputSchema = z28.object({
|
|
14647
|
+
totalCalls: z28.number(),
|
|
14648
|
+
calls: z28.array(z28.object({
|
|
14649
|
+
tool: z28.string(),
|
|
14650
|
+
action: z28.string().optional(),
|
|
14651
|
+
timestamp: z28.string(),
|
|
14652
|
+
durationMs: z28.number().optional()
|
|
15173
14653
|
}))
|
|
15174
14654
|
});
|
|
15175
|
-
var healthWhoamiOutputSchema =
|
|
15176
|
-
workspaceId:
|
|
15177
|
-
workspaceName:
|
|
15178
|
-
scope:
|
|
15179
|
-
sessionId:
|
|
15180
|
-
oriented:
|
|
14655
|
+
var healthWhoamiOutputSchema = z28.object({
|
|
14656
|
+
workspaceId: z28.string(),
|
|
14657
|
+
workspaceName: z28.string(),
|
|
14658
|
+
scope: z28.string(),
|
|
14659
|
+
sessionId: z28.union([z28.string(), z28.null()]),
|
|
14660
|
+
oriented: z28.boolean()
|
|
15181
14661
|
});
|
|
15182
|
-
var selfTestOutputSchema =
|
|
15183
|
-
passed:
|
|
15184
|
-
failed:
|
|
15185
|
-
total:
|
|
15186
|
-
results:
|
|
15187
|
-
tool:
|
|
15188
|
-
valid:
|
|
15189
|
-
error:
|
|
14662
|
+
var selfTestOutputSchema = z28.object({
|
|
14663
|
+
passed: z28.number(),
|
|
14664
|
+
failed: z28.number(),
|
|
14665
|
+
total: z28.number(),
|
|
14666
|
+
results: z28.array(z28.object({
|
|
14667
|
+
tool: z28.string(),
|
|
14668
|
+
valid: z28.boolean(),
|
|
14669
|
+
error: z28.string().optional()
|
|
15190
14670
|
}))
|
|
15191
14671
|
});
|
|
15192
14672
|
function handleSelfTest(server) {
|
|
@@ -15237,9 +14717,9 @@ function handleSelfTest(server) {
|
|
|
15237
14717
|
}
|
|
15238
14718
|
|
|
15239
14719
|
// src/tools/usage.ts
|
|
15240
|
-
import { z as
|
|
15241
|
-
var usageSummarySchema =
|
|
15242
|
-
periodDays:
|
|
14720
|
+
import { z as z29 } from "zod/v3";
|
|
14721
|
+
var usageSummarySchema = z29.object({
|
|
14722
|
+
periodDays: z29.number().min(1).max(90).optional().describe("Number of days to look back (default 30, max 90)")
|
|
15243
14723
|
});
|
|
15244
14724
|
async function handleUsageSummary(periodDays) {
|
|
15245
14725
|
const ws = await getWorkspaceContext();
|
|
@@ -15411,35 +14891,35 @@ var WORKSPACE_ACTIONS = [
|
|
|
15411
14891
|
"proposals-respond",
|
|
15412
14892
|
"proposals-count"
|
|
15413
14893
|
];
|
|
15414
|
-
var workspaceSchema =
|
|
15415
|
-
action:
|
|
14894
|
+
var workspaceSchema = z30.object({
|
|
14895
|
+
action: z30.enum(WORKSPACE_ACTIONS).describe(
|
|
15416
14896
|
"'check': connectivity and workspace stats (absorbs health action=check). 'whoami': session identity (absorbs health action=whoami). 'status': workspace readiness (absorbs health action=status). 'audit': session audit log (absorbs health action=audit). 'self-test': validate all tool schemas (absorbs health action=self-test). 'usage': LLM usage and cost summary (absorbs get-usage-summary). 'proposals-list': list open consent proposals (absorbs governance-proposals action=list). 'proposals-respond': approve/reject a consent proposal (absorbs governance-proposals action=respond). 'proposals-count': count open consent proposals (absorbs governance-proposals action=count)."
|
|
15417
14897
|
),
|
|
15418
|
-
limit:
|
|
15419
|
-
periodDays:
|
|
15420
|
-
status:
|
|
15421
|
-
proposalId:
|
|
15422
|
-
verdict:
|
|
15423
|
-
reason:
|
|
14898
|
+
limit: z30.number().min(1).max(50).optional().describe("For 'audit': how many recent calls to show (max 50, default 20)."),
|
|
14899
|
+
periodDays: z30.number().min(1).max(90).optional().describe("For 'usage': number of days to look back (default 30, max 90)."),
|
|
14900
|
+
status: z30.enum(["open", "approved", "objected", "expired"]).optional().describe("For 'proposals-list': filter by status (default: open)."),
|
|
14901
|
+
proposalId: z30.string().max(200).optional().describe("For 'proposals-respond': proposal ID."),
|
|
14902
|
+
verdict: z30.enum(["approve", "reject"]).optional().describe("For 'proposals-respond': approve or reject."),
|
|
14903
|
+
reason: z30.string().max(2e3).optional().describe("For 'proposals-respond': reason for the verdict (required when rejecting).")
|
|
15424
14904
|
});
|
|
15425
|
-
var workspaceCheckVariant =
|
|
15426
|
-
var workspaceWhoamiVariant =
|
|
15427
|
-
var workspaceStatusVariant =
|
|
15428
|
-
var workspaceAuditVariant =
|
|
15429
|
-
var workspaceSelfTestVariant =
|
|
15430
|
-
var workspaceUsageVariant =
|
|
15431
|
-
var workspaceProposalsListVariant =
|
|
15432
|
-
action:
|
|
15433
|
-
status:
|
|
14905
|
+
var workspaceCheckVariant = z30.object({ action: z30.literal("check") });
|
|
14906
|
+
var workspaceWhoamiVariant = z30.object({ action: z30.literal("whoami") });
|
|
14907
|
+
var workspaceStatusVariant = z30.object({ action: z30.literal("status") });
|
|
14908
|
+
var workspaceAuditVariant = z30.object({ action: z30.literal("audit"), limit: z30.number().min(1).max(50).optional().default(20) });
|
|
14909
|
+
var workspaceSelfTestVariant = z30.object({ action: z30.literal("self-test") });
|
|
14910
|
+
var workspaceUsageVariant = z30.object({ action: z30.literal("usage"), periodDays: z30.number().min(1).max(90).optional() });
|
|
14911
|
+
var workspaceProposalsListVariant = z30.object({
|
|
14912
|
+
action: z30.literal("proposals-list"),
|
|
14913
|
+
status: z30.enum(["open", "approved", "objected", "expired"]).optional()
|
|
15434
14914
|
});
|
|
15435
|
-
var workspaceProposalsRespondVariant =
|
|
15436
|
-
action:
|
|
15437
|
-
proposalId:
|
|
15438
|
-
verdict:
|
|
15439
|
-
reason:
|
|
14915
|
+
var workspaceProposalsRespondVariant = z30.object({
|
|
14916
|
+
action: z30.literal("proposals-respond"),
|
|
14917
|
+
proposalId: z30.string().max(200),
|
|
14918
|
+
verdict: z30.enum(["approve", "reject"]),
|
|
14919
|
+
reason: z30.string().max(2e3).optional()
|
|
15440
14920
|
});
|
|
15441
|
-
var workspaceProposalsCountVariant =
|
|
15442
|
-
var workspaceActionUnion =
|
|
14921
|
+
var workspaceProposalsCountVariant = z30.object({ action: z30.literal("proposals-count") });
|
|
14922
|
+
var workspaceActionUnion = z30.discriminatedUnion("action", [
|
|
15443
14923
|
workspaceCheckVariant,
|
|
15444
14924
|
workspaceWhoamiVariant,
|
|
15445
14925
|
workspaceStatusVariant,
|
|
@@ -15495,7 +14975,7 @@ function registerWorkspaceTools(server) {
|
|
|
15495
14975
|
}
|
|
15496
14976
|
|
|
15497
14977
|
// src/tools/feedback.ts
|
|
15498
|
-
import { z as
|
|
14978
|
+
import { z as z31 } from "zod/v3";
|
|
15499
14979
|
|
|
15500
14980
|
// src/lib/productFeedbackConstants.ts
|
|
15501
14981
|
var PRODUCT_FEEDBACK_CATEGORIES = ["bug", "friction", "idea", "praise", "other"];
|
|
@@ -15506,9 +14986,9 @@ var VENDOR_SETTABLE_STATUSES = PRODUCT_FEEDBACK_STATUSES.filter(
|
|
|
15506
14986
|
|
|
15507
14987
|
// src/tools/feedback.ts
|
|
15508
14988
|
var actions = ["submit", "list", "queue", "note", "group", "status"];
|
|
15509
|
-
var category =
|
|
15510
|
-
var status =
|
|
15511
|
-
var vendorStatus =
|
|
14989
|
+
var category = z31.enum(PRODUCT_FEEDBACK_CATEGORIES);
|
|
14990
|
+
var status = z31.enum(PRODUCT_FEEDBACK_STATUSES);
|
|
14991
|
+
var vendorStatus = z31.enum(VENDOR_SETTABLE_STATUSES);
|
|
15512
14992
|
var GATEWAY_MAX_STRING_BYTES = 10240;
|
|
15513
14993
|
var utf8Bytes = (value) => new TextEncoder().encode(value).length;
|
|
15514
14994
|
var fitsGatewayBytes = (value) => utf8Bytes(value) <= GATEWAY_MAX_STRING_BYTES;
|
|
@@ -15517,32 +14997,32 @@ var byteLimitMessage = (field) => ({
|
|
|
15517
14997
|
});
|
|
15518
14998
|
var MESSAGE_DISPLAY_LIMIT = 1e3;
|
|
15519
14999
|
var FULL_MESSAGE_MAX_LIMIT = 5;
|
|
15520
|
-
var feedbackSchema =
|
|
15521
|
-
action:
|
|
15522
|
-
message:
|
|
15000
|
+
var feedbackSchema = z31.object({
|
|
15001
|
+
action: z31.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."),
|
|
15002
|
+
message: z31.string().max(1e4).optional().describe("Required for submit: the product feedback text (max 10,000 chars and 10,240 UTF-8 bytes)."),
|
|
15523
15003
|
category: category.optional().describe("Submit/queue category; submit defaults to other."),
|
|
15524
|
-
command:
|
|
15525
|
-
route:
|
|
15526
|
-
client:
|
|
15527
|
-
feedbackId:
|
|
15528
|
-
feedbackIds:
|
|
15529
|
-
note:
|
|
15004
|
+
command: z31.string().max(1e3).optional().describe("Optional submit command context; argument values are scrubbed server-side."),
|
|
15005
|
+
route: z31.string().max(500).optional().describe("Optional submit route context."),
|
|
15006
|
+
client: z31.string().max(100).optional().describe("Optional submit client label."),
|
|
15007
|
+
feedbackId: z31.string().max(200).optional().describe("Required for note/status: target feedback ID."),
|
|
15008
|
+
feedbackIds: z31.array(z31.string().max(200)).max(100).optional().describe("Required for group: 1\u2013100 target feedback IDs."),
|
|
15009
|
+
note: z31.string().max(4e3).optional().describe("Required for note: replacement triage note (max 10,240 UTF-8 bytes)."),
|
|
15530
15010
|
status: status.optional().describe("list/queue filter (any status, including 'screening'); the status action's required target value excludes 'screening' (system-only)."),
|
|
15531
|
-
groupId:
|
|
15532
|
-
workspaceId:
|
|
15533
|
-
since:
|
|
15534
|
-
before:
|
|
15535
|
-
limit:
|
|
15536
|
-
cursor:
|
|
15537
|
-
full:
|
|
15011
|
+
groupId: z31.string().min(1).max(200).nullable().optional().describe("Group filter, or required group destination; null explicitly clears grouping."),
|
|
15012
|
+
workspaceId: z31.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."),
|
|
15013
|
+
since: z31.number().optional().describe("Queue-only lower createdAt window bound (inclusive) in epoch milliseconds."),
|
|
15014
|
+
before: z31.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."),
|
|
15015
|
+
limit: z31.number().int().min(1).max(100).optional().describe("list/queue row limit, default 50, maximum 100."),
|
|
15016
|
+
cursor: z31.string().max(2e3).optional().describe("Opaque pagination cursor from a previous list/queue response (continueCursor); omit for the first page."),
|
|
15017
|
+
full: z31.boolean().optional().describe(`list/queue only: return untruncated messages; allowed only when limit <= ${FULL_MESSAGE_MAX_LIMIT}.`)
|
|
15538
15018
|
});
|
|
15539
|
-
var union =
|
|
15540
|
-
|
|
15541
|
-
|
|
15542
|
-
|
|
15543
|
-
|
|
15544
|
-
|
|
15545
|
-
|
|
15019
|
+
var union = z31.discriminatedUnion("action", [
|
|
15020
|
+
z31.object({ action: z31.literal("submit"), message: z31.string().min(1).max(1e4).refine(fitsGatewayBytes, byteLimitMessage("message")), category: category.optional(), command: z31.string().max(1e3).optional(), route: z31.string().max(500).optional(), client: z31.string().max(100).optional() }),
|
|
15021
|
+
z31.object({ action: z31.literal("list"), status: status.optional(), limit: z31.number().int().min(1).max(100).optional(), cursor: z31.string().max(2e3).optional(), full: z31.boolean().optional() }),
|
|
15022
|
+
z31.object({ action: z31.literal("queue"), status: status.optional(), category: category.optional(), groupId: z31.string().min(1).max(200).optional(), workspaceId: z31.string().max(200).optional(), since: z31.number().optional(), before: z31.number().optional(), limit: z31.number().int().min(1).max(100).optional(), cursor: z31.string().max(2e3).optional(), full: z31.boolean().optional() }),
|
|
15023
|
+
z31.object({ action: z31.literal("note"), feedbackId: z31.string().min(1).max(200), note: z31.string().max(4e3).refine(fitsGatewayBytes, byteLimitMessage("note")) }),
|
|
15024
|
+
z31.object({ action: z31.literal("group"), feedbackIds: z31.array(z31.string().min(1).max(200)).min(1).max(100), groupId: z31.string().min(1).max(200).nullable() }),
|
|
15025
|
+
z31.object({ action: z31.literal("status"), feedbackId: z31.string().min(1).max(200), status: vendorStatus })
|
|
15546
15026
|
]);
|
|
15547
15027
|
var specs = {
|
|
15548
15028
|
submit: { params: ["message", "category", "command", "route", "client"], description: "message is required; category defaults to other." },
|
|
@@ -15669,34 +15149,34 @@ function registerFeedbackTool(server) {
|
|
|
15669
15149
|
}
|
|
15670
15150
|
|
|
15671
15151
|
// src/tools/shape.ts
|
|
15672
|
-
import { z as
|
|
15152
|
+
import { z as z32 } from "zod/v3";
|
|
15673
15153
|
var SHAPE_ACTIONS = ["list", "show", "agree", "dismiss"];
|
|
15674
15154
|
var LIST_DISPOSITIONS = ["pending", "agreed", "dismissed", "expired"];
|
|
15675
15155
|
var LIST_OUTCOMES = ["not_candidate", "atomic", "compound", "unavailable"];
|
|
15676
|
-
var shapeSchema =
|
|
15677
|
-
action:
|
|
15156
|
+
var shapeSchema = z32.object({
|
|
15157
|
+
action: z32.enum(SHAPE_ACTIONS).describe(
|
|
15678
15158
|
"'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."
|
|
15679
15159
|
),
|
|
15680
|
-
disposition:
|
|
15160
|
+
disposition: z32.enum(LIST_DISPOSITIONS).optional().describe(
|
|
15681
15161
|
"For 'list': filter by disposition. Omitting both disposition and outcome defaults to the actionable set (disposition:pending, outcome:compound)."
|
|
15682
15162
|
),
|
|
15683
|
-
outcome:
|
|
15163
|
+
outcome: z32.enum(LIST_OUTCOMES).optional().describe(
|
|
15684
15164
|
"For 'list': filter by outcome. Omitting both disposition and outcome defaults to the actionable set (disposition:pending, outcome:compound)."
|
|
15685
15165
|
),
|
|
15686
|
-
limit:
|
|
15687
|
-
rowId:
|
|
15688
|
-
reason:
|
|
15166
|
+
limit: z32.number().min(1).max(200).optional().describe("For 'list': max rows (default 50, max 200)."),
|
|
15167
|
+
rowId: z32.string().max(200).optional().describe("For 'show'/'agree'/'dismiss': the advisory row id."),
|
|
15168
|
+
reason: z32.string().max(1e3).optional().describe("For 'agree'/'dismiss': optional reason (capped at 1000 chars).")
|
|
15689
15169
|
});
|
|
15690
|
-
var shapeListVariant =
|
|
15691
|
-
action:
|
|
15692
|
-
disposition:
|
|
15693
|
-
outcome:
|
|
15694
|
-
limit:
|
|
15170
|
+
var shapeListVariant = z32.object({
|
|
15171
|
+
action: z32.literal("list"),
|
|
15172
|
+
disposition: z32.enum(LIST_DISPOSITIONS).optional(),
|
|
15173
|
+
outcome: z32.enum(LIST_OUTCOMES).optional(),
|
|
15174
|
+
limit: z32.number().min(1).max(200).optional()
|
|
15695
15175
|
});
|
|
15696
|
-
var shapeShowVariant =
|
|
15697
|
-
var shapeAgreeVariant =
|
|
15698
|
-
var shapeDismissVariant =
|
|
15699
|
-
var shapeActionUnion =
|
|
15176
|
+
var shapeShowVariant = z32.object({ action: z32.literal("show"), rowId: z32.string().max(200) });
|
|
15177
|
+
var shapeAgreeVariant = z32.object({ action: z32.literal("agree"), rowId: z32.string().max(200), reason: z32.string().max(1e3).optional() });
|
|
15178
|
+
var shapeDismissVariant = z32.object({ action: z32.literal("dismiss"), rowId: z32.string().max(200), reason: z32.string().max(1e3).optional() });
|
|
15179
|
+
var shapeActionUnion = z32.discriminatedUnion("action", [
|
|
15700
15180
|
shapeListVariant,
|
|
15701
15181
|
shapeShowVariant,
|
|
15702
15182
|
shapeAgreeVariant,
|
|
@@ -15843,7 +15323,7 @@ function registerShapeTools(server) {
|
|
|
15843
15323
|
}
|
|
15844
15324
|
|
|
15845
15325
|
// src/tools/question.ts
|
|
15846
|
-
import { z as
|
|
15326
|
+
import { z as z33 } from "zod/v3";
|
|
15847
15327
|
|
|
15848
15328
|
// src/lib/strip.ts
|
|
15849
15329
|
var ANSI_AND_CONTROL_RE2 = /\x1b\[[0-9;]*[A-Za-z]|\x1b\][^\x07]*\x07|\x1b[^[\]0-9;A-Za-z]?|[\x00-\x08\x0b-\x1f\x7f]/g;
|
|
@@ -15854,29 +15334,29 @@ function stripControlChars(str) {
|
|
|
15854
15334
|
|
|
15855
15335
|
// src/tools/question.ts
|
|
15856
15336
|
var QUESTION_ACTIONS = ["create", "adopt", "assign", "snooze", "decline", "answer", "force-close", "list"];
|
|
15857
|
-
var questionSchema =
|
|
15858
|
-
action:
|
|
15337
|
+
var questionSchema = z33.object({
|
|
15338
|
+
action: z33.enum(QUESTION_ACTIONS).describe(
|
|
15859
15339
|
"'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': attach routing to a tension already captured (e.g. via `pb capture \"TEN: ...\"`) \u2014 the pilot's real birth path; without adopt, captured tensions stay 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)."
|
|
15860
15340
|
),
|
|
15861
|
-
entryId:
|
|
15862
|
-
text:
|
|
15863
|
-
domain:
|
|
15864
|
-
blocks:
|
|
15865
|
-
toRole:
|
|
15866
|
-
toPerson:
|
|
15867
|
-
reason:
|
|
15868
|
-
answerEntryId:
|
|
15869
|
-
mine:
|
|
15341
|
+
entryId: z33.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'."),
|
|
15342
|
+
text: z33.string().max(5e3).optional().describe("'create': the question text. 'answer': the answer text (mutually exclusive with answerEntryId, max 2000 chars)."),
|
|
15343
|
+
domain: z33.string().max(200).optional().describe("'create'/'adopt': the domain slug (see this tool's refusal for the live list)."),
|
|
15344
|
+
blocks: z33.array(z33.string().max(200)).max(50).optional().describe("'create'/'adopt': entry ids this question is blocking (repeatable)."),
|
|
15345
|
+
toRole: z33.string().max(200).optional().describe("'assign': reassign to this role (human ROL-nnn form or a raw entry id)."),
|
|
15346
|
+
toPerson: z33.string().max(200).optional().describe("'assign': reassign to this person (a raw person id)."),
|
|
15347
|
+
reason: z33.string().max(2e3).optional().describe("'decline'/'force-close': required reason."),
|
|
15348
|
+
answerEntryId: z33.string().max(200).optional().describe("'answer': point at an already-written entry instead of supplying text (mutually exclusive with text)."),
|
|
15349
|
+
mine: z33.boolean().optional().describe("'list': true for arm C (every question YOU asked, every status). Omit/false for the ack-gate view (what you owe).")
|
|
15870
15350
|
});
|
|
15871
|
-
var createVariant =
|
|
15872
|
-
var adoptVariant =
|
|
15873
|
-
var assignVariant =
|
|
15874
|
-
var snoozeVariant =
|
|
15875
|
-
var declineVariant =
|
|
15876
|
-
var answerVariant =
|
|
15877
|
-
var forceCloseVariant =
|
|
15878
|
-
var listVariant =
|
|
15879
|
-
var questionActionUnion =
|
|
15351
|
+
var createVariant = z33.object({ action: z33.literal("create"), text: z33.string().min(1).max(5e3), domain: z33.string().max(200).optional(), blocks: z33.array(z33.string().max(200)).max(50).optional() });
|
|
15352
|
+
var adoptVariant = z33.object({ action: z33.literal("adopt"), entryId: z33.string().max(200), domain: z33.string().max(200).optional(), blocks: z33.array(z33.string().max(200)).max(50).optional() });
|
|
15353
|
+
var assignVariant = z33.object({ action: z33.literal("assign"), entryId: z33.string().max(200), toRole: z33.string().max(200).optional(), toPerson: z33.string().max(200).optional() });
|
|
15354
|
+
var snoozeVariant = z33.object({ action: z33.literal("snooze"), entryId: z33.string().max(200) });
|
|
15355
|
+
var declineVariant = z33.object({ action: z33.literal("decline"), entryId: z33.string().max(200), reason: z33.string().min(1).max(2e3) });
|
|
15356
|
+
var answerVariant = z33.object({ action: z33.literal("answer"), entryId: z33.string().max(200), text: z33.string().max(2e3).optional(), answerEntryId: z33.string().max(200).optional() });
|
|
15357
|
+
var forceCloseVariant = z33.object({ action: z33.literal("force-close"), entryId: z33.string().max(200), reason: z33.string().min(1).max(2e3) });
|
|
15358
|
+
var listVariant = z33.object({ action: z33.literal("list"), mine: z33.boolean().optional() });
|
|
15359
|
+
var questionActionUnion = z33.discriminatedUnion("action", [
|
|
15880
15360
|
createVariant,
|
|
15881
15361
|
adoptVariant,
|
|
15882
15362
|
assignVariant,
|
|
@@ -16265,10 +15745,10 @@ Browse: \`entries action=list collection=tracking-events\`.`
|
|
|
16265
15745
|
"## Knowledge Graph\nEntries are connected via typed relations (`entryRelations` table). Relations are bidirectional and collection-agnostic \u2014 any entry can link to any other entry.\n\n**Recommended relation types** (extensible \u2014 any string accepted):\n- `governs` \u2014 a rule constrains behavior of a feature\n- `defines_term_for` \u2014 a glossary term is canonical vocabulary for a feature/area\n- `belongs_to` \u2014 a feature belongs to a product area or parent concept (WP-641 typed successors: `anchored_to`, `authority_domain`)\n- `informs` \u2014 a decision or insight informs a feature\n- `fills_slot` \u2014 an ingredient entry fills a slot in a map\n- `surfaces_tension_in` \u2014 a tension exists within a feature area\n- `related_to`, `depends_on`, `replaces`, `conflicts_with`, `references`, `confused_with`\n\nEach relation type is defined as a glossary entry (prefix `GT-REL-*`) to prevent terminology drift. **Workflow-owned, NOT generic:** `domain_routed_to` (a question routed to a domain) \u2014 use the `question` tool (`action=create`/`adopt`, `domain=<slug>`), never `relations action=create`; the generic door has no replace/re-judge logic, so a raw write can leave duplicate routing edges and a stale suggested owner.\n\n**Tools:**\n- `context action=gather` \u2014 get the full context around any entry (multi-hop graph traversal)\n- `relations action=suggest` \u2014 discover potential connections for an entry\n- `relations action=create` \u2014 create a typed link between two entries\n- `relations action=find` \u2014 list direct relations for an entry\n\n**Convention:** When creating or updating entries in governed collections, always use `relations action=suggest` to discover and create relevant relations."
|
|
16266
15746
|
);
|
|
16267
15747
|
sections.push(
|
|
16268
|
-
"## Creating Knowledge\n**Entries:** Use `capture` as the primary tool for creating new entries. It handles the full workflow in one call:\n1. Creates the entry with collection-aware defaults (auto-fills dates, infers domains, sets priority)\n2. Auto-links related entries from across the chain (up to 5 confident matches)\n3. Returns a quality scorecard (X/10) with actionable improvement suggestions\n\n**Smart profiles** exist for: `tensions`, `business-rules`, `glossary`, `decisions`, `features`, `audiences`, `strategy`, `standards`, `maps`, `chains`, `tracking-events`.\nAll other collections use the `ENT-{random}` fallback profile.\n\n**Processes:** Use `chain action=create` with a template (e.g., `strategy-coherence`, `idm-proposal`). Fill links with `chain action=edit`.\n\n**
|
|
15748
|
+
"## Creating Knowledge\n**Entries:** Use `capture` as the primary tool for creating new entries. It handles the full workflow in one call:\n1. Creates the entry with collection-aware defaults (auto-fills dates, infers domains, sets priority)\n2. Auto-links related entries from across the chain (up to 5 confident matches)\n3. Returns a quality scorecard (X/10) with actionable improvement suggestions\n\n**Smart profiles** exist for: `tensions`, `business-rules`, `glossary`, `decisions`, `features`, `audiences`, `strategy`, `standards`, `maps`, `chains`, `tracking-events`.\nAll other collections use the `ENT-{random}` fallback profile.\n\n**Processes:** Use `chain action=create` with a template (e.g., `strategy-coherence`, `idm-proposal`). Fill links with `chain action=edit`.\n\n**Prompts** (invoke via MCP prompt protocol):\n- `name-check` \u2014 verify a name against glossary conventions\n- `draft-decision-record` \u2014 scaffold a decision entry\n- `review-against-rules` \u2014 check work against business rules for a domain\n- `draft-rule-from-context` \u2014 create a new business rule from context\n\nUse `quality action=check` to score existing entries retroactively.\nUse `entries action=update` for post-creation adjustments (status changes, field updates, deprecation)."
|
|
16269
15749
|
);
|
|
16270
15750
|
sections.push(
|
|
16271
|
-
"## Where to Go Next\n- **Create entry** \u2192 `capture` tool (auto-links + quality score in one call)\n- **Full context** \u2192 `context action=gather` (by entry ID or task description)\n- **Discover links** \u2192 `relations action=suggest`\n- **Quality audit** \u2192 `quality action=check`\n- **Terminology** \u2192 `name-check` prompt or `productbrain://terminology` resource\n- **Schema details** \u2192 `productbrain://collections` resource or `collections action=list`\n- **Labels** \u2192 `productbrain://labels` resource or `collections action=label-list`\n- **Any collection** \u2192 `productbrain://{slug}/entries` resource\n- **Log a decision** \u2192 `draft-decision-record` prompt\n- **
|
|
15751
|
+
"## Where to Go Next\n- **Create entry** \u2192 `capture` tool (auto-links + quality score in one call)\n- **Full context** \u2192 `context action=gather` (by entry ID or task description)\n- **Discover links** \u2192 `relations action=suggest`\n- **Quality audit** \u2192 `quality action=check`\n- **Terminology** \u2192 `name-check` prompt or `productbrain://terminology` resource\n- **Schema details** \u2192 `productbrain://collections` resource or `collections action=list`\n- **Labels** \u2192 `productbrain://labels` resource or `collections action=label-list`\n- **Any collection** \u2192 `productbrain://{slug}/entries` resource\n- **Log a decision** \u2192 `draft-decision-record` prompt\n- **Growth funnel** \u2192 `productbrain://growth-funnel` resource or `entries action=list collection=strategy status=draft`\n- **Audiences** \u2192 `productbrain://audiences/entries` resource or `entries action=list collection=audiences`\n- **Session identity** \u2192 `workspace action=whoami`\n- **Health check** \u2192 `workspace action=check`\n- **Debug MCP calls** \u2192 `workspace action=audit`"
|
|
16272
15752
|
);
|
|
16273
15753
|
return sections.join("\n\n---\n\n");
|
|
16274
15754
|
}
|
|
@@ -16638,12 +16118,12 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
|
|
|
16638
16118
|
}
|
|
16639
16119
|
|
|
16640
16120
|
// src/prompts/index.ts
|
|
16641
|
-
import { z as
|
|
16121
|
+
import { z as z34 } from "zod/v3";
|
|
16642
16122
|
function registerPrompts(server) {
|
|
16643
16123
|
server.prompt(
|
|
16644
16124
|
"review-against-rules",
|
|
16645
16125
|
"Review code or a design decision against all business rules for a given domain. Fetches the rules and asks you to do a structured compliance review.",
|
|
16646
|
-
{ domain:
|
|
16126
|
+
{ domain: z34.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
|
|
16647
16127
|
async ({ domain }) => {
|
|
16648
16128
|
const entries = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
|
|
16649
16129
|
const rules = entries.filter((e) => e.data?.domain === domain);
|
|
@@ -16696,7 +16176,7 @@ Provide a structured review with a compliance status for each rule (COMPLIANT /
|
|
|
16696
16176
|
server.prompt(
|
|
16697
16177
|
"name-check",
|
|
16698
16178
|
"Check variable names, field names, or API names against the glossary for terminology alignment. Flags drift from canonical terms.",
|
|
16699
|
-
{ names:
|
|
16179
|
+
{ names: z34.string().describe("Comma-separated list of names to check (e.g. 'vendor_id, compliance_level, formulator_type')") },
|
|
16700
16180
|
async ({ names }) => {
|
|
16701
16181
|
const terms = await kernelQuery("chain.listEntries", { collectionSlug: "glossary" });
|
|
16702
16182
|
const glossaryContext = terms.map(
|
|
@@ -16732,7 +16212,7 @@ Format as a table: Name | Status | Canonical Form | Action Needed`
|
|
|
16732
16212
|
server.prompt(
|
|
16733
16213
|
"draft-decision-record",
|
|
16734
16214
|
"Draft a structured decision record from a description of what was decided. Includes context from recent decisions and relevant rules.",
|
|
16735
|
-
{ context:
|
|
16215
|
+
{ context: z34.string().describe("Description of the decision (e.g. 'We decided to use MRSL v3.1 as the conformance baseline because...')") },
|
|
16736
16216
|
async ({ context }) => {
|
|
16737
16217
|
const recentDecisions = await kernelQuery("chain.listEntries", { collectionSlug: "decisions" });
|
|
16738
16218
|
const sorted = [...recentDecisions].sort((a, b) => (b.data?.date ?? "") > (a.data?.date ?? "") ? 1 : -1).slice(0, 5);
|
|
@@ -16770,8 +16250,8 @@ After drafting, I can log it using the capture tool with collection "decisions".
|
|
|
16770
16250
|
"draft-rule-from-context",
|
|
16771
16251
|
"Draft a new business rule from an observation or discovery made while coding. Fetches existing rules for the domain to ensure consistency.",
|
|
16772
16252
|
{
|
|
16773
|
-
observation:
|
|
16774
|
-
domain:
|
|
16253
|
+
observation: z34.string().describe("What you observed or discovered (e.g. 'Suppliers can have multiple org types in Gateway')"),
|
|
16254
|
+
domain: z34.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
|
|
16775
16255
|
},
|
|
16776
16256
|
async ({ observation, domain }) => {
|
|
16777
16257
|
const allRules = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
|
|
@@ -16837,8 +16317,8 @@ var INSTRUCTIONS = [
|
|
|
16837
16317
|
"- **Self-documenting**: orient and server instructions teach agents how PB works. Cursor rules supplement but don't replace.",
|
|
16838
16318
|
"",
|
|
16839
16319
|
"### Tool Rename Notice (WP-484 S3, one release)",
|
|
16840
|
-
"Serves 13 default compound tools (WP-559 adds `shape` \u2014 review/disposition for write-shape advisories; WP-638 S3 adds `question` \u2014 routed-question routing/ownership/lifecycle);
|
|
16841
|
-
"Old standalone names are gone \u2014 no alias window (ASM-43: zero external consumers). Map: `start_pb`\u2192`orient action=start`, `record_activation`\u2192`orient action=record-activation`, `session-wrapup`\u2192`session action=wrapup-review|wrapup-commit`, `facilitate`\u2192`session action=resume|commit-constellation`, `update-entry`\u2192`entries action=update`, `commit-entry`\u2192`entries action=commit`, `get-history`\u2192`entries action=history`, `move-entry`\u2192`entries action=move`, `verify-entry`\u2192`entries action=verify`, `graph`\u2192`relations action=find|suggest`, `documents`\u2192`context action=last-verified-brief`, `labels`\u2192`collections action=label-*`, `verify`\u2192`quality action=verify-chain`, `audit`\u2192`quality action=audit`, `health`\u2192`workspace action=check|whoami|status|self-test`, `get-usage-summary`\u2192`workspace action=usage`, `governance-proposals`\u2192`workspace action=proposals-*`, `skills`\u2192`workflows action=load-skill`, `chain-version`\u2192`chain action=version.*`, `chain-branch`\u2192`chain-review action=branch
|
|
16320
|
+
"Serves 13 default compound tools (WP-559 adds `shape` \u2014 review/disposition for write-shape advisories; WP-638 S3 adds `question` \u2014 routed-question routing/ownership/lifecycle); 2 more (chain, chain-review) behind PB_MODULES=gitchain.",
|
|
16321
|
+
"Old standalone names are gone \u2014 no alias window (ASM-43: zero external consumers). Map: `start_pb`\u2192`orient action=start`, `record_activation`\u2192`orient action=record-activation`, `session-wrapup`\u2192`session action=wrapup-review|wrapup-commit`, `facilitate`\u2192`session action=resume|commit-constellation`, `update-entry`\u2192`entries action=update`, `commit-entry`\u2192`entries action=commit`, `get-history`\u2192`entries action=history`, `move-entry`\u2192`entries action=move`, `verify-entry`\u2192`entries action=verify`, `graph`\u2192`relations action=find|suggest`, `documents`\u2192`context action=last-verified-brief`, `labels`\u2192`collections action=label-*`, `verify`\u2192`quality action=verify-chain`, `audit`\u2192`quality action=audit`, `health`\u2192`workspace action=check|whoami|status|self-test`, `get-usage-summary`\u2192`workspace action=usage`, `governance-proposals`\u2192`workspace action=proposals-*`, `skills`\u2192`workflows action=load-skill`, `chain-version`\u2192`chain action=version.*`, `chain-branch`\u2192`chain-review action=branch.*`.",
|
|
16842
16322
|
"",
|
|
16843
16323
|
"## Your Workspace Principles",
|
|
16844
16324
|
"",
|
|
@@ -16909,7 +16389,6 @@ function createProductBrainServer() {
|
|
|
16909
16389
|
registerShapeTools(server);
|
|
16910
16390
|
registerQuestionTools(server);
|
|
16911
16391
|
if (enabledModules.has("gitchain")) registerGitChainTools(server);
|
|
16912
|
-
if (enabledModules.has("gitchain")) registerMapTools(server);
|
|
16913
16392
|
registerResources(server);
|
|
16914
16393
|
registerPrompts(server);
|
|
16915
16394
|
return server;
|
|
@@ -17048,4 +16527,4 @@ export {
|
|
|
17048
16527
|
createProductBrainServer,
|
|
17049
16528
|
initFeatureFlags
|
|
17050
16529
|
};
|
|
17051
|
-
//# sourceMappingURL=chunk-
|
|
16530
|
+
//# sourceMappingURL=chunk-Y2OH35MJ.js.map
|