@unbrained/pm-cli 2026.8.12 → 2026.8.13
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 +22 -0
- package/dist/cli/error-guidance.js +4 -8
- package/dist/cli/main.js +3 -2
- package/dist/cli/register-assurance.js +28 -17
- package/dist/cli-bundle/bundle-manifest.json +161 -161
- package/dist/cli-bundle/chunks/chunk-3ZMOWAFM.js +2 -0
- package/dist/cli-bundle/chunks/chunk-DEDU3DG7.js +196 -0
- package/dist/cli-bundle/chunks/chunk-DL5M5J3V.js +13 -0
- package/dist/cli-bundle/chunks/chunk-F7FJYGK3.js +8 -0
- package/dist/cli-bundle/chunks/{chunk-RBTK5EZV.js → chunk-HIUZVCMN.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-IMGIN7R6.js +2 -0
- package/dist/cli-bundle/chunks/{chunk-WLAHPSOX.js → chunk-Q47C67TQ.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BM5YJ2UW.js → chunk-QGTUPEU5.js} +52 -52
- package/dist/cli-bundle/chunks/chunk-TF3TPKPR.js +34 -0
- package/dist/cli-bundle/chunks/{chunk-KOQMGCTA.js → chunk-YLBAPY22.js} +50 -50
- package/dist/cli-bundle/chunks/{register-list-query-XPCJRUUD.js → register-list-query-4HIZ7EA3.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-4RJCBKRS.js → register-mutation-W64FZ5HN.js} +2 -2
- package/dist/cli-bundle/chunks/register-operations-C44ET7R5.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-LLHAKP2V.js → register-setup-634MFRXU.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-27N23W6M.js +31 -0
- package/dist/cli-bundle/focused-chunks/{chunk-YIAXMC3T.js → chunk-2JP7W7GO.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-2RI2FESN.js +4 -0
- package/dist/cli-bundle/focused-chunks/chunk-3BNVU6LC.js +8 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KHM2CS2C.js → chunk-3DJSGWVB.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-2DALMVF7.js → chunk-6MLIRBLV.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-6XYLENDV.js +155 -0
- package/dist/cli-bundle/focused-chunks/chunk-CP4K4WFS.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-RWPAWUOT.js → chunk-E3AVJ655.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-5TAGTDRE.js → chunk-EBTNSFYE.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-KPSXVBDV.js → chunk-HC2OL2H2.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-GQW4BPUT.js → chunk-I75MANL7.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-ZMGWAYH7.js → chunk-IIS2FRKL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-NFHFZH2Z.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-OGC4XSBC.js +17 -0
- package/dist/cli-bundle/focused-chunks/{chunk-JAFRIWVF.js → chunk-OOYYKQWX.js} +4 -4
- package/dist/cli-bundle/focused-chunks/{chunk-KTLOKKCQ.js → chunk-PKPOZXLL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-QDZUABWL.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-QQX5TDFT.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-NYLOUPOB.js → chunk-TEZIXMTH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-WEH6NSL6.js +18 -0
- package/dist/cli-bundle/main.js +13 -13
- package/dist/cli-bundle/sdk-authoring.js +1 -1
- package/dist/cli-bundle/sdk-contracts.js +1 -1
- package/dist/cli-bundle/sdk-core.js +42 -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 +1 -1
- 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 +2 -2
- package/dist/core/checkpoint/checkpoint-gc.js +7 -12
- package/dist/core/extensions/activation-summary-markdown.js +5 -4
- package/dist/core/extensions/activation-summary.d.ts +2 -0
- package/dist/core/extensions/activation-summary.js +6 -2
- package/dist/core/extensions/capability-usage.d.ts +1 -1
- package/dist/core/extensions/capability-usage.js +4 -3
- package/dist/core/extensions/contribution-inventory.d.ts +1 -0
- package/dist/core/extensions/contribution-inventory.js +6 -2
- package/dist/core/extensions/extension-registries.js +3 -2
- package/dist/core/extensions/extension-types.d.ts +83 -1
- package/dist/core/extensions/extension-types.js +3 -2
- package/dist/core/extensions/loader.d.ts +2 -8
- package/dist/core/extensions/loader.js +53 -144
- package/dist/core/extensions/registration-values.d.ts +43 -0
- package/dist/core/extensions/registration-values.js +210 -0
- package/dist/core/extensions/runtime-registrations.d.ts +3 -1
- package/dist/core/extensions/runtime-registrations.js +12 -2
- package/dist/core/fs/fs-utils.d.ts +2 -0
- package/dist/core/fs/fs-utils.js +7 -3
- package/dist/core/history/drift-cache.js +4 -3
- package/dist/core/history/drift-scan.js +5 -11
- package/dist/core/lock/lock-gc.js +8 -13
- package/dist/core/lock/lock.js +5 -4
- package/dist/core/search/vector-stores.js +6 -11
- package/dist/core/store/item-metadata-cache.js +4 -4
- package/dist/core/telemetry/runtime.d.ts +6 -0
- package/dist/core/telemetry/runtime.js +101 -30
- package/dist/sdk/agent/command-recovery.d.ts +2 -0
- package/dist/sdk/agent/command-recovery.js +10 -2
- package/dist/sdk/annotations.js +4 -4
- package/dist/sdk/cli-contracts/completeness.js +9 -3
- package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts/flag-contracts.js +6 -3
- package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +32 -0
- package/dist/sdk/cli-contracts/schemas/assurance-definition.js +25 -2
- package/dist/sdk/cli-contracts/tool-parameter-tables.js +35 -5
- package/dist/sdk/cli-contracts/tool-schema.js +17 -2
- package/dist/sdk/comments.js +4 -3
- package/dist/sdk/compile-cache.js +4 -3
- package/dist/sdk/compose.d.ts +3 -1
- package/dist/sdk/compose.js +16 -2
- package/dist/sdk/context-signal-store.js +4 -3
- package/dist/sdk/extension/install-runtime.js +4 -4
- package/dist/sdk/extension/managed-state.js +4 -3
- package/dist/sdk/extension-contracts.d.ts +1 -1
- package/dist/sdk/flag-invocation-contracts.js +5 -6
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +14 -2
- package/dist/sdk/governance/assurance-action.d.ts +27 -3
- package/dist/sdk/governance/assurance-action.js +112 -28
- package/dist/sdk/governance/assurance-mutation-error.d.ts +7 -0
- package/dist/sdk/governance/assurance-mutation-error.js +25 -2
- package/dist/sdk/governance/assurance-presets.d.ts +54 -0
- package/dist/sdk/governance/assurance-presets.js +136 -0
- package/dist/sdk/governance/assurance-runtime.d.ts +4 -0
- package/dist/sdk/governance/assurance-runtime.js +109 -8
- package/dist/sdk/governance/assurance.d.ts +39 -0
- package/dist/sdk/governance/assurance.js +143 -4
- package/dist/sdk/governance/gc.js +5 -11
- package/dist/sdk/governance/health.js +5 -5
- package/dist/sdk/governance/validate.js +4 -4
- package/dist/sdk/graph/durable-cache.js +61 -3
- package/dist/sdk/graph/governance-contracts.d.ts +12 -0
- package/dist/sdk/graph/governance-contracts.js +27 -0
- package/dist/sdk/graph/governance.d.ts +30 -2
- package/dist/sdk/graph/governance.js +124 -5
- package/dist/sdk/guide.js +4 -4
- package/dist/sdk/index.d.ts +2 -1
- package/dist/sdk/index.js +4 -3
- package/dist/sdk/linked-artifacts.d.ts +2 -0
- package/dist/sdk/linked-artifacts.js +29 -4
- package/dist/sdk/merge/install.js +5 -4
- package/dist/sdk/query/activity.js +4 -3
- package/dist/sdk/relationship-history.js +5 -5
- package/dist/sdk/schema-migration.js +4 -4
- package/dist/sdk/test/execution.js +4 -4
- package/dist/sdk/workspace-memory.js +4 -4
- package/dist/sdk/workspace-snapshot.js +8 -14
- package/dist/sdk/workspace-transaction-gc.js +4 -9
- package/dist/sdk/workspace-transaction.js +4 -4
- package/dist/sdk/workspace.js +4 -3
- package/docs/ASSURANCE.md +154 -3
- package/docs/CONFIGURATION.md +2 -0
- package/docs/EXTENSIONS.md +11 -12
- package/docs/RELATIONSHIP_GRAPH.md +15 -0
- package/docs/SDK.md +17 -3
- package/docs/TESTING.md +24 -15
- package/marketplace.json +2 -2
- package/package.json +3 -3
- 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 +183 -33
- package/dist/cli-bundle/chunks/chunk-3PS7X6GS.js +0 -8
- package/dist/cli-bundle/chunks/chunk-7KL6KMWF.js +0 -13
- package/dist/cli-bundle/chunks/chunk-D55A5AEN.js +0 -33
- package/dist/cli-bundle/chunks/chunk-KIKDWECH.js +0 -196
- package/dist/cli-bundle/chunks/chunk-R76342NV.js +0 -2
- package/dist/cli-bundle/chunks/chunk-VLUQOIDT.js +0 -2
- package/dist/cli-bundle/chunks/register-operations-2OGISOVR.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-5OQIMELN.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-ECADZMVC.js +0 -18
- package/dist/cli-bundle/focused-chunks/chunk-EJGXRA6B.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-FFGSZCPK.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-ISKOBJCM.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-LGYK3NUF.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-NBLUKITQ.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-Q4T463SD.js +0 -31
- package/dist/cli-bundle/focused-chunks/chunk-QVZVY53N.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-UTEWXDEQ.js +0 -17
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
* mutations refresh the fenced block automatically once it is installed.
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
!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]="
|
|
11
|
+
!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]="5e1810a5-04b8-5929-8eee-7a63f1684860")}catch(e){}}();
|
|
12
|
+
import { isFileMissingError } from "../../core/fs/fs-utils.js";
|
|
12
13
|
import { readFile, realpath, writeFile } from "node:fs/promises";
|
|
13
14
|
import { execFile } from "node:child_process";
|
|
14
15
|
import path from "node:path";
|
|
@@ -253,7 +254,7 @@ async function reconcileGitattributesBlock(workspaceRoot, patterns, dryRun) {
|
|
|
253
254
|
current = await readFile(gitattributesPath, "utf8");
|
|
254
255
|
}
|
|
255
256
|
catch (error) {
|
|
256
|
-
if (!(error instanceof Error && "code" in error && error
|
|
257
|
+
if (!(error instanceof Error && "code" in error && isFileMissingError(error))) {
|
|
257
258
|
throw error;
|
|
258
259
|
}
|
|
259
260
|
}
|
|
@@ -414,7 +415,7 @@ export async function refreshMergeAttributeFenceIfInstalled(pmRoot) {
|
|
|
414
415
|
catch (error) {
|
|
415
416
|
if (error instanceof Error &&
|
|
416
417
|
"code" in error &&
|
|
417
|
-
error
|
|
418
|
+
isFileMissingError(error)) {
|
|
418
419
|
return { status: "not_installed", path: gitattributesPath };
|
|
419
420
|
}
|
|
420
421
|
throw error;
|
|
@@ -560,4 +561,4 @@ export async function installMergeFence(options) {
|
|
|
560
561
|
};
|
|
561
562
|
}
|
|
562
563
|
//# sourceMappingURL=install.js.map
|
|
563
|
-
//# debugId=
|
|
564
|
+
//# debugId=5e1810a5-04b8-5929-8eee-7a63f1684860
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Implements the pm activity command surface and its agent-facing runtime behavior.
|
|
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]="49304d18-d722-5413-8e4d-4f2c3df4a1ca")}catch(e){}}();
|
|
8
|
+
import { isFileMissingError } from "../../core/fs/fs-utils.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { getActiveExtensionRegistrations, runActiveOnReadHooks, pathExists, enforceHistoryStreamPolicyForItems, resolveItemTypeRegistry, EXIT_CODE, PmCliError, compareTimestampStrings, nowIso, resolveIsoOrRelative, listAllItemMetadataLight, getSettingsPath, resolvePmRoot, readSettings, } from "../runtime-primitives.js";
|
|
@@ -107,7 +108,7 @@ async function listHistoryFiles(historyDir) {
|
|
|
107
108
|
}
|
|
108
109
|
catch (error) {
|
|
109
110
|
// Activity should degrade gracefully when optional history storage is absent.
|
|
110
|
-
if (error
|
|
111
|
+
if (isFileMissingError(error)) {
|
|
111
112
|
return [];
|
|
112
113
|
}
|
|
113
114
|
throw error;
|
|
@@ -399,4 +400,4 @@ export async function runActivity(options, global) {
|
|
|
399
400
|
};
|
|
400
401
|
}
|
|
401
402
|
//# sourceMappingURL=activity.js.map
|
|
402
|
-
//# debugId=
|
|
403
|
+
//# debugId=49304d18-d722-5413-8e4d-4f2c3df4a1ca
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
* optimistic concurrency, deterministic replay, snapshots, and cursor pages.
|
|
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]="bb5dfa6f-b60f-55f2-ae17-3dbcaaff1b47")}catch(e){}}();
|
|
9
9
|
import { createQueryFingerprint, decodeQueryCursorState, paginateQueryRows, } from "./pagination.js";
|
|
10
10
|
import { constants } from "node:fs";
|
|
11
11
|
import { lstat, mkdir, open } from "node:fs/promises";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { acquireLock } from "../core/lock/lock.js";
|
|
14
|
-
import { writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
14
|
+
import { isFileMissingError, writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
15
15
|
import { stableStringify } from "../core/shared/serialization.js";
|
|
16
16
|
import { RelationshipGraph, createRelationshipKindRegistry, } from "./relationships.js";
|
|
17
17
|
function requiredText(value, field) {
|
|
@@ -298,7 +298,7 @@ async function resolveRelationshipEventStorePath(pmRoot, relativePath = "relatio
|
|
|
298
298
|
throw new TypeError("Relationship event path must not contain symbolic links");
|
|
299
299
|
}
|
|
300
300
|
catch (error) {
|
|
301
|
-
if (error
|
|
301
|
+
if (isFileMissingError(error))
|
|
302
302
|
break;
|
|
303
303
|
throw error;
|
|
304
304
|
}
|
|
@@ -314,7 +314,7 @@ async function loadRelationshipEventLog(target, nodes, registry) {
|
|
|
314
314
|
raw = await handle.readFile("utf8");
|
|
315
315
|
}
|
|
316
316
|
catch (error) {
|
|
317
|
-
if (error
|
|
317
|
+
if (isFileMissingError(error))
|
|
318
318
|
return { log, raw: "" };
|
|
319
319
|
throw error;
|
|
320
320
|
}
|
|
@@ -517,4 +517,4 @@ export class RelationshipEventStore {
|
|
|
517
517
|
}
|
|
518
518
|
}
|
|
519
519
|
//# sourceMappingURL=relationship-history.js.map
|
|
520
|
-
//# debugId=
|
|
520
|
+
//# debugId=bb5dfa6f-b60f-55f2-ae17-3dbcaaff1b47
|
|
@@ -7,11 +7,11 @@
|
|
|
7
7
|
* guarantees.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!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]="
|
|
10
|
+
!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]="cd777de3-665f-5e01-ac98-8986f2a5a4c2")}catch(e){}}();
|
|
11
11
|
import { createHash } from "node:crypto";
|
|
12
12
|
import fs from "node:fs/promises";
|
|
13
13
|
import path from "node:path";
|
|
14
|
-
import { pathExists, readFileIfExists, writeFileAtomic, } from "../core/fs/fs-utils.js";
|
|
14
|
+
import { isFileMissingError, pathExists, readFileIfExists, writeFileAtomic, } from "../core/fs/fs-utils.js";
|
|
15
15
|
import { appendWorkspaceHistoryChange } from "../core/history/workspace-history.js";
|
|
16
16
|
import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
|
|
17
17
|
import { parseFieldsFile, serializeFieldsFile, } from "../core/schema/fields-file.js";
|
|
@@ -681,7 +681,7 @@ async function collectSchemaReferenceState(params) {
|
|
|
681
681
|
if (typeof error !== "object" ||
|
|
682
682
|
error === null ||
|
|
683
683
|
!("code" in error) ||
|
|
684
|
-
error
|
|
684
|
+
!isFileMissingError(error)) {
|
|
685
685
|
throw error;
|
|
686
686
|
}
|
|
687
687
|
}
|
|
@@ -855,4 +855,4 @@ export const schemaMigrationTestOnly = {
|
|
|
855
855
|
validateAndStoreMigrationPlan,
|
|
856
856
|
};
|
|
857
857
|
//# sourceMappingURL=schema-migration.js.map
|
|
858
|
-
//# debugId=
|
|
858
|
+
//# debugId=cd777de3-665f-5e01-ac98-8986f2a5a4c2
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
* Implements the pm test command surface and its agent-facing runtime behavior.
|
|
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]="76053150-cc55-57e0-80d6-369196284cd0")}catch(e){}}();
|
|
8
8
|
import { spawn } from "node:child_process";
|
|
9
9
|
import { cp, mkdir, mkdtemp, open, readdir, rm } from "node:fs/promises";
|
|
10
10
|
import { tmpdir } from "node:os";
|
|
11
11
|
import path from "node:path";
|
|
12
12
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
13
|
-
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
13
|
+
import { isFileMissingError, pathExists } from "../../core/fs/fs-utils.js";
|
|
14
14
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
15
15
|
import { createStdinTokenResolver, parseCsvKv, parseOptionalNumber, } from "../../core/item/parse.js";
|
|
16
16
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
@@ -989,7 +989,7 @@ async function copyIntoSandboxIfPresent(sourcePath, targetPath, recursive = fals
|
|
|
989
989
|
if (typeof error === "object" &&
|
|
990
990
|
error !== null &&
|
|
991
991
|
"code" in error &&
|
|
992
|
-
error
|
|
992
|
+
isFileMissingError(error)) {
|
|
993
993
|
return;
|
|
994
994
|
}
|
|
995
995
|
throw error;
|
|
@@ -1939,4 +1939,4 @@ export const _testOnlyTestCommand = {
|
|
|
1939
1939
|
summarizeRunResultStatuses,
|
|
1940
1940
|
};
|
|
1941
1941
|
//# sourceMappingURL=execution.js.map
|
|
1942
|
-
//# debugId=
|
|
1942
|
+
//# debugId=76053150-cc55-57e0-80d6-369196284cd0
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
* Builds compact, cursor-bound historical rollups for large workspaces.
|
|
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]="ad77a79d-54da-55f1-8ac8-935366880d90")}catch(e){}}();
|
|
8
8
|
import path from "node:path";
|
|
9
9
|
import { createHash } from "node:crypto";
|
|
10
|
-
import { writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
10
|
+
import { isFileAbsentError, writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
11
11
|
import { normalizeStatusForRegistry } from "../core/item/status.js";
|
|
12
12
|
import { stableStringify } from "../core/shared/serialization.js";
|
|
13
13
|
import { readItemMetadataDerivedIndexState } from "../core/store/item-metadata-cache.js";
|
|
@@ -194,7 +194,7 @@ async function readPersistedWorkspaceMemory(filePath) {
|
|
|
194
194
|
const missing = typeof error === "object" &&
|
|
195
195
|
error !== null &&
|
|
196
196
|
"code" in error &&
|
|
197
|
-
error
|
|
197
|
+
isFileAbsentError(error);
|
|
198
198
|
return { snapshot: null, invalid: !missing };
|
|
199
199
|
}
|
|
200
200
|
}
|
|
@@ -316,4 +316,4 @@ export function searchWorkspaceMemoryReadResult(memory, query, limit = 5) {
|
|
|
316
316
|
};
|
|
317
317
|
}
|
|
318
318
|
//# sourceMappingURL=workspace-memory.js.map
|
|
319
|
-
//# debugId=
|
|
319
|
+
//# debugId=ad77a79d-54da-55f1-8ac8-935366880d90
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* state while excluding clone-local caches, locks, and recovery journals.
|
|
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]="36aacc71-c5f5-56f1-85f4-28b2be5b02e2")}catch(e){}}();
|
|
9
9
|
import crypto from "node:crypto";
|
|
10
10
|
import { cp, lstat, mkdir, readFile, readdir, rename, rm, writeFile, } from "node:fs/promises";
|
|
11
11
|
import path from "node:path";
|
|
12
|
-
import { writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
12
|
+
import { isFileMissingError, writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
13
13
|
import { appendWorkspaceAuditEvent } from "../core/history/workspace-history.js";
|
|
14
14
|
import { acquireLock } from "../core/lock/lock.js";
|
|
15
15
|
import { getLockPath } from "../core/store/paths.js";
|
|
@@ -205,12 +205,6 @@ function validateSnapshotTarget(target) {
|
|
|
205
205
|
});
|
|
206
206
|
}
|
|
207
207
|
}
|
|
208
|
-
function isErrno(error, code) {
|
|
209
|
-
return (typeof error === "object" &&
|
|
210
|
-
error !== null &&
|
|
211
|
-
"code" in error &&
|
|
212
|
-
error.code === code);
|
|
213
|
-
}
|
|
214
208
|
/**
|
|
215
209
|
* Runs a bounded snapshot filesystem stage, converting host environment faults
|
|
216
210
|
* into declared refusals.
|
|
@@ -250,7 +244,7 @@ async function readSnapshotJson(file, target) {
|
|
|
250
244
|
return JSON.parse(await readFile(file, "utf8"));
|
|
251
245
|
}
|
|
252
246
|
catch (error) {
|
|
253
|
-
if (
|
|
247
|
+
if (isFileMissingError(error)) {
|
|
254
248
|
throw workspaceSnapshotNotFound(target);
|
|
255
249
|
}
|
|
256
250
|
throw error;
|
|
@@ -261,7 +255,7 @@ async function removeSnapshotEntry(entry, target, recursive) {
|
|
|
261
255
|
await rm(entry, { recursive });
|
|
262
256
|
}
|
|
263
257
|
catch (error) {
|
|
264
|
-
if (
|
|
258
|
+
if (isFileMissingError(error)) {
|
|
265
259
|
throw workspaceSnapshotNotFound(target);
|
|
266
260
|
}
|
|
267
261
|
throw error;
|
|
@@ -335,7 +329,7 @@ export async function createWorkspaceSnapshot(pmRoot, options = {}) {
|
|
|
335
329
|
deduplicated = objectStat.isDirectory();
|
|
336
330
|
}
|
|
337
331
|
catch (error) {
|
|
338
|
-
if (!(error instanceof Error && "code" in error && error
|
|
332
|
+
if (!(error instanceof Error && "code" in error && isFileMissingError(error))) {
|
|
339
333
|
throw error;
|
|
340
334
|
}
|
|
341
335
|
}
|
|
@@ -392,7 +386,7 @@ export async function listWorkspaceSnapshots(pmRoot) {
|
|
|
392
386
|
const objectNames = await readdir(path.join(store, "objects")).catch((error) => {
|
|
393
387
|
if (error instanceof Error &&
|
|
394
388
|
"code" in error &&
|
|
395
|
-
error
|
|
389
|
+
isFileMissingError(error)) {
|
|
396
390
|
return [];
|
|
397
391
|
}
|
|
398
392
|
throw error;
|
|
@@ -400,7 +394,7 @@ export async function listWorkspaceSnapshots(pmRoot) {
|
|
|
400
394
|
const referenceNames = await readdir(path.join(store, "refs")).catch((error) => {
|
|
401
395
|
if (error instanceof Error &&
|
|
402
396
|
"code" in error &&
|
|
403
|
-
error
|
|
397
|
+
isFileMissingError(error)) {
|
|
404
398
|
return [];
|
|
405
399
|
}
|
|
406
400
|
throw error;
|
|
@@ -609,4 +603,4 @@ export async function deleteWorkspaceSnapshot(pmRoot, target) {
|
|
|
609
603
|
return { deleted: "object", target };
|
|
610
604
|
}
|
|
611
605
|
//# sourceMappingURL=workspace-snapshot.js.map
|
|
612
|
-
//# debugId=
|
|
606
|
+
//# debugId=36aacc71-c5f5-56f1-85f4-28b2be5b02e2
|
|
@@ -13,17 +13,12 @@
|
|
|
13
13
|
* never breaks correctness.
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
!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]="
|
|
16
|
+
!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]="7df80849-51e1-5efa-b40a-b44088f941a9")}catch(e){}}();
|
|
17
|
+
import { isFileMissingError } from "../core/fs/fs-utils.js";
|
|
17
18
|
import fs from "node:fs/promises";
|
|
18
19
|
import path from "node:path";
|
|
19
20
|
const MILLISECONDS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
20
21
|
const TERMINAL_JOURNAL_STATUSES = new Set(["committed", "compensated"]);
|
|
21
|
-
function isErrno(error, code) {
|
|
22
|
-
return (typeof error === "object" &&
|
|
23
|
-
error !== null &&
|
|
24
|
-
"code" in error &&
|
|
25
|
-
error.code === code);
|
|
26
|
-
}
|
|
27
22
|
function readJournalStatusAndTimestamp(raw) {
|
|
28
23
|
let parsed;
|
|
29
24
|
try {
|
|
@@ -129,7 +124,7 @@ export async function runWorkspaceTransactionGc(pmRoot, options) {
|
|
|
129
124
|
.sort((left, right) => left.localeCompare(right));
|
|
130
125
|
}
|
|
131
126
|
catch (error) {
|
|
132
|
-
if (
|
|
127
|
+
if (isFileMissingError(error)) {
|
|
133
128
|
return result;
|
|
134
129
|
}
|
|
135
130
|
throw error;
|
|
@@ -152,4 +147,4 @@ export async function runWorkspaceTransactionGc(pmRoot, options) {
|
|
|
152
147
|
return result;
|
|
153
148
|
}
|
|
154
149
|
//# sourceMappingURL=workspace-transaction-gc.js.map
|
|
155
|
-
//# debugId=
|
|
150
|
+
//# debugId=7df80849-51e1-5efa-b40a-b44088f941a9
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
* mutation primitives without rewriting immutable item or relationship history.
|
|
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]="6ed4a26f-2ae2-556a-87db-56844108757f")}catch(e){}}();
|
|
9
9
|
import { mkdir, readFile } from "node:fs/promises";
|
|
10
10
|
import path from "node:path";
|
|
11
11
|
import { acquireLock } from "../core/lock/lock.js";
|
|
12
|
-
import { writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
12
|
+
import { isFileMissingError, writeFileAtomic } from "../core/fs/fs-utils.js";
|
|
13
13
|
import { nowIso } from "../core/shared/time.js";
|
|
14
14
|
/**
|
|
15
15
|
* Deliberate process-boundary interruption used by deterministic crash tests.
|
|
@@ -244,7 +244,7 @@ async function loadJournal(pmRoot, transactionId, stepIds) {
|
|
|
244
244
|
if (error !== null &&
|
|
245
245
|
typeof error === "object" &&
|
|
246
246
|
"code" in error &&
|
|
247
|
-
error
|
|
247
|
+
isFileMissingError(error))
|
|
248
248
|
return undefined;
|
|
249
249
|
throw error;
|
|
250
250
|
}
|
|
@@ -361,4 +361,4 @@ export async function commitWorkspaceTransaction(options) {
|
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
//# sourceMappingURL=workspace-transaction.js.map
|
|
364
|
-
//# debugId=
|
|
364
|
+
//# debugId=6ed4a26f-2ae2-556a-87db-56844108757f
|
package/dist/sdk/workspace.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Maintains repository-scaffold contracts shared by the public SDK and CLI.
|
|
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]="89261a49-97e5-5ffc-a81c-2409f0b529cf")}catch(e){}}();
|
|
8
|
+
import { isFileMissingError } from "../core/fs/fs-utils.js";
|
|
8
9
|
import { readFile, writeFile } from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { EXIT_CODE } from "../core/shared/constants.js";
|
|
@@ -107,7 +108,7 @@ export async function ensurePmGitignore(workspaceRoot, options = {}) {
|
|
|
107
108
|
current = await withGitignorePermissionRecovery(() => readFile(gitignorePath, "utf8"));
|
|
108
109
|
}
|
|
109
110
|
catch (error) {
|
|
110
|
-
if (!(error instanceof Error && "code" in error && error
|
|
111
|
+
if (!(error instanceof Error && "code" in error && isFileMissingError(error))) {
|
|
111
112
|
throw error;
|
|
112
113
|
}
|
|
113
114
|
}
|
|
@@ -125,4 +126,4 @@ export async function ensurePmGitignore(workspaceRoot, options = {}) {
|
|
|
125
126
|
return { path: gitignorePath, changed: true };
|
|
126
127
|
}
|
|
127
128
|
//# sourceMappingURL=workspace.js.map
|
|
128
|
-
//# debugId=
|
|
129
|
+
//# debugId=89261a49-97e5-5ffc-a81c-2409f0b529cf
|
package/docs/ASSURANCE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Project Assurance Primitives
|
|
2
2
|
|
|
3
|
-
Tracker: [pm-2lex4r](../.agents/pm/features/pm-2lex4r.toon), [pm-lyfu7b](../.agents/pm/features/pm-lyfu7b.toon), [pm-wn6wot](../.agents/pm/features/pm-wn6wot.toon), [pm-91xeam](../.agents/pm/features/pm-91xeam.toon), [pm-py7qv2](../.agents/pm/issues/pm-py7qv2.toon), [pm-33mjrw](../.agents/pm/issues/pm-33mjrw.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon)
|
|
3
|
+
Tracker: [pm-2lex4r](../.agents/pm/features/pm-2lex4r.toon), [pm-lyfu7b](../.agents/pm/features/pm-lyfu7b.toon), [pm-wn6wot](../.agents/pm/features/pm-wn6wot.toon), [pm-91xeam](../.agents/pm/features/pm-91xeam.toon), [pm-uhv1m5](../.agents/pm/features/pm-uhv1m5.toon), [pm-m7bb7r](../.agents/pm/features/pm-m7bb7r.toon), [pm-py7qv2](../.agents/pm/issues/pm-py7qv2.toon), [pm-33mjrw](../.agents/pm/issues/pm-33mjrw.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon)
|
|
4
4
|
|
|
5
5
|
## Agent Quick Context
|
|
6
6
|
|
|
@@ -36,6 +36,11 @@ Measurements support these built-in sources:
|
|
|
36
36
|
|
|
37
37
|
Each measurement may declare `max_cost`. Evaluation fails closed when the total abstract compute units exceed that ceiling. Every result reports units, scanned items, scanned history rows, provider calls, duration, population size, and contributors.
|
|
38
38
|
|
|
39
|
+
One workspace context memoizes identical graph operations and the shared
|
|
40
|
+
validate and health reports for its lifetime. A gate may therefore project many
|
|
41
|
+
fields from one authoritative audit snapshot without multiplying full-workspace
|
|
42
|
+
I/O or allowing concurrent assertions to observe different tracker states.
|
|
43
|
+
|
|
39
44
|
An `items` source with `field` must declare exactly one predicate: `equals` (including an explicit `null`) or `state`. `state: missing` treats an absent property, `null`, an empty string, or an empty array as missing; `state: present` selects the complement. Workspace evaluation loads full item metadata, so `files`, `tests`, and `docs` selectors measure stored evidence rather than a light projection that omitted those collections.
|
|
40
45
|
|
|
41
46
|
Assertions require exactly one polarity:
|
|
@@ -86,6 +91,152 @@ pm assurance remove gate release-readiness
|
|
|
86
91
|
|
|
87
92
|
Referenced measurements and assertions cannot be removed. Remove the consuming gate or assertion first.
|
|
88
93
|
|
|
94
|
+
### Presets, derivation, and promotion
|
|
95
|
+
|
|
96
|
+
List the four built-in project shapes, preview one as ordinary declarations, or apply it atomically:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pm assurance presets
|
|
100
|
+
pm assurance presets software-delivery --owner pm-example
|
|
101
|
+
pm assurance apply software-delivery --owner pm-example \
|
|
102
|
+
--message "Adopt the initial delivery evidence contract"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The preset creates measurements, assertions, and a gate in one audited transaction. Reapplying the same bundle is idempotent; an existing divergent id is refused rather than overwritten. The available shapes are `software-delivery`, `research`, `agent-evaluation`, and `operations`.
|
|
106
|
+
|
|
107
|
+
Self-derivation observes active items without writing anything. Each proposal reports its active scope, population size, and observed missing-evidence ceiling. Persistence requires the explicit `--apply` flag:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pm assurance derive --owner pm-example
|
|
111
|
+
pm assurance derive --owner pm-example --apply \
|
|
112
|
+
--message "Accept the observed evidence baseline"
|
|
113
|
+
pm assurance promote derived-active-missing-tests-ceiling --enforcement warn
|
|
114
|
+
pm assurance promote derived-active-missing-tests-ceiling --enforcement block
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Derived assertions start at `observe`. Promotion is exactly one step (`observe` to `warn`, then `warn` to `block`) and each transition is an ordinary audited declaration mutation. There is no automatic promotion and no privileged preset execution path.
|
|
118
|
+
|
|
119
|
+
## Extension Measurement Providers
|
|
120
|
+
|
|
121
|
+
An extension opens the measurement vocabulary through `api.registerAssuranceMeasurementProvider`. The registration declares stable keys, parameter types, a coarse `low`/`medium`/`high` cost class, network use, a host timeout, and a resolver. It requires the `services` capability; a network provider must also declare `permissions.network: true` in `manifest.json`.
|
|
122
|
+
|
|
123
|
+
This code-quality provider measures a local report without changing assertion or gate semantics:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
import { readFile } from "node:fs/promises";
|
|
127
|
+
import { defineExtension } from "@unbrained/pm-cli/sdk";
|
|
128
|
+
|
|
129
|
+
export default defineExtension({
|
|
130
|
+
activate(api) {
|
|
131
|
+
api.registerAssuranceMeasurementProvider({
|
|
132
|
+
id: "coverage",
|
|
133
|
+
keys: {
|
|
134
|
+
lines: {
|
|
135
|
+
value_type: "number",
|
|
136
|
+
parameters: { report: { type: "string", required: true } },
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
cost_class: "low",
|
|
140
|
+
network: false,
|
|
141
|
+
timeout_ms: 2_000,
|
|
142
|
+
async resolve({ parameters }) {
|
|
143
|
+
const report = JSON.parse(
|
|
144
|
+
await readFile(String(parameters.report), "utf8"),
|
|
145
|
+
) as {
|
|
146
|
+
total: { lines: { pct: number } };
|
|
147
|
+
};
|
|
148
|
+
return { value: report.total.lines.pct, population_size: 1, cost: 1 };
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
An evaluation package can expose episode reward on the same surface:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
api.registerAssuranceMeasurementProvider({
|
|
159
|
+
id: "agent-eval",
|
|
160
|
+
keys: {
|
|
161
|
+
"mean-reward": {
|
|
162
|
+
value_type: "number",
|
|
163
|
+
parameters: { suite: { type: "string", required: true } },
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
cost_class: "high",
|
|
167
|
+
network: false,
|
|
168
|
+
timeout_ms: 120_000,
|
|
169
|
+
async resolve({ parameters }) {
|
|
170
|
+
const result = await runFrozenEvaluation(String(parameters.suite));
|
|
171
|
+
return {
|
|
172
|
+
value: result.meanReward,
|
|
173
|
+
population_size: result.episodes,
|
|
174
|
+
cost: result.steps,
|
|
175
|
+
contributors: result.regressedScenarioIds,
|
|
176
|
+
};
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
An external registry provider declares its network dependency explicitly:
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
api.registerAssuranceMeasurementProvider({
|
|
185
|
+
id: "npm-registry",
|
|
186
|
+
keys: {
|
|
187
|
+
"dist-tag-count": {
|
|
188
|
+
value_type: "number",
|
|
189
|
+
parameters: { package: { type: "string", required: true } },
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
cost_class: "medium",
|
|
193
|
+
network: true,
|
|
194
|
+
timeout_ms: 5_000,
|
|
195
|
+
async resolve({ parameters }) {
|
|
196
|
+
const name = encodeURIComponent(String(parameters.package));
|
|
197
|
+
const response = await fetch(
|
|
198
|
+
`https://registry.npmjs.org/-/package/${name}/dist-tags`,
|
|
199
|
+
);
|
|
200
|
+
if (!response.ok) throw new Error(`registry returned ${response.status}`);
|
|
201
|
+
const tags = (await response.json()) as Record<string, string>;
|
|
202
|
+
return { value: Object.keys(tags).length, population_size: 1, cost: 10 };
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
The corresponding measurement is ordinary registry data:
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"id": "published-tag-count",
|
|
212
|
+
"source": {
|
|
213
|
+
"kind": "provider",
|
|
214
|
+
"provider": "npm-registry",
|
|
215
|
+
"key": "dist-tag-count",
|
|
216
|
+
"parameters": { "package": "@example/tool" }
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
A provider-backed gate must opt into every provider and each trigger's execution envelope. Omission refuses provider execution:
|
|
222
|
+
|
|
223
|
+
```json
|
|
224
|
+
{
|
|
225
|
+
"id": "release-readiness",
|
|
226
|
+
"assertion_ids": ["published-tag-count-ceiling"],
|
|
227
|
+
"triggers": ["ci", "scheduled"],
|
|
228
|
+
"provider_policy": {
|
|
229
|
+
"allowed_providers": ["npm-registry"],
|
|
230
|
+
"triggers": {
|
|
231
|
+
"ci": { "max_cost_class": "low", "allow_network": false },
|
|
232
|
+
"scheduled": { "max_cost_class": "medium", "allow_network": true }
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Before invocation the host verifies the provider allow-list, declared cost class, and network capability for the active trigger. It then validates key parameters and result shape, enforces the registered timeout, and charges the returned cost through the existing measurement ceiling. Extension tests must bind `PM_PATH` and `PM_GLOBAL_PATH` to temporary roots; never point provider fixtures at the repository tracker or a live service.
|
|
239
|
+
|
|
89
240
|
## SDK and MCP
|
|
90
241
|
|
|
91
242
|
The reusable client exposes the same action grammar:
|
|
@@ -103,9 +254,9 @@ await pm.assurance({
|
|
|
103
254
|
});
|
|
104
255
|
```
|
|
105
256
|
|
|
106
|
-
For direct host composition, use `evaluateMeasurement`, `evaluateAssuranceGate`, `createAssuranceWorkspaceContext`, and the audited declaration/verdict helpers exported from `@unbrained/pm-cli/sdk`.
|
|
257
|
+
For direct host composition, use `evaluateMeasurement`, `evaluateAssuranceGate`, `createAssuranceWorkspaceContext`, the preset/derivation helpers, and the audited declaration/verdict helpers exported from `@unbrained/pm-cli/sdk`. Active extension registrations are discovered automatically. Embedding hosts may additionally pass stable resolver ids and matching `provider_capabilities` to `createAssuranceWorkspaceContext`; an absent resolver or capability fails loudly. The core evaluator bounds concurrent assertions and expression operands, and workspace history loading uses bounded concurrency; item-only callers can explicitly skip history and Git identity resolution.
|
|
107
258
|
|
|
108
|
-
Generic SDK and MCP dispatch use `action: "assurance"` with `subcommand` set to `list`, `show`, `put`, `remove`, `run`, or `
|
|
259
|
+
Generic SDK and MCP dispatch use `action: "assurance"` with `subcommand` set to `list`, `show`, `put`, `remove`, `run`, `verdicts`, `presets`, `apply`, `derive`, or `promote`. Discover the current machine contract instead of copying parameter lists:
|
|
109
260
|
|
|
110
261
|
```bash
|
|
111
262
|
pm contracts --action assurance --schema-only --json
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -156,6 +156,7 @@ Telemetry is opt-in via `pm config set telemetry-tracking on` (see [Common Setti
|
|
|
156
156
|
| `PM_TELEMETRY_OTEL_DISABLED` | boolean | Disable only OTLP trace-span export; the event queue still flushes. |
|
|
157
157
|
| `PM_TELEMETRY_INLINE_FLUSH` | boolean | Flush the queue and OTLP spans inline instead of dispatching the detached worker. Mainly for tests; normal use relies on the background worker. |
|
|
158
158
|
| `PM_TELEMETRY_SOURCE_CONTEXT` | `user` \| `automation` \| `test` \| `dogfood` | Override the inferred source context recorded on each event. Any other value is ignored and the context is inferred. |
|
|
159
|
+
| `PM_TELEMETRY_HTTP_TIMEOUT_MS` | integer milliseconds | Bound each background event or OTLP request (default `20000`, clamped to `1000`–`25000` to stay below the worker lock TTL). |
|
|
159
160
|
| `PM_TELEMETRY_INGEST_KEY` | string | Sent as the `x-pm-telemetry-key` header on queue flushes; never logged. |
|
|
160
161
|
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | URL | OTLP/HTTP traces endpoint for command spans. Takes precedence over the base endpoint. |
|
|
161
162
|
| `OTEL_EXPORTER_OTLP_ENDPOINT` | URL | Base OTLP endpoint; the traces endpoint is derived by appending `/v1/traces`. |
|
|
@@ -164,6 +165,7 @@ Telemetry is opt-in via `pm config set telemetry-tracking on` (see [Common Setti
|
|
|
164
165
|
Interaction rules:
|
|
165
166
|
|
|
166
167
|
- `PM_TELEMETRY_DISABLED` / `PM_NO_TELEMETRY` short-circuit everything, including OTLP export, regardless of the other knobs.
|
|
168
|
+
- `PM_TELEMETRY_HTTP_TIMEOUT_MS` applies only to the detached flush worker in normal use. It covers DNS, each IPv4/IPv6 connection attempt, TLS, and response completion. The upper bound preserves the 60-second worker-lock safety margin across the sequential event and OTLP phases; it does not make foreground commands wait for the network.
|
|
167
169
|
- OTLP span export only happens when telemetry is enabled, `PM_TELEMETRY_OTEL_DISABLED` is off, and a traces endpoint is configured. By default spans are persisted to a bounded queue and exported by the detached, unref'd flush worker so commands exit promptly even when the traces endpoint is unreachable. `PM_TELEMETRY_INLINE_FLUSH=1` is the explicit test-oriented exception that performs the flush inline.
|
|
168
170
|
- `pm health --check-telemetry --json` surfaces flush and OTLP export diagnostics (`pending_otel_spans`, `last_otel_attempt_at`, `last_otel_success_at`, `last_otel_failure_at`, `last_otel_failure_error`) and the active `env_overrides` (including `telemetry_inline_flush` and `telemetry_source_context`) so agents can self-diagnose a stalled endpoint.
|
|
169
171
|
- An explicit `PM_AUTHOR` override adds a privacy-preserving agent-identity dimension to `command_start`/`command_finish` events so overridden invocations can be segmented in dashboards without leaking the raw author string. At `redacted`/`max` capture the events carry `author_context_hash` — the same installation-id-keyed one-way SHA-256 used for `pm_root_hash`/`cwd_hash`, so the same author hashes consistently within an installation but differently across installations. At `minimal` capture only a boolean `has_author_context` is emitted. The raw `PM_AUTHOR` value is never exported.
|