@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
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Implements the pm health 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]="5cee1eaa-73f3-5709-867f-a8d73081da8b")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
11
|
-
import { pathExists, readFileIfExists } from "../../core/fs/fs-utils.js";
|
|
11
|
+
import { isFileMissingError, pathExists, readFileIfExists } from "../../core/fs/fs-utils.js";
|
|
12
12
|
import { activateExtensions, getActiveExtensionRegistrations, loadExtensions, runActiveOnReadHooks, } from "../../core/extensions/index.js";
|
|
13
13
|
import { collectRegisteredItemFieldNames } from "../../core/extensions/item-fields.js";
|
|
14
14
|
import { KNOWN_EXTENSION_CAPABILITIES, } from "../../core/extensions/loader.js";
|
|
@@ -207,7 +207,7 @@ async function listItemDocumentPaths(pmRoot, typeToFolder) {
|
|
|
207
207
|
if (typeof error === "object" &&
|
|
208
208
|
error !== null &&
|
|
209
209
|
"code" in error &&
|
|
210
|
-
error
|
|
210
|
+
isFileMissingError(error)) {
|
|
211
211
|
continue;
|
|
212
212
|
}
|
|
213
213
|
continue;
|
|
@@ -226,7 +226,7 @@ function shouldReportHistoryDirectoryUnreadable(error) {
|
|
|
226
226
|
return !(typeof error === "object" &&
|
|
227
227
|
error !== null &&
|
|
228
228
|
"code" in error &&
|
|
229
|
-
error
|
|
229
|
+
isFileMissingError(error));
|
|
230
230
|
}
|
|
231
231
|
async function scanItemIntegrity(pmRoot, typeToFolder, schema) {
|
|
232
232
|
const paths = await listItemDocumentPaths(pmRoot, typeToFolder);
|
|
@@ -2007,4 +2007,4 @@ export const _testOnlyHealthCommand = {
|
|
|
2007
2007
|
warningCode,
|
|
2008
2008
|
};
|
|
2009
2009
|
//# sourceMappingURL=health.js.map
|
|
2010
|
-
//# debugId=
|
|
2010
|
+
//# debugId=5cee1eaa-73f3-5709-867f-a8d73081da8b
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Implements the pm validate 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]="7dd04a2f-1798-5c16-8740-5b7094f81cc0")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import { realpathSync } from "node:fs";
|
|
10
10
|
import { execFile } from "node:child_process";
|
|
@@ -13,7 +13,7 @@ import { promisify } from "node:util";
|
|
|
13
13
|
import { buildRemediationCommands } from "../../core/diagnostics/remediation.js";
|
|
14
14
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
15
15
|
import { collectRegisteredItemFieldNames } from "../../core/extensions/item-fields.js";
|
|
16
|
-
import { pathExists } from "../../core/fs/fs-utils.js";
|
|
16
|
+
import { isFileMissingError, pathExists } from "../../core/fs/fs-utils.js";
|
|
17
17
|
import { scanHistoryDrift } from "../../core/history/drift-scan.js";
|
|
18
18
|
import { normalizeStatusInput } from "../../core/item/status.js";
|
|
19
19
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
@@ -475,7 +475,7 @@ async function listFilesRecursive(basePath, relativePath, output) {
|
|
|
475
475
|
entries = await fs.readdir(targetDirectory, { withFileTypes: true });
|
|
476
476
|
}
|
|
477
477
|
catch (error) {
|
|
478
|
-
if (
|
|
478
|
+
if (isFileMissingError(error)) {
|
|
479
479
|
return;
|
|
480
480
|
}
|
|
481
481
|
throw error;
|
|
@@ -2356,4 +2356,4 @@ export async function runValidate(options, global, services = {}) {
|
|
|
2356
2356
|
}
|
|
2357
2357
|
/* c8 ignore stop */
|
|
2358
2358
|
//# sourceMappingURL=validate.js.map
|
|
2359
|
-
//# debugId=
|
|
2359
|
+
//# debugId=7dd04a2f-1798-5c16-8740-5b7094f81cc0
|
|
@@ -15,11 +15,12 @@
|
|
|
15
15
|
* threshold or after an explicit `pm graph index --rebuild` opt-in.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
!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]="
|
|
18
|
+
!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]="2f7f14e3-6d41-5f45-a560-ebfbb8aa5828")}catch(e){}}();
|
|
19
19
|
import path from "node:path";
|
|
20
20
|
import { readFileIfExists, removeFileIfExists, writeFileAtomic, } from "../../core/fs/fs-utils.js";
|
|
21
21
|
import { acquireLock } from "../../core/lock/lock.js";
|
|
22
22
|
import { isSemanticContextKind, } from "./governance.js";
|
|
23
|
+
import { RELATIONSHIP_AUDIT_FINDING_CODES } from "./governance-contracts.js";
|
|
23
24
|
/** Envelope format version; any change invalidates persisted entries. */
|
|
24
25
|
export const GRAPH_DURABLE_CACHE_VERSION = 1;
|
|
25
26
|
/** Workspaces below this item count skip implicit persistence. */
|
|
@@ -173,6 +174,58 @@ function isNonnegativeCoverageByTypeRecord(value) {
|
|
|
173
174
|
return Object.values(value).every((entry) => isRecord(entry) &&
|
|
174
175
|
[entry.active, entry.isolated, entry.degree_leq_one].every(isNonnegativeInteger));
|
|
175
176
|
}
|
|
177
|
+
/** Decode optional structural fields while normalizing pre-structure baselines. */
|
|
178
|
+
function decodeStructuralProfile(profile, affectedSubjectsByCode) {
|
|
179
|
+
const countFields = [
|
|
180
|
+
"articulation_points",
|
|
181
|
+
"bridge_edges",
|
|
182
|
+
"outcome_nodes",
|
|
183
|
+
"active_outcome_reachable_nodes",
|
|
184
|
+
"active_outcome_unreachable_nodes",
|
|
185
|
+
"terminal_nodes",
|
|
186
|
+
"terminal_outcome_reachable_nodes",
|
|
187
|
+
"terminal_outcome_unreachable_nodes",
|
|
188
|
+
"outcome_reachable_nodes",
|
|
189
|
+
"outcome_unreachable_nodes",
|
|
190
|
+
];
|
|
191
|
+
const rateFields = [
|
|
192
|
+
"active_outcome_reachability_basis_points",
|
|
193
|
+
"terminal_outcome_reachability_basis_points",
|
|
194
|
+
"outcome_reachability_basis_points",
|
|
195
|
+
];
|
|
196
|
+
const introducedStructuralFields = [
|
|
197
|
+
...countFields,
|
|
198
|
+
...rateFields,
|
|
199
|
+
"finding_subjects_by_code",
|
|
200
|
+
];
|
|
201
|
+
const introducedStructuralFieldCount = introducedStructuralFields.filter((field) => profile[field] !== undefined).length;
|
|
202
|
+
if (introducedStructuralFieldCount !== 0 &&
|
|
203
|
+
introducedStructuralFieldCount !== introducedStructuralFields.length) {
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
const validCounts = countFields.every((field) => profile[field] === undefined || isNonnegativeInteger(profile[field]));
|
|
207
|
+
const validRates = rateFields.every((field) => profile[field] === undefined ||
|
|
208
|
+
(isNonnegativeInteger(profile[field]) && Number(profile[field]) <= 10_000));
|
|
209
|
+
if (!validCounts || !validRates)
|
|
210
|
+
return undefined;
|
|
211
|
+
if (profile.edge_basis !== undefined &&
|
|
212
|
+
profile.edge_basis !== "deduplicated_directed")
|
|
213
|
+
return undefined;
|
|
214
|
+
if (!isOptionalValid(profile.finding_subjects_by_code, isNonnegativeCountRecord))
|
|
215
|
+
return undefined;
|
|
216
|
+
const findingSubjects = isNonnegativeCountRecord(profile.finding_subjects_by_code)
|
|
217
|
+
? profile.finding_subjects_by_code
|
|
218
|
+
: {};
|
|
219
|
+
return {
|
|
220
|
+
edge_basis: "deduplicated_directed",
|
|
221
|
+
...Object.fromEntries(countFields.map((field) => [field, profile[field] ?? 0])),
|
|
222
|
+
...Object.fromEntries(rateFields.map((field) => [field, profile[field] ?? 0])),
|
|
223
|
+
finding_subjects_by_code: Object.fromEntries(RELATIONSHIP_AUDIT_FINDING_CODES.map((code) => [
|
|
224
|
+
code,
|
|
225
|
+
findingSubjects[code] ?? affectedSubjectsByCode[code] ?? 0,
|
|
226
|
+
])),
|
|
227
|
+
};
|
|
228
|
+
}
|
|
176
229
|
/** Decode and cross-check optional graph-composition fields as one coherent unit. */
|
|
177
230
|
function decodeGraphComposition(edges, edgesByKind, edgeShareByKind, semanticEdgesValue, semanticEdgeShareValue) {
|
|
178
231
|
const values = [
|
|
@@ -225,7 +278,8 @@ function decodeBaseline(raw) {
|
|
|
225
278
|
return undefined;
|
|
226
279
|
if (typeof snapshot.fingerprint !== "string")
|
|
227
280
|
return undefined;
|
|
228
|
-
|
|
281
|
+
const affectedSubjectsByCode = snapshot.affected_subjects_by_code;
|
|
282
|
+
if (!isNonnegativeCountRecord(affectedSubjectsByCode)) {
|
|
229
283
|
return undefined;
|
|
230
284
|
}
|
|
231
285
|
if (!isRecord(profile))
|
|
@@ -248,12 +302,16 @@ function decodeBaseline(raw) {
|
|
|
248
302
|
const composition = decodeGraphComposition(profile.edges, profile.edges_by_kind, profile.edge_share_by_kind, profile.semantic_edges, profile.semantic_edge_share);
|
|
249
303
|
if (composition === undefined)
|
|
250
304
|
return undefined;
|
|
305
|
+
const structural = decodeStructuralProfile(profile, affectedSubjectsByCode);
|
|
306
|
+
if (structural === undefined)
|
|
307
|
+
return undefined;
|
|
251
308
|
const { coverage_by_type = {} } = profile;
|
|
252
309
|
return {
|
|
253
310
|
...snapshot,
|
|
254
311
|
profile: {
|
|
255
312
|
...profile,
|
|
256
313
|
...composition,
|
|
314
|
+
...structural,
|
|
257
315
|
coverage_by_type,
|
|
258
316
|
},
|
|
259
317
|
};
|
|
@@ -271,4 +329,4 @@ export async function saveGraphAuditBaseline(pmRoot, snapshot) {
|
|
|
271
329
|
await writeFileAtomic(graphAuditBaselinePath(pmRoot), JSON.stringify(snapshot));
|
|
272
330
|
}
|
|
273
331
|
//# sourceMappingURL=durable-cache.js.map
|
|
274
|
-
//# debugId=
|
|
332
|
+
//# debugId=2f7f14e3-6d41-5f45-a560-ebfbb8aa5828
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/graph/governance-contracts
|
|
3
|
+
*
|
|
4
|
+
* Shared, runtime-visible relationship-audit finding identifiers used by the
|
|
5
|
+
* live audit and backward-compatible durable baseline decoder. Keeping the
|
|
6
|
+
* tuple authoritative prevents the public type and persisted zero census from
|
|
7
|
+
* drifting when a finding family is added.
|
|
8
|
+
*/
|
|
9
|
+
/** Stable machine-readable relationship audit finding families. */
|
|
10
|
+
export declare const RELATIONSHIP_AUDIT_FINDING_CODES: readonly ["missing_reference_active", "missing_reference_terminal", "legacy_no_blocker_sentinel", "ordering_cycle", "legacy_ordering_cycle", "duplicate_edge", "legacy_duplicate_edge", "duplicate_dependency_row", "legacy_duplicate_dependency_row", "stale_lifecycle_block", "isolated_active_node", "sparse_active_node"];
|
|
11
|
+
/** Machine-readable identifier for one relationship audit finding family. */
|
|
12
|
+
export type RelationshipAuditFindingCode = (typeof RELATIONSHIP_AUDIT_FINDING_CODES)[number];
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/graph/governance-contracts
|
|
3
|
+
*
|
|
4
|
+
* Shared, runtime-visible relationship-audit finding identifiers used by the
|
|
5
|
+
* live audit and backward-compatible durable baseline decoder. Keeping the
|
|
6
|
+
* tuple authoritative prevents the public type and persisted zero census from
|
|
7
|
+
* drifting when a finding family is added.
|
|
8
|
+
*/
|
|
9
|
+
/** Stable machine-readable relationship audit finding families. */
|
|
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]="a2043b27-3dfe-5da8-a10f-d92ff33f3c28")}catch(e){}}();
|
|
12
|
+
export const RELATIONSHIP_AUDIT_FINDING_CODES = [
|
|
13
|
+
"missing_reference_active",
|
|
14
|
+
"missing_reference_terminal",
|
|
15
|
+
"legacy_no_blocker_sentinel",
|
|
16
|
+
"ordering_cycle",
|
|
17
|
+
"legacy_ordering_cycle",
|
|
18
|
+
"duplicate_edge",
|
|
19
|
+
"legacy_duplicate_edge",
|
|
20
|
+
"duplicate_dependency_row",
|
|
21
|
+
"legacy_duplicate_dependency_row",
|
|
22
|
+
"stale_lifecycle_block",
|
|
23
|
+
"isolated_active_node",
|
|
24
|
+
"sparse_active_node",
|
|
25
|
+
];
|
|
26
|
+
//# sourceMappingURL=governance-contracts.js.map
|
|
27
|
+
//# debugId=a2043b27-3dfe-5da8-a10f-d92ff33f3c28
|
|
@@ -14,10 +14,10 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import type { RelationshipEdge } from "../relationships.js";
|
|
16
16
|
import type { WorkspaceRelationshipAssembly } from "./assembly.js";
|
|
17
|
+
import { type RelationshipAuditFindingCode } from "./governance-contracts.js";
|
|
18
|
+
export type { RelationshipAuditFindingCode } from "./governance-contracts.js";
|
|
17
19
|
/** Severity ladder shared by every relationship audit finding. */
|
|
18
20
|
export type RelationshipAuditSeverity = "error" | "warning" | "info";
|
|
19
|
-
/** Machine-readable identifier for one relationship audit finding family. */
|
|
20
|
-
export type RelationshipAuditFindingCode = "missing_reference_active" | "missing_reference_terminal" | "legacy_no_blocker_sentinel" | "ordering_cycle" | "legacy_ordering_cycle" | "duplicate_edge" | "legacy_duplicate_edge" | "duplicate_dependency_row" | "legacy_duplicate_dependency_row" | "stale_lifecycle_block" | "isolated_active_node" | "sparse_active_node";
|
|
21
21
|
/** One policy-aware relationship audit finding with bounded evidence. */
|
|
22
22
|
export interface RelationshipAuditFinding {
|
|
23
23
|
/** Machine-readable finding family identifier. */
|
|
@@ -72,6 +72,34 @@ export interface RelationshipCoverageProfile {
|
|
|
72
72
|
degree_leq_one_active_nodes: number;
|
|
73
73
|
/** Deterministic per-type connectivity coverage; untyped nodes bucket under `(untyped)`. */
|
|
74
74
|
coverage_by_type: Record<string, RelationshipCoverageTypeProfile>;
|
|
75
|
+
/** Undirected cut vertices whose removal increases the component count. */
|
|
76
|
+
articulation_points: number;
|
|
77
|
+
/** Undirected cut edges whose removal disconnects their endpoints. */
|
|
78
|
+
bridge_edges: number;
|
|
79
|
+
/** Milestone nodes whose title explicitly declares an outcome. */
|
|
80
|
+
outcome_nodes: number;
|
|
81
|
+
/** Active non-outcome nodes with a typed hierarchy or implements path to an outcome. */
|
|
82
|
+
active_outcome_reachable_nodes: number;
|
|
83
|
+
/** Active non-outcome nodes without a typed hierarchy or implements path to an outcome. */
|
|
84
|
+
active_outcome_unreachable_nodes: number;
|
|
85
|
+
/** Active typed-outcome reachability expressed as integer basis points. */
|
|
86
|
+
active_outcome_reachability_basis_points: number;
|
|
87
|
+
/** Terminal non-placeholder, non-outcome nodes included in the all-status census. */
|
|
88
|
+
terminal_nodes: number;
|
|
89
|
+
/** Terminal non-outcome nodes with a typed hierarchy or implements path to an outcome. */
|
|
90
|
+
terminal_outcome_reachable_nodes: number;
|
|
91
|
+
/** Terminal non-outcome nodes without a typed hierarchy or implements path to an outcome. */
|
|
92
|
+
terminal_outcome_unreachable_nodes: number;
|
|
93
|
+
/** Terminal typed-outcome reachability expressed as integer basis points. */
|
|
94
|
+
terminal_outcome_reachability_basis_points: number;
|
|
95
|
+
/** All active and terminal non-outcome nodes with a typed path to an outcome. */
|
|
96
|
+
outcome_reachable_nodes: number;
|
|
97
|
+
/** All active and terminal non-outcome nodes without a typed path to an outcome. */
|
|
98
|
+
outcome_unreachable_nodes: number;
|
|
99
|
+
/** All-status typed-outcome reachability expressed as integer basis points. */
|
|
100
|
+
outcome_reachability_basis_points: number;
|
|
101
|
+
/** Affected-subject census containing every known finding code, including zero populations. */
|
|
102
|
+
finding_subjects_by_code: Record<RelationshipAuditFindingCode, number>;
|
|
75
103
|
}
|
|
76
104
|
/** Tuning and policy inputs accepted by the relationship audit. */
|
|
77
105
|
export interface RelationshipAuditOptions {
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ab8a4904-0302-5e36-9963-750b3ba79876")}catch(e){}}();
|
|
3
3
|
import { isTransitiveKind, orientTransitiveEdge, transitiveFamilyKey, } from "./analytics.js";
|
|
4
|
+
import { findRelationshipCutStructure } from "./centrality.js";
|
|
5
|
+
import { RELATIONSHIP_AUDIT_FINDING_CODES, } from "./governance-contracts.js";
|
|
4
6
|
/** Default bounded sample size applied to every finding family. */
|
|
5
7
|
const DEFAULT_MAX_SAMPLE_SIZE = 25;
|
|
8
|
+
/** Canonical item type and title marker that identify explicit outcomes. */
|
|
9
|
+
const OUTCOME_MILESTONE_TYPE = "milestone";
|
|
10
|
+
const OUTCOME_MILESTONE_TITLE_PREFIX = "outcome milestone:";
|
|
6
11
|
/** Relationship kinds that preserve why work exists or how evidence supports it. */
|
|
7
12
|
const SEMANTIC_CONTEXT_KINDS = new Set([
|
|
8
13
|
"discovered_from",
|
|
@@ -290,6 +295,104 @@ function collectDuplicateRowFindings(assembly, maxSampleSize) {
|
|
|
290
295
|
appendFinding(findings, legacy, maxSampleSize, "legacy_duplicate_dependency_row", "info", "Identical repeated dependency rows on terminal holders are historical storage noise with no scheduling effect.", (count) => `${count} exactly duplicated stored dependency row(s) on terminal holder(s)`, "Leave as history debt or clean up in a dedicated changelog-safe closed-item batch.");
|
|
291
296
|
return findings;
|
|
292
297
|
}
|
|
298
|
+
/** Build the reverse typed paths that can carry context toward an outcome. */
|
|
299
|
+
function buildOutcomeReverseIndex(assembly, signal) {
|
|
300
|
+
const reverse = new Map();
|
|
301
|
+
for (const edge of assembly.graph.edges()) {
|
|
302
|
+
signal?.throwIfAborted();
|
|
303
|
+
const definition = assembly.graph.registry().require(edge.kind);
|
|
304
|
+
let oriented;
|
|
305
|
+
if (definition.hierarchy) {
|
|
306
|
+
oriented = orientTransitiveEdge(edge, definition);
|
|
307
|
+
}
|
|
308
|
+
else if (definition.kind === "implements") {
|
|
309
|
+
oriented = { from: edge.source, to: edge.target };
|
|
310
|
+
}
|
|
311
|
+
if (oriented === undefined)
|
|
312
|
+
continue;
|
|
313
|
+
const sources = reverse.get(oriented.to) ?? new Set();
|
|
314
|
+
sources.add(oriented.from);
|
|
315
|
+
reverse.set(oriented.to, sources);
|
|
316
|
+
}
|
|
317
|
+
return reverse;
|
|
318
|
+
}
|
|
319
|
+
/** Expand outcome nodes through every deterministic reverse typed path. */
|
|
320
|
+
function expandOutcomeReachability(outcomes, reverse, signal) {
|
|
321
|
+
const reachable = new Set(outcomes);
|
|
322
|
+
const queue = [...outcomes].sort();
|
|
323
|
+
for (let index = 0; index < queue.length; index += 1) {
|
|
324
|
+
signal?.throwIfAborted();
|
|
325
|
+
for (const source of [...(reverse.get(queue[index]) ?? [])].sort()) {
|
|
326
|
+
if (reachable.has(source))
|
|
327
|
+
continue;
|
|
328
|
+
reachable.add(source);
|
|
329
|
+
queue.push(source);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
return reachable;
|
|
333
|
+
}
|
|
334
|
+
/** Count active and terminal nodes against the resolved outcome-reachable set. */
|
|
335
|
+
function tallyOutcomeReachability(nodeStates, outcomes, reachable, signal) {
|
|
336
|
+
let activeReachable = 0;
|
|
337
|
+
let activeUnreachable = 0;
|
|
338
|
+
let terminal = 0;
|
|
339
|
+
let terminalReachable = 0;
|
|
340
|
+
for (const state of nodeStates.values()) {
|
|
341
|
+
signal?.throwIfAborted();
|
|
342
|
+
if (outcomes.has(state.id))
|
|
343
|
+
continue;
|
|
344
|
+
if (state.missing || state.status === "external")
|
|
345
|
+
continue;
|
|
346
|
+
if (state.terminal) {
|
|
347
|
+
terminal += 1;
|
|
348
|
+
if (reachable.has(state.id))
|
|
349
|
+
terminalReachable += 1;
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
if (reachable.has(state.id))
|
|
353
|
+
activeReachable += 1;
|
|
354
|
+
else
|
|
355
|
+
activeUnreachable += 1;
|
|
356
|
+
}
|
|
357
|
+
const active = activeReachable + activeUnreachable;
|
|
358
|
+
const terminalUnreachable = terminal - terminalReachable;
|
|
359
|
+
const outcomeReachable = activeReachable + terminalReachable;
|
|
360
|
+
const outcomeUnreachable = activeUnreachable + terminalUnreachable;
|
|
361
|
+
const outcomePopulation = outcomeReachable + outcomeUnreachable;
|
|
362
|
+
return {
|
|
363
|
+
active_outcome_reachable_nodes: activeReachable,
|
|
364
|
+
active_outcome_unreachable_nodes: activeUnreachable,
|
|
365
|
+
active_outcome_reachability_basis_points: active === 0 ? 0 : Math.floor((activeReachable * 10_000) / active),
|
|
366
|
+
terminal_nodes: terminal,
|
|
367
|
+
terminal_outcome_reachable_nodes: terminalReachable,
|
|
368
|
+
terminal_outcome_unreachable_nodes: terminalUnreachable,
|
|
369
|
+
terminal_outcome_reachability_basis_points: terminal === 0 ? 0 : Math.floor((terminalReachable * 10_000) / terminal),
|
|
370
|
+
outcome_reachable_nodes: outcomeReachable,
|
|
371
|
+
outcome_unreachable_nodes: outcomeUnreachable,
|
|
372
|
+
outcome_reachability_basis_points: outcomePopulation === 0
|
|
373
|
+
? 0
|
|
374
|
+
: Math.floor((outcomeReachable * 10_000) / outcomePopulation),
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Count nodes with an explicit typed path to an outcome milestone. Hierarchy
|
|
379
|
+
* edges flow child to parent and `implements` flows implementation to outcome;
|
|
380
|
+
* unrelated association edges deliberately contribute no reachability.
|
|
381
|
+
*/
|
|
382
|
+
function profileOutcomeReachability(assembly, nodeStates, signal) {
|
|
383
|
+
const outcomes = new Set(assembly.details
|
|
384
|
+
.filter((detail) => detail.type?.toLowerCase() === OUTCOME_MILESTONE_TYPE &&
|
|
385
|
+
detail.title
|
|
386
|
+
.trim()
|
|
387
|
+
.toLowerCase()
|
|
388
|
+
.startsWith(OUTCOME_MILESTONE_TITLE_PREFIX))
|
|
389
|
+
.map((detail) => detail.id));
|
|
390
|
+
const reachable = expandOutcomeReachability(outcomes, buildOutcomeReverseIndex(assembly, signal), signal);
|
|
391
|
+
return {
|
|
392
|
+
outcome_nodes: outcomes.size,
|
|
393
|
+
...tallyOutcomeReachability(nodeStates, outcomes, reachable, signal),
|
|
394
|
+
};
|
|
395
|
+
}
|
|
293
396
|
/** Fold one active node's degree into the aggregate and per-type coverage tallies. */
|
|
294
397
|
function tallyActiveCoverageNode(tallies, state, degree, exemptIsolates, isolateExemptTypes) {
|
|
295
398
|
tallies.active += 1;
|
|
@@ -316,7 +419,7 @@ function tallyActiveCoverageNode(tallies, state, degree, exemptIsolates, isolate
|
|
|
316
419
|
else
|
|
317
420
|
tallies.sparse.push(state.id);
|
|
318
421
|
}
|
|
319
|
-
function collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExemptTypes, maxSampleSize, edgesByKind) {
|
|
422
|
+
function collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExemptTypes, maxSampleSize, edgesByKind, signal) {
|
|
320
423
|
const tallies = {
|
|
321
424
|
active: 0,
|
|
322
425
|
missing: 0,
|
|
@@ -327,6 +430,7 @@ function collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExem
|
|
|
327
430
|
byType: new Map(),
|
|
328
431
|
};
|
|
329
432
|
for (const id of assembly.graph.nodes()) {
|
|
433
|
+
signal?.throwIfAborted();
|
|
330
434
|
const state = nodeStates.get(id);
|
|
331
435
|
/* c8 ignore next -- every graph node originates from assembly details by construction */
|
|
332
436
|
if (!state)
|
|
@@ -346,6 +450,10 @@ function collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExem
|
|
|
346
450
|
const edgeCount = assembly.graph.edges().length;
|
|
347
451
|
const sortedEdgesByKind = Object.fromEntries(Object.entries(edgesByKind).sort(([left], [right]) => left.localeCompare(right)));
|
|
348
452
|
const semanticEdges = Object.entries(sortedEdgesByKind).reduce((count, [kind, value]) => count + (isSemanticContextKind(kind) ? value : 0), 0);
|
|
453
|
+
const cutStructure = findRelationshipCutStructure(assembly.graph, {
|
|
454
|
+
signal,
|
|
455
|
+
}).value;
|
|
456
|
+
const outcomeReachability = profileOutcomeReachability(assembly, nodeStates, signal);
|
|
349
457
|
return {
|
|
350
458
|
findings,
|
|
351
459
|
profile: {
|
|
@@ -364,6 +472,10 @@ function collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExem
|
|
|
364
472
|
isolated_active_nodes: tallies.isolated,
|
|
365
473
|
degree_leq_one_active_nodes: tallies.degreeLeqOne,
|
|
366
474
|
coverage_by_type: Object.fromEntries([...tallies.byType.entries()].sort(([left], [right]) => left < right ? -1 : 1)),
|
|
475
|
+
articulation_points: cutStructure.articulationPoints.length,
|
|
476
|
+
bridge_edges: cutStructure.bridges.length,
|
|
477
|
+
...outcomeReachability,
|
|
478
|
+
finding_subjects_by_code: Object.fromEntries(RELATIONSHIP_AUDIT_FINDING_CODES.map((code) => [code, 0])),
|
|
367
479
|
},
|
|
368
480
|
};
|
|
369
481
|
}
|
|
@@ -410,14 +522,21 @@ export function auditWorkspaceRelationshipGraph(assembly, options = {}) {
|
|
|
410
522
|
options.signal?.throwIfAborted();
|
|
411
523
|
findings.push(...collectDuplicateEdgeFindings(assembly, nodeStates, maxSampleSize), ...collectDuplicateRowFindings(assembly, maxSampleSize));
|
|
412
524
|
options.signal?.throwIfAborted();
|
|
413
|
-
const coverage = collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExemptTypes, maxSampleSize, edgesByKind);
|
|
525
|
+
const coverage = collectCoverageReport(assembly, nodeStates, exemptIsolates, isolateExemptTypes, maxSampleSize, edgesByKind, options.signal);
|
|
414
526
|
findings.push(...coverage.findings);
|
|
415
527
|
findings.sort((left, right) => SEVERITY_RANK[left.severity] - SEVERITY_RANK[right.severity] ||
|
|
416
528
|
left.code.localeCompare(right.code) ||
|
|
417
529
|
left.sample[0].localeCompare(right.sample[0]));
|
|
530
|
+
const findingSubjectsByCode = coverage.profile.finding_subjects_by_code;
|
|
531
|
+
for (const finding of findings) {
|
|
532
|
+
findingSubjectsByCode[finding.code] += finding.count;
|
|
533
|
+
}
|
|
418
534
|
return {
|
|
419
535
|
findings,
|
|
420
|
-
profile:
|
|
536
|
+
profile: {
|
|
537
|
+
...coverage.profile,
|
|
538
|
+
finding_subjects_by_code: findingSubjectsByCode,
|
|
539
|
+
},
|
|
421
540
|
};
|
|
422
541
|
}
|
|
423
542
|
/** Subtract two count records, keeping only non-zero signed deltas in sorted key order. */
|
|
@@ -491,4 +610,4 @@ export function diffRelationshipAuditSnapshots(baseline, current) {
|
|
|
491
610
|
};
|
|
492
611
|
}
|
|
493
612
|
//# sourceMappingURL=governance.js.map
|
|
494
|
-
//# debugId=
|
|
613
|
+
//# debugId=ab8a4904-0302-5e36-9963-750b3ba79876
|
package/dist/sdk/guide.js
CHANGED
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Implements the pm guide 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]="27be0fa5-1c6a-53de-a0e8-179aab7c795a")}catch(e){}}();
|
|
8
|
+
import { isFileAbsentError } from "../core/fs/fs-utils.js";
|
|
8
9
|
import { readFile } from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { resolveConfiguredPmPackageRoot, EXIT_CODE, PmCliError, } from "./runtime-primitives.js";
|
|
@@ -119,8 +120,7 @@ async function renderGuideDocs(topic, depth, packageRoot) {
|
|
|
119
120
|
}
|
|
120
121
|
}
|
|
121
122
|
catch (error) {
|
|
122
|
-
const
|
|
123
|
-
const missing = code === "ENOENT";
|
|
123
|
+
const missing = isFileAbsentError(error);
|
|
124
124
|
docs.push({
|
|
125
125
|
path: doc.path,
|
|
126
126
|
purpose: doc.purpose,
|
|
@@ -277,4 +277,4 @@ export function renderGuideMarkdown(result) {
|
|
|
277
277
|
return lines.join("\n");
|
|
278
278
|
}
|
|
279
279
|
//# sourceMappingURL=guide.js.map
|
|
280
|
-
//# debugId=
|
|
280
|
+
//# debugId=27be0fa5-1c6a-53de-a0e8-179aab7c795a
|
package/dist/sdk/index.d.ts
CHANGED
|
@@ -58,6 +58,7 @@ export * from "./compose.js";
|
|
|
58
58
|
export * from "./governance/assurance.js";
|
|
59
59
|
export * from "./governance/assurance-action.js";
|
|
60
60
|
export * from "./governance/assurance-runtime.js";
|
|
61
|
+
export * from "./governance/assurance-presets.js";
|
|
61
62
|
export * from "./compile-cache.js";
|
|
62
63
|
export * from "./environment/project-runtime-compatibility.js";
|
|
63
64
|
export * from "./environment/source-context.js";
|
|
@@ -94,7 +95,7 @@ export { runDeps, type DepsCollapseMode, type DepsFormat, type DepsGraphEdge, ty
|
|
|
94
95
|
export * from "./graph/index.js";
|
|
95
96
|
export { runDocs } from "./docs.js";
|
|
96
97
|
export { runFiles, runFilesDiscover, runFilesLookup, type FilesDiscoveryCandidate, type FilesLookupItem, type FilesLookupMatch, } from "./files.js";
|
|
97
|
-
export { applyPathMigrations, applyStandaloneNote, artifactKey, dedupeLinkedArtifacts, ensureScope, expandAddGlobEntries, normalizeLinkedPath, parseAddEntries, parseAddGlobEntries, parseMigrateEntries, parseRemoveEntries, renameArtifactsResultKey, runLinkedArtifacts, sortLinkedArtifacts, validateLinkedPaths, type AddGlobEntry, type LinkedArtifact, type LinkedArtifactCommandOptions, type LinkedArtifactKindConfig, type LinkedArtifactResult, type LinkedPathValidation, type PathMigration, } from "./linked-artifacts.js";
|
|
98
|
+
export { applyPathMigrations, applyStandaloneNote, artifactKey, assertLinkedArtifactMutationIsUnambiguous, dedupeLinkedArtifacts, ensureScope, expandAddGlobEntries, normalizeLinkedPath, parseAddEntries, parseAddGlobEntries, parseMigrateEntries, parseRemoveEntries, renameArtifactsResultKey, runLinkedArtifacts, sortLinkedArtifacts, validateLinkedPaths, type AddGlobEntry, type LinkedArtifact, type LinkedArtifactCommandOptions, type LinkedArtifactKindConfig, type LinkedArtifactResult, type LinkedPathValidation, type PathMigration, } from "./linked-artifacts.js";
|
|
98
99
|
export * from "./pagination.js";
|
|
99
100
|
export * from "./query/item-filter-options.js";
|
|
100
101
|
export * from "./query/parsers.js";
|
package/dist/sdk/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Defines public SDK APIs and package-author helpers for Index.
|
|
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]="8664ab01-dc47-5344-b2d7-9ac315e8a74b")}catch(e){}}();
|
|
8
8
|
export { PM_COMMAND_VISIBILITY_CONTRACTS, PM_MCP_PROMPT_CONTRACTS, PM_MCP_RESOURCE_CONTRACTS, PM_MCP_TOOL_COMMAND_CONTRACTS, listPmCommandsForTier, listPmMcpToolsForProfile, renderPmCommandVisibilityMarkdown, resolvePmCommandVisibilityTier, } from "./agent-capability-contracts.js";
|
|
9
9
|
export * from "./agent-session-context.js";
|
|
10
10
|
export { isErrnoError, limitAnnotationEntries, parseAnnotationTextInput, readAnnotationEntries, normalizeAnnotationTransportOptions, resolveAnnotationInput, resolveAnnotationIndex, runAnnotationCommand, wrapOwnershipConflict, } from "./annotations.js";
|
|
@@ -56,6 +56,7 @@ export * from "./compose.js";
|
|
|
56
56
|
export * from "./governance/assurance.js";
|
|
57
57
|
export * from "./governance/assurance-action.js";
|
|
58
58
|
export * from "./governance/assurance-runtime.js";
|
|
59
|
+
export * from "./governance/assurance-presets.js";
|
|
59
60
|
export * from "./compile-cache.js";
|
|
60
61
|
export * from "./environment/project-runtime-compatibility.js";
|
|
61
62
|
export * from "./environment/source-context.js";
|
|
@@ -92,7 +93,7 @@ export { runDeps, } from "./dependencies.js";
|
|
|
92
93
|
export * from "./graph/index.js";
|
|
93
94
|
export { runDocs } from "./docs.js";
|
|
94
95
|
export { runFiles, runFilesDiscover, runFilesLookup, } from "./files.js";
|
|
95
|
-
export { applyPathMigrations, applyStandaloneNote, artifactKey, dedupeLinkedArtifacts, ensureScope, expandAddGlobEntries, normalizeLinkedPath, parseAddEntries, parseAddGlobEntries, parseMigrateEntries, parseRemoveEntries, renameArtifactsResultKey, runLinkedArtifacts, sortLinkedArtifacts, validateLinkedPaths, } from "./linked-artifacts.js";
|
|
96
|
+
export { applyPathMigrations, applyStandaloneNote, artifactKey, assertLinkedArtifactMutationIsUnambiguous, dedupeLinkedArtifacts, ensureScope, expandAddGlobEntries, normalizeLinkedPath, parseAddEntries, parseAddGlobEntries, parseMigrateEntries, parseRemoveEntries, renameArtifactsResultKey, runLinkedArtifacts, sortLinkedArtifacts, validateLinkedPaths, } from "./linked-artifacts.js";
|
|
96
97
|
export * from "./pagination.js";
|
|
97
98
|
export * from "./query/item-filter-options.js";
|
|
98
99
|
export * from "./query/parsers.js";
|
|
@@ -150,4 +151,4 @@ export * from "./governance.js";
|
|
|
150
151
|
export * from "./query.js";
|
|
151
152
|
export * from "./testing.js";
|
|
152
153
|
//# sourceMappingURL=index.js.map
|
|
153
|
-
//# debugId=
|
|
154
|
+
//# debugId=8664ab01-dc47-5344-b2d7-9ac315e8a74b
|
|
@@ -115,6 +115,8 @@ export declare function parseRemoveEntries(raw: string[] | undefined): string[];
|
|
|
115
115
|
export declare function parseMigrateEntries(raw: string[] | undefined): PathMigration[];
|
|
116
116
|
/** Implements apply path migrations for the public runtime surface of this module. */
|
|
117
117
|
export declare function applyPathMigrations(artifactPath: string, migrations: PathMigration[]): string;
|
|
118
|
+
/** Reject a transaction that resolves the same linked path into both add and remove sets. */
|
|
119
|
+
export declare function assertLinkedArtifactMutationIsUnambiguous(adds: LinkedArtifact[], removes: string[], migrations?: PathMigration[]): void;
|
|
118
120
|
/** Implements normalize linked path for the public runtime surface of this module. */
|
|
119
121
|
export declare function normalizeLinkedPath(value: string): string;
|
|
120
122
|
/** Anchor a local linked path to the project workspace while preserving remote references and absolute paths. */
|
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* Implements the pm linked artifacts 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]="585364aa-e5ff-56b6-8276-8f741fbd6be4")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
10
|
import fg from "fast-glob";
|
|
11
|
-
import { pathExists } from "../core/fs/fs-utils.js";
|
|
11
|
+
import { isFileAbsentError, pathExists } from "../core/fs/fs-utils.js";
|
|
12
12
|
import { getActiveExtensionRegistrations } from "../core/extensions/index.js";
|
|
13
13
|
import { assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, parseCsvKv, } from "../core/item/parse.js";
|
|
14
14
|
import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
|
|
@@ -179,6 +179,30 @@ export function applyPathMigrations(artifactPath, migrations) {
|
|
|
179
179
|
}
|
|
180
180
|
return next;
|
|
181
181
|
}
|
|
182
|
+
/** Reject a transaction that resolves the same linked path into both add and remove sets. */
|
|
183
|
+
export function assertLinkedArtifactMutationIsUnambiguous(adds, removes, migrations = []) {
|
|
184
|
+
if (adds.length === 0 || removes.length === 0) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const addedPaths = new Set(adds.map((entry) => applyPathMigrations(entry.path, migrations)));
|
|
188
|
+
const conflicts = [
|
|
189
|
+
...new Set(removes
|
|
190
|
+
.map((entry) => applyPathMigrations(entry, migrations))
|
|
191
|
+
.filter((entry) => addedPaths.has(entry))),
|
|
192
|
+
].sort((left, right) => left.localeCompare(right));
|
|
193
|
+
if (conflicts.length === 0) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
throw new PmCliError(`Linked artifact mutation cannot add and remove the same normalized path in one transaction: ${conflicts.join(", ")}. Split the replacement into separate commands so each history event has one unambiguous intent.`, EXIT_CODE.USAGE, {
|
|
197
|
+
code: "linked_artifact_mutation_conflict",
|
|
198
|
+
reason: "same_path_added_and_removed",
|
|
199
|
+
required: "Use distinct normalized paths for --add and --remove in one invocation.",
|
|
200
|
+
why: "Conflicting batch intent cannot be applied deterministically without silently discarding metadata or a removal.",
|
|
201
|
+
nextSteps: [
|
|
202
|
+
"Run the removal and addition as separate commands with a --message describing each intent.",
|
|
203
|
+
],
|
|
204
|
+
});
|
|
205
|
+
}
|
|
182
206
|
/** Implements normalize linked path for the public runtime surface of this module. */
|
|
183
207
|
export function normalizeLinkedPath(value) {
|
|
184
208
|
return value.split(path.sep).join("/");
|
|
@@ -293,7 +317,7 @@ export async function validateLinkedPaths(paths, workspaceRoot = process.cwd())
|
|
|
293
317
|
if (typeof error === "object" &&
|
|
294
318
|
error !== null &&
|
|
295
319
|
"code" in error &&
|
|
296
|
-
error
|
|
320
|
+
isFileAbsentError(error)) {
|
|
297
321
|
missingPaths.push(relativePath);
|
|
298
322
|
continue;
|
|
299
323
|
}
|
|
@@ -384,6 +408,7 @@ export async function runLinkedArtifacts(id, options, global, config) {
|
|
|
384
408
|
const adds = applyStandaloneNote([...parsedAdds, ...expandedGlobAdds], options.note, parsedAdds.length > 0 || addGlobs.length > 0);
|
|
385
409
|
const removes = parseRemoveEntries(resolvedRemoves).map((entry) => anchorLinkedPath(entry, workspaceRoot, invocationRoot));
|
|
386
410
|
const migrations = parseMigrateEntries(resolvedMigrations);
|
|
411
|
+
assertLinkedArtifactMutationIsUnambiguous(adds, removes, migrations);
|
|
387
412
|
const shouldMutate = adds.length > 0 || removes.length > 0 || migrations.length > 0;
|
|
388
413
|
if (!shouldMutate) {
|
|
389
414
|
const located = await locateItem(pmRoot, id, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
|
|
@@ -454,4 +479,4 @@ export function renameArtifactsResultKey(result, key) {
|
|
|
454
479
|
return out;
|
|
455
480
|
}
|
|
456
481
|
//# sourceMappingURL=linked-artifacts.js.map
|
|
457
|
-
//# debugId=
|
|
482
|
+
//# debugId=585364aa-e5ff-56b6-8276-8f741fbd6be4
|