@unbrained/pm-cli 2026.8.20 → 2026.8.22
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 +38 -0
- package/dist/cli/error-guidance.d.ts +29 -4
- package/dist/cli/error-guidance.js +43 -43
- package/dist/cli/main.d.ts +3 -0
- package/dist/cli/main.js +40 -7
- package/dist/cli-bundle/bundle-manifest.json +150 -150
- package/dist/cli-bundle/chunks/{chunk-L4LGPBJU.js → chunk-BWX4SK46.js} +58 -58
- package/dist/cli-bundle/chunks/chunk-EMWDM5FI.js +13 -0
- package/dist/cli-bundle/chunks/chunk-HYG6LRL4.js +200 -0
- package/dist/cli-bundle/chunks/{chunk-TSMWLCHS.js → chunk-MYYI3ZOA.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-4GB2LTOQ.js → chunk-MZTZQTMS.js} +2 -2
- package/dist/cli-bundle/chunks/{chunk-7BRF2BX2.js → chunk-QI2CT3IX.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-SMWXHMVB.js +35 -0
- package/dist/cli-bundle/chunks/{chunk-US2ZQW2M.js → chunk-U6GQ4VMV.js} +47 -47
- package/dist/cli-bundle/chunks/{chunk-K3EN3LK2.js → chunk-VMMIL3SI.js} +2 -2
- package/dist/cli-bundle/chunks/chunk-WG4STC36.js +5 -0
- package/dist/cli-bundle/chunks/{chunk-XYDDWBZN.js → chunk-YBPJAOQQ.js} +3 -3
- package/dist/cli-bundle/chunks/{register-list-query-JSAQCVOC.js → register-list-query-HZKBQNWW.js} +2 -2
- package/dist/cli-bundle/chunks/{register-mutation-XJPAW63D.js → register-mutation-HTKEEGRD.js} +2 -2
- package/dist/cli-bundle/chunks/{register-operations-DSOSB2XQ.js → register-operations-6EMRWJJY.js} +2 -2
- package/dist/cli-bundle/chunks/{register-setup-QUR6QL2C.js → register-setup-QK4OTOXN.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-TDR5OGG3.js → chunk-2ARQGDDW.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-AZBACT5T.js → chunk-2AZT5WXZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-M32HFIQB.js → chunk-2POVTNLY.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-3LKU6PTJ.js +4 -0
- package/dist/cli-bundle/focused-chunks/chunk-5SHSBMX2.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-UGSS4F5X.js → chunk-6S2MO3Q3.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-5L7M4AI7.js → chunk-A2BC5PQL.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-C4S4A4JJ.js +5 -0
- package/dist/cli-bundle/focused-chunks/{chunk-OM65KHGF.js → chunk-D6RBZEJJ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-E2EWYPY6.js +16 -0
- package/dist/cli-bundle/focused-chunks/{chunk-G3C5ERXG.js → chunk-GMYPD4FX.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-L5LDSRO2.js +155 -0
- package/dist/cli-bundle/focused-chunks/{chunk-BLJCGGID.js → chunk-MB37AYN6.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-MCOR37QK.js +2 -0
- package/dist/cli-bundle/focused-chunks/{chunk-FUREQLQN.js → chunk-PH2OXXVZ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/{chunk-325UXIO7.js → chunk-PMGJUFNQ.js} +2 -2
- package/dist/cli-bundle/focused-chunks/chunk-R6SR45XU.js +50 -0
- package/dist/cli-bundle/focused-chunks/chunk-WZE4LIPW.js +8 -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 +2 -2
- package/dist/cli-bundle/sdk-core.js +40 -40
- package/dist/cli-bundle/sdk-governance.js +1 -1
- package/dist/cli-bundle/sdk-graph.js +1 -1
- package/dist/cli-bundle/sdk-merge.js +32 -32
- package/dist/cli-bundle/sdk-query.js +1 -1
- package/dist/cli-bundle/sdk-runtime.js +1 -1
- package/dist/cli-bundle/sdk-testing.js +1 -1
- package/dist/cli-bundle/sdk.js +5 -5
- package/dist/core/extensions/extension-hook-runtime.js +22 -20
- package/dist/core/extensions/extension-types.d.ts +8 -1
- package/dist/core/extensions/extension-types.js +2 -2
- package/dist/core/extensions/loader.js +7 -3
- package/dist/core/extensions/service-ownership.d.ts +8 -0
- package/dist/core/extensions/service-ownership.js +20 -0
- package/dist/core/item/id.js +20 -5
- package/dist/core/item/item-format.js +27 -2
- package/dist/core/shared/errors.d.ts +20 -0
- package/dist/core/shared/errors.js +2 -2
- package/dist/core/store/item-store.js +6 -91
- package/dist/core/store/tracker-preflight.d.ts +7 -0
- package/dist/core/store/tracker-preflight.js +142 -0
- package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
- package/dist/sdk/agent/tracker-preflight-contracts.d.ts +63 -0
- package/dist/sdk/agent/tracker-preflight-contracts.js +127 -0
- package/dist/sdk/annotations.js +6 -7
- package/dist/sdk/authoring.d.ts +1 -1
- package/dist/sdk/authoring.js +2 -2
- package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
- package/dist/sdk/cli-contracts/agent-output-contracts.js +324 -2
- package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
- package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
- package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
- package/dist/sdk/cli-contracts.d.ts +1 -1
- package/dist/sdk/cli-contracts.js +3 -3
- package/dist/sdk/config.d.ts +5 -0
- package/dist/sdk/config.js +5 -5
- package/dist/sdk/context-intent-runtime.js +7 -4
- package/dist/sdk/contracts.d.ts +1 -0
- package/dist/sdk/contracts.js +3 -2
- package/dist/sdk/dependencies.js +5 -7
- package/dist/sdk/dependency-flag-validation.d.ts +1 -1
- package/dist/sdk/dependency-flag-validation.js +10 -4
- package/dist/sdk/environment/tracker-preflight.d.ts +6 -0
- package/dist/sdk/environment/tracker-preflight.js +10 -0
- package/dist/sdk/eval.js +5 -7
- package/dist/sdk/extension/install-sources.d.ts +1 -1
- package/dist/sdk/extension/install-sources.js +6 -3
- package/dist/sdk/extension/output-ownership.d.ts +1 -0
- package/dist/sdk/extension/output-ownership.js +3 -2
- package/dist/sdk/files.js +6 -10
- package/dist/sdk/generated/generated-error-code-catalog-part-1.js +75 -15
- package/dist/sdk/generated/generated-error-code-catalog-part-2.js +81 -8
- package/dist/sdk/governance/assurance.d.ts +36 -2
- package/dist/sdk/governance/assurance.js +184 -10
- package/dist/sdk/governance/gc.js +5 -6
- package/dist/sdk/governance/health.d.ts +3 -0
- package/dist/sdk/governance/health.js +42 -11
- package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
- package/dist/sdk/governance/hierarchy-validation.js +109 -0
- package/dist/sdk/governance/reindex.js +5 -6
- package/dist/sdk/governance/validate.d.ts +2 -9
- package/dist/sdk/governance/validate.js +51 -109
- package/dist/sdk/graph/assembly.d.ts +6 -1
- package/dist/sdk/graph/assembly.js +16 -22
- package/dist/sdk/graph/governance-contracts.d.ts +1 -1
- package/dist/sdk/graph/governance-contracts.js +8 -2
- package/dist/sdk/graph/governance.d.ts +7 -5
- package/dist/sdk/graph/governance.js +76 -16
- package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
- package/dist/sdk/graph/hierarchy-integrity.js +311 -0
- package/dist/sdk/graph/index.d.ts +2 -1
- package/dist/sdk/graph/index.js +3 -2
- package/dist/sdk/graph/remediation.js +32 -2
- package/dist/sdk/graph/run.d.ts +31 -2
- package/dist/sdk/graph/run.js +83 -36
- package/dist/sdk/graph/traversal.js +14 -5
- package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
- package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
- package/dist/sdk/history-compact.js +6 -9
- package/dist/sdk/history-read.js +5 -7
- package/dist/sdk/history-redact.js +5 -6
- package/dist/sdk/history-repair.js +6 -9
- package/dist/sdk/improvement-ledger.js +7 -10
- package/dist/sdk/index.d.ts +4 -2
- package/dist/sdk/index.js +5 -3
- package/dist/sdk/item-children.js +21 -8
- package/dist/sdk/lifecycle/append.d.ts +0 -5
- package/dist/sdk/lifecycle/append.js +5 -6
- package/dist/sdk/lifecycle/claim.d.ts +0 -5
- package/dist/sdk/lifecycle/claim.js +6 -9
- package/dist/sdk/lifecycle/close-many.d.ts +0 -5
- package/dist/sdk/lifecycle/close-many.js +5 -6
- package/dist/sdk/lifecycle/close.d.ts +0 -5
- package/dist/sdk/lifecycle/close.js +5 -6
- package/dist/sdk/lifecycle/copy.d.ts +0 -5
- package/dist/sdk/lifecycle/copy.js +5 -6
- package/dist/sdk/lifecycle/create.d.ts +0 -5
- package/dist/sdk/lifecycle/create.js +127 -102
- package/dist/sdk/lifecycle/delete.js +5 -6
- package/dist/sdk/lifecycle/focus.d.ts +0 -5
- package/dist/sdk/lifecycle/focus.js +5 -6
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
- package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
- package/dist/sdk/lifecycle/plan.d.ts +0 -5
- package/dist/sdk/lifecycle/plan.js +5 -6
- package/dist/sdk/lifecycle/restore.js +5 -6
- package/dist/sdk/lifecycle/update-many.d.ts +0 -5
- package/dist/sdk/lifecycle/update-many.js +5 -6
- package/dist/sdk/lifecycle/update.d.ts +2 -5
- package/dist/sdk/lifecycle/update.js +211 -84
- package/dist/sdk/linked-artifacts.js +6 -7
- package/dist/sdk/merge/install.js +5 -6
- package/dist/sdk/mutation-events.js +5 -7
- package/dist/sdk/package-import-adapters.js +6 -8
- package/dist/sdk/profile.js +6 -7
- package/dist/sdk/query/activity.js +5 -6
- package/dist/sdk/query/calendar.js +5 -6
- package/dist/sdk/query/complete-list.d.ts +3 -3
- package/dist/sdk/query/complete-list.js +46 -3
- package/dist/sdk/query/get.d.ts +0 -5
- package/dist/sdk/query/get.js +5 -6
- package/dist/sdk/query/history.d.ts +0 -5
- package/dist/sdk/query/history.js +5 -6
- package/dist/sdk/query/list.d.ts +4 -3
- package/dist/sdk/query/list.js +92 -54
- package/dist/sdk/query/search.js +5 -7
- package/dist/sdk/read-output-contracts.d.ts +5 -1
- package/dist/sdk/read-output-contracts.js +87 -22
- package/dist/sdk/relationship-context.js +3 -4
- package/dist/sdk/relationship-kinds/contract.d.ts +8 -0
- package/dist/sdk/relationship-kinds/contract.js +13 -13
- package/dist/sdk/relationships.d.ts +1 -1
- package/dist/sdk/relationships.js +27 -2
- package/dist/sdk/runtime.d.ts +3 -2
- package/dist/sdk/runtime.js +3 -2
- package/dist/sdk/schema-migration.js +6 -7
- package/dist/sdk/schema.js +5 -6
- package/dist/sdk/stats.js +5 -8
- package/dist/sdk/templates.js +5 -6
- package/dist/sdk/test/batch.js +15 -9
- package/dist/sdk/test/execution.js +12 -5
- package/dist/sdk/test/runs.js +5 -7
- package/dist/types.d.ts +11 -0
- package/dist/types.js +2 -2
- package/docs/AGENT_UX_CONTRACTS.md +24 -1
- package/docs/COMMANDS.md +29 -14
- package/docs/DEPENDENCY_KIND_CONTRACT.md +40 -1
- package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +98 -0
- package/docs/EXTENSIONS.md +2 -1
- package/docs/README.md +1 -0
- package/docs/READ_OUTPUT_CONTRACTS.md +9 -2
- package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +37 -0
- package/docs/RELATIONSHIP_GRAPH.md +97 -12
- package/docs/SDK_PRIMITIVE_INVENTORY.md +15 -1
- package/docs/TESTING.md +15 -0
- package/marketplace.json +2 -2
- package/package.json +1 -1
- 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 +848 -56
- package/dist/cli-bundle/chunks/chunk-2RDVGYWE.js +0 -13
- package/dist/cli-bundle/chunks/chunk-BLVQHFSY.js +0 -35
- package/dist/cli-bundle/chunks/chunk-CU25EQVV.js +0 -5
- package/dist/cli-bundle/chunks/chunk-RS3IV2R6.js +0 -197
- package/dist/cli-bundle/focused-chunks/chunk-6AHG2YW7.js +0 -50
- package/dist/cli-bundle/focused-chunks/chunk-GXWQBE3T.js +0 -8
- package/dist/cli-bundle/focused-chunks/chunk-JWKEDZJI.js +0 -4
- package/dist/cli-bundle/focused-chunks/chunk-KYZ6JGPL.js +0 -155
- package/dist/cli-bundle/focused-chunks/chunk-Q47EX4DI.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-RIHDMCUM.js +0 -2
- package/dist/cli-bundle/focused-chunks/chunk-T4ZFY7ZJ.js +0 -16
- package/dist/cli-bundle/focused-chunks/chunk-Z3PLWSGM.js +0 -2
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* one deterministic SDK path.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
10
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="d4c380ce-031e-5b2d-aaa8-658bb4aa3087")}catch(e){}}();
|
|
11
11
|
import { createHash } from "node:crypto";
|
|
12
12
|
import path from "node:path";
|
|
13
13
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
@@ -34,6 +34,7 @@ export const ASSURANCE_GATE_TRIGGERS = [
|
|
|
34
34
|
export const ASSURANCE_MEASUREMENT_SOURCE_KINDS = [
|
|
35
35
|
"items",
|
|
36
36
|
"dependency_kind",
|
|
37
|
+
"prose_edge_gap",
|
|
37
38
|
"graph",
|
|
38
39
|
"validate",
|
|
39
40
|
"health",
|
|
@@ -167,6 +168,53 @@ function validateItemsMeasurementSource(source) {
|
|
|
167
168
|
throw new AssuranceMutationRefusalError("items source equals/state requires field");
|
|
168
169
|
}
|
|
169
170
|
}
|
|
171
|
+
/** Validate relationship-provenance predicates on a dependency-kind measurement. */
|
|
172
|
+
function validateDependencyKindMeasurementSource(source) {
|
|
173
|
+
if (typeof source.dependency_kind !== "string" ||
|
|
174
|
+
source.dependency_kind.trim().length === 0) {
|
|
175
|
+
throw new AssuranceMutationRefusalError("dependency_kind source requires dependency_kind");
|
|
176
|
+
}
|
|
177
|
+
const provenancePredicateCount = [
|
|
178
|
+
source.source_kind,
|
|
179
|
+
source.source_kind_prefix,
|
|
180
|
+
source.source_kind_state,
|
|
181
|
+
].filter((value) => value !== undefined).length;
|
|
182
|
+
if (provenancePredicateCount > 1) {
|
|
183
|
+
throw new AssuranceMutationRefusalError("dependency_kind source accepts at most one source_kind predicate");
|
|
184
|
+
}
|
|
185
|
+
if ((source.source_kind !== undefined &&
|
|
186
|
+
source.source_kind.trim().length === 0) ||
|
|
187
|
+
(source.source_kind_prefix !== undefined &&
|
|
188
|
+
source.source_kind_prefix.trim().length === 0)) {
|
|
189
|
+
throw new AssuranceMutationRefusalError("dependency_kind source provenance values must not be empty");
|
|
190
|
+
}
|
|
191
|
+
if (source.source_kind_state !== undefined &&
|
|
192
|
+
source.source_kind_state !== "present" &&
|
|
193
|
+
source.source_kind_state !== "missing") {
|
|
194
|
+
throw new AssuranceMutationRefusalError("dependency_kind source source_kind_state must be present or missing");
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
/** Validate bounded, reasoned prose-parity exemptions. */
|
|
198
|
+
function validateProseEdgeGapSource(source) {
|
|
199
|
+
if (source.sample_limit !== undefined &&
|
|
200
|
+
(!Number.isInteger(source.sample_limit) || source.sample_limit < 1)) {
|
|
201
|
+
throw new AssuranceMutationRefusalError("prose_edge_gap sample_limit must be a positive integer");
|
|
202
|
+
}
|
|
203
|
+
for (const exemption of source.exemptions ?? []) {
|
|
204
|
+
if (typeof exemption.holder_id !== "string" ||
|
|
205
|
+
exemption.holder_id.trim().length === 0 ||
|
|
206
|
+
typeof exemption.reason !== "string" ||
|
|
207
|
+
exemption.reason.trim().length === 0) {
|
|
208
|
+
throw new AssuranceMutationRefusalError("prose_edge_gap exemptions require holder_id and reason");
|
|
209
|
+
}
|
|
210
|
+
if ((exemption.target_id !== undefined &&
|
|
211
|
+
exemption.target_id.trim().length === 0) ||
|
|
212
|
+
(exemption.text_contains !== undefined &&
|
|
213
|
+
exemption.text_contains.trim().length === 0)) {
|
|
214
|
+
throw new AssuranceMutationRefusalError("prose_edge_gap exemption selectors must not be empty");
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
170
218
|
/** Validate and return one measurement declaration. */
|
|
171
219
|
export function validateMeasurementDefinition(definition) {
|
|
172
220
|
requireStableId(definition.id, "measurement.id");
|
|
@@ -185,11 +233,10 @@ export function validateMeasurementDefinition(definition) {
|
|
|
185
233
|
if (source.kind === "items") {
|
|
186
234
|
validateItemsMeasurementSource(source);
|
|
187
235
|
}
|
|
188
|
-
if (source.kind === "dependency_kind"
|
|
189
|
-
(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
}
|
|
236
|
+
if (source.kind === "dependency_kind")
|
|
237
|
+
validateDependencyKindMeasurementSource(source);
|
|
238
|
+
if (source.kind === "prose_edge_gap")
|
|
239
|
+
validateProseEdgeGapSource(source);
|
|
193
240
|
if ((source.kind === "graph" ||
|
|
194
241
|
source.kind === "validate" ||
|
|
195
242
|
source.kind === "health") &&
|
|
@@ -419,6 +466,24 @@ function itemsSourceResult(source, context) {
|
|
|
419
466
|
contributors: matches.map((item) => item.id),
|
|
420
467
|
};
|
|
421
468
|
}
|
|
469
|
+
/** Match one normalized dependency provenance against an optional partition. */
|
|
470
|
+
function dependencyProvenanceMatches(source, sourceKind) {
|
|
471
|
+
if (source.source_kind !== undefined) {
|
|
472
|
+
return (sourceKind?.toLowerCase() === source.source_kind.trim().toLowerCase());
|
|
473
|
+
}
|
|
474
|
+
if (source.source_kind_prefix !== undefined) {
|
|
475
|
+
return (sourceKind
|
|
476
|
+
?.toLowerCase()
|
|
477
|
+
.startsWith(source.source_kind_prefix.trim().toLowerCase()) === true);
|
|
478
|
+
}
|
|
479
|
+
if (source.source_kind_state === "present") {
|
|
480
|
+
return sourceKind !== undefined && sourceKind.length > 0;
|
|
481
|
+
}
|
|
482
|
+
if (source.source_kind_state === "missing") {
|
|
483
|
+
return sourceKind === undefined || sourceKind.length === 0;
|
|
484
|
+
}
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
422
487
|
function dependencyKindSourceResult(source, context) {
|
|
423
488
|
const contributors = [];
|
|
424
489
|
const requestedKind = resolveCanonicalRelationshipKind(source.dependency_kind) ??
|
|
@@ -427,9 +492,10 @@ function dependencyKindSourceResult(source, context) {
|
|
|
427
492
|
for (const dependency of item.dependencies ?? []) {
|
|
428
493
|
const dependencyKind = resolveCanonicalRelationshipKind(dependency.kind) ??
|
|
429
494
|
dependency.kind.trim().toLowerCase();
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
495
|
+
const sourceKind = dependency.source_kind?.trim();
|
|
496
|
+
if (dependencyKind === requestedKind &&
|
|
497
|
+
dependencyProvenanceMatches(source, sourceKind))
|
|
498
|
+
contributors.push(`${item.id}->${dependency.id}${sourceKind ? `@${sourceKind}` : ""}`);
|
|
433
499
|
}
|
|
434
500
|
}
|
|
435
501
|
return {
|
|
@@ -439,6 +505,109 @@ function dependencyKindSourceResult(source, context) {
|
|
|
439
505
|
contributors,
|
|
440
506
|
};
|
|
441
507
|
}
|
|
508
|
+
/** Return every text segment whose item identifiers form the prose graph. */
|
|
509
|
+
function assuranceItemProseSegments(item) {
|
|
510
|
+
const segments = [item.description, item.body]
|
|
511
|
+
.filter((value) => typeof value === "string")
|
|
512
|
+
.map((value) => value.trim())
|
|
513
|
+
.filter(Boolean);
|
|
514
|
+
for (const key of ["comments", "notes", "learnings"]) {
|
|
515
|
+
const entries = item[key];
|
|
516
|
+
if (!Array.isArray(entries))
|
|
517
|
+
continue;
|
|
518
|
+
for (const entry of entries) {
|
|
519
|
+
if (typeof entry === "string")
|
|
520
|
+
segments.push(entry);
|
|
521
|
+
else if (typeof entry === "object" && entry !== null) {
|
|
522
|
+
const text = Reflect.get(entry, "text");
|
|
523
|
+
if (typeof text === "string")
|
|
524
|
+
segments.push(text);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
return segments;
|
|
529
|
+
}
|
|
530
|
+
/** Return whether a reviewed exemption applies to one prose reference. */
|
|
531
|
+
function proseReferenceIsExempt(exemptions, holderId, targetId, segment) {
|
|
532
|
+
return exemptions.some((exemption) => exemption.holder_id.trim().toLowerCase() === holderId.toLowerCase() &&
|
|
533
|
+
(exemption.target_id === undefined ||
|
|
534
|
+
exemption.target_id.trim().toLowerCase() === targetId.toLowerCase()) &&
|
|
535
|
+
(exemption.text_contains === undefined ||
|
|
536
|
+
segment
|
|
537
|
+
.toLowerCase()
|
|
538
|
+
.includes(exemption.text_contains.trim().toLowerCase())));
|
|
539
|
+
}
|
|
540
|
+
/** Return the direction-independent identity of a prose or structured item pair. */
|
|
541
|
+
function prosePairKey(left, right) {
|
|
542
|
+
return [left.toLowerCase(), right.toLowerCase()].sort().join("\u0000");
|
|
543
|
+
}
|
|
544
|
+
/** Collect canonical ids, typed links, and raw prose mentions in one item pass. */
|
|
545
|
+
function collectProseEdgeCensusInputs(items) {
|
|
546
|
+
const canonicalIds = new Map();
|
|
547
|
+
const linkedPairs = new Set();
|
|
548
|
+
const proseMentions = [];
|
|
549
|
+
const mentionPattern = /\b[a-z][a-z0-9]*-[a-z0-9]+\b/giu;
|
|
550
|
+
let mentionCount = 0;
|
|
551
|
+
for (const item of items) {
|
|
552
|
+
canonicalIds.set(item.id.toLowerCase(), item.id);
|
|
553
|
+
for (const dependency of item.dependencies ?? [])
|
|
554
|
+
linkedPairs.add(prosePairKey(item.id, dependency.id));
|
|
555
|
+
for (const scalar of [item.parent, item.blocked_by])
|
|
556
|
+
if (typeof scalar === "string")
|
|
557
|
+
linkedPairs.add(prosePairKey(item.id, scalar));
|
|
558
|
+
for (const segment of assuranceItemProseSegments(item)) {
|
|
559
|
+
const mentionedIds = [...segment.matchAll(mentionPattern)].map((match) => match[0]);
|
|
560
|
+
mentionCount += mentionedIds.length;
|
|
561
|
+
proseMentions.push({
|
|
562
|
+
holder_id: item.id,
|
|
563
|
+
segment,
|
|
564
|
+
mentioned_ids: mentionedIds,
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return {
|
|
569
|
+
canonical_ids: canonicalIds,
|
|
570
|
+
linked_pairs: linkedPairs,
|
|
571
|
+
prose_mentions: proseMentions,
|
|
572
|
+
mention_count: mentionCount,
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
/** Count distinct prose-named item pairs that have no typed edge in either direction. */
|
|
576
|
+
function proseEdgeGapSourceResult(source, context) {
|
|
577
|
+
const census = collectProseEdgeCensusInputs(context.items);
|
|
578
|
+
const gaps = new Map();
|
|
579
|
+
for (const proseMention of census.prose_mentions) {
|
|
580
|
+
const mentions = proseMention.mentioned_ids
|
|
581
|
+
.map((id) => census.canonical_ids.get(id.toLowerCase()))
|
|
582
|
+
.filter((id) => id !== undefined && id !== proseMention.holder_id);
|
|
583
|
+
const distinctMentions = [...new Set(mentions)];
|
|
584
|
+
for (const targetId of distinctMentions) {
|
|
585
|
+
const key = prosePairKey(proseMention.holder_id, targetId);
|
|
586
|
+
if (census.linked_pairs.has(key) ||
|
|
587
|
+
proseReferenceIsExempt(source.exemptions ?? [], proseMention.holder_id, targetId, proseMention.segment))
|
|
588
|
+
continue;
|
|
589
|
+
const explicit = distinctMentions.some((candidate) => candidate !== targetId);
|
|
590
|
+
if (gaps.get(key)?.explicit === true && !explicit)
|
|
591
|
+
continue;
|
|
592
|
+
gaps.set(key, {
|
|
593
|
+
contributor: `${proseMention.holder_id}->${targetId}|subject=${explicit ? "explicit" : "implicit"}`,
|
|
594
|
+
explicit,
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const gapRows = [...gaps.values()];
|
|
599
|
+
const contributors = gapRows.map((entry) => entry.contributor).sort();
|
|
600
|
+
return {
|
|
601
|
+
value: contributors.length,
|
|
602
|
+
population_size: census.canonical_ids.size,
|
|
603
|
+
cost: context.items.length + census.linked_pairs.size + census.mention_count,
|
|
604
|
+
contributors: contributors.slice(0, source.sample_limit ?? 25),
|
|
605
|
+
partitions: {
|
|
606
|
+
explicit_subject: gapRows.filter((entry) => entry.explicit).length,
|
|
607
|
+
implicit_subject: gapRows.filter((entry) => !entry.explicit).length,
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
}
|
|
442
611
|
function historySourceResult(source, context) {
|
|
443
612
|
const matches = context.history.filter((entry) => (source.op === undefined || entry.op === source.op) &&
|
|
444
613
|
(source.author === undefined || entry.author === source.author) &&
|
|
@@ -471,6 +640,8 @@ function sourceResult(definition, context) {
|
|
|
471
640
|
if (source.kind === "dependency_kind") {
|
|
472
641
|
return dependencyKindSourceResult(source, context);
|
|
473
642
|
}
|
|
643
|
+
if (source.kind === "prose_edge_gap")
|
|
644
|
+
return proseEdgeGapSourceResult(source, context);
|
|
474
645
|
if (source.kind === "history")
|
|
475
646
|
return historySourceResult(source, context);
|
|
476
647
|
if (source.kind === "links")
|
|
@@ -583,6 +754,7 @@ async function evaluateMeasurementInternal(definition, context, definitions, sta
|
|
|
583
754
|
units: result.cost,
|
|
584
755
|
items_scanned: definition.source.kind === "items" ||
|
|
585
756
|
definition.source.kind === "dependency_kind" ||
|
|
757
|
+
definition.source.kind === "prose_edge_gap" ||
|
|
586
758
|
definition.source.kind === "links"
|
|
587
759
|
? context.items.length
|
|
588
760
|
: 0,
|
|
@@ -603,6 +775,7 @@ async function evaluateMeasurementInternal(definition, context, definitions, sta
|
|
|
603
775
|
population_size: result.population_size,
|
|
604
776
|
cost,
|
|
605
777
|
contributors: result.contributors ?? [],
|
|
778
|
+
...(result.partitions ? { partitions: result.partitions } : {}),
|
|
606
779
|
};
|
|
607
780
|
}
|
|
608
781
|
function evaluateMeasurementCached(definition, context, definitions, stack, state) {
|
|
@@ -670,6 +843,7 @@ export function evaluateAssuranceAssertion(definition, measurement, options = {}
|
|
|
670
843
|
negative_control_proven: proveNegativeControl(definition),
|
|
671
844
|
cost: measurement.cost,
|
|
672
845
|
contributors: measurement.contributors,
|
|
846
|
+
...(measurement.partitions ? { partitions: measurement.partitions } : {}),
|
|
673
847
|
};
|
|
674
848
|
}
|
|
675
849
|
function enforceGateProviderPolicy(gate, document, context, trigger) {
|
|
@@ -1006,4 +1180,4 @@ export async function listAssuranceVerdicts(pmRoot, options = {}) {
|
|
|
1006
1180
|
.slice(0, limit);
|
|
1007
1181
|
}
|
|
1008
1182
|
//# sourceMappingURL=assurance.js.map
|
|
1009
|
-
//# debugId=
|
|
1183
|
+
//# debugId=d4c380ce-031e-5b2d-aaa8-658bb4aa3087
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* Implements the pm gc command surface and its agent-facing runtime behavior.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="
|
|
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]="76f8405f-138d-5119-a300-f068354394a5")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
11
|
import { runCheckpointGc } from "../../core/checkpoint/checkpoint-gc.js";
|
|
@@ -15,7 +16,7 @@ import { runLockGc } from "../../core/lock/lock-gc.js";
|
|
|
15
16
|
import { EXIT_CODE } from "../../core/shared/constants.js";
|
|
16
17
|
import { PmCliError } from "../../core/shared/errors.js";
|
|
17
18
|
import { nowIso } from "../../core/shared/time.js";
|
|
18
|
-
import {
|
|
19
|
+
import { resolvePmRoot } from "../../core/store/paths.js";
|
|
19
20
|
import { readSettings } from "../../core/store/settings.js";
|
|
20
21
|
const GC_SCOPE_VALUES = [
|
|
21
22
|
"index",
|
|
@@ -234,9 +235,7 @@ function buildGcGuidance(params) {
|
|
|
234
235
|
/** Implements run gc for the public runtime surface of this module. */
|
|
235
236
|
export async function runGc(global, options = {}) {
|
|
236
237
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
237
|
-
|
|
238
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
239
|
-
}
|
|
238
|
+
await assertInitializedTracker(pmRoot);
|
|
240
239
|
const settings = await readSettings(pmRoot);
|
|
241
240
|
const dryRun = options.dryRun === true;
|
|
242
241
|
const scopes = parseScopes(options.scope);
|
|
@@ -367,4 +366,4 @@ export async function runGc(global, options = {}) {
|
|
|
367
366
|
};
|
|
368
367
|
}
|
|
369
368
|
//# sourceMappingURL=gc.js.map
|
|
370
|
-
//# debugId=
|
|
369
|
+
//# debugId=76f8405f-138d-5119-a300-f068354394a5
|
|
@@ -7,6 +7,7 @@ import { type HistoryAuthorAttributionScan } from "../author-attribution.js";
|
|
|
7
7
|
import type { PmSettings } from "../../types/index.js";
|
|
8
8
|
import { buildCapabilityContractMetadata, collectUnknownCapabilityGuidance } from "../extension/doctor.js";
|
|
9
9
|
import { type StaleInProgressScan } from "./stale-work.js";
|
|
10
|
+
import { type HierarchyIntegrityAnalysis } from "../graph/hierarchy-integrity.js";
|
|
10
11
|
type HealthStatus = "ok" | "warn";
|
|
11
12
|
type MigrationRuntimeStatus = "pending" | "failed" | "applied";
|
|
12
13
|
/** Documents the health check payload exchanged by command, SDK, and package integrations. */
|
|
@@ -145,6 +146,7 @@ declare function normalizeExtensionNameForMatch(value: string): string;
|
|
|
145
146
|
declare function isExpectedUnmanagedExtension(name: string, directory: string): boolean;
|
|
146
147
|
declare function isDirectory(targetPath: string): Promise<boolean>;
|
|
147
148
|
declare function listItemDocumentPaths(pmRoot: string, typeToFolder: Record<string, string>): Promise<string[]>;
|
|
149
|
+
declare function buildHierarchyIntegrityWarnings(analysis: HierarchyIntegrityAnalysis): string[];
|
|
148
150
|
declare function buildExtensionHealthTriageSummary(warnings: string[], loadFailureCount: number, activationFailureCount: number, migrationStatus: MigrationStatusSummary, managedStateWarningCount: number, managedExtensionEntriesCount: number, unmanagedLoadedExtensions: string[], unmanagedExpectedExtensions: string[], unmanagedActionRequiredExtensions: string[]): ExtensionHealthTriageSummary;
|
|
149
151
|
declare function summarizeRecordList(value: unknown, limit: number): {
|
|
150
152
|
count: number;
|
|
@@ -218,6 +220,7 @@ declare function projectHealthResult(result: HealthResult, options: RunHealthOpt
|
|
|
218
220
|
export declare function runHealth(global: GlobalOptions, options?: RunHealthOptions): Promise<HealthResult>;
|
|
219
221
|
/** Public contract for test only health command, shared by SDK and presentation-layer consumers. */
|
|
220
222
|
export declare const _testOnlyHealthCommand: {
|
|
223
|
+
buildHierarchyIntegrityWarnings: typeof buildHierarchyIntegrityWarnings;
|
|
221
224
|
buildExtensionHealthTriageSummary: typeof buildExtensionHealthTriageSummary;
|
|
222
225
|
buildHealthFindings: typeof buildHealthFindings;
|
|
223
226
|
buildCapabilityContractMetadata: typeof buildCapabilityContractMetadata;
|
|
@@ -4,11 +4,14 @@
|
|
|
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]="f7b3ff92-1fc7-55e9-aa76-af956714998f")}catch(e){}}();
|
|
8
8
|
import fs from "node:fs/promises";
|
|
9
9
|
import path from "node:path";
|
|
10
|
+
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
11
|
+
import { isTerminalStatus } from "../../core/item/status.js";
|
|
10
12
|
import { resolveItemTypeRegistry } from "../../core/item/type-registry.js";
|
|
11
|
-
import {
|
|
13
|
+
import { resolveRuntimeStatusRegistry } from "../../core/schema/runtime-schema.js";
|
|
14
|
+
import { isFileMissingError, readFileIfExists, } from "../../core/fs/fs-utils.js";
|
|
12
15
|
import { activateExtensions, getActiveExtensionRegistrations, loadExtensions, runActiveOnReadHooks, } from "../../core/extensions/index.js";
|
|
13
16
|
import { collectRegisteredItemFieldNames } from "../../core/extensions/item-fields.js";
|
|
14
17
|
import { KNOWN_EXTENSION_CAPABILITIES, } from "../../core/extensions/loader.js";
|
|
@@ -43,6 +46,8 @@ import { scanStaleInProgressItems, } from "./stale-work.js";
|
|
|
43
46
|
import { scanTrackedRuntimeCache } from "./tracked-runtime-cache.js";
|
|
44
47
|
import { auditMergeDriverConfiguration, findGitWorkspaceRoot, } from "../merge/install.js";
|
|
45
48
|
import { listMergeReceipts, partitionMergeReceipts, } from "../merge/receipts.js";
|
|
49
|
+
import { resolveWorkspaceRelationshipKindRegistry } from "../graph/assembly.js";
|
|
50
|
+
import { analyzeHierarchyIntegrity, } from "../graph/hierarchy-integrity.js";
|
|
46
51
|
const PM_TELEMETRY_SOURCE_CONTEXT_SET = new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);
|
|
47
52
|
const STALE_VECTORIZATION_SUMMARY_LIMIT = 25;
|
|
48
53
|
const BRIEF_HEALTH_DETAIL_LIMIT = 8;
|
|
@@ -60,6 +65,7 @@ const TELEMETRY_SERVER_MAX_SCHEMA_VERSION_HEADERS = [
|
|
|
60
65
|
function isAdvisoryHealthWarning(warning, requireMergeDrivers = false) {
|
|
61
66
|
return (warning.startsWith("telemetry_") ||
|
|
62
67
|
warning.startsWith("history_stream_over_compact_threshold:") ||
|
|
68
|
+
warning.startsWith("integrity_legacy_hierarchy_") ||
|
|
63
69
|
warning.startsWith("stale_in_progress_items:") ||
|
|
64
70
|
warning.startsWith("provenance_resolver_zero_success:") ||
|
|
65
71
|
warning.startsWith("provenance_value_domain_invalid:") ||
|
|
@@ -314,10 +320,25 @@ async function scanHistoryIntegrity(pmRoot) {
|
|
|
314
320
|
}
|
|
315
321
|
return { files, unreadable, conflictMarkers, invalidJson };
|
|
316
322
|
}
|
|
317
|
-
|
|
323
|
+
function buildHierarchyIntegrityWarnings(analysis) {
|
|
324
|
+
return [
|
|
325
|
+
...analysis.cycles.map((cycle) => cycle.legacy_terminal
|
|
326
|
+
? `integrity_legacy_hierarchy_cycle:${cycle.item_ids.join(",")}`
|
|
327
|
+
: `integrity_hierarchy_cycle:${cycle.item_ids.join(",")}`),
|
|
328
|
+
...analysis.cardinality_violations.map((finding) => finding.legacy_terminal
|
|
329
|
+
? `integrity_legacy_hierarchy_cardinality:${finding.child_id}`
|
|
330
|
+
: `integrity_hierarchy_cardinality:${finding.child_id}`),
|
|
331
|
+
...analysis.divergences.map((finding) => finding.legacy_terminal
|
|
332
|
+
? `integrity_legacy_hierarchy_divergence:${finding.child_id}`
|
|
333
|
+
: `integrity_hierarchy_divergence:${finding.child_id}`),
|
|
334
|
+
];
|
|
335
|
+
}
|
|
336
|
+
async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDrivers, items) {
|
|
318
337
|
const itemScan = await scanItemIntegrity(pmRoot, typeToFolder, schema);
|
|
319
338
|
const historyScan = await scanHistoryIntegrity(pmRoot);
|
|
320
339
|
const formatVersionScan = scanItemFormatVersions(itemScan.formatVersions);
|
|
340
|
+
const statusRegistry = resolveRuntimeStatusRegistry(schema);
|
|
341
|
+
const hierarchyIntegrity = analyzeHierarchyIntegrity(items, (status) => isTerminalStatus(status, statusRegistry), resolveWorkspaceRelationshipKindRegistry());
|
|
321
342
|
const trackedRuntimeCache = await scanTrackedRuntimeCache(pmRoot);
|
|
322
343
|
const gitWorkspaceRoot = await findGitWorkspaceRoot(pmRoot);
|
|
323
344
|
const mergeDriverAudit = gitWorkspaceRoot === null
|
|
@@ -344,6 +365,7 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
|
|
|
344
365
|
...formatVersionScan.outdated.map((entry) => `integrity_item_outdated_format_version:${entry}`),
|
|
345
366
|
/* c8 ignore stop */
|
|
346
367
|
...formatVersionScan.ahead.map((entry) => `integrity_item_ahead_format_version:${entry}`),
|
|
368
|
+
...buildHierarchyIntegrityWarnings(hierarchyIntegrity),
|
|
347
369
|
...(trackedRuntimeCache.tracked_path_count > 0
|
|
348
370
|
? [
|
|
349
371
|
`tracked_runtime_cache_files:${trackedRuntimeCache.tracked_path_count}`,
|
|
@@ -359,11 +381,12 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
|
|
|
359
381
|
: []),
|
|
360
382
|
];
|
|
361
383
|
const normalizedWarnings = [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
|
|
384
|
+
const actionableWarnings = normalizedWarnings.filter((warning) => !warning.startsWith("integrity_legacy_hierarchy_"));
|
|
362
385
|
return {
|
|
363
386
|
check: {
|
|
364
387
|
name: "integrity",
|
|
365
|
-
status:
|
|
366
|
-
ok:
|
|
388
|
+
status: actionableWarnings.length === 0 ? "ok" : "warn",
|
|
389
|
+
ok: actionableWarnings.length === 0,
|
|
367
390
|
details: {
|
|
368
391
|
checked_item_files: itemScan.paths.length,
|
|
369
392
|
checked_history_streams: historyScan.files.length,
|
|
@@ -376,6 +399,9 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
|
|
|
376
399
|
history_invalid_json: historyScan.invalidJson.length,
|
|
377
400
|
item_outdated_format_version: formatVersionScan.outdated.length,
|
|
378
401
|
item_ahead_format_version: formatVersionScan.ahead.length,
|
|
402
|
+
hierarchy_cycles: hierarchyIntegrity.cycles.length,
|
|
403
|
+
hierarchy_cardinality_violations: hierarchyIntegrity.cardinality_violations.length,
|
|
404
|
+
hierarchy_parent_divergences: hierarchyIntegrity.divergences.length,
|
|
379
405
|
tracked_runtime_cache_files: trackedRuntimeCache.tracked_path_count,
|
|
380
406
|
merge_driver_configuration: mergeDriverAudit === null || mergeDriverAudit.status === "ok"
|
|
381
407
|
? 0
|
|
@@ -389,6 +415,10 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
|
|
|
389
415
|
item_parse_failures: itemScan.parseFailures,
|
|
390
416
|
item_outdated_format_version: formatVersionScan.outdated,
|
|
391
417
|
item_ahead_format_version: formatVersionScan.ahead,
|
|
418
|
+
hierarchy_integrity: {
|
|
419
|
+
...hierarchyIntegrity,
|
|
420
|
+
relations: summarizeRecordList(hierarchyIntegrity.relations, BRIEF_HEALTH_DETAIL_LIMIT),
|
|
421
|
+
},
|
|
392
422
|
history_unreadable: historyScan.unreadable,
|
|
393
423
|
history_conflict_markers: historyScan.conflictMarkers,
|
|
394
424
|
history_invalid_json: historyScan.invalidJson,
|
|
@@ -1831,7 +1861,9 @@ function extractHistoryDriftedCount(historyDriftCheck) {
|
|
|
1831
1861
|
function buildHealthRemediationSources(params) {
|
|
1832
1862
|
return {
|
|
1833
1863
|
settings: params.normalizedSettingsReadWarnings,
|
|
1834
|
-
directories: params.directoryState.missingDirs
|
|
1864
|
+
directories: params.directoryState.missingDirs
|
|
1865
|
+
.map((dir) => `missing_directory:${dir}`)
|
|
1866
|
+
.concat(params.directoryState.hookWarnings),
|
|
1835
1867
|
settings_values: params.settingWarnings,
|
|
1836
1868
|
telemetry: params.telemetryCheck.warnings,
|
|
1837
1869
|
extensions: params.extensionCheck.warnings,
|
|
@@ -1950,10 +1982,8 @@ function projectHealthResult(result, options, summaryMode) {
|
|
|
1950
1982
|
/** Implements run health for the public runtime surface of this module. */
|
|
1951
1983
|
export async function runHealth(global, options = {}) {
|
|
1952
1984
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
1985
|
+
await assertInitializedTracker(pmRoot);
|
|
1953
1986
|
const settingsPath = getSettingsPath(pmRoot);
|
|
1954
|
-
if (!(await pathExists(settingsPath))) {
|
|
1955
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
1956
|
-
}
|
|
1957
1987
|
const { settings, warnings: settingsReadWarnings } = await readSettingsWithMetadata(pmRoot);
|
|
1958
1988
|
const normalizedSettingsReadWarnings = [...new Set(settingsReadWarnings)];
|
|
1959
1989
|
const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
|
|
@@ -2001,7 +2031,7 @@ export async function runHealth(global, options = {}) {
|
|
|
2001
2031
|
const locksCheck = await buildLocksCheck(pmRoot);
|
|
2002
2032
|
const integrityCheck = skipPolicy.skipIntegrity
|
|
2003
2033
|
? buildSkippedHealthCheck("integrity")
|
|
2004
|
-
: await buildIntegrityCheck(pmRoot, typeRegistry.type_to_folder, settings.schema, options.requireMergeDrivers === true);
|
|
2034
|
+
: await buildIntegrityCheck(pmRoot, typeRegistry.type_to_folder, settings.schema, options.requireMergeDrivers === true, items);
|
|
2005
2035
|
const historyDriftCheck = skipPolicy.skipDrift
|
|
2006
2036
|
? buildSkippedHealthCheck("history_drift")
|
|
2007
2037
|
: await buildHistoryDriftCheck(pmRoot, itemsWithBody);
|
|
@@ -2083,6 +2113,7 @@ export async function runHealth(global, options = {}) {
|
|
|
2083
2113
|
}
|
|
2084
2114
|
/** Public contract for test only health command, shared by SDK and presentation-layer consumers. */
|
|
2085
2115
|
export const _testOnlyHealthCommand = {
|
|
2116
|
+
buildHierarchyIntegrityWarnings,
|
|
2086
2117
|
buildExtensionHealthTriageSummary,
|
|
2087
2118
|
buildHealthFindings,
|
|
2088
2119
|
buildCapabilityContractMetadata,
|
|
@@ -2111,4 +2142,4 @@ export const _testOnlyHealthCommand = {
|
|
|
2111
2142
|
warningCode,
|
|
2112
2143
|
};
|
|
2113
2144
|
//# sourceMappingURL=health.js.map
|
|
2114
|
-
//# debugId=
|
|
2145
|
+
//# debugId=f7b3ff92-1fc7-55e9-aa76-af956714998f
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/governance/hierarchy-validation
|
|
3
|
+
*
|
|
4
|
+
* Adapts the shared hierarchy analyzer to validation-specific diagnostics and
|
|
5
|
+
* deterministic cycle paths without coupling the analyzer to CLI policy.
|
|
6
|
+
*/
|
|
7
|
+
import { type RuntimeStatusRegistry } from "../../core/schema/runtime-schema.js";
|
|
8
|
+
import type { RelationshipKindRegistry } from "../relationships.js";
|
|
9
|
+
import type { ValidateItem } from "./validate-item-reader.js";
|
|
10
|
+
/** Resolve one deterministic closed walk through a known cycle component. */
|
|
11
|
+
export declare function resolveLifecycleDependencyCycleSamplePath(component: string[], graph: Map<string, string[]>): string[];
|
|
12
|
+
/** Build canonical child-to-parent adjacency across every hierarchy spelling. */
|
|
13
|
+
export declare function buildLifecycleParentGraph(items: ValidateItem[], relationshipRegistry?: RelationshipKindRegistry): Map<string, string[]>;
|
|
14
|
+
/** Project shared hierarchy analysis into the validation result contract. */
|
|
15
|
+
export declare function detectLifecycleParentCycles(items: ValidateItem[], statusRegistry?: RuntimeStatusRegistry, relationshipRegistry?: RelationshipKindRegistry): {
|
|
16
|
+
cycle_count: number;
|
|
17
|
+
active_cycle_count: number;
|
|
18
|
+
legacy_cycle_count: number;
|
|
19
|
+
cycle_item_ids: string[];
|
|
20
|
+
cycle_sample_paths: string[];
|
|
21
|
+
cardinality_violation_count: number;
|
|
22
|
+
active_cardinality_violation_count: number;
|
|
23
|
+
legacy_cardinality_violation_count: number;
|
|
24
|
+
cardinality_violation_rows: string[];
|
|
25
|
+
parent_divergence_count: number;
|
|
26
|
+
active_parent_divergence_count: number;
|
|
27
|
+
legacy_parent_divergence_count: number;
|
|
28
|
+
parent_divergence_rows: string[];
|
|
29
|
+
};
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/governance/hierarchy-validation
|
|
3
|
+
*
|
|
4
|
+
* Adapts the shared hierarchy analyzer to validation-specific diagnostics and
|
|
5
|
+
* deterministic cycle paths without coupling the analyzer to CLI policy.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
!function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="77a3c404-bbcd-5a5e-80bf-cb61c45af55d")}catch(e){}}();
|
|
9
|
+
import { statusIsTerminal, } from "../../core/schema/runtime-schema.js";
|
|
10
|
+
import { resolveWorkspaceRelationshipKindRegistry } from "../graph/assembly.js";
|
|
11
|
+
import { analyzeHierarchyIntegrity } from "../graph/hierarchy-integrity.js";
|
|
12
|
+
/** Resolve one deterministic closed walk through a known cycle component. */
|
|
13
|
+
/* c8 ignore start -- fallback branches are covered by lifecycle graph integration tests */
|
|
14
|
+
export function resolveLifecycleDependencyCycleSamplePath(component, graph) {
|
|
15
|
+
const start = component[0];
|
|
16
|
+
if (component.length === 1)
|
|
17
|
+
return [start, start];
|
|
18
|
+
const componentSet = new Set(component);
|
|
19
|
+
const path = [start];
|
|
20
|
+
const visited = new Set([start]);
|
|
21
|
+
const search = (current) => {
|
|
22
|
+
for (const next of (graph.get(current) ?? []).filter((candidate) => componentSet.has(candidate))) {
|
|
23
|
+
if (next === start && path.length > 1) {
|
|
24
|
+
path.push(start);
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
if (visited.has(next))
|
|
28
|
+
continue;
|
|
29
|
+
visited.add(next);
|
|
30
|
+
path.push(next);
|
|
31
|
+
if (search(next))
|
|
32
|
+
return true;
|
|
33
|
+
path.pop();
|
|
34
|
+
visited.delete(next);
|
|
35
|
+
}
|
|
36
|
+
return false;
|
|
37
|
+
};
|
|
38
|
+
return search(start) ? [...path] : [...component, start];
|
|
39
|
+
}
|
|
40
|
+
/* c8 ignore stop */
|
|
41
|
+
/** Resolve a scalar parent spelling to the workspace's canonical identifier. */
|
|
42
|
+
function resolveCanonicalScalarParent(parent, canonicalIdByLowercase) {
|
|
43
|
+
if (typeof parent !== "string")
|
|
44
|
+
return undefined;
|
|
45
|
+
const normalized = parent.trim().toLowerCase();
|
|
46
|
+
return normalized.length > 0
|
|
47
|
+
? canonicalIdByLowercase.get(normalized)
|
|
48
|
+
: undefined;
|
|
49
|
+
}
|
|
50
|
+
/** Append dependency-backed child-to-parent adjacency for one holder. */
|
|
51
|
+
function appendDependencyHierarchyEdges(item, graph, canonicalIdByLowercase, relationshipRegistry) {
|
|
52
|
+
for (const dependency of item.dependencies ?? []) {
|
|
53
|
+
if (typeof dependency !== "object" ||
|
|
54
|
+
dependency === null ||
|
|
55
|
+
typeof dependency.id !== "string")
|
|
56
|
+
continue;
|
|
57
|
+
const definition = relationshipRegistry.resolve(dependency.kind);
|
|
58
|
+
if (!definition?.hierarchy)
|
|
59
|
+
continue;
|
|
60
|
+
const target = canonicalIdByLowercase.get(dependency.id.toLowerCase());
|
|
61
|
+
if (!target)
|
|
62
|
+
continue;
|
|
63
|
+
if (definition.hierarchyDirection === "source_parent")
|
|
64
|
+
graph.get(target).push(item.id);
|
|
65
|
+
else
|
|
66
|
+
graph.get(item.id).push(target);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** Build canonical child-to-parent adjacency across every hierarchy spelling. */
|
|
70
|
+
export function buildLifecycleParentGraph(items, relationshipRegistry = resolveWorkspaceRelationshipKindRegistry()) {
|
|
71
|
+
const canonicalIdByLowercase = new Map(items.map((item) => [item.id.toLowerCase(), item.id]));
|
|
72
|
+
const graph = new Map(items.map((item) => [item.id, []]));
|
|
73
|
+
for (const item of [...items].sort((left, right) => left.id.localeCompare(right.id))) {
|
|
74
|
+
const edges = graph.get(item.id);
|
|
75
|
+
const canonicalParentId = resolveCanonicalScalarParent(item.parent, canonicalIdByLowercase);
|
|
76
|
+
if (canonicalParentId)
|
|
77
|
+
edges.push(canonicalParentId);
|
|
78
|
+
appendDependencyHierarchyEdges(item, graph, canonicalIdByLowercase, relationshipRegistry);
|
|
79
|
+
}
|
|
80
|
+
for (const [id, edges] of graph) {
|
|
81
|
+
graph.set(id, [...new Set(edges)].sort());
|
|
82
|
+
}
|
|
83
|
+
return graph;
|
|
84
|
+
}
|
|
85
|
+
/** Project shared hierarchy analysis into the validation result contract. */
|
|
86
|
+
export function detectLifecycleParentCycles(items, statusRegistry, relationshipRegistry = resolveWorkspaceRelationshipKindRegistry()) {
|
|
87
|
+
const hierarchy = analyzeHierarchyIntegrity(items, (status) => statusRegistry
|
|
88
|
+
? statusIsTerminal(status, statusRegistry)
|
|
89
|
+
: status === "closed" || status === "canceled", relationshipRegistry);
|
|
90
|
+
const graph = buildLifecycleParentGraph(items, relationshipRegistry);
|
|
91
|
+
const cycleComponents = hierarchy.cycles.map((cycle) => cycle.item_ids);
|
|
92
|
+
return {
|
|
93
|
+
cycle_count: cycleComponents.length,
|
|
94
|
+
active_cycle_count: hierarchy.cycles.filter((cycle) => !cycle.legacy_terminal).length,
|
|
95
|
+
legacy_cycle_count: hierarchy.cycles.filter((cycle) => cycle.legacy_terminal).length,
|
|
96
|
+
cycle_item_ids: [...new Set(cycleComponents.flat())].sort(),
|
|
97
|
+
cycle_sample_paths: cycleComponents.map((component) => resolveLifecycleDependencyCycleSamplePath(component, graph).join("->")),
|
|
98
|
+
cardinality_violation_count: hierarchy.cardinality_violations.length,
|
|
99
|
+
active_cardinality_violation_count: hierarchy.cardinality_violations.filter((finding) => !finding.legacy_terminal).length,
|
|
100
|
+
legacy_cardinality_violation_count: hierarchy.cardinality_violations.filter((finding) => finding.legacy_terminal).length,
|
|
101
|
+
cardinality_violation_rows: hierarchy.cardinality_violations.map((finding) => `${finding.child_id}:${finding.parent_ids.join(",")}:${finding.legacy_terminal ? "legacy" : "active"}`),
|
|
102
|
+
parent_divergence_count: hierarchy.divergences.length,
|
|
103
|
+
active_parent_divergence_count: hierarchy.divergences.filter((finding) => !finding.legacy_terminal).length,
|
|
104
|
+
legacy_parent_divergence_count: hierarchy.divergences.filter((finding) => finding.legacy_terminal).length,
|
|
105
|
+
parent_divergence_rows: hierarchy.divergences.map((finding) => `${finding.child_id}:scalar=${finding.scalar_parent_id}:dependencies=${finding.dependency_parent_ids.join(",")}:${finding.legacy_terminal ? "legacy" : "active"}`),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=hierarchy-validation.js.map
|
|
109
|
+
//# debugId=77a3c404-bbcd-5a5e-80bf-cb61c45af55d
|
|
@@ -4,10 +4,11 @@
|
|
|
4
4
|
* Implements the pm reindex 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]="1bcd20e1-2995-56ef-8d04-f265b8282c19")}catch(e){}}();
|
|
8
|
+
import { assertInitializedTracker } from "../environment/tracker-preflight.js";
|
|
8
9
|
import fs from "node:fs/promises";
|
|
9
10
|
import path from "node:path";
|
|
10
|
-
import { toNonEmptyStringOrUndefined, getActiveExtensionRegistrations, runActiveOnIndexHooks, runActiveOnWriteHooks, collectRegisteredItemFieldNames, resolveRegisteredSearchProvider, resolveRegisteredVectorStoreAdapter,
|
|
11
|
+
import { toNonEmptyStringOrUndefined, getActiveExtensionRegistrations, runActiveOnIndexHooks, runActiveOnWriteHooks, collectRegisteredItemFieldNames, resolveRegisteredSearchProvider, resolveRegisteredVectorStoreAdapter, writeFileAtomic, resolveItemTypeRegistry, parseItemDocument, acquireLock, buildSearchCorpus, buildSemanticCorpusInput, resolveSearchCorpusFields, resolveSemanticCorpusCharacterLimit, executeEmbeddingBatchesWithRetry, readVectorizationStatusLedger, writeVectorizationStatusLedger, REINDEX_LOCK_ID, resolveEmbeddingProviders, resolveSettingsWithSemanticRuntimeDefaults, executeVectorDelete, executeVectorReset, executeVectorUpsert, resolveVectorStores, buildVectorizationEmbeddingIdentity, buildVectorizationEmbeddingMetadata, hasVectorizationEmbeddingIdentityChanged, hasVectorizationVectorDimensionChanged, inferConsistentVectorDimension, EXIT_CODE, PmCliError, nowIso, listAllDocumentCandidatesCached, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
|
|
11
12
|
const MANIFEST_PATH = "index/manifest.json";
|
|
12
13
|
const EMBEDDINGS_PATH = "search/embeddings.jsonl";
|
|
13
14
|
const EMBEDDING_MIGRATION_REINDEX_HINT = "Provider or model has changed since last index. Run pm reindex --mode semantic to rebuild.";
|
|
@@ -630,9 +631,7 @@ export async function runReindex(options, global) {
|
|
|
630
631
|
const forceFullSemantic = options.full === true;
|
|
631
632
|
emitReindexProgress(progressEnabled, `start mode=${requestedMode}`);
|
|
632
633
|
const pmRoot = resolvePmRoot(process.cwd(), global.path);
|
|
633
|
-
|
|
634
|
-
throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
|
|
635
|
-
}
|
|
634
|
+
await assertInitializedTracker(pmRoot);
|
|
636
635
|
const settings = resolveSettingsWithSemanticRuntimeDefaults(await readSettings(pmRoot)).settings;
|
|
637
636
|
let releaseReindexLock = null;
|
|
638
637
|
try {
|
|
@@ -760,4 +759,4 @@ export async function runReindex(options, global) {
|
|
|
760
759
|
}
|
|
761
760
|
}
|
|
762
761
|
//# sourceMappingURL=reindex.js.map
|
|
763
|
-
//# debugId=
|
|
762
|
+
//# debugId=1bcd20e1-2995-56ef-8d04-f265b8282c19
|