@unbrained/pm-cli 2026.10.23 → 2026.10.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 (194) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/CHANGELOG.md +41 -0
  3. package/dist/cli/error-guidance.js +2 -2
  4. package/dist/cli/extension-command-help.js +2 -2
  5. package/dist/cli/register-history-activity.js +1 -1
  6. package/dist/cli-bundle/bundle-manifest.json +1 -1
  7. package/dist/cli-bundle/chunks/{chunk-R7KWBFM2.js → chunk-3CYXE6BV.js} +2 -2
  8. package/dist/cli-bundle/chunks/chunk-444VPGQT.js +20 -0
  9. package/dist/cli-bundle/chunks/{chunk-5V4HU6GK.js → chunk-4GD6QOP6.js} +21 -21
  10. package/dist/cli-bundle/chunks/{chunk-5DKCD4KV.js → chunk-5ZPT67NJ.js} +35 -34
  11. package/dist/cli-bundle/chunks/{chunk-KY34HTT2.js → chunk-7C3GCLOO.js} +29 -29
  12. package/dist/cli-bundle/chunks/{chunk-MTRYEVZR.js → chunk-7T3H24HN.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-REXCO5AG.js → chunk-EYCVAAIP.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-2UX2TAN2.js → chunk-FNZT4BTE.js} +60 -56
  15. package/dist/cli-bundle/chunks/chunk-HMJSFWHK.js +2 -0
  16. package/dist/cli-bundle/chunks/{chunk-ZDVTXLA6.js → chunk-LNKPH2DD.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-HDKY2YX3.js → chunk-MVJGGCGQ.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-3S5FLCG7.js → chunk-O3ZTGRIH.js} +2 -2
  19. package/dist/cli-bundle/chunks/{chunk-ZEI3DC5E.js → chunk-RD6UW3MW.js} +3 -3
  20. package/dist/cli-bundle/chunks/chunk-RLXK2S7P.js +2 -0
  21. package/dist/cli-bundle/chunks/{chunk-F76ZUP73.js → chunk-RQKDANP7.js} +42 -42
  22. package/dist/cli-bundle/chunks/chunk-TLMXSYJA.js +2 -0
  23. package/dist/cli-bundle/chunks/{chunk-AAX7CNL7.js → chunk-UI3FD3DW.js} +2 -2
  24. package/dist/cli-bundle/chunks/{chunk-ZMJF5HQW.js → chunk-VAEB6IUQ.js} +2 -2
  25. package/dist/cli-bundle/chunks/{chunk-ZNDYAZZ6.js → chunk-XYLBOXSH.js} +6 -6
  26. package/dist/cli-bundle/chunks/{chunk-AXGFNNI3.js → chunk-YCCGZHOR.js} +2 -2
  27. package/dist/cli-bundle/chunks/{indexed-receipt-blobs-XANVELIV.js → indexed-receipt-blobs-47I6KKDO.js} +2 -2
  28. package/dist/cli-bundle/chunks/{mutation-admission-P6LOBNLO.js → mutation-admission-747C6IUR.js} +2 -2
  29. package/dist/cli-bundle/chunks/{register-list-query-JOB65KDN.js → register-list-query-COST6KRV.js} +3 -3
  30. package/dist/cli-bundle/chunks/{register-mutation-QMNIN3RJ.js → register-mutation-JZVVJUHY.js} +2 -2
  31. package/dist/cli-bundle/chunks/register-operations-S4LKLUBJ.js +2 -0
  32. package/dist/cli-bundle/chunks/{register-setup-GNKWL3VL.js → register-setup-3ITZXPOL.js} +2 -2
  33. package/dist/cli-bundle/chunks/{settlement-hook-YUVCO65H.js → settlement-hook-5IVCF6ZY.js} +2 -2
  34. package/dist/cli-bundle/chunks/stage-3UUIYROS.js +2 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-DWQMYLFM.js → chunk-22727JYL.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-4MNUQCGR.js → chunk-3FM75SBJ.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-ZHMF34DT.js → chunk-3M5FZCMC.js} +53 -53
  38. package/dist/cli-bundle/focused-chunks/{chunk-BUZ2Z4P3.js → chunk-46KDJH3K.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-5LBZR6YW.js +2 -0
  40. package/dist/cli-bundle/focused-chunks/{chunk-EDXTOAXP.js → chunk-74KC7FUQ.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/chunk-77NU7NPN.js +2 -0
  42. package/dist/cli-bundle/focused-chunks/{chunk-MLET6I3I.js → chunk-7DEZT4JN.js} +2 -2
  43. package/dist/cli-bundle/focused-chunks/{chunk-NSMZY6IK.js → chunk-B5JOVH5F.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/chunk-HMYDUEQK.js +8 -0
  45. package/dist/cli-bundle/focused-chunks/chunk-IVLIUPVV.js +12 -0
  46. package/dist/cli-bundle/focused-chunks/chunk-KIIGME23.js +2 -0
  47. package/dist/cli-bundle/focused-chunks/{chunk-P7DPS5M4.js → chunk-LWJ2X75I.js} +24 -24
  48. package/dist/cli-bundle/focused-chunks/{chunk-6GTZ24YV.js → chunk-MT5TYMEU.js} +2 -2
  49. package/dist/cli-bundle/focused-chunks/{chunk-OMXMYTEX.js → chunk-NC5HUGHU.js} +3 -3
  50. package/dist/cli-bundle/focused-chunks/chunk-NI5SG2M2.js +2 -0
  51. package/dist/cli-bundle/focused-chunks/chunk-QH5KMIYZ.js +91 -0
  52. package/dist/cli-bundle/focused-chunks/{chunk-UNTCCJPL.js → chunk-U6HXIF6G.js} +2 -2
  53. package/dist/cli-bundle/focused-chunks/{chunk-CGL36F6I.js → chunk-URWYYJ7K.js} +2 -2
  54. package/dist/cli-bundle/focused-chunks/{chunk-I2USTQNQ.js → chunk-W7MCCFYV.js} +2 -2
  55. package/dist/cli-bundle/focused-chunks/chunk-WMPDY5ZU.js +21 -0
  56. package/dist/cli-bundle/focused-chunks/{chunk-R536272H.js → chunk-Y4JHHY24.js} +2 -2
  57. package/dist/cli-bundle/focused-chunks/{chunk-KI5YFKNN.js → chunk-ZYCOMRFT.js} +2 -2
  58. package/dist/cli-bundle/focused-chunks/{indexed-receipt-blobs-FVOA3XMI.js → indexed-receipt-blobs-YCLN2ZZG.js} +2 -2
  59. package/dist/cli-bundle/focused-chunks/{mutation-admission-HTFAIHJL.js → mutation-admission-BQBQXILV.js} +2 -2
  60. package/dist/cli-bundle/focused-chunks/{settlement-hook-2VXEB6PP.js → settlement-hook-XVS6P2XI.js} +2 -2
  61. package/dist/cli-bundle/focused-chunks/stage-VSIL4MTZ.js +2 -0
  62. package/dist/cli-bundle/main.js +21 -21
  63. package/dist/cli-bundle/sdk-authoring.js +1 -1
  64. package/dist/cli-bundle/sdk-contracts.js +2 -2
  65. package/dist/cli-bundle/sdk-core.js +24 -24
  66. package/dist/cli-bundle/sdk-governance.js +1 -1
  67. package/dist/cli-bundle/sdk-graph.js +1 -1
  68. package/dist/cli-bundle/sdk-merge.js +51 -52
  69. package/dist/cli-bundle/sdk-query.js +1 -1
  70. package/dist/cli-bundle/sdk-runtime.js +1 -1
  71. package/dist/cli-bundle/sdk-testing.js +1 -1
  72. package/dist/cli-bundle/sdk.js +9 -9
  73. package/dist/core/checkpoint/mutation-checkpoint.d.ts +6 -3
  74. package/dist/core/checkpoint/mutation-checkpoint.js +2 -2
  75. package/dist/core/checkpoint/mutation-context.d.ts +10 -0
  76. package/dist/core/checkpoint/mutation-context.js +2 -0
  77. package/dist/core/diagnostics/remediation.js +1 -1
  78. package/dist/core/shared/errors.d.ts +13 -0
  79. package/dist/core/shared/errors.js +1 -1
  80. package/dist/core/store/item-store.js +1 -1
  81. package/dist/core/store/settings.js +2 -2
  82. package/dist/sdk/agent/command-recovery.d.ts +1 -0
  83. package/dist/sdk/agent/command-recovery.js +1 -1
  84. package/dist/sdk/agent/linked-resource-recovery.d.ts +13 -0
  85. package/dist/sdk/agent/linked-resource-recovery.js +2 -0
  86. package/dist/sdk/cli-contracts/commander-types.js +1 -1
  87. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  88. package/dist/sdk/cli-contracts/flag-contracts.js +1 -1
  89. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +1 -1
  90. package/dist/sdk/cli-contracts/grammar-contracts.js +1 -1
  91. package/dist/sdk/cli-contracts/registration-helpers.d.ts +2 -0
  92. package/dist/sdk/cli-contracts/registration-helpers.js +2 -2
  93. package/dist/sdk/cli-contracts/runtime-contracts.js +1 -1
  94. package/dist/sdk/cli-contracts/tool-option-contracts.js +1 -1
  95. package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +3 -2
  96. package/dist/sdk/completion/fish.js +3 -1
  97. package/dist/sdk/completion/zsh.js +3 -1
  98. package/dist/sdk/core.d.ts +1 -1
  99. package/dist/sdk/core.js +1 -1
  100. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +1 -1
  101. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +1 -1
  102. package/dist/sdk/governance/health-merge-evidence.d.ts +5 -0
  103. package/dist/sdk/governance/health-merge-evidence.js +1 -1
  104. package/dist/sdk/governance/health.js +1 -1
  105. package/dist/sdk/index.d.ts +2 -1
  106. package/dist/sdk/index.js +1 -1
  107. package/dist/sdk/lifecycle/checkpoint-rollback.d.ts +7 -0
  108. package/dist/sdk/lifecycle/checkpoint-rollback.js +2 -0
  109. package/dist/sdk/lifecycle/close-many.d.ts +1 -1
  110. package/dist/sdk/lifecycle/close-many.js +1 -1
  111. package/dist/sdk/lifecycle/update-many.d.ts +1 -1
  112. package/dist/sdk/lifecycle/update-many.js +1 -1
  113. package/dist/sdk/merge/history-scalar-rebase.d.ts +9 -0
  114. package/dist/sdk/merge/history-scalar-rebase.js +2 -0
  115. package/dist/sdk/merge/ignored-artifacts.d.ts +13 -0
  116. package/dist/sdk/merge/ignored-artifacts.js +2 -0
  117. package/dist/sdk/merge/stage.js +1 -1
  118. package/dist/sdk/merge/three-way.js +1 -1
  119. package/dist/sdk/public-surface.json +1 -1
  120. package/dist/sdk/query/activity.d.ts +14 -2
  121. package/dist/sdk/query/activity.js +1 -1
  122. package/dist/sdk/query/calendar.d.ts +16 -0
  123. package/dist/sdk/query/calendar.js +3 -3
  124. package/dist/sdk/query/context.d.ts +2 -1
  125. package/dist/sdk/query/context.js +2 -2
  126. package/dist/sdk/query/get.d.ts +2 -1
  127. package/dist/sdk/query/get.js +1 -1
  128. package/dist/sdk/query/list.d.ts +2 -1
  129. package/dist/sdk/query/list.js +1 -1
  130. package/dist/sdk/query/search/types.d.ts +2 -1
  131. package/dist/sdk/query/search-contracts.js +1 -1
  132. package/dist/sdk/query/window-pagination.d.ts +20 -0
  133. package/dist/sdk/query/window-pagination.js +2 -0
  134. package/dist/sdk/query.d.ts +1 -0
  135. package/dist/sdk/query.js +1 -1
  136. package/dist/sdk/read-output-contracts.d.ts +10 -2
  137. package/dist/sdk/read-output-contracts.js +1 -1
  138. package/dist/sdk/runtime-input.js +1 -1
  139. package/dist/sdk/runtime-primitives.d.ts +1 -0
  140. package/dist/sdk/runtime-primitives.js +1 -1
  141. package/dist/sdk/runtime.d.ts +11 -11
  142. package/dist/sdk/runtime.js +1 -1
  143. package/dist/sdk/schema-migration.js +2 -2
  144. package/dist/sdk/templates.d.ts +7 -1
  145. package/dist/sdk/templates.js +2 -2
  146. package/dist/sdk/test/batch.js +2 -2
  147. package/dist/sdk/test/entry.d.ts +5 -1
  148. package/dist/sdk/test/entry.js +2 -1
  149. package/dist/sdk/test/execution.js +2 -2
  150. package/docs/COMMANDS.md +40 -3
  151. package/docs/EXTENSIONS.md +1 -1
  152. package/docs/MERGE_SAFETY.md +28 -0
  153. package/docs/READ_OUTPUT_CONTRACTS.md +15 -0
  154. package/docs/SDK.md +130 -6
  155. package/docs/TESTING.md +28 -0
  156. package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
  157. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +7 -3
  158. package/marketplace.json +1 -1
  159. package/package.json +1 -1
  160. package/packages/pm-beads/package.json +1 -1
  161. package/packages/pm-calendar/extensions/calendar/index.ts +6 -0
  162. package/packages/pm-calendar/package.json +1 -1
  163. package/packages/pm-command-kit/package.json +1 -1
  164. package/packages/pm-digital-twin/package.json +1 -1
  165. package/packages/pm-governance-audit/package.json +1 -1
  166. package/packages/pm-guide-shell/package.json +1 -1
  167. package/packages/pm-kanban/package.json +1 -1
  168. package/packages/pm-lifecycle-hooks/package.json +1 -1
  169. package/packages/pm-linked-test-adapters/package.json +1 -1
  170. package/packages/pm-search-advanced/package.json +1 -1
  171. package/packages/pm-templates/extensions/templates/runtime.ts +3 -1
  172. package/packages/pm-templates/package.json +1 -1
  173. package/packages/pm-todos/package.json +1 -1
  174. package/packages/pm-vcs/package.json +1 -1
  175. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  176. package/plugins/pm-claude/package.json +1 -1
  177. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  178. package/plugins/pm-codex/package.json +1 -1
  179. package/plugins/pm-codex/plugin.json +1 -1
  180. package/runtime-dependencies.json +1 -1
  181. package/dist/cli-bundle/chunks/chunk-2LTGJ5DL.js +0 -2
  182. package/dist/cli-bundle/chunks/chunk-MMVX5L32.js +0 -20
  183. package/dist/cli-bundle/chunks/chunk-QSY55FTA.js +0 -2
  184. package/dist/cli-bundle/chunks/register-operations-Z4VET3I7.js +0 -2
  185. package/dist/cli-bundle/chunks/stage-FW5OXCCR.js +0 -2
  186. package/dist/cli-bundle/focused-chunks/chunk-BM652VCB.js +0 -8
  187. package/dist/cli-bundle/focused-chunks/chunk-FO4U3FIP.js +0 -91
  188. package/dist/cli-bundle/focused-chunks/chunk-GXKP56W7.js +0 -2
  189. package/dist/cli-bundle/focused-chunks/chunk-JDN34LEZ.js +0 -2
  190. package/dist/cli-bundle/focused-chunks/chunk-LEHGCPZ6.js +0 -12
  191. package/dist/cli-bundle/focused-chunks/chunk-XIZYJDYW.js +0 -2
  192. package/dist/cli-bundle/focused-chunks/chunk-Z5LDTMZ3.js +0 -2
  193. package/dist/cli-bundle/focused-chunks/chunk-ZR6ZKQUK.js +0 -20
  194. package/dist/cli-bundle/focused-chunks/stage-X3BUGEJT.js +0 -2
@@ -40,7 +40,7 @@ error?:string;
40
40
  }
41
41
  interface UpdateManyRollbackResultRow {
42
42
  id:string;
43
- status:"restored" | "failed";
43
+ status:"restored" | "failed" | "skipped";
44
44
  changed_fields?:string[];
45
45
  warnings?:string[];
46
46
  error?:string;
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="4a59a772-3e2a-5ae2-88c1-a96bc36f9f85")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{createCheckpointId,loadMutationCheckpoint,restoreCheckpointItems,writeMutationCheckpoint,toItemRecord,applyAcceptanceCriteriaMutations,applyTagRemovals,mergeAdditiveTags,parseOptionalNonNegativeInteger,parseTags,splitAcceptanceCriteria,resolvePriority,normalizeStatusInput,resolveItemTypeRegistry,resolveTypeName,collectRuntimeUpdateFieldValues,buildInvalidTypeError,resolveItemTypesFilePath,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,toErrorMessage,stableValueEquals,nowIso,preserveMutationStdinTokenLiterals,resolveIsoOrRelative,getActiveExtensionRegistrations,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{assertDependencyTargetsResolvable}from"../dependency-flag-validation.js";import{parseStatusFilterCsv}from"../../core/item/status-filter.js";import{hasListFilters}from"../query/list-filter-shared.js";import{runList}from"../query/list.js";import{runRestore}from"./restore.js";import{assertUpdateMutationOptionCombinations,parseDependencyAdditions,resolveUpdateTransportOptions,runUpdate}from"./update.js";import{derivePmBulkMutationEffect}from"../cli-contracts/command-exit-contracts.js";const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION=1,UPDATE_MANY_CHECKPOINT_SUBDIR="update-many",NON_MUTATION_UPDATE_OPTION_KEYS=new Set(["author","message","force","ownershipMetadataBypass","ownershipDependencyBypass","allowUnresolvedDeps"]),UPDATE_MANY_MUTATION_FLAG_GUIDANCE=["--status","--priority","--type","--tags","--description","--body","--deadline","--estimate","--assignee","--dep","--dep-remove","--comment","--note","--learning","--file","--test","--doc","--replace-deps","--replace-tests","--replace-files","--replace-docs","--unset","--clear-*"].join(", "),UPDATE_OPTION_TO_ITEM_KEY={title:"title",description:"description",body:"body",status:"status",closeReason:"close_reason",priority:"priority",type:"type",deadline:"deadline",estimatedMinutes:"estimated_minutes",acceptanceCriteria:"acceptance_criteria",definitionOfReady:"definition_of_ready",order:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",whyNow:"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blockedBy:"blocked_by",blockedReason:"blocked_reason",unblockNote:"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",reproSteps:"repro_steps",resolution:"resolution",expectedResult:"expected_result",actualResult:"actual_result",affectedVersion:"affected_version",fixedVersion:"fixed_version",component:"component",regression:"regression",customerImpact:"customer_impact"},COLLECTION_MUTATION_PLAN_DEFINITIONS=[{field:"dependencies",addKey:"dep",removeKey:"depRemove",clearKey:"clearDeps",replaceKey:"replaceDeps"},{field:"comments",addKey:"comment",clearKey:"clearComments"},{field:"notes",addKey:"note",clearKey:"clearNotes"},{field:"learnings",addKey:"learning",clearKey:"clearLearnings"},{field:"files",addKey:"file",clearKey:"clearFiles",replaceKey:"replaceFiles"},{field:"tests",addKey:"test",clearKey:"clearTests",replaceKey:"replaceTests"},{field:"docs",addKey:"doc",clearKey:"clearDocs",replaceKey:"replaceDocs"},{field:"reminders",addKey:"reminder",clearKey:"clearReminders"},{field:"events",addKey:"event",clearKey:"clearEvents"},{field:"type_options",addKey:"typeOption",clearKey:"clearTypeOptions"}],UNSET_FIELD_ALIASES={close_reason:"close_reason","close-reason":"close_reason",deadline:"deadline",estimate:"estimated_minutes",estimated_minutes:"estimated_minutes","estimated-minutes":"estimated_minutes",acceptance_criteria:"acceptance_criteria","acceptance-criteria":"acceptance_criteria",ac:"acceptance_criteria",definition_of_ready:"definition_of_ready","definition-of-ready":"definition_of_ready",order:"order",rank:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",why_now:"why_now","why-now":"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blocked_by:"blocked_by","blocked-by":"blocked_by",blocked_reason:"blocked_reason","blocked-reason":"blocked_reason",unblock_note:"unblock_note","unblock-note":"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",repro_steps:"repro_steps","repro-steps":"repro_steps",resolution:"resolution",expected_result:"expected_result","expected-result":"expected_result",actual_result:"actual_result","actual-result":"actual_result",affected_version:"affected_version","affected-version":"affected_version",fixed_version:"fixed_version","fixed-version":"fixed_version",component:"component",regression:"regression",customer_impact:"customer_impact","customer-impact":"customer_impact",type_options:"type_options","type-options":"type_options",tags:"tags"},sanitizeUpdateOptionsForSummary=options=>{const summary={};for(const[key,value]of Object.entries(options))NON_MUTATION_UPDATE_OPTION_KEYS.has(key)||value!==void 0&&(summary[key]=value);return summary},hasAnyUpdateMutationInput=options=>Object.keys(sanitizeUpdateOptionsForSummary(options)).length>0,trimPreviewValue=value=>typeof value=="string"?value.trim():value,normalizeIntegerPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isInteger(parsed)?parsed:trimmed},normalizeNumericPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isFinite(parsed)?parsed:trimmed},normalizeRegressionPreviewValue=value=>{const normalized=String(value).trim().toLowerCase();return new Map([["true",!0],["1",!0],["false",!1],["0",!1]]).get(normalized)??trimPreviewValue(value)},PREVIEW_VALUE_NORMALIZERS={priority:normalizeIntegerPreviewValue,estimatedMinutes:normalizeNumericPreviewValue,order:normalizeNumericPreviewValue,rank:normalizeNumericPreviewValue,regression:normalizeRegressionPreviewValue},toComparablePreviewValue=(optionKey,value)=>{if(value!==void 0)return(PREVIEW_VALUE_NORMALIZERS[optionKey]??trimPreviewValue)(value)},normalizeUnsetField=rawField=>{const normalized=rawField.trim().toLowerCase().replaceAll("-","_");return UNSET_FIELD_ALIASES[normalized]??normalized},areValuesEqual=(left,right)=>stableValueEquals(left,right),normalizeCollectionBeforeValue=(field,value)=>value!==void 0?value:field==="type_options"?{}:[],collectionValueCount=(field,value)=>Array.isArray(value)?value.length:field==="type_options"&&value&&typeof value=="object"?Object.keys(value).length:0,resolveCollectionMutationOperation=params=>params.replace?"replace":params.clear?"clear_or_reset":params.removeCount>0?"merge_remove":"append",readOptionalUpdateValue=(update,key)=>key===void 0?void 0:update[key],updateArrayValueCount=value=>Array.isArray(value)?value.length:0,buildCollectionMutationPlan=(definition,row,update)=>{const addValues=update[definition.addKey],removeValues=readOptionalUpdateValue(update,definition.removeKey),addCount=updateArrayValueCount(addValues),removeCount=updateArrayValueCount(removeValues),clear=update[definition.clearKey]===!0,replace=readOptionalUpdateValue(update,definition.replaceKey)===!0;if(![clear,replace,addCount>0,removeCount>0].includes(!0))return;const before=normalizeCollectionBeforeValue(definition.field,row[definition.field]);return{field:definition.field,before,after:{operation:resolveCollectionMutationOperation({replace,clear,removeCount}),clear,replace,add_count:addCount,remove_count:removeCount,before_count:collectionValueCount(definition.field,before)}}},buildCollectionMutationPlans=(row,update)=>{const changes=[];for(const definition of COLLECTION_MUTATION_PLAN_DEFINITIONS){const plan=buildCollectionMutationPlan(definition,row,update);plan!==void 0&&changes.push(plan)}return changes},normalizeExistingTags=value=>Array.isArray(value)?value.filter(tag=>typeof tag=="string"):[],buildTagMutationPlan=(row,update)=>{if(![update.tags!==void 0,updateArrayValueCount(update.addTags)>0,updateArrayValueCount(update.removeTags)>0].includes(!0))return;const existing=normalizeExistingTags(row.tags),baseTags=update.tags===void 0?existing:parseTags(update.tags),withAdditions=mergeAdditiveTags(baseTags,update.addTags),after=applyTagRemovals(withAdditions,update.removeTags).slice().sort((a,b)=>a.localeCompare(b)),before=existing.slice().sort((a,b)=>a.localeCompare(b));if(!areValuesEqual(before,after))return{field:"tags",before:existing,after}},buildAcceptanceCriteriaMutationPlan=(row,update)=>{const before=row.acceptance_criteria,mutation=applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(before),update.addAc,update.removeAc);if(mutation.unmatchedRemovals.length>0)throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`,EXIT_CODE.NOT_FOUND,{code:"acceptance_criteria_remove_unmatched",reason:"exact_match_not_found",field:"acceptance_criteria",unmatched:mutation.unmatchedRemovals});const after=mutation.criteria.join("; ");if(!areValuesEqual(typeof before=="string"?before:"",after))return{field:"acceptance_criteria",before,after}},appendScalarMutationPlans=(changes,row,update)=>{for(const[optionKey,itemKey]of Object.entries(UPDATE_OPTION_TO_ITEM_KEY)){const candidate=update[optionKey];if(candidate===void 0)continue;const before=row[itemKey],after=toComparablePreviewValue(optionKey,candidate);areValuesEqual(before,after)||changes.push({field:itemKey,before,after})}},appendRuntimeFieldMutationPlans=(changes,row,update,runtimeFieldRegistry)=>{const runtimeFieldUpdates=collectRuntimeUpdateFieldValues(update,runtimeFieldRegistry,["update_many"]);for(const[field,after]of Object.entries(runtimeFieldUpdates)){const before=row[field];areValuesEqual(before,after)||changes.push({field,before,after})}},appendUnsetMutationPlans=(changes,row,unset)=>{for(const rawUnsetField of unset??[]){const field=normalizeUnsetField(rawUnsetField),before=row[field];before!==void 0&&changes.push({field,before,after:null})}},buildPlannedItemDiff=(item,runtimeFieldRegistry,update={})=>{const row=toItemRecord(item),changes=[],tagPlan=buildTagMutationPlan(row,update);if(tagPlan&&changes.push(tagPlan),appendScalarMutationPlans(changes,row,update),updateArrayValueCount(update.addAc)>0||updateArrayValueCount(update.removeAc)>0){const acceptanceCriteriaChange=buildAcceptanceCriteriaMutationPlan(row,update);acceptanceCriteriaChange!==void 0&&changes.push(acceptanceCriteriaChange)}return changes.push(...buildCollectionMutationPlans(row,update)),appendRuntimeFieldMutationPlans(changes,row,update,runtimeFieldRegistry),appendUnsetMutationPlans(changes,row,update.unset),{id:item.id,changes}},normalizeStatusFilter=(value,statusRegistry)=>parseStatusFilterCsv(value,statusRegistry,{strict:!0,flagLabel:"--filter-status"}),rejectBlankIdsFilter=list=>{if(list?.ids!=null&&String(list.ids).trim().length===0)throw new PmCliError("--ids requires at least one non-empty item ID",EXIT_CODE.USAGE)},PLANNED_UPDATE_VALIDATORS=[({update})=>{update.priority!==void 0&&resolvePriority(update.priority)},({update,settings,pmRoot})=>{if(update.type===void 0)return;const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());if(!resolveTypeName(update.type,typeRegistry))throw new PmCliError(buildInvalidTypeError(update.type,typeRegistry.types,resolveItemTypesFilePath(pmRoot,settings.schema)),EXIT_CODE.USAGE)},({update,statusRegistry})=>{if(update.status!==void 0&&!normalizeStatusInput(update.status,statusRegistry)){const allowedStatuses=statusRegistry.definitions.map(definition=>definition.id);throw new PmCliError(`Invalid --status value "${update.status}". Allowed: ${allowedStatuses.join(", ")}`,EXIT_CODE.USAGE)}},({update})=>{update.deadline!==void 0&&resolveIsoOrRelative(update.deadline,new Date,"deadline")},({update})=>{update.estimatedMinutes!==void 0&&parseOptionalNonNegativeInteger(update.estimatedMinutes,"estimated-minutes")}],assertPlannedUpdateValuesValid=(update,settings,statusRegistry,pmRoot)=>{const context={update,settings,statusRegistry,pmRoot};for(const validate of PLANNED_UPDATE_VALIDATORS)validate(context)},runUpdateManyRollback=async params=>{const checkpoint=await loadMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.rollbackId,UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION),restoreMessage=params.options.update?.message??`Rollback update-many checkpoint ${checkpoint.id}`,rollback=await restoreCheckpointItems(checkpoint.items,(id,targetUpdatedAt)=>runRestore(id,targetUpdatedAt,{author:params.options.update?.author,message:restoreMessage,force:params.options.update?.force??!0},params.global));return{...derivePmBulkMutationEffect({applied:rollback.restored_ids.length,skipped:0,failed:rollback.failed_count,unmatched:0}),mode:"rollback",matched_count:checkpoint.items.length,dry_run:!1,rollback_checkpoint_id:checkpoint.id,checkpoint:{id:checkpoint.id,created_at:checkpoint.created_at,path:checkpoint.path,rollback_command:`pm update-many --rollback ${checkpoint.id}`},restored_count:rollback.restored_ids.length,failed_count:rollback.failed_count,rows:rollback.rows,ids:rollback.restored_ids}},writeUpdateManyCheckpoint=async params=>{const checkpointPayload={schema_version:UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION,id:params.checkpointId,created_at:params.nowValue,author:resolveAuthor(params.options.update?.author,"unknown"),status_filter:params.statusFilter??null,list_filters:params.filters,update_options:params.updateSummary,items:params.checkpointItems},checkpointPath=await writeMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.checkpointId,checkpointPayload);return{id:params.checkpointId,created_at:params.nowValue,path:checkpointPath,rollback_command:`pm update-many --rollback ${params.checkpointId}`}},collectUnmatchedRequestedIds=(rawIds,existingItems)=>{if(rawIds==null)return;const requested=[...new Set(String(rawIds).split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0))],existing=new Set(existingItems.map(item=>item.id));return requested.filter(id=>!existing.has(id))},buildUnmatchedIdFields=plan=>plan.unmatchedIds===void 0?{}:{unmatched_ids:plan.unmatchedIds,unmatched_count:plan.unmatchedIds.length},loadUpdateManyRuntimeContext=async global2=>{const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);return{pmRoot,settings,statusRegistry:resolveRuntimeStatusRegistry(settings.schema),runtimeFieldRegistry:resolveRuntimeFieldRegistry(settings.schema)}},runRequestedUpdateManyRollback=params=>{if(params.options.dryRun===!0)throw new PmCliError("--dry-run cannot be combined with --rollback",EXIT_CODE.USAGE);if(hasListFilters(params.options.list,params.options.status))throw new PmCliError("Rollback mode does not accept filter options",EXIT_CODE.USAGE);if(Object.keys(params.updateSummary).length>0)throw new PmCliError("Rollback mode does not accept update mutation flags",EXIT_CODE.USAGE);return runUpdateManyRollback({pmRoot:params.runtime.pmRoot,rollbackId:params.rollbackId,options:params.options,global:params.global})},buildUpdateManyPlan=async params=>{normalizeStatusFilter(params.options.status,params.runtime.statusRegistry);const listed=await runList(void 0,{...params.options.list,status:params.options.status,compact:void 0,brief:void 0,fields:void 0,includeBody:!0,full:!0},params.global),planned=listed.items.map(item=>{const diff=buildPlannedItemDiff(item,params.runtime.runtimeFieldRegistry,params.options.update);return params.dependencyWarnings.length===0?diff:{...diff,warnings:[...params.dependencyWarnings]}}),existenceItems=params.options.list?.ids==null?[]:(await runList(void 0,{ids:params.options.list.ids,noTruncate:!0,full:!0},params.global)).items;return{listed,planned,actionable:planned.filter(row=>row.changes.length>0),updateSummary:params.updateSummary,unmatchedIds:collectUnmatchedRequestedIds(params.options.list?.ids,existenceItems)}},buildUpdateManyDryRunResult=plan=>({outcome:"effect",exit_code:EXIT_CODE.SUCCESS,mode:"dry_run",matched_count:plan.listed.items.length,dry_run:!0,filters:plan.listed.filters,planned_update_options:plan.updateSummary,item_plans:plan.planned,ids:[],...buildUnmatchedIdFields(plan)}),buildUpdateManyNoopResult=plan=>({...derivePmBulkMutationEffect({applied:0,skipped:plan.listed.items.length,failed:0,unmatched:plan.unmatchedIds?.length??0}),mode:"apply",matched_count:plan.listed.items.length,dry_run:!1,filters:plan.listed.filters,planned_update_options:plan.updateSummary,updated_count:0,skipped_count:plan.listed.items.length,failed_count:0,rows:plan.planned.map(row=>({id:row.id,status:"skipped"})),ids:[],...buildUnmatchedIdFields(plan)}),applyUpdateManyRows=async params=>{const rows=[],updatedIds=[],updateMessage=params.options.update.message??`update-many apply ${params.checkpointId}`,actionableById=new Set(params.plans.filter(row=>row.changes.length>0).map(row=>row.id));for(const item of params.items){if(!actionableById.has(item.id)){rows.push({id:item.id,status:"skipped"});continue}try{const rowUpdateOptions=preserveMutationStdinTokenLiterals({...params.options.update,message:updateMessage,runtimeFieldCommands:["update_many"]}),result=await runUpdate(item.id,rowUpdateOptions,params.global);rows.push({id:item.id,status:"updated",changed_fields:result.changed_fields,warnings:result.warnings}),updatedIds.push(item.id)}catch(error){rows.push({id:item.id,status:"failed",error:toErrorMessage(error)})}}return{rows,updatedIds}},applyUpdateManyPlan=async params=>{if(params.plan.actionable.length===0)return buildUpdateManyNoopResult(params.plan);const nowValue=nowIso(),checkpointId=createCheckpointId(UPDATE_MANY_CHECKPOINT_SUBDIR,nowValue),actionableById=new Set(params.plan.actionable.map(row=>row.id)),checkpointItems=params.plan.listed.items.filter(item=>actionableById.has(item.id)).map(item=>({id:item.id,target_updated_at:item.updated_at})),checkpointInfo=params.options.checkpoint===!1?void 0:await writeUpdateManyCheckpoint({pmRoot:params.runtime.pmRoot,checkpointId,nowValue,options:params.options,statusFilter:params.options.status,filters:params.plan.listed.filters,updateSummary:params.plan.updateSummary,checkpointItems}),applied=await applyUpdateManyRows({items:params.plan.listed.items,plans:params.plan.planned,options:params.options,global:params.global,checkpointId}),countStatus=status=>applied.rows.filter(row=>row.status===status).length,updatedCount=countStatus("updated"),skippedCount=countStatus("skipped"),failedCount=countStatus("failed");return{...derivePmBulkMutationEffect({applied:updatedCount,skipped:skippedCount,failed:failedCount,unmatched:params.plan.unmatchedIds?.length??0}),mode:"apply",matched_count:params.plan.listed.items.length,dry_run:!1,filters:params.plan.listed.filters,planned_update_options:params.plan.updateSummary,...checkpointInfo?{checkpoint:checkpointInfo}:{},updated_count:updatedCount,skipped_count:skippedCount,failed_count:failedCount,rows:applied.rows,ids:applied.updatedIds,...buildUnmatchedIdFields(params.plan)}},runUpdateMany=async(options,global2)=>{const runtime=await loadUpdateManyRuntimeContext(global2),rollbackId=typeof options.rollback=="string"?options.rollback:void 0;rollbackId===void 0&&(options={...options,update:preserveMutationStdinTokenLiterals(await resolveUpdateTransportOptions(options.update))});const updateSummary=sanitizeUpdateOptionsForSummary(options.update);if(rejectBlankIdsFilter(options.list),rollbackId!==void 0)return runRequestedUpdateManyRollback({runtime,rollbackId,options,global:global2,updateSummary});if(!hasAnyUpdateMutationInput(options.update)&&options.dryRun!==!0)throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}), or pass --dry-run for a filter-only preview.`,EXIT_CODE.USAGE);assertPlannedUpdateValuesValid(options.update,runtime.settings,runtime.statusRegistry,runtime.pmRoot),assertUpdateMutationOptionCombinations(options.update);const dependencyWarnings=await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps}),plan=await buildUpdateManyPlan({options,global:global2,runtime,updateSummary,dependencyWarnings});return await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps,holders:plan.listed.items.map(item=>({id:item.id,createdAt:item.created_at})),schema:runtime.settings.schema}),options.dryRun===!0?buildUpdateManyDryRunResult(plan):applyUpdateManyPlan({runtime,options,global:global2,plan})},_testOnlyUpdateManyCommand={assertPlannedUpdateValuesValid,buildCollectionMutationPlans,buildPlannedItemDiff,buildTagMutationPlan,collectionValueCount,hasAnyUpdateMutationInput,hasListFilters,normalizeStatusFilter,normalizeCollectionBeforeValue,normalizeExistingTags,normalizeUnsetField,rejectBlankIdsFilter,sanitizeUpdateOptionsForSummary,toComparablePreviewValue};export{_testOnlyUpdateManyCommand,runUpdateMany};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="631c5c02-967a-53ca-9f1c-fa1a80bf3f4d")}catch{}})();import{assertInitializedTracker}from"../environment/tracker-preflight.js";import{withCheckpointMutation}from"../../core/checkpoint/mutation-context.js";import{resolveCheckpointRollbackId}from"../../core/checkpoint/mutation-checkpoint.js";import{rollbackMutationCheckpoint}from"./checkpoint-rollback.js";import{createCheckpointId,loadMutationCheckpoint,writeMutationCheckpoint,toItemRecord,applyAcceptanceCriteriaMutations,applyTagRemovals,mergeAdditiveTags,parseOptionalNonNegativeInteger,parseTags,splitAcceptanceCriteria,resolvePriority,normalizeStatusInput,resolveItemTypeRegistry,resolveTypeName,collectRuntimeUpdateFieldValues,buildInvalidTypeError,resolveItemTypesFilePath,resolveRuntimeFieldRegistry,resolveRuntimeStatusRegistry,EXIT_CODE,PmCliError,toErrorMessage,stableValueEquals,nowIso,preserveMutationStdinTokenLiterals,resolveIsoOrRelative,getActiveExtensionRegistrations,resolvePmRoot,readSettings,resolveAuthor}from"../runtime-primitives.js";import{assertDependencyTargetsResolvable}from"../dependency-flag-validation.js";import{parseStatusFilterCsv}from"../../core/item/status-filter.js";import{hasListFilters}from"../query/list-filter-shared.js";import{runList}from"../query/list.js";import{assertUpdateMutationOptionCombinations,parseDependencyAdditions,resolveUpdateTransportOptions,runUpdate}from"./update.js";import{derivePmBulkMutationEffect}from"../cli-contracts/command-exit-contracts.js";const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION=2,UPDATE_MANY_CHECKPOINT_SUBDIR="update-many",NON_MUTATION_UPDATE_OPTION_KEYS=new Set(["author","message","force","ownershipMetadataBypass","ownershipDependencyBypass","allowUnresolvedDeps"]),UPDATE_MANY_MUTATION_FLAG_GUIDANCE=["--status","--priority","--type","--tags","--description","--body","--deadline","--estimate","--assignee","--dep","--dep-remove","--comment","--note","--learning","--file","--test","--doc","--replace-deps","--replace-tests","--replace-files","--replace-docs","--unset","--clear-*"].join(", "),UPDATE_OPTION_TO_ITEM_KEY={title:"title",description:"description",body:"body",status:"status",closeReason:"close_reason",priority:"priority",type:"type",deadline:"deadline",estimatedMinutes:"estimated_minutes",acceptanceCriteria:"acceptance_criteria",definitionOfReady:"definition_of_ready",order:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",whyNow:"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blockedBy:"blocked_by",blockedReason:"blocked_reason",unblockNote:"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",reproSteps:"repro_steps",resolution:"resolution",expectedResult:"expected_result",actualResult:"actual_result",affectedVersion:"affected_version",fixedVersion:"fixed_version",component:"component",regression:"regression",customerImpact:"customer_impact"},COLLECTION_MUTATION_PLAN_DEFINITIONS=[{field:"dependencies",addKey:"dep",removeKey:"depRemove",clearKey:"clearDeps",replaceKey:"replaceDeps"},{field:"comments",addKey:"comment",clearKey:"clearComments"},{field:"notes",addKey:"note",clearKey:"clearNotes"},{field:"learnings",addKey:"learning",clearKey:"clearLearnings"},{field:"files",addKey:"file",clearKey:"clearFiles",replaceKey:"replaceFiles"},{field:"tests",addKey:"test",clearKey:"clearTests",replaceKey:"replaceTests"},{field:"docs",addKey:"doc",clearKey:"clearDocs",replaceKey:"replaceDocs"},{field:"reminders",addKey:"reminder",clearKey:"clearReminders"},{field:"events",addKey:"event",clearKey:"clearEvents"},{field:"type_options",addKey:"typeOption",clearKey:"clearTypeOptions"}],UNSET_FIELD_ALIASES={close_reason:"close_reason","close-reason":"close_reason",deadline:"deadline",estimate:"estimated_minutes",estimated_minutes:"estimated_minutes","estimated-minutes":"estimated_minutes",acceptance_criteria:"acceptance_criteria","acceptance-criteria":"acceptance_criteria",ac:"acceptance_criteria",definition_of_ready:"definition_of_ready","definition-of-ready":"definition_of_ready",order:"order",rank:"order",goal:"goal",objective:"objective",value:"value",impact:"impact",outcome:"outcome",why_now:"why_now","why-now":"why_now",assignee:"assignee",parent:"parent",reviewer:"reviewer",risk:"risk",confidence:"confidence",sprint:"sprint",release:"release",blocked_by:"blocked_by","blocked-by":"blocked_by",blocked_reason:"blocked_reason","blocked-reason":"blocked_reason",unblock_note:"unblock_note","unblock-note":"unblock_note",reporter:"reporter",severity:"severity",environment:"environment",repro_steps:"repro_steps","repro-steps":"repro_steps",resolution:"resolution",expected_result:"expected_result","expected-result":"expected_result",actual_result:"actual_result","actual-result":"actual_result",affected_version:"affected_version","affected-version":"affected_version",fixed_version:"fixed_version","fixed-version":"fixed_version",component:"component",regression:"regression",customer_impact:"customer_impact","customer-impact":"customer_impact",type_options:"type_options","type-options":"type_options",tags:"tags"},sanitizeUpdateOptionsForSummary=options=>{const summary={};for(const[key,value]of Object.entries(options))NON_MUTATION_UPDATE_OPTION_KEYS.has(key)||value!==void 0&&(summary[key]=value);return summary},hasAnyUpdateMutationInput=options=>Object.keys(sanitizeUpdateOptionsForSummary(options)).length>0,trimPreviewValue=value=>typeof value=="string"?value.trim():value,normalizeIntegerPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isInteger(parsed)?parsed:trimmed},normalizeNumericPreviewValue=value=>{const trimmed=String(value).trim(),parsed=Number(trimmed);return Number.isFinite(parsed)?parsed:trimmed},normalizeRegressionPreviewValue=value=>{const normalized=String(value).trim().toLowerCase();return new Map([["true",!0],["1",!0],["false",!1],["0",!1]]).get(normalized)??trimPreviewValue(value)},PREVIEW_VALUE_NORMALIZERS={priority:normalizeIntegerPreviewValue,estimatedMinutes:normalizeNumericPreviewValue,order:normalizeNumericPreviewValue,rank:normalizeNumericPreviewValue,regression:normalizeRegressionPreviewValue},toComparablePreviewValue=(optionKey,value)=>{if(value!==void 0)return(PREVIEW_VALUE_NORMALIZERS[optionKey]??trimPreviewValue)(value)},normalizeUnsetField=rawField=>{const normalized=rawField.trim().toLowerCase().replaceAll("-","_");return UNSET_FIELD_ALIASES[normalized]??normalized},areValuesEqual=(left,right)=>stableValueEquals(left,right),normalizeCollectionBeforeValue=(field,value)=>value!==void 0?value:field==="type_options"?{}:[],collectionValueCount=(field,value)=>Array.isArray(value)?value.length:field==="type_options"&&value&&typeof value=="object"?Object.keys(value).length:0,resolveCollectionMutationOperation=params=>params.replace?"replace":params.clear?"clear_or_reset":params.removeCount>0?"merge_remove":"append",readOptionalUpdateValue=(update,key)=>key===void 0?void 0:update[key],updateArrayValueCount=value=>Array.isArray(value)?value.length:0,buildCollectionMutationPlan=(definition,row,update)=>{const addValues=update[definition.addKey],removeValues=readOptionalUpdateValue(update,definition.removeKey),addCount=updateArrayValueCount(addValues),removeCount=updateArrayValueCount(removeValues),clear=update[definition.clearKey]===!0,replace=readOptionalUpdateValue(update,definition.replaceKey)===!0;if(![clear,replace,addCount>0,removeCount>0].includes(!0))return;const before=normalizeCollectionBeforeValue(definition.field,row[definition.field]);return{field:definition.field,before,after:{operation:resolveCollectionMutationOperation({replace,clear,removeCount}),clear,replace,add_count:addCount,remove_count:removeCount,before_count:collectionValueCount(definition.field,before)}}},buildCollectionMutationPlans=(row,update)=>{const changes=[];for(const definition of COLLECTION_MUTATION_PLAN_DEFINITIONS){const plan=buildCollectionMutationPlan(definition,row,update);plan!==void 0&&changes.push(plan)}return changes},normalizeExistingTags=value=>Array.isArray(value)?value.filter(tag=>typeof tag=="string"):[],buildTagMutationPlan=(row,update)=>{if(![update.tags!==void 0,updateArrayValueCount(update.addTags)>0,updateArrayValueCount(update.removeTags)>0].includes(!0))return;const existing=normalizeExistingTags(row.tags),baseTags=update.tags===void 0?existing:parseTags(update.tags),withAdditions=mergeAdditiveTags(baseTags,update.addTags),after=applyTagRemovals(withAdditions,update.removeTags).slice().sort((a,b)=>a.localeCompare(b)),before=existing.slice().sort((a,b)=>a.localeCompare(b));if(!areValuesEqual(before,after))return{field:"tags",before:existing,after}},buildAcceptanceCriteriaMutationPlan=(row,update)=>{const before=row.acceptance_criteria,mutation=applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(before),update.addAc,update.removeAc);if(mutation.unmatchedRemovals.length>0)throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`,EXIT_CODE.NOT_FOUND,{code:"acceptance_criteria_remove_unmatched",reason:"exact_match_not_found",field:"acceptance_criteria",unmatched:mutation.unmatchedRemovals});const after=mutation.criteria.join("; ");if(!areValuesEqual(typeof before=="string"?before:"",after))return{field:"acceptance_criteria",before,after}},appendScalarMutationPlans=(changes,row,update)=>{for(const[optionKey,itemKey]of Object.entries(UPDATE_OPTION_TO_ITEM_KEY)){const candidate=update[optionKey];if(candidate===void 0)continue;const before=row[itemKey],after=toComparablePreviewValue(optionKey,candidate);areValuesEqual(before,after)||changes.push({field:itemKey,before,after})}},appendRuntimeFieldMutationPlans=(changes,row,update,runtimeFieldRegistry)=>{const runtimeFieldUpdates=collectRuntimeUpdateFieldValues(update,runtimeFieldRegistry,["update_many"]);for(const[field,after]of Object.entries(runtimeFieldUpdates)){const before=row[field];areValuesEqual(before,after)||changes.push({field,before,after})}},appendUnsetMutationPlans=(changes,row,unset)=>{for(const rawUnsetField of unset??[]){const field=normalizeUnsetField(rawUnsetField),before=row[field];before!==void 0&&changes.push({field,before,after:null})}},buildPlannedItemDiff=(item,runtimeFieldRegistry,update={})=>{const row=toItemRecord(item),changes=[],tagPlan=buildTagMutationPlan(row,update);if(tagPlan&&changes.push(tagPlan),appendScalarMutationPlans(changes,row,update),updateArrayValueCount(update.addAc)>0||updateArrayValueCount(update.removeAc)>0){const acceptanceCriteriaChange=buildAcceptanceCriteriaMutationPlan(row,update);acceptanceCriteriaChange!==void 0&&changes.push(acceptanceCriteriaChange)}return changes.push(...buildCollectionMutationPlans(row,update)),appendRuntimeFieldMutationPlans(changes,row,update,runtimeFieldRegistry),appendUnsetMutationPlans(changes,row,update.unset),{id:item.id,changes}},normalizeStatusFilter=(value,statusRegistry)=>parseStatusFilterCsv(value,statusRegistry,{strict:!0,flagLabel:"--filter-status"}),rejectBlankIdsFilter=list=>{if(list?.ids!=null&&String(list.ids).trim().length===0)throw new PmCliError("--ids requires at least one non-empty item ID",EXIT_CODE.USAGE)},PLANNED_UPDATE_VALIDATORS=[({update})=>{update.priority!==void 0&&resolvePriority(update.priority)},({update,settings,pmRoot})=>{if(update.type===void 0)return;const typeRegistry=resolveItemTypeRegistry(settings,getActiveExtensionRegistrations());if(!resolveTypeName(update.type,typeRegistry))throw new PmCliError(buildInvalidTypeError(update.type,typeRegistry.types,resolveItemTypesFilePath(pmRoot,settings.schema)),EXIT_CODE.USAGE)},({update,statusRegistry})=>{if(update.status!==void 0&&!normalizeStatusInput(update.status,statusRegistry)){const allowedStatuses=statusRegistry.definitions.map(definition=>definition.id);throw new PmCliError(`Invalid --status value "${update.status}". Allowed: ${allowedStatuses.join(", ")}`,EXIT_CODE.USAGE)}},({update})=>{update.deadline!==void 0&&resolveIsoOrRelative(update.deadline,new Date,"deadline")},({update})=>{update.estimatedMinutes!==void 0&&parseOptionalNonNegativeInteger(update.estimatedMinutes,"estimated-minutes")}],assertPlannedUpdateValuesValid=(update,settings,statusRegistry,pmRoot)=>{const context={update,settings,statusRegistry,pmRoot};for(const validate of PLANNED_UPDATE_VALIDATORS)validate(context)},runUpdateManyRollback=async params=>{const checkpoint=await loadMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.rollbackId,UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION),restoreMessage=params.options.update?.message??`Rollback update-many checkpoint ${checkpoint.id}`,rollback=await rollbackMutationCheckpoint(params.pmRoot,checkpoint,{author:params.options.update?.author,message:restoreMessage,force:params.options.update?.force}),skipped=rollback.rows.filter(row=>row.status==="skipped").length;return{...derivePmBulkMutationEffect({applied:rollback.restored_ids.length,skipped,failed:rollback.failed_count,unmatched:0}),mode:"rollback",matched_count:checkpoint.items.length,dry_run:!1,rollback_checkpoint_id:checkpoint.id,checkpoint:{id:checkpoint.id,created_at:checkpoint.created_at,path:checkpoint.path,rollback_command:`pm update-many --rollback ${checkpoint.id}`},restored_count:rollback.restored_ids.length,skipped_count:skipped,failed_count:rollback.failed_count,rows:rollback.rows,ids:rollback.restored_ids}},writeUpdateManyCheckpoint=async params=>{const checkpointPayload={schema_version:UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION,rollback_strategy:"guarded_inverse",id:params.checkpointId,created_at:params.nowValue,author:resolveAuthor(params.options.update?.author,"unknown"),status_filter:params.statusFilter??null,list_filters:params.filters,update_options:params.updateSummary,items:params.checkpointItems},checkpointPath=await writeMutationCheckpoint(params.pmRoot,UPDATE_MANY_CHECKPOINT_SUBDIR,params.checkpointId,checkpointPayload);return{id:params.checkpointId,created_at:params.nowValue,path:checkpointPath,rollback_command:`pm update-many --rollback ${params.checkpointId}`}},collectUnmatchedRequestedIds=(rawIds,existingItems)=>{if(rawIds==null)return;const requested=[...new Set(String(rawIds).split(",").map(entry=>entry.trim()).filter(entry=>entry.length>0))],existing=new Set(existingItems.map(item=>item.id));return requested.filter(id=>!existing.has(id))},buildUnmatchedIdFields=plan=>plan.unmatchedIds===void 0?{}:{unmatched_ids:plan.unmatchedIds,unmatched_count:plan.unmatchedIds.length},loadUpdateManyRuntimeContext=async global2=>{const pmRoot=resolvePmRoot(process.cwd(),global2.path);await assertInitializedTracker(pmRoot);const settings=await readSettings(pmRoot);return{pmRoot,settings,statusRegistry:resolveRuntimeStatusRegistry(settings.schema),runtimeFieldRegistry:resolveRuntimeFieldRegistry(settings.schema)}},runRequestedUpdateManyRollback=params=>{if(params.options.dryRun===!0)throw new PmCliError("--dry-run cannot be combined with --rollback",EXIT_CODE.USAGE);if(hasListFilters(params.options.list,params.options.status))throw new PmCliError("Rollback mode does not accept filter options",EXIT_CODE.USAGE);if(Object.keys(params.updateSummary).length>0)throw new PmCliError("Rollback mode does not accept update mutation flags",EXIT_CODE.USAGE);return runUpdateManyRollback({pmRoot:params.runtime.pmRoot,rollbackId:params.rollbackId,options:params.options,global:params.global})},buildUpdateManyPlan=async params=>{normalizeStatusFilter(params.options.status,params.runtime.statusRegistry);const listed=await runList(void 0,{...params.options.list,status:params.options.status,compact:void 0,brief:void 0,fields:void 0,includeBody:!0,full:!0},params.global),planned=listed.items.map(item=>{const diff=buildPlannedItemDiff(item,params.runtime.runtimeFieldRegistry,params.options.update);return params.dependencyWarnings.length===0?diff:{...diff,warnings:[...params.dependencyWarnings]}}),existenceItems=params.options.list?.ids==null?[]:(await runList(void 0,{ids:params.options.list.ids,noTruncate:!0,full:!0},params.global)).items;return{listed,planned,actionable:planned.filter(row=>row.changes.length>0),updateSummary:params.updateSummary,unmatchedIds:collectUnmatchedRequestedIds(params.options.list?.ids,existenceItems)}},buildUpdateManyDryRunResult=plan=>({outcome:"effect",exit_code:EXIT_CODE.SUCCESS,mode:"dry_run",matched_count:plan.listed.items.length,dry_run:!0,filters:plan.listed.filters,planned_update_options:plan.updateSummary,item_plans:plan.planned,ids:[],...buildUnmatchedIdFields(plan)}),buildUpdateManyNoopResult=plan=>({...derivePmBulkMutationEffect({applied:0,skipped:plan.listed.items.length,failed:0,unmatched:plan.unmatchedIds?.length??0}),mode:"apply",matched_count:plan.listed.items.length,dry_run:!1,filters:plan.listed.filters,planned_update_options:plan.updateSummary,updated_count:0,skipped_count:plan.listed.items.length,failed_count:0,rows:plan.planned.map(row=>({id:row.id,status:"skipped"})),ids:[],...buildUnmatchedIdFields(plan)}),applyUpdateManyRows=async params=>{const rows=[],updatedIds=[],updateMessage=params.options.update.message??`update-many apply ${params.checkpointId}`,actionableById=new Set(params.plans.filter(row=>row.changes.length>0).map(row=>row.id));for(const item of params.items){if(!actionableById.has(item.id)){rows.push({id:item.id,status:"skipped"});continue}try{const rowUpdateOptions=preserveMutationStdinTokenLiterals({...params.options.update,message:updateMessage,runtimeFieldCommands:["update_many"]}),result=await withCheckpointMutation({pmRoot:params.pmRoot,itemId:item.id,checkpointId:params.checkpointId},()=>runUpdate(item.id,rowUpdateOptions,params.global));rows.push({id:item.id,status:"updated",changed_fields:result.changed_fields,warnings:result.warnings}),updatedIds.push(item.id)}catch(error){rows.push({id:item.id,status:"failed",error:toErrorMessage(error)})}}return{rows,updatedIds}},applyUpdateManyPlan=async params=>{if(params.plan.actionable.length===0)return buildUpdateManyNoopResult(params.plan);const nowValue=nowIso(),checkpointId=createCheckpointId(UPDATE_MANY_CHECKPOINT_SUBDIR,nowValue),actionableById=new Set(params.plan.actionable.map(row=>row.id)),checkpointItems=params.plan.listed.items.filter(item=>actionableById.has(item.id)).map(item=>({id:item.id,target_updated_at:item.updated_at})),checkpointInfo=params.options.checkpoint===!1?void 0:await writeUpdateManyCheckpoint({pmRoot:params.runtime.pmRoot,checkpointId,nowValue,options:params.options,statusFilter:params.options.status,filters:params.plan.listed.filters,updateSummary:params.plan.updateSummary,checkpointItems}),applied=await applyUpdateManyRows({pmRoot:params.runtime.pmRoot,items:params.plan.listed.items,plans:params.plan.planned,options:params.options,global:params.global,checkpointId}),countStatus=status=>applied.rows.filter(row=>row.status===status).length,updatedCount=countStatus("updated"),skippedCount=countStatus("skipped"),failedCount=countStatus("failed");return{...derivePmBulkMutationEffect({applied:updatedCount,skipped:skippedCount,failed:failedCount,unmatched:params.plan.unmatchedIds?.length??0}),mode:"apply",matched_count:params.plan.listed.items.length,dry_run:!1,filters:params.plan.listed.filters,planned_update_options:params.plan.updateSummary,...checkpointInfo?{checkpoint:checkpointInfo}:{},updated_count:updatedCount,skipped_count:skippedCount,failed_count:failedCount,rows:applied.rows,ids:applied.updatedIds,...buildUnmatchedIdFields(params.plan)}},runUpdateMany=async(options,global2)=>{const rollbackId=resolveCheckpointRollbackId(options.rollback),runtime=await loadUpdateManyRuntimeContext(global2);rollbackId===void 0&&(options={...options,update:preserveMutationStdinTokenLiterals(await resolveUpdateTransportOptions(options.update))});const updateSummary=sanitizeUpdateOptionsForSummary(options.update);if(rejectBlankIdsFilter(options.list),rollbackId!==void 0)return runRequestedUpdateManyRollback({runtime,rollbackId,options,global:global2,updateSummary});if(!hasAnyUpdateMutationInput(options.update)&&options.dryRun!==!0)throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}), or pass --dry-run for a filter-only preview.`,EXIT_CODE.USAGE);assertPlannedUpdateValuesValid(options.update,runtime.settings,runtime.statusRegistry,runtime.pmRoot),assertUpdateMutationOptionCombinations(options.update);const dependencyWarnings=await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps}),plan=await buildUpdateManyPlan({options,global:global2,runtime,updateSummary,dependencyWarnings});return await assertDependencyTargetsResolvable({pmRoot:runtime.pmRoot,dependencies:parseDependencyAdditions(options.update.dep,runtime.settings.id_prefix,nowIso(),resolveAuthor(options.update.author,runtime.settings.author_default)).additions,idPrefix:runtime.settings.id_prefix,itemFormat:runtime.settings.item_format,typeToFolder:resolveItemTypeRegistry(runtime.settings,getActiveExtensionRegistrations()).type_to_folder,allowUnresolved:options.update.allowUnresolvedDeps,holders:plan.listed.items.map(item=>({id:item.id,createdAt:item.created_at})),schema:runtime.settings.schema}),options.dryRun===!0?buildUpdateManyDryRunResult(plan):applyUpdateManyPlan({runtime,options,global:global2,plan})},_testOnlyUpdateManyCommand={assertPlannedUpdateValuesValid,buildCollectionMutationPlans,buildPlannedItemDiff,buildTagMutationPlan,collectionValueCount,hasAnyUpdateMutationInput,hasListFilters,normalizeStatusFilter,normalizeCollectionBeforeValue,normalizeExistingTags,normalizeUnsetField,rejectBlankIdsFilter,sanitizeUpdateOptionsForSummary,toComparablePreviewValue};export{_testOnlyUpdateManyCommand,runUpdateMany};
2
2
  //# sourceMappingURL=update-many.js.map
@@ -0,0 +1,9 @@
1
+ /** Preserve whole-field scalar intent when another branch removed its target. */
2
+ import { type ReplayDocument } from "../../core/history/replay.js";
3
+ import type { HistoryPatchOp } from "../../types/index.js";
4
+ /** Rebase only validated whole-field assignments/removals; nested and conditional operations stay strict. */
5
+ export declare function rebaseHistoryScalarPatch(current:ReplayDocument,patch:HistoryPatchOp[],coordinate:{
6
+ branch:"ours" | "theirs";
7
+ line:number;
8
+ op:string;
9
+ }):ReplayDocument;
@@ -0,0 +1,2 @@
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="b3ef9db1-1d20-5d88-927e-a08edf563cd5")}catch{}})();import{tryApplyReplayPatch}from"../../core/history/replay.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";function rebaseHistoryScalarPatch(current,patch,coordinate){const direct=tryApplyReplayPatch(current,patch);if(direct.ok)return direct.document;let next=structuredClone(current);for(const[index,operation]of patch.entries()){const field=/^\/metadata\/([^/]*)$/u.exec(operation.path)?.[1],missingField=field!==void 0&&!Object.hasOwn(next.metadata,field.replaceAll("~1","/").replaceAll("~0","~"));if(missingField&&operation.op==="remove")continue;const projected=missingField&&operation.op==="replace"?{...operation,op:"add"}:operation,applied=tryApplyReplayPatch(next,[projected]);if(!applied.ok)throw new PmCliError(`History union cannot rebase a scalar patch at ${coordinate.branch} line ${coordinate.line} (${coordinate.op}), operation ${index+1} ${operation.op} ${operation.path}; preserve the source histories for manual recovery.`,EXIT_CODE.CONFLICT,{code:"history_union_rebase_conflict",field:operation.path,history_merge:{...coordinate,patch_index:index,patch_path:operation.path},nextSteps:["Preserve all three history inputs and both item snapshots. Review the named branch event against the merged replay state; do not drop the event or concatenate unchecked patches. After resolving the history and item deliberately, run pm history <id> --verify and pm merge reconcile --dry-run before committing."]});next=applied.document}return next}export{rebaseHistoryScalarPatch};
2
+ //# sourceMappingURL=history-scalar-rebase.js.map
@@ -0,0 +1,13 @@
1
+ /** Git's owning ignore rule for one untracked reconciliation artifact. */
2
+ export interface MergeArtifactIgnoreRule {
3
+ /** Repository-relative artifact path, decoded without Git quoting. */
4
+ path:string;
5
+ /** Ignore file reported by Git, including global and clone-local sources. */
6
+ source:string;
7
+ /** One-based ignore file line. */
8
+ line:number;
9
+ /** Exact effective pattern, without interpretation by pm. */
10
+ pattern:string;
11
+ }
12
+ /** Respect tracked files and negations while checking literal repository paths with Git's NUL protocol. */
13
+ export declare function inspectIgnoredMergeArtifacts(workspaceRoot:string,paths:string[]):Promise<MergeArtifactIgnoreRule[]>;
@@ -0,0 +1,2 @@
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e57ef62f-fd40-5a33-9816-e24d8dba4d1d")}catch{}})();import{execFile}from"node:child_process";import{promisify}from"node:util";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{gitWorkspaceEnvironment}from"./worktree-config.js";const execFileAsync=promisify(execFile);async function inspectIgnoredMergeArtifacts(workspaceRoot,paths){if(paths.length===0)return[];let stdout;try{const pending=execFileAsync("git",["check-ignore","--verbose","-z","--stdin"],{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),timeout:1e4}),input=pending.child.stdin;input!==null&&(input.on("error",()=>{pending.child.kill()}),input.end(`${paths.join("\0")}\0`)),{stdout}=await pending}catch(error){if(typeof error=="object"&&error!==null&&"code"in error&&error.code===1)return[];throw new PmCliError("Git could not verify ignore rules for merge artifacts; no automatic settlement is safe until that check succeeds.",EXIT_CODE.CONFLICT,{code:"merge_settlement_review_required",reason:"ignore_check_unavailable",nextSteps:["Check Git configuration and ignore-file readability, then retry pm merge reconcile --stage --dry-run."]})}const fields=stdout.split("\0"),ignored=[];for(let index=0;index+3<fields.length;index+=4){const[source,line,pattern,target]=fields.slice(index,index+4);pattern.startsWith("!")||ignored.push({path:target,source,line:Number(line),pattern})}return ignored}export{inspectIgnoredMergeArtifacts};
2
+ //# sourceMappingURL=ignored-artifacts.js.map
@@ -1,2 +1,2 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fe5937fc-def3-5ed4-9663-70a6e9d258a1")}catch{}})();import{execFile}from"node:child_process";import{realpath}from"node:fs/promises";import path from"node:path";import{promisify}from"node:util";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolvePmRoot}from"../../core/store/paths.js";import{findGitWorkspaceRoot}from"./install.js";import{gitWorkspaceEnvironment}from"./worktree-config.js";import{isPathOutsideRoot}from"../workspace.js";const execFileAsync=promisify(execFile);function stagingRefusal(reason){return new PmCliError(`Automatic merge settlement refused: ${reason}`,EXIT_CODE.CONFLICT,{code:"merge_settlement_review_required",recovery:{suggested_retry:"pm merge reconcile --dry-run"},nextSteps:["Inspect receipts, repair streams and Git changes. Resolve competing values or unrelated drift explicitly, then run pm merge reconcile and stage the reviewed artifacts manually."]})}async function assertNormalGitIndex(git){const indexOverride=process.env.GIT_INDEX_FILE;if(indexOverride===void 0)return;const indexPath=(await git(["rev-parse","--path-format=absolute","--git-path","index"])).stdout.trim();if(path.resolve(indexOverride)!==path.resolve(indexPath))throw stagingRefusal("an alternate Git index requires explicit manual settlement")}async function newReceiptPaths(git,receiptPaths){if(receiptPaths.length===0)return[];const pathspecs=receiptPaths.map(target=>`:(literal)${target}`),indexed=new Set((await git(["ls-files","--cached","-z","--",...pathspecs])).stdout.split("\0")),missing=receiptPaths.filter(target=>!indexed.has(target)).map(target=>`:(literal)${target}`);if(missing.length>0&&(await git(["diff","--cached","--name-only","--diff-filter=D","-z","--",...missing])).stdout.length>0)throw stagingRefusal("a receipt has a staged deletion that requires explicit review");return missing}async function applyAndStage(params){const{git,preview,paths,newReceiptPathspecs}=params;let preparedReceipts=!1;try{newReceiptPathspecs.length>0&&(await git(["add","--",...newReceiptPathspecs]),preparedReceipts=!0);const result=await params.apply();if(!result.ok||JSON.stringify(result.receipts.summaries)!==JSON.stringify(preview.receipts.summaries)||result.repair.streams.some(stream=>!preview.repair.streams.some(prior=>prior.id===stream.id)))throw stagingRefusal("reconciliation changed or did not finish; inspect the audit artifacts before staging");return paths.length>0&&await git(["add","--",...paths.map(target=>`:(literal)${target}`)]),{...result,staged_paths:paths,guidance:["Lossless reconciliation artifacts are staged for the merge commit. Review git diff --cached before committing."]}}catch(error){throw preparedReceipts&&await git(["reset","--quiet","--",...newReceiptPathspecs]),error}}function assertLosslessPreview(preview){if(preview.repair.totals.failed>0||preview.receipts.missing_history_references_after>0||preview.receipts.summaries.some(receipt=>receipt.conflict_fields.length>0)||preview.repair.streams.some(stream=>stream.merge_receipt_proof?.trusted!==!0)||preview.validation.checks.some(check=>check.name!=="history_drift"&&check.status!=="ok"))throw stagingRefusal("only fully authenticated receipt-backed repairs without discarded values can be staged")}async function resolveMergeSettlementGlobal(global2){try{return{...global2,path:await realpath(resolvePmRoot(process.cwd(),global2.path))}}catch{throw stagingRefusal("the tracker root cannot be resolved")}}async function stageLosslessMergeReconciliation(params){const{preview}=params;assertLosslessPreview(preview);const{path:pmRoot}=await resolveMergeSettlementGlobal(params.global),workspaceRoot=await findGitWorkspaceRoot(pmRoot);if(workspaceRoot===null)throw stagingRefusal("a Git workspace is required");const git=args=>execFileAsync("git",args,{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),timeout:1e4});if(await assertNormalGitIndex(git),(await git(["ls-files","--unmerged","-z"])).stdout.length>0)throw stagingRefusal("Git still has unresolved paths");const paths=[...new Set([...[...new Set([...preview.repair.streams.map(stream=>stream.id),...preview.receipts.summaries.map(receipt=>receipt.item_id)])].map(id=>path.join(pmRoot,"history",`${id}.jsonl`)),...preview.receipts.summaries.map(receipt=>path.join(pmRoot,"merge-receipts",`${receipt.receipt_id}.json`))])].map(target=>path.relative(workspaceRoot,target).replaceAll("\\","/"));if(paths.some(isPathOutsideRoot))throw stagingRefusal("reconciliation artifacts must belong to this Git workspace");const pathspecs=paths.map(target=>`:(literal)${target}`),receiptPaths=preview.receipts.summaries.map(receipt=>path.relative(workspaceRoot,path.join(pmRoot,"merge-receipts",`${receipt.receipt_id}.json`)).replaceAll("\\","/"));if(pathspecs.length>0)try{await git(["diff","--quiet","--",...pathspecs])}catch{throw stagingRefusal("reconciliation paths have unstaged edits or Git cannot verify their index state")}const newReceiptPathspecs=await newReceiptPaths(git,receiptPaths);return params.dryRun?{...preview,staged_paths:[]}:applyAndStage({...params,git,paths,newReceiptPathspecs})}export{resolveMergeSettlementGlobal,stageLosslessMergeReconciliation};
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7f4b2fc8-c9c6-51ff-a345-b76b8abdacf4")}catch{}})();import{execFile}from"node:child_process";import{realpath}from"node:fs/promises";import path from"node:path";import{promisify}from"node:util";import{EXIT_CODE}from"../../core/shared/constants.js";import{PmCliError}from"../../core/shared/errors.js";import{resolvePmRoot}from"../../core/store/paths.js";import{findGitWorkspaceRoot}from"./install.js";import{gitWorkspaceEnvironment}from"./worktree-config.js";import{inspectIgnoredMergeArtifacts}from"./ignored-artifacts.js";import{isPathOutsideRoot}from"../workspace.js";const execFileAsync=promisify(execFile);function stagingRefusal(reason){return new PmCliError(`Automatic merge settlement refused: ${reason}`,EXIT_CODE.CONFLICT,{code:"merge_settlement_review_required",recovery:{suggested_retry:"pm merge reconcile --dry-run"},nextSteps:["Inspect receipts, repair streams and Git changes. Resolve competing values or unrelated drift explicitly, then run pm merge reconcile and stage the reviewed artifacts manually."]})}async function assertNormalGitIndex(git){const indexOverride=process.env.GIT_INDEX_FILE;if(indexOverride===void 0)return;const indexPath=(await git(["rev-parse","--path-format=absolute","--git-path","index"])).stdout.trim();if(path.resolve(indexOverride)!==path.resolve(indexPath))throw stagingRefusal("an alternate Git index requires explicit manual settlement")}async function newReceiptPaths(git,receiptPaths){if(receiptPaths.length===0)return[];const pathspecs=receiptPaths.map(target=>`:(literal)${target}`),indexed=new Set((await git(["ls-files","--cached","-z","--",...pathspecs])).stdout.split("\0")),missing=receiptPaths.filter(target=>!indexed.has(target)).map(target=>`:(literal)${target}`);if(missing.length>0&&(await git(["diff","--cached","--name-only","--diff-filter=D","-z","--",...missing])).stdout.length>0)throw stagingRefusal("a receipt has a staged deletion that requires explicit review");return missing}async function applyAndStage(params){const{git,preview,paths,newReceiptPathspecs}=params;let preparedReceipts=!1;try{newReceiptPathspecs.length>0&&(preparedReceipts=!0,await git(["add","--",...newReceiptPathspecs]));const result=await params.apply();if(!result.ok||JSON.stringify(result.receipts.summaries)!==JSON.stringify(preview.receipts.summaries)||result.repair.streams.some(stream=>!preview.repair.streams.some(prior=>prior.id===stream.id)))throw stagingRefusal("reconciliation changed or did not finish; inspect the audit artifacts before staging");return paths.length>0&&await git(["add","--",...paths.map(target=>`:(literal)${target}`)]),{...result,staged_paths:paths,guidance:["Lossless reconciliation artifacts are staged for the merge commit. Review git diff --cached before committing."]}}catch(error){throw preparedReceipts&&await git(["reset","--quiet","--",...newReceiptPathspecs]),error}}function assertLosslessPreview(preview){if(preview.repair.totals.failed>0||preview.receipts.missing_history_references_after>0||preview.receipts.summaries.some(receipt=>receipt.conflict_fields.length>0)||preview.repair.streams.some(stream=>stream.merge_receipt_proof?.trusted!==!0)||preview.validation.checks.some(check=>check.name!=="history_drift"&&check.status!=="ok"))throw stagingRefusal("only fully authenticated receipt-backed repairs without discarded values can be staged")}async function resolveMergeSettlementGlobal(global2){try{return{...global2,path:await realpath(resolvePmRoot(process.cwd(),global2.path))}}catch{throw stagingRefusal("the tracker root cannot be resolved")}}async function stageLosslessMergeReconciliation(params){const{preview}=params;assertLosslessPreview(preview);const{path:pmRoot}=await resolveMergeSettlementGlobal(params.global),workspaceRoot=await findGitWorkspaceRoot(pmRoot);if(workspaceRoot===null)throw stagingRefusal("a Git workspace is required");const git=args=>execFileAsync("git",args,{cwd:workspaceRoot,env:gitWorkspaceEnvironment(),timeout:1e4});if(await assertNormalGitIndex(git),(await git(["ls-files","--unmerged","-z"])).stdout.length>0)throw stagingRefusal("Git still has unresolved paths");const paths=[...new Set([...[...new Set([...preview.repair.streams.map(stream=>stream.id),...preview.receipts.summaries.map(receipt=>receipt.item_id)])].map(id=>path.join(pmRoot,"history",`${id}.jsonl`)),...preview.receipts.summaries.map(receipt=>path.join(pmRoot,"merge-receipts",`${receipt.receipt_id}.json`))])].map(target=>path.relative(workspaceRoot,target).replaceAll("\\","/"));if(paths.some(isPathOutsideRoot))throw stagingRefusal("reconciliation artifacts must belong to this Git workspace");const ignored=await inspectIgnoredMergeArtifacts(workspaceRoot,paths);if(ignored.length>0)throw new PmCliError(`Automatic merge settlement refused: required artifacts are ignored by Git: ${ignored.map(rule=>`${rule.path} (${rule.source}:${rule.line}: ${rule.pattern})`).join(", ")}. Remove or narrow the owning ignore rules because merge receipts must travel with the commit.`,EXIT_CODE.CONFLICT,{code:"merge_settlement_review_required",reason:"ignored_merge_artifacts",paths:ignored.map(rule=>rule.path),nextSteps:["Remove or narrow the named ignore rules, preserve receipt and history files, then retry pm merge reconcile --stage --dry-run before applying pm merge reconcile --stage. Do not force-add ignored proof as a substitute for fixing the shared policy."]});const pathspecs=paths.map(target=>`:(literal)${target}`),receiptPaths=preview.receipts.summaries.map(receipt=>path.relative(workspaceRoot,path.join(pmRoot,"merge-receipts",`${receipt.receipt_id}.json`)).replaceAll("\\","/"));if(pathspecs.length>0)try{await git(["diff","--quiet","--",...pathspecs])}catch{throw stagingRefusal("reconciliation paths have unstaged edits or Git cannot verify their index state")}const newReceiptPathspecs=await newReceiptPaths(git,receiptPaths);return params.dryRun?{...preview,staged_paths:[]}:applyAndStage({...params,git,paths,newReceiptPathspecs})}export{resolveMergeSettlementGlobal,stageLosslessMergeReconciliation};
2
2
  //# sourceMappingURL=stage.js.map
@@ -1,4 +1,4 @@
1
- (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f6def6d2-fbf3-55ce-8654-0c4e76d78a2a")}catch{}})();import{cloneEmptyReplayDocument,historyEntriesToRaw,normalizeReplayPatchOps,reanchorHistoryEntries,toReplayDocument,tryApplyReplayPatch}from"../../core/history/replay.js";import jsonPatch from"fast-json-patch";import{canonicalDocument,parseItemDocument,serializeItemDocument}from"../../core/item/item-format.js";import{splitAcceptanceCriteria}from"../../core/item/parse.js";import{normalizeItemFormatVersion,requiredItemFormatVersion}from"../../core/item/item-format-version.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{findFirstMergeConflictMarker}from"../../core/shared/conflict-markers.js";import{PmCliError}from"../../core/shared/errors.js";import{sha256Hex,stableStringify}from"../../core/shared/serialization.js";import{compareTimestampStrings}from"../../core/shared/time.js";const ITEM_SCALAR_MISSING_VALUE=Object.freeze({pm_item_scalar_missing:!0});function isItemScalarMissingValue(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)&&Object.keys(value).length===1&&value.pm_item_scalar_missing===!0}function encodeItemScalarDecisionValue(value){return value===void 0?ITEM_SCALAR_MISSING_VALUE:value}function hashItemScalarDecisionValue(value){return sha256Hex(stableStringify(value===void 0?{pm_item_scalar_presence:"missing"}:{pm_item_scalar_presence:"present",value}))}function parseHistoryJsonl(raw,label){const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker)throw new PmCliError(`History merge input (${label}) contains unresolved conflict markers at line ${conflictMarker.line}. Merge drivers must receive clean per-side versions.`,EXIT_CODE.GENERIC_FAILURE);const entries=[];for(const[index,rawLine]of raw.split(/\r?\n/).entries()){const line=rawLine.trim();if(line)try{const parsed=JSON.parse(line);if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new TypeError("history entry must be an object");entries.push(parsed)}catch{throw new PmCliError(`History merge input (${label}) contains invalid JSON at line ${index+1}.`,EXIT_CODE.GENERIC_FAILURE)}}return entries}function historyEntryIdentity(entry){return stableStringify({ts:entry.ts,author:entry.author,op:entry.op,patch:entry.patch,message:entry.message??null})}function commonHistoryPrefixLength(ours,theirs){const limit=Math.min(ours.length,theirs.length);let shared=0;for(;shared<limit&&historyEntryIdentity(ours[shared])===historyEntryIdentity(theirs[shared]);)shared+=1;return shared}function orderHistoryUnionSuffix(ours,theirs,incoming,oursIdentities){const entries=[...ours,...incoming],positions=new Map(entries.map((entry,index)=>[entry,index])),aliases=new Map(entries.map((entry,index)=>[historyEntryIdentity(entry),index])),successors=entries.map(()=>new Set);for(const branch of[ours,theirs]){const coordinates=branch.map(entry=>positions.get(entry)??aliases.get(historyEntryIdentity(entry)));for(let index=1;index<coordinates.length;index+=1)coordinates[index-1]!==coordinates[index]&&successors[coordinates[index-1]].add(coordinates[index])}const predecessors=entries.map(()=>0);for(const targets of successors)for(const target of targets)predecessors[target]+=1;const ready=entries.map((_,index)=>index).filter(index=>predecessors[index]===0),result=[];for(;ready.length>0;){ready.sort((leftIndex,rightIndex)=>{const left=entries[leftIndex],right=entries[rightIndex],byTs=compareTimestampStrings(left.ts,right.ts),leftIdentity=historyEntryIdentity(left),rightIdentity=historyEntryIdentity(right);return byTs||Number(oursIdentities.has(rightIdentity))-Number(oursIdentities.has(leftIdentity))});const index=ready.shift();result.push(entries[index]);for(const target of successors[index])predecessors[target]-=1,predecessors[target]===0&&ready.push(target)}if(result.length!==entries.length)throw new PmCliError("History union cannot preserve contradictory original branch event orders; leave the file unresolved for manual recovery.",EXIT_CODE.GENERIC_FAILURE);return result}function createHistoryBranchProjection(entries){return{entries,positions:new Map(entries.map((entry,index)=>[historyEntryIdentity(entry),index])),index:-1,document:cloneEmptyReplayDocument()}}function advanceHistoryBranch(state,target){const end=target??state.index;for(;state.index<end;){const applied=tryApplyReplayPatch(state.document,state.entries[state.index+1].patch);if(!applied.ok)throw new PmCliError("History union cannot preserve a patch that does not apply in its original branch.",EXIT_CODE.GENERIC_FAILURE);state.document=applied.document,state.index+=1}return state.document}function advanceOrderedHistoryBranch(state,target){if(target!==void 0&&target>state.index+1)throw new PmCliError("History union cannot attribute multiple original branch events to one semantic identity; preserve the source histories for manual recovery.",EXIT_CODE.GENERIC_FAILURE);return advanceHistoryBranch(state,target)}function historyUnionPatchProjection(ours,theirs,shared){if(shared===0)return;const oursBranch=createHistoryBranchProjection(ours),theirsBranch=createHistoryBranchProjection(theirs),prefix=advanceHistoryBranch(oursBranch,shared-1);advanceHistoryBranch(theirsBranch,shared-1);let position=0;const unionFields=new Set([...ITEM_UNION_COLLECTION_FIELDS,...ITEM_UNION_DELIMITED_FIELDS]);return(entry,current)=>{if(position++<shared)return entry.patch;const identity=historyEntryIdentity(entry),oursState=advanceOrderedHistoryBranch(oursBranch,oursBranch.positions.get(identity)),theirsState=advanceOrderedHistoryBranch(theirsBranch,theirsBranch.positions.get(identity)),scalarPatch=normalizeReplayPatchOps(entry.patch).filter(operation=>{const[root,field]=operation.path.slice(1).split("/");return root!=="metadata"||!unionFields.has(field)}),scalar=tryApplyReplayPatch(current,scalarPatch);if(!scalar.ok)throw new PmCliError("History union cannot rebase a scalar patch onto the merged replay position; leave the file unresolved for manual recovery.",EXIT_CODE.GENERIC_FAILURE);const merged=mergeItemMetadataRecords(prefix.metadata,oursState.metadata,theirsState.metadata,"ours","latest_document_update",String(oursState.metadata.updated_at),String(theirsState.metadata.updated_at)),next=scalar.document;for(const field of unionFields)Object.hasOwn(merged.merged,field)?next.metadata[field]=merged.merged[field]:delete next.metadata[field];const canonical=toReplayDocument({metadata:next.metadata,body:next.body});return jsonPatch.compare(current,canonical)}}function mergeHistoryStreams(baseRaw,oursRaw,theirsRaw){const base=parseHistoryJsonl(baseRaw,"base"),ours=parseHistoryJsonl(oursRaw,"ours"),theirs=parseHistoryJsonl(theirsRaw,"theirs"),creates=[base,ours,theirs].map(entries=>entries.filter(entry=>entry.op==="create"));if(creates[0].length===0&&creates.slice(1).every(entries=>entries.length>0)||creates.some(entries=>entries.length>1)||new Set(creates.flat().map(historyEntryIdentity)).size>1)throw new PmCliError("Duplicate item identity: history contains independent or unproven create events. Preserve both branches and assign distinct item ids before merging.",EXIT_CODE.CONFLICT,{code:"item_identity_conflict"});const shared=commonHistoryPrefixLength(ours,theirs);if(shared===ours.length&&shared===theirs.length)return{merged:historyEntriesToRaw(ours),strategy:"identical",common_entries:shared,entries_from_ours:0,entries_from_theirs:0,entries_total:ours.length,reanchored:!1};if(shared===theirs.length)return{merged:historyEntriesToRaw(ours),strategy:"fast_forward_ours",common_entries:shared,entries_from_ours:ours.length-shared,entries_from_theirs:0,entries_total:ours.length,reanchored:!1};if(shared===ours.length)return{merged:historyEntriesToRaw(theirs),strategy:"fast_forward_theirs",common_entries:shared,entries_from_ours:0,entries_from_theirs:theirs.length-shared,entries_total:theirs.length,reanchored:!1};const oursSuffix=ours.slice(shared),seenIdentities=new Set(oursSuffix.map(historyEntryIdentity)),theirsSuffix=theirs.slice(shared).filter(entry=>!seenIdentities.has(historyEntryIdentity(entry))),mergedSuffix=orderHistoryUnionSuffix(oursSuffix,theirs.slice(shared),theirsSuffix,seenIdentities),reanchored=reanchorHistoryEntries([...ours.slice(0,shared),...mergedSuffix],void 0,{continuousHashSurface:!0,projectPatch:historyUnionPatchProjection(ours,theirs,shared)});if(reanchored.skippedOps>0)throw new PmCliError(`History union cannot preserve ${reanchored.skippedOps} patch operation(s) after deterministic suffix ordering; leave the file unresolved for manual recovery.`,EXIT_CODE.GENERIC_FAILURE);return{merged:historyEntriesToRaw(reanchored.entries),strategy:"union_reanchor",common_entries:shared,entries_from_ours:oursSuffix.length,entries_from_theirs:theirsSuffix.length,entries_total:reanchored.entries.length,reanchored:!0}}function parseRelationshipJsonl(raw,label){const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker)throw new PmCliError(`Relationship merge input (${label}) contains unresolved conflict markers at line ${conflictMarker.line}. Merge drivers must receive clean per-side versions.`,EXIT_CODE.GENERIC_FAILURE);const events=[];for(const[index,rawLine]of raw.split(/\r?\n/).entries()){const line=rawLine.trim();if(!line)continue;let parsed;try{parsed=JSON.parse(line)}catch{throw new PmCliError(`Relationship merge input (${label}) contains invalid JSON at line ${index+1}.`,EXIT_CODE.GENERIC_FAILURE)}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed)||typeof parsed.eventId!="string"||typeof parsed.sequence!="number")throw new PmCliError(`Relationship merge input (${label}) line ${index+1} is not a relationship event (eventId + sequence required).`,EXIT_CODE.GENERIC_FAILURE);events.push(parsed)}return events}function relationshipEventsToRaw(events){return events.length===0?"":`${events.map(event=>JSON.stringify(event)).join(`
1
+ (function(){try{var e=typeof window<"u"?window:typeof global<"u"?global:typeof globalThis<"u"?globalThis:typeof self<"u"?self:{},n=new e.Error().stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="425ef2aa-56fa-5d06-b8d0-316373ad2433")}catch{}})();import{cloneEmptyReplayDocument,historyEntriesToRaw,normalizeReplayPatchOps,reanchorHistoryEntries,toReplayDocument,tryApplyReplayPatch}from"../../core/history/replay.js";import jsonPatch from"fast-json-patch";import{rebaseHistoryScalarPatch}from"./history-scalar-rebase.js";import{canonicalDocument,parseItemDocument,serializeItemDocument}from"../../core/item/item-format.js";import{splitAcceptanceCriteria}from"../../core/item/parse.js";import{normalizeItemFormatVersion,requiredItemFormatVersion}from"../../core/item/item-format-version.js";import{EXIT_CODE}from"../../core/shared/constants.js";import{findFirstMergeConflictMarker}from"../../core/shared/conflict-markers.js";import{PmCliError}from"../../core/shared/errors.js";import{sha256Hex,stableStringify}from"../../core/shared/serialization.js";import{compareTimestampStrings}from"../../core/shared/time.js";const ITEM_SCALAR_MISSING_VALUE=Object.freeze({pm_item_scalar_missing:!0});function isItemScalarMissingValue(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)&&Object.keys(value).length===1&&value.pm_item_scalar_missing===!0}function encodeItemScalarDecisionValue(value){return value===void 0?ITEM_SCALAR_MISSING_VALUE:value}function hashItemScalarDecisionValue(value){return sha256Hex(stableStringify(value===void 0?{pm_item_scalar_presence:"missing"}:{pm_item_scalar_presence:"present",value}))}function parseHistoryJsonl(raw,label){const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker)throw new PmCliError(`History merge input (${label}) contains unresolved conflict markers at line ${conflictMarker.line}. Merge drivers must receive clean per-side versions.`,EXIT_CODE.GENERIC_FAILURE);const entries=[];for(const[index,rawLine]of raw.split(/\r?\n/).entries()){const line=rawLine.trim();if(line)try{const parsed=JSON.parse(line);if(typeof parsed!="object"||parsed===null||Array.isArray(parsed))throw new TypeError("history entry must be an object");entries.push(parsed)}catch{throw new PmCliError(`History merge input (${label}) contains invalid JSON at line ${index+1}.`,EXIT_CODE.GENERIC_FAILURE)}}return entries}function historyEntryIdentity(entry){return stableStringify({ts:entry.ts,author:entry.author,op:entry.op,patch:entry.patch,message:entry.message??null})}function commonHistoryPrefixLength(ours,theirs){const limit=Math.min(ours.length,theirs.length);let shared=0;for(;shared<limit&&historyEntryIdentity(ours[shared])===historyEntryIdentity(theirs[shared]);)shared+=1;return shared}function orderHistoryUnionSuffix(ours,theirs,incoming,oursIdentities){const entries=[...ours,...incoming],positions=new Map(entries.map((entry,index)=>[entry,index])),aliases=new Map(entries.map((entry,index)=>[historyEntryIdentity(entry),index])),successors=entries.map(()=>new Set);for(const branch of[ours,theirs]){const coordinates=branch.map(entry=>positions.get(entry)??aliases.get(historyEntryIdentity(entry)));for(let index=1;index<coordinates.length;index+=1)coordinates[index-1]!==coordinates[index]&&successors[coordinates[index-1]].add(coordinates[index])}const predecessors=entries.map(()=>0);for(const targets of successors)for(const target of targets)predecessors[target]+=1;const ready=entries.map((_,index)=>index).filter(index=>predecessors[index]===0),result=[];for(;ready.length>0;){ready.sort((leftIndex,rightIndex)=>{const left=entries[leftIndex],right=entries[rightIndex],byTs=compareTimestampStrings(left.ts,right.ts),leftIdentity=historyEntryIdentity(left),rightIdentity=historyEntryIdentity(right);return byTs||Number(oursIdentities.has(rightIdentity))-Number(oursIdentities.has(leftIdentity))});const index=ready.shift();result.push(entries[index]);for(const target of successors[index])predecessors[target]-=1,predecessors[target]===0&&ready.push(target)}if(result.length!==entries.length)throw new PmCliError("History union cannot preserve contradictory original branch event orders; leave the file unresolved for manual recovery.",EXIT_CODE.GENERIC_FAILURE);return result}function createHistoryBranchProjection(entries){return{entries,positions:new Map(entries.map((entry,index)=>[historyEntryIdentity(entry),index])),index:-1,document:cloneEmptyReplayDocument()}}function advanceHistoryBranch(state,target){const end=target??state.index;for(;state.index<end;){const applied=tryApplyReplayPatch(state.document,state.entries[state.index+1].patch);if(!applied.ok)throw new PmCliError("History union cannot preserve a patch that does not apply in its original branch.",EXIT_CODE.GENERIC_FAILURE);state.document=applied.document,state.index+=1}return state.document}function advanceOrderedHistoryBranch(state,target){if(target!==void 0&&target>state.index+1)throw new PmCliError("History union cannot attribute multiple original branch events to one semantic identity; preserve the source histories for manual recovery.",EXIT_CODE.GENERIC_FAILURE);return advanceHistoryBranch(state,target)}function historyUnionPatchProjection(ours,theirs,shared){if(shared===0)return;const oursBranch=createHistoryBranchProjection(ours),theirsBranch=createHistoryBranchProjection(theirs),prefix=advanceHistoryBranch(oursBranch,shared-1);advanceHistoryBranch(theirsBranch,shared-1);let position=0;const unionFields=new Set([...ITEM_UNION_COLLECTION_FIELDS,...ITEM_UNION_DELIMITED_FIELDS]);return(entry,current)=>{if(position++<shared)return entry.patch;const identity=historyEntryIdentity(entry),oursState=advanceOrderedHistoryBranch(oursBranch,oursBranch.positions.get(identity)),theirsState=advanceOrderedHistoryBranch(theirsBranch,theirsBranch.positions.get(identity)),scalarPatch=normalizeReplayPatchOps(entry.patch).filter(operation=>{const[root,field]=operation.path.slice(1).split("/");return root!=="metadata"||!unionFields.has(field)}),oursPosition=oursBranch.positions.get(identity),next=rebaseHistoryScalarPatch(current,scalarPatch,{branch:oursPosition===void 0?"theirs":"ours",line:(oursPosition??theirsBranch.positions.get(identity))+1,op:entry.op}),merged=mergeItemMetadataRecords(prefix.metadata,oursState.metadata,theirsState.metadata,"ours","latest_document_update",String(oursState.metadata.updated_at),String(theirsState.metadata.updated_at));for(const field of unionFields)Object.hasOwn(merged.merged,field)?next.metadata[field]=merged.merged[field]:delete next.metadata[field];const canonical=toReplayDocument({metadata:next.metadata,body:next.body});return jsonPatch.compare(current,canonical)}}function mergeHistoryStreams(baseRaw,oursRaw,theirsRaw){const base=parseHistoryJsonl(baseRaw,"base"),ours=parseHistoryJsonl(oursRaw,"ours"),theirs=parseHistoryJsonl(theirsRaw,"theirs"),creates=[base,ours,theirs].map(entries=>entries.filter(entry=>entry.op==="create"));if(creates[0].length===0&&creates.slice(1).every(entries=>entries.length>0)||creates.some(entries=>entries.length>1)||new Set(creates.flat().map(historyEntryIdentity)).size>1)throw new PmCliError("Duplicate item identity: history contains independent or unproven create events. Preserve both branches and assign distinct item ids before merging.",EXIT_CODE.CONFLICT,{code:"item_identity_conflict"});const shared=commonHistoryPrefixLength(ours,theirs);if(shared===ours.length&&shared===theirs.length)return{merged:historyEntriesToRaw(ours),strategy:"identical",common_entries:shared,entries_from_ours:0,entries_from_theirs:0,entries_total:ours.length,reanchored:!1};if(shared===theirs.length)return{merged:historyEntriesToRaw(ours),strategy:"fast_forward_ours",common_entries:shared,entries_from_ours:ours.length-shared,entries_from_theirs:0,entries_total:ours.length,reanchored:!1};if(shared===ours.length)return{merged:historyEntriesToRaw(theirs),strategy:"fast_forward_theirs",common_entries:shared,entries_from_ours:0,entries_from_theirs:theirs.length-shared,entries_total:theirs.length,reanchored:!1};const oursSuffix=ours.slice(shared),seenIdentities=new Set(oursSuffix.map(historyEntryIdentity)),theirsSuffix=theirs.slice(shared).filter(entry=>!seenIdentities.has(historyEntryIdentity(entry))),mergedSuffix=orderHistoryUnionSuffix(oursSuffix,theirs.slice(shared),theirsSuffix,seenIdentities),reanchored=reanchorHistoryEntries([...ours.slice(0,shared),...mergedSuffix],void 0,{continuousHashSurface:!0,projectPatch:historyUnionPatchProjection(ours,theirs,shared)});if(reanchored.skippedOps>0)throw new PmCliError(`History union cannot preserve ${reanchored.skippedOps} patch operation(s) after deterministic suffix ordering; leave the file unresolved for manual recovery.`,EXIT_CODE.GENERIC_FAILURE);return{merged:historyEntriesToRaw(reanchored.entries),strategy:"union_reanchor",common_entries:shared,entries_from_ours:oursSuffix.length,entries_from_theirs:theirsSuffix.length,entries_total:reanchored.entries.length,reanchored:!0}}function parseRelationshipJsonl(raw,label){const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker)throw new PmCliError(`Relationship merge input (${label}) contains unresolved conflict markers at line ${conflictMarker.line}. Merge drivers must receive clean per-side versions.`,EXIT_CODE.GENERIC_FAILURE);const events=[];for(const[index,rawLine]of raw.split(/\r?\n/).entries()){const line=rawLine.trim();if(!line)continue;let parsed;try{parsed=JSON.parse(line)}catch{throw new PmCliError(`Relationship merge input (${label}) contains invalid JSON at line ${index+1}.`,EXIT_CODE.GENERIC_FAILURE)}if(typeof parsed!="object"||parsed===null||Array.isArray(parsed)||typeof parsed.eventId!="string"||typeof parsed.sequence!="number")throw new PmCliError(`Relationship merge input (${label}) line ${index+1} is not a relationship event (eventId + sequence required).`,EXIT_CODE.GENERIC_FAILURE);events.push(parsed)}return events}function relationshipEventsToRaw(events){return events.length===0?"":`${events.map(event=>JSON.stringify(event)).join(`
2
2
  `)}
3
3
  `}function renumberRelationshipEvents(events){return events.map((event,index)=>({...event,sequence:index+1}))}function mergeRelationshipEventStreams(baseRaw,oursRaw,theirsRaw){parseRelationshipJsonl(baseRaw,"base");const ours=parseRelationshipJsonl(oursRaw,"ours"),theirs=parseRelationshipJsonl(theirsRaw,"theirs"),limit=Math.min(ours.length,theirs.length);let shared=0;for(;shared<limit&&ours[shared].eventId===theirs[shared].eventId;)shared+=1;if(shared===ours.length&&shared===theirs.length)return{merged:relationshipEventsToRaw(ours),strategy:"identical",common_entries:shared,entries_from_ours:0,entries_from_theirs:0,entries_total:ours.length,reanchored:!1};if(shared===theirs.length)return{merged:relationshipEventsToRaw(ours),strategy:"fast_forward_ours",common_entries:shared,entries_from_ours:ours.length-shared,entries_from_theirs:0,entries_total:ours.length,reanchored:!1};if(shared===ours.length)return{merged:relationshipEventsToRaw(theirs),strategy:"fast_forward_theirs",common_entries:shared,entries_from_ours:0,entries_from_theirs:theirs.length-shared,entries_total:theirs.length,reanchored:!1};const oursSuffix=ours.slice(shared),oursEventIds=new Set(oursSuffix.map(event=>event.eventId)),theirsSuffix=theirs.slice(shared).filter(event=>!oursEventIds.has(event.eventId)),mergedSuffix=[...oursSuffix,...theirsSuffix].sort((left,right)=>{if(left.timestamp!==void 0&&right.timestamp!==void 0){const byTs=compareTimestampStrings(left.timestamp,right.timestamp);if(byTs!==0)return byTs}else{if(left.timestamp===void 0&&right.timestamp!==void 0)return 1;if(left.timestamp!==void 0)return-1}const leftFromOurs=oursEventIds.has(left.eventId),rightFromOurs=oursEventIds.has(right.eventId);return leftFromOurs!==rightFromOurs?Number(rightFromOurs)-Number(leftFromOurs):0}),merged=renumberRelationshipEvents([...ours.slice(0,shared),...mergedSuffix]);return{merged:relationshipEventsToRaw(merged),strategy:"union_reanchor",common_entries:shared,entries_from_ours:oursSuffix.length,entries_from_theirs:theirsSuffix.length,entries_total:merged.length,reanchored:!0}}const ITEM_UNION_COLLECTION_FIELDS=["tags","dependencies","comments","notes","learnings","files","tests","test_runs","docs","reminders","events"],ITEM_UNION_DELIMITED_FIELDS=["acceptance_criteria"],ITEM_LATEST_TIMESTAMP_FIELDS=["updated_at"];function jsonEquals(left,right){return left===void 0||right===void 0?left===void 0&&right===void 0:stableStringify(left)===stableStringify(right)}function unionCollection(base,ours,theirs){const toEntries=value=>Array.isArray(value)?value:[],baseIds=new Set(toEntries(base).map(entry=>stableStringify(entry))),oursEntries=toEntries(ours),oursIds=new Set(oursEntries.map(entry=>stableStringify(entry))),theirsEntries=toEntries(theirs),theirsIds=new Set(theirsEntries.map(entry=>stableStringify(entry))),merged=oursEntries.filter(entry=>{const identity=stableStringify(entry);return!baseIds.has(identity)||theirsIds.has(identity)});for(const entry of theirsEntries){const identity=stableStringify(entry);!oursIds.has(identity)&&!baseIds.has(identity)&&merged.push(entry)}return merged}function linkedTestDefinitionIdentity(value){if(typeof value!="object"||value===null||Array.isArray(value))return stableStringify(value);const{provenance:_provenance,...definition}=value;return stableStringify(definition)}function markMergedLinkedTest(value){if(typeof value!="object"||value===null||Array.isArray(value))return value;const test=value;return test.provenance?{...test,provenance:{...test.provenance,source_kind:"merge_union"}}:{...test,provenance:{source_kind:"merge_union"}}}function unionLinkedTests(base,ours,theirs){const toEntries=value=>Array.isArray(value)?value:[],baseIds=new Set(toEntries(base).map(linkedTestDefinitionIdentity)),oursEntries=toEntries(ours),oursIds=new Set(oursEntries.map(linkedTestDefinitionIdentity)),theirsEntries=toEntries(theirs),theirsIds=new Set(theirsEntries.map(linkedTestDefinitionIdentity)),merged=oursEntries.filter(entry=>{const identity=linkedTestDefinitionIdentity(entry);return!baseIds.has(identity)||theirsIds.has(identity)});for(const entry of theirsEntries){const identity=linkedTestDefinitionIdentity(entry);!oursIds.has(identity)&&!baseIds.has(identity)&&merged.push(markMergedLinkedTest(entry))}return merged}function latestTimestamp(ours,theirs){return compareTimestampStrings(String(ours),String(theirs))>=0?ours:theirs}function mergeScalarThreeWay(base,ours,theirs,preferred){return jsonEquals(ours,theirs)?{value:ours,from_theirs:!1,conflict:!1}:jsonEquals(base,ours)?{value:theirs,from_theirs:!0,conflict:!1}:jsonEquals(base,theirs)?{value:ours,from_theirs:!1,conflict:!1}:{value:preferred==="theirs"?theirs:ours,from_theirs:preferred==="theirs",conflict:!0}}function mergeItemScalarThreeWay(base,ours,theirs,preferred,conflictResolution,oursUpdatedAt,theirsUpdatedAt){const outcome=mergeScalarThreeWay(base,ours,theirs,preferred);if(!outcome.conflict)return{...outcome,conflict:!1};if(conflictResolution==="preferred_side")return{...outcome,resolution_basis:"requested_preference",retained_side:outcome.from_theirs?"theirs":"ours"};const timestampOrder=compareTimestampStrings(oursUpdatedAt,theirsUpdatedAt);if(conflictResolution==="latest_document_update"&&timestampOrder!==0){const retainTheirs2=timestampOrder<0;return{value:retainTheirs2?theirs:ours,from_theirs:retainTheirs2,conflict:!0,resolution_basis:"document_updated_at",retained_side:retainTheirs2?"theirs":"ours"}}const retainTheirs=stableStringify(encodeItemScalarDecisionValue(theirs)).localeCompare(stableStringify(encodeItemScalarDecisionValue(ours)))<0;return{value:retainTheirs?theirs:ours,from_theirs:retainTheirs,conflict:!0,resolution_basis:"stable_value_tiebreak",retained_side:retainTheirs?"theirs":"ours"}}function toMetadataRecord(document){return{...document.metadata}}function parseItemMergeSide(raw,label,options){try{const document=canonicalDocument(parseItemDocument(raw,{...options,requireSupportedFormat:!0}),options),reservedField=Object.entries(document.metadata).find(([,value])=>isItemScalarMissingValue(value))?.[0];if(reservedField!==void 0)throw new TypeError(`metadata field ${reservedField} uses the reserved missing-scalar evidence marker`);return document}catch(error){throw error instanceof PmCliError&&error.context?.code==="item_format_version_unsupported"?error:new PmCliError(`Item merge input (${label}) is not a readable item document: ${String(error)}`,EXIT_CODE.GENERIC_FAILURE)}}function mergeItemUnionField(params){if(!params.unionFieldSet.has(params.field))return!1;const union=params.field==="tests"?unionLinkedTests(params.baseValue,params.oursValue,params.theirsValue):params.field==="acceptance_criteria"?unionCollection(splitAcceptanceCriteria(params.baseValue),splitAcceptanceCriteria(params.oursValue),splitAcceptanceCriteria(params.theirsValue)).join("; "):unionCollection(params.baseValue,params.oursValue,params.theirsValue);return params.accumulator.merged[params.field]=union,jsonEquals(union,params.oursValue)||params.accumulator.unionFields.push(params.field),!0}function mergeItemScalarField(params){const outcome=mergeItemScalarThreeWay(params.baseValue,params.oursValue,params.theirsValue,params.preferred,params.conflictResolution,params.oursUpdatedAt,params.theirsUpdatedAt);outcome.value!==void 0&&(params.accumulator.merged[params.field]=outcome.value),outcome.conflict?(params.accumulator.conflictFields.push(params.field),params.accumulator.conflictDecisions.push({field:params.field,base:encodeItemScalarDecisionValue(params.baseValue),ours:encodeItemScalarDecisionValue(params.oursValue),theirs:encodeItemScalarDecisionValue(params.theirsValue),retained:encodeItemScalarDecisionValue(outcome.value),discarded:encodeItemScalarDecisionValue(outcome.from_theirs?params.oursValue:params.theirsValue),retained_side:outcome.retained_side,resolution_basis:outcome.resolution_basis})):outcome.from_theirs&&params.accumulator.fieldsFromTheirs.push(params.field)}function mergeItemMetadataRecords(baseRecord,oursRecord,theirsRecord,preferred,conflictResolution,oursUpdatedAt,theirsUpdatedAt){const unionFieldSet=new Set([...ITEM_UNION_COLLECTION_FIELDS,...ITEM_UNION_DELIMITED_FIELDS]),latestFieldSet=new Set(ITEM_LATEST_TIMESTAMP_FIELDS),fieldNames=[...new Set([...Object.keys(oursRecord),...Object.keys(theirsRecord)])].sort((left,right)=>left.localeCompare(right)),accumulator={merged:{},conflictFields:[],fieldsFromTheirs:[],unionFields:[],conflictDecisions:[]};for(const field of fieldNames){const baseValue=baseRecord[field],oursValue=oursRecord[field],theirsValue=theirsRecord[field];if(!mergeItemUnionField({field,baseValue,oursValue,theirsValue,unionFieldSet,accumulator})){if(latestFieldSet.has(field)){accumulator.merged[field]=latestTimestamp(oursValue,theirsValue);continue}mergeItemScalarField({field,baseValue,oursValue,theirsValue,preferred,conflictResolution,oursUpdatedAt,theirsUpdatedAt,accumulator})}}return accumulator}function mergeItemDocuments(baseRaw,oursRaw,theirsRaw,options={}){const preferred=options.preferred??"ours",conflictResolution=options.conflictResolution??"preferred_side",ours=parseItemMergeSide(oursRaw,"ours",options),theirs=parseItemMergeSide(theirsRaw,"theirs",options);if(baseRaw.trim().length===0)throw new PmCliError("Duplicate item identity: add/add item documents have no common ancestor. Preserve both branches and assign distinct item ids before merging.",EXIT_CODE.CONFLICT,{code:"item_identity_conflict",item_id:ours.metadata.id});const base=parseItemMergeSide(baseRaw,"base",options);if(base.metadata.id!==ours.metadata.id||base.metadata.id!==theirs.metadata.id)throw new PmCliError("Duplicate or mismatched item identity: all merge sides must address the common ancestor's item id.",EXIT_CODE.CONFLICT,{code:"item_identity_conflict",item_id:base.metadata.id});const baseRecord=toMetadataRecord(base),oursRecord=toMetadataRecord(ours),theirsRecord=toMetadataRecord(theirs),{merged,conflictFields,fieldsFromTheirs,unionFields,conflictDecisions}=mergeItemMetadataRecords(baseRecord,oursRecord,theirsRecord,preferred,conflictResolution,ours.metadata.updated_at,theirs.metadata.updated_at),bodyOutcome=mergeItemScalarThreeWay(base.body,ours.body,theirs.body,preferred,conflictResolution,ours.metadata.updated_at,theirs.metadata.updated_at);bodyOutcome.conflict?(conflictFields.push("body"),conflictDecisions.push({field:"body",base:encodeItemScalarDecisionValue(base.body),ours:encodeItemScalarDecisionValue(ours.body),theirs:encodeItemScalarDecisionValue(theirs.body),retained:encodeItemScalarDecisionValue(bodyOutcome.value),discarded:encodeItemScalarDecisionValue(bodyOutcome.from_theirs?ours.body:theirs.body),retained_side:bodyOutcome.retained_side,resolution_basis:bodyOutcome.resolution_basis})):bodyOutcome.from_theirs&&fieldsFromTheirs.push("body");const mergedMetadata=merged;return mergedMetadata.pm_format_version=normalizeItemFormatVersion(Math.max(...[base.metadata,ours.metadata,theirs.metadata,mergedMetadata].map(requiredItemFormatVersion))),{merged:serializeItemDocument({metadata:mergedMetadata,body:bodyOutcome.value},options),conflict_fields:conflictFields,fields_from_theirs:fieldsFromTheirs,union_fields:unionFields,conflict_decisions:conflictDecisions,requested_preference:preferred,requested_preference_applied:conflictResolution==="preferred_side",conflict_resolution:conflictResolution}}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function parseJsonSide(raw,label){const conflictMarker=findFirstMergeConflictMarker(raw);if(conflictMarker)throw new PmCliError(`JSON merge input (${label}) contains unresolved conflict markers at line ${conflictMarker.line}.`,EXIT_CODE.GENERIC_FAILURE);if(raw.trim().length!==0)try{return JSON.parse(raw)}catch{throw new PmCliError(`JSON merge input (${label}) is not valid JSON.`,EXIT_CODE.GENERIC_FAILURE)}}function mergeAdditiveJsonArrays(base,ours,theirs){if(!Array.isArray(base)||!Array.isArray(ours)||!Array.isArray(theirs))return null;const countEntries=entries=>{const counts=new Map;for(const entry of entries){const identity=stableStringify(entry);counts.set(identity,(counts.get(identity)??0)+1)}return counts},baseCounts=countEntries(base),oursCounts=countEntries(ours),theirsCounts=countEntries(theirs);for(const[identity,baseCount]of baseCounts)if((oursCounts.get(identity)??0)<baseCount||(theirsCounts.get(identity)??0)<baseCount)return null;const unmatchedOursCounts=new Map(oursCounts),additionsFromTheirs=[];for(const entry of theirs){const identity=stableStringify(entry),unmatchedOursCount=unmatchedOursCounts.get(identity)??0;unmatchedOursCount>0?unmatchedOursCounts.set(identity,unmatchedOursCount-1):additionsFromTheirs.push(entry)}return{merged:[...ours,...additionsFromTheirs],acceptedTheirs:additionsFromTheirs.length>0}}function mergeJsonObjects(base,ours,theirs,preferred,pathPrefix,conflictPaths,pathsFromTheirs){if(!isPlainObject(ours)||!isPlainObject(theirs))return null;const baseObject=isPlainObject(base)?base:{},merged={},keys=[...new Set([...Object.keys(ours),...Object.keys(theirs)])].sort((left,right)=>left.localeCompare(right));for(const key of keys){const childPath=pathPrefix.length>0?`${pathPrefix}.${key}`:key,child=mergeJsonKey(baseObject,ours,theirs,key,preferred,childPath,conflictPaths,pathsFromTheirs);child!==void 0&&(merged[key]=child)}return merged}function mergeJsonValue(base,ours,theirs,preferred,pathPrefix,conflictPaths,pathsFromTheirs){if(jsonEquals(ours,theirs))return ours;const additiveArrayMerge=mergeAdditiveJsonArrays(base,ours,theirs);if(additiveArrayMerge!==null)return additiveArrayMerge.acceptedTheirs&&pathsFromTheirs.push(pathPrefix),additiveArrayMerge.merged;const mergedObject=mergeJsonObjects(base,ours,theirs,preferred,pathPrefix,conflictPaths,pathsFromTheirs);if(mergedObject!==null)return mergedObject;const outcome=mergeScalarThreeWay(base,ours,theirs,preferred);return outcome.conflict?conflictPaths.push(pathPrefix):outcome.from_theirs&&pathsFromTheirs.push(pathPrefix),outcome.value}function mergeJsonKey(base,ours,theirs,key,preferred,childPath,conflictPaths,pathsFromTheirs){const inOurs=Object.prototype.hasOwnProperty.call(ours,key),inTheirs=Object.prototype.hasOwnProperty.call(theirs,key),inBase=Object.prototype.hasOwnProperty.call(base,key);if(inOurs&&inTheirs)return mergeJsonValue(base[key],ours[key],theirs[key],preferred,childPath,conflictPaths,pathsFromTheirs);if(inOurs){if(inBase&&jsonEquals(base[key],ours[key])){pathsFromTheirs.push(childPath);return}return inBase?(conflictPaths.push(childPath),preferred==="theirs"?void 0:ours[key]):ours[key]}if(!(inBase&&jsonEquals(base[key],theirs[key])))return inBase?(conflictPaths.push(childPath),preferred==="theirs"?theirs[key]:void 0):(pathsFromTheirs.push(childPath),theirs[key])}function mergeJsonDocuments(baseRaw,oursRaw,theirsRaw,options={}){const preferred=options.preferred??"ours",base=parseJsonSide(baseRaw,"base"),ours=parseJsonSide(oursRaw,"ours"),theirs=parseJsonSide(theirsRaw,"theirs"),conflictPaths=[],pathsFromTheirs=[],merged=mergeJsonValue(base,ours,theirs,preferred,"",conflictPaths,pathsFromTheirs);return{merged:`${JSON.stringify(merged??null,null,2)}
4
4
  `,conflict_paths:conflictPaths,paths_from_theirs:pathsFromTheirs,preferred}}export{ITEM_LATEST_TIMESTAMP_FIELDS,ITEM_SCALAR_MISSING_VALUE,ITEM_UNION_COLLECTION_FIELDS,encodeItemScalarDecisionValue,hashItemScalarDecisionValue,isItemScalarMissingValue,mergeHistoryStreams,mergeItemDocuments,mergeJsonDocuments,mergeRelationshipEventStreams};