@unbrained/pm-cli 2026.8.23 → 2026.8.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +27 -1
  3. package/dist/cli/description-stdin.js +5 -4
  4. package/dist/cli/extension-command-help.d.ts +5 -0
  5. package/dist/cli/extension-command-help.js +6 -2
  6. package/dist/cli/help-content.d.ts +5 -0
  7. package/dist/cli/help-content.js +56 -3
  8. package/dist/cli/help-json-payload.d.ts +5 -2
  9. package/dist/cli/help-json-payload.js +57 -17
  10. package/dist/cli/main.d.ts +3 -0
  11. package/dist/cli/main.js +28 -3
  12. package/dist/cli/register-annotations.js +5 -5
  13. package/dist/cli/register-mutation.js +73 -27
  14. package/dist/cli-bundle/bundle-manifest.json +152 -152
  15. package/dist/cli-bundle/chunks/{chunk-HWZ6CELB.js → chunk-244MI4GS.js} +3 -3
  16. package/dist/cli-bundle/chunks/{chunk-QDVHNHAQ.js → chunk-2F3LUFMW.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-EG6CLDZT.js → chunk-5I5RWIJC.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-KPH73XXJ.js → chunk-65MHLHAA.js} +2 -2
  19. package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +13 -0
  20. package/dist/cli-bundle/chunks/chunk-OWHNAR2B.js +2 -0
  21. package/dist/cli-bundle/chunks/chunk-QKGMHGEI.js +202 -0
  22. package/dist/cli-bundle/chunks/chunk-QLUORNIB.js +2092 -0
  23. package/dist/cli-bundle/chunks/{chunk-JB4KZWBF.js → chunk-T2ENPRXF.js} +2 -2
  24. package/dist/cli-bundle/chunks/{chunk-F3AI2JFL.js → chunk-TPQIBSL2.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +35 -0
  26. package/dist/cli-bundle/chunks/{register-list-query-UJB5FMV2.js → register-list-query-XVN2ZLI7.js} +2 -2
  27. package/dist/cli-bundle/chunks/register-mutation-QCKAEGIJ.js +20 -0
  28. package/dist/cli-bundle/chunks/{register-operations-RXIJIYXC.js → register-operations-SDEAXE7E.js} +2 -2
  29. package/dist/cli-bundle/chunks/{register-setup-GFUZEKRE.js → register-setup-LXVBRCJ3.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-QGFNI65N.js → chunk-2UIWOP3O.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +50 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-OGLQBL46.js → chunk-7I23XGWO.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-7YCDTCBC.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/{chunk-OFVUGTLJ.js → chunk-A644DUFQ.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-AUFH5H35.js → chunk-GQR3WH3F.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-3UPTYG44.js → chunk-H5JZEIQV.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/chunk-IBZZZGK3.js +2 -0
  38. package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +5 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-LYVSW5VM.js → chunk-N7W67YIG.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-37Z4OEAP.js → chunk-NOOZGIXP.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-FZS4H32O.js → chunk-OHIHZ7HS.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-ONYQCALA.js +19 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-OVJL6NZE.js +4 -0
  44. package/dist/cli-bundle/focused-chunks/chunk-RAFKLNZX.js +16 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-IFLWKY2R.js → chunk-VXWATRFL.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-R27IDGHD.js → chunk-XUQPEKRN.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-JOWDB2MH.js → chunk-YO3ZF3FI.js} +2 -2
  48. package/dist/cli-bundle/main.js +18 -17
  49. package/dist/cli-bundle/sdk-authoring.js +1 -1
  50. package/dist/cli-bundle/sdk-contracts.js +2 -2
  51. package/dist/cli-bundle/sdk-core.js +32 -32
  52. package/dist/cli-bundle/sdk-governance.js +1 -1
  53. package/dist/cli-bundle/sdk-graph.js +1 -1
  54. package/dist/cli-bundle/sdk-merge.js +32 -33
  55. package/dist/cli-bundle/sdk-query.js +1 -1
  56. package/dist/cli-bundle/sdk-runtime.js +1 -1
  57. package/dist/cli-bundle/sdk-testing.js +1 -1
  58. package/dist/cli-bundle/sdk.js +6 -5
  59. package/dist/core/diagnostics/remediation.js +17 -2
  60. package/dist/core/extensions/command-metadata-contract.d.ts +10 -0
  61. package/dist/core/extensions/command-metadata-contract.js +23 -0
  62. package/dist/core/extensions/command-visibility-tier.js +12 -2
  63. package/dist/core/extensions/extension-types.d.ts +6 -0
  64. package/dist/core/extensions/extension-types.js +2 -2
  65. package/dist/core/extensions/loader.js +4 -3
  66. package/dist/core/io/body-file.js +7 -2
  67. package/dist/core/io/bulk-ids-input.d.ts +24 -0
  68. package/dist/core/io/bulk-ids-input.js +113 -0
  69. package/dist/core/item/parse.d.ts +22 -2
  70. package/dist/core/item/parse.js +97 -4
  71. package/dist/mcp/server.d.ts +3 -2
  72. package/dist/mcp/server.js +16 -9
  73. package/dist/sdk/agent/refusal-closure-census.d.ts +66 -0
  74. package/dist/sdk/agent/refusal-closure-census.js +144 -0
  75. package/dist/sdk/agent-capability-contracts.d.ts +34 -1
  76. package/dist/sdk/agent-capability-contracts.js +104 -6
  77. package/dist/sdk/annotations.d.ts +2 -0
  78. package/dist/sdk/annotations.js +25 -7
  79. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +10 -0
  80. package/dist/sdk/cli-contracts/runtime-contracts.js +20 -3
  81. package/dist/sdk/cli-contracts/tool-parameter-tables.js +38 -2
  82. package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +4 -1
  83. package/dist/sdk/cli-contracts/typed-action-inputs.js +2 -2
  84. package/dist/sdk/comments.js +15 -7
  85. package/dist/sdk/flag-invocation-contracts.d.ts +2 -0
  86. package/dist/sdk/flag-invocation-contracts.js +28 -3
  87. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +109 -52
  88. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +62 -2
  89. package/dist/sdk/governance/health.js +98 -11
  90. package/dist/sdk/governance/validate.js +15 -9
  91. package/dist/sdk/guide-topics.d.ts +0 -5
  92. package/dist/sdk/guide-topics.js +28 -2
  93. package/dist/sdk/history-compact.d.ts +2 -1
  94. package/dist/sdk/history-compact.js +24 -5
  95. package/dist/sdk/history-mcp.js +11 -10
  96. package/dist/sdk/history-repair.d.ts +24 -0
  97. package/dist/sdk/history-repair.js +145 -4
  98. package/dist/sdk/index.d.ts +1 -0
  99. package/dist/sdk/index.js +3 -2
  100. package/dist/sdk/item-transaction.js +19 -12
  101. package/dist/sdk/lifecycle/append.js +4 -4
  102. package/dist/sdk/lifecycle/close-many.js +16 -7
  103. package/dist/sdk/lifecycle/create.js +29 -21
  104. package/dist/sdk/lifecycle/plan.js +24 -6
  105. package/dist/sdk/lifecycle/update-many.js +15 -8
  106. package/dist/sdk/lifecycle/update.d.ts +2 -0
  107. package/dist/sdk/lifecycle/update.js +34 -24
  108. package/dist/sdk/merge/driver.js +25 -4
  109. package/dist/sdk/merge/receipt-file-boundary.d.ts +21 -0
  110. package/dist/sdk/merge/receipt-file-boundary.js +47 -0
  111. package/dist/sdk/merge/receipts.d.ts +24 -1
  112. package/dist/sdk/merge/receipts.js +342 -36
  113. package/dist/sdk/merge/reconcile.js +117 -47
  114. package/dist/sdk/read-output/continuation.d.ts +15 -2
  115. package/dist/sdk/read-output/continuation.js +86 -6
  116. package/dist/sdk/read-output-contracts.d.ts +4 -1
  117. package/dist/sdk/read-output-contracts.js +9 -6
  118. package/dist/sdk/runtime-extended-actions.js +5 -3
  119. package/dist/sdk/runtime-input.d.ts +4 -0
  120. package/dist/sdk/runtime-input.js +98 -23
  121. package/dist/sdk/runtime-primitives.d.ts +2 -1
  122. package/dist/sdk/runtime-primitives.js +4 -3
  123. package/dist/sdk/runtime.js +7 -20
  124. package/dist/sdk/scheduling-shortcuts.js +5 -3
  125. package/dist/sdk/structured-mutations.js +10 -3
  126. package/dist/sdk/workspace-contracts.d.ts +3 -0
  127. package/dist/sdk/workspace-contracts.js +3 -2
  128. package/docs/MERGE_SAFETY.md +34 -5
  129. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +13 -1
  130. package/docs/README.md +2 -0
  131. package/docs/READ_OUTPUT_CONTRACTS.md +25 -2
  132. package/docs/RELEASING.md +40 -21
  133. package/docs/SCRIPTING.md +62 -3
  134. package/docs/SDK.md +8 -0
  135. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +17 -0
  136. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
  137. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +359 -0
  138. package/marketplace.json +2 -2
  139. package/package.json +1 -1
  140. package/packages/pm-beads/package.json +1 -1
  141. package/packages/pm-calendar/package.json +1 -1
  142. package/packages/pm-command-kit/README.md +9 -11
  143. package/packages/pm-command-kit/extensions/command-kit/index.ts +3 -1
  144. package/packages/pm-command-kit/package.json +1 -1
  145. package/packages/pm-digital-twin/package.json +1 -1
  146. package/packages/pm-governance-audit/package.json +1 -1
  147. package/packages/pm-guide-shell/extensions/guide-shell/index.ts +10 -0
  148. package/packages/pm-guide-shell/package.json +1 -1
  149. package/packages/pm-kanban/package.json +1 -1
  150. package/packages/pm-lifecycle-hooks/package.json +1 -1
  151. package/packages/pm-linked-test-adapters/package.json +1 -1
  152. package/packages/pm-search-advanced/package.json +1 -1
  153. package/packages/pm-templates/package.json +1 -1
  154. package/packages/pm-todos/package.json +1 -1
  155. package/packages/pm-vcs/package.json +1 -1
  156. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  157. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  158. package/scripts/generate-agent-capability-surfaces.mjs +27 -1
  159. package/sdk/public-surface.json +351 -26
  160. package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +0 -36
  161. package/dist/cli-bundle/chunks/chunk-DW2CGEMU.js +0 -2
  162. package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +0 -201
  163. package/dist/cli-bundle/chunks/chunk-KXPMB2YL.js +0 -2092
  164. package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +0 -13
  165. package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +0 -20
  166. package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +0 -16
  167. package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +0 -2
  168. package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +0 -4
  169. package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +0 -2
  170. package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +0 -51
  171. package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +0 -5
  172. package/dist/cli-bundle/focused-chunks/chunk-ZHVA42R5.js +0 -18
@@ -4,15 +4,15 @@
4
4
  * Implements the pm update many command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7a157c2e-e9e6-5bce-b124-0a7d34e3c7dc")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="fada7a33-ad1d-54f1-ae03-c5f8e4568d75")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
- 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, resolveIsoOrRelative, getActiveExtensionRegistrations, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
9
+ 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";
10
10
  import { assertDependencyTargetsResolvable } from "../dependency-flag-validation.js";
11
11
  import { parseStatusFilterCsv } from "../../core/item/status-filter.js";
12
12
  import { hasListFilters } from "../query/list-filter-shared.js";
13
13
  import { runList, } from "../query/list.js";
14
14
  import { runRestore } from "./restore.js";
15
- import { assertUpdateMutationOptionCombinations, parseDependencyAdditions, runUpdate, } from "./update.js";
15
+ import { assertUpdateMutationOptionCombinations, parseDependencyAdditions, resolveUpdateTransportOptions, runUpdate, } from "./update.js";
16
16
  import { derivePmBulkMutationEffect, } from "../cli-contracts/command-exit-contracts.js";
17
17
  const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION = 1;
18
18
  const UPDATE_MANY_CHECKPOINT_SUBDIR = "update-many";
@@ -703,11 +703,12 @@ const applyUpdateManyRows = async (params) => {
703
703
  continue;
704
704
  }
705
705
  try {
706
- const result = await runUpdate(item.id, {
706
+ const rowUpdateOptions = preserveMutationStdinTokenLiterals({
707
707
  ...params.options.update,
708
708
  message: updateMessage,
709
709
  runtimeFieldCommands: ["update_many"],
710
- }, params.global);
710
+ });
711
+ const result = await runUpdate(item.id, rowUpdateOptions, params.global);
711
712
  rows.push({
712
713
  id: item.id,
713
714
  status: "updated",
@@ -786,6 +787,12 @@ const applyUpdateManyPlan = async (params) => {
786
787
  export const runUpdateMany = async (options, global) => {
787
788
  const runtime = await loadUpdateManyRuntimeContext(global);
788
789
  const rollbackId = typeof options.rollback === "string" ? options.rollback : undefined;
790
+ if (rollbackId === undefined) {
791
+ options = {
792
+ ...options,
793
+ update: preserveMutationStdinTokenLiterals(await resolveUpdateTransportOptions(options.update)),
794
+ };
795
+ }
789
796
  const updateSummary = sanitizeUpdateOptionsForSummary(options.update);
790
797
  rejectBlankIdsFilter(options.list);
791
798
  if (rollbackId !== undefined) {
@@ -797,8 +804,8 @@ export const runUpdateMany = async (options, global) => {
797
804
  updateSummary,
798
805
  });
799
806
  }
800
- if (!hasAnyUpdateMutationInput(options.update)) {
801
- throw new PmCliError(`No update-many mutation flags provided. Add at least one mutation flag (for example: ${UPDATE_MANY_MUTATION_FLAG_GUIDANCE}).`, EXIT_CODE.USAGE);
807
+ if (!hasAnyUpdateMutationInput(options.update) && options.dryRun !== true) {
808
+ 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);
802
809
  }
803
810
  assertPlannedUpdateValuesValid(options.update, runtime.settings, runtime.statusRegistry, runtime.pmRoot);
804
811
  assertUpdateMutationOptionCombinations(options.update);
@@ -852,4 +859,4 @@ export const _testOnlyUpdateManyCommand = {
852
859
  toComparablePreviewValue,
853
860
  };
854
861
  //# sourceMappingURL=update-many.js.map
855
- //# debugId=7a157c2e-e9e6-5bce-b124-0a7d34e3c7dc
862
+ //# debugId=fada7a33-ad1d-54f1-ae03-c5f8e4568d75
@@ -159,6 +159,8 @@ interface UpdateMutationContext {
159
159
  author: string;
160
160
  pmRoot: string;
161
161
  }
162
+ /** Resolve update stdin tokens once while preserving transport-marked literals. */
163
+ export declare function resolveUpdateTransportOptions(options: UpdateCommandOptions): Promise<UpdateCommandOptions>;
162
164
  /** Validate mutually exclusive and required update mutation option combinations. */
163
165
  export declare function assertUpdateMutationOptionCombinations(options: UpdateCommandOptions): void;
164
166
  type UpdateStatusMutationContext = Pick<UpdateMutationContext, "options" | "statusRegistry" | "clearItemMetadataKeys" | "nowIso">;
@@ -4,9 +4,10 @@
4
4
  * Implements the pm update command surface and its agent-facing runtime behavior.
5
5
  */
6
6
 
7
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="c88f01be-6abe-5fa2-9792-3f54e61bb282")}catch(e){}}();
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6865ca88-7ca1-52fd-86fb-2a3439abeafa")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
- import { COMMON_MUTATION_COMMAND_OPTION_KEYS, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, normalizeItemId, toItemRecord, buildInvalidTypeError, assertParentReferenceIsNotSelf, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, applyAcceptanceCriteriaMutations, applyTagRemovals, assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, isTerminalStatus, collectRuntimeUpdateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, describeAllowedTransitions, evaluateTransition, resolveTypeWorkflows, EXIT_CODE, PmCliError, stableValueEquals, resolveIsoOrRelative, getActiveExtensionRegistrations, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, buildItemNotFoundError, listAllItemMetadataLight, locateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
9
+ import { resolveMutationStdinTokenFields } from "../../core/item/parse.js";
10
+ import { COMMON_MUTATION_COMMAND_OPTION_KEYS, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, normalizeItemId, toItemRecord, buildInvalidTypeError, assertParentReferenceIsNotSelf, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, applyAcceptanceCriteriaMutations, applyTagRemovals, assertNoUnknownCsvKeys, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, shouldResolveMutationStdinTokens, transferMutationStdinTokenPolicy, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, isTerminalStatus, collectRuntimeUpdateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, describeAllowedTransitions, evaluateTransition, resolveTypeWorkflows, EXIT_CODE, PmCliError, stableValueEquals, resolveIsoOrRelative, getActiveExtensionRegistrations, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, buildItemNotFoundError, listAllItemMetadataLight, locateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
10
11
  import { mutateItemWithHistoryContextResolver } from "../../core/store/item-store.js";
11
12
  import { runClose } from "./close.js";
12
13
  import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
@@ -108,7 +109,7 @@ function normalizeLegacyNoneUpdateOptions(options) {
108
109
  normalized[optionKey] = undefined;
109
110
  /* c8 ignore stop */
110
111
  }
111
- return applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS);
112
+ return transferMutationStdinTokenPolicy(options, applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS));
112
113
  }
113
114
  function parseUpdateUnsetTargets(raw, runtimeFieldRegistry, extensionFieldNames = []) {
114
115
  return parseCommandUnsetTargets({
@@ -858,23 +859,31 @@ function applyUpdateScalarMutations(definitions, options, context) {
858
859
  }
859
860
  }
860
861
  async function resolveStdinUpdateOptions(options) {
861
- const stdinResolver = createStdinTokenResolver();
862
- return normalizeLegacyNoneUpdateOptions({
863
- ...options,
864
- body: await stdinResolver.resolveValue(options.body, "--body"),
865
- dep: await stdinResolver.resolveList(options.dep, "--dep"),
866
- depRemove: await stdinResolver.resolveList(options.depRemove, "--dep-remove"),
867
- comment: await stdinResolver.resolveList(options.comment, "--comment"),
868
- note: await stdinResolver.resolveList(options.note, "--note"),
869
- learning: await stdinResolver.resolveList(options.learning, "--learning"),
870
- file: await stdinResolver.resolveList(options.file, "--file"),
871
- test: await stdinResolver.resolveList(options.test, "--test"),
872
- doc: await stdinResolver.resolveList(options.doc, "--doc"),
873
- reminder: await stdinResolver.resolveList(options.reminder, "--reminder"),
874
- event: await stdinResolver.resolveList(options.event, "--event"),
875
- typeOption: await stdinResolver.resolveList(options.typeOption, "--type-option"),
876
- field: await stdinResolver.resolveList(options.field, "--field"),
877
- });
862
+ const scalarFields = [
863
+ ["body", "--body"],
864
+ ["description", "--description"],
865
+ ];
866
+ const listFields = [
867
+ ["dep", "--dep"],
868
+ ["depRemove", "--dep-remove"],
869
+ ["comment", "--comment"],
870
+ ["note", "--note"],
871
+ ["learning", "--learning"],
872
+ ["file", "--file"],
873
+ ["test", "--test"],
874
+ ["doc", "--doc"],
875
+ ["reminder", "--reminder"],
876
+ ["event", "--event"],
877
+ ["typeOption", "--type-option"],
878
+ ["field", "--field"],
879
+ ];
880
+ return normalizeLegacyNoneUpdateOptions(await resolveMutationStdinTokenFields(options, scalarFields, listFields));
881
+ }
882
+ /** Resolve update stdin tokens once while preserving transport-marked literals. */
883
+ export async function resolveUpdateTransportOptions(options) {
884
+ return shouldResolveMutationStdinTokens(options)
885
+ ? await resolveStdinUpdateOptions(options)
886
+ : normalizeLegacyNoneUpdateOptions(options);
878
887
  }
879
888
  function buildClearCollectionDefinitions(options) {
880
889
  return [
@@ -1220,12 +1229,13 @@ async function routeCloseStatusUpdate(context) {
1220
1229
  const routeWarnings = [];
1221
1230
  let preChangedFields = [];
1222
1231
  if (otherFieldKeys.length > 0) {
1223
- const preUpdate = await runUpdate(context.id, {
1232
+ const preUpdateOptions = transferMutationStdinTokenPolicy(context.options, {
1224
1233
  ...context.options,
1225
1234
  status: undefined,
1226
1235
  closeReason: undefined,
1227
1236
  message: undefined,
1228
- }, context.global);
1237
+ });
1238
+ const preUpdate = await runUpdate(context.id, preUpdateOptions, context.global);
1229
1239
  preChangedFields = preUpdate.changed_fields;
1230
1240
  routeWarnings.push(...preUpdate.warnings);
1231
1241
  }
@@ -1804,7 +1814,7 @@ function mutateUpdateDocument(document, context) {
1804
1814
  }
1805
1815
  /** Implements run update for the public runtime surface of this module. */
1806
1816
  async function runUpdateWithContext(id, options, global, execution = {}) {
1807
- options = await resolveStdinUpdateOptions(options);
1817
+ options = await resolveUpdateTransportOptions(options);
1808
1818
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
1809
1819
  await assertUpdateTrackerInitialized(pmRoot);
1810
1820
  const settings = await readSettings(pmRoot);
@@ -2111,4 +2121,4 @@ export const _testOnlyUpdateCommand = {
2111
2121
  resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
2112
2122
  };
2113
2123
  //# sourceMappingURL=update.js.map
2114
- //# debugId=c88f01be-6abe-5fa2-9792-3f54e61bb282
2124
+ //# debugId=6865ca88-7ca1-52fd-86fb-2a3439abeafa
@@ -9,14 +9,16 @@
9
9
  * merge never corrupts tracker storage the way raw conflict markers do.
10
10
  */
11
11
 
12
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8d79e3a4-6104-5855-837f-69a041b87b27")}catch(e){}}();
12
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="2c8046a5-06aa-58f8-b347-e757086082d1")}catch(e){}}();
13
13
  import { readFile, writeFile } from "node:fs/promises";
14
14
  import path from "node:path";
15
15
  import { getActiveExtensionRegistrations } from "../../core/extensions/index.js";
16
16
  import { collectRegisteredItemFieldNames } from "../../core/extensions/item-fields.js";
17
17
  import { pathExists } from "../../core/fs/fs-utils.js";
18
+ import { parseItemDocument } from "../../core/item/item-format.js";
18
19
  import { EXIT_CODE } from "../../core/shared/constants.js";
19
20
  import { PmCliError } from "../../core/shared/errors.js";
21
+ import { sha256Hex, stableStringify } from "../../core/shared/serialization.js";
20
22
  import { nowIso } from "../../core/shared/time.js";
21
23
  import { getSettingsPath, resolvePmRoot } from "../../core/store/paths.js";
22
24
  import { readSettings } from "../../core/store/settings.js";
@@ -122,10 +124,12 @@ export async function runMergeDriver(options, global) {
122
124
  }
123
125
  else if (artifact === "item") {
124
126
  const settings = await loadOptionalSettings(global);
127
+ const itemFormat = itemFormatForPath(options.itemPath ?? outputPath, settings);
128
+ const extensionFieldNames = collectRegisteredItemFieldNames(getActiveExtensionRegistrations());
125
129
  const itemMerge = mergeItemDocuments(baseRaw, oursRaw, theirsRaw, {
126
- format: itemFormatForPath(options.itemPath ?? outputPath, settings),
130
+ format: itemFormat,
127
131
  schema: settings?.schema,
128
- extensionFieldNames: collectRegisteredItemFieldNames(getActiveExtensionRegistrations()),
132
+ extensionFieldNames,
129
133
  preferred,
130
134
  conflictResolution: "stable_value_order",
131
135
  });
@@ -137,6 +141,19 @@ export async function runMergeDriver(options, global) {
137
141
  conflict_resolution: "stable_value_order",
138
142
  };
139
143
  if (options.itemPath !== undefined) {
144
+ const mergedDocument = parseItemDocument(merged, {
145
+ format: itemFormat,
146
+ schema: settings?.schema,
147
+ extensionFieldNames,
148
+ });
149
+ const mergedMetadata = mergedDocument.metadata;
150
+ const receiptFields = [
151
+ ...new Set([
152
+ ...itemMerge.fields_from_theirs,
153
+ ...itemMerge.union_fields,
154
+ ...itemMerge.conflict_decisions.map((decision) => decision.field),
155
+ ]),
156
+ ];
140
157
  receiptInput = {
141
158
  cwd: process.cwd(),
142
159
  itemPath: options.itemPath,
@@ -144,6 +161,10 @@ export async function runMergeDriver(options, global) {
144
161
  conflictResolution: "stable_value_order",
145
162
  fieldsFromTheirs: itemMerge.fields_from_theirs,
146
163
  unionFields: itemMerge.union_fields,
164
+ mergedFieldHashes: Object.fromEntries(receiptFields.map((field) => [
165
+ field,
166
+ sha256Hex(stableStringify(field === "body" ? mergedDocument.body : mergedMetadata[field])),
167
+ ])),
147
168
  decisions: itemMerge.conflict_decisions,
148
169
  };
149
170
  }
@@ -187,4 +208,4 @@ export async function runMergeDriver(options, global) {
187
208
  };
188
209
  }
189
210
  //# sourceMappingURL=driver.js.map
190
- //# debugId=8d79e3a4-6104-5855-837f-69a041b87b27
211
+ //# debugId=2c8046a5-06aa-58f8-b347-e757086082d1
@@ -0,0 +1,21 @@
1
+ /**
2
+ * @module sdk/merge/receipt-file-boundary
3
+ *
4
+ * Reads untrusted receipt candidates through a bounded, no-follow file
5
+ * boundary whose race and short-read behavior can be exercised directly.
6
+ */
7
+ import { type Stats } from "node:fs";
8
+ import { type FileHandle } from "node:fs/promises";
9
+ /** Minimal filesystem operations required by the receipt reader. */
10
+ export interface ReceiptFileBoundary {
11
+ /** Inspect the path without following its final symbolic link. */
12
+ lstat(receiptPath: string): Promise<Stats>;
13
+ /** Open the candidate and return the handle used for verified reads. */
14
+ open(receiptPath: string, flags: number): Promise<FileHandle>;
15
+ }
16
+ /** Resolve the platform no-follow flag, falling back only where Node omits it. */
17
+ export declare function resolveReceiptNoFollowFlag(constants: {
18
+ O_NOFOLLOW?: number;
19
+ }): number;
20
+ /** Read one regular file only when its opened identity remains bounded and stable. */
21
+ export declare function readBoundedRegularFile(receiptPath: string, maximumBytes: number, boundary?: ReceiptFileBoundary): Promise<string | null>;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * @module sdk/merge/receipt-file-boundary
3
+ *
4
+ * Reads untrusted receipt candidates through a bounded, no-follow file
5
+ * boundary whose race and short-read behavior can be exercised directly.
6
+ */
7
+
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6ece0e15-aff5-5e2d-b18a-16ffaa0fe2ea")}catch(e){}}();
9
+ import { constants as fsConstants } from "node:fs";
10
+ import { lstat, open } from "node:fs/promises";
11
+ const NODE_RECEIPT_FILE_BOUNDARY = { lstat, open };
12
+ /** Resolve the platform no-follow flag, falling back only where Node omits it. */
13
+ export function resolveReceiptNoFollowFlag(constants) {
14
+ return constants.O_NOFOLLOW ?? 0;
15
+ }
16
+ /** Read one regular file only when its opened identity remains bounded and stable. */
17
+ export async function readBoundedRegularFile(receiptPath, maximumBytes, boundary = NODE_RECEIPT_FILE_BOUNDARY) {
18
+ const pathStats = await boundary.lstat(receiptPath);
19
+ if (pathStats.isSymbolicLink() ||
20
+ !pathStats.isFile() ||
21
+ pathStats.size > maximumBytes) {
22
+ return null;
23
+ }
24
+ const handle = await boundary.open(receiptPath, fsConstants.O_RDONLY | resolveReceiptNoFollowFlag(fsConstants));
25
+ try {
26
+ const openedStats = await handle.stat();
27
+ if (!openedStats.isFile() || openedStats.size > maximumBytes)
28
+ return null;
29
+ const buffer = Buffer.alloc(openedStats.size);
30
+ let offset = 0;
31
+ while (offset < buffer.length) {
32
+ const { bytesRead } = await handle.read(buffer, offset, buffer.length - offset, offset);
33
+ if (bytesRead === 0)
34
+ break;
35
+ offset += bytesRead;
36
+ }
37
+ const finalStats = await handle.stat();
38
+ return finalStats.size === openedStats.size && offset === openedStats.size
39
+ ? buffer.toString("utf8", 0, offset)
40
+ : null;
41
+ }
42
+ finally {
43
+ await handle.close();
44
+ }
45
+ }
46
+ //# sourceMappingURL=receipt-file-boundary.js.map
47
+ //# debugId=6ece0e15-aff5-5e2d-b18a-16ffaa0fe2ea
@@ -19,6 +19,8 @@ export interface MergeDecisionReceipt {
19
19
  fields_from_theirs: string[];
20
20
  /** Collections combined from both branches. */
21
21
  union_fields: string[];
22
+ /** SHA-256 hashes of the merged values for every field represented by this receipt. Absent on legacy receipts, which cannot prove drift attribution. */
23
+ merged_field_hashes?: Record<string, string>;
22
24
  /** Full recoverable scalar decisions, retained only in the clone. */
23
25
  decisions: ItemMergeConflictDecision[];
24
26
  /** Whether a merge reconciliation history event consumed this receipt. */
@@ -29,6 +31,8 @@ export interface MergeDecisionReceipt {
29
31
  reconciled_at?: string;
30
32
  /** Whether decision values are recoverable locally or represented by hashes only. */
31
33
  value_availability?: "clone_local" | "hash_only";
34
+ /** Runtime-only provenance assigned by the reader; serialized values are ignored. */
35
+ evidence_source?: "clone_local" | "durable";
32
36
  }
33
37
  /** Privacy-safe receipt summary suitable for committed history context. */
34
38
  export interface MergeDecisionReceiptSummary {
@@ -66,6 +70,13 @@ export interface MergeReceiptReport {
66
70
  /** ISO timestamp for the report. */
67
71
  generated_at: string;
68
72
  }
73
+ /** Internal integrity scan result used by health without exposing malformed receipt contents. */
74
+ export interface MergeReceiptEvidenceScan {
75
+ /** Valid receipts that passed bounded-file, schema, and identity validation. */
76
+ receipts: MergeDecisionReceipt[];
77
+ /** Number of JSON receipt candidates that could not be validated safely. */
78
+ invalid_evidence_count: number;
79
+ }
69
80
  /** Convert a raw receipt into privacy-safe history context. */
70
81
  export declare function summarizeMergeReceipt(receipt: MergeDecisionReceipt): MergeDecisionReceiptSummary;
71
82
  /** Persist one item-driver outcome in the clone-local Git directory. */
@@ -76,8 +87,18 @@ export declare function writeMergeReceipt(params: {
76
87
  conflictResolution?: "preferred_side" | "stable_value_order";
77
88
  fieldsFromTheirs: string[];
78
89
  unionFields: string[];
90
+ mergedFieldHashes?: Record<string, string>;
79
91
  decisions: ItemMergeConflictDecision[];
80
92
  }): Promise<MergeDecisionReceipt | null>;
93
+ /** Inspect valid receipts and count invalid evidence without returning untrusted file contents. */
94
+ export declare function inspectMergeReceiptEvidence(cwd: string, options?: {
95
+ /** Include receipts whose reconciliation state is already settled. */
96
+ includeReconciled?: boolean;
97
+ /** Include receipts that contain no discarded scalar values. */
98
+ includeLossless?: boolean;
99
+ /** Explicit tracker root used to locate durable receipt evidence. */
100
+ pmRoot?: string;
101
+ }): Promise<MergeReceiptEvidenceScan>;
81
102
  /** Read clone-local receipts with explicit reconciled/lossless classification controls. */
82
103
  export declare function listMergeReceipts(cwd: string, options?: {
83
104
  includeReconciled?: boolean;
@@ -92,7 +113,9 @@ export declare function partitionMergeReceipts(receipts: MergeDecisionReceipt[])
92
113
  lossless: MergeDecisionReceipt[];
93
114
  };
94
115
  /** Mark a receipt as represented by a committed merge history event. */
95
- export declare function markMergeReceiptReconciled(cwd: string, receipt: MergeDecisionReceipt): Promise<void>;
116
+ export declare function markMergeReceiptReconciled(cwd: string, receipt: MergeDecisionReceipt, options?: {
117
+ requireExisting?: boolean;
118
+ }): Promise<void>;
96
119
  /** Report pending or historical clone-local merge decisions. */
97
120
  export declare function runMergeReceiptReport(options: {
98
121
  /** Include receipts already represented by merge history events. */