@unbrained/pm-cli 2026.8.23 → 2026.8.25

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 (172) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +27 -1
  3. package/dist/cli/description-stdin.js +5 -4
  4. package/dist/cli/extension-command-help.d.ts +5 -0
  5. package/dist/cli/extension-command-help.js +6 -2
  6. package/dist/cli/help-content.d.ts +5 -0
  7. package/dist/cli/help-content.js +56 -3
  8. package/dist/cli/help-json-payload.d.ts +5 -2
  9. package/dist/cli/help-json-payload.js +57 -17
  10. package/dist/cli/main.d.ts +3 -0
  11. package/dist/cli/main.js +28 -3
  12. package/dist/cli/register-annotations.js +5 -5
  13. package/dist/cli/register-mutation.js +73 -27
  14. package/dist/cli-bundle/bundle-manifest.json +152 -152
  15. package/dist/cli-bundle/chunks/{chunk-HWZ6CELB.js → chunk-244MI4GS.js} +3 -3
  16. package/dist/cli-bundle/chunks/{chunk-QDVHNHAQ.js → chunk-2F3LUFMW.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-EG6CLDZT.js → chunk-5I5RWIJC.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-KPH73XXJ.js → chunk-65MHLHAA.js} +2 -2
  19. package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +13 -0
  20. package/dist/cli-bundle/chunks/chunk-OWHNAR2B.js +2 -0
  21. package/dist/cli-bundle/chunks/chunk-QKGMHGEI.js +202 -0
  22. package/dist/cli-bundle/chunks/chunk-QLUORNIB.js +2092 -0
  23. package/dist/cli-bundle/chunks/{chunk-JB4KZWBF.js → chunk-T2ENPRXF.js} +2 -2
  24. package/dist/cli-bundle/chunks/{chunk-F3AI2JFL.js → chunk-TPQIBSL2.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +35 -0
  26. package/dist/cli-bundle/chunks/{register-list-query-UJB5FMV2.js → register-list-query-XVN2ZLI7.js} +2 -2
  27. package/dist/cli-bundle/chunks/register-mutation-QCKAEGIJ.js +20 -0
  28. package/dist/cli-bundle/chunks/{register-operations-RXIJIYXC.js → register-operations-SDEAXE7E.js} +2 -2
  29. package/dist/cli-bundle/chunks/{register-setup-GFUZEKRE.js → register-setup-LXVBRCJ3.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-QGFNI65N.js → chunk-2UIWOP3O.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +50 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-OGLQBL46.js → chunk-7I23XGWO.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-7YCDTCBC.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/{chunk-OFVUGTLJ.js → chunk-A644DUFQ.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-AUFH5H35.js → chunk-GQR3WH3F.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-3UPTYG44.js → chunk-H5JZEIQV.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/chunk-IBZZZGK3.js +2 -0
  38. package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +5 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-LYVSW5VM.js → chunk-N7W67YIG.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-37Z4OEAP.js → chunk-NOOZGIXP.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-FZS4H32O.js → chunk-OHIHZ7HS.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-ONYQCALA.js +19 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-OVJL6NZE.js +4 -0
  44. package/dist/cli-bundle/focused-chunks/chunk-RAFKLNZX.js +16 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-IFLWKY2R.js → chunk-VXWATRFL.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-R27IDGHD.js → chunk-XUQPEKRN.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-JOWDB2MH.js → chunk-YO3ZF3FI.js} +2 -2
  48. package/dist/cli-bundle/main.js +18 -17
  49. package/dist/cli-bundle/sdk-authoring.js +1 -1
  50. package/dist/cli-bundle/sdk-contracts.js +2 -2
  51. package/dist/cli-bundle/sdk-core.js +32 -32
  52. package/dist/cli-bundle/sdk-governance.js +1 -1
  53. package/dist/cli-bundle/sdk-graph.js +1 -1
  54. package/dist/cli-bundle/sdk-merge.js +32 -33
  55. package/dist/cli-bundle/sdk-query.js +1 -1
  56. package/dist/cli-bundle/sdk-runtime.js +1 -1
  57. package/dist/cli-bundle/sdk-testing.js +1 -1
  58. package/dist/cli-bundle/sdk.js +6 -5
  59. package/dist/core/diagnostics/remediation.js +17 -2
  60. package/dist/core/extensions/command-metadata-contract.d.ts +10 -0
  61. package/dist/core/extensions/command-metadata-contract.js +23 -0
  62. package/dist/core/extensions/command-visibility-tier.js +12 -2
  63. package/dist/core/extensions/extension-types.d.ts +6 -0
  64. package/dist/core/extensions/extension-types.js +2 -2
  65. package/dist/core/extensions/loader.js +4 -3
  66. package/dist/core/io/body-file.js +7 -2
  67. package/dist/core/io/bulk-ids-input.d.ts +24 -0
  68. package/dist/core/io/bulk-ids-input.js +113 -0
  69. package/dist/core/item/parse.d.ts +22 -2
  70. package/dist/core/item/parse.js +97 -4
  71. package/dist/mcp/server.d.ts +3 -2
  72. package/dist/mcp/server.js +16 -9
  73. package/dist/sdk/agent/refusal-closure-census.d.ts +66 -0
  74. package/dist/sdk/agent/refusal-closure-census.js +144 -0
  75. package/dist/sdk/agent-capability-contracts.d.ts +34 -1
  76. package/dist/sdk/agent-capability-contracts.js +104 -6
  77. package/dist/sdk/annotations.d.ts +2 -0
  78. package/dist/sdk/annotations.js +25 -7
  79. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +10 -0
  80. package/dist/sdk/cli-contracts/runtime-contracts.js +20 -3
  81. package/dist/sdk/cli-contracts/tool-parameter-tables.js +38 -2
  82. package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +4 -1
  83. package/dist/sdk/cli-contracts/typed-action-inputs.js +2 -2
  84. package/dist/sdk/comments.js +15 -7
  85. package/dist/sdk/flag-invocation-contracts.d.ts +2 -0
  86. package/dist/sdk/flag-invocation-contracts.js +28 -3
  87. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +109 -52
  88. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +62 -2
  89. package/dist/sdk/governance/health.js +98 -11
  90. package/dist/sdk/governance/validate.js +15 -9
  91. package/dist/sdk/guide-topics.d.ts +0 -5
  92. package/dist/sdk/guide-topics.js +28 -2
  93. package/dist/sdk/history-compact.d.ts +2 -1
  94. package/dist/sdk/history-compact.js +24 -5
  95. package/dist/sdk/history-mcp.js +11 -10
  96. package/dist/sdk/history-repair.d.ts +24 -0
  97. package/dist/sdk/history-repair.js +145 -4
  98. package/dist/sdk/index.d.ts +1 -0
  99. package/dist/sdk/index.js +3 -2
  100. package/dist/sdk/item-transaction.js +19 -12
  101. package/dist/sdk/lifecycle/append.js +4 -4
  102. package/dist/sdk/lifecycle/close-many.js +16 -7
  103. package/dist/sdk/lifecycle/create.js +29 -21
  104. package/dist/sdk/lifecycle/plan.js +24 -6
  105. package/dist/sdk/lifecycle/update-many.js +15 -8
  106. package/dist/sdk/lifecycle/update.d.ts +2 -0
  107. package/dist/sdk/lifecycle/update.js +34 -24
  108. package/dist/sdk/merge/driver.js +25 -4
  109. package/dist/sdk/merge/receipt-file-boundary.d.ts +21 -0
  110. package/dist/sdk/merge/receipt-file-boundary.js +47 -0
  111. package/dist/sdk/merge/receipts.d.ts +24 -1
  112. package/dist/sdk/merge/receipts.js +342 -36
  113. package/dist/sdk/merge/reconcile.js +117 -47
  114. package/dist/sdk/read-output/continuation.d.ts +15 -2
  115. package/dist/sdk/read-output/continuation.js +86 -6
  116. package/dist/sdk/read-output-contracts.d.ts +4 -1
  117. package/dist/sdk/read-output-contracts.js +9 -6
  118. package/dist/sdk/runtime-extended-actions.js +5 -3
  119. package/dist/sdk/runtime-input.d.ts +4 -0
  120. package/dist/sdk/runtime-input.js +98 -23
  121. package/dist/sdk/runtime-primitives.d.ts +2 -1
  122. package/dist/sdk/runtime-primitives.js +4 -3
  123. package/dist/sdk/runtime.js +7 -20
  124. package/dist/sdk/scheduling-shortcuts.js +5 -3
  125. package/dist/sdk/structured-mutations.js +10 -3
  126. package/dist/sdk/workspace-contracts.d.ts +3 -0
  127. package/dist/sdk/workspace-contracts.js +3 -2
  128. package/docs/MERGE_SAFETY.md +34 -5
  129. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +13 -1
  130. package/docs/README.md +2 -0
  131. package/docs/READ_OUTPUT_CONTRACTS.md +25 -2
  132. package/docs/RELEASING.md +40 -21
  133. package/docs/SCRIPTING.md +62 -3
  134. package/docs/SDK.md +8 -0
  135. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +17 -0
  136. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
  137. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +359 -0
  138. package/marketplace.json +2 -2
  139. package/package.json +1 -1
  140. package/packages/pm-beads/package.json +1 -1
  141. package/packages/pm-calendar/package.json +1 -1
  142. package/packages/pm-command-kit/README.md +9 -11
  143. package/packages/pm-command-kit/extensions/command-kit/index.ts +3 -1
  144. package/packages/pm-command-kit/package.json +1 -1
  145. package/packages/pm-digital-twin/package.json +1 -1
  146. package/packages/pm-governance-audit/package.json +1 -1
  147. package/packages/pm-guide-shell/extensions/guide-shell/index.ts +10 -0
  148. package/packages/pm-guide-shell/package.json +1 -1
  149. package/packages/pm-kanban/package.json +1 -1
  150. package/packages/pm-lifecycle-hooks/package.json +1 -1
  151. package/packages/pm-linked-test-adapters/package.json +1 -1
  152. package/packages/pm-search-advanced/package.json +1 -1
  153. package/packages/pm-templates/package.json +1 -1
  154. package/packages/pm-todos/package.json +1 -1
  155. package/packages/pm-vcs/package.json +1 -1
  156. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  157. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  158. package/scripts/generate-agent-capability-surfaces.mjs +27 -1
  159. package/sdk/public-surface.json +351 -26
  160. package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +0 -36
  161. package/dist/cli-bundle/chunks/chunk-DW2CGEMU.js +0 -2
  162. package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +0 -201
  163. package/dist/cli-bundle/chunks/chunk-KXPMB2YL.js +0 -2092
  164. package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +0 -13
  165. package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +0 -20
  166. package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +0 -16
  167. package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +0 -2
  168. package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +0 -4
  169. package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +0 -2
  170. package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +0 -51
  171. package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +0 -5
  172. package/dist/cli-bundle/focused-chunks/chunk-ZHVA42R5.js +0 -18
@@ -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]="f7b3ff92-1fc7-55e9-aa76-af956714998f")}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]="5887be76-3d1d-56fb-9cae-cf972f0b73f8")}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";
@@ -45,7 +45,8 @@ import { buildCapabilityContractMetadata, buildRegistrationCollisionRemediation,
45
45
  import { scanStaleInProgressItems, } from "./stale-work.js";
46
46
  import { scanTrackedRuntimeCache } from "./tracked-runtime-cache.js";
47
47
  import { auditMergeDriverConfiguration, findGitWorkspaceRoot, } from "../merge/install.js";
48
- import { listMergeReceipts, partitionMergeReceipts, } from "../merge/receipts.js";
48
+ import { inspectMergeReceiptEvidence, partitionMergeReceipts, } from "../merge/receipts.js";
49
+ import { runHistoryRepair } from "../history-repair.js";
49
50
  import { resolveWorkspaceRelationshipKindRegistry } from "../graph/assembly.js";
50
51
  import { analyzeHierarchyIntegrity, } from "../graph/hierarchy-integrity.js";
51
52
  const PM_TELEMETRY_SOURCE_CONTEXT_SET = new Set(PM_TELEMETRY_SOURCE_CONTEXT_VALUES);
@@ -333,6 +334,11 @@ function buildHierarchyIntegrityWarnings(analysis) {
333
334
  : `integrity_hierarchy_divergence:${finding.child_id}`),
334
335
  ];
335
336
  }
337
+ function buildMergeReceiptEvidenceWarnings(invalidEvidenceCount) {
338
+ return invalidEvidenceCount === 0
339
+ ? []
340
+ : [`merge_receipt_evidence_invalid:${invalidEvidenceCount}`];
341
+ }
336
342
  async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDrivers, items) {
337
343
  const itemScan = await scanItemIntegrity(pmRoot, typeToFolder, schema);
338
344
  const historyScan = await scanHistoryIntegrity(pmRoot);
@@ -344,12 +350,11 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
344
350
  const mergeDriverAudit = gitWorkspaceRoot === null
345
351
  ? null
346
352
  : await auditMergeDriverConfiguration(gitWorkspaceRoot);
347
- const pendingMergeReceipts = gitWorkspaceRoot === null
348
- ? []
349
- : await listMergeReceipts(gitWorkspaceRoot, {
350
- includeLossless: true,
351
- pmRoot,
352
- });
353
+ const mergeReceiptEvidence = await inspectMergeReceiptEvidence(gitWorkspaceRoot ?? pmRoot, {
354
+ includeLossless: true,
355
+ pmRoot,
356
+ });
357
+ const pendingMergeReceipts = mergeReceiptEvidence.receipts;
353
358
  const { pendingDecisions: pendingMergeDecisions, lossless: losslessMergeReceipts, } = partitionMergeReceipts(pendingMergeReceipts);
354
359
  const mergeDriverInstallationMissing = mergeDriverAudit?.status === "missing" &&
355
360
  mergeDriverAudit.missing_keys.length === 5 &&
@@ -379,6 +384,10 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
379
384
  ...(pendingMergeDecisions.length > 0
380
385
  ? [`merge_decisions_unreviewed:${pendingMergeDecisions.length}`]
381
386
  : []),
387
+ ...(losslessMergeReceipts.length > 0
388
+ ? [`merge_receipts_pending:${losslessMergeReceipts.length}`]
389
+ : []),
390
+ ...buildMergeReceiptEvidenceWarnings(mergeReceiptEvidence.invalid_evidence_count),
382
391
  ];
383
392
  const normalizedWarnings = [...new Set(warnings)].sort((left, right) => left.localeCompare(right));
384
393
  const actionableWarnings = normalizedWarnings.filter((warning) => !warning.startsWith("integrity_legacy_hierarchy_"));
@@ -409,6 +418,7 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
409
418
  mergeDriverAudit.drifted_keys.length,
410
419
  pending_merge_decisions: pendingMergeDecisions.length,
411
420
  lossless_merge_receipts: losslessMergeReceipts.length,
421
+ invalid_merge_receipt_evidence: mergeReceiptEvidence.invalid_evidence_count,
412
422
  },
413
423
  item_unreadable: itemScan.unreadable,
414
424
  item_conflict_markers: itemScan.conflictMarkers,
@@ -443,6 +453,8 @@ async function buildIntegrityCheck(pmRoot, typeToFolder, schema, requireMergeDri
443
453
  },
444
454
  },
445
455
  warnings: normalizedWarnings,
456
+ gitWorkspaceRoot,
457
+ pendingMergeReceipts,
446
458
  };
447
459
  }
448
460
  /* c8 ignore start -- activate export shape variants are exercised through integration load tests */
@@ -949,6 +961,7 @@ const HEALTH_DETAIL_SUMMARIZERS = {
949
961
  checked_items: details.checked_items,
950
962
  counts: details.counts,
951
963
  drifted_items: summarizeStringList(details.drifted_items, limit),
964
+ merge_receipt_attributed_items: summarizeStringList(details.merge_receipt_attributed_items, limit),
952
965
  missing_streams: summarizeStringList(details.missing_streams, limit),
953
966
  unreadable_streams: summarizeStringList(details.unreadable_streams, limit),
954
967
  hash_mismatches: summarizeStringList(details.hash_mismatches, limit),
@@ -1922,7 +1935,9 @@ function buildHealthFindings(params) {
1922
1935
  function rewriteBulkHealthRemediation(params) {
1923
1936
  if (params.check.name === "history_drift" && params.historyDriftedCount > 1) {
1924
1937
  for (const code of Object.keys(params.remediationMap)) {
1925
- params.remediationMap[code] = "pm history-repair --all";
1938
+ if (code !== "history_drift_merge_receipt") {
1939
+ params.remediationMap[code] = "pm history-repair --all";
1940
+ }
1926
1941
  }
1927
1942
  }
1928
1943
  if (params.check.name === "storage" && params.overThresholdCount > 1) {
@@ -1945,6 +1960,67 @@ function attachHealthRemediationMaps(params) {
1945
1960
  }
1946
1961
  }
1947
1962
  }
1963
+ async function correlateMergeReceiptHistoryDriftItems(params) {
1964
+ if (params.gitWorkspaceRoot === null ||
1965
+ params.pendingMergeReceipts.length === 0) {
1966
+ return [];
1967
+ }
1968
+ const details = params.historyDriftCheck.check.details;
1969
+ const hashMismatches = Array.isArray(details.hash_mismatches)
1970
+ ? details.hash_mismatches.filter((entry) => typeof entry === "string")
1971
+ : [];
1972
+ const unsafeStreamIds = new Set([
1973
+ details.missing_streams,
1974
+ details.unreadable_streams,
1975
+ details.chain_mismatches,
1976
+ ].flatMap((value) => (Array.isArray(value) ? value : [])));
1977
+ const cloneLocalReceiptsByItem = new Map();
1978
+ for (const receipt of params.pendingMergeReceipts) {
1979
+ if (receipt.evidence_source !== "clone_local")
1980
+ continue;
1981
+ const receipts = cloneLocalReceiptsByItem.get(receipt.item_id) ?? [];
1982
+ receipts.push(receipt);
1983
+ cloneLocalReceiptsByItem.set(receipt.item_id, receipts);
1984
+ }
1985
+ const attributed = [];
1986
+ for (const id of hashMismatches) {
1987
+ if (unsafeStreamIds.has(id))
1988
+ continue;
1989
+ const receipts = cloneLocalReceiptsByItem.get(id);
1990
+ if (!receipts || receipts.length === 0)
1991
+ continue;
1992
+ try {
1993
+ const repair = await runHistoryRepair(id, {
1994
+ dryRun: true,
1995
+ mergeReceiptProof: {
1996
+ gitWorkspaceRoot: params.gitWorkspaceRoot,
1997
+ receipts,
1998
+ },
1999
+ }, params.global);
2000
+ if (repair.merge_receipt_proof?.trusted)
2001
+ attributed.push(id);
2002
+ }
2003
+ catch {
2004
+ // Fail closed: generic history-repair guidance remains authoritative.
2005
+ }
2006
+ }
2007
+ return [...new Set(attributed)].sort((left, right) => left.localeCompare(right));
2008
+ }
2009
+ function applyMergeReceiptHistoryDriftAttribution(historyDriftCheck, attributedItems) {
2010
+ const attributed = new Set(attributedItems);
2011
+ historyDriftCheck.warnings = [
2012
+ ...historyDriftCheck.warnings.filter((warning) => {
2013
+ if (!warning.startsWith("history_drift_hash_mismatch:"))
2014
+ return true;
2015
+ return !attributed.has(warning.slice(warning.indexOf(":") + 1));
2016
+ }),
2017
+ ...attributedItems.map((id) => `history_drift_merge_receipt:${id}`),
2018
+ ].sort((left, right) => left.localeCompare(right));
2019
+ historyDriftCheck.check.details = {
2020
+ ...historyDriftCheck.check.details,
2021
+ merge_receipt_attributed_items: attributedItems,
2022
+ };
2023
+ }
1948
2024
  function projectHealthResult(result, options, summaryMode) {
1949
2025
  const warningCount = result.warning_count ?? result.warnings.length;
1950
2026
  const boundedResult = {
@@ -2030,11 +2106,22 @@ export async function runHealth(global, options = {}) {
2030
2106
  const provenanceWarnings = provenanceResolverHealth.warnings;
2031
2107
  const locksCheck = await buildLocksCheck(pmRoot);
2032
2108
  const integrityCheck = skipPolicy.skipIntegrity
2033
- ? buildSkippedHealthCheck("integrity")
2109
+ ? {
2110
+ ...buildSkippedHealthCheck("integrity"),
2111
+ gitWorkspaceRoot: null,
2112
+ pendingMergeReceipts: [],
2113
+ }
2034
2114
  : await buildIntegrityCheck(pmRoot, typeRegistry.type_to_folder, settings.schema, options.requireMergeDrivers === true, items);
2035
2115
  const historyDriftCheck = skipPolicy.skipDrift
2036
2116
  ? buildSkippedHealthCheck("history_drift")
2037
2117
  : await buildHistoryDriftCheck(pmRoot, itemsWithBody);
2118
+ const mergeReceiptAttributedHistoryDriftItems = await correlateMergeReceiptHistoryDriftItems({
2119
+ gitWorkspaceRoot: integrityCheck.gitWorkspaceRoot,
2120
+ pendingMergeReceipts: integrityCheck.pendingMergeReceipts,
2121
+ historyDriftCheck,
2122
+ global,
2123
+ });
2124
+ applyMergeReceiptHistoryDriftAttribution(historyDriftCheck, mergeReceiptAttributedHistoryDriftItems);
2038
2125
  const vectorizationCheck = skipPolicy.skipVectors
2039
2126
  ? buildSkippedHealthCheck("vectorization")
2040
2127
  : await buildVectorizationCheck(pmRoot, settings, itemsWithBody, refreshPolicy, options.verboseStaleItems === true);
@@ -2142,4 +2229,4 @@ export const _testOnlyHealthCommand = {
2142
2229
  warningCode,
2143
2230
  };
2144
2231
  //# sourceMappingURL=health.js.map
2145
- //# debugId=f7b3ff92-1fc7-55e9-aa76-af956714998f
2232
+ //# debugId=5887be76-3d1d-56fb-9cae-cf972f0b73f8
@@ -4,7 +4,7 @@
4
4
  * Implements the pm validate command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="aca69fd7-c47a-5424-b58f-f305f690edd9")}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]="3d7d6f15-7587-5c22-8deb-373bfd063d2b")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import fs from "node:fs/promises";
10
10
  import { realpathSync } from "node:fs";
@@ -34,7 +34,7 @@ import { buildMissingLinkedPathRows, summarizeMissingLinkedPathRows, } from "../
34
34
  import { assertProjectionModeChoice, } from "../output-projection.js";
35
35
  import { collectDanglingDependencyReferences } from "../graph/assembly.js";
36
36
  import { auditMergeAttributeFence, auditMergeDriverConfiguration, findGitWorkspaceRoot, resolveProjectMergeTypeFolders, } from "../merge/install.js";
37
- import { listMergeReceipts, partitionMergeReceipts, } from "../merge/receipts.js";
37
+ import { inspectMergeReceiptEvidence, partitionMergeReceipts, } from "../merge/receipts.js";
38
38
  import { scanStorageIntegrity } from "./storage-integrity.js";
39
39
  import { scanTrackedRuntimeCache } from "./tracked-runtime-cache.js";
40
40
  import { scanHistoryAuthorAttribution } from "../author-attribution.js";
@@ -1991,6 +1991,11 @@ export const _testOnlyValidateCommand = {
1991
1991
  summarizeDuplicateIssueCodes,
1992
1992
  toMeaningfulString,
1993
1993
  };
1994
+ function appendInvalidMergeReceiptEvidenceWarning(warnings, invalidEvidenceCount) {
1995
+ if (invalidEvidenceCount > 0) {
1996
+ warnings.push(`merge_receipt_evidence_invalid:${invalidEvidenceCount}`);
1997
+ }
1998
+ }
1994
1999
  /** Build the post-merge storage-integrity check (GH-603/GH-607/GH-609/GH-611): provably corrupted storage — unreadable item documents, on-disk-vs-parsed census mismatches, history conflict markers, resurrected deletes, and unparseable config/schema files — fails validate as an error instead of hiding behind ok:true. The `history_repair_reconciliations` count is informational: it surfaces post-repair divergence without permanently failing repaired workspaces. */
1995
2000
  async function buildStorageIntegrityCheck(pmRoot, items, typeToFolder, settings) {
1996
2001
  const scan = await scanStorageIntegrity(pmRoot, new Set(items.map((item) => item.id)), typeToFolder, {
@@ -2032,16 +2037,16 @@ async function buildStorageIntegrityCheck(pmRoot, items, typeToFolder, settings)
2032
2037
  if (mergeDriverAudit !== null && mergeDriverAudit.status !== "ok") {
2033
2038
  warnings.push(`validate_merge_driver_configuration:${mergeDriverAudit.missing_keys.length + mergeDriverAudit.drifted_keys.length}`);
2034
2039
  }
2035
- const pendingMergeReceipts = gitWorkspaceRoot === null
2036
- ? []
2037
- : await listMergeReceipts(gitWorkspaceRoot, {
2038
- includeLossless: true,
2039
- pmRoot,
2040
- });
2040
+ const mergeReceiptEvidence = await inspectMergeReceiptEvidence(gitWorkspaceRoot ?? pmRoot, {
2041
+ includeLossless: true,
2042
+ pmRoot,
2043
+ });
2044
+ const pendingMergeReceipts = mergeReceiptEvidence.receipts;
2041
2045
  const { pendingDecisions: pendingMergeDecisions, lossless: losslessMergeReceipts, } = partitionMergeReceipts(pendingMergeReceipts);
2042
2046
  if (pendingMergeDecisions.length > 0) {
2043
2047
  warnings.push(`validate_merge_decisions_unreviewed:${pendingMergeDecisions.length}`);
2044
2048
  }
2049
+ appendInvalidMergeReceiptEvidenceWarning(warnings, mergeReceiptEvidence.invalid_evidence_count);
2045
2050
  const status = errorCount > 0 ? "error" : warnings.length > 0 ? "warn" : "ok";
2046
2051
  return {
2047
2052
  check: {
@@ -2060,6 +2065,7 @@ async function buildStorageIntegrityCheck(pmRoot, items, typeToFolder, settings)
2060
2065
  ...new Set(pendingMergeDecisions.map((receipt) => receipt.item_id)),
2061
2066
  ].sort((left, right) => left.localeCompare(right)),
2062
2067
  lossless_merge_receipt_count: losslessMergeReceipts.length,
2068
+ invalid_merge_receipt_evidence_count: mergeReceiptEvidence.invalid_evidence_count,
2063
2069
  lossless_merge_receipt_items: [
2064
2070
  ...new Set(losslessMergeReceipts.map((receipt) => receipt.item_id)),
2065
2071
  ].sort((left, right) => left.localeCompare(right)),
@@ -2280,4 +2286,4 @@ export async function runValidate(options, global, services = {}) {
2280
2286
  }
2281
2287
  /* c8 ignore stop */
2282
2288
  //# sourceMappingURL=validate.js.map
2283
- //# debugId=aca69fd7-c47a-5424-b58f-f305f690edd9
2289
+ //# debugId=3d7d6f15-7587-5c22-8deb-373bfd063d2b
@@ -1,8 +1,3 @@
1
- /**
2
- * @module cli/guide-topics
3
- *
4
- * Provides CLI runtime support for Guide Topics.
5
- */
6
1
  /** Describes one documentation file surfaced by a progressive-disclosure guide topic. */
7
2
  export interface GuideDocReference {
8
3
  /** Filesystem path used for path resolution. */
@@ -1,9 +1,35 @@
1
+ /**
2
+ * @module cli/guide-topics
3
+ *
4
+ * Provides CLI runtime support for Guide Topics.
5
+ */
1
6
 
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]="7be35c3f-df6f-5ed6-b887-a7d8d53910a7")}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]="3e5f92c9-c299-592d-a7ab-a6f9998159f0")}catch(e){}}();
8
+ import { listPmCommandCapabilityGroups } from "./agent-capability-contracts.js";
3
9
  function normalizeTopicToken(value) {
4
10
  return value.trim().toLowerCase().replaceAll("_", "-");
5
11
  }
6
12
  const GUIDE_TOPICS = [
13
+ {
14
+ id: "capabilities",
15
+ aliases: ["capability-map", "families", "routing"],
16
+ title: "Generated Capability Routing",
17
+ summary: "Route work through command families generated from the canonical agent capability contract.",
18
+ intent: "Use this as the drift-free entrypoint when selecting a CLI, MCP, completion, documentation, or extension command surface.",
19
+ commands: listPmCommandCapabilityGroups().flatMap(({ commands }) => commands.map((command) => `pm ${command}`)),
20
+ workflows: [],
21
+ docs: [
22
+ {
23
+ path: "docs/generated/AGENT_CAPABILITY_ROUTING.md",
24
+ purpose: "Generated command-to-family routing table.",
25
+ },
26
+ {
27
+ path: "docs/generated/AGENT_COMMAND_SURFACE.md",
28
+ purpose: "Generated visibility-tier and family table.",
29
+ },
30
+ ],
31
+ related: ["commands", "workflows", "extensions"],
32
+ },
7
33
  {
8
34
  id: "quickstart",
9
35
  aliases: ["start", "getting-started", "bootstrap"],
@@ -565,4 +591,4 @@ export function resolveGuideTopic(rawTopic) {
565
591
  return TOPIC_BY_TOKEN.get(normalized) ?? null;
566
592
  }
567
593
  //# sourceMappingURL=guide-topics.js.map
568
- //# debugId=7be35c3f-df6f-5ed6-b887-a7d8d53910a7
594
+ //# debugId=3e5f92c9-c299-592d-a7ab-a6f9998159f0
@@ -1,4 +1,5 @@
1
1
  import { type HistoryCompactBulkSkipReason, type HistoryCompactScope } from "../core/history/history-compact-bulk.js";
2
+ import { type BulkIdsValue } from "../core/io/bulk-ids-input.js";
2
3
  import type { GlobalOptions } from "../core/shared/command-types.js";
3
4
  /** Documents the history compact command options payload exchanged by command, SDK, and package integrations. */
4
5
  export interface HistoryCompactCommandOptions {
@@ -58,7 +59,7 @@ export declare const HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES = 3;
58
59
  /** Documents the bulk history compact command options payload exchanged by command, SDK, and package integrations. */
59
60
  export interface HistoryCompactBulkCommandOptions {
60
61
  /** Value that configures or reports ids for this contract. */
61
- ids?: string[];
62
+ ids?: BulkIdsValue;
62
63
  /** Value that configures or reports scope for this contract. */
63
64
  scope?: HistoryCompactScope;
64
65
  /** Value that configures or reports all over for this contract. */
@@ -4,7 +4,7 @@
4
4
  * Implements the pm history compact 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]="adcf4d1b-689d-52cb-903b-5fba857707f3")}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]="31152621-df59-54a5-a28d-63119e734e6e")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "./environment/tracker-preflight.js";
9
9
  import fs from "node:fs/promises";
10
10
  import path from "node:path";
@@ -19,6 +19,7 @@ import { lifecycleClassifierFromStatusRegistry } from "../core/governance/metada
19
19
  import { resolveRuntimeStatusRegistry } from "../core/schema/runtime-schema.js";
20
20
  import { listAllItemMetadataLight } from "../core/store/item-store.js";
21
21
  import { pathExists, readFileIfExists } from "../core/fs/fs-utils.js";
22
+ import { normalizeBulkIdsValue, parseBulkIdsText, } from "../core/io/bulk-ids-input.js";
22
23
  import { EXIT_CODE } from "../core/shared/constants.js";
23
24
  import { PmCliError } from "../core/shared/errors.js";
24
25
  import { nowIso } from "../core/shared/time.js";
@@ -301,6 +302,21 @@ export async function runHistoryCompact(id, options, global) {
301
302
  }
302
303
  /** Default entry floor below which a stream is treated as already compact. */
303
304
  export const HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES = 3;
305
+ function normalizeHistoryCompactBulkOptions(options) {
306
+ const normalizedIdsText = normalizeBulkIdsValue(options.ids);
307
+ if (options.ids !== undefined && normalizedIdsText === "") {
308
+ throw new PmCliError("history-compact ids requires at least one valid item ID.", EXIT_CODE.USAGE, {
309
+ code: "bulk_ids_input_empty",
310
+ required: "Provide one or more string or finite numeric IDs; non-finite and unsupported selector values are rejected.",
311
+ });
312
+ }
313
+ return {
314
+ ...options,
315
+ ids: normalizedIdsText === undefined
316
+ ? undefined
317
+ : parseBulkIdsText(normalizedIdsText),
318
+ };
319
+ }
304
320
  /** Enforce the `pm history-compact` target contract shared by the CLI and MCP surfaces: exactly one selection mode — a single item `<id>`, an explicit `--ids` list, or a scan selector (`--all-over` / `--closed` / `--all-streams`). */
305
321
  export function assertHistoryCompactTarget(id, bulk) {
306
322
  const hasIds = bulk.ids !== undefined && bulk.ids.length > 0;
@@ -436,6 +452,7 @@ async function runHistoryCompactBulkRow(params) {
436
452
  * configured policy drives the sweep.
437
453
  */
438
454
  export async function runHistoryCompactBulk(options, global) {
455
+ const normalizedOptions = normalizeHistoryCompactBulkOptions(options);
439
456
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
440
457
  await assertInitializedTracker(pmRoot);
441
458
  const settings = await readSettings(pmRoot);
@@ -445,14 +462,16 @@ export async function runHistoryCompactBulk(options, global) {
445
462
  settings,
446
463
  typeToFolder: typeRegistry.type_to_folder,
447
464
  });
448
- const mode = options.ids !== undefined && options.ids.length > 0 ? "ids" : "scan";
465
+ const mode = normalizedOptions.ids !== undefined && normalizedOptions.ids.length > 0
466
+ ? "ids"
467
+ : "scan";
449
468
  const minEntries = options.minEntries ?? HISTORY_COMPACT_BULK_DEFAULT_MIN_ENTRIES;
450
469
  const policy = settings.history.compact_policy;
451
470
  const policyThresholdApplied = mode === "scan" && options.allOver === undefined && policy.enabled;
452
471
  const allOver = options.allOver ??
453
472
  (policyThresholdApplied ? policy.max_entries : undefined);
454
473
  const selection = selectHistoryCompactBulkTargets(candidates, {
455
- ids: options.ids,
474
+ ids: normalizedOptions.ids,
456
475
  scope: options.scope,
457
476
  minEntries,
458
477
  allOver,
@@ -469,7 +488,7 @@ export async function runHistoryCompactBulk(options, global) {
469
488
  for (const row of selection) {
470
489
  const outcome = await runHistoryCompactBulkRow({
471
490
  row,
472
- options,
491
+ options: normalizedOptions,
473
492
  dryRun,
474
493
  global,
475
494
  });
@@ -502,4 +521,4 @@ export async function runHistoryCompactBulk(options, global) {
502
521
  };
503
522
  }
504
523
  //# sourceMappingURL=history-compact.js.map
505
- //# debugId=adcf4d1b-689d-52cb-903b-5fba857707f3
524
+ //# debugId=31152621-df59-54a5-a28d-63119e734e6e
@@ -1,5 +1,6 @@
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]="f762b5e6-8224-531f-9dd1-f71dc18c3ddf")}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]="4888a558-7f50-5c28-8e29-fcd19180cbd4")}catch(e){}}();
3
+ import { normalizeBulkIdsValue, parseBulkIdsText, } from "../core/io/bulk-ids-input.js";
3
4
  import { EXIT_CODE } from "../core/shared/constants.js";
4
5
  import { PmCliError } from "../core/shared/errors.js";
5
6
  import { assertHistoryCompactTarget, runHistoryCompact, runHistoryCompactBulk, } from "./history-compact.js";
@@ -17,14 +18,14 @@ export function runMcpHistoryRepairAction(context) {
17
18
  /** Dispatch single or bounded bulk history compaction from an MCP payload. */
18
19
  export function runMcpHistoryCompactAction(context) {
19
20
  const idsSource = context.options.ids;
20
- const ids = Array.isArray(idsSource)
21
- ? idsSource.map(String).filter((value) => value.trim().length > 0)
22
- : typeof idsSource === "string"
23
- ? idsSource
24
- .split(",")
25
- .map((value) => value.trim())
26
- .filter(Boolean)
27
- : undefined;
21
+ const normalizedIds = normalizeBulkIdsValue(idsSource);
22
+ if (idsSource !== undefined && normalizedIds === "") {
23
+ throw new PmCliError("history-compact ids requires at least one valid item ID.", EXIT_CODE.USAGE, {
24
+ code: "bulk_ids_input_empty",
25
+ required: "Provide one or more string or finite numeric IDs; non-finite and unsupported selector values are rejected.",
26
+ });
27
+ }
28
+ const ids = normalizedIds === undefined ? undefined : parseBulkIdsText(normalizedIds);
28
29
  const allOver = parseRuntimeInteger(context.options.allOver ?? context.options.all_over, "history-compact allOver");
29
30
  const minEntries = parseRuntimeInteger(context.options.minEntries ?? context.options.min_entries, "history-compact minEntries");
30
31
  const explicitScope = readRuntimeString(context.options, "scope");
@@ -65,4 +66,4 @@ export function runMcpHistoryCompactAction(context) {
65
66
  }, context.global);
66
67
  }
67
68
  //# sourceMappingURL=history-mcp.js.map
68
- //# debugId=f762b5e6-8224-531f-9dd1-f71dc18c3ddf
69
+ //# debugId=4888a558-7f50-5c28-8e29-fcd19180cbd4
@@ -1,6 +1,7 @@
1
1
  import { type ReplayDocument } from "../core/history/replay.js";
2
2
  import type { GlobalOptions } from "../core/shared/command-types.js";
3
3
  import type { HistoryEntry } from "../types/index.js";
4
+ import { type MergeDecisionReceipt } from "./merge/receipts.js";
4
5
  import { type ProvenanceNormalizationReceipt } from "./governance/provenance-health.js";
5
6
  /** Documents the history repair command options payload exchanged by command, SDK, and package integrations. */
6
7
  export interface HistoryRepairCommandOptions {
@@ -22,6 +23,16 @@ export interface HistoryRepairCommandOptions {
22
23
  forceAuditEntry?: boolean;
23
24
  /** Remove bounded-domain-invalid provenance observations and record an aggregate privacy-safe audit receipt. */
24
25
  normalizeProvenance?: boolean;
26
+ /** Internal receipt evidence revalidated against the exact item snapshot used by this repair. */
27
+ mergeReceiptProof?: {
28
+ gitWorkspaceRoot: string | null;
29
+ receipts: MergeDecisionReceipt[];
30
+ };
31
+ /** Internal per-item receipt proof index used by bounded bulk reconciliation. */
32
+ mergeReceiptProofById?: Record<string, {
33
+ gitWorkspaceRoot: string | null;
34
+ receipts: MergeDecisionReceipt[];
35
+ }>;
25
36
  }
26
37
  /** Documents the history repair result payload exchanged by command, SDK, and package integrations. */
27
38
  export interface HistoryRepairResult {
@@ -60,11 +71,22 @@ export interface HistoryRepairResult {
60
71
  };
61
72
  /** Present when reconciling the chain with the on-disk item discards the replayed effect of earlier history events (GH-603): names the reverted fields and the authors whose mutations the reconciliation overwrites, so cross-author data loss after a lossy merge is loud instead of silent. */
62
73
  reconciliation?: HistoryRepairReconciliationReport;
74
+ /** Present when merge reconciliation supplied receipt evidence for this item. */
75
+ merge_receipt_proof?: MergeReceiptProofResult;
63
76
  /** Value that configures or reports warnings for this contract. */
64
77
  warnings: string[];
65
78
  /** ISO 8601 timestamp recording when generated occurred. */
66
79
  generated_at: string;
67
80
  }
81
+ /** Fail-closed proof that clone-local driver receipts exactly cover the current reconciliation fields and values. */
82
+ export interface MergeReceiptProofResult {
83
+ /** Whether exact receipt identity, path, field, and value-hash evidence proves the snapshot. */
84
+ trusted: boolean;
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";
87
+ /** Exact receipt identities accepted as proof; empty when proof is refused. */
88
+ receipt_ids: string[];
89
+ }
68
90
  /** Documents one history event attributed to fields changed by reconciliation. */
69
91
  export interface HistoryRepairDiscardedEvent {
70
92
  /** 1-based index of the event in the (re-anchored) history stream. */
@@ -121,6 +143,8 @@ export interface HistoryRepairAllStreamResult {
121
143
  reconciled_with_item?: boolean;
122
144
  /** Cross-author data-loss detail when reconciliation overwrites replayed mutations. */
123
145
  reconciliation?: HistoryRepairReconciliationReport;
146
+ /** Exact receipt proof used to authorize this stream, when supplied. */
147
+ merge_receipt_proof?: MergeReceiptProofResult;
124
148
  /** Stream-specific repair warnings retained by the bulk workflow. */
125
149
  warnings?: string[];
126
150
  /** Value that configures or reports error for this contract. */