@unbrained/pm-cli 2026.8.12 → 2026.8.14

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.
Files changed (218) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +162 -111
  3. package/dist/cli/error-guidance.js +4 -8
  4. package/dist/cli/main.js +40 -3
  5. package/dist/cli/register-assurance.js +28 -17
  6. package/dist/cli-bundle/bundle-manifest.json +141 -173
  7. package/dist/cli-bundle/chunks/chunk-BBOFSVAK.js +197 -0
  8. package/dist/cli-bundle/chunks/chunk-BFALV3YP.js +5 -0
  9. package/dist/cli-bundle/chunks/{chunk-WLAHPSOX.js → chunk-FIW4P64F.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-BM5YJ2UW.js → chunk-G5JUB66K.js} +52 -52
  11. package/dist/cli-bundle/chunks/chunk-SBRKH6OR.js +2 -0
  12. package/dist/cli-bundle/chunks/chunk-TMJ7URWS.js +13 -0
  13. package/dist/cli-bundle/chunks/chunk-TXMEUUUY.js +8 -0
  14. package/dist/cli-bundle/chunks/{chunk-KOQMGCTA.js → chunk-XAVMOK6B.js} +50 -50
  15. package/dist/cli-bundle/chunks/chunk-YAMTJL6Y.js +34 -0
  16. package/dist/cli-bundle/chunks/chunk-YSVSMJ2B.js +2 -0
  17. package/dist/cli-bundle/chunks/{register-list-query-XPCJRUUD.js → register-list-query-T3EHHNNV.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-mutation-4RJCBKRS.js → register-mutation-E27WCLSZ.js} +2 -2
  19. package/dist/cli-bundle/chunks/register-operations-4R6I7CPY.js +2 -0
  20. package/dist/cli-bundle/chunks/{register-setup-LLHAKP2V.js → register-setup-3YXZ444E.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-JAFRIWVF.js → chunk-4DQ2YERC.js} +4 -4
  22. package/dist/cli-bundle/focused-chunks/chunk-F43TT2QQ.js +8 -0
  23. package/dist/cli-bundle/focused-chunks/chunk-K7RWWOAG.js +4 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-KFSZ3BP6.js +16 -0
  25. package/dist/cli-bundle/focused-chunks/{chunk-KHM2CS2C.js → chunk-KSEDUWVZ.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-KYUQGTSB.js +2 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-ZMGWAYH7.js → chunk-LZ4MV3RH.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/chunk-PGXJQLCT.js +155 -0
  29. package/dist/cli-bundle/focused-chunks/{chunk-RWPAWUOT.js → chunk-PPFGQDSI.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-Q4YY3XNF.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-QK753U3U.js +46 -0
  32. package/dist/cli-bundle/focused-chunks/chunk-QUMB2J27.js +2 -0
  33. package/dist/cli-bundle/focused-chunks/chunk-SM7MTG27.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/{chunk-GQW4BPUT.js → chunk-WCVE2NIG.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/chunk-XDNAW5OI.js +18 -0
  36. package/dist/cli-bundle/focused-chunks/{chunk-YIAXMC3T.js → chunk-YOOI3UZX.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/chunk-ZM6TZVHC.js +2 -0
  38. package/dist/cli-bundle/main.js +13 -13
  39. package/dist/cli-bundle/sdk-authoring.js +1 -1
  40. package/dist/cli-bundle/sdk-contracts.js +1 -1
  41. package/dist/cli-bundle/sdk-core.js +45 -41
  42. package/dist/cli-bundle/sdk-governance.js +1 -1
  43. package/dist/cli-bundle/sdk-graph.js +1 -1
  44. package/dist/cli-bundle/sdk-merge.js +109 -1
  45. package/dist/cli-bundle/sdk-query.js +1 -1
  46. package/dist/cli-bundle/sdk-runtime.js +1 -1
  47. package/dist/cli-bundle/sdk-testing.js +1 -1
  48. package/dist/cli-bundle/sdk.js +2 -2
  49. package/dist/core/checkpoint/checkpoint-gc.js +7 -12
  50. package/dist/core/extensions/activation-summary-markdown.js +5 -4
  51. package/dist/core/extensions/activation-summary.d.ts +2 -0
  52. package/dist/core/extensions/activation-summary.js +6 -2
  53. package/dist/core/extensions/capability-usage.d.ts +1 -1
  54. package/dist/core/extensions/capability-usage.js +4 -3
  55. package/dist/core/extensions/contribution-inventory.d.ts +1 -0
  56. package/dist/core/extensions/contribution-inventory.js +6 -2
  57. package/dist/core/extensions/extension-registries.js +3 -2
  58. package/dist/core/extensions/extension-types.d.ts +83 -1
  59. package/dist/core/extensions/extension-types.js +3 -2
  60. package/dist/core/extensions/loader.d.ts +2 -8
  61. package/dist/core/extensions/loader.js +53 -144
  62. package/dist/core/extensions/registration-values.d.ts +43 -0
  63. package/dist/core/extensions/registration-values.js +210 -0
  64. package/dist/core/extensions/runtime-registrations.d.ts +3 -1
  65. package/dist/core/extensions/runtime-registrations.js +12 -2
  66. package/dist/core/fs/fs-utils.d.ts +2 -0
  67. package/dist/core/fs/fs-utils.js +7 -3
  68. package/dist/core/history/drift-cache.js +4 -3
  69. package/dist/core/history/drift-scan.d.ts +6 -0
  70. package/dist/core/history/drift-scan.js +76 -58
  71. package/dist/core/history/workspace-history.d.ts +59 -0
  72. package/dist/core/history/workspace-history.js +197 -10
  73. package/dist/core/lock/lock-gc.js +8 -13
  74. package/dist/core/lock/lock.js +5 -4
  75. package/dist/core/output/output.js +12 -4
  76. package/dist/core/search/vector-stores.js +6 -11
  77. package/dist/core/store/item-metadata-cache.js +4 -4
  78. package/dist/core/telemetry/runtime.d.ts +6 -0
  79. package/dist/core/telemetry/runtime.js +101 -30
  80. package/dist/sdk/agent/command-recovery.d.ts +2 -0
  81. package/dist/sdk/agent/command-recovery.js +10 -2
  82. package/dist/sdk/annotations.js +4 -4
  83. package/dist/sdk/cli-contracts/completeness.js +9 -3
  84. package/dist/sdk/cli-contracts/enum-contracts.d.ts +1 -1
  85. package/dist/sdk/cli-contracts/flag-contracts.js +6 -3
  86. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +6 -1
  87. package/dist/sdk/cli-contracts/runtime-contracts.js +155 -60
  88. package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +32 -0
  89. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +25 -2
  90. package/dist/sdk/cli-contracts/tool-parameter-tables.js +35 -5
  91. package/dist/sdk/cli-contracts/tool-schema.js +17 -2
  92. package/dist/sdk/cli-program.js +3 -3
  93. package/dist/sdk/comments.js +4 -3
  94. package/dist/sdk/compile-cache.js +4 -3
  95. package/dist/sdk/compose.d.ts +3 -1
  96. package/dist/sdk/compose.js +16 -2
  97. package/dist/sdk/context-relevance.js +12 -4
  98. package/dist/sdk/context-signal-store.js +4 -3
  99. package/dist/sdk/extension/install-runtime.js +4 -4
  100. package/dist/sdk/extension/managed-state.js +4 -3
  101. package/dist/sdk/extension-contracts.d.ts +1 -1
  102. package/dist/sdk/flag-invocation-contracts.js +5 -6
  103. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +14 -2
  104. package/dist/sdk/governance/assurance-action.d.ts +27 -3
  105. package/dist/sdk/governance/assurance-action.js +112 -28
  106. package/dist/sdk/governance/assurance-mutation-error.d.ts +7 -0
  107. package/dist/sdk/governance/assurance-mutation-error.js +25 -2
  108. package/dist/sdk/governance/assurance-presets.d.ts +54 -0
  109. package/dist/sdk/governance/assurance-presets.js +136 -0
  110. package/dist/sdk/governance/assurance-runtime.d.ts +4 -0
  111. package/dist/sdk/governance/assurance-runtime.js +109 -8
  112. package/dist/sdk/governance/assurance.d.ts +39 -0
  113. package/dist/sdk/governance/assurance.js +145 -6
  114. package/dist/sdk/governance/gc.js +5 -11
  115. package/dist/sdk/governance/health.js +18 -6
  116. package/dist/sdk/governance/validate-history-drift.d.ts +7 -0
  117. package/dist/sdk/governance/validate-history-drift.js +68 -0
  118. package/dist/sdk/governance/validate.js +6 -48
  119. package/dist/sdk/graph/assembly.d.ts +23 -0
  120. package/dist/sdk/graph/assembly.js +54 -2
  121. package/dist/sdk/graph/durable-cache.js +91 -3
  122. package/dist/sdk/graph/governance-contracts.d.ts +12 -0
  123. package/dist/sdk/graph/governance-contracts.js +29 -0
  124. package/dist/sdk/graph/governance.d.ts +51 -3
  125. package/dist/sdk/graph/governance.js +216 -35
  126. package/dist/sdk/graph/index.d.ts +2 -2
  127. package/dist/sdk/graph/index.js +4 -4
  128. package/dist/sdk/graph/mutation-advisory.js +15 -7
  129. package/dist/sdk/graph/remediation.js +12 -2
  130. package/dist/sdk/guide.js +4 -4
  131. package/dist/sdk/history-read.d.ts +8 -0
  132. package/dist/sdk/history-read.js +2 -2
  133. package/dist/sdk/index.d.ts +3 -2
  134. package/dist/sdk/index.js +5 -4
  135. package/dist/sdk/linked-artifacts.d.ts +2 -0
  136. package/dist/sdk/linked-artifacts.js +29 -4
  137. package/dist/sdk/merge/install.js +5 -4
  138. package/dist/sdk/query/activity.js +4 -3
  139. package/dist/sdk/query/history.js +20 -3
  140. package/dist/sdk/read-output-budget.d.ts +2 -0
  141. package/dist/sdk/read-output-budget.js +12 -5
  142. package/dist/sdk/read-output-contracts.d.ts +61 -5
  143. package/dist/sdk/read-output-contracts.js +210 -28
  144. package/dist/sdk/read-output-rows.d.ts +11 -0
  145. package/dist/sdk/read-output-rows.js +47 -2
  146. package/dist/sdk/relationship-history.js +5 -5
  147. package/dist/sdk/runtime-primitives.d.ts +1 -1
  148. package/dist/sdk/runtime-primitives.js +3 -3
  149. package/dist/sdk/runtime.js +5 -3
  150. package/dist/sdk/schema-migration.js +4 -4
  151. package/dist/sdk/test/execution.js +4 -4
  152. package/dist/sdk/workspace-memory.js +4 -4
  153. package/dist/sdk/workspace-snapshot.js +8 -14
  154. package/dist/sdk/workspace-transaction-gc.js +4 -9
  155. package/dist/sdk/workspace-transaction.js +4 -4
  156. package/dist/sdk/workspace.js +4 -3
  157. package/docs/ASSURANCE.md +163 -3
  158. package/docs/COMMANDS.md +31 -2
  159. package/docs/CONFIGURATION.md +2 -0
  160. package/docs/EXTENSIONS.md +11 -12
  161. package/docs/READ_OUTPUT_CONTRACTS.md +44 -8
  162. package/docs/RELATIONSHIP_GRAPH.md +34 -4
  163. package/docs/SDK.md +29 -8
  164. package/docs/SDK_CONTEXT_INTEGRITY.md +32 -1
  165. package/docs/TESTING.md +47 -16
  166. package/docs/performance/sdk-entrypoint-import-costs.md +20 -13
  167. package/marketplace.json +2 -2
  168. package/package.json +6 -6
  169. package/packages/pm-beads/extensions/beads/index.ts +1 -0
  170. package/packages/pm-beads/package.json +1 -1
  171. package/packages/pm-calendar/extensions/calendar/index.ts +1 -0
  172. package/packages/pm-calendar/package.json +1 -1
  173. package/packages/pm-command-kit/package.json +1 -1
  174. package/packages/pm-digital-twin/extensions/digital-twin/index.ts +7 -0
  175. package/packages/pm-digital-twin/package.json +1 -1
  176. package/packages/pm-governance-audit/extensions/governance-audit/index.ts +4 -0
  177. package/packages/pm-governance-audit/package.json +1 -1
  178. package/packages/pm-guide-shell/extensions/guide-shell/index.ts +5 -0
  179. package/packages/pm-guide-shell/package.json +1 -1
  180. package/packages/pm-kanban/package.json +1 -1
  181. package/packages/pm-lifecycle-hooks/package.json +1 -1
  182. package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/index.ts +6 -0
  183. package/packages/pm-linked-test-adapters/package.json +1 -1
  184. package/packages/pm-search-advanced/extensions/search-advanced/index.ts +2 -0
  185. package/packages/pm-search-advanced/package.json +1 -1
  186. package/packages/pm-templates/extensions/templates/index.ts +4 -0
  187. package/packages/pm-templates/package.json +1 -1
  188. package/packages/pm-todos/extensions/todos/index.ts +2 -0
  189. package/packages/pm-todos/package.json +1 -1
  190. package/packages/pm-vcs/extensions/vcs/index.ts +7 -0
  191. package/packages/pm-vcs/package.json +1 -1
  192. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  193. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  194. package/scripts/bundle-cli.mjs +17 -4
  195. package/sdk/public-surface.json +390 -60
  196. package/dist/cli-bundle/chunks/chunk-3PS7X6GS.js +0 -8
  197. package/dist/cli-bundle/chunks/chunk-7KL6KMWF.js +0 -13
  198. package/dist/cli-bundle/chunks/chunk-D55A5AEN.js +0 -33
  199. package/dist/cli-bundle/chunks/chunk-KIKDWECH.js +0 -196
  200. package/dist/cli-bundle/chunks/chunk-R76342NV.js +0 -2
  201. package/dist/cli-bundle/chunks/chunk-RBTK5EZV.js +0 -5
  202. package/dist/cli-bundle/chunks/chunk-VLUQOIDT.js +0 -2
  203. package/dist/cli-bundle/chunks/register-operations-2OGISOVR.js +0 -2
  204. package/dist/cli-bundle/focused-chunks/chunk-2DALMVF7.js +0 -5
  205. package/dist/cli-bundle/focused-chunks/chunk-5OQIMELN.js +0 -155
  206. package/dist/cli-bundle/focused-chunks/chunk-5TAGTDRE.js +0 -2
  207. package/dist/cli-bundle/focused-chunks/chunk-ECADZMVC.js +0 -18
  208. package/dist/cli-bundle/focused-chunks/chunk-EJGXRA6B.js +0 -2
  209. package/dist/cli-bundle/focused-chunks/chunk-FFGSZCPK.js +0 -16
  210. package/dist/cli-bundle/focused-chunks/chunk-ISKOBJCM.js +0 -2
  211. package/dist/cli-bundle/focused-chunks/chunk-KPSXVBDV.js +0 -2
  212. package/dist/cli-bundle/focused-chunks/chunk-KTLOKKCQ.js +0 -2
  213. package/dist/cli-bundle/focused-chunks/chunk-LGYK3NUF.js +0 -8
  214. package/dist/cli-bundle/focused-chunks/chunk-NBLUKITQ.js +0 -4
  215. package/dist/cli-bundle/focused-chunks/chunk-NYLOUPOB.js +0 -2
  216. package/dist/cli-bundle/focused-chunks/chunk-Q4T463SD.js +0 -31
  217. package/dist/cli-bundle/focused-chunks/chunk-QVZVY53N.js +0 -2
  218. package/dist/cli-bundle/focused-chunks/chunk-UTEWXDEQ.js +0 -17
@@ -0,0 +1,136 @@
1
+ /**
2
+ * @module sdk/governance/assurance-presets
3
+ *
4
+ * Supplies readable assurance starter bundles and observation-derived proposals
5
+ * without introducing privileged evaluation semantics.
6
+ */
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]="05c29627-6763-5aee-8579-71e563a98780")}catch(e){}}();
9
+ import { evaluateMeasurement, putAssuranceDeclaration, putAssuranceDeclarationBundle, } from "./assurance.js";
10
+ /** Built-in project shapes that can acquire a quality contract in one command. */
11
+ export const ASSURANCE_PRESET_IDS = [
12
+ "software-delivery",
13
+ "research",
14
+ "agent-evaluation",
15
+ "operations",
16
+ ];
17
+ function assertion(id, measurementId, ownerItemId, ceiling, enforcement) {
18
+ return {
19
+ id,
20
+ measurement_id: measurementId,
21
+ owner_item_id: ownerItemId,
22
+ scope: { kind: "active" },
23
+ ceiling,
24
+ lifetime: "hold",
25
+ enforcement,
26
+ negative_control: {
27
+ cases: [
28
+ { observed: ceiling, expected: "pass" },
29
+ { observed: ceiling + 1, expected: "fail" },
30
+ ],
31
+ },
32
+ };
33
+ }
34
+ function evidencePreset(id, title, description, ownerItemId, links) {
35
+ const prefix = `preset-${id}`;
36
+ const measurements = links.map((link) => ({
37
+ id: `${prefix}-missing-${link}`,
38
+ description: `Active items missing ${link} evidence.`,
39
+ source: { kind: "links", link, state: "missing" },
40
+ }));
41
+ const assertions = measurements.map((measurement) => assertion(`${measurement.id}-zero`, measurement.id, ownerItemId, 0, "warn"));
42
+ return {
43
+ id,
44
+ title,
45
+ description,
46
+ declarations: {
47
+ measurements,
48
+ assertions,
49
+ gates: [
50
+ {
51
+ id: `${prefix}-readiness`,
52
+ description,
53
+ assertion_ids: assertions.map((entry) => entry.id),
54
+ triggers: ["ci", "scheduled"],
55
+ },
56
+ ],
57
+ },
58
+ };
59
+ }
60
+ /** Materialize one built-in preset as ordinary declarations owned by a pm item. */
61
+ export function createAssurancePreset(id, ownerItemId) {
62
+ if (id === "software-delivery") {
63
+ return evidencePreset(id, "Software delivery", "Warn when active delivery work lacks executable tests or documentation.", ownerItemId, ["tests", "docs"]);
64
+ }
65
+ if (id === "research") {
66
+ return evidencePreset(id, "Research", "Warn when active research work lacks reproducibility files or documentation.", ownerItemId, ["files", "docs"]);
67
+ }
68
+ if (id === "agent-evaluation") {
69
+ return evidencePreset(id, "Agent evaluation", "Warn when active evaluation work lacks executable scenarios or recorded artifacts.", ownerItemId, ["tests", "files"]);
70
+ }
71
+ return evidencePreset(id, "Operations", "Warn when active operational work lacks runbook documentation or repair evidence.", ownerItemId, ["docs", "files"]);
72
+ }
73
+ /** Apply one preset atomically; a second identical application is idempotent. */
74
+ export function applyAssurancePreset(pmRoot, id, ownerItemId, options = {}) {
75
+ return putAssuranceDeclarationBundle(pmRoot, createAssurancePreset(id, ownerItemId).declarations, options);
76
+ }
77
+ /** Propose active-scope evidence ceilings from the record without persisting them. */
78
+ export async function deriveAssuranceProposals(context, ownerItemId) {
79
+ const terminalStatuses = new Set(context.terminal_statuses ?? ["closed", "canceled"]);
80
+ const activeContext = {
81
+ ...context,
82
+ items: context.items.filter((item) => !terminalStatuses.has(item.status)),
83
+ };
84
+ const proposals = await Promise.all(["files", "tests", "docs"].map(async (link) => {
85
+ const measurement = {
86
+ id: `derived-active-missing-${link}`,
87
+ description: `Observed active items missing ${link} evidence.`,
88
+ source: { kind: "links", link, state: "missing" },
89
+ };
90
+ const measured = await evaluateMeasurement(measurement, activeContext);
91
+ const observed = measured.value;
92
+ const derivedAssertion = assertion(`${measurement.id}-ceiling`, measurement.id, ownerItemId, observed, "observe");
93
+ const id = `active-missing-${link}`;
94
+ return {
95
+ id,
96
+ population_size: activeContext.items.length,
97
+ scope: { kind: "active" },
98
+ observed,
99
+ declarations: {
100
+ measurements: [measurement],
101
+ assertions: [derivedAssertion],
102
+ gates: [
103
+ {
104
+ id: `derived-${id}`,
105
+ description: `Observe the accepted ${link} evidence baseline.`,
106
+ assertion_ids: [derivedAssertion.id],
107
+ triggers: ["ci", "scheduled"],
108
+ },
109
+ ],
110
+ },
111
+ };
112
+ }));
113
+ return proposals;
114
+ }
115
+ /** Accept all derived proposals in one audited registry transaction. */
116
+ export function acceptAssuranceProposals(pmRoot, proposals, options = {}) {
117
+ return putAssuranceDeclarationBundle(pmRoot, {
118
+ measurements: proposals.flatMap((proposal) => proposal.declarations.measurements),
119
+ assertions: proposals.flatMap((proposal) => proposal.declarations.assertions),
120
+ gates: proposals.flatMap((proposal) => proposal.declarations.gates),
121
+ }, options);
122
+ }
123
+ /** Promote one assertion by exactly one enforcement level and audit the transition. */
124
+ export async function promoteAssuranceAssertion(pmRoot, definition, enforcement, options = {}) {
125
+ const expected = definition.enforcement === "observe" ? "warn" : "block";
126
+ if (definition.enforcement === "block" || enforcement !== expected) {
127
+ throw new TypeError(`assurance assertion ${definition.id} promotion must be ${definition.enforcement} -> ${expected}`);
128
+ }
129
+ return putAssuranceDeclaration(pmRoot, "assertion", { ...definition, enforcement }, {
130
+ ...options,
131
+ message: options.message ??
132
+ `Promote assurance assertion ${definition.id} from ${definition.enforcement} to ${enforcement}`,
133
+ });
134
+ }
135
+ //# sourceMappingURL=assurance-presets.js.map
136
+ //# debugId=05c29627-6763-5aee-8579-71e563a98780
@@ -11,6 +11,10 @@ export interface CreateAssuranceWorkspaceContextOptions {
11
11
  resolve_tree?: boolean;
12
12
  /** Provider resolvers keyed by stable provider id. */
13
13
  providers?: Readonly<Record<string, AssuranceProviderResolver>>;
14
+ /** Capabilities for host-provided resolvers that are not extension registrations. */
15
+ provider_capabilities?: AssuranceEvaluationContext["provider_capabilities"];
16
+ /** Gate trigger supplied to extension provider resolvers. */
17
+ trigger?: string;
14
18
  }
15
19
  /**
16
20
  * Build an assurance context from authoritative workspace data and public SDK
@@ -5,15 +5,87 @@
5
5
  * and verdict semantics in the host-neutral assurance module.
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]="abb3946c-ec68-52af-8521-ae0389f31f54")}catch(e){}}();
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]="7c99dfd8-2fa4-56c4-8191-229701eab251")}catch(e){}}();
9
9
  import { execFile } from "node:child_process";
10
10
  import { promisify } from "node:util";
11
11
  import { runGraph } from "../graph/run.js";
12
12
  import { runHealth } from "./health.js";
13
13
  import { runValidate } from "./validate.js";
14
+ import { getActiveExtensionRegistrations, resolvePortableWorkspaceContext, } from "../../core/extensions/index.js";
15
+ import { resolveRegisteredAssuranceMeasurementProvider } from "../../core/extensions/runtime-registrations.js";
16
+ import { stableStringify } from "../../core/shared/serialization.js";
14
17
  import { getHistoryPath, listAllItemMetadata, readHistoryEntries, readSettings, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, } from "../runtime-primitives.js";
15
18
  const execFileAsync = promisify(execFile);
16
19
  const HISTORY_READ_CONCURRENCY = 16;
20
+ const DEFAULT_PROVIDER_TIMEOUT_MS = 30_000;
21
+ function assertProviderResult(provider, key, result) {
22
+ const keyDefinition = provider.keys[key];
23
+ const valueMatches = keyDefinition.value_type === "number"
24
+ ? typeof result.value === "number" && Number.isFinite(result.value)
25
+ : Array.isArray(result.value) &&
26
+ result.value.every((entry) => typeof entry === "string");
27
+ if (!valueMatches) {
28
+ throw new TypeError(`assurance provider ${provider.id} key ${key} returned the wrong value type`);
29
+ }
30
+ if (!Number.isInteger(result.population_size) ||
31
+ result.population_size < 0 ||
32
+ !Number.isFinite(result.cost) ||
33
+ result.cost < 0) {
34
+ throw new TypeError(`assurance provider ${provider.id} returned an invalid population or cost`);
35
+ }
36
+ return result;
37
+ }
38
+ function validateProviderParameters(provider, source) {
39
+ const keyDefinition = provider.keys[source.key];
40
+ if (!keyDefinition) {
41
+ throw new TypeError(`assurance provider ${provider.id} does not declare key ${source.key}`);
42
+ }
43
+ const parameters = source.parameters ?? {};
44
+ const schema = keyDefinition.parameters ?? {};
45
+ for (const required of Object.entries(schema)
46
+ .filter(([, definition]) => definition.required === true)
47
+ .map(([name]) => name)) {
48
+ if (!Object.hasOwn(parameters, required)) {
49
+ throw new TypeError(`assurance provider ${provider.id} key ${source.key} requires parameter ${required}`);
50
+ }
51
+ }
52
+ for (const [name, value] of Object.entries(parameters)) {
53
+ const definition = schema[name];
54
+ if (!definition) {
55
+ throw new TypeError(`assurance provider ${provider.id} key ${source.key} does not declare parameter ${name}`);
56
+ }
57
+ if (value === null || typeof value !== definition.type) {
58
+ throw new TypeError(`assurance provider ${provider.id} parameter ${name} must be ${definition.type}`);
59
+ }
60
+ }
61
+ return { ...parameters };
62
+ }
63
+ async function runRegisteredProvider(provider, source, pmRoot, trigger) {
64
+ const parameters = validateProviderParameters(provider, source);
65
+ const providerPromise = Promise.resolve().then(() => provider.resolve({
66
+ provider: provider.id,
67
+ key: source.key,
68
+ parameters,
69
+ trigger,
70
+ pm_root: pmRoot,
71
+ ...resolvePortableWorkspaceContext(pmRoot),
72
+ }));
73
+ providerPromise.catch(() => { });
74
+ let timeoutHandle;
75
+ try {
76
+ const result = await Promise.race([
77
+ providerPromise,
78
+ new Promise((_, reject) => {
79
+ timeoutHandle = setTimeout(() => reject(new TypeError(`assurance provider ${provider.id} timed out`)), provider.timeout_ms ?? DEFAULT_PROVIDER_TIMEOUT_MS);
80
+ timeoutHandle.unref?.();
81
+ }),
82
+ ]);
83
+ return assertProviderResult(provider, source.key, result);
84
+ }
85
+ finally {
86
+ clearTimeout(timeoutHandle);
87
+ }
88
+ }
17
89
  function valueAtPath(input, field) {
18
90
  let current = input;
19
91
  for (const segment of field.split(".")) {
@@ -96,6 +168,17 @@ export async function createAssuranceWorkspaceContext(pmRoot, options = {}) {
96
168
  type: item.type,
97
169
  }));
98
170
  const global = { path: pmRoot };
171
+ const activeRegistrations = getActiveExtensionRegistrations();
172
+ const registeredProviderCapabilities = Object.fromEntries((activeRegistrations?.assurance_providers ?? []).map((registration) => [
173
+ registration.definition.id,
174
+ {
175
+ cost_class: registration.runtime_definition.cost_class,
176
+ network: registration.runtime_definition.network,
177
+ },
178
+ ]));
179
+ const graphRuns = new Map();
180
+ let validateRun;
181
+ let healthRun;
99
182
  return {
100
183
  tree_id: options.resolve_tree === false
101
184
  ? (options.tree_id ?? "working-copy")
@@ -105,9 +188,22 @@ export async function createAssuranceWorkspaceContext(pmRoot, options = {}) {
105
188
  ? []
106
189
  : await readWorkspaceHistory(pmRoot, items),
107
190
  terminal_statuses: [...statusRegistry.terminal_statuses],
191
+ provider_capabilities: {
192
+ ...registeredProviderCapabilities,
193
+ ...options.provider_capabilities,
194
+ },
108
195
  external: async (source) => {
109
196
  if (source.kind === "graph") {
110
- const result = await runGraph(source.operation, undefined, undefined, { ...source.parameters, full: true }, global);
197
+ const key = stableStringify({
198
+ operation: source.operation,
199
+ parameters: source.parameters ?? {},
200
+ });
201
+ let pending = graphRuns.get(key);
202
+ if (pending === undefined) {
203
+ pending = runGraph(source.operation, undefined, undefined, { ...source.parameters, full: true }, global);
204
+ graphRuns.set(key, pending);
205
+ }
206
+ const result = await pending;
111
207
  return {
112
208
  value: valueAtPath(result, source.field),
113
209
  population_size: items.length,
@@ -115,20 +211,25 @@ export async function createAssuranceWorkspaceContext(pmRoot, options = {}) {
115
211
  };
116
212
  }
117
213
  if (source.kind === "validate") {
118
- const result = await runValidate({ counts: true }, global);
214
+ validateRun ??= runValidate({ counts: true }, global);
215
+ const result = await validateRun;
119
216
  return checkValue(result, source.check, source.field);
120
217
  }
121
218
  if (source.kind === "health") {
122
- const result = await runHealth(global, { checkOnly: true, full: true });
219
+ healthRun ??= runHealth(global, { checkOnly: true, full: true });
220
+ const result = await healthRun;
123
221
  return checkValue(result, source.check, source.field);
124
222
  }
125
- const provider = options.providers?.[source.provider];
126
- if (!provider) {
223
+ const hostProvider = options.providers?.[source.provider];
224
+ if (hostProvider)
225
+ return hostProvider(source);
226
+ const registeredProvider = resolveRegisteredAssuranceMeasurementProvider(activeRegistrations, source.provider);
227
+ if (!registeredProvider) {
127
228
  throw new TypeError(`assurance provider ${source.provider} is not registered`);
128
229
  }
129
- return provider(source);
230
+ return runRegisteredProvider(registeredProvider.runtime_definition, source, pmRoot, options.trigger ?? "sdk");
130
231
  },
131
232
  };
132
233
  }
133
234
  //# sourceMappingURL=assurance-runtime.js.map
134
- //# debugId=abb3946c-ec68-52af-8521-ae0389f31f54
235
+ //# debugId=7c99dfd8-2fa4-56c4-8191-229701eab251
@@ -6,6 +6,8 @@ export declare const ASSURANCE_GATE_TRIGGERS: readonly ["pre-commit", "pre-push"
6
6
  export type AssuranceGateTrigger = (typeof ASSURANCE_GATE_TRIGGERS)[number];
7
7
  /** Assertion enforcement strength. */
8
8
  export type AssuranceEnforcement = "block" | "warn" | "observe";
9
+ /** Provider execution classes ordered from cheapest to most expensive. */
10
+ export type AssuranceProviderCostClass = "low" | "medium" | "high";
9
11
  /** Assertion lifetime after its owning work item becomes terminal. */
10
12
  export type AssuranceLifetime = "hold" | "retire";
11
13
  /** Numeric or labelled-set value produced by a measurement. */
@@ -246,6 +248,18 @@ export interface AssuranceGateDefinition {
246
248
  triggers: AssuranceGateTrigger[];
247
249
  /** Optional description. */
248
250
  description?: string;
251
+ /** Explicit provider allow-list and trigger-specific execution policy. */
252
+ provider_policy?: {
253
+ /** Provider ids this gate may invoke. An empty set refuses every provider. */
254
+ allowed_providers: string[];
255
+ /** Trigger rules; an omitted rule refuses provider execution for that trigger. */
256
+ triggers: Partial<Record<AssuranceGateTrigger, {
257
+ /** Highest provider cost class allowed at this trigger. */
258
+ max_cost_class: AssuranceProviderCostClass;
259
+ /** Whether network-declaring providers may run. */
260
+ allow_network: boolean;
261
+ }>>;
262
+ };
249
263
  }
250
264
  /** Complete persisted assurance registry. */
251
265
  export interface AssuranceDocument {
@@ -258,6 +272,24 @@ export interface AssuranceDocument {
258
272
  /** Gate declarations. */
259
273
  gates: AssuranceGateDefinition[];
260
274
  }
275
+ /** Atomic set of ordinary declarations used by presets and accepted proposals. */
276
+ export interface AssuranceDeclarationBundle {
277
+ /** Measurement declarations to create without overwriting divergent ids. */
278
+ measurements: AssuranceMeasurementDefinition[];
279
+ /** Assertion declarations to create without overwriting divergent ids. */
280
+ assertions: AssuranceAssertionDefinition[];
281
+ /** Gate declarations to create without overwriting divergent ids. */
282
+ gates: AssuranceGateDefinition[];
283
+ }
284
+ /** Audited receipt for one atomic assurance bundle application. */
285
+ export interface AssuranceBundleMutationReceipt {
286
+ /** Whether persistence changed. */
287
+ changed: boolean;
288
+ /** Stable ids created by the bundle. */
289
+ created_ids: string[];
290
+ /** Stable ids already present with byte-equivalent declarations. */
291
+ unchanged_ids: string[];
292
+ }
261
293
  /** Host adapter result for graph, validate, health, or provider sources. */
262
294
  export interface AssuranceExternalMeasurementResult {
263
295
  /** Observed value. */
@@ -279,6 +311,11 @@ export interface AssuranceEvaluationContext {
279
311
  history: AssuranceHistoryRecord[];
280
312
  /** Status ids that make an assertion owner terminal. */
281
313
  terminal_statuses?: string[];
314
+ /** Host-declared capabilities for provider-policy enforcement. */
315
+ provider_capabilities?: Readonly<Record<string, {
316
+ cost_class: AssuranceProviderCostClass;
317
+ network: boolean;
318
+ }>>;
282
319
  /** External source adapter. Implementations must enforce an appropriate timeout. */
283
320
  external: (source: AssuranceGraphSource | AssuranceValidateSource | AssuranceHealthSource | AssuranceProviderSource) => Promise<AssuranceExternalMeasurementResult>;
284
321
  }
@@ -427,6 +464,8 @@ export declare function listAssuranceDeclarations(pmRoot: string, kind: Assuranc
427
464
  export declare function getAssuranceDeclaration(pmRoot: string, kind: AssuranceDeclarationKind, id: string): Promise<AssuranceDeclaration>;
428
465
  /** Create or update one declaration through audited singleton persistence. */
429
466
  export declare function putAssuranceDeclaration(pmRoot: string, kind: AssuranceDeclarationKind, definition: AssuranceDeclaration, options?: AssuranceMutationOptions): Promise<AssuranceMutationReceipt>;
467
+ /** Apply a declaration bundle atomically, idempotently, and without replacing divergent ids. */
468
+ export declare function putAssuranceDeclarationBundle(pmRoot: string, bundle: AssuranceDeclarationBundle, options?: AssuranceMutationOptions): Promise<AssuranceBundleMutationReceipt>;
430
469
  /** Remove an unreferenced declaration through audited singleton persistence. */
431
470
  export declare function removeAssuranceDeclaration(pmRoot: string, kind: AssuranceDeclarationKind, id: string, options?: AssuranceMutationOptions): Promise<AssuranceMutationReceipt>;
432
471
  /** Append one immutable gate verdict without changing registry state. */
@@ -7,7 +7,7 @@
7
7
  * one deterministic SDK path.
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]="ecc8eb89-b9e9-51fa-8573-2afb8ec801be")}catch(e){}}();
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]="07889857-2176-5659-96f7-8f5591f4c692")}catch(e){}}();
11
11
  import { createHash } from "node:crypto";
12
12
  import path from "node:path";
13
13
  import { EXIT_CODE } from "../../core/shared/constants.js";
@@ -15,7 +15,7 @@ import { PmCliError } from "../../core/shared/errors.js";
15
15
  import { appendWorkspaceAuditEvent, mutateWorkspaceJsonWithHistory, readFileIfExists, readHistoryEntries, readSettings, resolveAuthor, stableStringify, WORKSPACE_HISTORY_ID, getWorkspaceHistoryPath, } from "../runtime-primitives.js";
16
16
  import { resolveCanonicalRelationshipKind } from "../relationships.js";
17
17
  import { MAX_ASSURANCE_VERDICT_LIMIT } from "./assurance-limits.js";
18
- import { AssuranceMutationRefusalError } from "./assurance-mutation-error.js";
18
+ import { AssuranceEvaluationRefusalError, AssuranceMutationRefusalError, } from "./assurance-mutation-error.js";
19
19
  /** Current serialized assurance registry format. */
20
20
  export const ASSURANCE_DOCUMENT_VERSION = 1;
21
21
  /** Supported lifecycle points that can evaluate a gate. */
@@ -213,6 +213,30 @@ export function validateAssertionDefinition(definition) {
213
213
  }
214
214
  return definition;
215
215
  }
216
+ function validateGateProviderPolicy(policy) {
217
+ if (!Array.isArray(policy.allowed_providers)) {
218
+ throw new AssuranceMutationRefusalError("gate provider_policy.allowed_providers must be an array");
219
+ }
220
+ for (const provider of policy.allowed_providers) {
221
+ requireStableId(provider, "gate.provider_policy.allowed_provider");
222
+ }
223
+ if (typeof policy.triggers !== "object" ||
224
+ policy.triggers === null ||
225
+ Array.isArray(policy.triggers)) {
226
+ throw new AssuranceMutationRefusalError("gate provider_policy.triggers must be an object");
227
+ }
228
+ for (const [trigger, rule] of Object.entries(policy.triggers)) {
229
+ if (!ASSURANCE_GATE_TRIGGERS.includes(trigger)) {
230
+ throw new AssuranceMutationRefusalError(`gate provider policy has unknown trigger ${trigger}`);
231
+ }
232
+ if (typeof rule !== "object" ||
233
+ rule === null ||
234
+ !["low", "medium", "high"].includes(rule.max_cost_class) ||
235
+ typeof rule.allow_network !== "boolean") {
236
+ throw new AssuranceMutationRefusalError(`gate provider policy trigger ${trigger} is invalid`);
237
+ }
238
+ }
239
+ }
216
240
  /** Validate and return one gate declaration. */
217
241
  export function validateGateDefinition(definition) {
218
242
  requireStableId(definition.id, "gate.id");
@@ -224,6 +248,9 @@ export function validateGateDefinition(definition) {
224
248
  if (definition.triggers.length === 0) {
225
249
  throw new AssuranceMutationRefusalError("gate requires at least one trigger");
226
250
  }
251
+ if (definition.provider_policy) {
252
+ validateGateProviderPolicy(definition.provider_policy);
253
+ }
227
254
  return definition;
228
255
  }
229
256
  /** Validate registry references, uniqueness, and declaration-local contracts. */
@@ -300,6 +327,33 @@ function collectMeasurementReferences(document) {
300
327
  }
301
328
  return references;
302
329
  }
330
+ function collectGateProviderIds(gate, document) {
331
+ const pending = gate.assertion_ids.flatMap((assertionId) => {
332
+ const assertion = document.assertions.find((entry) => entry.id === assertionId);
333
+ return [
334
+ assertion.measurement_id,
335
+ ...(assertion.scope.kind === "filter"
336
+ ? [assertion.scope.measurement_id]
337
+ : []),
338
+ ];
339
+ });
340
+ const visited = new Set();
341
+ const providers = new Set();
342
+ while (pending.length > 0) {
343
+ const measurementId = pending.pop();
344
+ if (visited.has(measurementId))
345
+ continue;
346
+ visited.add(measurementId);
347
+ const measurement = document.measurements.find((entry) => entry.id === measurementId);
348
+ if (measurement.source.kind === "provider") {
349
+ providers.add(measurement.source.provider);
350
+ }
351
+ else if (measurement.source.kind === "derived") {
352
+ collectExpressionMeasurementReferences(measurement.source.expression, pending);
353
+ }
354
+ }
355
+ return providers;
356
+ }
303
357
  /** Create an empty, valid assurance registry. */
304
358
  export function createEmptyAssuranceDocument() {
305
359
  return {
@@ -513,7 +567,7 @@ async function evaluateMeasurementInternal(definition, context, definitions, sta
513
567
  };
514
568
  const cost = sumCosts([...nestedCosts, ownCost], Date.now() - startedAt);
515
569
  if (definition.max_cost !== undefined && cost.units > definition.max_cost) {
516
- throw new TypeError(`measurement ${definition.id} exceeded cost ceiling ${definition.max_cost} with ${cost.units}`);
570
+ throw new AssuranceEvaluationRefusalError(`measurement ${definition.id} exceeded cost ceiling ${definition.max_cost} with ${cost.units}`);
517
571
  }
518
572
  return {
519
573
  id: definition.id,
@@ -579,15 +633,47 @@ export function evaluateAssuranceAssertion(definition, measurement, options = {}
579
633
  contributors: measurement.contributors,
580
634
  };
581
635
  }
636
+ function enforceGateProviderPolicy(gate, document, context, trigger) {
637
+ const providerIds = collectGateProviderIds(gate, document);
638
+ if (providerIds.size === 0)
639
+ return;
640
+ const policy = gate.provider_policy;
641
+ const triggerPolicy = policy?.triggers[trigger];
642
+ if (!policy || !triggerPolicy) {
643
+ throw new AssuranceEvaluationRefusalError(`assurance gate ${gate.id} refuses provider execution at trigger ${trigger} without an explicit provider policy`);
644
+ }
645
+ const allowedProviders = new Set(policy.allowed_providers);
646
+ const costRank = {
647
+ low: 0,
648
+ medium: 1,
649
+ high: 2,
650
+ };
651
+ for (const providerId of providerIds) {
652
+ if (!allowedProviders.has(providerId)) {
653
+ throw new AssuranceEvaluationRefusalError(`assurance gate ${gate.id} refuses provider ${providerId}`);
654
+ }
655
+ const capability = context.provider_capabilities?.[providerId];
656
+ if (!capability) {
657
+ throw new AssuranceEvaluationRefusalError(`assurance provider ${providerId} has no declared capabilities`);
658
+ }
659
+ if (costRank[capability.cost_class] > costRank[triggerPolicy.max_cost_class]) {
660
+ throw new AssuranceEvaluationRefusalError(`assurance gate ${gate.id} refuses ${capability.cost_class}-cost provider ${providerId} at trigger ${trigger}`);
661
+ }
662
+ if (capability.network && !triggerPolicy.allow_network) {
663
+ throw new AssuranceEvaluationRefusalError(`assurance gate ${gate.id} refuses network provider ${providerId} at trigger ${trigger}`);
664
+ }
665
+ }
666
+ }
582
667
  /** Evaluate a named gate into one presentation-independent verdict document. */
583
668
  export async function evaluateAssuranceGate(gateId, document, context, options) {
584
669
  validateAssuranceDocument(document);
585
670
  const gateDefinition = document.gates.find((entry) => entry.id === gateId);
586
671
  if (!gateDefinition)
587
- throw new TypeError(`assurance gate ${gateId} not found`);
672
+ throw new AssuranceEvaluationRefusalError(`assurance gate ${gateId} not found`);
588
673
  if (!gateDefinition.triggers.includes(options.trigger)) {
589
- throw new TypeError(`assurance gate ${gateId} does not declare trigger ${options.trigger}`);
674
+ throw new AssuranceEvaluationRefusalError(`assurance gate ${gateId} does not declare trigger ${options.trigger}`);
590
675
  }
676
+ enforceGateProviderPolicy(gateDefinition, document, context, options.trigger);
591
677
  const assertions = await mapWithConcurrency(gateDefinition.assertion_ids, EVALUATION_CONCURRENCY, async (id) => {
592
678
  const assertionDefinition = document.assertions.find((entry) => entry.id === id);
593
679
  const measurementDefinition = document.measurements.find((entry) => entry.id === assertionDefinition.measurement_id);
@@ -726,6 +812,59 @@ export async function putAssuranceDeclaration(pmRoot, kind, definition, options
726
812
  });
727
813
  return { ...mutation.result, changed: mutation.changed };
728
814
  }
815
+ /** Apply a declaration bundle atomically, idempotently, and without replacing divergent ids. */
816
+ export async function putAssuranceDeclarationBundle(pmRoot, bundle, options = {}) {
817
+ const candidate = createEmptyAssuranceDocument();
818
+ candidate.measurements = structuredClone(bundle.measurements);
819
+ candidate.assertions = structuredClone(bundle.assertions);
820
+ candidate.gates = structuredClone(bundle.gates);
821
+ validateAssuranceDocument(candidate);
822
+ const settings = await readSettings(pmRoot);
823
+ const author = resolveAuthor(options.author, settings.author_default);
824
+ const mutation = await mutateWorkspaceJsonWithHistory({
825
+ pmRoot,
826
+ filePath: assurancePath(pmRoot),
827
+ op: "assurance:bundle:apply",
828
+ author,
829
+ message: options.message,
830
+ lockTtlSeconds: LOCK_TTL_SECONDS,
831
+ lockWaitMs: LOCK_WAIT_MS,
832
+ mutate: (beforeRaw) => {
833
+ const document = beforeRaw === null
834
+ ? createEmptyAssuranceDocument()
835
+ : parseAssuranceDocument(beforeRaw);
836
+ const createdIds = [];
837
+ const unchangedIds = [];
838
+ const apply = (target, additions, kind) => {
839
+ for (const definition of additions) {
840
+ const existing = target.find((entry) => entry.id === definition.id);
841
+ if (!existing) {
842
+ target.push(structuredClone(definition));
843
+ createdIds.push(`${kind}:${definition.id}`);
844
+ continue;
845
+ }
846
+ if (stableStringify(existing) !== stableStringify(definition)) {
847
+ throw new AssuranceMutationRefusalError(`assurance bundle refuses to replace divergent ${kind} ${definition.id}`);
848
+ }
849
+ unchangedIds.push(`${kind}:${definition.id}`);
850
+ }
851
+ };
852
+ apply(document.measurements, candidate.measurements, "measurement");
853
+ apply(document.assertions, candidate.assertions, "assertion");
854
+ apply(document.gates, candidate.gates, "gate");
855
+ validateAssuranceDocument(document);
856
+ return {
857
+ raw: `${JSON.stringify(document, null, 2)}\n`,
858
+ result: {
859
+ changed: createdIds.length > 0,
860
+ created_ids: createdIds,
861
+ unchanged_ids: unchangedIds,
862
+ },
863
+ };
864
+ },
865
+ });
866
+ return { ...mutation.result, changed: mutation.changed };
867
+ }
729
868
  /** Remove an unreferenced declaration through audited singleton persistence. */
730
869
  export async function removeAssuranceDeclaration(pmRoot, kind, id, options = {}) {
731
870
  const settings = await readSettings(pmRoot);
@@ -801,4 +940,4 @@ export async function listAssuranceVerdicts(pmRoot, options = {}) {
801
940
  .slice(0, limit);
802
941
  }
803
942
  //# sourceMappingURL=assurance.js.map
804
- //# debugId=ecc8eb89-b9e9-51fa-8573-2afb8ec801be
943
+ //# debugId=07889857-2176-5659-96f7-8f5591f4c692
@@ -4,13 +4,13 @@
4
4
  * Implements the pm gc 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]="0973a87f-2b63-5fa1-9624-82897d181f71")}catch(e){}}();
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]="e982158e-4a8d-57a9-bd0b-24bd73aef342")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import { runCheckpointGc } from "../../core/checkpoint/checkpoint-gc.js";
11
11
  import { runWorkspaceTransactionGc } from "../workspace-transaction-gc.js";
12
12
  import { runActiveOnIndexHooks, runActiveOnReadHooks, runActiveOnWriteHooks, } 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 { runLockGc } from "../../core/lock/lock-gc.js";
15
15
  import { EXIT_CODE } from "../../core/shared/constants.js";
16
16
  import { PmCliError } from "../../core/shared/errors.js";
@@ -73,12 +73,6 @@ const GC_TARGETS = [
73
73
  kind: "file",
74
74
  },
75
75
  ];
76
- function isErrno(error, code) {
77
- return (typeof error === "object" &&
78
- error !== null &&
79
- "code" in error &&
80
- error.code === code);
81
- }
82
76
  async function removeCacheFile(pmRoot, target, dryRun) {
83
77
  const relativePath = target.relativePath;
84
78
  const absolutePath = path.join(pmRoot, relativePath);
@@ -123,7 +117,7 @@ async function removeCacheFile(pmRoot, target, dryRun) {
123
117
  };
124
118
  }
125
119
  catch (error) {
126
- if (isErrno(error, "ENOENT")) {
120
+ if (isFileMissingError(error)) {
127
121
  return {
128
122
  removed: false,
129
123
  warnings,
@@ -163,7 +157,7 @@ async function sweepWorkspaceSnapshotTemps(pmRoot, dryRun) {
163
157
  scope: "project",
164
158
  })));
165
159
  const stats = await fs.stat(absolutePath).catch((error) => {
166
- if (isErrno(error, "ENOENT")) {
160
+ if (isFileMissingError(error)) {
167
161
  return undefined;
168
162
  }
169
163
  throw error;
@@ -373,4 +367,4 @@ export async function runGc(global, options = {}) {
373
367
  };
374
368
  }
375
369
  //# sourceMappingURL=gc.js.map
376
- //# debugId=0973a87f-2b63-5fa1-9624-82897d181f71
370
+ //# debugId=e982158e-4a8d-57a9-bd0b-24bd73aef342