@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.
- package/.claude-plugin/marketplace.json +2 -2
- package/CHANGELOG.md +162 -111
- package/dist/cli/error-guidance.js +4 -8
- package/dist/cli/main.js +40 -3
- package/dist/cli/register-assurance.js +28 -17
- package/dist/cli-bundle/bundle-manifest.json +141 -173
- package/dist/cli-bundle/chunks/chunk-BBOFSVAK.js +197 -0
- package/dist/cli-bundle/chunks/chunk-BFALV3YP.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-WLAHPSOX.js → chunk-FIW4P64F.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-BM5YJ2UW.js → chunk-G5JUB66K.js} +52 -52
- package/dist/cli-bundle/chunks/chunk-SBRKH6OR.js +2 -0
- package/dist/cli-bundle/chunks/chunk-TMJ7URWS.js +13 -0
- package/dist/cli-bundle/chunks/chunk-TXMEUUUY.js +8 -0
- package/dist/cli-bundle/chunks/{chunk-KOQMGCTA.js → chunk-XAVMOK6B.js} +50 -50
- package/dist/cli-bundle/chunks/chunk-YAMTJL6Y.js +34 -0
- package/dist/cli-bundle/chunks/chunk-YSVSMJ2B.js +2 -0
- package/dist/cli-bundle/chunks/{register-list-query-XPCJRUUD.js → register-list-query-T3EHHNNV.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-4RJCBKRS.js → register-mutation-E27WCLSZ.js} +2 -2
- package/dist/cli-bundle/chunks/register-operations-4R6I7CPY.js +2 -0
- package/dist/cli-bundle/chunks/{register-setup-LLHAKP2V.js → register-setup-3YXZ444E.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-JAFRIWVF.js → chunk-4DQ2YERC.js} +4 -4
- package/dist/cli-bundle/focused-chunks/chunk-F43TT2QQ.js +8 -0
- package/dist/cli-bundle/focused-chunks/chunk-K7RWWOAG.js +4 -0
- package/dist/cli-bundle/focused-chunks/chunk-KFSZ3BP6.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-KHM2CS2C.js → chunk-KSEDUWVZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-KYUQGTSB.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-ZMGWAYH7.js → chunk-LZ4MV3RH.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-PGXJQLCT.js +155 -0
- package/dist/cli-bundle/focused-chunks/{chunk-RWPAWUOT.js → chunk-PPFGQDSI.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-Q4YY3XNF.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-QK753U3U.js +46 -0
- package/dist/cli-bundle/focused-chunks/chunk-QUMB2J27.js +2 -0
- package/dist/cli-bundle/focused-chunks/chunk-SM7MTG27.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-GQW4BPUT.js → chunk-WCVE2NIG.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-XDNAW5OI.js +18 -0
- package/dist/cli-bundle/focused-chunks/{chunk-YIAXMC3T.js → chunk-YOOI3UZX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-ZM6TZVHC.js +2 -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 +45 -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 +109 -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.d.ts +6 -0
- package/dist/core/history/drift-scan.js +76 -58
- package/dist/core/history/workspace-history.d.ts +59 -0
- package/dist/core/history/workspace-history.js +197 -10
- package/dist/core/lock/lock-gc.js +8 -13
- package/dist/core/lock/lock.js +5 -4
- package/dist/core/output/output.js +12 -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/runtime-contracts.d.ts +6 -1
- package/dist/sdk/cli-contracts/runtime-contracts.js +155 -60
- 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/cli-program.js +3 -3
- 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-relevance.js +12 -4
- 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 +145 -6
- package/dist/sdk/governance/gc.js +5 -11
- package/dist/sdk/governance/health.js +18 -6
- package/dist/sdk/governance/validate-history-drift.d.ts +7 -0
- package/dist/sdk/governance/validate-history-drift.js +68 -0
- package/dist/sdk/governance/validate.js +6 -48
- package/dist/sdk/graph/assembly.d.ts +23 -0
- package/dist/sdk/graph/assembly.js +54 -2
- package/dist/sdk/graph/durable-cache.js +91 -3
- package/dist/sdk/graph/governance-contracts.d.ts +12 -0
- package/dist/sdk/graph/governance-contracts.js +29 -0
- package/dist/sdk/graph/governance.d.ts +51 -3
- package/dist/sdk/graph/governance.js +216 -35
- package/dist/sdk/graph/index.d.ts +2 -2
- package/dist/sdk/graph/index.js +4 -4
- package/dist/sdk/graph/mutation-advisory.js +15 -7
- package/dist/sdk/graph/remediation.js +12 -2
- package/dist/sdk/guide.js +4 -4
- package/dist/sdk/history-read.d.ts +8 -0
- package/dist/sdk/history-read.js +2 -2
- package/dist/sdk/index.d.ts +3 -2
- package/dist/sdk/index.js +5 -4
- 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/query/history.js +20 -3
- package/dist/sdk/read-output-budget.d.ts +2 -0
- package/dist/sdk/read-output-budget.js +12 -5
- package/dist/sdk/read-output-contracts.d.ts +61 -5
- package/dist/sdk/read-output-contracts.js +210 -28
- package/dist/sdk/read-output-rows.d.ts +11 -0
- package/dist/sdk/read-output-rows.js +47 -2
- package/dist/sdk/relationship-history.js +5 -5
- package/dist/sdk/runtime-primitives.d.ts +1 -1
- package/dist/sdk/runtime-primitives.js +3 -3
- package/dist/sdk/runtime.js +5 -3
- 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 +163 -3
- package/docs/COMMANDS.md +31 -2
- package/docs/CONFIGURATION.md +2 -0
- package/docs/EXTENSIONS.md +11 -12
- package/docs/READ_OUTPUT_CONTRACTS.md +44 -8
- package/docs/RELATIONSHIP_GRAPH.md +34 -4
- package/docs/SDK.md +29 -8
- package/docs/SDK_CONTEXT_INTEGRITY.md +32 -1
- package/docs/TESTING.md +47 -16
- package/docs/performance/sdk-entrypoint-import-costs.md +20 -13
- package/marketplace.json +2 -2
- package/package.json +6 -6
- package/packages/pm-beads/extensions/beads/index.ts +1 -0
- package/packages/pm-beads/package.json +1 -1
- package/packages/pm-calendar/extensions/calendar/index.ts +1 -0
- package/packages/pm-calendar/package.json +1 -1
- package/packages/pm-command-kit/package.json +1 -1
- package/packages/pm-digital-twin/extensions/digital-twin/index.ts +7 -0
- package/packages/pm-digital-twin/package.json +1 -1
- package/packages/pm-governance-audit/extensions/governance-audit/index.ts +4 -0
- package/packages/pm-governance-audit/package.json +1 -1
- package/packages/pm-guide-shell/extensions/guide-shell/index.ts +5 -0
- package/packages/pm-guide-shell/package.json +1 -1
- package/packages/pm-kanban/package.json +1 -1
- package/packages/pm-lifecycle-hooks/package.json +1 -1
- package/packages/pm-linked-test-adapters/extensions/linked-test-adapters/index.ts +6 -0
- package/packages/pm-linked-test-adapters/package.json +1 -1
- package/packages/pm-search-advanced/extensions/search-advanced/index.ts +2 -0
- package/packages/pm-search-advanced/package.json +1 -1
- package/packages/pm-templates/extensions/templates/index.ts +4 -0
- package/packages/pm-templates/package.json +1 -1
- package/packages/pm-todos/extensions/todos/index.ts +2 -0
- package/packages/pm-todos/package.json +1 -1
- package/packages/pm-vcs/extensions/vcs/index.ts +7 -0
- package/packages/pm-vcs/package.json +1 -1
- package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
- package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
- package/scripts/bundle-cli.mjs +17 -4
- package/sdk/public-surface.json +390 -60
- 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-RBTK5EZV.js +0 -5
- 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-2DALMVF7.js +0 -5
- package/dist/cli-bundle/focused-chunks/chunk-5OQIMELN.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-5TAGTDRE.js +0 -2
- 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-KPSXVBDV.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-KTLOKKCQ.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-NYLOUPOB.js +0 -2
- 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]="97fd3651-47de-5505-be2b-bc466313e91f")}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);
|
|
@@ -917,6 +917,9 @@ const HEALTH_DETAIL_SUMMARIZERS = {
|
|
|
917
917
|
unreadable_streams: summarizeStringList(details.unreadable_streams, limit),
|
|
918
918
|
hash_mismatches: summarizeStringList(details.hash_mismatches, limit),
|
|
919
919
|
chain_mismatches: summarizeStringList(details.chain_mismatches, limit),
|
|
920
|
+
workspace_state_mismatches: summarizeStringList(details.workspace_state_mismatches, limit),
|
|
921
|
+
workspace_state_missing: summarizeStringList(details.workspace_state_missing, limit),
|
|
922
|
+
workspace_state_unreadable: summarizeStringList(details.workspace_state_unreadable, limit),
|
|
920
923
|
skipped: details.skipped,
|
|
921
924
|
}),
|
|
922
925
|
vectorization: (details, limit) => ({
|
|
@@ -1351,12 +1354,15 @@ async function buildLocksCheck(pmRoot) {
|
|
|
1351
1354
|
}
|
|
1352
1355
|
async function buildHistoryDriftCheck(pmRoot, items) {
|
|
1353
1356
|
const cacheHitVerification = "metadata";
|
|
1354
|
-
const { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems, } = await scanHistoryDrift(pmRoot, items, { cacheHitVerification });
|
|
1357
|
+
const { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems, workspaceStateMismatches, workspaceStateMissing, workspaceStateUnreadable, } = await scanHistoryDrift(pmRoot, items, { cacheHitVerification });
|
|
1355
1358
|
const warnings = [
|
|
1356
1359
|
...missingStreams.map((id) => `history_drift_missing_stream:${id}`),
|
|
1357
1360
|
...unreadableStreams.map((id) => `history_drift_unreadable_stream:${id}`),
|
|
1358
1361
|
...hashMismatches.map((id) => `history_drift_hash_mismatch:${id}`),
|
|
1359
1362
|
...chainMismatches.map((id) => `history_drift_chain_mismatch:${id}`),
|
|
1363
|
+
...workspaceStateMismatches.map((documentPath) => `history_drift_workspace_state_mismatch:${documentPath}`),
|
|
1364
|
+
...workspaceStateMissing.map((documentPath) => `history_drift_workspace_state_missing:${documentPath}`),
|
|
1365
|
+
...workspaceStateUnreadable.map((documentPath) => `history_drift_workspace_state_unreadable:${documentPath}`),
|
|
1360
1366
|
];
|
|
1361
1367
|
return {
|
|
1362
1368
|
check: {
|
|
@@ -1373,11 +1379,17 @@ async function buildHistoryDriftCheck(pmRoot, items) {
|
|
|
1373
1379
|
unreadable_streams: unreadableStreams.length,
|
|
1374
1380
|
hash_mismatches: hashMismatches.length,
|
|
1375
1381
|
chain_mismatches: chainMismatches.length,
|
|
1382
|
+
workspace_state_mismatches: workspaceStateMismatches.length,
|
|
1383
|
+
workspace_state_missing: workspaceStateMissing.length,
|
|
1384
|
+
workspace_state_unreadable: workspaceStateUnreadable.length,
|
|
1376
1385
|
},
|
|
1377
1386
|
missing_streams: missingStreams,
|
|
1378
1387
|
unreadable_streams: unreadableStreams,
|
|
1379
1388
|
hash_mismatches: hashMismatches,
|
|
1380
1389
|
chain_mismatches: chainMismatches,
|
|
1390
|
+
workspace_state_mismatches: workspaceStateMismatches,
|
|
1391
|
+
workspace_state_missing: workspaceStateMissing,
|
|
1392
|
+
workspace_state_unreadable: workspaceStateUnreadable,
|
|
1381
1393
|
},
|
|
1382
1394
|
},
|
|
1383
1395
|
warnings,
|
|
@@ -2007,4 +2019,4 @@ export const _testOnlyHealthCommand = {
|
|
|
2007
2019
|
warningCode,
|
|
2008
2020
|
};
|
|
2009
2021
|
//# sourceMappingURL=health.js.map
|
|
2010
|
-
//# debugId=
|
|
2022
|
+
//# debugId=97fd3651-47de-5505-be2b-bc466313e91f
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ValidateCheck } from "./validate.js";
|
|
2
|
+
import type { ValidateItem } from "./validate-item-reader.js";
|
|
3
|
+
/** Build the validation warning and bounded evidence projection for history drift. */
|
|
4
|
+
export declare function buildValidateHistoryDriftCheck(pmRoot: string, items: ValidateItem[], verboseDiagnostics: boolean): Promise<{
|
|
5
|
+
check: ValidateCheck;
|
|
6
|
+
warnings: string[];
|
|
7
|
+
}>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/governance/validate-history-drift
|
|
3
|
+
*
|
|
4
|
+
* Projects append-only item and workspace singleton drift into the validation
|
|
5
|
+
* check contract without adding history-specific weight to the main validate
|
|
6
|
+
* orchestration module.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a1261d65-222c-5c6c-8634-a4413a91aba9")}catch(e){}}();
|
|
10
|
+
import { scanHistoryDrift } from "../../core/history/drift-scan.js";
|
|
11
|
+
const DEFAULT_DIAGNOSTIC_LIMIT = 5;
|
|
12
|
+
/** Build the validation warning and bounded evidence projection for history drift. */
|
|
13
|
+
export async function buildValidateHistoryDriftCheck(pmRoot, items, verboseDiagnostics) {
|
|
14
|
+
const drift = await scanHistoryDrift(pmRoot, items);
|
|
15
|
+
const warningCounts = [
|
|
16
|
+
["validate_history_drift_missing_streams", drift.missingStreams.length],
|
|
17
|
+
["validate_history_drift_unreadable_streams", drift.unreadableStreams.length],
|
|
18
|
+
["validate_history_drift_hash_mismatches", drift.hashMismatches.length],
|
|
19
|
+
["validate_history_drift_chain_mismatches", drift.chainMismatches.length],
|
|
20
|
+
[
|
|
21
|
+
"validate_history_drift_workspace_state_mismatches",
|
|
22
|
+
drift.workspaceStateMismatches.length,
|
|
23
|
+
],
|
|
24
|
+
[
|
|
25
|
+
"validate_history_drift_workspace_state_missing",
|
|
26
|
+
drift.workspaceStateMissing.length,
|
|
27
|
+
],
|
|
28
|
+
[
|
|
29
|
+
"validate_history_drift_workspace_state_unreadable",
|
|
30
|
+
drift.workspaceStateUnreadable.length,
|
|
31
|
+
],
|
|
32
|
+
];
|
|
33
|
+
const warnings = warningCounts
|
|
34
|
+
.filter(([, count]) => count > 0)
|
|
35
|
+
.map(([code, count]) => `${code}:${count}`);
|
|
36
|
+
const diagnosticLimit = verboseDiagnostics
|
|
37
|
+
? Number.POSITIVE_INFINITY
|
|
38
|
+
: DEFAULT_DIAGNOSTIC_LIMIT;
|
|
39
|
+
const driftedItems = drift.driftedItems.slice(0, diagnosticLimit);
|
|
40
|
+
return {
|
|
41
|
+
check: {
|
|
42
|
+
name: "history_drift",
|
|
43
|
+
status: warnings.length === 0 ? "ok" : "warn",
|
|
44
|
+
ok: warnings.length === 0,
|
|
45
|
+
details: {
|
|
46
|
+
checked_items: items.length,
|
|
47
|
+
drifted_items_count: drift.driftedItems.length,
|
|
48
|
+
drifted_items: driftedItems,
|
|
49
|
+
drifted_items_truncated: driftedItems.length < drift.driftedItems.length,
|
|
50
|
+
counts: {
|
|
51
|
+
missing_streams: drift.missingStreams.length,
|
|
52
|
+
unreadable_streams: drift.unreadableStreams.length,
|
|
53
|
+
hash_mismatches: drift.hashMismatches.length,
|
|
54
|
+
chain_mismatches: drift.chainMismatches.length,
|
|
55
|
+
workspace_state_mismatches: drift.workspaceStateMismatches.length,
|
|
56
|
+
workspace_state_missing: drift.workspaceStateMissing.length,
|
|
57
|
+
workspace_state_unreadable: drift.workspaceStateUnreadable.length,
|
|
58
|
+
},
|
|
59
|
+
workspace_state_mismatches: drift.workspaceStateMismatches,
|
|
60
|
+
workspace_state_missing: drift.workspaceStateMissing,
|
|
61
|
+
workspace_state_unreadable: drift.workspaceStateUnreadable,
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
warnings,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=validate-history-drift.js.map
|
|
68
|
+
//# debugId=a1261d65-222c-5c6c-8634-a4413a91aba9
|
|
@@ -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]="7b47a375-e72c-5108-bd93-75dd8cf93218")}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,8 +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";
|
|
17
|
-
import { scanHistoryDrift } from "../../core/history/drift-scan.js";
|
|
16
|
+
import { isFileMissingError, pathExists } from "../../core/fs/fs-utils.js";
|
|
18
17
|
import { normalizeStatusInput } from "../../core/item/status.js";
|
|
19
18
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
20
19
|
import { resolveRuntimeStatusRegistry, } from "../../core/schema/runtime-schema.js";
|
|
@@ -43,6 +42,7 @@ import { runDocs } from "../docs.js";
|
|
|
43
42
|
import { runFiles } from "../files.js";
|
|
44
43
|
import { extractReferencedPmItemIdsFromCommand } from "../test/linked-command-detection.js";
|
|
45
44
|
import { readValidateItems, } from "./validate-item-reader.js";
|
|
45
|
+
import { buildValidateHistoryDriftCheck } from "./validate-history-drift.js";
|
|
46
46
|
const FILE_SCAN_DIRECTORIES = ["src", "tests", "docs"];
|
|
47
47
|
const FILE_SCAN_ROOT_FILES = [
|
|
48
48
|
"README.md",
|
|
@@ -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;
|
|
@@ -1767,48 +1767,6 @@ async function buildFilesCheck(items, workspaceRoot, pmRoot, fileScanMode, inclu
|
|
|
1767
1767
|
};
|
|
1768
1768
|
}
|
|
1769
1769
|
/* c8 ignore stop */
|
|
1770
|
-
/* c8 ignore start -- history-drift warning/count projection permutations are covered by drift integration tests */
|
|
1771
|
-
async function buildHistoryDriftCheck(pmRoot, items, verboseDiagnostics) {
|
|
1772
|
-
const { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems, } = await scanHistoryDrift(pmRoot, items);
|
|
1773
|
-
const warnings = [];
|
|
1774
|
-
if (missingStreams.length > 0) {
|
|
1775
|
-
warnings.push(`validate_history_drift_missing_streams:${missingStreams.length}`);
|
|
1776
|
-
}
|
|
1777
|
-
if (unreadableStreams.length > 0) {
|
|
1778
|
-
warnings.push(`validate_history_drift_unreadable_streams:${unreadableStreams.length}`);
|
|
1779
|
-
}
|
|
1780
|
-
if (hashMismatches.length > 0) {
|
|
1781
|
-
warnings.push(`validate_history_drift_hash_mismatches:${hashMismatches.length}`);
|
|
1782
|
-
}
|
|
1783
|
-
if (chainMismatches.length > 0) {
|
|
1784
|
-
warnings.push(`validate_history_drift_chain_mismatches:${chainMismatches.length}`);
|
|
1785
|
-
}
|
|
1786
|
-
const diagnosticLimit = verboseDiagnostics
|
|
1787
|
-
? Number.POSITIVE_INFINITY
|
|
1788
|
-
: DIAGNOSTIC_LIST_SUMMARY_LIMIT;
|
|
1789
|
-
const summarizedDrifted = summarizeList(driftedItems, diagnosticLimit);
|
|
1790
|
-
return {
|
|
1791
|
-
check: {
|
|
1792
|
-
name: "history_drift",
|
|
1793
|
-
status: warnings.length === 0 ? "ok" : "warn",
|
|
1794
|
-
ok: warnings.length === 0,
|
|
1795
|
-
details: {
|
|
1796
|
-
checked_items: items.length,
|
|
1797
|
-
drifted_items_count: driftedItems.length,
|
|
1798
|
-
drifted_items: summarizedDrifted.values,
|
|
1799
|
-
drifted_items_truncated: summarizedDrifted.truncated,
|
|
1800
|
-
counts: {
|
|
1801
|
-
missing_streams: missingStreams.length,
|
|
1802
|
-
unreadable_streams: unreadableStreams.length,
|
|
1803
|
-
hash_mismatches: hashMismatches.length,
|
|
1804
|
-
chain_mismatches: chainMismatches.length,
|
|
1805
|
-
},
|
|
1806
|
-
},
|
|
1807
|
-
},
|
|
1808
|
-
warnings,
|
|
1809
|
-
};
|
|
1810
|
-
}
|
|
1811
|
-
/* c8 ignore stop */
|
|
1812
1770
|
/* c8 ignore start -- command preview truncation formatting is covered by command-reference integration fixtures */
|
|
1813
1771
|
function summarizeCommandReferenceRow(ownerId, referencedId, command) {
|
|
1814
1772
|
const normalizedCommand = command.trim().replaceAll(/\s+/g, " ");
|
|
@@ -2195,7 +2153,7 @@ async function executeRequestedValidateChecks(params) {
|
|
|
2195
2153
|
recordValidateCheck(state, buildCommandReferencesCheck(params.items, params.settings.id_prefix, fullDiagnostics), fixHintsEnabled);
|
|
2196
2154
|
}
|
|
2197
2155
|
if (params.requestedChecks.has("history_drift")) {
|
|
2198
|
-
recordValidateCheck(state, await
|
|
2156
|
+
recordValidateCheck(state, await buildValidateHistoryDriftCheck(params.pmRoot, params.items, fullDiagnostics), fixHintsEnabled);
|
|
2199
2157
|
}
|
|
2200
2158
|
if (params.requestedChecks.has("format_version")) {
|
|
2201
2159
|
recordValidateCheck(state, buildFormatVersionCheck(params.items, fullDiagnostics), fixHintsEnabled);
|
|
@@ -2356,4 +2314,4 @@ export async function runValidate(options, global, services = {}) {
|
|
|
2356
2314
|
}
|
|
2357
2315
|
/* c8 ignore stop */
|
|
2358
2316
|
//# sourceMappingURL=validate.js.map
|
|
2359
|
-
//# debugId=
|
|
2317
|
+
//# debugId=7b47a375-e72c-5108-bd93-75dd8cf93218
|
|
@@ -77,6 +77,19 @@ export interface DuplicateDependencyRow {
|
|
|
77
77
|
/** Whether the holder is terminal and the duplication is historical debt. */
|
|
78
78
|
legacy_terminal: boolean;
|
|
79
79
|
}
|
|
80
|
+
/** One holder whose scalar blocker and structured ordering row assert opposite precedence. */
|
|
81
|
+
export interface OrderingStorageContradiction {
|
|
82
|
+
/** Item storing both contradictory representations. */
|
|
83
|
+
holder_id: string;
|
|
84
|
+
/** Target named by both the scalar blocker and structured dependency row. */
|
|
85
|
+
target_id: string;
|
|
86
|
+
/** Structured ordering kind that places the holder before the target. */
|
|
87
|
+
dependency_kind: string;
|
|
88
|
+
/** Current lifecycle status of the holder. */
|
|
89
|
+
holder_status: ItemStatus;
|
|
90
|
+
/** Whether the holder is terminal and the contradiction is historical debt. */
|
|
91
|
+
legacy_terminal: boolean;
|
|
92
|
+
}
|
|
80
93
|
/**
|
|
81
94
|
* Collect raw stored dependency rows whose exact identity — holder, kind, and
|
|
82
95
|
* case-insensitive target — appears more than once on one item. Graph
|
|
@@ -85,6 +98,14 @@ export interface DuplicateDependencyRow {
|
|
|
85
98
|
* only surface that reports the storage-layer defect.
|
|
86
99
|
*/
|
|
87
100
|
export declare function collectDuplicateDependencyRows(items: readonly DependencyReferenceHolder[], isTerminal?: (status: ItemStatus) => boolean): DuplicateDependencyRow[];
|
|
101
|
+
/**
|
|
102
|
+
* Collect storage rows where `blocked_by: target` places the target before the
|
|
103
|
+
* holder while a same-target structured ordering dependency places the holder
|
|
104
|
+
* before the target. The contradictory rows form an artificial two-node cycle
|
|
105
|
+
* after graph assembly, so this pre-assembly evidence identifies the exact row
|
|
106
|
+
* to remove instead of reporting only strongly connected component members.
|
|
107
|
+
*/
|
|
108
|
+
export declare function collectOrderingStorageContradictions(items: readonly DependencyReferenceHolder[], isTerminal?: (status: ItemStatus) => boolean, registry?: RelationshipKindRegistry): OrderingStorageContradiction[];
|
|
88
109
|
/**
|
|
89
110
|
* Classify missing hierarchy and dependency targets without mutating their holders.
|
|
90
111
|
*
|
|
@@ -127,6 +148,8 @@ export interface WorkspaceRelationshipAssembly {
|
|
|
127
148
|
dangling: DanglingDependencyReferenceSummary;
|
|
128
149
|
/** Raw same-identity duplicated dependency rows found before graph dedup. */
|
|
129
150
|
duplicateRows: DuplicateDependencyRow[];
|
|
151
|
+
/** Scalar-versus-structured ordering contradictions found before graph normalization. */
|
|
152
|
+
orderingContradictions?: OrderingStorageContradiction[];
|
|
130
153
|
/** Raw legacy alias rows grouped by accepted spelling before graph canonicalization. */
|
|
131
154
|
legacyAliasCounts: Record<string, number>;
|
|
132
155
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
2
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a6fc5da1-b7d1-5b3c-8033-cecccc7861c3")}catch(e){}}();
|
|
3
3
|
import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
|
|
4
4
|
import { RelationshipGraph, createRelationshipKindRegistry, } from "../relationships.js";
|
|
5
5
|
import { isExternalDependencySourceKind } from "../dependency-provenance.js";
|
|
@@ -104,6 +104,57 @@ export function collectDuplicateDependencyRows(items, isTerminal = (status) => s
|
|
|
104
104
|
return compareCaseFoldedText(left.kind, right.kind);
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
|
+
/** Decode one dependency row only when it contradicts the holder's scalar blocker. */
|
|
108
|
+
function decodeOrderingStorageContradiction(item, blocker, dependency, isTerminal, registry) {
|
|
109
|
+
if (typeof dependency !== "object" || dependency === null)
|
|
110
|
+
return undefined;
|
|
111
|
+
const target = normalizeDependencyReferenceTarget(dependency.id);
|
|
112
|
+
if (!target || target.toLowerCase() !== blocker.toLowerCase())
|
|
113
|
+
return undefined;
|
|
114
|
+
const definition = registry.resolve(typeof dependency.kind === "string" ? dependency.kind : "related");
|
|
115
|
+
if (definition?.ordering !== true ||
|
|
116
|
+
(definition.precedence ?? "source_before_target") !== "source_before_target")
|
|
117
|
+
return undefined;
|
|
118
|
+
return {
|
|
119
|
+
holder_id: item.id.trim(),
|
|
120
|
+
target_id: target,
|
|
121
|
+
dependency_kind: definition.kind,
|
|
122
|
+
holder_status: item.status,
|
|
123
|
+
legacy_terminal: isTerminal(item.status),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Collect storage rows where `blocked_by: target` places the target before the
|
|
128
|
+
* holder while a same-target structured ordering dependency places the holder
|
|
129
|
+
* before the target. The contradictory rows form an artificial two-node cycle
|
|
130
|
+
* after graph assembly, so this pre-assembly evidence identifies the exact row
|
|
131
|
+
* to remove instead of reporting only strongly connected component members.
|
|
132
|
+
*/
|
|
133
|
+
export function collectOrderingStorageContradictions(items, isTerminal = (status) => status === "closed" || status === "canceled", registry = resolveWorkspaceRelationshipKindRegistry()) {
|
|
134
|
+
const contradictions = new Map();
|
|
135
|
+
for (const item of items) {
|
|
136
|
+
if (typeof item?.id !== "string" || item.id.trim().length === 0)
|
|
137
|
+
continue;
|
|
138
|
+
const blocker = normalizeDependencyReferenceTarget(item.blocked_by);
|
|
139
|
+
if (!blocker)
|
|
140
|
+
continue;
|
|
141
|
+
for (const dependency of item.dependencies ?? []) {
|
|
142
|
+
const row = decodeOrderingStorageContradiction(item, blocker, dependency, isTerminal, registry);
|
|
143
|
+
if (!row)
|
|
144
|
+
continue;
|
|
145
|
+
contradictions.set(`${row.holder_id.toLowerCase()}\u0000${row.target_id.toLowerCase()}\u0000${row.dependency_kind}`, row);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return [...contradictions.values()].sort((left, right) => {
|
|
149
|
+
const holderCompare = compareCaseFoldedText(left.holder_id, right.holder_id);
|
|
150
|
+
if (holderCompare !== 0)
|
|
151
|
+
return holderCompare;
|
|
152
|
+
const targetCompare = compareCaseFoldedText(left.target_id, right.target_id);
|
|
153
|
+
if (targetCompare !== 0)
|
|
154
|
+
return targetCompare;
|
|
155
|
+
return compareCaseFoldedText(left.dependency_kind, right.dependency_kind);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
107
158
|
/**
|
|
108
159
|
* Classify missing hierarchy and dependency targets without mutating their holders.
|
|
109
160
|
*
|
|
@@ -296,8 +347,9 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
|
|
|
296
347
|
missingIdSet: new Set(missingIds.map((id) => id.toLowerCase())),
|
|
297
348
|
dangling,
|
|
298
349
|
duplicateRows: collectDuplicateDependencyRows(safeItems, isTerminal),
|
|
350
|
+
orderingContradictions: collectOrderingStorageContradictions(safeItems, isTerminal, relationshipRegistry),
|
|
299
351
|
legacyAliasCounts: collectLegacyDependencyAliasCounts(safeItems, relationshipRegistry),
|
|
300
352
|
};
|
|
301
353
|
}
|
|
302
354
|
//# sourceMappingURL=assembly.js.map
|
|
303
|
-
//# debugId=
|
|
355
|
+
//# debugId=a6fc5da1-b7d1-5b3c-8033-cecccc7861c3
|
|
@@ -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]="9e4aa41d-fca4-5e55-ab2b-d99f06d90ae2")}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,88 @@ 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 the additive information-bearing census as one coherent field group. */
|
|
178
|
+
function decodeInformativeProfile(profile, nodes, edges) {
|
|
179
|
+
const fields = [
|
|
180
|
+
"recorded_nodes",
|
|
181
|
+
"informative_edges",
|
|
182
|
+
"redundant_edges",
|
|
183
|
+
"ordering_contradiction_edges",
|
|
184
|
+
];
|
|
185
|
+
const presentCount = fields.filter((field) => profile[field] !== undefined).length;
|
|
186
|
+
if (presentCount !== 0 && presentCount !== fields.length)
|
|
187
|
+
return undefined;
|
|
188
|
+
if (!fields.every((field) => isOptionalValid(profile[field], isNonnegativeInteger)))
|
|
189
|
+
return undefined;
|
|
190
|
+
const decoded = {
|
|
191
|
+
recorded_nodes: profile.recorded_nodes ?? nodes,
|
|
192
|
+
informative_edges: profile.informative_edges ?? edges,
|
|
193
|
+
redundant_edges: profile.redundant_edges ?? 0,
|
|
194
|
+
ordering_contradiction_edges: profile.ordering_contradiction_edges ?? 0,
|
|
195
|
+
};
|
|
196
|
+
return decoded.recorded_nodes <= nodes &&
|
|
197
|
+
decoded.informative_edges <= edges &&
|
|
198
|
+
decoded.redundant_edges <= edges &&
|
|
199
|
+
decoded.ordering_contradiction_edges <= edges
|
|
200
|
+
? decoded
|
|
201
|
+
: undefined;
|
|
202
|
+
}
|
|
203
|
+
/** Validate the optional structural census fields as one complete version group. */
|
|
204
|
+
function hasValidStructuralFields(profile, countFields, rateFields) {
|
|
205
|
+
const introducedFields = [
|
|
206
|
+
...countFields,
|
|
207
|
+
...rateFields,
|
|
208
|
+
"finding_subjects_by_code",
|
|
209
|
+
];
|
|
210
|
+
const presentCount = introducedFields.filter((field) => profile[field] !== undefined).length;
|
|
211
|
+
if (presentCount !== 0 && presentCount !== introducedFields.length)
|
|
212
|
+
return false;
|
|
213
|
+
return (countFields.every((field) => isOptionalValid(profile[field], isNonnegativeInteger)) &&
|
|
214
|
+
rateFields.every((field) => isOptionalValid(profile[field], isNonnegativeInteger) &&
|
|
215
|
+
(profile[field] === undefined || Number(profile[field]) <= 10_000)) &&
|
|
216
|
+
isOptionalValid(profile.finding_subjects_by_code, isNonnegativeCountRecord));
|
|
217
|
+
}
|
|
218
|
+
/** Decode optional structural fields while normalizing pre-structure baselines. */
|
|
219
|
+
function decodeStructuralProfile(profile, affectedSubjectsByCode, nodes, edges) {
|
|
220
|
+
const informative = decodeInformativeProfile(profile, nodes, edges);
|
|
221
|
+
if (informative === undefined)
|
|
222
|
+
return undefined;
|
|
223
|
+
const countFields = [
|
|
224
|
+
"articulation_points",
|
|
225
|
+
"bridge_edges",
|
|
226
|
+
"outcome_nodes",
|
|
227
|
+
"active_outcome_reachable_nodes",
|
|
228
|
+
"active_outcome_unreachable_nodes",
|
|
229
|
+
"terminal_nodes",
|
|
230
|
+
"terminal_outcome_reachable_nodes",
|
|
231
|
+
"terminal_outcome_unreachable_nodes",
|
|
232
|
+
"outcome_reachable_nodes",
|
|
233
|
+
"outcome_unreachable_nodes",
|
|
234
|
+
];
|
|
235
|
+
const rateFields = [
|
|
236
|
+
"active_outcome_reachability_basis_points",
|
|
237
|
+
"terminal_outcome_reachability_basis_points",
|
|
238
|
+
"outcome_reachability_basis_points",
|
|
239
|
+
];
|
|
240
|
+
if (!hasValidStructuralFields(profile, countFields, rateFields))
|
|
241
|
+
return undefined;
|
|
242
|
+
if (profile.edge_basis !== undefined &&
|
|
243
|
+
profile.edge_basis !== "deduplicated_directed")
|
|
244
|
+
return undefined;
|
|
245
|
+
const findingSubjects = isNonnegativeCountRecord(profile.finding_subjects_by_code)
|
|
246
|
+
? profile.finding_subjects_by_code
|
|
247
|
+
: {};
|
|
248
|
+
return {
|
|
249
|
+
edge_basis: "deduplicated_directed",
|
|
250
|
+
...informative,
|
|
251
|
+
...Object.fromEntries(countFields.map((field) => [field, profile[field] ?? 0])),
|
|
252
|
+
...Object.fromEntries(rateFields.map((field) => [field, profile[field] ?? 0])),
|
|
253
|
+
finding_subjects_by_code: Object.fromEntries(RELATIONSHIP_AUDIT_FINDING_CODES.map((code) => [
|
|
254
|
+
code,
|
|
255
|
+
findingSubjects[code] ?? affectedSubjectsByCode[code] ?? 0,
|
|
256
|
+
])),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
176
259
|
/** Decode and cross-check optional graph-composition fields as one coherent unit. */
|
|
177
260
|
function decodeGraphComposition(edges, edgesByKind, edgeShareByKind, semanticEdgesValue, semanticEdgeShareValue) {
|
|
178
261
|
const values = [
|
|
@@ -225,7 +308,8 @@ function decodeBaseline(raw) {
|
|
|
225
308
|
return undefined;
|
|
226
309
|
if (typeof snapshot.fingerprint !== "string")
|
|
227
310
|
return undefined;
|
|
228
|
-
|
|
311
|
+
const affectedSubjectsByCode = snapshot.affected_subjects_by_code;
|
|
312
|
+
if (!isNonnegativeCountRecord(affectedSubjectsByCode)) {
|
|
229
313
|
return undefined;
|
|
230
314
|
}
|
|
231
315
|
if (!isRecord(profile))
|
|
@@ -248,12 +332,16 @@ function decodeBaseline(raw) {
|
|
|
248
332
|
const composition = decodeGraphComposition(profile.edges, profile.edges_by_kind, profile.edge_share_by_kind, profile.semantic_edges, profile.semantic_edge_share);
|
|
249
333
|
if (composition === undefined)
|
|
250
334
|
return undefined;
|
|
335
|
+
const structural = decodeStructuralProfile(profile, affectedSubjectsByCode, profile.nodes, profile.edges);
|
|
336
|
+
if (structural === undefined)
|
|
337
|
+
return undefined;
|
|
251
338
|
const { coverage_by_type = {} } = profile;
|
|
252
339
|
return {
|
|
253
340
|
...snapshot,
|
|
254
341
|
profile: {
|
|
255
342
|
...profile,
|
|
256
343
|
...composition,
|
|
344
|
+
...structural,
|
|
257
345
|
coverage_by_type,
|
|
258
346
|
},
|
|
259
347
|
};
|
|
@@ -271,4 +359,4 @@ export async function saveGraphAuditBaseline(pmRoot, snapshot) {
|
|
|
271
359
|
await writeFileAtomic(graphAuditBaselinePath(pmRoot), JSON.stringify(snapshot));
|
|
272
360
|
}
|
|
273
361
|
//# sourceMappingURL=durable-cache.js.map
|
|
274
|
-
//# debugId=
|
|
362
|
+
//# debugId=9e4aa41d-fca4-5e55-ab2b-d99f06d90ae2
|
|
@@ -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", "ordering_storage_contradiction", "legacy_ordering_storage_contradiction", "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,29 @@
|
|
|
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]="bc561e73-75b8-5ea7-a18c-da70fb991b69")}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
|
+
"ordering_storage_contradiction",
|
|
19
|
+
"legacy_ordering_storage_contradiction",
|
|
20
|
+
"duplicate_edge",
|
|
21
|
+
"legacy_duplicate_edge",
|
|
22
|
+
"duplicate_dependency_row",
|
|
23
|
+
"legacy_duplicate_dependency_row",
|
|
24
|
+
"stale_lifecycle_block",
|
|
25
|
+
"isolated_active_node",
|
|
26
|
+
"sparse_active_node",
|
|
27
|
+
];
|
|
28
|
+
//# sourceMappingURL=governance-contracts.js.map
|
|
29
|
+
//# debugId=bc561e73-75b8-5ea7-a18c-da70fb991b69
|