@unbrained/pm-cli 2026.8.22 → 2026.8.23
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 +28 -0
- package/dist/cli/error-guidance.d.ts +13 -0
- package/dist/cli/error-guidance.js +62 -6
- package/dist/cli/main.js +13 -4
- package/dist/cli/register-mutation.js +6 -6
- 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-3ENVHX6C.js +36 -0
- package/dist/cli-bundle/chunks/{chunk-QI2CT3IX.js → chunk-DW2CGEMU.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-WG4STC36.js → chunk-EG6CLDZT.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-MYYI3ZOA.js → chunk-F3AI2JFL.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-U6GQ4VMV.js → chunk-HWZ6CELB.js} +4 -4
- package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +201 -0
- package/dist/cli-bundle/chunks/chunk-JB4KZWBF.js +3 -0
- package/dist/cli-bundle/chunks/chunk-KPH73XXJ.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-BWX4SK46.js → chunk-KXPMB2YL.js} +58 -58
- package/dist/cli-bundle/chunks/{chunk-MZTZQTMS.js → chunk-QDVHNHAQ.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +13 -0
- package/dist/cli-bundle/chunks/{register-list-query-HZKBQNWW.js → register-list-query-UJB5FMV2.js} +2 -2
- package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +20 -0
- package/dist/cli-bundle/chunks/register-operations-RXIJIYXC.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-QK4OTOXN.js → register-setup-GFUZEKRE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-2POVTNLY.js → chunk-37Z4OEAP.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-3UPTYG44.js +8 -0
- package/dist/cli-bundle/focused-chunks/{chunk-E2EWYPY6.js → chunk-5S7E72FY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GMYPD4FX.js → chunk-AUFH5H35.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-3LKU6PTJ.js → chunk-FQCSTBWE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-6S2MO3Q3.js → chunk-FZS4H32O.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-IFLWKY2R.js +156 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PMGJUFNQ.js → chunk-JOWDB2MH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-LYVSW5VM.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-A2BC5PQL.js → chunk-OFVUGTLJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-2ARQGDDW.js → chunk-OGLQBL46.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-R6SR45XU.js → chunk-OY7QAV4Y.js} +48 -47
- package/dist/cli-bundle/focused-chunks/chunk-QGFNI65N.js +26 -0
- package/dist/cli-bundle/focused-chunks/{chunk-D6RBZEJJ.js → chunk-R27IDGHD.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +5 -0
- package/dist/cli-bundle/focused-chunks/{chunk-PH2OXXVZ.js → chunk-ZHVA42R5.js} +9 -9
- package/dist/cli-bundle/main.js +13 -13
- 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 +40 -40
- 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 +5 -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/history/history.js +3 -3
- package/dist/core/item/item-format.js +66 -12
- 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 +1 -1
- package/dist/mcp/server.js +30 -9
- package/dist/sdk/agent/identity-config.d.ts +63 -0
- package/dist/sdk/agent/identity-config.js +107 -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/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 +22 -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.d.ts +3 -3
- package/dist/sdk/cli-contracts.js +4 -4
- 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.js +4 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +50 -2
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +87 -38
- 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/index.d.ts +7 -2
- package/dist/sdk/index.js +8 -3
- package/dist/sdk/lifecycle/create.js +6 -3
- package/dist/sdk/lifecycle/update.js +5 -3
- 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-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime.js +6 -5
- 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/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/READ_OUTPUT_CONTRACTS.md +11 -1
- package/docs/REPRODUCIBLE_WORKSPACES.md +42 -8
- package/docs/SDK.md +9 -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/FLAG_LEXICON_BUDGETS.md +2 -2
- 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/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/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/sdk/public-surface.json +427 -17
- 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-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-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-WZE4LIPW.js +0 -8
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Provides shared primitives and utilities for Author.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="8d89d381-5c6e-5f96-ba03-298fc6db9bba")}catch(e){}}();
|
|
8
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
10
|
import fs from "node:fs";
|
|
@@ -50,7 +50,11 @@ export const BUILTIN_HARNESS_SIGNAL_DESCRIPTORS = [
|
|
|
50
50
|
effort: ["CODEX_REASONING_EFFORT", "CODEX_EFFORT"],
|
|
51
51
|
role: ["CODEX_SESSION_ROLE"],
|
|
52
52
|
},
|
|
53
|
-
provenance_resolvers: {
|
|
53
|
+
provenance_resolvers: {
|
|
54
|
+
model: "codex_session_file",
|
|
55
|
+
effort: "codex_session_file",
|
|
56
|
+
version: "ai_agent_version",
|
|
57
|
+
},
|
|
54
58
|
provenance_unavailable_dimensions: ["topic"],
|
|
55
59
|
argv_markers: ["codex"],
|
|
56
60
|
client_names: ["codex"],
|
|
@@ -108,8 +112,61 @@ export const BUILTIN_HARNESS_SIGNAL_DESCRIPTORS = [
|
|
|
108
112
|
client_names: [],
|
|
109
113
|
},
|
|
110
114
|
];
|
|
111
|
-
const
|
|
115
|
+
const PROVENANCE_PROBE_POLICY = Object.freeze({
|
|
116
|
+
max_bytes: 1_048_576,
|
|
117
|
+
max_lines: 4_096,
|
|
118
|
+
network_access: false,
|
|
119
|
+
subprocess_access: false,
|
|
120
|
+
});
|
|
121
|
+
const CODEX_PROVENANCE_PROBE_POLICY = Object.freeze({
|
|
122
|
+
...PROVENANCE_PROBE_POLICY,
|
|
123
|
+
max_bytes: 4_194_304,
|
|
124
|
+
});
|
|
112
125
|
const HARNESS_NAMESPACE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/u;
|
|
126
|
+
function buildBuiltinProvenanceAdapter(descriptor) {
|
|
127
|
+
const unavailableDimensions = normalizeHarnessSignalDescriptor(descriptor).provenance_unavailable_dimensions;
|
|
128
|
+
const dimensions = new Set([
|
|
129
|
+
"model",
|
|
130
|
+
"version",
|
|
131
|
+
...Object.keys(descriptor.provenance_environment_keys ?? {}),
|
|
132
|
+
...Object.keys(descriptor.provenance_resolvers ?? {}),
|
|
133
|
+
]);
|
|
134
|
+
return Object.freeze({
|
|
135
|
+
contract_version: 1,
|
|
136
|
+
adapter_version: "v1",
|
|
137
|
+
priority: 0,
|
|
138
|
+
harness: descriptor.harness,
|
|
139
|
+
descriptor,
|
|
140
|
+
supported_dimensions: Object.freeze([...dimensions].sort()),
|
|
141
|
+
native_sources: Object.freeze([
|
|
142
|
+
"environment",
|
|
143
|
+
"argv",
|
|
144
|
+
"mcp_client",
|
|
145
|
+
...(Object.values(descriptor.provenance_resolvers ?? {}).some((resolver) => resolver?.endsWith("session_file"))
|
|
146
|
+
? ["session_file"]
|
|
147
|
+
: []),
|
|
148
|
+
]),
|
|
149
|
+
probe_policy: descriptor.harness === "codex"
|
|
150
|
+
? CODEX_PROVENANCE_PROBE_POLICY
|
|
151
|
+
: PROVENANCE_PROBE_POLICY,
|
|
152
|
+
normalization: Object.freeze({
|
|
153
|
+
model_family: "v1",
|
|
154
|
+
effort: "v1",
|
|
155
|
+
preserve_raw: true,
|
|
156
|
+
}),
|
|
157
|
+
confidence: "high",
|
|
158
|
+
waivers: Object.freeze(Object.fromEntries(unavailableDimensions.map((dimension) => [
|
|
159
|
+
dimension,
|
|
160
|
+
"Harness does not expose this dimension.",
|
|
161
|
+
]))),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
/** Built-in versioned adapters for supported interactive agent harnesses. */
|
|
165
|
+
export const BUILTIN_AGENT_PROVENANCE_ADAPTERS = Object.freeze(BUILTIN_HARNESS_SIGNAL_DESCRIPTORS.filter((descriptor) => descriptor.harness !== "ci")
|
|
166
|
+
.map(buildBuiltinProvenanceAdapter)
|
|
167
|
+
.sort((left, right) => left.harness.localeCompare(right.harness)));
|
|
168
|
+
const registeredAgentProvenanceAdapters = new Map();
|
|
169
|
+
const registeredHarnessSignalDescriptors = new Map();
|
|
113
170
|
function nonBlank(value) {
|
|
114
171
|
const trimmed = typeof value === "string" ? value.trim() : undefined;
|
|
115
172
|
return trimmed && trimmed.length > 0 ? trimmed : undefined;
|
|
@@ -149,7 +206,8 @@ function normalizeHarnessSignalDescriptor(descriptor) {
|
|
|
149
206
|
.filter((entry) => typeof entry[0] === "string" &&
|
|
150
207
|
HARNESS_NAMESPACE_PATTERN.test(entry[0]) &&
|
|
151
208
|
(entry[1] === "ai_agent_version" ||
|
|
152
|
-
entry[1] === "claude_session_file"
|
|
209
|
+
entry[1] === "claude_session_file" ||
|
|
210
|
+
entry[1] === "codex_session_file"))),
|
|
153
211
|
provenance_unavailable_dimensions: boundedUniqueStrings(descriptor.provenance_unavailable_dimensions).map((value) => value.toLowerCase()),
|
|
154
212
|
argv_markers: boundedUniqueStrings(descriptor.argv_markers).map((value) => value.toLowerCase()),
|
|
155
213
|
client_names: boundedUniqueStrings(descriptor.client_names).map((value) => value.toLowerCase()),
|
|
@@ -168,8 +226,16 @@ function literalSignalMatches(value, marker) {
|
|
|
168
226
|
return segments.includes(marker) || value.trim().toLowerCase() === marker;
|
|
169
227
|
}
|
|
170
228
|
function currentHarnessSignalDescriptors(localDescriptors = []) {
|
|
229
|
+
const adapterDescriptors = new Map(BUILTIN_HARNESS_SIGNAL_DESCRIPTORS.filter((descriptor) => descriptor.harness !== "ci").map((descriptor) => [
|
|
230
|
+
descriptor.harness,
|
|
231
|
+
normalizeHarnessSignalDescriptor(descriptor),
|
|
232
|
+
]));
|
|
233
|
+
for (const { adapter } of registeredAgentProvenanceAdapters.values()) {
|
|
234
|
+
adapterDescriptors.set(adapter.harness, normalizeHarnessSignalDescriptor(adapter.descriptor));
|
|
235
|
+
}
|
|
171
236
|
const descriptors = [
|
|
172
|
-
...
|
|
237
|
+
...adapterDescriptors.values(),
|
|
238
|
+
...NORMALIZED_BUILTIN_HARNESS_SIGNAL_DESCRIPTORS.filter((descriptor) => descriptor.harness === "ci"),
|
|
173
239
|
...[...registeredHarnessSignalDescriptors.values()].map((entry) => entry.descriptor),
|
|
174
240
|
...(workspaceHarnessSignalsStorage.getStore()?.descriptors ?? []),
|
|
175
241
|
...localDescriptors.map(normalizeHarnessSignalDescriptor),
|
|
@@ -243,9 +309,10 @@ function boundedProvenanceValue(provenance, dimension) {
|
|
|
243
309
|
return nonBlank(provenance?.[dimension])?.slice(0, 256);
|
|
244
310
|
}
|
|
245
311
|
const MAX_PROVENANCE_PROBE_BYTES = 1_048_576;
|
|
312
|
+
const MAX_CODEX_PROVENANCE_PROBE_BYTES = 4_194_304;
|
|
313
|
+
const codexProvenanceSnapshotCache = new Map();
|
|
314
|
+
const EMPTY_CODEX_PROVENANCE_SNAPSHOT = Object.freeze({});
|
|
246
315
|
function parseClaudeProvenanceLine(line, dimension) {
|
|
247
|
-
if (line.length === 0 || line.length > 262_144)
|
|
248
|
-
return undefined;
|
|
249
316
|
let parsed;
|
|
250
317
|
try {
|
|
251
318
|
parsed = JSON.parse(line);
|
|
@@ -253,8 +320,6 @@ function parseClaudeProvenanceLine(line, dimension) {
|
|
|
253
320
|
catch {
|
|
254
321
|
return undefined;
|
|
255
322
|
}
|
|
256
|
-
if (typeof parsed !== "object" || parsed === null)
|
|
257
|
-
return undefined;
|
|
258
323
|
const record = parsed;
|
|
259
324
|
const message = typeof record.message === "object" && record.message !== null
|
|
260
325
|
? record.message
|
|
@@ -273,22 +338,140 @@ function readClaudeSessionProvenance(dimension, signals, env) {
|
|
|
273
338
|
const file = fs.openSync(sessionPath, "r");
|
|
274
339
|
try {
|
|
275
340
|
const size = fs.fstatSync(file).size;
|
|
276
|
-
const
|
|
277
|
-
const
|
|
278
|
-
fs.readSync(file,
|
|
279
|
-
const lines =
|
|
280
|
-
for (const line of lines
|
|
341
|
+
const tailLength = Math.min(size, MAX_PROVENANCE_PROBE_BYTES);
|
|
342
|
+
const tail = Buffer.alloc(tailLength);
|
|
343
|
+
fs.readSync(file, tail, 0, tailLength, Math.max(0, size - tailLength));
|
|
344
|
+
const lines = tail.toString("utf8").split("\n").reverse().slice(0, 4_096);
|
|
345
|
+
for (const line of lines) {
|
|
346
|
+
if (line.length === 0 || line.length > 262_144)
|
|
347
|
+
continue;
|
|
281
348
|
const value = parseClaudeProvenanceLine(line, dimension);
|
|
282
349
|
if (value)
|
|
283
350
|
return value;
|
|
284
351
|
}
|
|
352
|
+
}
|
|
353
|
+
finally {
|
|
354
|
+
fs.closeSync(file);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
catch {
|
|
358
|
+
return undefined;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
function findCodexSessionFile(root, session) {
|
|
362
|
+
let visited = 0;
|
|
363
|
+
const visit = (directory, depth) => {
|
|
364
|
+
if (depth > 4 || visited >= 512)
|
|
285
365
|
return undefined;
|
|
366
|
+
let entries;
|
|
367
|
+
try {
|
|
368
|
+
entries = fs
|
|
369
|
+
.readdirSync(directory, { withFileTypes: true })
|
|
370
|
+
.sort((left, right) => right.name.localeCompare(left.name));
|
|
371
|
+
}
|
|
372
|
+
catch {
|
|
373
|
+
return undefined;
|
|
374
|
+
}
|
|
375
|
+
for (const entry of entries) {
|
|
376
|
+
visited += 1;
|
|
377
|
+
if (visited > 512)
|
|
378
|
+
return undefined;
|
|
379
|
+
const entryPath = path.join(directory, entry.name);
|
|
380
|
+
if (entry.isFile() && entry.name.endsWith(`-${session}.jsonl`)) {
|
|
381
|
+
return entryPath;
|
|
382
|
+
}
|
|
383
|
+
if (entry.isDirectory()) {
|
|
384
|
+
const found = visit(entryPath, depth + 1);
|
|
385
|
+
if (found)
|
|
386
|
+
return found;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return undefined;
|
|
390
|
+
};
|
|
391
|
+
return visit(root, 0);
|
|
392
|
+
}
|
|
393
|
+
function codexProvenanceWindows(size) {
|
|
394
|
+
if (size <= MAX_CODEX_PROVENANCE_PROBE_BYTES) {
|
|
395
|
+
return [{ offset: 0, length: size }];
|
|
396
|
+
}
|
|
397
|
+
const halfBudget = Math.floor(MAX_CODEX_PROVENANCE_PROBE_BYTES / 2);
|
|
398
|
+
return [
|
|
399
|
+
{ offset: size - halfBudget, length: halfBudget },
|
|
400
|
+
{ offset: 0, length: halfBudget },
|
|
401
|
+
];
|
|
402
|
+
}
|
|
403
|
+
function mergeCodexTurnContext(snapshot, line) {
|
|
404
|
+
if (line.length === 0 || line.length > 262_144)
|
|
405
|
+
return;
|
|
406
|
+
let parsed;
|
|
407
|
+
try {
|
|
408
|
+
parsed = JSON.parse(line);
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const record = parsed;
|
|
417
|
+
if (record.type !== "turn_context")
|
|
418
|
+
return;
|
|
419
|
+
const payload = typeof record.payload === "object" && record.payload !== null
|
|
420
|
+
? record.payload
|
|
421
|
+
: undefined;
|
|
422
|
+
snapshot.model ??= nonBlank(payload?.model)?.slice(0, 256);
|
|
423
|
+
snapshot.effort ??= nonBlank(payload?.effort)?.slice(0, 256);
|
|
424
|
+
}
|
|
425
|
+
function readCodexProvenanceSnapshot(file, size) {
|
|
426
|
+
const snapshot = {};
|
|
427
|
+
let linesRemaining = 4_096;
|
|
428
|
+
for (const window of codexProvenanceWindows(size)) {
|
|
429
|
+
const buffer = Buffer.alloc(window.length);
|
|
430
|
+
fs.readSync(file, buffer, 0, window.length, window.offset);
|
|
431
|
+
const lines = buffer
|
|
432
|
+
.toString("utf8")
|
|
433
|
+
.split("\n")
|
|
434
|
+
.reverse()
|
|
435
|
+
.slice(0, linesRemaining);
|
|
436
|
+
linesRemaining -= lines.length;
|
|
437
|
+
for (const line of lines) {
|
|
438
|
+
mergeCodexTurnContext(snapshot, line);
|
|
439
|
+
if (snapshot.model && snapshot.effort)
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
if ((snapshot.model && snapshot.effort) || linesRemaining <= 0)
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
return snapshot;
|
|
446
|
+
}
|
|
447
|
+
function readCodexSessionProvenance(dimension, signals, env) {
|
|
448
|
+
const session = nonBlank(env.CODEX_THREAD_ID);
|
|
449
|
+
if (!session || !/^[A-Za-z0-9_-]{1,128}$/u.test(session))
|
|
450
|
+
return undefined;
|
|
451
|
+
const sessionsRoot = path.join(signals.home_dir ?? os.homedir(), ".codex", "sessions");
|
|
452
|
+
const cacheKey = `${sessionsRoot}\0${session}`;
|
|
453
|
+
const cached = codexProvenanceSnapshotCache.get(cacheKey);
|
|
454
|
+
if (cached)
|
|
455
|
+
return cached[dimension];
|
|
456
|
+
const sessionPath = findCodexSessionFile(sessionsRoot, session);
|
|
457
|
+
if (!sessionPath) {
|
|
458
|
+
codexProvenanceSnapshotCache.set(cacheKey, EMPTY_CODEX_PROVENANCE_SNAPSHOT);
|
|
459
|
+
return undefined;
|
|
460
|
+
}
|
|
461
|
+
try {
|
|
462
|
+
const file = fs.openSync(sessionPath, "r");
|
|
463
|
+
try {
|
|
464
|
+
const size = fs.fstatSync(file).size;
|
|
465
|
+
const snapshot = readCodexProvenanceSnapshot(file, size);
|
|
466
|
+
codexProvenanceSnapshotCache.set(cacheKey, snapshot);
|
|
467
|
+
return snapshot[dimension];
|
|
286
468
|
}
|
|
287
469
|
finally {
|
|
288
470
|
fs.closeSync(file);
|
|
289
471
|
}
|
|
290
472
|
}
|
|
291
473
|
catch {
|
|
474
|
+
codexProvenanceSnapshotCache.set(cacheKey, EMPTY_CODEX_PROVENANCE_SNAPSHOT);
|
|
292
475
|
return undefined;
|
|
293
476
|
}
|
|
294
477
|
}
|
|
@@ -303,6 +486,9 @@ function resolveProvenanceProbe(dimension, signals, env, descriptor) {
|
|
|
303
486
|
if (resolver === "claude_session_file") {
|
|
304
487
|
return readClaudeSessionProvenance(dimension, signals, env);
|
|
305
488
|
}
|
|
489
|
+
if (resolver === "codex_session_file") {
|
|
490
|
+
return readCodexSessionProvenance(dimension, signals, env);
|
|
491
|
+
}
|
|
306
492
|
if (resolver === "ai_agent_version") {
|
|
307
493
|
const value = nonBlank(env.AI_AGENT);
|
|
308
494
|
if (!value ||
|
|
@@ -320,7 +506,9 @@ function provenanceResolverHasInput(resolver, descriptor, env) {
|
|
|
320
506
|
const value = nonBlank(env.AI_AGENT);
|
|
321
507
|
return (value !== undefined && literalSignalMatches(value, descriptor.harness));
|
|
322
508
|
}
|
|
323
|
-
return
|
|
509
|
+
return resolver === "codex_session_file"
|
|
510
|
+
? nonBlank(env.CODEX_THREAD_ID) !== undefined
|
|
511
|
+
: nonBlank(env.CLAUDE_CODE_SESSION_ID) !== undefined;
|
|
324
512
|
}
|
|
325
513
|
function effectiveHarnessDetectionSignals(signals) {
|
|
326
514
|
if (signals)
|
|
@@ -482,6 +670,135 @@ export function registerHarnessSignalDescriptors(descriptors) {
|
|
|
482
670
|
}
|
|
483
671
|
};
|
|
484
672
|
}
|
|
673
|
+
function normalizeAgentProvenanceAdapter(adapter) {
|
|
674
|
+
const descriptor = normalizeHarnessSignalDescriptor(adapter.descriptor);
|
|
675
|
+
const harness = adapter.harness.trim().toLowerCase();
|
|
676
|
+
if (adapter.contract_version !== 1) {
|
|
677
|
+
throw new Error(`Unsupported provenance adapter contract for "${harness}": ${adapter.contract_version}`);
|
|
678
|
+
}
|
|
679
|
+
if (descriptor.harness !== harness) {
|
|
680
|
+
throw new Error(`Provenance adapter harness "${harness}" does not match descriptor "${descriptor.harness}".`);
|
|
681
|
+
}
|
|
682
|
+
const adapterVersion = nonBlank(adapter.adapter_version)?.slice(0, 64);
|
|
683
|
+
if (!adapterVersion) {
|
|
684
|
+
throw new Error(`Provenance adapter "${harness}" requires a version.`);
|
|
685
|
+
}
|
|
686
|
+
if (!Number.isSafeInteger(adapter.priority)) {
|
|
687
|
+
throw new Error(`Provenance adapter "${harness}" requires an integer priority.`);
|
|
688
|
+
}
|
|
689
|
+
if (adapter.probe_policy.network_access !== false ||
|
|
690
|
+
adapter.probe_policy.subprocess_access !== false ||
|
|
691
|
+
adapter.probe_policy.max_bytes > MAX_CODEX_PROVENANCE_PROBE_BYTES ||
|
|
692
|
+
adapter.probe_policy.max_lines > 4_096) {
|
|
693
|
+
throw new Error(`Provenance adapter "${harness}" exceeds the bounded local probe policy.`);
|
|
694
|
+
}
|
|
695
|
+
return Object.freeze({
|
|
696
|
+
...adapter,
|
|
697
|
+
adapter_version: adapterVersion,
|
|
698
|
+
harness,
|
|
699
|
+
descriptor,
|
|
700
|
+
supported_dimensions: Object.freeze(boundedUniqueStrings(adapter.supported_dimensions)
|
|
701
|
+
.map((dimension) => dimension.toLowerCase())
|
|
702
|
+
.sort()),
|
|
703
|
+
native_sources: Object.freeze([...new Set(adapter.native_sources)]),
|
|
704
|
+
probe_policy: Object.freeze({ ...adapter.probe_policy }),
|
|
705
|
+
normalization: Object.freeze({ ...adapter.normalization }),
|
|
706
|
+
...(adapter.waivers
|
|
707
|
+
? {
|
|
708
|
+
waivers: Object.freeze(Object.fromEntries(Object.entries(adapter.waivers)
|
|
709
|
+
.slice(0, 32)
|
|
710
|
+
.map(([dimension, reason]) => [
|
|
711
|
+
dimension.slice(0, 64),
|
|
712
|
+
reason.slice(0, 256),
|
|
713
|
+
]))),
|
|
714
|
+
}
|
|
715
|
+
: {}),
|
|
716
|
+
});
|
|
717
|
+
}
|
|
718
|
+
/** Return the effective built-in or explicitly higher-priority package adapters. */
|
|
719
|
+
export function listAgentProvenanceAdapters() {
|
|
720
|
+
const effective = new Map(BUILTIN_AGENT_PROVENANCE_ADAPTERS.map((adapter) => [
|
|
721
|
+
adapter.harness,
|
|
722
|
+
adapter,
|
|
723
|
+
]));
|
|
724
|
+
for (const { adapter } of registeredAgentProvenanceAdapters.values()) {
|
|
725
|
+
effective.set(adapter.harness, adapter);
|
|
726
|
+
}
|
|
727
|
+
return Object.freeze([...effective.values()].sort((left, right) => left.harness.localeCompare(right.harness)));
|
|
728
|
+
}
|
|
729
|
+
/**
|
|
730
|
+
* Register package adapters until disposal. Replacing a built-in requires an
|
|
731
|
+
* explicitly greater priority; equal-priority ambiguity fails closed.
|
|
732
|
+
*/
|
|
733
|
+
export function registerAgentProvenanceAdapters(adapters) {
|
|
734
|
+
const normalized = adapters.map(normalizeAgentProvenanceAdapter);
|
|
735
|
+
const builtins = new Map(BUILTIN_AGENT_PROVENANCE_ADAPTERS.map((adapter) => [
|
|
736
|
+
adapter.harness,
|
|
737
|
+
adapter,
|
|
738
|
+
]));
|
|
739
|
+
const seen = new Set();
|
|
740
|
+
for (const adapter of normalized) {
|
|
741
|
+
if (seen.has(adapter.harness)) {
|
|
742
|
+
throw new Error(`Provenance adapter collision for "${adapter.harness}".`);
|
|
743
|
+
}
|
|
744
|
+
const builtin = builtins.get(adapter.harness);
|
|
745
|
+
if (builtin && adapter.priority <= builtin.priority) {
|
|
746
|
+
throw new Error(`Provenance adapter override for "${adapter.harness}" requires priority greater than ${builtin.priority}.`);
|
|
747
|
+
}
|
|
748
|
+
const registered = registeredAgentProvenanceAdapters.get(adapter.harness);
|
|
749
|
+
if (registered &&
|
|
750
|
+
JSON.stringify(registered.adapter) !== JSON.stringify(adapter)) {
|
|
751
|
+
throw new Error(`Provenance adapter collision for "${adapter.harness}".`);
|
|
752
|
+
}
|
|
753
|
+
seen.add(adapter.harness);
|
|
754
|
+
}
|
|
755
|
+
for (const adapter of normalized) {
|
|
756
|
+
const registered = registeredAgentProvenanceAdapters.get(adapter.harness);
|
|
757
|
+
registeredAgentProvenanceAdapters.set(adapter.harness, {
|
|
758
|
+
adapter,
|
|
759
|
+
registrations: (registered?.registrations ?? 0) + 1,
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
let active = true;
|
|
763
|
+
return () => {
|
|
764
|
+
if (!active)
|
|
765
|
+
return;
|
|
766
|
+
active = false;
|
|
767
|
+
for (const adapter of normalized) {
|
|
768
|
+
const registered = registeredAgentProvenanceAdapters.get(adapter.harness);
|
|
769
|
+
if (!registered || registered.registrations <= 1) {
|
|
770
|
+
registeredAgentProvenanceAdapters.delete(adapter.harness);
|
|
771
|
+
}
|
|
772
|
+
else {
|
|
773
|
+
registered.registrations -= 1;
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
};
|
|
777
|
+
}
|
|
778
|
+
/** Normalize model-family or effort vocabulary while retaining the raw value. */
|
|
779
|
+
export function normalizeAgentProvenanceAdapterValue(dimension, value) {
|
|
780
|
+
const raw = value.trim().slice(0, 256);
|
|
781
|
+
let normalized = raw.toLowerCase();
|
|
782
|
+
if (dimension === "model") {
|
|
783
|
+
const family = /^(gpt-\d+(?:\.\d+)?)/u.exec(normalized)?.[1];
|
|
784
|
+
if (family)
|
|
785
|
+
normalized = family;
|
|
786
|
+
}
|
|
787
|
+
else {
|
|
788
|
+
normalized = normalized.replaceAll(/[_\s-]+/gu, "");
|
|
789
|
+
const effortAliases = {
|
|
790
|
+
minimal: "low",
|
|
791
|
+
low: "low",
|
|
792
|
+
medium: "medium",
|
|
793
|
+
high: "high",
|
|
794
|
+
xhigh: "xhigh",
|
|
795
|
+
max: "max",
|
|
796
|
+
ultra: "ultra",
|
|
797
|
+
};
|
|
798
|
+
normalized = effortAliases[normalized] ?? normalized;
|
|
799
|
+
}
|
|
800
|
+
return { raw, normalized, vocabulary: "v1" };
|
|
801
|
+
}
|
|
485
802
|
/** Run one invocation with host-provided detection signals available downstream. */
|
|
486
803
|
export function runWithHarnessDetectionSignals(signals, callback) {
|
|
487
804
|
return harnessDetectionStorage.run(signals, callback);
|
|
@@ -713,4 +1030,4 @@ export function resolveAuthor(candidate, fallback) {
|
|
|
713
1030
|
return identity.author;
|
|
714
1031
|
}
|
|
715
1032
|
//# sourceMappingURL=author.js.map
|
|
716
|
-
//# debugId=
|
|
1033
|
+
//# debugId=8d89d381-5c6e-5f96-ba03-298fc6db9bba
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!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]="
|
|
2
|
+
!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]="4bb01c24-e203-5f9f-ba23-25888bd7f6ea")}catch(e){}}();
|
|
3
3
|
import { createDefaultExtensionGovernancePolicy } from "../extensions/extension-types.js";
|
|
4
4
|
export { ITEM_METADATA_KEY_ORDER, ITEM_PROJECT_CONTEXT_KEYS, } from "./item-metadata-contract.js";
|
|
5
5
|
/**
|
|
@@ -232,6 +232,7 @@ export const SETTINGS_DEFAULTS = {
|
|
|
232
232
|
},
|
|
233
233
|
testing: {
|
|
234
234
|
record_results_to_items: false,
|
|
235
|
+
allow_untrusted_linked_tests: false,
|
|
235
236
|
},
|
|
236
237
|
telemetry: {
|
|
237
238
|
enabled: true,
|
|
@@ -402,4 +403,4 @@ export function resolveTelemetryErrorCategory(errorCode) {
|
|
|
402
403
|
return "unknown";
|
|
403
404
|
}
|
|
404
405
|
//# sourceMappingURL=constants.js.map
|
|
405
|
-
//# debugId=
|
|
406
|
+
//# debugId=4bb01c24-e203-5f9f-ba23-25888bd7f6ea
|
|
@@ -69,6 +69,7 @@ export interface ParsedSettings {
|
|
|
69
69
|
/** Value that configures or reports testing for this contract. */
|
|
70
70
|
testing?: {
|
|
71
71
|
record_results_to_items: boolean;
|
|
72
|
+
allow_untrusted_linked_tests?: boolean;
|
|
72
73
|
};
|
|
73
74
|
/** Value that configures or reports telemetry for this contract. */
|
|
74
75
|
telemetry?: {
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* byte-identical to the previous implementation.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
!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]="
|
|
15
|
+
!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]="0e135793-d2ed-505b-b73e-6db55218d8af")}catch(e){}}();
|
|
16
16
|
import { GOVERNANCE_PRESET_VALUES, RUNTIME_FIELD_COMMAND_VALUES, RUNTIME_FIELD_TYPE_VALUES, RUNTIME_STATUS_ROLE_VALUES, RUNTIME_UNKNOWN_FIELD_POLICY_VALUES, } from "../../types.js";
|
|
17
17
|
// Generic over `never` so it is assignable to every `Outcome<T>`.
|
|
18
18
|
const FAIL = { ok: false };
|
|
@@ -326,7 +326,10 @@ const settingsCheck = vObject({
|
|
|
326
326
|
})),
|
|
327
327
|
governance: governanceSettings,
|
|
328
328
|
workflow: vOptional(vObject({ definition_of_done: vArray(vString) })),
|
|
329
|
-
testing: vOptional(vObject({
|
|
329
|
+
testing: vOptional(vObject({
|
|
330
|
+
record_results_to_items: vBoolean,
|
|
331
|
+
allow_untrusted_linked_tests: vOptional(vBoolean),
|
|
332
|
+
})),
|
|
330
333
|
telemetry: vOptional(vObject({
|
|
331
334
|
enabled: vBoolean,
|
|
332
335
|
first_run_prompt_completed: vOptional(vBoolean),
|
|
@@ -415,4 +418,4 @@ export function validateSettings(raw) {
|
|
|
415
418
|
return { success: true, data: result.value };
|
|
416
419
|
}
|
|
417
420
|
//# sourceMappingURL=settings-validator.js.map
|
|
418
|
-
//# debugId=
|
|
421
|
+
//# debugId=0e135793-d2ed-505b-b73e-6db55218d8af
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Reads and writes tracker storage with format-aware helpers for Settings.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!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]="
|
|
7
|
+
!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]="5b95183e-9fd3-55cf-9059-8736f692e96e")}catch(e){}}();
|
|
8
8
|
import { validateSettings } from "./settings-validator.js";
|
|
9
9
|
import { runActiveOnReadHooks, runActiveOnWriteHooks, } from "../extensions/index.js";
|
|
10
10
|
import { GOVERNANCE_PRESET_DEFAULTS, SETTINGS_DEFAULTS, } from "../shared/constants.js";
|
|
@@ -730,6 +730,8 @@ function mergeSettings(settings) {
|
|
|
730
730
|
testing: {
|
|
731
731
|
record_results_to_items: settings.testing?.record_results_to_items ??
|
|
732
732
|
defaults.testing.record_results_to_items,
|
|
733
|
+
allow_untrusted_linked_tests: settings.testing?.allow_untrusted_linked_tests ??
|
|
734
|
+
defaults.testing.allow_untrusted_linked_tests,
|
|
733
735
|
},
|
|
734
736
|
telemetry: buildTelemetrySettings(settings, defaults),
|
|
735
737
|
agent_guidance: normalizeAgentGuidanceSettings(settings.agent_guidance ?? defaults.agent_guidance),
|
|
@@ -816,6 +818,7 @@ function orderSerializedSettingsSections(ordered) {
|
|
|
816
818
|
]);
|
|
817
819
|
ordered.testing = orderObject(ordered.testing, [
|
|
818
820
|
"record_results_to_items",
|
|
821
|
+
"allow_untrusted_linked_tests",
|
|
819
822
|
]);
|
|
820
823
|
ordered.telemetry = orderObject(ordered.telemetry, [
|
|
821
824
|
"enabled",
|
|
@@ -1304,4 +1307,4 @@ export const settingsStoreTestOnly = {
|
|
|
1304
1307
|
selectedSettingsReadCacheSignaturesEqual,
|
|
1305
1308
|
};
|
|
1306
1309
|
//# sourceMappingURL=settings.js.map
|
|
1307
|
-
//# debugId=
|
|
1310
|
+
//# debugId=5b95183e-9fd3-55cf-9059-8736f692e96e
|
package/dist/mcp/server.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ declare function resultContent(result: unknown, warnings?: string[], tokenAccoun
|
|
|
14
14
|
declare function errorContent(error: unknown): Record<string, unknown>;
|
|
15
15
|
/** Retain at most 32 own, valid provenance values without cloning unbounded input. */
|
|
16
16
|
declare function boundMcpClientProvenance(value: unknown): Record<string, string>;
|
|
17
|
-
/**
|
|
17
|
+
/** Dispatch one MCP request under supported process-level reproducibility settings. */
|
|
18
18
|
export declare function handleRequest(request: JsonRpcRequest): Promise<Record<string, unknown> | undefined>;
|
|
19
19
|
declare function writeError(id: JsonRpcRequest["id"], error: unknown): void;
|
|
20
20
|
/** Implements process rpc line for the public runtime surface of this module. */
|
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]="740314ae-4228-5187-a939-f438fea48415")}catch(e){}}();
|
|
9
9
|
import { realpathSync } from "node:fs";
|
|
10
10
|
import { readFile } from "node:fs/promises";
|
|
11
11
|
import path from "node:path";
|
|
@@ -20,6 +20,7 @@ import { PM_MCP_PROMPT_CONTRACTS, PM_MCP_RESOURCE_CONTRACTS, } from "../sdk/agen
|
|
|
20
20
|
import { commitItemMutations } from "../sdk/item-transaction.js";
|
|
21
21
|
import { isRuntimeRecord } 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";
|
|
25
26
|
const PM_PACKAGE_ROOT_ENV = "PM_CLI_PACKAGE_ROOT";
|
|
@@ -227,17 +228,18 @@ function resultContent(result, warnings, tokenAccounting = false) {
|
|
|
227
228
|
function errorContent(error) {
|
|
228
229
|
const code = error instanceof PmCliError ? error.exitCode : 1;
|
|
229
230
|
const message = error instanceof Error ? error.message : String(error);
|
|
231
|
+
const details = error instanceof PmCliError ? error.context : undefined;
|
|
230
232
|
return {
|
|
231
233
|
isError: true,
|
|
232
234
|
content: [
|
|
233
235
|
{
|
|
234
236
|
type: "text",
|
|
235
|
-
text: JSON.stringify({ error: message, code }, null, 2),
|
|
237
|
+
text: JSON.stringify({ error: message, code, details }, null, 2),
|
|
236
238
|
},
|
|
237
239
|
],
|
|
238
240
|
// Keep `result` present on the error envelope so consumers can read
|
|
239
241
|
// `structuredContent.result` uniformly across success and failure (pm-l40h).
|
|
240
|
-
structuredContent: { result: null, error: message, code },
|
|
242
|
+
structuredContent: { result: null, error: message, code, details },
|
|
241
243
|
};
|
|
242
244
|
}
|
|
243
245
|
/** Retain at most 32 own, valid provenance values without cloning unbounded input. */
|
|
@@ -403,7 +405,7 @@ function renderWorkflowPrompt(params) {
|
|
|
403
405
|
};
|
|
404
406
|
}
|
|
405
407
|
/** Implements handle request for the public runtime surface of this module. */
|
|
406
|
-
|
|
408
|
+
async function handleRequestInReproducibleContext(request) {
|
|
407
409
|
if (!request.id && request.method?.startsWith("notifications/")) {
|
|
408
410
|
return undefined;
|
|
409
411
|
}
|
|
@@ -459,19 +461,24 @@ export async function handleRequest(request) {
|
|
|
459
461
|
}
|
|
460
462
|
throw new PmCliError(`Unsupported MCP method: ${request.method ?? "(missing)"}`, 64);
|
|
461
463
|
}
|
|
464
|
+
/** Dispatch one MCP request under supported process-level reproducibility settings. */
|
|
465
|
+
export async function handleRequest(request) {
|
|
466
|
+
return runWithReproducibleProcessEnvironment(process.env, () => handleRequestInReproducibleContext(request));
|
|
467
|
+
}
|
|
462
468
|
function writeResponse(id, payload) {
|
|
463
469
|
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, result: payload })}\n`);
|
|
464
470
|
}
|
|
465
471
|
function writeError(id, error) {
|
|
466
472
|
const code = error instanceof PmCliError ? error.exitCode : -32603;
|
|
467
473
|
const message = error instanceof Error ? error.message : String(error);
|
|
468
|
-
|
|
474
|
+
const data = error instanceof PmCliError ? error.context : undefined;
|
|
475
|
+
process.stdout.write(`${JSON.stringify({ jsonrpc: "2.0", id, error: { code, message, data } })}\n`);
|
|
469
476
|
}
|
|
470
477
|
// pm-3puw: parse one JSON-RPC line, dispatch it, and write the response. Kept
|
|
471
478
|
// as a standalone async unit so the stdio loop can enqueue it onto a serial
|
|
472
479
|
// queue (process lines in arrival order) and tests can drive it directly.
|
|
473
480
|
/** Implements process rpc line for the public runtime surface of this module. */
|
|
474
|
-
|
|
481
|
+
async function processRpcLineWithHandler(line, requestHandler) {
|
|
475
482
|
if (line.trim().length === 0) {
|
|
476
483
|
return;
|
|
477
484
|
}
|
|
@@ -492,7 +499,7 @@ export async function processRpcLine(line) {
|
|
|
492
499
|
}
|
|
493
500
|
const shouldRespond = Object.prototype.hasOwnProperty.call(request, "id");
|
|
494
501
|
try {
|
|
495
|
-
const result = await
|
|
502
|
+
const result = await requestHandler(request);
|
|
496
503
|
if (shouldRespond && result !== undefined) {
|
|
497
504
|
writeResponse(request.id, result);
|
|
498
505
|
}
|
|
@@ -509,6 +516,10 @@ export async function processRpcLine(line) {
|
|
|
509
516
|
}
|
|
510
517
|
}
|
|
511
518
|
}
|
|
519
|
+
/** Implements process rpc line for the public runtime surface of this module. */
|
|
520
|
+
export async function processRpcLine(line) {
|
|
521
|
+
await processRpcLineWithHandler(line, handleRequest);
|
|
522
|
+
}
|
|
512
523
|
/** Implements start mcp server for the public runtime surface of this module. */
|
|
513
524
|
export function startMcpServer() {
|
|
514
525
|
const rl = readline.createInterface({
|
|
@@ -520,8 +531,18 @@ export function startMcpServer() {
|
|
|
520
531
|
// concurrently, so a client that pipelined two mutations on the same item
|
|
521
532
|
// (without awaiting the first response) hit a lock conflict on the second.
|
|
522
533
|
const queue = createSerialQueue();
|
|
534
|
+
let processLine;
|
|
535
|
+
try {
|
|
536
|
+
const runInProcessContext = createReproducibleProcessRunner(process.env);
|
|
537
|
+
processLine = (line) => runInProcessContext(() => processRpcLineWithHandler(line, handleRequestInReproducibleContext));
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
// Preserve one typed JSON-RPC error per request when process configuration
|
|
541
|
+
// is invalid; processRpcLine resolves the same configuration fail-closed.
|
|
542
|
+
processLine = processRpcLine;
|
|
543
|
+
}
|
|
523
544
|
rl.on("line", (line) => {
|
|
524
|
-
void queue.enqueue(() =>
|
|
545
|
+
void queue.enqueue(() => processLine(line));
|
|
525
546
|
});
|
|
526
547
|
}
|
|
527
548
|
// npm bin entries are symlinks (node_modules/.bin/pm-mcp -> dist/mcp/server.js),
|
|
@@ -621,4 +642,4 @@ if (isInvokedAsMcpMainModule(process.argv[1], import.meta.url)) {
|
|
|
621
642
|
}
|
|
622
643
|
/* c8 ignore stop */
|
|
623
644
|
//# sourceMappingURL=server.js.map
|
|
624
|
-
//# debugId=
|
|
645
|
+
//# debugId=740314ae-4228-5187-a939-f438fea48415
|