@unbrained/pm-cli 2026.9.5 → 2026.9.6

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 (185) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +32 -2
  3. package/dist/cli/main.js +10 -8
  4. package/dist/cli/register-operations.js +13 -8
  5. package/dist/cli-bundle/bundle-manifest.json +150 -158
  6. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +9 -0
  7. package/dist/cli-bundle/chunks/{chunk-WWAEGW4V.js → chunk-BAX2BYUW.js} +66 -66
  8. package/dist/cli-bundle/chunks/{chunk-IBYREGSP.js → chunk-CKOL5U7J.js} +51 -51
  9. package/dist/cli-bundle/chunks/{chunk-ZRAQS3UA.js → chunk-JT6XF6GE.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-HUAQITVW.js → chunk-JX4DH4WC.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-QPZHQY2O.js → chunk-NPN5I67J.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-66VPKFP2.js → chunk-OF76PSDQ.js} +2 -2
  13. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +232 -0
  14. package/dist/cli-bundle/chunks/{chunk-3HBDTJRK.js → chunk-RWWBOWJ5.js} +2 -2
  15. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +40 -0
  16. package/dist/cli-bundle/chunks/{chunk-SF6SM6U5.js → chunk-WI2AYPA7.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-list-query-AYKGODWT.js → register-list-query-5JL52D33.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-mutation-YZYG53SQ.js → register-mutation-ZPG7KMVP.js} +2 -2
  19. package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +2 -0
  20. package/dist/cli-bundle/chunks/{register-setup-UJCRVGBG.js → register-setup-H4SVAVX7.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-QL66QNWG.js → chunk-3BZEOXLT.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +2 -0
  23. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +6 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +20 -0
  25. package/dist/cli-bundle/focused-chunks/{chunk-WOCIPMW7.js → chunk-EZR3GHFE.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +56 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-3ASU6WGI.js → chunk-LIJIA4TY.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-H5FOGAVD.js → chunk-M6PBRFSH.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-B2TTQGFG.js → chunk-NTPY5GSO.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +177 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-YEF5PQQ2.js → chunk-PEFABF7E.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-KWWCBWFO.js → chunk-QTVCLMSZ.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-4OSHLNUE.js → chunk-QTZRBUYA.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +12 -0
  36. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +10 -0
  37. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +2 -0
  38. package/dist/cli-bundle/main.js +20 -20
  39. package/dist/cli-bundle/sdk-authoring.js +1 -1
  40. package/dist/cli-bundle/sdk-contracts.js +2 -2
  41. package/dist/cli-bundle/sdk-core.js +37 -37
  42. package/dist/cli-bundle/sdk-governance.js +1 -1
  43. package/dist/cli-bundle/sdk-graph.js +1 -1
  44. package/dist/cli-bundle/sdk-merge.js +42 -42
  45. package/dist/cli-bundle/sdk-query.js +1 -1
  46. package/dist/cli-bundle/sdk-runtime.js +1 -1
  47. package/dist/cli-bundle/sdk-testing.js +1 -1
  48. package/dist/cli-bundle/sdk.js +9 -9
  49. package/dist/core/extensions/module-graph-snapshot.js +5 -4
  50. package/dist/core/fs/host-environment-errors.d.ts +27 -0
  51. package/dist/core/fs/host-environment-errors.js +142 -0
  52. package/dist/core/output/mutation-projection.js +12 -5
  53. package/dist/core/store/item-metadata-query-index.js +13 -10
  54. package/dist/core/store/item-metadata-read-work.d.ts +19 -0
  55. package/dist/core/store/item-metadata-read-work.js +44 -0
  56. package/dist/core/store/item-store.js +6 -2
  57. package/dist/core/validate/fix-planning.d.ts +1 -1
  58. package/dist/core/validate/fix-planning.js +2 -2
  59. package/dist/core/validate/missing-link-owners.d.ts +1 -1
  60. package/dist/core/validate/missing-link-owners.js +5 -3
  61. package/dist/core/validate/stale-file-classification.d.ts +6 -4
  62. package/dist/core/validate/stale-file-classification.js +20 -5
  63. package/dist/mcp/server.js +12 -5
  64. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  65. package/dist/sdk/cli-contracts/flag-contracts.js +7 -5
  66. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -3
  67. package/dist/sdk/cli-contracts/grammar-contracts.js +11 -2
  68. package/dist/sdk/cli-contracts/runtime-contracts.js +5 -2
  69. package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +254 -5
  70. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +52 -2
  71. package/dist/sdk/cli-contracts/tool-parameter-tables.js +18 -6
  72. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  73. package/dist/sdk/cli-contracts/tool-schema.js +17 -5
  74. package/dist/sdk/context/usage-ledger.d.ts +41 -0
  75. package/dist/sdk/context/usage-ledger.js +186 -0
  76. package/dist/sdk/context-usage.d.ts +18 -9
  77. package/dist/sdk/context-usage.js +37 -112
  78. package/dist/sdk/dependency-provenance.d.ts +7 -0
  79. package/dist/sdk/dependency-provenance.js +14 -4
  80. package/dist/sdk/duplicates.d.ts +2 -0
  81. package/dist/sdk/duplicates.js +3 -2
  82. package/dist/sdk/environment/host-environment-errors.d.ts +5 -27
  83. package/dist/sdk/environment/host-environment-errors.js +4 -137
  84. package/dist/sdk/extension/install-runtime.js +9 -6
  85. package/dist/sdk/extension/install-snapshot.js +7 -6
  86. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +8 -8
  87. package/dist/sdk/governance/assurance-action.d.ts +3 -2
  88. package/dist/sdk/governance/assurance-action.js +23 -11
  89. package/dist/sdk/governance/assurance-runtime.d.ts +2 -0
  90. package/dist/sdk/governance/assurance-runtime.js +6 -3
  91. package/dist/sdk/governance/defect-recurrence-coverage.d.ts +93 -0
  92. package/dist/sdk/governance/defect-recurrence-coverage.js +189 -0
  93. package/dist/sdk/governance/defect-recurrence-graph.d.ts +33 -0
  94. package/dist/sdk/governance/defect-recurrence-graph.js +121 -0
  95. package/dist/sdk/governance/defect-recurrence.d.ts +8 -0
  96. package/dist/sdk/governance/defect-recurrence.js +118 -17
  97. package/dist/sdk/governance/health.d.ts +17 -2
  98. package/dist/sdk/governance/health.js +31 -10
  99. package/dist/sdk/governance/linked-file-report.d.ts +41 -0
  100. package/dist/sdk/governance/linked-file-report.js +72 -0
  101. package/dist/sdk/governance/validate.d.ts +5 -2
  102. package/dist/sdk/governance/validate.js +21 -37
  103. package/dist/sdk/governance.d.ts +2 -0
  104. package/dist/sdk/governance.js +4 -2
  105. package/dist/sdk/history-repair.d.ts +7 -0
  106. package/dist/sdk/history-repair.js +48 -13
  107. package/dist/sdk/lifecycle/close.d.ts +8 -0
  108. package/dist/sdk/lifecycle/close.js +16 -8
  109. package/dist/sdk/lifecycle/create.js +9 -12
  110. package/dist/sdk/lifecycle/update.js +12 -12
  111. package/dist/sdk/lifecycle-policy.d.ts +3 -0
  112. package/dist/sdk/lifecycle-policy.js +2 -2
  113. package/dist/sdk/merge/abandoned-receipts.d.ts +15 -0
  114. package/dist/sdk/merge/abandoned-receipts.js +47 -0
  115. package/dist/sdk/merge/driver.js +4 -2
  116. package/dist/sdk/merge/index.d.ts +1 -0
  117. package/dist/sdk/merge/index.js +2 -2
  118. package/dist/sdk/merge/receipt-operation.d.ts +15 -0
  119. package/dist/sdk/merge/receipt-operation.js +97 -0
  120. package/dist/sdk/merge/receipt-schema.d.ts +20 -0
  121. package/dist/sdk/merge/receipt-schema.js +398 -0
  122. package/dist/sdk/merge/receipts.d.ts +16 -7
  123. package/dist/sdk/merge/receipts.js +54 -340
  124. package/dist/sdk/merge/reconcile.d.ts +2 -0
  125. package/dist/sdk/merge/reconcile.js +11 -4
  126. package/dist/sdk/public-surface.json +1 -1
  127. package/dist/sdk/query/duplicate-candidates.d.ts +7 -0
  128. package/dist/sdk/query/duplicate-candidates.js +71 -0
  129. package/dist/sdk/query/get.js +7 -7
  130. package/dist/sdk/query.d.ts +2 -0
  131. package/dist/sdk/query.js +4 -2
  132. package/dist/sdk/read-output-session.js +5 -3
  133. package/dist/sdk/runtime.js +4 -2
  134. package/dist/sdk/similarity.d.ts +24 -3
  135. package/dist/sdk/similarity.js +50 -55
  136. package/docs/AGENT_GUIDE.md +23 -2
  137. package/docs/BOUNDED_CONTEXT_READS.md +185 -0
  138. package/docs/CLOSE_EVIDENCE_RECOVERY.md +35 -0
  139. package/docs/COMMANDS.md +30 -8
  140. package/docs/CONTEXT_RELEVANCE.md +16 -4
  141. package/docs/DEFECT_RECURRENCE.md +80 -6
  142. package/docs/EXTENSIONS.md +18 -19
  143. package/docs/MERGE_SAFETY.md +50 -0
  144. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +66 -0
  145. package/docs/PR_REVIEW_LOOP.md +18 -3
  146. package/docs/README.md +18 -1
  147. package/docs/RELEASING.md +6 -2
  148. package/docs/SDK_LIFECYCLE.md +27 -0
  149. package/docs/SDK_RUNTIME_BOUNDARIES.md +11 -0
  150. package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -1
  151. package/marketplace.json +2 -2
  152. package/package.json +6 -3
  153. package/packages/pm-beads/package.json +1 -1
  154. package/packages/pm-calendar/package.json +1 -1
  155. package/packages/pm-command-kit/package.json +1 -1
  156. package/packages/pm-digital-twin/package.json +1 -1
  157. package/packages/pm-governance-audit/README.md +10 -1
  158. package/packages/pm-governance-audit/extensions/governance-audit/dedupe-audit.ts +50 -65
  159. package/packages/pm-governance-audit/extensions/governance-audit/index.ts +2 -2
  160. package/packages/pm-governance-audit/extensions/governance-audit/sdk.ts +1 -0
  161. package/packages/pm-governance-audit/package.json +1 -1
  162. package/packages/pm-guide-shell/package.json +1 -1
  163. package/packages/pm-kanban/package.json +1 -1
  164. package/packages/pm-lifecycle-hooks/package.json +1 -1
  165. package/packages/pm-linked-test-adapters/package.json +1 -1
  166. package/packages/pm-search-advanced/package.json +1 -1
  167. package/packages/pm-templates/package.json +1 -1
  168. package/packages/pm-todos/package.json +1 -1
  169. package/packages/pm-vcs/package.json +1 -1
  170. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  171. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  172. package/dist/cli-bundle/chunks/chunk-LUI4E32I.js +0 -231
  173. package/dist/cli-bundle/chunks/chunk-SVK5Y64D.js +0 -40
  174. package/dist/cli-bundle/chunks/chunk-V5GBD5KV.js +0 -9
  175. package/dist/cli-bundle/chunks/register-operations-KFSCC7QV.js +0 -2
  176. package/dist/cli-bundle/focused-chunks/chunk-24IG6ONG.js +0 -2
  177. package/dist/cli-bundle/focused-chunks/chunk-3ITLIBKS.js +0 -56
  178. package/dist/cli-bundle/focused-chunks/chunk-3NQD5YDG.js +0 -2
  179. package/dist/cli-bundle/focused-chunks/chunk-65N6JHAN.js +0 -2
  180. package/dist/cli-bundle/focused-chunks/chunk-GUBM3RGY.js +0 -20
  181. package/dist/cli-bundle/focused-chunks/chunk-JX3RCVCX.js +0 -2
  182. package/dist/cli-bundle/focused-chunks/chunk-MV752SUC.js +0 -12
  183. package/dist/cli-bundle/focused-chunks/chunk-PKIPMCFS.js +0 -6
  184. package/dist/cli-bundle/focused-chunks/chunk-RJMR2JIF.js +0 -9
  185. package/dist/cli-bundle/focused-chunks/chunk-WIUPWIZR.js +0 -177
@@ -1,10 +1,5 @@
1
- /**
2
- * @module sdk/lifecycle/close
3
- *
4
- * Implements the pm close command surface and its agent-facing runtime behavior.
5
- */
6
1
 
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]="9f28f7d8-993b-5201-b606-d1eab0c3ff5c")}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]="0e166cbb-ef9c-5016-89a6-07f287e00a2e")}catch(e){}}();
8
3
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
4
  import { toItemRecord, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, buildItemNotFoundError, listAllItemMetadataLight, locateItem, mutateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, resolveIsoOrRelative, shouldCompletePlanOnClose, getActiveExtensionRegistrations, } from "../runtime-primitives.js";
10
5
  import { collectBlockedByIds, indexBlockedByIds } from "../actionability.js";
@@ -47,6 +42,16 @@ function findMissingCloseValidationFields(itemMetadata) {
47
42
  }
48
43
  return missing;
49
44
  }
45
+ /** Build an argv-safe update that appends acceptance evidence without repeating a terminal transition. */
46
+ function closeEvidenceRecovery(metadata, pmRoot, options = {}) {
47
+ const missing = findMissingCloseValidationFields(metadata);
48
+ if (missing.length === 0)
49
+ return undefined;
50
+ const values = { resolution: options.resolution, expected_result: options.expectedResult, actual_result: options.actualResult };
51
+ const missingFlags = missing.map((field) => `--${field.key.replaceAll("_", "-")}`);
52
+ const args = ["--pm-path", pmRoot, "update", metadata.id, ...missing.flatMap((field, index) => [missingFlags[index], values[field.key]?.trim() || "<value>"])];
53
+ return { missing: missingFlags, suggested_retry: renderPmCommand(args), suggested_retry_args: args };
54
+ }
50
55
  async function duplicateChainReferencesClosingItem(loadItemById, initialDuplicateOf, closingId) {
51
56
  const visited = new Set();
52
57
  let current = initialDuplicateOf;
@@ -317,10 +322,11 @@ function clearCloseAssignee(metadata) {
317
322
  delete metadata.assignee;
318
323
  return ["assignee"];
319
324
  }
325
+ /** Enforce terminal and closure policies before applying acceptance fields and the atomic lifecycle transition. */
320
326
  function mutateCloseMetadata(metadata, context) {
321
327
  if (isTerminalStatus(metadata.status, context.statusRegistry) &&
322
328
  !context.force) {
323
- throw new PmCliError(`Item ${metadata.id} is already terminal; use --force to close again.`, EXIT_CODE.CONFLICT);
329
+ throw new PmCliError(`Item ${metadata.id} is already terminal; use pm update to append acceptance evidence, or --force only for an intentional repeat closure.`, EXIT_CODE.CONFLICT, { recovery: closeEvidenceRecovery(metadata, context.pmRoot, context.options) });
324
330
  }
325
331
  const inlineChangedFields = applyInlineCloseFields(metadata, context.options);
326
332
  const duplicateFallbackFields = applyDuplicateCloseMetadata(metadata, context.duplicateOf);
@@ -444,9 +450,11 @@ export async function closeItem(id, closeReasonText, options, global) {
444
450
  });
445
451
  },
446
452
  });
453
+ const recovery = validateCloseMode === "warn" ? closeEvidenceRecovery(result.item, pmRoot) : undefined;
447
454
  return {
448
455
  item: toItemRecord(result.item),
449
456
  changed_fields: result.changedFields,
457
+ ...(recovery ? { recovery } : {}),
450
458
  warnings: [
451
459
  ...result.warnings,
452
460
  ...(await autoUnblockResolvedDependents(pmRoot, settings, trackerItems, located.id, author, statusRegistry)),
@@ -458,4 +466,4 @@ export function runClose(id, closeReasonText, options, global) {
458
466
  return closeItem(id, closeReasonText, options, global);
459
467
  }
460
468
  //# sourceMappingURL=close.js.map
461
- //# debugId=9f28f7d8-993b-5201-b606-d1eab0c3ff5c
469
+ //# debugId=0e166cbb-ef9c-5016-89a6-07f287e00a2e
@@ -4,7 +4,7 @@
4
4
  * Implements the pm create 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]="c9bfbfd4-3d34-5fa7-b264-6bf9ed5f7f81")}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]="44240cea-9996-5f86-acc5-ac0cfa71c586")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import { assertNoAmbiguousBareCommaEntry, looksLikeStructuredKeyValueEntry, resolveMutationStdinTokenFields, } from "../../core/item/parse.js";
10
10
  import { removeFileIfExists, writeFileAtomic, appendHistoryEntry, createHistoryEntry, generateItemId, normalizeItemId, canonicalDocument, normalizeItemMetadata, serializeItemDocument, assertParentReferenceIsNotSelf, isPlaceholderReferenceToken, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, assertNoUnknownCsvKeys, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, shouldResolveMutationStdinTokens, transferMutationStdinTokenPolicy, resolvePriority, getFocusedItem, normalizeStatusInput, isTerminalStatus, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, acquireLock, printError, buildInvalidTypeError, resolveTypeSynonym, collectRuntimeCreateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, ITEM_METADATA_KEY_ORDER, PmCliError, nowIso, resolveIsoOrRelative, getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveCommandHandler, runActiveBeforeMutationHooks, runActiveOnWriteHooks, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, listAllItemMetadataLight, locateItem, createMutationGuardSdk, getHistoryPath, getItemPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
@@ -24,7 +24,7 @@ import { attachLinkedTestMutationProvenance } from "../test/trust.js";
24
24
  import { COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR, COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_AUTHOR, parseCommandUnsetTargets, resolveRuntimeUnsetFieldDefinition, } from "./shared-unset-fields.js";
25
25
  import { ensureEnumValue } from "./recurrence-parsers.js";
26
26
  import { assertDependencyEdgesAllowed, assertDependencyTargetsResolvable, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
27
- import { normalizeDependencySeedId, normalizeDependencySourceKind, } from "../dependency-provenance.js";
27
+ import { normalizeDependencySeedId, normalizeItemReference, isExternalDependencyReference, normalizeDependencySourceKind, } from "../dependency-provenance.js";
28
28
  import { resolveCanonicalRelationshipKind } from "../relationships.js";
29
29
  import { supportsCreateExplicitEmpty } from "../agent/create-option-policy.js";
30
30
  import { parseEventEntries, parseReminderEntries, parseTypeOptionEntries, } from "./repeatable-metadata-parsers.js";
@@ -767,9 +767,6 @@ export function requireStringOption(value, flag) {
767
767
  }
768
768
  return normalized;
769
769
  }
770
- function ensurePriority(rawPriority) {
771
- return resolvePriority(rawPriority);
772
- }
773
770
  function mergeCreateOptionsWithTemplate(templateOptions, explicitOptions) {
774
771
  const merged = {};
775
772
  for (const [key, value] of Object.entries(templateOptions)) {
@@ -847,9 +844,6 @@ async function loadCreateTemplateOptionsFromRuntime(templateName, global, pmRoot
847
844
  /* c8 ignore next -- template runtime success path is covered by package-level integration tests. */
848
845
  return readTemplateOptionsFromRuntimeResult(handlerResult.result, templateName);
849
846
  }
850
- function ensureInitHasRun(pmRoot) {
851
- return assertInitializedTracker(pmRoot);
852
- }
853
847
  /**
854
848
  * Resolve an optional string item-metadata field for {@link runCreate}: yields
855
849
  * `undefined` when the field is being cleared via `--unset <key>` or was never
@@ -913,7 +907,10 @@ async function inheritFocusedParent(parent, resolvedOptions, unsetKeys, pmRoot)
913
907
  }
914
908
  /** Normalize and locate a new item's parent reference, returning the normalized value plus any never-blocking missing-parent warnings the configured `parent_reference` policy produces when the target does not resolve. */
915
909
  async function validateCreateParentReference(pmRoot, settings, typeRegistry, itemId, parent, policy) {
916
- const normalized = normalizeParentReferenceValue(parent);
910
+ const normalized = normalizeItemReference(normalizeParentReferenceValue(parent), settings.id_prefix);
911
+ if (isExternalDependencyReference(normalized)) {
912
+ return { parent: normalized, warnings: [] };
913
+ }
917
914
  assertParentReferenceIsNotSelf(itemId, normalized, settings.id_prefix);
918
915
  const parentLocated = await locateItem(pmRoot, normalized, settings.id_prefix, settings.item_format, typeRegistry.type_to_folder);
919
916
  if (parentLocated) {
@@ -1618,7 +1615,7 @@ async function writeCreatedItem(params) {
1618
1615
  export async function runCreate(options, global) {
1619
1616
  let resolvedOptions = normalizeLegacyNoneCreateOptions(await resolveCreateTransportInputs(options));
1620
1617
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
1621
- await ensureInitHasRun(pmRoot);
1618
+ await assertInitializedTracker(pmRoot);
1622
1619
  const settings = await readSettings(pmRoot);
1623
1620
  const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
1624
1621
  const runtimeFieldRegistry = resolveRuntimeFieldRegistry(settings.schema);
@@ -1683,7 +1680,7 @@ export async function runCreate(options, global) {
1683
1680
  ? parseStatusValue(resolvedOptions.status, statusRegistry)
1684
1681
  : resolveCreateDefaultStatus(typeDefinition, statusRegistry);
1685
1682
  const priority = resolvedOptions.priority !== undefined
1686
- ? ensurePriority(resolvedOptions.priority)
1683
+ ? resolvePriority(resolvedOptions.priority)
1687
1684
  : 2;
1688
1685
  const unsetKeys = unsetTargets.metadataKeys;
1689
1686
  const tags = resolveCreateTags(unsetKeys, resolvedOptions);
@@ -1950,4 +1947,4 @@ export const _testOnlyCreateCommand = {
1950
1947
  typeOptionExampleValue,
1951
1948
  };
1952
1949
  //# sourceMappingURL=create.js.map
1953
- //# debugId=c9bfbfd4-3d34-5fa7-b264-6bf9ed5f7f81
1950
+ //# debugId=44240cea-9996-5f86-acc5-ac0cfa71c586
@@ -4,7 +4,7 @@
4
4
  * Implements the pm update 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]="78f8b369-1802-555d-a8cc-0147c0d8fb08")}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]="5a6614ac-62fd-5680-9eed-447bfb7a167f")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import { resolveMutationStdinTokenFields } from "../../core/item/parse.js";
10
10
  import { COMMON_MUTATION_COMMAND_OPTION_KEYS, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, normalizeItemId, toItemRecord, buildInvalidTypeError, assertParentReferenceIsNotSelf, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, applyAcceptanceCriteriaMutations, applyTagRemovals, assertNoUnknownCsvKeys, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, shouldResolveMutationStdinTokens, transferMutationStdinTokenPolicy, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, isTerminalStatus, collectRuntimeUpdateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, describeAllowedTransitions, evaluateTransition, resolveTypeWorkflows, EXIT_CODE, PmCliError, stableValueEquals, resolveIsoOrRelative, getActiveExtensionRegistrations, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, buildItemNotFoundError, listAllItemMetadataLight, locateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
@@ -15,7 +15,7 @@ import { applyLegacyNoneCollectionNormalizers, createLegacyNoneCollectionNormali
15
15
  import { ensureEnumValue as ensureEnum } from "./recurrence-parsers.js";
16
16
  import { parseEventEntries, parseReminderEntries, parseTypeOptionEntries, } from "./repeatable-metadata-parsers.js";
17
17
  import { assertDependencyEdgesAllowed, assertDependencyTargetsResolvable, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
18
- import { normalizeDependencySeedId, normalizeDependencySourceKind, } from "../dependency-provenance.js";
18
+ import { normalizeDependencySeedId, normalizeItemReference, isExternalDependencyReference, normalizeDependencySourceKind, } from "../dependency-provenance.js";
19
19
  import { resolveCanonicalRelationshipKind } from "../relationships.js";
20
20
  import { collectNewOrderingCycleWarnings } from "../graph/mutation-advisory.js";
21
21
  import { assertHierarchyMutationAllowed } from "../graph/hierarchy-integrity.js";
@@ -619,9 +619,6 @@ function matchesDependencySelector(value, selector) {
619
619
  }
620
620
  return true;
621
621
  }
622
- function ensurePriority(raw) {
623
- return resolvePriority(raw);
624
- }
625
622
  function normalizeUpdatePolicyOptionKey(raw, typeName) {
626
623
  const canonical = canonicalizeCommandOptionKey("update", raw);
627
624
  if (!canonical) {
@@ -1152,9 +1149,6 @@ function assertUpdateHierarchyIntegrity(params) {
1152
1149
  return;
1153
1150
  assertHierarchyMutationAllowed(params.before, params.before.map((item) => item.id === params.document.metadata.id ? params.document.metadata : item), params.document.metadata.id, (status) => isTerminalStatus(status, params.statusRegistry), resolveWorkspaceRelationshipKindRegistry());
1154
1151
  }
1155
- async function assertUpdateTrackerInitialized(pmRoot) {
1156
- await assertInitializedTracker(pmRoot);
1157
- }
1158
1152
  function assertMatchingOrderRank(options) {
1159
1153
  if (options.order !== undefined &&
1160
1154
  options.rank !== undefined &&
@@ -1162,12 +1156,16 @@ function assertMatchingOrderRank(options) {
1162
1156
  throw new PmCliError("--order and --rank must match when both are provided", EXIT_CODE.USAGE);
1163
1157
  }
1164
1158
  }
1159
+ /** Canonicalize local parent input before self/existence checks; preserve explicit remote locators and explicit unsets. */
1165
1160
  async function resolveParentReferenceForUpdate(params) {
1166
1161
  if (params.options.parent === undefined ||
1167
1162
  params.unsetTargets.metadataKeys.has("parent")) {
1168
1163
  return { resolvedParentValue: undefined, warnings: [] };
1169
1164
  }
1170
- const resolvedParentValue = normalizeParentReferenceValue(params.options.parent);
1165
+ const resolvedParentValue = normalizeItemReference(normalizeParentReferenceValue(params.options.parent), params.settings.id_prefix);
1166
+ if (isExternalDependencyReference(resolvedParentValue)) {
1167
+ return { resolvedParentValue, warnings: [] };
1168
+ }
1171
1169
  assertParentReferenceIsNotSelf(params.id, resolvedParentValue, params.settings.id_prefix);
1172
1170
  const parentLocated = await locateItem(params.pmRoot, resolvedParentValue, params.settings.id_prefix, params.settings.item_format, params.typeRegistry.type_to_folder);
1173
1171
  if (parentLocated) {
@@ -1212,6 +1210,7 @@ async function collectWorkflowTransitionWarnings(params) {
1212
1210
  });
1213
1211
  return warning ? [warning] : [];
1214
1212
  }
1213
+ /** Delegate the configured close transition to the closure writer, applying other requested fields first and retaining its evidence. */
1215
1214
  async function routeCloseStatusUpdate(context) {
1216
1215
  if (!context.fieldFlags.status) {
1217
1216
  return undefined;
@@ -1349,11 +1348,12 @@ function applyStatusAndCloseReasonMutations(document, context, previousStatusNor
1349
1348
  applyStatusAndCompletionMutations(document, context, previousStatusNormalized, changedFields);
1350
1349
  applyCloseReasonMutations(document, context, previousStatusNormalized, changedFields);
1351
1350
  }
1351
+ /** Resolve priority and type changes against runtime registries before enforcing type-specific options and recording changed fields. */
1352
1352
  function applyPriorityTypeAndOptions(document, context, changedFields) {
1353
1353
  let activeTypeName = resolveTypeName(document.metadata.type, context.typeRegistry) ??
1354
1354
  document.metadata.type;
1355
1355
  if (context.options.priority !== undefined) {
1356
- document.metadata.priority = ensurePriority(context.options.priority);
1356
+ document.metadata.priority = resolvePriority(context.options.priority);
1357
1357
  changedFields.push("priority");
1358
1358
  }
1359
1359
  if (context.options.type !== undefined) {
@@ -1829,7 +1829,7 @@ function mutateUpdateDocument(document, context) {
1829
1829
  async function runUpdateWithContext(id, options, global, execution = {}) {
1830
1830
  options = await resolveUpdateTransportOptions(options);
1831
1831
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
1832
- await assertUpdateTrackerInitialized(pmRoot);
1832
+ await assertInitializedTracker(pmRoot);
1833
1833
  const settings = await readSettings(pmRoot);
1834
1834
  const statusRegistry = resolveRuntimeStatusRegistry(settings.schema);
1835
1835
  const runtimeFieldRegistry = resolveRuntimeFieldRegistry(settings.schema);
@@ -2134,4 +2134,4 @@ export const _testOnlyUpdateCommand = {
2134
2134
  resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
2135
2135
  };
2136
2136
  //# sourceMappingURL=update.js.map
2137
- //# debugId=78f8b369-1802-555d-a8cc-0147c0d8fb08
2137
+ //# debugId=5a6614ac-62fd-5680-9eed-447bfb7a167f
@@ -1,3 +1,4 @@
1
+ import { type PmCliErrorRecoveryPayload } from "../core/shared/errors.js";
1
2
  import type { ItemMetadata } from "../types/index.js";
2
3
  /** The author-controlled field from which a terminal reason was derived. */
3
4
  export type TerminalReasonSource = "explicit" | "duplicate" | "resolution" | "message" | "none";
@@ -37,6 +38,8 @@ export interface CloseOperationResult {
37
38
  item: Record<string, unknown>;
38
39
  /** Metadata fields changed by the transition. */
39
40
  changed_fields: string[];
41
+ /** Evidence-only update guidance when a successful warning close leaves acceptance fields missing. */
42
+ recovery?: PmCliErrorRecoveryPayload;
40
43
  /** Validation and lifecycle policy receipts. */
41
44
  warnings: string[];
42
45
  }
@@ -5,7 +5,7 @@
5
5
  * item enters a terminal lifecycle state.
6
6
  */
7
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]="a7ae3c89-b50b-5e4f-8273-8318bc976d84")}catch(e){}}();
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]="89e3f65e-8455-5921-bcc1-45cf572d8585")}catch(e){}}();
9
9
  import { EXIT_CODE } from "../core/shared/constants.js";
10
10
  import { PmCliError } from "../core/shared/errors.js";
11
11
  /** Default terminal policy shared by CLI, SDK, and MCP operations. */
@@ -118,4 +118,4 @@ export function applyTerminalOrderingPolicy(metadata, policy) {
118
118
  };
119
119
  }
120
120
  //# sourceMappingURL=lifecycle-policy.js.map
121
- //# debugId=a7ae3c89-b50b-5e4f-8273-8318bc976d84
121
+ //# debugId=89e3f65e-8455-5921-bcc1-45cf572d8585
@@ -0,0 +1,15 @@
1
+ /**
2
+ * @module sdk/merge/abandoned-receipts
3
+ * Settles verified restored-origin receipts through an explicit history event.
4
+ */
5
+ import type { GlobalOptions } from "../../core/shared/command-types.js";
6
+ import { type MergeDecisionReceipt } from "./receipts.js";
7
+ /** Preview or record restored-origin dispositions without treating them as applied merges. */
8
+ export declare function settleAbandonedMergeReceipts(params: {
9
+ cwd: string | null;
10
+ receipts: readonly MergeDecisionReceipt[];
11
+ dryRun: boolean;
12
+ author?: string;
13
+ message?: string;
14
+ global: GlobalOptions;
15
+ }): Promise<string[]>;
@@ -0,0 +1,47 @@
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]="cd45ee09-e4c3-5fc6-8253-1f1dc709a3a8")}catch(e){}}();
3
+ import { runHistoryRepair } from "../history-repair.js";
4
+ import { isOriginalGitStateRestored } from "./receipt-operation.js";
5
+ import { markMergeReceiptReconciled, summarizeMergeReceipt, } from "./receipts.js";
6
+ /** Preview or record restored-origin dispositions without treating them as applied merges. */
7
+ export async function settleAbandonedMergeReceipts(params) {
8
+ if (params.cwd === null)
9
+ return [];
10
+ const settled = [];
11
+ for (const receipt of params.receipts) {
12
+ if (receipt.operation === undefined ||
13
+ !(await isOriginalGitStateRestored(params.cwd, receipt.item_path, receipt.operation)))
14
+ continue;
15
+ const mergeAbandonmentProof = { gitWorkspaceRoot: params.cwd, receipt };
16
+ await runHistoryRepair(receipt.item_id, { dryRun: true, mergeAbandonmentProof }, params.global);
17
+ if (!params.dryRun) {
18
+ await runHistoryRepair(receipt.item_id, {
19
+ author: params.author ?? params.global.author,
20
+ mergeAbandonmentProof,
21
+ message: params.message ??
22
+ "Settle rebase receipt after exact original Git state restoration",
23
+ auditOperation: "merge_reconcile",
24
+ forceAuditEntry: true,
25
+ auditContext: {
26
+ merge: {
27
+ abandoned_receipts: [
28
+ {
29
+ ...summarizeMergeReceipt(receipt),
30
+ reason: "original_git_state_restored",
31
+ operation: receipt.operation,
32
+ },
33
+ ],
34
+ },
35
+ },
36
+ }, params.global);
37
+ await markMergeReceiptReconciled(params.cwd, receipt, {
38
+ requireExisting: true,
39
+ settlement: "original_git_state_restored",
40
+ });
41
+ }
42
+ settled.push(receipt.id);
43
+ }
44
+ return settled;
45
+ }
46
+ //# sourceMappingURL=abandoned-receipts.js.map
47
+ //# debugId=cd45ee09-e4c3-5fc6-8253-1f1dc709a3a8
@@ -9,7 +9,7 @@
9
9
  * merge never corrupts tracker storage the way raw conflict markers do.
10
10
  */
11
11
 
12
- !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]="5dc5f70c-0b04-51bb-983b-49b15be11587")}catch(e){}}();
12
+ !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]="22b1f103-54de-5a63-a2d2-2f99181a73e2")}catch(e){}}();
13
13
  import { readFile, writeFile } from "node:fs/promises";
14
14
  import path from "node:path";
15
15
  import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
@@ -22,6 +22,7 @@ import { nowIso } from "../../core/shared/time.js";
22
22
  import { getSettingsPath, resolvePmRoot } from "../../core/store/paths.js";
23
23
  import { readSettings } from "../../core/store/settings.js";
24
24
  import { hashItemScalarDecisionValue, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, } from "./three-way.js";
25
+ import { captureMergeReceiptOperation } from "./receipt-operation.js";
25
26
  import { summarizeMergeReceipt, writeMergeReceipt, } from "./receipts.js";
26
27
  /** Supported values accepted by the merge driver artifact contract across CLI, SDK, and MCP surfaces. */
27
28
  export const MERGE_DRIVER_ARTIFACT_VALUES = [
@@ -166,6 +167,7 @@ export async function runMergeDriver(options, global) {
166
167
  hashItemScalarDecisionValue(field === "body" ? mergedDocument.body : mergedMetadata[field]),
167
168
  ])),
168
169
  decisions: itemMerge.conflict_decisions,
170
+ operation: await captureMergeReceiptOperation(process.cwd(), options.itemPath),
169
171
  };
170
172
  }
171
173
  }
@@ -208,4 +210,4 @@ export async function runMergeDriver(options, global) {
208
210
  };
209
211
  }
210
212
  //# sourceMappingURL=driver.js.map
211
- //# debugId=5dc5f70c-0b04-51bb-983b-49b15be11587
213
+ //# debugId=22b1f103-54de-5a63-a2d2-2f99181a73e2
@@ -11,3 +11,4 @@ export { inspectMergeReceiptEvidence, listMergeReceipts, markMergeReceiptReconci
11
11
  export { MERGE_DRIVER_ARTIFACT_VALUES, runMergeDriver, type MergeDriverArtifact, type MergeDriverOptions, type MergeDriverResult, } from "./driver.js";
12
12
  export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_V2_END, PM_GITATTRIBUTES_V2_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, type MergeFenceAuditResult, type MergeDriverConfigurationAuditResult, type MergeFenceRefreshOutcome, type MergeInstallOptions, type MergeInstallContextResolution, type MergeInstallResult, } from "./install.js";
13
13
  export { runMergeReconcile, type MergeReconcileOptions, type MergeReconcileResult, } from "./reconcile.js";
14
+ export type { MergeReceiptOperation } from "./receipt-operation.js";
@@ -7,11 +7,11 @@
7
7
  * this module so packages and hosts can reuse the same merge behavior.
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]="925be497-bdd3-527b-9a88-cf9c9f682ab2")}catch(e){}}();
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]="5079995b-ef00-5fe3-b87d-0882ef976d10")}catch(e){}}();
11
11
  export { ITEM_SCALAR_MISSING_VALUE, ITEM_LATEST_TIMESTAMP_FIELDS, ITEM_UNION_COLLECTION_FIELDS, encodeItemScalarDecisionValue, hashItemScalarDecisionValue, isItemScalarMissingValue, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, } from "./three-way.js";
12
12
  export { inspectMergeReceiptEvidence, listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptEvidenceReport, runMergeReceiptReport, summarizeMergeReceipt, } from "./receipts.js";
13
13
  export { MERGE_DRIVER_ARTIFACT_VALUES, runMergeDriver, } from "./driver.js";
14
14
  export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_V2_END, PM_GITATTRIBUTES_V2_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, } from "./install.js";
15
15
  export { runMergeReconcile, } from "./reconcile.js";
16
16
  //# sourceMappingURL=index.js.map
17
- //# debugId=925be497-bdd3-527b-9a88-cf9c9f682ab2
17
+ //# debugId=5079995b-ef00-5fe3-b87d-0882ef976d10
@@ -0,0 +1,15 @@
1
+ /** Immutable pre-rebase coordinates, without branch names or item contents. */
2
+ export interface MergeReceiptOperation {
3
+ /** Git operation whose original state can be checked after it ends. */
4
+ kind: "rebase";
5
+ /** Commit from which the rebase began. */
6
+ original_head: string;
7
+ /** Original item blob at that commit. */
8
+ original_blob: string;
9
+ }
10
+ /** Capture a rebase's original commit and item blob, or omit unprovable coordinates. */
11
+ export declare function captureMergeReceiptOperation(cwd: string, itemPath: string): Promise<MergeReceiptOperation | undefined>;
12
+ /** Validate only the bounded, privacy-safe operation schema accepted by receipt readers. */
13
+ export declare function isMergeReceiptOperation(value: unknown): value is MergeReceiptOperation;
14
+ /** Prove HEAD, index, and working item all match the captured origin after Git leaves the operation. */
15
+ export declare function isOriginalGitStateRestored(cwd: string, itemPath: string, operation: MergeReceiptOperation, expectedItemRaw?: string): Promise<boolean>;
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @module sdk/merge/receipt-operation
3
+ * Records Git coordinates that let reconciliation prove a rebase restored its original state.
4
+ */
5
+
6
+ !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]="7bef66b4-7131-5998-84bd-07983a25d762")}catch(e){}}();
7
+ import { execFile } from "node:child_process";
8
+ import { createHash } from "node:crypto";
9
+ import { readdir } from "node:fs/promises";
10
+ import path from "node:path";
11
+ import { promisify } from "node:util";
12
+ import { readBoundedRegularFile } from "./receipt-file-boundary.js";
13
+ const execFileAsync = promisify(execFile);
14
+ const GIT_OBJECT_ID = /^[a-f0-9]{40}(?:[a-f0-9]{24})?$/u;
15
+ /** Capture a rebase's original commit and item blob, or omit unprovable coordinates. */
16
+ export async function captureMergeReceiptOperation(cwd, itemPath) {
17
+ const trimmedItemPath = itemPath.trim();
18
+ const normalizedItemPath = /^(['"])(.*)\1$/su.exec(trimmedItemPath)?.[2] ?? trimmedItemPath;
19
+ for (const backend of ["rebase-merge", "rebase-apply"]) {
20
+ try {
21
+ const { stdout: marker } = await execFileAsync("git", [
22
+ "rev-parse",
23
+ "--path-format=absolute",
24
+ "--git-path",
25
+ `${backend}/orig-head`,
26
+ ], { cwd, timeout: 10_000 });
27
+ const originalHead = (await readBoundedRegularFile(marker.trim(), 128))?.trim();
28
+ if (originalHead === undefined || !GIT_OBJECT_ID.test(originalHead))
29
+ continue;
30
+ const { stdout } = await execFileAsync("git", ["rev-parse", "--verify", `${originalHead}:${normalizedItemPath}`], { cwd, timeout: 10_000 });
31
+ const originalBlob = stdout.trim();
32
+ return {
33
+ kind: "rebase",
34
+ original_head: originalHead,
35
+ original_blob: originalBlob,
36
+ };
37
+ }
38
+ catch {
39
+ // No evidence is safer than inferring an abandoned operation from item drift.
40
+ }
41
+ }
42
+ return undefined;
43
+ }
44
+ /** Validate only the bounded, privacy-safe operation schema accepted by receipt readers. */
45
+ export function isMergeReceiptOperation(value) {
46
+ if (typeof value !== "object" || value === null || Array.isArray(value))
47
+ return false;
48
+ const record = value;
49
+ return (Object.keys(record).length === 3 &&
50
+ record.kind === "rebase" &&
51
+ typeof record.original_head === "string" &&
52
+ GIT_OBJECT_ID.test(record.original_head) &&
53
+ typeof record.original_blob === "string" &&
54
+ GIT_OBJECT_ID.test(record.original_blob));
55
+ }
56
+ /** Prove HEAD, index, and working item all match the captured origin after Git leaves the operation. */
57
+ export async function isOriginalGitStateRestored(cwd, itemPath, operation, expectedItemRaw) {
58
+ if (expectedItemRaw !== undefined) {
59
+ const snapshotBlob = createHash(operation.original_blob.length === 40 ? "sha1" : "sha256")
60
+ .update(`blob ${Buffer.byteLength(expectedItemRaw)}\0`)
61
+ .update(expectedItemRaw)
62
+ .digest("hex");
63
+ if (snapshotBlob !== operation.original_blob)
64
+ return false;
65
+ }
66
+ try {
67
+ const { stdout: gitDirectory } = await execFileAsync("git", ["rev-parse", "--absolute-git-dir"], { cwd, timeout: 10_000 });
68
+ const activeMarkers = new Set([
69
+ "rebase-merge",
70
+ "rebase-apply",
71
+ "MERGE_HEAD",
72
+ "CHERRY_PICK_HEAD",
73
+ "REVERT_HEAD",
74
+ ]);
75
+ if ((await readdir(gitDirectory.trim())).some((entry) => activeMarkers.has(entry)))
76
+ return false;
77
+ const { stdout: head } = await execFileAsync("git", ["rev-parse", "HEAD"], {
78
+ cwd,
79
+ timeout: 10_000,
80
+ });
81
+ if (head.trim() !== operation.original_head)
82
+ return false;
83
+ const { stdout: originalBlob } = await execFileAsync("git", ["rev-parse", "--verify", `HEAD:${itemPath}`], { cwd, timeout: 10_000 });
84
+ if (originalBlob.trim() !== operation.original_blob)
85
+ return false;
86
+ const { stdout: blob } = await execFileAsync("git", ["hash-object", "--", path.resolve(cwd, itemPath)], { cwd, timeout: 10_000 });
87
+ if (blob.trim() !== operation.original_blob)
88
+ return false;
89
+ await execFileAsync("git", ["diff", "--cached", "--quiet", "HEAD", "--", itemPath], { cwd, timeout: 10_000 });
90
+ return true;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ //# sourceMappingURL=receipt-operation.js.map
97
+ //# debugId=7bef66b4-7131-5998-84bd-07983a25d762
@@ -0,0 +1,20 @@
1
+ import type { MergeDecisionReceipt, MergeReceiptInvalidEvidence } from "./receipts.js";
2
+ /** Return whether a receipt id is safe to expose in cleartext diagnostics. */
3
+ export declare function isSafeReceiptId(value: string): boolean;
4
+ /** Versioned allowlist controlling which scalar evidence may enter tracked receipt sidecars. */
5
+ export declare const DURABLE_VALUE_POLICY: "bounded_non_sensitive_scalars_v1";
6
+ /** Return the narrowest validation class for untrusted receipt evidence. */
7
+ export declare function receiptValidationError(value: unknown, evidenceSource: "clone_local" | "durable"): MergeReceiptInvalidEvidence["validation_error"] | null;
8
+ /** Restore omitted non-selected slots from identified v1 clone-local writer contracts; never infer a missing retained or discarded value. */
9
+ export declare function normalizeLegacyReceipt(value: unknown): unknown;
10
+ /** Identify the rejected collection without exposing its values. */
11
+ export declare function receiptCollectionValidationPath(value: unknown): string | undefined;
12
+ /** Validate a complete receipt against its clone-local or durable evidence policy. */
13
+ export declare function isMergeDecisionReceipt(value: unknown, evidenceSource: "clone_local" | "durable"): value is MergeDecisionReceipt;
14
+ /** Extract a structurally valid precomputed SHA-256 decision hash. */
15
+ export declare function isPrehashedValue(value: unknown): string | undefined;
16
+ /** Convert a raw scalar into hashed evidence with an allowlisted preview. */
17
+ export declare function durableValueEvidence(field: string, value: unknown): {
18
+ pm_value_hash: string;
19
+ pm_value?: unknown;
20
+ };