@unbrained/pm-cli 2026.8.28 → 2026.8.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +30 -0
  3. package/dist/cli-bundle/bundle-manifest.json +125 -125
  4. package/dist/cli-bundle/chunks/{chunk-E73FDIWT.js → chunk-2MKLQL2E.js} +2 -2
  5. package/dist/cli-bundle/chunks/{chunk-NTXZHRKA.js → chunk-2UETTHY6.js} +46 -46
  6. package/dist/cli-bundle/chunks/{chunk-FEVBFFCQ.js → chunk-3TEF3HM5.js} +2 -2
  7. package/dist/cli-bundle/chunks/{chunk-BY2FQ2NI.js → chunk-7SKMLSMX.js} +2 -2
  8. package/dist/cli-bundle/chunks/chunk-7X6OZEIV.js +34 -0
  9. package/dist/cli-bundle/chunks/{chunk-M7OXRQE3.js → chunk-CMIEDWAY.js} +50 -50
  10. package/dist/cli-bundle/chunks/{chunk-XWEQGHHG.js → chunk-GNWPTEBW.js} +64 -61
  11. package/dist/cli-bundle/chunks/{chunk-X2RROGZE.js → chunk-MTTKAUBX.js} +2 -2
  12. package/dist/cli-bundle/chunks/chunk-N6OR6FAR.js +13 -0
  13. package/dist/cli-bundle/chunks/{chunk-NBCBFVZI.js → chunk-TGNAA66W.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-QE6WQXFO.js → chunk-WS2GJQVG.js} +2 -2
  15. package/dist/cli-bundle/chunks/{register-list-query-J35ZPQQ5.js → register-list-query-OMKJ5ONN.js} +2 -2
  16. package/dist/cli-bundle/chunks/{register-mutation-J6XJJOGU.js → register-mutation-QBSNCOY3.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-operations-AE3JEMFT.js → register-operations-UC77FQZC.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-setup-OQERLLWE.js → register-setup-GLQ5SYV3.js} +2 -2
  19. package/dist/cli-bundle/focused-chunks/{chunk-HC7ODMH3.js → chunk-3AVAWVZA.js} +2 -2
  20. package/dist/cli-bundle/focused-chunks/chunk-3UMBF26I.js +158 -0
  21. package/dist/cli-bundle/focused-chunks/{chunk-YVVZ3LQ6.js → chunk-73EDXGYE.js} +16 -15
  22. package/dist/cli-bundle/focused-chunks/chunk-AXZ5AJAF.js +50 -0
  23. package/dist/cli-bundle/focused-chunks/{chunk-AHAM2HAU.js → chunk-G6PATS5E.js} +3 -3
  24. package/dist/cli-bundle/focused-chunks/chunk-RKOKG43G.js +2 -0
  25. package/dist/cli-bundle/focused-chunks/chunk-TDK3OCX3.js +2 -0
  26. package/dist/cli-bundle/focused-chunks/{chunk-FC2AXLB5.js → chunk-XXOWRJZ5.js} +2 -2
  27. package/dist/cli-bundle/main.js +2 -2
  28. package/dist/cli-bundle/sdk-contracts.js +1 -1
  29. package/dist/cli-bundle/sdk-core.js +31 -32
  30. package/dist/cli-bundle/sdk-governance.js +1 -1
  31. package/dist/cli-bundle/sdk-graph.js +1 -1
  32. package/dist/cli-bundle/sdk-merge.js +34 -32
  33. package/dist/cli-bundle/sdk-query.js +1 -1
  34. package/dist/cli-bundle/sdk-runtime.js +1 -1
  35. package/dist/cli-bundle/sdk-testing.js +1 -1
  36. package/dist/cli-bundle/sdk.js +8 -8
  37. package/dist/core/diagnostics/remediation.js +16 -6
  38. package/dist/core/history/drift-scan.d.ts +2 -0
  39. package/dist/core/history/drift-scan.js +72 -36
  40. package/dist/core/history/history.d.ts +3 -3
  41. package/dist/core/history/history.js +5 -5
  42. package/dist/core/history/replay.d.ts +1 -1
  43. package/dist/core/history/replay.js +50 -19
  44. package/dist/core/item/actionability.d.ts +7 -1
  45. package/dist/core/item/actionability.js +44 -11
  46. package/dist/core/item/dependency-reference.d.ts +10 -0
  47. package/dist/core/item/dependency-reference.js +21 -0
  48. package/dist/core/item/parse.d.ts +4 -0
  49. package/dist/core/item/parse.js +38 -16
  50. package/dist/core/shared/author.js +69 -17
  51. package/dist/sdk/dependency-provenance.d.ts +51 -2
  52. package/dist/sdk/dependency-provenance.js +91 -7
  53. package/dist/sdk/extension/install-sources.d.ts +1 -7
  54. package/dist/sdk/extension/install-sources.js +94 -33
  55. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +50 -14
  56. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +62 -26
  57. package/dist/sdk/governance/health.js +86 -22
  58. package/dist/sdk/governance/validate-history-drift.js +5 -2
  59. package/dist/sdk/graph/assembly.js +51 -22
  60. package/dist/sdk/history-repair.d.ts +1 -1
  61. package/dist/sdk/history-repair.js +20 -10
  62. package/dist/sdk/lifecycle/create.js +43 -19
  63. package/dist/sdk/linked-artifacts.js +21 -31
  64. package/dist/sdk/merge/reconcile.js +3 -16
  65. package/dist/sdk/query/next.d.ts +6 -0
  66. package/dist/sdk/query/next.js +7 -2
  67. package/dist/sdk/test/entry.d.ts +1 -1
  68. package/dist/sdk/test/entry.js +5 -9
  69. package/dist/sdk/test/execution.d.ts +3 -0
  70. package/dist/sdk/test/execution.js +54 -13
  71. package/docs/CONTEXT_RECOVERY_PRIMITIVES.md +67 -0
  72. package/docs/MERGE_SAFETY.md +23 -10
  73. package/docs/README.md +1 -0
  74. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +10 -4
  75. package/marketplace.json +2 -2
  76. package/package.json +8 -8
  77. package/packages/pm-beads/package.json +1 -1
  78. package/packages/pm-calendar/package.json +1 -1
  79. package/packages/pm-command-kit/package.json +1 -1
  80. package/packages/pm-digital-twin/package.json +1 -1
  81. package/packages/pm-governance-audit/package.json +1 -1
  82. package/packages/pm-guide-shell/package.json +1 -1
  83. package/packages/pm-kanban/package.json +1 -1
  84. package/packages/pm-lifecycle-hooks/package.json +1 -1
  85. package/packages/pm-linked-test-adapters/package.json +1 -1
  86. package/packages/pm-search-advanced/package.json +1 -1
  87. package/packages/pm-templates/package.json +1 -1
  88. package/packages/pm-todos/package.json +1 -1
  89. package/packages/pm-vcs/package.json +1 -1
  90. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  91. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  92. package/sdk/public-surface.json +100 -11
  93. package/dist/cli-bundle/chunks/chunk-TIQ6AMH2.js +0 -13
  94. package/dist/cli-bundle/chunks/chunk-XRVVYRRO.js +0 -35
  95. package/dist/cli-bundle/focused-chunks/chunk-4ZDRZYYJ.js +0 -50
  96. package/dist/cli-bundle/focused-chunks/chunk-XDPYBQCF.js +0 -156
  97. package/dist/cli-bundle/focused-chunks/chunk-Y5A7SJJ7.js +0 -2
  98. package/dist/cli-bundle/focused-chunks/chunk-YJLDHJOD.js +0 -2
@@ -1,6 +1,6 @@
1
1
  /** Generated partition 1 of the exhaustive error-code catalog. */
2
2
 
3
- !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]="95253070-db43-5ddd-8468-7d001bc6657b")}catch(e){}}();
3
+ !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]="0823f083-1719-5ec2-9f7e-43bd86a2a3a2")}catch(e){}}();
4
4
  export const PM_ERROR_CODE_CATALOG_PART_1 = [
5
5
  {
6
6
  code: "acceptance_criteria_mutation_conflict",
@@ -182,6 +182,18 @@ export const PM_ERROR_CODE_CATALOG_PART_1 = [
182
182
  canonical_code: "assurance_registry_invalid",
183
183
  aliases: [],
184
184
  },
185
+ {
186
+ code: "bare_comma_entry_ambiguous",
187
+ meaning: "Bare comma entry ambiguous condition.",
188
+ stability: "provisional",
189
+ exit_code: 2,
190
+ class: "usage",
191
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
192
+ sources: ["core/item/parse.ts"],
193
+ emitting_commands: ["*"],
194
+ canonical_code: "bare_comma_entry_ambiguous",
195
+ aliases: [],
196
+ },
185
197
  {
186
198
  code: "body_file_conflicts_with_body",
187
199
  meaning: "Body file conflicts with body condition.",
@@ -1211,6 +1223,18 @@ export const PM_ERROR_CODE_CATALOG_PART_1 = [
1211
1223
  canonical_code: "history_drift_unreadable_stream",
1212
1224
  aliases: ["validate_history_drift_unreadable_streams"],
1213
1225
  },
1226
+ {
1227
+ code: "history_drift_version_skew",
1228
+ meaning: "History drift version skew condition.",
1229
+ stability: "stable",
1230
+ exit_code: 1,
1231
+ class: "generic_failure",
1232
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
1233
+ sources: ["core/diagnostics/remediation.ts"],
1234
+ emitting_commands: ["*"],
1235
+ canonical_code: "history_drift_version_skew",
1236
+ aliases: ["validate_history_drift_version_skews"],
1237
+ },
1214
1238
  {
1215
1239
  code: "history_merge_conflict_markers_detected",
1216
1240
  meaning: "History merge conflict markers detected condition.",
@@ -2064,18 +2088,6 @@ export const PM_ERROR_CODE_CATALOG_PART_1 = [
2064
2088
  canonical_code: "merge_receipts_pending",
2065
2089
  aliases: [],
2066
2090
  },
2067
- {
2068
- code: "merge_reconcile_discards_require_acceptance",
2069
- meaning: "Merge reconcile discards require acceptance condition.",
2070
- stability: "provisional",
2071
- exit_code: 4,
2072
- class: "conflict",
2073
- recovery: "Inspect the structured error guidance and retry the suggested command.",
2074
- sources: ["sdk/merge/reconcile.ts"],
2075
- emitting_commands: ["*"],
2076
- canonical_code: "merge_reconcile_discards_require_acceptance",
2077
- aliases: [],
2078
- },
2079
2091
  {
2080
2092
  code: "merge_reconcile_receipt_evidence_untrusted",
2081
2093
  meaning: "Merge reconcile receipt evidence untrusted condition.",
@@ -2112,6 +2124,30 @@ export const PM_ERROR_CODE_CATALOG_PART_1 = [
2112
2124
  canonical_code: "missing_allowed_values",
2113
2125
  aliases: [],
2114
2126
  },
2127
+ {
2128
+ code: "missing_budget",
2129
+ meaning: "Missing budget condition.",
2130
+ stability: "provisional",
2131
+ exit_code: 1,
2132
+ class: "generic_failure",
2133
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
2134
+ sources: ["sdk/cli-contracts/flag-lexicon-contracts.ts"],
2135
+ emitting_commands: ["*"],
2136
+ canonical_code: "missing_budget",
2137
+ aliases: [],
2138
+ },
2139
+ {
2140
+ code: "missing_cli_flag",
2141
+ meaning: "Missing cli flag condition.",
2142
+ stability: "provisional",
2143
+ exit_code: 1,
2144
+ class: "generic_failure",
2145
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
2146
+ sources: ["sdk/cli-contracts/tool-option-contracts.ts"],
2147
+ emitting_commands: ["*"],
2148
+ canonical_code: "missing_cli_flag",
2149
+ aliases: [],
2150
+ },
2115
2151
  ];
2116
2152
  //# sourceMappingURL=generated-error-code-catalog-part-1.js.map
2117
- //# debugId=95253070-db43-5ddd-8468-7d001bc6657b
2153
+ //# debugId=0823f083-1719-5ec2-9f7e-43bd86a2a3a2
@@ -1,31 +1,7 @@
1
1
  /** Generated partition 2 of the exhaustive error-code catalog. */
2
2
 
3
- !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]="5d5ca5e6-4286-59d6-a669-29fbce3fa19f")}catch(e){}}();
3
+ !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]="015f826a-6490-56d1-8e26-131e5503d8f1")}catch(e){}}();
4
4
  export const PM_ERROR_CODE_CATALOG_PART_2 = [
5
- {
6
- code: "missing_budget",
7
- meaning: "Missing budget condition.",
8
- stability: "provisional",
9
- exit_code: 1,
10
- class: "generic_failure",
11
- recovery: "Inspect the structured error guidance and retry the suggested command.",
12
- sources: ["sdk/cli-contracts/flag-lexicon-contracts.ts"],
13
- emitting_commands: ["*"],
14
- canonical_code: "missing_budget",
15
- aliases: [],
16
- },
17
- {
18
- code: "missing_cli_flag",
19
- meaning: "Missing cli flag condition.",
20
- stability: "provisional",
21
- exit_code: 1,
22
- class: "generic_failure",
23
- recovery: "Inspect the structured error guidance and retry the suggested command.",
24
- sources: ["sdk/cli-contracts/tool-option-contracts.ts"],
25
- emitting_commands: ["*"],
26
- canonical_code: "missing_cli_flag",
27
- aliases: [],
28
- },
29
5
  {
30
6
  code: "missing_destination",
31
7
  meaning: "Missing destination condition.",
@@ -110,6 +86,18 @@ export const PM_ERROR_CODE_CATALOG_PART_2 = [
110
86
  canonical_code: "missing_parameter_alias",
111
87
  aliases: [],
112
88
  },
89
+ {
90
+ code: "missing_positive_execution_receipt",
91
+ meaning: "Missing positive execution receipt condition.",
92
+ stability: "provisional",
93
+ exit_code: 1,
94
+ class: "generic_failure",
95
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
96
+ sources: ["sdk/test/execution.ts"],
97
+ emitting_commands: ["*"],
98
+ canonical_code: "missing_positive_execution_receipt",
99
+ aliases: [],
100
+ },
113
101
  {
114
102
  code: "missing_probe",
115
103
  meaning: "Missing probe condition.",
@@ -319,6 +307,18 @@ export const PM_ERROR_CODE_CATALOG_PART_2 = [
319
307
  canonical_code: "non_refusal_exit",
320
308
  aliases: [],
321
309
  },
310
+ {
311
+ code: "npm_pack_json_shape_unsupported",
312
+ meaning: "Npm pack json shape unsupported condition.",
313
+ stability: "provisional",
314
+ exit_code: 1,
315
+ class: "generic_failure",
316
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
317
+ sources: ["sdk/extension/install-sources.ts"],
318
+ emitting_commands: ["*"],
319
+ canonical_code: "npm_pack_json_shape_unsupported",
320
+ aliases: [],
321
+ },
322
322
  {
323
323
  code: "npm_package_archive_missing",
324
324
  meaning: "Npm package archive missing condition.",
@@ -739,6 +739,30 @@ export const PM_ERROR_CODE_CATALOG_PART_2 = [
739
739
  canonical_code: "reopen_target_status_invalid",
740
740
  aliases: [],
741
741
  },
742
+ {
743
+ code: "reported_zero_passes",
744
+ meaning: "Reported zero passes condition.",
745
+ stability: "provisional",
746
+ exit_code: 1,
747
+ class: "generic_failure",
748
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
749
+ sources: ["sdk/test/execution.ts"],
750
+ emitting_commands: ["*"],
751
+ canonical_code: "reported_zero_passes",
752
+ aliases: [],
753
+ },
754
+ {
755
+ code: "reported_zero_tests",
756
+ meaning: "Reported zero tests condition.",
757
+ stability: "provisional",
758
+ exit_code: 1,
759
+ class: "generic_failure",
760
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
761
+ sources: ["sdk/test/execution.ts"],
762
+ emitting_commands: ["*"],
763
+ canonical_code: "reported_zero_tests",
764
+ aliases: [],
765
+ },
742
766
  {
743
767
  code: "reserved_item_field",
744
768
  meaning: "Reserved item field condition.",
@@ -1584,6 +1608,18 @@ export const PM_ERROR_CODE_CATALOG_PART_2 = [
1584
1608
  canonical_code: "history_drift_unreadable_stream",
1585
1609
  aliases: [],
1586
1610
  },
1611
+ {
1612
+ code: "validate_history_drift_version_skews",
1613
+ meaning: "Validate history drift version skews condition.",
1614
+ stability: "stable",
1615
+ exit_code: 1,
1616
+ class: "generic_failure",
1617
+ recovery: "Inspect the structured error guidance and retry the suggested command.",
1618
+ sources: ["core/diagnostics/remediation.ts"],
1619
+ emitting_commands: ["*"],
1620
+ canonical_code: "history_drift_version_skew",
1621
+ aliases: [],
1622
+ },
1587
1623
  {
1588
1624
  code: "validate_history_unknown_author_events",
1589
1625
  meaning: "Validate history unknown author events condition.",
@@ -2126,4 +2162,4 @@ export const PM_ERROR_CODE_CATALOG_PART_2 = [
2126
2162
  },
2127
2163
  ];
2128
2164
  //# sourceMappingURL=generated-error-code-catalog-part-2.js.map
2129
- //# debugId=5d5ca5e6-4286-59d6-a669-29fbce3fa19f
2165
+ //# debugId=015f826a-6490-56d1-8e26-131e5503d8f1
@@ -4,7 +4,7 @@
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]="652d1b49-f9d1-55a7-84b5-ff3cf57648ad")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3c68e4be-fd09-560c-9654-f270e5d7ba73")}catch(e){}}();
8
8
  import fs from "node:fs/promises";
9
9
  import path from "node:path";
10
10
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
@@ -962,20 +962,36 @@ const HEALTH_DETAIL_SUMMARIZERS = {
962
962
  skipped: details.skipped,
963
963
  };
964
964
  },
965
- history_drift: (details, limit) => ({
966
- checked_items: details.checked_items,
967
- counts: details.counts,
968
- drifted_items: summarizeStringList(details.drifted_items, limit),
969
- merge_receipt_attributed_items: summarizeStringList(details.merge_receipt_attributed_items, limit),
970
- missing_streams: summarizeStringList(details.missing_streams, limit),
971
- unreadable_streams: summarizeStringList(details.unreadable_streams, limit),
972
- hash_mismatches: summarizeStringList(details.hash_mismatches, limit),
973
- chain_mismatches: summarizeStringList(details.chain_mismatches, limit),
974
- workspace_state_mismatches: summarizeStringList(details.workspace_state_mismatches, limit),
975
- workspace_state_missing: summarizeStringList(details.workspace_state_missing, limit),
976
- workspace_state_unreadable: summarizeStringList(details.workspace_state_unreadable, limit),
977
- skipped: details.skipped,
978
- }),
965
+ history_drift: (details, limit) => {
966
+ const cacheConfirmation = typeof details.cache_confirmation === "object" &&
967
+ details.cache_confirmation !== null
968
+ ? details.cache_confirmation
969
+ : undefined;
970
+ return {
971
+ checked_items: details.checked_items,
972
+ cache_hit_verification: details.cache_hit_verification,
973
+ cache_confirmation: cacheConfirmation === undefined
974
+ ? details.cache_confirmation
975
+ : {
976
+ ...cacheConfirmation,
977
+ candidate_items: summarizeStringList(cacheConfirmation.candidate_items, limit),
978
+ confirmed_items: summarizeStringList(cacheConfirmation.confirmed_items, limit),
979
+ resolved_false_positive_items: summarizeStringList(cacheConfirmation.resolved_false_positive_items, limit),
980
+ },
981
+ counts: details.counts,
982
+ drifted_items: summarizeStringList(details.drifted_items, limit),
983
+ merge_receipt_attributed_items: summarizeStringList(details.merge_receipt_attributed_items, limit),
984
+ missing_streams: summarizeStringList(details.missing_streams, limit),
985
+ unreadable_streams: summarizeStringList(details.unreadable_streams, limit),
986
+ hash_mismatches: summarizeStringList(details.hash_mismatches, limit),
987
+ chain_mismatches: summarizeStringList(details.chain_mismatches, limit),
988
+ version_skews: summarizeStringList(details.version_skews, limit),
989
+ workspace_state_mismatches: summarizeStringList(details.workspace_state_mismatches, limit),
990
+ workspace_state_missing: summarizeStringList(details.workspace_state_missing, limit),
991
+ workspace_state_unreadable: summarizeStringList(details.workspace_state_unreadable, limit),
992
+ skipped: details.skipped,
993
+ };
994
+ },
979
995
  vectorization: (details, limit) => ({
980
996
  semantic_runtime_available: details.semantic_runtime_available,
981
997
  compatibility_mode_auto_defaults: details.compatibility_mode_auto_defaults,
@@ -1412,14 +1428,41 @@ async function buildLocksCheck(pmRoot) {
1412
1428
  warnings,
1413
1429
  };
1414
1430
  }
1415
- async function buildHistoryDriftCheck(pmRoot, items) {
1431
+ async function buildHistoryDriftCheck(params) {
1416
1432
  const cacheHitVerification = "metadata";
1417
- const { missingStreams, unreadableStreams, hashMismatches, chainMismatches, driftedItems, workspaceStateMismatches, workspaceStateMissing, workspaceStateUnreadable, } = await scanHistoryDrift(pmRoot, items, { cacheHitVerification });
1433
+ let items = params.items;
1434
+ let drift = await scanHistoryDrift(params.pmRoot, items, {
1435
+ cacheHitVerification,
1436
+ });
1437
+ const cacheConfirmationCandidates = [
1438
+ ...new Set([
1439
+ ...drift.hashMismatches,
1440
+ ...drift.chainMismatches,
1441
+ ...drift.versionSkews,
1442
+ ]),
1443
+ ].sort((left, right) => left.localeCompare(right));
1444
+ let confirmedItems = [];
1445
+ let resolvedFalsePositiveItems = [];
1446
+ if (cacheConfirmationCandidates.length > 0) {
1447
+ items = await listAllItemMetadataWithBody(params.pmRoot, params.settings.item_format, params.typeRegistry.type_to_folder, params.itemReadWarnings, params.settings.schema, { forceSourceScan: true });
1448
+ drift = await scanHistoryDrift(params.pmRoot, items);
1449
+ confirmedItems = [
1450
+ ...new Set([
1451
+ ...drift.hashMismatches,
1452
+ ...drift.chainMismatches,
1453
+ ...drift.versionSkews,
1454
+ ]),
1455
+ ].sort((left, right) => left.localeCompare(right));
1456
+ const confirmedSet = new Set(confirmedItems);
1457
+ resolvedFalsePositiveItems = cacheConfirmationCandidates.filter((id) => !confirmedSet.has(id));
1458
+ }
1459
+ const { missingStreams, unreadableStreams, hashMismatches, chainMismatches, versionSkews, driftedItems, workspaceStateMismatches, workspaceStateMissing, workspaceStateUnreadable, } = drift;
1418
1460
  const warnings = [
1419
1461
  ...missingStreams.map((id) => `history_drift_missing_stream:${id}`),
1420
1462
  ...unreadableStreams.map((id) => `history_drift_unreadable_stream:${id}`),
1421
1463
  ...hashMismatches.map((id) => `history_drift_hash_mismatch:${id}`),
1422
1464
  ...chainMismatches.map((id) => `history_drift_chain_mismatch:${id}`),
1465
+ ...versionSkews.map((id) => `history_drift_version_skew:${id}`),
1423
1466
  ...workspaceStateMismatches.map((documentPath) => `history_drift_workspace_state_mismatch:${documentPath}`),
1424
1467
  ...workspaceStateMissing.map((documentPath) => `history_drift_workspace_state_missing:${documentPath}`),
1425
1468
  ...workspaceStateUnreadable.map((documentPath) => `history_drift_workspace_state_unreadable:${documentPath}`),
@@ -1431,7 +1474,19 @@ async function buildHistoryDriftCheck(pmRoot, items) {
1431
1474
  ok: warnings.length === 0,
1432
1475
  details: {
1433
1476
  checked_items: items.length,
1434
- cache_hit_verification: cacheHitVerification,
1477
+ cache_hit_verification: cacheConfirmationCandidates.length > 0
1478
+ ? "metadata_then_content_hash"
1479
+ : cacheHitVerification,
1480
+ cache_confirmation: {
1481
+ triggered: cacheConfirmationCandidates.length > 0,
1482
+ reason: cacheConfirmationCandidates.length > 0
1483
+ ? "cached_corruption_candidate"
1484
+ : null,
1485
+ candidate_items: cacheConfirmationCandidates,
1486
+ confirmed_items: confirmedItems,
1487
+ resolved_false_positive_items: resolvedFalsePositiveItems,
1488
+ authoritative_item_source: cacheConfirmationCandidates.length > 0,
1489
+ },
1435
1490
  drifted_items: driftedItems,
1436
1491
  counts: {
1437
1492
  drifted: driftedItems.length,
@@ -1439,6 +1494,7 @@ async function buildHistoryDriftCheck(pmRoot, items) {
1439
1494
  unreadable_streams: unreadableStreams.length,
1440
1495
  hash_mismatches: hashMismatches.length,
1441
1496
  chain_mismatches: chainMismatches.length,
1497
+ version_skews: versionSkews.length,
1442
1498
  workspace_state_mismatches: workspaceStateMismatches.length,
1443
1499
  workspace_state_missing: workspaceStateMissing.length,
1444
1500
  workspace_state_unreadable: workspaceStateUnreadable.length,
@@ -1447,6 +1503,7 @@ async function buildHistoryDriftCheck(pmRoot, items) {
1447
1503
  unreadable_streams: unreadableStreams,
1448
1504
  hash_mismatches: hashMismatches,
1449
1505
  chain_mismatches: chainMismatches,
1506
+ version_skews: versionSkews,
1450
1507
  workspace_state_mismatches: workspaceStateMismatches,
1451
1508
  workspace_state_missing: workspaceStateMissing,
1452
1509
  workspace_state_unreadable: workspaceStateUnreadable,
@@ -1940,7 +1997,8 @@ function buildHealthFindings(params) {
1940
1997
  function rewriteBulkHealthRemediation(params) {
1941
1998
  if (params.check.name === "history_drift" && params.historyDriftedCount > 1) {
1942
1999
  for (const code of Object.keys(params.remediationMap)) {
1943
- if (code !== "history_drift_merge_receipt") {
2000
+ if (code !== "history_drift_merge_receipt" &&
2001
+ code !== "history_drift_version_skew") {
1944
2002
  params.remediationMap[code] = "pm history-repair --all";
1945
2003
  }
1946
2004
  }
@@ -2086,7 +2144,6 @@ export async function runHealth(global, options = {}) {
2086
2144
  itemReadWarnings,
2087
2145
  });
2088
2146
  const itemsWithBody = items;
2089
- const normalizedItemReadWarnings = [...new Set(itemReadWarnings)];
2090
2147
  const historyPolicy = skipPolicy.skipDrift
2091
2148
  ? { warnings: [] }
2092
2149
  : await enforceHistoryStreamPolicyForItems({
@@ -2119,7 +2176,14 @@ export async function runHealth(global, options = {}) {
2119
2176
  : await buildIntegrityCheck(pmRoot, typeRegistry.type_to_folder, settings.schema, options.requireMergeDrivers === true, items);
2120
2177
  const historyDriftCheck = skipPolicy.skipDrift
2121
2178
  ? buildSkippedHealthCheck("history_drift")
2122
- : await buildHistoryDriftCheck(pmRoot, itemsWithBody);
2179
+ : await buildHistoryDriftCheck({
2180
+ pmRoot,
2181
+ items: itemsWithBody,
2182
+ settings,
2183
+ typeRegistry,
2184
+ itemReadWarnings,
2185
+ });
2186
+ const normalizedItemReadWarnings = [...new Set(itemReadWarnings)];
2123
2187
  const mergeReceiptAttributedHistoryDriftItems = await correlateMergeReceiptHistoryDriftItems({
2124
2188
  gitWorkspaceRoot: integrityCheck.gitWorkspaceRoot,
2125
2189
  pendingMergeReceipts: integrityCheck.pendingMergeReceipts,
@@ -2234,4 +2298,4 @@ export const _testOnlyHealthCommand = {
2234
2298
  warningCode,
2235
2299
  };
2236
2300
  //# sourceMappingURL=health.js.map
2237
- //# debugId=652d1b49-f9d1-55a7-84b5-ff3cf57648ad
2301
+ //# debugId=3c68e4be-fd09-560c-9654-f270e5d7ba73
@@ -6,7 +6,7 @@
6
6
  * orchestration module.
7
7
  */
8
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){}}();
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]="8bec3c39-b871-5c7c-907c-6da66274d9be")}catch(e){}}();
10
10
  import { scanHistoryDrift } from "../../core/history/drift-scan.js";
11
11
  const DEFAULT_DIAGNOSTIC_LIMIT = 5;
12
12
  /** Build the validation warning and bounded evidence projection for history drift. */
@@ -17,6 +17,7 @@ export async function buildValidateHistoryDriftCheck(pmRoot, items, verboseDiagn
17
17
  ["validate_history_drift_unreadable_streams", drift.unreadableStreams.length],
18
18
  ["validate_history_drift_hash_mismatches", drift.hashMismatches.length],
19
19
  ["validate_history_drift_chain_mismatches", drift.chainMismatches.length],
20
+ ["validate_history_drift_version_skews", drift.versionSkews.length],
20
21
  [
21
22
  "validate_history_drift_workspace_state_mismatches",
22
23
  drift.workspaceStateMismatches.length,
@@ -52,6 +53,7 @@ export async function buildValidateHistoryDriftCheck(pmRoot, items, verboseDiagn
52
53
  unreadable_streams: drift.unreadableStreams.length,
53
54
  hash_mismatches: drift.hashMismatches.length,
54
55
  chain_mismatches: drift.chainMismatches.length,
56
+ version_skews: drift.versionSkews.length,
55
57
  workspace_state_mismatches: drift.workspaceStateMismatches.length,
56
58
  workspace_state_missing: drift.workspaceStateMissing.length,
57
59
  workspace_state_unreadable: drift.workspaceStateUnreadable.length,
@@ -59,10 +61,11 @@ export async function buildValidateHistoryDriftCheck(pmRoot, items, verboseDiagn
59
61
  workspace_state_mismatches: drift.workspaceStateMismatches,
60
62
  workspace_state_missing: drift.workspaceStateMissing,
61
63
  workspace_state_unreadable: drift.workspaceStateUnreadable,
64
+ version_skews: drift.versionSkews.slice(0, diagnosticLimit),
62
65
  },
63
66
  },
64
67
  warnings,
65
68
  };
66
69
  }
67
70
  //# sourceMappingURL=validate-history-drift.js.map
68
- //# debugId=a1261d65-222c-5c6c-8634-a4413a91aba9
71
+ //# debugId=8bec3c39-b871-5c7c-907c-6da66274d9be
@@ -1,7 +1,7 @@
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]="9a6974b3-63d7-5dc7-8329-0f15f0dc83ec")}catch(e){}}();
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]="e04a91fa-4625-50fd-9bfd-c712126baf0d")}catch(e){}}();
3
3
  import { RelationshipGraph, } from "../relationships.js";
4
- import { isExternalDependencySourceKind } from "../dependency-provenance.js";
4
+ import { isExternalDependencyReference, isExternalDependencySourceKind, } from "../dependency-provenance.js";
5
5
  import { analyzeHierarchyIntegrity, } from "./hierarchy-integrity.js";
6
6
  import { resolveWorkspaceRelationshipKindRegistry } from "./workspace-relationship-kind-registry.js";
7
7
  export { resolveWorkspaceRelationshipKindRegistry } from "./workspace-relationship-kind-registry.js";
@@ -22,6 +22,25 @@ export function normalizeDependencyGraphTarget(target) {
22
22
  ? undefined
23
23
  : normalized;
24
24
  }
25
+ /** Return whether edge provenance assigns a normalized target to the external graph namespace. */
26
+ function isExternalGraphReference(target, sourceKind, externalAllowed = true) {
27
+ const normalized = normalizeDependencyReferenceTarget(target);
28
+ return (externalAllowed &&
29
+ (isExternalDependencySourceKind(sourceKind) ||
30
+ (normalized !== undefined && isExternalDependencyReference(normalized))));
31
+ }
32
+ /** Build a namespace-aware reference identity: local ids are case-folded while external locators retain case. */
33
+ function dependencyReferenceIdentityKey(target, sourceKind) {
34
+ return isExternalGraphReference(target, sourceKind)
35
+ ? `external\u0000${target}`
36
+ : `local\u0000${target.toLowerCase()}`;
37
+ }
38
+ /** Resolve one normalized edge target through the namespace selected by its provenance. */
39
+ function resolveGraphReferenceTarget(target, sourceKind, canonicalIds, externalGraphIds) {
40
+ return isExternalGraphReference(target, sourceKind)
41
+ ? externalGraphIds.get(target)
42
+ : canonicalIds.get(target.toLowerCase());
43
+ }
25
44
  /** Compare text case-insensitively with an exact-spelling deterministic tie-breaker. */
26
45
  function compareCaseFoldedText(left, right) {
27
46
  const normalizedLeft = left.toLowerCase();
@@ -45,7 +64,7 @@ function countDependencyRowIdentities(item) {
45
64
  const kind = typeof legacyDependency.kind === "string"
46
65
  ? legacyDependency.kind
47
66
  : "related";
48
- const key = `${kind}\u0000${target.toLowerCase()}`;
67
+ const key = `${kind}\u0000${dependencyReferenceIdentityKey(target, legacyDependency.source_kind)}`;
49
68
  const existing = occurrences.get(key);
50
69
  if (existing)
51
70
  existing.count += 1;
@@ -94,7 +113,9 @@ function decodeOrderingStorageContradiction(item, blocker, dependency, isTermina
94
113
  if (typeof dependency !== "object" || dependency === null)
95
114
  return undefined;
96
115
  const target = normalizeDependencyReferenceTarget(dependency.id);
97
- if (!target || target.toLowerCase() !== blocker.toLowerCase())
116
+ if (!target ||
117
+ dependencyReferenceIdentityKey(target, dependency.source_kind) !==
118
+ dependencyReferenceIdentityKey(blocker))
98
119
  return undefined;
99
120
  const definition = registry.resolve(typeof dependency.kind === "string" ? dependency.kind : "related");
100
121
  if (definition?.ordering !== true ||
@@ -151,9 +172,11 @@ export function collectDanglingDependencyReferences(items, isTerminal = (status)
151
172
  const safeItems = items.filter((item) => typeof item?.id === "string" && item.id.trim().length > 0);
152
173
  const knownIds = new Set(safeItems.map((item) => item.id.trim().toLowerCase()));
153
174
  const rows = new Map();
154
- const addReference = (item, target, kind, source) => {
175
+ const addReference = (item, target, kind, source, externalAllowed) => {
155
176
  const normalized = normalizeDependencyReferenceTarget(target);
156
- if (!normalized || knownIds.has(normalized.toLowerCase())) {
177
+ if (!normalized ||
178
+ knownIds.has(normalized.toLowerCase()) ||
179
+ isExternalGraphReference(normalized, undefined, externalAllowed)) {
157
180
  return;
158
181
  }
159
182
  const row = {
@@ -168,8 +191,8 @@ export function collectDanglingDependencyReferences(items, isTerminal = (status)
168
191
  rows.set(`${row.holder_id}::${row.target_id}::${row.kind}::${row.source}`, row);
169
192
  };
170
193
  for (const item of safeItems) {
171
- addReference(item, item.parent, "parent", "parent");
172
- addReference(item, item.blocked_by, "blocked_by", "blocked_by");
194
+ addReference(item, item.parent, "parent", "parent", false);
195
+ addReference(item, item.blocked_by, "blocked_by", "blocked_by", true);
173
196
  for (const dependency of item.dependencies ?? []) {
174
197
  // Public SDK callers may supply legacy or JSON-decoded payloads that do
175
198
  // not yet satisfy the current structured dependency contract.
@@ -182,7 +205,7 @@ export function collectDanglingDependencyReferences(items, isTerminal = (status)
182
205
  }
183
206
  addReference(item, legacyDependency.id, typeof legacyDependency.kind === "string"
184
207
  ? legacyDependency.kind
185
- : "related", "dependency");
208
+ : "related", "dependency", true);
186
209
  }
187
210
  }
188
211
  const sorted = [...rows.values()].sort((left, right) => left.holder_id.localeCompare(right.holder_id) ||
@@ -213,15 +236,21 @@ export function collectMissingDependencyTargetIds(dangling) {
213
236
  export function collectExternalDependencyTargetIds(items) {
214
237
  const targets = new Map();
215
238
  for (const item of items) {
239
+ const scalarBlocker = normalizeDependencyGraphTarget(item.blocked_by);
240
+ if (scalarBlocker &&
241
+ isExternalGraphReference(scalarBlocker) &&
242
+ !targets.has(scalarBlocker)) {
243
+ targets.set(scalarBlocker, scalarBlocker);
244
+ }
216
245
  for (const dependency of item.dependencies ?? []) {
217
246
  if (typeof dependency !== "object" ||
218
247
  dependency === null ||
219
- !isExternalDependencySourceKind(dependency.source_kind)) {
248
+ !isExternalGraphReference(dependency.id, dependency.source_kind)) {
220
249
  continue;
221
250
  }
222
- const id = normalizeDependencyReferenceTarget(dependency.id);
223
- if (id && !targets.has(id.toLowerCase())) {
224
- targets.set(id.toLowerCase(), id);
251
+ const id = normalizeDependencyGraphTarget(dependency.id);
252
+ if (id && !targets.has(id)) {
253
+ targets.set(id, id);
225
254
  }
226
255
  }
227
256
  }
@@ -230,7 +259,7 @@ export function collectExternalDependencyTargetIds(items) {
230
259
  const hierarchyIntegrityByAssembly = new WeakMap();
231
260
  /** Read the hierarchy analysis paired with an assembly created by this module. */
232
261
  export function getWorkspaceHierarchyIntegrity(assembly) {
233
- return assembly.hierarchyIntegrity ?? hierarchyIntegrityByAssembly.get(assembly);
262
+ return (assembly.hierarchyIntegrity ?? hierarchyIntegrityByAssembly.get(assembly));
234
263
  }
235
264
  /** Count raw dependency rows that use a registered compatibility alias instead of its canonical kind. */
236
265
  export function collectLegacyDependencyAliasCounts(items, registry = resolveWorkspaceRelationshipKindRegistry()) {
@@ -274,7 +303,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
274
303
  while (usedGraphIds.has(graphId.toLowerCase())) {
275
304
  graphId = `external:${graphId}`;
276
305
  }
277
- externalGraphIds.set(id.toLowerCase(), graphId);
306
+ externalGraphIds.set(id, graphId);
278
307
  usedGraphIds.add(graphId.toLowerCase());
279
308
  }
280
309
  const graphItems = safeItems.map((item) => {
@@ -287,9 +316,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
287
316
  const target = normalizeDependencyGraphTarget(dependency.id);
288
317
  if (!target)
289
318
  return [];
290
- const targetId = isExternalDependencySourceKind(dependency.source_kind)
291
- ? externalGraphIds.get(target.toLowerCase())
292
- : canonicalIds.get(target.toLowerCase());
319
+ const targetId = resolveGraphReferenceTarget(target, dependency.source_kind, canonicalIds, externalGraphIds);
293
320
  return [
294
321
  {
295
322
  id: targetId,
@@ -301,7 +328,9 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
301
328
  id: item.id.trim(),
302
329
  ...(parent ? { parent: canonicalIds.get(parent.toLowerCase()) } : {}),
303
330
  ...(blocker
304
- ? { blocked_by: canonicalIds.get(blocker.toLowerCase()) }
331
+ ? {
332
+ blocked_by: resolveGraphReferenceTarget(blocker, undefined, canonicalIds, externalGraphIds),
333
+ }
305
334
  : {}),
306
335
  dependencies,
307
336
  };
@@ -312,7 +341,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
312
341
  ...graphItems,
313
342
  ...missingIds.map((id) => ({ id })),
314
343
  ...externalIds.map((id) => ({
315
- id: externalGraphIds.get(id.toLowerCase()),
344
+ id: externalGraphIds.get(id),
316
345
  })),
317
346
  ], relationshipRegistry),
318
347
  details: [
@@ -330,7 +359,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
330
359
  status: "missing",
331
360
  })),
332
361
  ...externalIds.map((id) => ({
333
- id: externalGraphIds.get(id.toLowerCase()),
362
+ id: externalGraphIds.get(id),
334
363
  title: `[external] ${id}`,
335
364
  status: "external",
336
365
  })),
@@ -346,4 +375,4 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
346
375
  return assembly;
347
376
  }
348
377
  //# sourceMappingURL=assembly.js.map
349
- //# debugId=9a6974b3-63d7-5dc7-8329-0f15f0dc83ec
378
+ //# debugId=e04a91fa-4625-50fd-9bfd-c712126baf0d
@@ -83,7 +83,7 @@ export interface MergeReceiptProofResult {
83
83
  /** Whether exact receipt identity, path, field, and value-hash evidence proves the snapshot. */
84
84
  trusted: boolean;
85
85
  /** Stable explanation for the trust decision. */
86
- reason: "trusted_clone_local_driver_evidence" | "git_workspace_unavailable" | "item_path_unavailable" | "no_item_receipts" | "no_receipt_set_proves_snapshot";
86
+ reason: "trusted_merge_driver_hash_evidence" | "git_workspace_unavailable" | "item_path_unavailable" | "no_item_receipts" | "no_receipt_set_proves_snapshot";
87
87
  /** Exact receipt identities accepted as proof; empty when proof is refused. */
88
88
  receipt_ids: string[];
89
89
  }