@productbrain/mcp 0.0.1-beta.190 → 0.0.1-beta.191
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-ZF6N62QQ.js → chunk-GJFGULJV.js} +134 -11
- package/dist/chunk-GJFGULJV.js.map +1 -0
- package/dist/http.js +126 -88
- package/dist/http.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-ZF6N62QQ.js.map +0 -1
|
@@ -351,7 +351,11 @@ var TOUCH_EXCLUDED = /* @__PURE__ */ new Set([
|
|
|
351
351
|
"agent.markOriented",
|
|
352
352
|
"agent.recordActivity",
|
|
353
353
|
"agent.recordWrapup",
|
|
354
|
-
"agent.closeSession"
|
|
354
|
+
"agent.closeSession",
|
|
355
|
+
// WP-376 α.3: orient byte report is itself a heartbeat-equivalent observability
|
|
356
|
+
// write that already patches the same agentSessions row. A follow-up touchSession
|
|
357
|
+
// would create a redundant second write per orient call (DEC-50 OCC anti-pattern).
|
|
358
|
+
"agent.reportOrientMetric"
|
|
355
359
|
]);
|
|
356
360
|
async function callGateway(fn, args) {
|
|
357
361
|
const siteUrl = await resolveDeploymentUrl();
|
|
@@ -13387,6 +13391,15 @@ function formatScanReport(result) {
|
|
|
13387
13391
|
// src/tools/orient.ts
|
|
13388
13392
|
import { z as z22 } from "zod";
|
|
13389
13393
|
var PURPOSE_GAP_PREFIX = "purpose-gap-";
|
|
13394
|
+
function reportOrientWrapperBytes(toolResult, truncated) {
|
|
13395
|
+
try {
|
|
13396
|
+
const fullToolOutput = JSON.stringify({ content: toolResult.content ?? [] });
|
|
13397
|
+
const bytes = Buffer.byteLength(fullToolOutput, "utf8");
|
|
13398
|
+
void kernelMutation("agent.reportOrientMetric", { bytes, truncated }).catch(() => {
|
|
13399
|
+
});
|
|
13400
|
+
} catch {
|
|
13401
|
+
}
|
|
13402
|
+
}
|
|
13390
13403
|
async function markOrientedWithSnapshotFallback(agentSessionId, coherenceSnapshot) {
|
|
13391
13404
|
try {
|
|
13392
13405
|
await kernelCall("agent.markOriented", {
|
|
@@ -13589,7 +13602,7 @@ function registerOrientTool(server) {
|
|
|
13589
13602
|
orientationStatus2 = "failed";
|
|
13590
13603
|
}
|
|
13591
13604
|
}
|
|
13592
|
-
|
|
13605
|
+
const blankResult = {
|
|
13593
13606
|
content: [{ type: "text", text: scanLines.join("\n") }],
|
|
13594
13607
|
structuredContent: success(
|
|
13595
13608
|
"Workspace is blank. Use the start tool for guided setup.",
|
|
@@ -13597,6 +13610,8 @@ function registerOrientTool(server) {
|
|
|
13597
13610
|
[{ tool: "start", description: "Guided workspace setup", parameters: {} }]
|
|
13598
13611
|
)
|
|
13599
13612
|
};
|
|
13613
|
+
reportOrientWrapperBytes(blankResult, false);
|
|
13614
|
+
return blankResult;
|
|
13600
13615
|
}
|
|
13601
13616
|
const lines = [];
|
|
13602
13617
|
const isLowReadiness = readiness && readiness.score < 50;
|
|
@@ -13740,7 +13755,7 @@ function registerOrientTool(server) {
|
|
|
13740
13755
|
lines.push("");
|
|
13741
13756
|
for (const err of errors) lines.push(`- ${err}`);
|
|
13742
13757
|
}
|
|
13743
|
-
|
|
13758
|
+
const briefResult = {
|
|
13744
13759
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
13745
13760
|
structuredContent: success(
|
|
13746
13761
|
`Oriented (brief). Stage: ${readiness?.stage ?? "unknown"}.`,
|
|
@@ -13756,6 +13771,8 @@ function registerOrientTool(server) {
|
|
|
13756
13771
|
}
|
|
13757
13772
|
)
|
|
13758
13773
|
};
|
|
13774
|
+
reportOrientWrapperBytes(briefResult, orientEntries?._truncated === true);
|
|
13775
|
+
return briefResult;
|
|
13759
13776
|
}
|
|
13760
13777
|
const orientStage = readiness?.stage ?? "seeded";
|
|
13761
13778
|
if (isLowReadiness && wsCtx?.createdAt) {
|
|
@@ -14123,7 +14140,7 @@ function registerOrientTool(server) {
|
|
|
14123
14140
|
lines.push("---");
|
|
14124
14141
|
lines.push("_No active agent session. Call `session action=start` to begin a tracked session._");
|
|
14125
14142
|
}
|
|
14126
|
-
|
|
14143
|
+
const fullResult = {
|
|
14127
14144
|
content: [{ type: "text", text: lines.join("\n") }],
|
|
14128
14145
|
structuredContent: success(
|
|
14129
14146
|
`Oriented (full). Stage: ${orientStage}. ${isLowReadiness ? "Low readiness \u2014 gaps remain." : "Ready."}`,
|
|
@@ -14140,6 +14157,8 @@ function registerOrientTool(server) {
|
|
|
14140
14157
|
}
|
|
14141
14158
|
)
|
|
14142
14159
|
};
|
|
14160
|
+
reportOrientWrapperBytes(fullResult, orientEntries?._truncated === true);
|
|
14161
|
+
return fullResult;
|
|
14143
14162
|
})
|
|
14144
14163
|
);
|
|
14145
14164
|
}
|
|
@@ -14897,6 +14916,109 @@ function registerGovernanceTools(server) {
|
|
|
14897
14916
|
trackWriteTool(tool);
|
|
14898
14917
|
}
|
|
14899
14918
|
|
|
14919
|
+
// src/tools/documents.ts
|
|
14920
|
+
import { z as z26 } from "zod";
|
|
14921
|
+
var DOCUMENTS_ACTIONS = ["get-last-verified-brief"];
|
|
14922
|
+
var documentsSchema = z26.object({
|
|
14923
|
+
action: z26.enum(DOCUMENTS_ACTIONS).describe(
|
|
14924
|
+
"'get-last-verified-brief': fetch the most recent verified brief snapshot for a (templateId, scopeKey) pair. Returns the verified summary so agents can build delta narratives ('since you last verified, X workstreams advanced')."
|
|
14925
|
+
),
|
|
14926
|
+
templateId: z26.string().describe(
|
|
14927
|
+
"Brief template identifier \u2014 currently 'steering-brief' is the only registered template."
|
|
14928
|
+
),
|
|
14929
|
+
scopeKey: z26.string().describe(
|
|
14930
|
+
"Canonical scope key. Use 'workspace:<workspaceId>' for the full workspace brief, or 'initiative:<INI-ID>' for an initiative-scoped brief. The same formula is applied at write time (chainwork/docKernel/scopeKey.ts), so passing the wrong shape returns exists:false."
|
|
14931
|
+
)
|
|
14932
|
+
});
|
|
14933
|
+
function registerDocumentsTools(server) {
|
|
14934
|
+
server.registerTool(
|
|
14935
|
+
"documents",
|
|
14936
|
+
{
|
|
14937
|
+
title: "Documents",
|
|
14938
|
+
description: "Read agent-facing snapshots of verified briefs.\n\n**Actions:**\n- `get-last-verified-brief`: returns the most recent verified-brief snapshot for a (templateId, scopeKey) pair, including the at-a-glance markdown, workstream snapshots, cited entry IDs, and verification timestamp.\n\nUse this to build delta narratives ('since the last verified brief on Tuesday, two workstreams advanced and one new tension was captured').\n\nReturns `{ exists: false }` when no row matches. Returns `{ exists: true, summary: <snapshot>, verifiedAt }` when an S4 row is found, or `{ exists: true, summary: undefined, verifiedAt }` for legacy backfilled rows that pre-date snapshot capture.",
|
|
14939
|
+
inputSchema: documentsSchema,
|
|
14940
|
+
annotations: {
|
|
14941
|
+
readOnlyHint: true,
|
|
14942
|
+
destructiveHint: false,
|
|
14943
|
+
idempotentHint: true,
|
|
14944
|
+
openWorldHint: false
|
|
14945
|
+
}
|
|
14946
|
+
},
|
|
14947
|
+
thinWrapper(async (args) => {
|
|
14948
|
+
const parsed = parseOrFail(documentsSchema, args);
|
|
14949
|
+
if (!parsed.ok) return parsed.result;
|
|
14950
|
+
const { action, templateId, scopeKey } = parsed.data;
|
|
14951
|
+
return runWithToolContext(
|
|
14952
|
+
{ tool: "documents", action },
|
|
14953
|
+
() => handleGetLastVerifiedBrief(templateId, scopeKey)
|
|
14954
|
+
);
|
|
14955
|
+
})
|
|
14956
|
+
);
|
|
14957
|
+
}
|
|
14958
|
+
async function handleGetLastVerifiedBrief(templateId, scopeKey) {
|
|
14959
|
+
const result = await kernelQuery(
|
|
14960
|
+
"chainwork.getLastVerifiedBrief",
|
|
14961
|
+
{ templateId, scopeKey }
|
|
14962
|
+
);
|
|
14963
|
+
if (!result.exists) {
|
|
14964
|
+
const text = `No verified brief found for template '${templateId}', scope '${scopeKey}'.
|
|
14965
|
+
|
|
14966
|
+
This is normal for a never-verified initiative or workspace. If you expected a row here, check that the scope key matches the format produced at write time: 'workspace:<workspaceId>' or 'initiative:<INI-ID>'.`;
|
|
14967
|
+
return {
|
|
14968
|
+
content: [{ type: "text", text }],
|
|
14969
|
+
structuredContent: success(
|
|
14970
|
+
`No verified brief found for ${templateId} / ${scopeKey}.`,
|
|
14971
|
+
{ exists: false }
|
|
14972
|
+
)
|
|
14973
|
+
};
|
|
14974
|
+
}
|
|
14975
|
+
const verifiedAtIso = new Date(result.verifiedAt).toISOString();
|
|
14976
|
+
if (result.summary === void 0) {
|
|
14977
|
+
const text = `Verified brief found for template '${templateId}', scope '${scopeKey}', verified at ${verifiedAtIso}.
|
|
14978
|
+
|
|
14979
|
+
This row pre-dates snapshot capture (legacy backfill), so no summary is available. The verification timestamp itself is still authoritative \u2014 you can reason about staleness, just not delta narratives.`;
|
|
14980
|
+
return {
|
|
14981
|
+
content: [{ type: "text", text }],
|
|
14982
|
+
structuredContent: success(
|
|
14983
|
+
`Legacy verified brief at ${verifiedAtIso} (no summary).`,
|
|
14984
|
+
{ exists: true, summary: void 0, verifiedAt: result.verifiedAt }
|
|
14985
|
+
)
|
|
14986
|
+
};
|
|
14987
|
+
}
|
|
14988
|
+
const summary = result.summary;
|
|
14989
|
+
const lines = [
|
|
14990
|
+
`## Last verified brief \u2014 ${templateId} / ${scopeKey}`,
|
|
14991
|
+
`Verified at: ${verifiedAtIso} by ${summary.verifiedBy}`,
|
|
14992
|
+
`Chain synced at: ${new Date(summary.chainSyncedAt).toISOString()}`,
|
|
14993
|
+
"",
|
|
14994
|
+
`### At a glance (verbatim)`,
|
|
14995
|
+
summary.verifiedAtGlance || "(empty)",
|
|
14996
|
+
"",
|
|
14997
|
+
`### Workstreams at verification (${summary.verifiedWorkstreams.length})`
|
|
14998
|
+
];
|
|
14999
|
+
for (const ws of summary.verifiedWorkstreams) {
|
|
15000
|
+
lines.push(
|
|
15001
|
+
`- **${ws.entryId}** ${ws.name} \u2014 status: ${ws.status}` + (ws.whatChanged ? ` \u2014 ${ws.whatChanged}` : "")
|
|
15002
|
+
);
|
|
15003
|
+
}
|
|
15004
|
+
if (summary.citedEntryIds.length > 0) {
|
|
15005
|
+
lines.push("");
|
|
15006
|
+
lines.push(`### Cited entries (${summary.citedEntryIds.length})`);
|
|
15007
|
+
lines.push(summary.citedEntryIds.join(", "));
|
|
15008
|
+
}
|
|
15009
|
+
return {
|
|
15010
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
15011
|
+
structuredContent: success(
|
|
15012
|
+
`Verified brief found at ${verifiedAtIso} with ${summary.verifiedWorkstreams.length} workstream snapshot(s).`,
|
|
15013
|
+
{
|
|
15014
|
+
exists: true,
|
|
15015
|
+
summary,
|
|
15016
|
+
verifiedAt: result.verifiedAt
|
|
15017
|
+
}
|
|
15018
|
+
)
|
|
15019
|
+
};
|
|
15020
|
+
}
|
|
15021
|
+
|
|
14900
15022
|
// src/resources/index.ts
|
|
14901
15023
|
import { existsSync as existsSync4 } from "fs";
|
|
14902
15024
|
import { dirname as dirname2, join, resolve as resolve5 } from "path";
|
|
@@ -15402,12 +15524,12 @@ ${entry.labels.map((l) => `- ${l.name ?? l.slug}`).join("\n")}`);
|
|
|
15402
15524
|
}
|
|
15403
15525
|
|
|
15404
15526
|
// src/prompts/index.ts
|
|
15405
|
-
import { z as
|
|
15527
|
+
import { z as z27 } from "zod";
|
|
15406
15528
|
function registerPrompts(server) {
|
|
15407
15529
|
server.prompt(
|
|
15408
15530
|
"review-against-rules",
|
|
15409
15531
|
"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.",
|
|
15410
|
-
{ domain:
|
|
15532
|
+
{ domain: z27.string().describe("Business rule domain (e.g. 'Identity & Access', 'Governance & Decision-Making')") },
|
|
15411
15533
|
async ({ domain }) => {
|
|
15412
15534
|
const entries = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
|
|
15413
15535
|
const rules = entries.filter((e) => e.data?.domain === domain);
|
|
@@ -15460,7 +15582,7 @@ Provide a structured review with a compliance status for each rule (COMPLIANT /
|
|
|
15460
15582
|
server.prompt(
|
|
15461
15583
|
"name-check",
|
|
15462
15584
|
"Check variable names, field names, or API names against the glossary for terminology alignment. Flags drift from canonical terms.",
|
|
15463
|
-
{ names:
|
|
15585
|
+
{ names: z27.string().describe("Comma-separated list of names to check (e.g. 'vendor_id, compliance_level, formulator_type')") },
|
|
15464
15586
|
async ({ names }) => {
|
|
15465
15587
|
const terms = await kernelQuery("chain.listEntries", { collectionSlug: "glossary" });
|
|
15466
15588
|
const glossaryContext = terms.map(
|
|
@@ -15496,7 +15618,7 @@ Format as a table: Name | Status | Canonical Form | Action Needed`
|
|
|
15496
15618
|
server.prompt(
|
|
15497
15619
|
"draft-decision-record",
|
|
15498
15620
|
"Draft a structured decision record from a description of what was decided. Includes context from recent decisions and relevant rules.",
|
|
15499
|
-
{ context:
|
|
15621
|
+
{ context: z27.string().describe("Description of the decision (e.g. 'We decided to use MRSL v3.1 as the conformance baseline because...')") },
|
|
15500
15622
|
async ({ context }) => {
|
|
15501
15623
|
const recentDecisions = await kernelQuery("chain.listEntries", { collectionSlug: "decisions" });
|
|
15502
15624
|
const sorted = [...recentDecisions].sort((a, b) => (b.data?.date ?? "") > (a.data?.date ?? "") ? 1 : -1).slice(0, 5);
|
|
@@ -15534,8 +15656,8 @@ After drafting, I can log it using the capture tool with collection "decisions".
|
|
|
15534
15656
|
"draft-rule-from-context",
|
|
15535
15657
|
"Draft a new business rule from an observation or discovery made while coding. Fetches existing rules for the domain to ensure consistency.",
|
|
15536
15658
|
{
|
|
15537
|
-
observation:
|
|
15538
|
-
domain:
|
|
15659
|
+
observation: z27.string().describe("What you observed or discovered (e.g. 'Suppliers can have multiple org types in Gateway')"),
|
|
15660
|
+
domain: z27.string().describe("Which domain this rule belongs to (e.g. 'Governance & Decision-Making')")
|
|
15539
15661
|
},
|
|
15540
15662
|
async ({ observation, domain }) => {
|
|
15541
15663
|
const allRules = await kernelQuery("chain.listEntries", { collectionSlug: "business-rules" });
|
|
@@ -15679,6 +15801,7 @@ function createProductBrainServer() {
|
|
|
15679
15801
|
registerFacilitateTools(server);
|
|
15680
15802
|
registerAuditTools(server);
|
|
15681
15803
|
registerGovernanceTools(server);
|
|
15804
|
+
registerDocumentsTools(server);
|
|
15682
15805
|
registerResources(server);
|
|
15683
15806
|
registerPrompts(server);
|
|
15684
15807
|
return server;
|
|
@@ -15723,4 +15846,4 @@ export {
|
|
|
15723
15846
|
createProductBrainServer,
|
|
15724
15847
|
initFeatureFlags
|
|
15725
15848
|
};
|
|
15726
|
-
//# sourceMappingURL=chunk-
|
|
15849
|
+
//# sourceMappingURL=chunk-GJFGULJV.js.map
|