@unbrained/pm-cli 2026.8.22 → 2026.8.24
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/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +42 -1
- package/dist/cli/description-stdin.js +5 -4
- package/dist/cli/error-guidance.d.ts +13 -0
- package/dist/cli/error-guidance.js +62 -6
- package/dist/cli/extension-command-help.d.ts +5 -0
- package/dist/cli/extension-command-help.js +6 -2
- package/dist/cli/help-content.d.ts +5 -0
- package/dist/cli/help-content.js +56 -3
- package/dist/cli/help-json-payload.d.ts +5 -2
- package/dist/cli/help-json-payload.js +57 -17
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.js +39 -5
- package/dist/cli/register-annotations.js +5 -5
- package/dist/cli/register-mutation.js +77 -31
- package/dist/cli/register-operations.d.ts +73 -0
- package/dist/cli/register-operations.js +39 -14
- package/dist/cli/register-setup.js +3 -3
- package/dist/cli/schema-registration-helpers.d.ts +8 -1
- package/dist/cli/schema-registration-helpers.js +14 -5
- package/dist/cli-bundle/bundle-manifest.json +155 -155
- package/dist/cli-bundle/chunks/chunk-AGUL3HUT.js +3 -0
- package/dist/cli-bundle/chunks/{chunk-WG4STC36.js → chunk-DJNJBWAQ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MYYI3ZOA.js → chunk-I5Q7QSZX.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-IW72J5FW.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-BWX4SK46.js → chunk-L22NP5MA.js} +66 -66
- package/dist/cli-bundle/chunks/chunk-MKE6MD2K.js +36 -0
- package/dist/cli-bundle/chunks/{chunk-MZTZQTMS.js → chunk-NXBFO63A.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-TEQDR5KI.js +202 -0
- package/dist/cli-bundle/chunks/chunk-X7WWQDYQ.js +2 -0
- package/dist/cli-bundle/chunks/chunk-YOLLRCLY.js +13 -0
- package/dist/cli-bundle/chunks/{chunk-U6GQ4VMV.js → chunk-ZAVCS2GH.js} +4 -4
- package/dist/cli-bundle/chunks/{register-list-query-HZKBQNWW.js → register-list-query-37A4P6O4.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-TBJDHYIT.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-WRZNEBUM.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-QK4OTOXN.js → register-setup-H4PDLACD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GMYPD4FX.js → chunk-4WP7LNE3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-6MUTDXMP.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-6Z24ZMU3.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-2ARQGDDW.js → chunk-BFA6KKCI.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-CWCN5RLO.js +26 -0
- package/dist/cli-bundle/focused-chunks/chunk-FCTT4CZU.js +5 -0
- package/dist/cli-bundle/focused-chunks/chunk-GJR6YEMR.js +156 -0
- package/dist/cli-bundle/focused-chunks/{chunk-2POVTNLY.js → chunk-IMWTYKII.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-D6RBZEJJ.js → chunk-IZNRRCU3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-PMGJUFNQ.js → chunk-MNPECIRL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-A2BC5PQL.js → chunk-O4ZXNJMT.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-Q63PSLO4.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-QBP5FSBX.js +4 -0
- package/dist/cli-bundle/focused-chunks/{chunk-R6SR45XU.js → chunk-QV5UP27O.js} +48 -47
- package/dist/cli-bundle/focused-chunks/chunk-RASVBJX5.js +8 -0
- package/dist/cli-bundle/focused-chunks/{chunk-E2EWYPY6.js → chunk-RPRLENVA.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-TOFVXBWA.js +19 -0
- package/dist/cli-bundle/focused-chunks/{chunk-6S2MO3Q3.js → chunk-WZLSSGEU.js} +2 -2
- package/dist/cli-bundle/main.js +18 -17
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +2 -2
- package/dist/cli-bundle/sdk-core.js +41 -41
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +33 -32
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +6 -5
- package/dist/core/config/nested-settings.js +8 -2
- package/dist/core/config/positional-value.d.ts +1 -1
- package/dist/core/config/positional-value.js +5 -2
- package/dist/core/extensions/command-metadata-contract.d.ts +10 -0
- package/dist/core/extensions/command-metadata-contract.js +23 -0
- package/dist/core/extensions/command-visibility-tier.js +12 -2
- package/dist/core/extensions/extension-types.d.ts +6 -0
- package/dist/core/extensions/extension-types.js +2 -2
- package/dist/core/extensions/loader.js +4 -3
- package/dist/core/history/history.js +3 -3
- package/dist/core/io/body-file.js +7 -2
- package/dist/core/io/bulk-ids-input.d.ts +24 -0
- package/dist/core/io/bulk-ids-input.js +113 -0
- package/dist/core/item/item-format.js +66 -12
- package/dist/core/item/parse.d.ts +22 -2
- package/dist/core/item/parse.js +97 -4
- package/dist/core/reproducibility/context.d.ts +4 -0
- package/dist/core/reproducibility/context.js +14 -8
- package/dist/core/shared/author.d.ts +55 -1
- package/dist/core/shared/author.js +333 -16
- package/dist/core/shared/constants.js +3 -2
- package/dist/core/store/settings-validator.d.ts +1 -0
- package/dist/core/store/settings-validator.js +6 -3
- package/dist/core/store/settings.js +5 -2
- package/dist/mcp/server.d.ts +4 -3
- package/dist/mcp/server.js +44 -16
- package/dist/sdk/agent/identity-config.d.ts +63 -0
- package/dist/sdk/agent/identity-config.js +107 -0
- package/dist/sdk/agent/refusal-closure-census.d.ts +66 -0
- package/dist/sdk/agent/refusal-closure-census.js +144 -0
- package/dist/sdk/agent/refusal-corpus-contracts.d.ts +76 -0
- package/dist/sdk/agent/refusal-corpus-contracts.js +194 -0
- package/dist/sdk/agent-capability-contracts.d.ts +34 -1
- package/dist/sdk/agent-capability-contracts.js +104 -6
- package/dist/sdk/annotations.d.ts +2 -0
- package/dist/sdk/annotations.js +25 -7
- package/dist/sdk/cli-contracts/agent-output-contracts.js +6 -4
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -0
- package/dist/sdk/cli-contracts/enum-contracts.js +9 -2
- package/dist/sdk/cli-contracts/flag-contracts.js +9 -2
- package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -4
- package/dist/sdk/cli-contracts/registration-helpers.js +5 -2
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +58 -2
- package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
- package/dist/sdk/cli-contracts/tool-schema.js +14 -3
- package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +4 -1
- package/dist/sdk/cli-contracts/typed-action-inputs.js +2 -2
- package/dist/sdk/cli-contracts.d.ts +3 -3
- package/dist/sdk/cli-contracts.js +4 -4
- package/dist/sdk/comments.js +15 -7
- package/dist/sdk/config.d.ts +6 -1
- package/dist/sdk/config.js +119 -14
- package/dist/sdk/context-intent-contracts.js +4 -2
- package/dist/sdk/core-governance.d.ts +1 -1
- package/dist/sdk/core-governance.js +3 -3
- package/dist/sdk/extension/scaffold.js +11 -5
- package/dist/sdk/flag-invocation-contracts.d.ts +2 -0
- package/dist/sdk/flag-invocation-contracts.js +30 -3
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +83 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +87 -2
- package/dist/sdk/governance/assurance-action.js +30 -10
- package/dist/sdk/governance/validate.d.ts +2 -2
- package/dist/sdk/governance/validate.js +39 -14
- package/dist/sdk/guide-topics.d.ts +0 -5
- package/dist/sdk/guide-topics.js +28 -2
- package/dist/sdk/history-compact.d.ts +2 -1
- package/dist/sdk/history-compact.js +24 -5
- package/dist/sdk/history-mcp.js +11 -10
- package/dist/sdk/index.d.ts +8 -2
- package/dist/sdk/index.js +9 -3
- package/dist/sdk/item-transaction.js +19 -12
- package/dist/sdk/lifecycle/append.js +4 -4
- package/dist/sdk/lifecycle/close-many.js +16 -7
- package/dist/sdk/lifecycle/create.js +33 -22
- package/dist/sdk/lifecycle/plan.js +24 -6
- package/dist/sdk/lifecycle/update-many.js +15 -8
- package/dist/sdk/lifecycle/update.d.ts +2 -0
- package/dist/sdk/lifecycle/update.js +37 -25
- package/dist/sdk/merge/three-way.js +105 -26
- package/dist/sdk/read-output-budget.d.ts +21 -0
- package/dist/sdk/read-output-budget.js +39 -2
- package/dist/sdk/read-output-contracts.d.ts +5 -3
- package/dist/sdk/read-output-contracts.js +20 -12
- package/dist/sdk/reproducibility/process.d.ts +19 -0
- package/dist/sdk/reproducibility/process.js +88 -0
- package/dist/sdk/runtime-extended-actions.js +5 -3
- package/dist/sdk/runtime-input.d.ts +4 -0
- package/dist/sdk/runtime-input.js +98 -23
- package/dist/sdk/runtime-primitives.d.ts +3 -2
- package/dist/sdk/runtime-primitives.js +5 -4
- package/dist/sdk/runtime.js +11 -23
- package/dist/sdk/scheduling-shortcuts.js +5 -3
- package/dist/sdk/structured-mutations.js +10 -3
- package/dist/sdk/test/batch.d.ts +6 -0
- package/dist/sdk/test/batch.js +15 -3
- package/dist/sdk/test/entry.d.ts +1 -1
- package/dist/sdk/test/entry.js +3 -2
- package/dist/sdk/test/execution.d.ts +28 -3
- package/dist/sdk/test/execution.js +193 -34
- package/dist/sdk/test/parsers.d.ts +6 -0
- package/dist/sdk/test/parsers.js +21 -2
- package/dist/sdk/test/trust.d.ts +33 -0
- package/dist/sdk/test/trust.js +207 -0
- package/dist/sdk/workspace-contracts.d.ts +3 -0
- package/dist/sdk/workspace-contracts.js +3 -2
- package/dist/types.d.ts +23 -0
- package/dist/types.js +2 -2
- package/docs/AGENT_PROVENANCE_ADR.md +41 -5
- package/docs/CONFIGURATION.md +4 -0
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +19 -2
- package/docs/MERGE_SAFETY.md +15 -1
- package/docs/README.md +2 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +11 -1
- package/docs/RELEASING.md +40 -21
- package/docs/REPRODUCIBLE_WORKSPACES.md +42 -8
- package/docs/SCRIPTING.md +62 -3
- package/docs/SDK.md +17 -0
- package/docs/SDK_AGENT_SESSION_CONTEXT.md +6 -4
- package/docs/SDK_EVIDENCE_TRACEABILITY.md +1 -1
- package/docs/TESTING.md +75 -8
- package/docs/agent-task-token-baseline.json +2 -2
- package/docs/generated/AGENT_CAPABILITY_ROUTING.md +17 -0
- package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
- package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
- package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +355 -0
- package/marketplace.json +2 -2
- package/package.json +2 -2
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/README.md +9 -11
- package/packages/pm-command-kit/extensions/command-kit/index.ts +3 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/extensions/guide-shell/index.ts +10 -0
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/generate-agent-capability-surfaces.mjs +27 -1
- package/sdk/public-surface.json +642 -28
- package/dist/cli-bundle/chunks/chunk-EMWDM5FI.js +0 -13
- package/dist/cli-bundle/chunks/chunk-HYG6LRL4.js +0 -200
- package/dist/cli-bundle/chunks/chunk-QI2CT3IX.js +0 -2
- package/dist/cli-bundle/chunks/chunk-SMWXHMVB.js +0 -35
- package/dist/cli-bundle/chunks/chunk-VMMIL3SI.js +0 -2
- package/dist/cli-bundle/chunks/chunk-YBPJAOQQ.js +0 -3
- package/dist/cli-bundle/chunks/register-mutation-HTKEEGRD.js +0 -20
- package/dist/cli-bundle/chunks/register-operations-6EMRWJJY.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-2AZT5WXZ.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-3LKU6PTJ.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-5SHSBMX2.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-C4S4A4JJ.js +0 -5
- package/dist/cli-bundle/focused-chunks/chunk-L5LDSRO2.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-MB37AYN6.js +0 -26
- package/dist/cli-bundle/focused-chunks/chunk-MCOR37QK.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-PH2OXXVZ.js +0 -18
- package/dist/cli-bundle/focused-chunks/chunk-WZE4LIPW.js +0 -8
package/dist/mcp/server.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Runs the MCP server adapter that exposes pm actions and contracts to external agents.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
8
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8ce8addc-e47e-5bb9-8a94-0959a1a535e9")}catch(e){}}();
|
|
9
9
|
import { realpathSync } from "node:fs";
|
|
10
10
|
import { readFile } from "node:fs/promises";
|
|
11
11
|
import path from "node:path";
|
|
@@ -18,10 +18,14 @@ import { NARROW_TOOL_ACTIONS, TOOLS } from "./tool-definitions.js";
|
|
|
18
18
|
import { normalizeWorkspaceToolArguments, resolveMcpToolAccess, resolveMcpToolSurface, } from "./runtime-capabilities.js";
|
|
19
19
|
import { PM_MCP_PROMPT_CONTRACTS, PM_MCP_RESOURCE_CONTRACTS, } from "../sdk/agent-capability-contracts.js";
|
|
20
20
|
import { commitItemMutations } from "../sdk/item-transaction.js";
|
|
21
|
-
import { isRuntimeRecord } from "../sdk/runtime-input.js";
|
|
21
|
+
import { isRuntimeRecord, markMcpMutationTransportInput, } from "../sdk/runtime-input.js";
|
|
22
22
|
import { attachOutputTokenAccounting } from "../sdk/output-token-accounting.js";
|
|
23
|
+
import { createReproducibleProcessRunner, runWithReproducibleProcessEnvironment, } from "../sdk/reproducibility/process.js";
|
|
23
24
|
import { parseAtomicMutationControls, resolveItemMutationDocument, } from "../sdk/structured-mutations.js";
|
|
24
25
|
import { resolveAuthor, resolvePmRoot } from "../sdk/runtime-primitives.js";
|
|
26
|
+
function runMcpAction(args) {
|
|
27
|
+
return runAction(markMcpMutationTransportInput(args));
|
|
28
|
+
}
|
|
25
29
|
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
26
30
|
function resolvePmPackageRoot() {
|
|
27
31
|
return fileURLToPath(new URL("../..", import.meta.url));
|
|
@@ -96,7 +100,7 @@ function detectUnexpectedTopLevelKeys(toolName, args, toolDeclaredKeys = declare
|
|
|
96
100
|
return warnings;
|
|
97
101
|
}
|
|
98
102
|
const HANDLERS = {
|
|
99
|
-
pm_run: (args) =>
|
|
103
|
+
pm_run: (args) => runMcpAction(args),
|
|
100
104
|
pm_mutate: async (args) => {
|
|
101
105
|
const transactionId = readRequiredString(args, "transactionId");
|
|
102
106
|
const controls = parseAtomicMutationControls(args);
|
|
@@ -137,7 +141,7 @@ const HANDLERS = {
|
|
|
137
141
|
},
|
|
138
142
|
...Object.fromEntries(Object.entries(NARROW_TOOL_ACTIONS).map(([tool, action]) => [
|
|
139
143
|
tool,
|
|
140
|
-
(args) =>
|
|
144
|
+
(args) => runMcpAction({ ...args, action }),
|
|
141
145
|
])),
|
|
142
146
|
};
|
|
143
147
|
/** Resolve the pm action a tools/call invocation will dispatch, when knowable. */
|
|
@@ -227,17 +231,18 @@ function resultContent(result, warnings, tokenAccounting = false) {
|
|
|
227
231
|
function errorContent(error) {
|
|
228
232
|
const code = error instanceof PmCliError ? error.exitCode : 1;
|
|
229
233
|
const message = error instanceof Error ? error.message : String(error);
|
|
234
|
+
const details = error instanceof PmCliError ? error.context : undefined;
|
|
230
235
|
return {
|
|
231
236
|
isError: true,
|
|
232
237
|
content: [
|
|
233
238
|
{
|
|
234
239
|
type: "text",
|
|
235
|
-
text: JSON.stringify({ error: message, code }, null, 2),
|
|
240
|
+
text: JSON.stringify({ error: message, code, details }, null, 2),
|
|
236
241
|
},
|
|
237
242
|
],
|
|
238
243
|
// Keep `result` present on the error envelope so consumers can read
|
|
239
244
|
// `structuredContent.result` uniformly across success and failure (pm-l40h).
|
|
240
|
-
structuredContent: { result: null, error: message, code },
|
|
245
|
+
structuredContent: { result: null, error: message, code, details },
|
|
241
246
|
};
|
|
242
247
|
}
|
|
243
248
|
/** Retain at most 32 own, valid provenance values without cloning unbounded input. */
|
|
@@ -351,10 +356,10 @@ async function readWorkspaceResource(uri, params) {
|
|
|
351
356
|
}
|
|
352
357
|
let value;
|
|
353
358
|
if (uri === "pm://workspace/context") {
|
|
354
|
-
value = await
|
|
359
|
+
value = await runMcpAction({ ...args, action: "context", limit: 10 });
|
|
355
360
|
}
|
|
356
361
|
else if (uri === "pm://workspace/claims") {
|
|
357
|
-
value = await
|
|
362
|
+
value = await runMcpAction({
|
|
358
363
|
...args,
|
|
359
364
|
action: "list",
|
|
360
365
|
status: "in_progress",
|
|
@@ -362,7 +367,11 @@ async function readWorkspaceResource(uri, params) {
|
|
|
362
367
|
});
|
|
363
368
|
}
|
|
364
369
|
else if (uri === "pm://workspace/focus") {
|
|
365
|
-
value = await
|
|
370
|
+
value = await runMcpAction({
|
|
371
|
+
...args,
|
|
372
|
+
action: "focus",
|
|
373
|
+
subcommand: "show",
|
|
374
|
+
});
|
|
366
375
|
}
|
|
367
376
|
else {
|
|
368
377
|
const guidePath = path.join(cwd, "AGENTS.md");
|
|
@@ -403,7 +412,7 @@ function renderWorkflowPrompt(params) {
|
|
|
403
412
|
};
|
|
404
413
|
}
|
|
405
414
|
/** Implements handle request for the public runtime surface of this module. */
|
|
406
|
-
|
|
415
|
+
async function handleRequestInReproducibleContext(request) {
|
|
407
416
|
if (!request.id && request.method?.startsWith("notifications/")) {
|
|
408
417
|
return undefined;
|
|
409
418
|
}
|
|
@@ -459,19 +468,24 @@ export async function handleRequest(request) {
|
|
|
459
468
|
}
|
|
460
469
|
throw new PmCliError(`Unsupported MCP method: ${request.method ?? "(missing)"}`, 64);
|
|
461
470
|
}
|
|
471
|
+
/** Dispatch one MCP request under supported process-level reproducibility settings. */
|
|
472
|
+
export async function handleRequest(request) {
|
|
473
|
+
return runWithReproducibleProcessEnvironment(process.env, () => handleRequestInReproducibleContext(request));
|
|
474
|
+
}
|
|
462
475
|
function writeResponse(id, payload) {
|
|
463
476
|
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, result: payload })}\n`);
|
|
464
477
|
}
|
|
465
478
|
function writeError(id, error) {
|
|
466
479
|
const code = error instanceof PmCliError ? error.exitCode : -32603;
|
|
467
480
|
const message = error instanceof Error ? error.message : String(error);
|
|
468
|
-
|
|
481
|
+
const data = error instanceof PmCliError ? error.context : undefined;
|
|
482
|
+
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, error: { code, message, data } })}\n`);
|
|
469
483
|
}
|
|
470
484
|
// pm-3puw: parse one JSON-RPC line, dispatch it, and write the response. Kept
|
|
471
485
|
// as a standalone async unit so the stdio loop can enqueue it onto a serial
|
|
472
486
|
// queue (process lines in arrival order) and tests can drive it directly.
|
|
473
487
|
/** Implements process rpc line for the public runtime surface of this module. */
|
|
474
|
-
|
|
488
|
+
async function processRpcLineWithHandler(line, requestHandler) {
|
|
475
489
|
if (line.trim().length === 0) {
|
|
476
490
|
return;
|
|
477
491
|
}
|
|
@@ -492,7 +506,7 @@ export async function processRpcLine(line) {
|
|
|
492
506
|
}
|
|
493
507
|
const shouldRespond = Object.prototype.hasOwnProperty.call(request, "id");
|
|
494
508
|
try {
|
|
495
|
-
const result = await
|
|
509
|
+
const result = await requestHandler(request);
|
|
496
510
|
if (shouldRespond && result !== undefined) {
|
|
497
511
|
writeResponse(request.id, result);
|
|
498
512
|
}
|
|
@@ -509,6 +523,10 @@ export async function processRpcLine(line) {
|
|
|
509
523
|
}
|
|
510
524
|
}
|
|
511
525
|
}
|
|
526
|
+
/** Implements process rpc line for the public runtime surface of this module. */
|
|
527
|
+
export async function processRpcLine(line) {
|
|
528
|
+
await processRpcLineWithHandler(line, handleRequest);
|
|
529
|
+
}
|
|
512
530
|
/** Implements start mcp server for the public runtime surface of this module. */
|
|
513
531
|
export function startMcpServer() {
|
|
514
532
|
const rl = readline.createInterface({
|
|
@@ -520,8 +538,18 @@ export function startMcpServer() {
|
|
|
520
538
|
// concurrently, so a client that pipelined two mutations on the same item
|
|
521
539
|
// (without awaiting the first response) hit a lock conflict on the second.
|
|
522
540
|
const queue = createSerialQueue();
|
|
541
|
+
let processLine;
|
|
542
|
+
try {
|
|
543
|
+
const runInProcessContext = createReproducibleProcessRunner(process.env);
|
|
544
|
+
processLine = (line) => runInProcessContext(() => processRpcLineWithHandler(line, handleRequestInReproducibleContext));
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
// Preserve one typed JSON-RPC error per request when process configuration
|
|
548
|
+
// is invalid; processRpcLine resolves the same configuration fail-closed.
|
|
549
|
+
processLine = processRpcLine;
|
|
550
|
+
}
|
|
523
551
|
rl.on("line", (line) => {
|
|
524
|
-
void queue.enqueue(() =>
|
|
552
|
+
void queue.enqueue(() => processLine(line));
|
|
525
553
|
});
|
|
526
554
|
}
|
|
527
555
|
// npm bin entries are symlinks (node_modules/.bin/pm-mcp -> dist/mcp/server.js),
|
|
@@ -600,7 +628,7 @@ export const _testOnly = {
|
|
|
600
628
|
get readStringArray() {
|
|
601
629
|
return readRuntimeTestHook("readStringArray");
|
|
602
630
|
},
|
|
603
|
-
runAction,
|
|
631
|
+
runAction: runMcpAction,
|
|
604
632
|
get updateManyOptionsFromFlat() {
|
|
605
633
|
return readRuntimeTestHook("updateManyOptionsFromFlat");
|
|
606
634
|
},
|
|
@@ -621,4 +649,4 @@ if (isInvokedAsMcpMainModule(process.argv[1], import.meta.url)) {
|
|
|
621
649
|
}
|
|
622
650
|
/* c8 ignore stop */
|
|
623
651
|
//# sourceMappingURL=server.js.map
|
|
624
|
-
//# debugId=
|
|
652
|
+
//# debugId=8ce8addc-e47e-5bb9-8a94-0959a1a535e9
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/agent-identity-config
|
|
3
|
+
*
|
|
4
|
+
* Pure and versioned mutation planning for legacy author interpretation. The
|
|
5
|
+
* public summaries deliberately expose counts and revisions, never alias
|
|
6
|
+
* spellings, so config discovery is useful without leaking historical names.
|
|
7
|
+
*/
|
|
8
|
+
/** Persisted legacy-author interpretation vocabulary. */
|
|
9
|
+
export interface AgentIdentityVocabulary {
|
|
10
|
+
/** Monotonic interpretation revision. */
|
|
11
|
+
version: number;
|
|
12
|
+
/** Exact legacy author spelling to canonical harness namespace. */
|
|
13
|
+
aliases: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
/** Privacy-safe vocabulary projection used by config get/list/export. */
|
|
16
|
+
export interface AgentIdentityVocabularySummary {
|
|
17
|
+
/** Current interpretation revision. */
|
|
18
|
+
version: number;
|
|
19
|
+
/** Number of exact legacy spellings configured. */
|
|
20
|
+
alias_count: number;
|
|
21
|
+
}
|
|
22
|
+
/** Supported vocabulary mutations. */
|
|
23
|
+
export type AgentIdentityVocabularyOperation = "add" | "remove" | "clear";
|
|
24
|
+
/** One typed vocabulary mutation and optional residual-coverage census. */
|
|
25
|
+
export interface AgentIdentityVocabularyMutationInput {
|
|
26
|
+
/** Exact operation applied to the vocabulary. */
|
|
27
|
+
operation: AgentIdentityVocabularyOperation;
|
|
28
|
+
/** Exact legacy spelling required by add/remove. */
|
|
29
|
+
legacy_author?: string;
|
|
30
|
+
/** Canonical lowercase harness namespace required by add. */
|
|
31
|
+
canonical_harness?: string;
|
|
32
|
+
/** Optional bounded author census used only to count still-unmapped values. */
|
|
33
|
+
observed_authors?: readonly string[];
|
|
34
|
+
}
|
|
35
|
+
/** Privacy-safe dry-run or committed mutation preview. */
|
|
36
|
+
export interface AgentIdentityVocabularyMutationPreview {
|
|
37
|
+
/** Operation that was evaluated. */
|
|
38
|
+
operation: AgentIdentityVocabularyOperation;
|
|
39
|
+
/** Whether persistence would change. */
|
|
40
|
+
changed: boolean;
|
|
41
|
+
/** Revision before the operation. */
|
|
42
|
+
version_before: number;
|
|
43
|
+
/** Revision after the operation, equal when idempotent. */
|
|
44
|
+
version_after: number;
|
|
45
|
+
/** Alias count after the operation. */
|
|
46
|
+
alias_count: number;
|
|
47
|
+
/** Unique non-canonical authors not covered after the operation. */
|
|
48
|
+
residual_author_count: number;
|
|
49
|
+
}
|
|
50
|
+
/** Planned vocabulary plus a privacy-safe result preview. */
|
|
51
|
+
export interface AgentIdentityVocabularyMutationPlan {
|
|
52
|
+
/** Complete value suitable for settings persistence. */
|
|
53
|
+
vocabulary: AgentIdentityVocabulary;
|
|
54
|
+
/** Public mutation result with no alias spellings. */
|
|
55
|
+
preview: AgentIdentityVocabularyMutationPreview;
|
|
56
|
+
}
|
|
57
|
+
/** Return only the revision and count suitable for config discovery surfaces. */
|
|
58
|
+
export declare function summarizeAgentIdentityVocabulary(vocabulary: AgentIdentityVocabulary | undefined): AgentIdentityVocabularySummary;
|
|
59
|
+
/**
|
|
60
|
+
* Validate and plan one exact mutation. A real change increments the revision
|
|
61
|
+
* exactly once; identical adds and absent removes are idempotent.
|
|
62
|
+
*/
|
|
63
|
+
export declare function planAgentIdentityVocabularyMutation(current: AgentIdentityVocabulary | undefined, input: AgentIdentityVocabularyMutationInput): AgentIdentityVocabularyMutationPlan;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/agent-identity-config
|
|
3
|
+
*
|
|
4
|
+
* Pure and versioned mutation planning for legacy author interpretation. The
|
|
5
|
+
* public summaries deliberately expose counts and revisions, never alias
|
|
6
|
+
* spellings, so config discovery is useful without leaking historical names.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="09703f32-9491-5d3a-9f90-f038d9982e17")}catch(e){}}();
|
|
10
|
+
const HARNESS_NAMESPACE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
11
|
+
const MAX_AUTHOR_LENGTH = 128;
|
|
12
|
+
const MAX_OBSERVED_AUTHORS = 10_000;
|
|
13
|
+
function requireLegacyAuthor(value) {
|
|
14
|
+
const author = value?.trim();
|
|
15
|
+
if (!author || author === "__proto__" || author.length > MAX_AUTHOR_LENGTH) {
|
|
16
|
+
throw new Error(`A legacy author must contain 1-${MAX_AUTHOR_LENGTH} characters.`);
|
|
17
|
+
}
|
|
18
|
+
return author;
|
|
19
|
+
}
|
|
20
|
+
function requireCanonicalHarness(value) {
|
|
21
|
+
const harness = value?.trim().toLowerCase();
|
|
22
|
+
if (!harness || !HARNESS_NAMESPACE_PATTERN.test(harness)) {
|
|
23
|
+
throw new Error("A canonical harness must be a lowercase dash-separated namespace.");
|
|
24
|
+
}
|
|
25
|
+
return harness;
|
|
26
|
+
}
|
|
27
|
+
function orderedAliases(aliases) {
|
|
28
|
+
return Object.fromEntries(Object.entries(aliases).sort(([left], [right]) => left.localeCompare(right)));
|
|
29
|
+
}
|
|
30
|
+
function countResidualAuthors(observed, aliases) {
|
|
31
|
+
const residual = new Set();
|
|
32
|
+
for (const raw of (observed ?? []).slice(0, MAX_OBSERVED_AUTHORS)) {
|
|
33
|
+
const author = raw.trim().slice(0, MAX_AUTHOR_LENGTH);
|
|
34
|
+
if (author.length === 0 ||
|
|
35
|
+
author.startsWith("harness:") ||
|
|
36
|
+
Object.hasOwn(aliases, author)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
residual.add(author);
|
|
40
|
+
}
|
|
41
|
+
return residual.size;
|
|
42
|
+
}
|
|
43
|
+
function applyAddOperation(aliases, input) {
|
|
44
|
+
const legacyAuthor = requireLegacyAuthor(input.legacy_author);
|
|
45
|
+
const canonicalHarness = requireCanonicalHarness(input.canonical_harness);
|
|
46
|
+
if (legacyAuthor === canonicalHarness ||
|
|
47
|
+
legacyAuthor === `harness:${canonicalHarness}` ||
|
|
48
|
+
legacyAuthor.startsWith("harness:")) {
|
|
49
|
+
throw new Error(`The legacy author "${legacyAuthor}" is already canonical and must not be aliased.`);
|
|
50
|
+
}
|
|
51
|
+
if (aliases[legacyAuthor] === canonicalHarness)
|
|
52
|
+
return false;
|
|
53
|
+
aliases[legacyAuthor] = canonicalHarness;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
function applyVocabularyOperation(aliases, input) {
|
|
57
|
+
if (input.operation === "add")
|
|
58
|
+
return applyAddOperation(aliases, input);
|
|
59
|
+
if (input.operation === "remove") {
|
|
60
|
+
const legacyAuthor = requireLegacyAuthor(input.legacy_author);
|
|
61
|
+
if (!Object.hasOwn(aliases, legacyAuthor))
|
|
62
|
+
return false;
|
|
63
|
+
delete aliases[legacyAuthor];
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
if (input.operation === "clear") {
|
|
67
|
+
const changed = Object.keys(aliases).length > 0;
|
|
68
|
+
for (const key of Object.keys(aliases))
|
|
69
|
+
delete aliases[key];
|
|
70
|
+
return changed;
|
|
71
|
+
}
|
|
72
|
+
const exhaustive = input.operation;
|
|
73
|
+
throw new Error(`Unsupported vocabulary operation: ${String(exhaustive)}`);
|
|
74
|
+
}
|
|
75
|
+
/** Return only the revision and count suitable for config discovery surfaces. */
|
|
76
|
+
export function summarizeAgentIdentityVocabulary(vocabulary) {
|
|
77
|
+
return {
|
|
78
|
+
version: vocabulary?.version ?? 1,
|
|
79
|
+
alias_count: Object.keys(vocabulary?.aliases ?? {}).length,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Validate and plan one exact mutation. A real change increments the revision
|
|
84
|
+
* exactly once; identical adds and absent removes are idempotent.
|
|
85
|
+
*/
|
|
86
|
+
export function planAgentIdentityVocabularyMutation(current, input) {
|
|
87
|
+
const versionBefore = current?.version ?? 1;
|
|
88
|
+
const aliases = { ...current?.aliases };
|
|
89
|
+
const changed = applyVocabularyOperation(aliases, input);
|
|
90
|
+
const vocabulary = {
|
|
91
|
+
version: changed ? versionBefore + 1 : versionBefore,
|
|
92
|
+
aliases: orderedAliases(aliases),
|
|
93
|
+
};
|
|
94
|
+
return {
|
|
95
|
+
vocabulary,
|
|
96
|
+
preview: {
|
|
97
|
+
operation: input.operation,
|
|
98
|
+
changed,
|
|
99
|
+
version_before: versionBefore,
|
|
100
|
+
version_after: vocabulary.version,
|
|
101
|
+
alias_count: Object.keys(vocabulary.aliases).length,
|
|
102
|
+
residual_author_count: countResidualAuthors(input.observed_authors, vocabulary.aliases),
|
|
103
|
+
},
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=identity-config.js.map
|
|
107
|
+
//# debugId=09703f32-9491-5d3a-9f90-f038d9982e17
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/agent/refusal-closure-census
|
|
3
|
+
*
|
|
4
|
+
* Joins the complete emitted error vocabulary to every executable refusal
|
|
5
|
+
* corpus. Missing proof remains an explicit row; no catalog code disappears
|
|
6
|
+
* merely because it has not yet received a probe.
|
|
7
|
+
*/
|
|
8
|
+
import type { PmErrorCodeContract } from "../error-code-catalog.js";
|
|
9
|
+
import type { PmClosedDomainContract } from "./closed-domain-contracts.js";
|
|
10
|
+
import type { PmGrammarRefusalContract } from "./refusal-corpus-contracts.js";
|
|
11
|
+
/** Evidence family that makes an error code executable. */
|
|
12
|
+
export type PmRefusalEvidenceKind = "owned_state" | "closed_domain" | "grammar";
|
|
13
|
+
/** One complete-catalog closure row. */
|
|
14
|
+
export interface PmRefusalClosureCensusRow {
|
|
15
|
+
/** Declared machine-readable error code. */
|
|
16
|
+
code: string;
|
|
17
|
+
/** Canonical compatibility-group code. */
|
|
18
|
+
canonical_code: string;
|
|
19
|
+
/** Whether at least one executable probe reaches the compatibility group. */
|
|
20
|
+
disposition: "executable" | "uncovered";
|
|
21
|
+
/** Evidence families contributing executable probes. */
|
|
22
|
+
evidence_kinds: PmRefusalEvidenceKind[];
|
|
23
|
+
/** Stable executable probe identities. */
|
|
24
|
+
probe_ids: string[];
|
|
25
|
+
}
|
|
26
|
+
/** Full emitted-vocabulary refusal closure receipt. */
|
|
27
|
+
export interface PmRefusalClosureCensusReport {
|
|
28
|
+
/** True only when every catalog code belongs to a probed compatibility group. */
|
|
29
|
+
ok: boolean;
|
|
30
|
+
/** Number of emitted codes in the catalog. */
|
|
31
|
+
catalog_error_code_count: number;
|
|
32
|
+
/** Number of codes backed by executable evidence. */
|
|
33
|
+
executable_error_code_count: number;
|
|
34
|
+
/** Number of codes still lacking executable evidence. */
|
|
35
|
+
uncovered_error_code_count: number;
|
|
36
|
+
/** Executable codes divided by all catalog codes. */
|
|
37
|
+
coverage_fraction: number;
|
|
38
|
+
/** Number of closed-domain probes joined into the census. */
|
|
39
|
+
closed_domain_probe_count: number;
|
|
40
|
+
/** Number of grammar-derived probes joined into the census. */
|
|
41
|
+
grammar_probe_count: number;
|
|
42
|
+
/** Stable complete list of codes without executable evidence. */
|
|
43
|
+
uncovered_error_codes: string[];
|
|
44
|
+
/** Exactly one row for every catalog code. */
|
|
45
|
+
rows: PmRefusalClosureCensusRow[];
|
|
46
|
+
}
|
|
47
|
+
/** Reviewed floor of 16 catalog rows; includes one alias across 15 canonical groups. */
|
|
48
|
+
export declare const PM_REFUSAL_CLOSURE_EXECUTABLE_CODE_BASELINE = 16;
|
|
49
|
+
/** Fifteen canonical compatibility groups that must retain executable evidence. */
|
|
50
|
+
export declare const PM_REFUSAL_CLOSURE_EXECUTABLE_CANONICAL_CODE_BASELINE: readonly ["bulk_ids_input_empty", "bulk_ids_input_missing_path", "bulk_ids_input_unreadable", "invalid_argument_value", "missing_lifecycle_target", "missing_required_argument", "projection_options_mutually_exclusive", "tracker_not_initialized", "tracker_root_missing", "tracker_root_not_directory", "tracker_root_unreadable", "unknown_context_intent", "unknown_field_projection", "unknown_option", "unknown_subcommand"];
|
|
51
|
+
/** Ratchet receipt that prevents catalog growth from erasing proven closure. */
|
|
52
|
+
export declare function verifyPmRefusalClosureRatchet(report: PmRefusalClosureCensusReport, baseline?: number): {
|
|
53
|
+
ok: boolean;
|
|
54
|
+
baseline: number;
|
|
55
|
+
actual: number;
|
|
56
|
+
};
|
|
57
|
+
/** Ratchet canonical compatibility-group identities independently from counts. */
|
|
58
|
+
export declare function verifyPmRefusalClosureIdentityRatchet(report: PmRefusalClosureCensusReport, requiredCanonicalCodes?: readonly string[]): {
|
|
59
|
+
ok: boolean;
|
|
60
|
+
required_canonical_codes: string[];
|
|
61
|
+
missing_required_canonical_codes: string[];
|
|
62
|
+
};
|
|
63
|
+
/** Build the complete closure join without silently omitting uncovered codes. */
|
|
64
|
+
export declare function buildPmRefusalClosureCensus(catalog: readonly PmErrorCodeContract[], closedDomains: readonly PmClosedDomainContract[], grammar: readonly PmGrammarRefusalContract[]): PmRefusalClosureCensusReport;
|
|
65
|
+
/** Render the complete census for generated documentation and review evidence. */
|
|
66
|
+
export declare function renderPmRefusalClosureCensusMarkdown(report: PmRefusalClosureCensusReport): string;
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/** Reviewed floor of 16 catalog rows; includes one alias across 15 canonical groups. */
|
|
2
|
+
|
|
3
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="5560aa3a-036e-509c-955c-a09e9bf9df18")}catch(e){}}();
|
|
4
|
+
export const PM_REFUSAL_CLOSURE_EXECUTABLE_CODE_BASELINE = 16;
|
|
5
|
+
/** Fifteen canonical compatibility groups that must retain executable evidence. */
|
|
6
|
+
export const PM_REFUSAL_CLOSURE_EXECUTABLE_CANONICAL_CODE_BASELINE = Object.freeze([
|
|
7
|
+
"bulk_ids_input_empty",
|
|
8
|
+
"bulk_ids_input_missing_path",
|
|
9
|
+
"bulk_ids_input_unreadable",
|
|
10
|
+
"invalid_argument_value",
|
|
11
|
+
"missing_lifecycle_target",
|
|
12
|
+
"missing_required_argument",
|
|
13
|
+
"projection_options_mutually_exclusive",
|
|
14
|
+
"tracker_not_initialized",
|
|
15
|
+
"tracker_root_missing",
|
|
16
|
+
"tracker_root_not_directory",
|
|
17
|
+
"tracker_root_unreadable",
|
|
18
|
+
"unknown_context_intent",
|
|
19
|
+
"unknown_field_projection",
|
|
20
|
+
"unknown_option",
|
|
21
|
+
"unknown_subcommand",
|
|
22
|
+
]);
|
|
23
|
+
/** Ratchet receipt that prevents catalog growth from erasing proven closure. */
|
|
24
|
+
export function verifyPmRefusalClosureRatchet(report, baseline = PM_REFUSAL_CLOSURE_EXECUTABLE_CODE_BASELINE) {
|
|
25
|
+
return {
|
|
26
|
+
ok: report.executable_error_code_count >= baseline,
|
|
27
|
+
baseline,
|
|
28
|
+
actual: report.executable_error_code_count,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/** Ratchet canonical compatibility-group identities independently from counts. */
|
|
32
|
+
export function verifyPmRefusalClosureIdentityRatchet(report, requiredCanonicalCodes = PM_REFUSAL_CLOSURE_EXECUTABLE_CANONICAL_CODE_BASELINE) {
|
|
33
|
+
const executableCanonicalCodes = new Set(report.rows
|
|
34
|
+
.filter(({ disposition }) => disposition === "executable")
|
|
35
|
+
.map(({ canonical_code: canonicalCode }) => canonicalCode));
|
|
36
|
+
const missingRequiredCanonicalCodes = requiredCanonicalCodes.filter((code) => !executableCanonicalCodes.has(code));
|
|
37
|
+
return {
|
|
38
|
+
ok: missingRequiredCanonicalCodes.length === 0,
|
|
39
|
+
required_canonical_codes: [...requiredCanonicalCodes],
|
|
40
|
+
missing_required_canonical_codes: missingRequiredCanonicalCodes,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function evidenceFor(evidence, canonicalCode) {
|
|
44
|
+
const existing = evidence.get(canonicalCode);
|
|
45
|
+
if (existing)
|
|
46
|
+
return existing;
|
|
47
|
+
const created = {
|
|
48
|
+
kinds: new Set(),
|
|
49
|
+
probeIds: new Set(),
|
|
50
|
+
};
|
|
51
|
+
evidence.set(canonicalCode, created);
|
|
52
|
+
return created;
|
|
53
|
+
}
|
|
54
|
+
/** Build the complete closure join without silently omitting uncovered codes. */
|
|
55
|
+
export function buildPmRefusalClosureCensus(catalog, closedDomains, grammar) {
|
|
56
|
+
const canonicalByCode = new Map(catalog.map((contract) => [
|
|
57
|
+
contract.code,
|
|
58
|
+
contract.canonical_code ?? contract.code,
|
|
59
|
+
]));
|
|
60
|
+
const evidence = new Map();
|
|
61
|
+
let closedDomainProbeCount = 0;
|
|
62
|
+
let grammarProbeCount = 0;
|
|
63
|
+
for (const contract of catalog) {
|
|
64
|
+
const target = evidenceFor(evidence, contract.canonical_code ?? contract.code);
|
|
65
|
+
for (const state of contract.owned_states ?? []) {
|
|
66
|
+
target.kinds.add("owned_state");
|
|
67
|
+
target.probeIds.add(state.probe_id);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
for (const contract of closedDomains) {
|
|
71
|
+
const canonical = canonicalByCode.get(contract.error_code);
|
|
72
|
+
if (canonical === undefined)
|
|
73
|
+
continue;
|
|
74
|
+
closedDomainProbeCount += 1;
|
|
75
|
+
const target = evidenceFor(evidence, canonical);
|
|
76
|
+
target.kinds.add("closed_domain");
|
|
77
|
+
target.probeIds.add(contract.probe_id);
|
|
78
|
+
}
|
|
79
|
+
for (const contract of grammar) {
|
|
80
|
+
const canonical = canonicalByCode.get(contract.error_code);
|
|
81
|
+
if (canonical === undefined)
|
|
82
|
+
continue;
|
|
83
|
+
grammarProbeCount += 1;
|
|
84
|
+
const target = evidenceFor(evidence, canonical);
|
|
85
|
+
target.kinds.add("grammar");
|
|
86
|
+
target.probeIds.add(contract.probe_id);
|
|
87
|
+
}
|
|
88
|
+
const rows = catalog
|
|
89
|
+
.map((contract) => {
|
|
90
|
+
const canonicalCode = contract.canonical_code ?? contract.code;
|
|
91
|
+
const joined = evidence.get(canonicalCode);
|
|
92
|
+
const probeIds = [...joined.probeIds].sort();
|
|
93
|
+
return {
|
|
94
|
+
code: contract.code,
|
|
95
|
+
canonical_code: canonicalCode,
|
|
96
|
+
disposition: probeIds.length > 0 ? "executable" : "uncovered",
|
|
97
|
+
evidence_kinds: [...joined.kinds].sort(),
|
|
98
|
+
probe_ids: probeIds,
|
|
99
|
+
};
|
|
100
|
+
})
|
|
101
|
+
.sort((left, right) => (left.code < right.code ? -1 : 1));
|
|
102
|
+
const uncoveredErrorCodes = rows
|
|
103
|
+
.filter(({ disposition }) => disposition === "uncovered")
|
|
104
|
+
.map(({ code }) => code);
|
|
105
|
+
const executableCount = rows.length - uncoveredErrorCodes.length;
|
|
106
|
+
return {
|
|
107
|
+
ok: uncoveredErrorCodes.length === 0,
|
|
108
|
+
catalog_error_code_count: rows.length,
|
|
109
|
+
executable_error_code_count: executableCount,
|
|
110
|
+
uncovered_error_code_count: uncoveredErrorCodes.length,
|
|
111
|
+
coverage_fraction: rows.length === 0 ? 1 : executableCount / rows.length,
|
|
112
|
+
closed_domain_probe_count: closedDomainProbeCount,
|
|
113
|
+
grammar_probe_count: grammarProbeCount,
|
|
114
|
+
uncovered_error_codes: uncoveredErrorCodes,
|
|
115
|
+
rows,
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/** Render the complete census for generated documentation and review evidence. */
|
|
119
|
+
export function renderPmRefusalClosureCensusMarkdown(report) {
|
|
120
|
+
const rows = report.rows.map((row) => `| \`${row.code}\` | \`${row.canonical_code}\` | ${row.disposition} | ${row.evidence_kinds.join(", ") || "none"} | ${row.probe_ids.length} |`);
|
|
121
|
+
return [
|
|
122
|
+
"# Generated refusal closure census",
|
|
123
|
+
"",
|
|
124
|
+
"Tracker: `pm-f05lsg`.",
|
|
125
|
+
"",
|
|
126
|
+
"Every catalog code is listed. An `uncovered` row is an explicit closure obligation, never an omission or implied approval.",
|
|
127
|
+
"",
|
|
128
|
+
`- Catalog error codes: ${report.catalog_error_code_count}`,
|
|
129
|
+
`- Executable error codes: ${report.executable_error_code_count}`,
|
|
130
|
+
`- Executable-code ratchet floor: ${PM_REFUSAL_CLOSURE_EXECUTABLE_CODE_BASELINE}`,
|
|
131
|
+
`- Required executable canonical codes: ${PM_REFUSAL_CLOSURE_EXECUTABLE_CANONICAL_CODE_BASELINE.map((code) => `\`${code}\``).join(", ")}`,
|
|
132
|
+
`- Uncovered error codes: ${report.uncovered_error_code_count}`,
|
|
133
|
+
`- Coverage fraction: ${report.coverage_fraction.toFixed(6)}`,
|
|
134
|
+
`- Closed-domain probes: ${report.closed_domain_probe_count}`,
|
|
135
|
+
`- Grammar probes: ${report.grammar_probe_count}`,
|
|
136
|
+
"",
|
|
137
|
+
"| Error code | Canonical code | Disposition | Evidence kinds | Probe count |",
|
|
138
|
+
"| --- | --- | --- | --- | --- |",
|
|
139
|
+
...rows,
|
|
140
|
+
"",
|
|
141
|
+
].join("\n");
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=refusal-closure-census.js.map
|
|
144
|
+
//# debugId=5560aa3a-036e-509c-955c-a09e9bf9df18
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { type PmCommandPositionalContract } from "../cli-contracts/grammar-contracts.js";
|
|
2
|
+
/** Shared executable shape for a refusal that must not mutate tracker state. */
|
|
3
|
+
export interface PmGrammarRefusalContract {
|
|
4
|
+
/** Stable probe identity used by ratchets and evidence. */
|
|
5
|
+
probe_id: string;
|
|
6
|
+
/** Canonical command path under test. */
|
|
7
|
+
command: string;
|
|
8
|
+
/** Exact argv expected to refuse. */
|
|
9
|
+
refusal_args: readonly string[];
|
|
10
|
+
/** Exact help argv that must execute successfully after the refusal. */
|
|
11
|
+
recovery_args: readonly string[];
|
|
12
|
+
/** Stable problem-envelope code expected from the refusal. */
|
|
13
|
+
error_code: "invalid_argument_value" | "missing_lifecycle_target" | "missing_required_argument" | "unknown_subcommand";
|
|
14
|
+
}
|
|
15
|
+
/** One required positional omission derived from the grammar declaration. */
|
|
16
|
+
export interface PmRequiredArgumentRefusalContract extends PmGrammarRefusalContract {
|
|
17
|
+
/** Stable positional name deliberately omitted by the probe. */
|
|
18
|
+
missing_argument: string;
|
|
19
|
+
/** Zero-based slot index in the command's declared positional signature. */
|
|
20
|
+
missing_argument_index: number;
|
|
21
|
+
}
|
|
22
|
+
/** One invalid action probe for a closed positional subcommand family. */
|
|
23
|
+
export interface PmSubcommandRefusalContract extends PmGrammarRefusalContract {
|
|
24
|
+
/** Invalid action token used to reach the refusal. */
|
|
25
|
+
rejected_value: string;
|
|
26
|
+
/** Complete authoritative action domain expected in recovery. */
|
|
27
|
+
allowed_values: readonly string[];
|
|
28
|
+
}
|
|
29
|
+
/** Runtime evidence for one grammar-derived refusal probe. */
|
|
30
|
+
export interface PmGrammarRefusalObservation {
|
|
31
|
+
/** Probe identity matching a declared contract. */
|
|
32
|
+
probe_id: string;
|
|
33
|
+
/** Machine-readable code emitted by the refusal. */
|
|
34
|
+
error_code: string;
|
|
35
|
+
/** Process exit code emitted by the refusal. */
|
|
36
|
+
exit_code: number;
|
|
37
|
+
/** Allowed values emitted for a closed action family. */
|
|
38
|
+
allowed_values: readonly string[];
|
|
39
|
+
/** Whether the advertised help recovery exited successfully. */
|
|
40
|
+
recovery_succeeded: boolean;
|
|
41
|
+
/** Whether any tracker state changed while executing the refusal. */
|
|
42
|
+
refusal_mutated_state: boolean;
|
|
43
|
+
/** Repository-relative tracker paths changed by the refusal, when measured. */
|
|
44
|
+
mutated_paths?: readonly string[];
|
|
45
|
+
}
|
|
46
|
+
/** Stable reason a grammar-derived refusal failed closure. */
|
|
47
|
+
export type PmGrammarRefusalFindingCode = "refusal_allowed_values_mismatch" | "refusal_error_code_mismatch" | "refusal_exit_code_mismatch" | "refusal_mutated_state" | "refusal_probe_missing" | "refusal_recovery_failed" | "unexpected_refusal_probe";
|
|
48
|
+
/** One actionable grammar-derived refusal closure failure. */
|
|
49
|
+
export interface PmGrammarRefusalFinding {
|
|
50
|
+
/** Stable machine-readable failure category. */
|
|
51
|
+
code: PmGrammarRefusalFindingCode;
|
|
52
|
+
/** Probe associated with the finding. */
|
|
53
|
+
probe_id: string;
|
|
54
|
+
/** Human-readable failure detail. */
|
|
55
|
+
detail: string;
|
|
56
|
+
}
|
|
57
|
+
/** Aggregate closure receipt for the grammar-derived refusal corpus. */
|
|
58
|
+
export interface PmGrammarRefusalClosureReport {
|
|
59
|
+
/** Whether every declared probe refused safely and recovered. */
|
|
60
|
+
ok: boolean;
|
|
61
|
+
/** Number of declared probes. */
|
|
62
|
+
probe_count: number;
|
|
63
|
+
/** Number of probes without findings. */
|
|
64
|
+
closed_probe_count: number;
|
|
65
|
+
/** Stable actionable failures. */
|
|
66
|
+
findings: PmGrammarRefusalFinding[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Return one omission probe for every required slot in the declared grammar.
|
|
70
|
+
* Earlier positionals receive deterministic, non-mutating placeholder values.
|
|
71
|
+
*/
|
|
72
|
+
export declare function listPmRequiredArgumentRefusalContracts(contracts?: readonly PmCommandPositionalContract[]): PmRequiredArgumentRefusalContract[];
|
|
73
|
+
/** Return one invalid-action probe for every required positional action family. */
|
|
74
|
+
export declare function listPmSubcommandRefusalContracts(contracts?: readonly PmCommandPositionalContract[]): PmSubcommandRefusalContract[];
|
|
75
|
+
/** Score exact code, exit, domain, state-safety, and recovery closure. */
|
|
76
|
+
export declare function scorePmGrammarRefusalClosure(contracts: readonly (PmRequiredArgumentRefusalContract | PmSubcommandRefusalContract)[], observations: readonly PmGrammarRefusalObservation[]): PmGrammarRefusalClosureReport;
|