@unbrained/pm-cli 2026.8.22 → 2026.8.24

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 (229) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +42 -1
  3. package/dist/cli/description-stdin.js +5 -4
  4. package/dist/cli/error-guidance.d.ts +13 -0
  5. package/dist/cli/error-guidance.js +62 -6
  6. package/dist/cli/extension-command-help.d.ts +5 -0
  7. package/dist/cli/extension-command-help.js +6 -2
  8. package/dist/cli/help-content.d.ts +5 -0
  9. package/dist/cli/help-content.js +56 -3
  10. package/dist/cli/help-json-payload.d.ts +5 -2
  11. package/dist/cli/help-json-payload.js +57 -17
  12. package/dist/cli/main.d.ts +3 -0
  13. package/dist/cli/main.js +39 -5
  14. package/dist/cli/register-annotations.js +5 -5
  15. package/dist/cli/register-mutation.js +77 -31
  16. package/dist/cli/register-operations.d.ts +73 -0
  17. package/dist/cli/register-operations.js +39 -14
  18. package/dist/cli/register-setup.js +3 -3
  19. package/dist/cli/schema-registration-helpers.d.ts +8 -1
  20. package/dist/cli/schema-registration-helpers.js +14 -5
  21. package/dist/cli-bundle/bundle-manifest.json +155 -155
  22. package/dist/cli-bundle/chunks/chunk-AGUL3HUT.js +3 -0
  23. package/dist/cli-bundle/chunks/{chunk-WG4STC36.js → chunk-DJNJBWAQ.js} +2 -2
  24. package/dist/cli-bundle/chunks/{chunk-MYYI3ZOA.js → chunk-I5Q7QSZX.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-IW72J5FW.js +2 -0
  26. package/dist/cli-bundle/chunks/{chunk-BWX4SK46.js → chunk-L22NP5MA.js} +66 -66
  27. package/dist/cli-bundle/chunks/chunk-MKE6MD2K.js +36 -0
  28. package/dist/cli-bundle/chunks/{chunk-MZTZQTMS.js → chunk-NXBFO63A.js} +2 -2
  29. package/dist/cli-bundle/chunks/chunk-TEQDR5KI.js +202 -0
  30. package/dist/cli-bundle/chunks/chunk-X7WWQDYQ.js +2 -0
  31. package/dist/cli-bundle/chunks/chunk-YOLLRCLY.js +13 -0
  32. package/dist/cli-bundle/chunks/{chunk-U6GQ4VMV.js → chunk-ZAVCS2GH.js} +4 -4
  33. package/dist/cli-bundle/chunks/{register-list-query-HZKBQNWW.js → register-list-query-37A4P6O4.js} +2 -2
  34. package/dist/cli-bundle/chunks/register-mutation-TBJDHYIT.js +20 -0
  35. package/dist/cli-bundle/chunks/register-operations-WRZNEBUM.js +2 -0
  36. package/dist/cli-bundle/chunks/{register-setup-QK4OTOXN.js → register-setup-H4PDLACD.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-GMYPD4FX.js → chunk-4WP7LNE3.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-6MUTDXMP.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/chunk-6Z24ZMU3.js +2 -0
  40. package/dist/cli-bundle/focused-chunks/{chunk-2ARQGDDW.js → chunk-BFA6KKCI.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/chunk-CWCN5RLO.js +26 -0
  42. package/dist/cli-bundle/focused-chunks/chunk-FCTT4CZU.js +5 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-GJR6YEMR.js +156 -0
  44. package/dist/cli-bundle/focused-chunks/{chunk-2POVTNLY.js → chunk-IMWTYKII.js} +2 -2
  45. package/dist/cli-bundle/focused-chunks/{chunk-D6RBZEJJ.js → chunk-IZNRRCU3.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-PMGJUFNQ.js → chunk-MNPECIRL.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-A2BC5PQL.js → chunk-O4ZXNJMT.js} +2 -2
  48. package/dist/cli-bundle/focused-chunks/chunk-Q63PSLO4.js +2 -0
  49. package/dist/cli-bundle/focused-chunks/chunk-QBP5FSBX.js +4 -0
  50. package/dist/cli-bundle/focused-chunks/{chunk-R6SR45XU.js → chunk-QV5UP27O.js} +48 -47
  51. package/dist/cli-bundle/focused-chunks/chunk-RASVBJX5.js +8 -0
  52. package/dist/cli-bundle/focused-chunks/{chunk-E2EWYPY6.js → chunk-RPRLENVA.js} +2 -2
  53. package/dist/cli-bundle/focused-chunks/chunk-TOFVXBWA.js +19 -0
  54. package/dist/cli-bundle/focused-chunks/{chunk-6S2MO3Q3.js → chunk-WZLSSGEU.js} +2 -2
  55. package/dist/cli-bundle/main.js +18 -17
  56. package/dist/cli-bundle/sdk-authoring.js +1 -1
  57. package/dist/cli-bundle/sdk-contracts.js +2 -2
  58. package/dist/cli-bundle/sdk-core.js +41 -41
  59. package/dist/cli-bundle/sdk-governance.js +1 -1
  60. package/dist/cli-bundle/sdk-graph.js +1 -1
  61. package/dist/cli-bundle/sdk-merge.js +33 -32
  62. package/dist/cli-bundle/sdk-query.js +1 -1
  63. package/dist/cli-bundle/sdk-runtime.js +1 -1
  64. package/dist/cli-bundle/sdk-testing.js +1 -1
  65. package/dist/cli-bundle/sdk.js +6 -5
  66. package/dist/core/config/nested-settings.js +8 -2
  67. package/dist/core/config/positional-value.d.ts +1 -1
  68. package/dist/core/config/positional-value.js +5 -2
  69. package/dist/core/extensions/command-metadata-contract.d.ts +10 -0
  70. package/dist/core/extensions/command-metadata-contract.js +23 -0
  71. package/dist/core/extensions/command-visibility-tier.js +12 -2
  72. package/dist/core/extensions/extension-types.d.ts +6 -0
  73. package/dist/core/extensions/extension-types.js +2 -2
  74. package/dist/core/extensions/loader.js +4 -3
  75. package/dist/core/history/history.js +3 -3
  76. package/dist/core/io/body-file.js +7 -2
  77. package/dist/core/io/bulk-ids-input.d.ts +24 -0
  78. package/dist/core/io/bulk-ids-input.js +113 -0
  79. package/dist/core/item/item-format.js +66 -12
  80. package/dist/core/item/parse.d.ts +22 -2
  81. package/dist/core/item/parse.js +97 -4
  82. package/dist/core/reproducibility/context.d.ts +4 -0
  83. package/dist/core/reproducibility/context.js +14 -8
  84. package/dist/core/shared/author.d.ts +55 -1
  85. package/dist/core/shared/author.js +333 -16
  86. package/dist/core/shared/constants.js +3 -2
  87. package/dist/core/store/settings-validator.d.ts +1 -0
  88. package/dist/core/store/settings-validator.js +6 -3
  89. package/dist/core/store/settings.js +5 -2
  90. package/dist/mcp/server.d.ts +4 -3
  91. package/dist/mcp/server.js +44 -16
  92. package/dist/sdk/agent/identity-config.d.ts +63 -0
  93. package/dist/sdk/agent/identity-config.js +107 -0
  94. package/dist/sdk/agent/refusal-closure-census.d.ts +66 -0
  95. package/dist/sdk/agent/refusal-closure-census.js +144 -0
  96. package/dist/sdk/agent/refusal-corpus-contracts.d.ts +76 -0
  97. package/dist/sdk/agent/refusal-corpus-contracts.js +194 -0
  98. package/dist/sdk/agent-capability-contracts.d.ts +34 -1
  99. package/dist/sdk/agent-capability-contracts.js +104 -6
  100. package/dist/sdk/annotations.d.ts +2 -0
  101. package/dist/sdk/annotations.js +25 -7
  102. package/dist/sdk/cli-contracts/agent-output-contracts.js +6 -4
  103. package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -0
  104. package/dist/sdk/cli-contracts/enum-contracts.js +9 -2
  105. package/dist/sdk/cli-contracts/flag-contracts.js +9 -2
  106. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -4
  107. package/dist/sdk/cli-contracts/registration-helpers.js +5 -2
  108. package/dist/sdk/cli-contracts/tool-parameter-tables.js +58 -2
  109. package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
  110. package/dist/sdk/cli-contracts/tool-schema.js +14 -3
  111. package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +4 -1
  112. package/dist/sdk/cli-contracts/typed-action-inputs.js +2 -2
  113. package/dist/sdk/cli-contracts.d.ts +3 -3
  114. package/dist/sdk/cli-contracts.js +4 -4
  115. package/dist/sdk/comments.js +15 -7
  116. package/dist/sdk/config.d.ts +6 -1
  117. package/dist/sdk/config.js +119 -14
  118. package/dist/sdk/context-intent-contracts.js +4 -2
  119. package/dist/sdk/core-governance.d.ts +1 -1
  120. package/dist/sdk/core-governance.js +3 -3
  121. package/dist/sdk/extension/scaffold.js +11 -5
  122. package/dist/sdk/flag-invocation-contracts.d.ts +2 -0
  123. package/dist/sdk/flag-invocation-contracts.js +30 -3
  124. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +83 -2
  125. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +87 -2
  126. package/dist/sdk/governance/assurance-action.js +30 -10
  127. package/dist/sdk/governance/validate.d.ts +2 -2
  128. package/dist/sdk/governance/validate.js +39 -14
  129. package/dist/sdk/guide-topics.d.ts +0 -5
  130. package/dist/sdk/guide-topics.js +28 -2
  131. package/dist/sdk/history-compact.d.ts +2 -1
  132. package/dist/sdk/history-compact.js +24 -5
  133. package/dist/sdk/history-mcp.js +11 -10
  134. package/dist/sdk/index.d.ts +8 -2
  135. package/dist/sdk/index.js +9 -3
  136. package/dist/sdk/item-transaction.js +19 -12
  137. package/dist/sdk/lifecycle/append.js +4 -4
  138. package/dist/sdk/lifecycle/close-many.js +16 -7
  139. package/dist/sdk/lifecycle/create.js +33 -22
  140. package/dist/sdk/lifecycle/plan.js +24 -6
  141. package/dist/sdk/lifecycle/update-many.js +15 -8
  142. package/dist/sdk/lifecycle/update.d.ts +2 -0
  143. package/dist/sdk/lifecycle/update.js +37 -25
  144. package/dist/sdk/merge/three-way.js +105 -26
  145. package/dist/sdk/read-output-budget.d.ts +21 -0
  146. package/dist/sdk/read-output-budget.js +39 -2
  147. package/dist/sdk/read-output-contracts.d.ts +5 -3
  148. package/dist/sdk/read-output-contracts.js +20 -12
  149. package/dist/sdk/reproducibility/process.d.ts +19 -0
  150. package/dist/sdk/reproducibility/process.js +88 -0
  151. package/dist/sdk/runtime-extended-actions.js +5 -3
  152. package/dist/sdk/runtime-input.d.ts +4 -0
  153. package/dist/sdk/runtime-input.js +98 -23
  154. package/dist/sdk/runtime-primitives.d.ts +3 -2
  155. package/dist/sdk/runtime-primitives.js +5 -4
  156. package/dist/sdk/runtime.js +11 -23
  157. package/dist/sdk/scheduling-shortcuts.js +5 -3
  158. package/dist/sdk/structured-mutations.js +10 -3
  159. package/dist/sdk/test/batch.d.ts +6 -0
  160. package/dist/sdk/test/batch.js +15 -3
  161. package/dist/sdk/test/entry.d.ts +1 -1
  162. package/dist/sdk/test/entry.js +3 -2
  163. package/dist/sdk/test/execution.d.ts +28 -3
  164. package/dist/sdk/test/execution.js +193 -34
  165. package/dist/sdk/test/parsers.d.ts +6 -0
  166. package/dist/sdk/test/parsers.js +21 -2
  167. package/dist/sdk/test/trust.d.ts +33 -0
  168. package/dist/sdk/test/trust.js +207 -0
  169. package/dist/sdk/workspace-contracts.d.ts +3 -0
  170. package/dist/sdk/workspace-contracts.js +3 -2
  171. package/dist/types.d.ts +23 -0
  172. package/dist/types.js +2 -2
  173. package/docs/AGENT_PROVENANCE_ADR.md +41 -5
  174. package/docs/CONFIGURATION.md +4 -0
  175. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +19 -2
  176. package/docs/MERGE_SAFETY.md +15 -1
  177. package/docs/README.md +2 -0
  178. package/docs/READ_OUTPUT_CONTRACTS.md +11 -1
  179. package/docs/RELEASING.md +40 -21
  180. package/docs/REPRODUCIBLE_WORKSPACES.md +42 -8
  181. package/docs/SCRIPTING.md +62 -3
  182. package/docs/SDK.md +17 -0
  183. package/docs/SDK_AGENT_SESSION_CONTEXT.md +6 -4
  184. package/docs/SDK_EVIDENCE_TRACEABILITY.md +1 -1
  185. package/docs/TESTING.md +75 -8
  186. package/docs/agent-task-token-baseline.json +2 -2
  187. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +17 -0
  188. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
  189. package/docs/generated/FLAG_LEXICON_BUDGETS.md +2 -2
  190. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +355 -0
  191. package/marketplace.json +2 -2
  192. package/package.json +2 -2
  193. package/packages/pm-beads/package.json +1 -1
  194. package/packages/pm-calendar/package.json +1 -1
  195. package/packages/pm-command-kit/README.md +9 -11
  196. package/packages/pm-command-kit/extensions/command-kit/index.ts +3 -1
  197. package/packages/pm-command-kit/package.json +1 -1
  198. package/packages/pm-digital-twin/package.json +1 -1
  199. package/packages/pm-governance-audit/package.json +1 -1
  200. package/packages/pm-guide-shell/extensions/guide-shell/index.ts +10 -0
  201. package/packages/pm-guide-shell/package.json +1 -1
  202. package/packages/pm-kanban/package.json +1 -1
  203. package/packages/pm-lifecycle-hooks/package.json +1 -1
  204. package/packages/pm-linked-test-adapters/package.json +1 -1
  205. package/packages/pm-search-advanced/package.json +1 -1
  206. package/packages/pm-templates/package.json +1 -1
  207. package/packages/pm-todos/package.json +1 -1
  208. package/packages/pm-vcs/package.json +1 -1
  209. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  210. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  211. package/scripts/generate-agent-capability-surfaces.mjs +27 -1
  212. package/sdk/public-surface.json +642 -28
  213. package/dist/cli-bundle/chunks/chunk-EMWDM5FI.js +0 -13
  214. package/dist/cli-bundle/chunks/chunk-HYG6LRL4.js +0 -200
  215. package/dist/cli-bundle/chunks/chunk-QI2CT3IX.js +0 -2
  216. package/dist/cli-bundle/chunks/chunk-SMWXHMVB.js +0 -35
  217. package/dist/cli-bundle/chunks/chunk-VMMIL3SI.js +0 -2
  218. package/dist/cli-bundle/chunks/chunk-YBPJAOQQ.js +0 -3
  219. package/dist/cli-bundle/chunks/register-mutation-HTKEEGRD.js +0 -20
  220. package/dist/cli-bundle/chunks/register-operations-6EMRWJJY.js +0 -2
  221. package/dist/cli-bundle/focused-chunks/chunk-2AZT5WXZ.js +0 -2
  222. package/dist/cli-bundle/focused-chunks/chunk-3LKU6PTJ.js +0 -4
  223. package/dist/cli-bundle/focused-chunks/chunk-5SHSBMX2.js +0 -2
  224. package/dist/cli-bundle/focused-chunks/chunk-C4S4A4JJ.js +0 -5
  225. package/dist/cli-bundle/focused-chunks/chunk-L5LDSRO2.js +0 -155
  226. package/dist/cli-bundle/focused-chunks/chunk-MB37AYN6.js +0 -26
  227. package/dist/cli-bundle/focused-chunks/chunk-MCOR37QK.js +0 -2
  228. package/dist/cli-bundle/focused-chunks/chunk-PH2OXXVZ.js +0 -18
  229. package/dist/cli-bundle/focused-chunks/chunk-WZE4LIPW.js +0 -8
@@ -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]="7c1729f8-4a67-5746-a1bf-351f862ceb66")}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";
@@ -22,6 +23,7 @@ import { resolveWorkspaceRelationshipKindRegistry } from "../graph/assembly.js";
22
23
  import { acquireHierarchyMutationLock } from "./hierarchy-mutation-lock.js";
23
24
  import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, } from "../../types/index.js";
24
25
  import { parseDocs, parseFiles, parseLogSeed, parseTests, requireStringOption, } from "./create.js";
26
+ import { attachLinkedTestMutationProvenance } from "../test/trust.js";
25
27
  import { COMMON_UNSET_FIELD_DEFINITIONS_AFTER_CLOSE_REASON_BEFORE_AUTHOR, COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR, COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON, parseCommandUnsetTargets, resolveRuntimeUnsetFieldDefinition, } from "./shared-unset-fields.js";
26
28
  const UPDATE_UNSET_FIELD_DEFINITIONS = [
27
29
  ...COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_CLOSE_REASON,
@@ -107,7 +109,7 @@ function normalizeLegacyNoneUpdateOptions(options) {
107
109
  normalized[optionKey] = undefined;
108
110
  /* c8 ignore stop */
109
111
  }
110
- return applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS);
112
+ return transferMutationStdinTokenPolicy(options, applyLegacyNoneCollectionNormalizers(normalized, UPDATE_LEGACY_NONE_COLLECTION_NORMALIZERS));
111
113
  }
112
114
  function parseUpdateUnsetTargets(raw, runtimeFieldRegistry, extensionFieldNames = []) {
113
115
  return parseCommandUnsetTargets({
@@ -590,7 +592,7 @@ function docKey(value) {
590
592
  return `${value.path}::${value.scope}`;
591
593
  }
592
594
  function testKey(value) {
593
- return `${value.command}::${value.path ?? ""}::${value.scope}::${value.pm_context_mode ?? ""}`;
595
+ return `${value.command}::${value.path ?? ""}::${value.scope}::${value.pm_context_mode ?? ""}::${value.workspace_context_mode ?? ""}`;
594
596
  }
595
597
  function matchesDependencySelector(value, selector) {
596
598
  if (value.id.trim().toLowerCase() !== selector.id.trim().toLowerCase()) {
@@ -857,23 +859,31 @@ function applyUpdateScalarMutations(definitions, options, context) {
857
859
  }
858
860
  }
859
861
  async function resolveStdinUpdateOptions(options) {
860
- const stdinResolver = createStdinTokenResolver();
861
- return normalizeLegacyNoneUpdateOptions({
862
- ...options,
863
- body: await stdinResolver.resolveValue(options.body, "--body"),
864
- dep: await stdinResolver.resolveList(options.dep, "--dep"),
865
- depRemove: await stdinResolver.resolveList(options.depRemove, "--dep-remove"),
866
- comment: await stdinResolver.resolveList(options.comment, "--comment"),
867
- note: await stdinResolver.resolveList(options.note, "--note"),
868
- learning: await stdinResolver.resolveList(options.learning, "--learning"),
869
- file: await stdinResolver.resolveList(options.file, "--file"),
870
- test: await stdinResolver.resolveList(options.test, "--test"),
871
- doc: await stdinResolver.resolveList(options.doc, "--doc"),
872
- reminder: await stdinResolver.resolveList(options.reminder, "--reminder"),
873
- event: await stdinResolver.resolveList(options.event, "--event"),
874
- typeOption: await stdinResolver.resolveList(options.typeOption, "--type-option"),
875
- field: await stdinResolver.resolveList(options.field, "--field"),
876
- });
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);
877
887
  }
878
888
  function buildClearCollectionDefinitions(options) {
879
889
  return [
@@ -1219,12 +1229,13 @@ async function routeCloseStatusUpdate(context) {
1219
1229
  const routeWarnings = [];
1220
1230
  let preChangedFields = [];
1221
1231
  if (otherFieldKeys.length > 0) {
1222
- const preUpdate = await runUpdate(context.id, {
1232
+ const preUpdateOptions = transferMutationStdinTokenPolicy(context.options, {
1223
1233
  ...context.options,
1224
1234
  status: undefined,
1225
1235
  closeReason: undefined,
1226
1236
  message: undefined,
1227
- }, context.global);
1237
+ });
1238
+ const preUpdate = await runUpdate(context.id, preUpdateOptions, context.global);
1228
1239
  preChangedFields = preUpdate.changed_fields;
1229
1240
  routeWarnings.push(...preUpdate.warnings);
1230
1241
  }
@@ -1803,7 +1814,7 @@ function mutateUpdateDocument(document, context) {
1803
1814
  }
1804
1815
  /** Implements run update for the public runtime surface of this module. */
1805
1816
  async function runUpdateWithContext(id, options, global, execution = {}) {
1806
- options = await resolveStdinUpdateOptions(options);
1817
+ options = await resolveUpdateTransportOptions(options);
1807
1818
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
1808
1819
  await assertUpdateTrackerInitialized(pmRoot);
1809
1820
  const settings = await readSettings(pmRoot);
@@ -1871,6 +1882,7 @@ async function runUpdateWithContext(id, options, global, execution = {}) {
1871
1882
  const learningUpdates = parseLogSeed("--learning", options.learning, nowIso, author);
1872
1883
  const fileUpdates = parseFiles(options.file);
1873
1884
  const testUpdates = parseTests(options.test);
1885
+ testUpdates.values = await attachLinkedTestMutationProvenance(testUpdates.values, author, nowIso);
1874
1886
  const docUpdates = parseDocs(options.doc);
1875
1887
  const workflowTransitionWarnings = [];
1876
1888
  const parentReference = await resolveParentReferenceForUpdate({
@@ -2109,4 +2121,4 @@ export const _testOnlyUpdateCommand = {
2109
2121
  resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
2110
2122
  };
2111
2123
  //# sourceMappingURL=update.js.map
2112
- //# debugId=7c1729f8-4a67-5746-a1bf-351f862ceb66
2124
+ //# debugId=6865ca88-7ca1-52fd-86fb-2a3439abeafa
@@ -9,7 +9,7 @@
9
9
  * definition for multi-branch agent workflows.
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]="3c9d6924-ae7c-57c3-a346-1e2189c532fa")}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]="393f6460-bf8b-5479-8e3e-cac6f2680823")}catch(e){}}();
13
13
  import { historyEntriesToRaw, reanchorHistoryEntries, } from "../../core/history/replay.js";
14
14
  import { canonicalDocument, parseItemDocument, serializeItemDocument, } from "../../core/item/item-format.js";
15
15
  import { EXIT_CODE } from "../../core/shared/constants.js";
@@ -318,6 +318,58 @@ function unionCollection(base, ours, theirs) {
318
318
  }
319
319
  return merged;
320
320
  }
321
+ function linkedTestDefinitionIdentity(value) {
322
+ /* c8 ignore start -- canonical item parsing normalizes linked-test entries to object records */
323
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
324
+ return stableStringify(value);
325
+ }
326
+ /* c8 ignore stop */
327
+ const { provenance: _provenance, ...definition } = value;
328
+ return stableStringify(definition);
329
+ }
330
+ function markMergedLinkedTest(value) {
331
+ /* c8 ignore start -- canonical item parsing normalizes linked-test entries to object records */
332
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
333
+ return value;
334
+ }
335
+ /* c8 ignore stop */
336
+ const test = value;
337
+ if (!test.provenance) {
338
+ return {
339
+ ...test,
340
+ // Legacy entries contributed by another branch must not regain implicit
341
+ // local trust. This incomplete merge marker is preserved by normalization
342
+ // and refused until an operator acknowledges it in the receiving clone.
343
+ provenance: { source_kind: "merge_union" },
344
+ };
345
+ }
346
+ return {
347
+ ...test,
348
+ provenance: {
349
+ ...test.provenance,
350
+ source_kind: "merge_union",
351
+ },
352
+ };
353
+ }
354
+ function unionLinkedTests(base, ours, theirs) {
355
+ const toEntries = (value) => Array.isArray(value) ? value : [];
356
+ const baseIds = new Set(toEntries(base).map(linkedTestDefinitionIdentity));
357
+ const oursEntries = toEntries(ours);
358
+ const oursIds = new Set(oursEntries.map(linkedTestDefinitionIdentity));
359
+ const theirsEntries = toEntries(theirs);
360
+ const theirsIds = new Set(theirsEntries.map(linkedTestDefinitionIdentity));
361
+ const merged = oursEntries.filter((entry) => {
362
+ const identity = linkedTestDefinitionIdentity(entry);
363
+ return !baseIds.has(identity) || theirsIds.has(identity);
364
+ });
365
+ for (const entry of theirsEntries) {
366
+ const identity = linkedTestDefinitionIdentity(entry);
367
+ if (!oursIds.has(identity) && !baseIds.has(identity)) {
368
+ merged.push(markMergedLinkedTest(entry));
369
+ }
370
+ }
371
+ return merged;
372
+ }
321
373
  function latestTimestamp(ours, theirs) {
322
374
  return compareTimestampStrings(String(ours), String(theirs)) >= 0
323
375
  ? ours
@@ -362,6 +414,40 @@ function parseItemMergeSide(raw, label, options) {
362
414
  throw new PmCliError(`Item merge input (${label}) is not a readable item document: ${String(error)}`, EXIT_CODE.GENERIC_FAILURE);
363
415
  }
364
416
  }
417
+ /** Merge one collection field and report whether the field was handled. */
418
+ function mergeItemUnionField(params) {
419
+ if (!params.unionFieldSet.has(params.field))
420
+ return false;
421
+ const union = params.field === "tests"
422
+ ? unionLinkedTests(params.baseValue, params.oursValue, params.theirsValue)
423
+ : unionCollection(params.baseValue, params.oursValue, params.theirsValue);
424
+ params.accumulator.merged[params.field] = union;
425
+ if (!jsonEquals(union, params.oursValue)) {
426
+ params.accumulator.unionFields.push(params.field);
427
+ }
428
+ return true;
429
+ }
430
+ /** Merge one scalar field while preserving conflict evidence. */
431
+ function mergeItemScalarField(params) {
432
+ const outcome = mergeItemScalarThreeWay(params.baseValue, params.oursValue, params.theirsValue, params.preferred, params.conflictResolution);
433
+ if (outcome.value !== undefined) {
434
+ params.accumulator.merged[params.field] = outcome.value;
435
+ }
436
+ if (outcome.conflict) {
437
+ params.accumulator.conflictFields.push(params.field);
438
+ params.accumulator.conflictDecisions.push({
439
+ field: params.field,
440
+ base: params.baseValue,
441
+ ours: params.oursValue,
442
+ theirs: params.theirsValue,
443
+ retained: outcome.value,
444
+ discarded: outcome.from_theirs ? params.oursValue : params.theirsValue,
445
+ });
446
+ }
447
+ else if (outcome.from_theirs) {
448
+ params.accumulator.fieldsFromTheirs.push(params.field);
449
+ }
450
+ }
365
451
  function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferred, conflictResolution) {
366
452
  const unionFieldSet = new Set(ITEM_UNION_COLLECTION_FIELDS);
367
453
  const latestFieldSet = new Set(ITEM_LATEST_TIMESTAMP_FIELDS);
@@ -379,39 +465,32 @@ function mergeItemMetadataRecords(baseRecord, oursRecord, theirsRecord, preferre
379
465
  const baseValue = baseRecord[field];
380
466
  const oursValue = oursRecord[field];
381
467
  const theirsValue = theirsRecord[field];
382
- if (unionFieldSet.has(field)) {
383
- const union = unionCollection(baseValue, oursValue, theirsValue);
468
+ if (mergeItemUnionField({
469
+ field,
470
+ baseValue,
471
+ oursValue,
472
+ theirsValue,
473
+ unionFieldSet,
474
+ accumulator,
475
+ })) {
384
476
  // `fieldNames` is derived from both records' own keys, so a collection
385
477
  // reached here is declared by at least one side. Preserve even an empty
386
478
  // result (`tags` is required) so serialization never drops it.
387
- accumulator.merged[field] = union;
388
- if (!jsonEquals(union, oursValue)) {
389
- accumulator.unionFields.push(field);
390
- }
391
479
  continue;
392
480
  }
393
481
  if (latestFieldSet.has(field)) {
394
482
  accumulator.merged[field] = latestTimestamp(oursValue, theirsValue);
395
483
  continue;
396
484
  }
397
- const outcome = mergeItemScalarThreeWay(baseValue, oursValue, theirsValue, preferred, conflictResolution);
398
- if (outcome.value !== undefined) {
399
- accumulator.merged[field] = outcome.value;
400
- }
401
- if (outcome.conflict) {
402
- accumulator.conflictFields.push(field);
403
- accumulator.conflictDecisions.push({
404
- field,
405
- base: baseValue,
406
- ours: oursValue,
407
- theirs: theirsValue,
408
- retained: outcome.value,
409
- discarded: outcome.from_theirs ? oursValue : theirsValue,
410
- });
411
- }
412
- else if (outcome.from_theirs) {
413
- accumulator.fieldsFromTheirs.push(field);
414
- }
485
+ mergeItemScalarField({
486
+ field,
487
+ baseValue,
488
+ oursValue,
489
+ theirsValue,
490
+ preferred,
491
+ conflictResolution,
492
+ accumulator,
493
+ });
415
494
  }
416
495
  return accumulator;
417
496
  }
@@ -625,4 +704,4 @@ export function mergeJsonDocuments(baseRaw, oursRaw, theirsRaw, options = {}) {
625
704
  };
626
705
  }
627
706
  //# sourceMappingURL=three-way.js.map
628
- //# debugId=3c9d6924-ae7c-57c3-a346-1e2189c532fa
707
+ //# debugId=393f6460-bf8b-5479-8e3e-cac6f2680823
@@ -5,6 +5,27 @@
5
5
  * read-output contract without expanding its public declaration module.
6
6
  */
7
7
  import type { PmReadOutputReceipt } from "./read-output-contracts.js";
8
+ /** Input to the deterministic finite-retry recommendation contract. */
9
+ export interface PmReadOutputRecoveryBudgetInput {
10
+ /** Ceiling that already bound and truncated the response. */
11
+ effective_budget_tokens: number;
12
+ /** Measured cost of the useful result before row compaction. */
13
+ measured_result_tokens: number;
14
+ }
15
+ /** Executable next-budget recommendation shared by CLI, SDK, and MCP. */
16
+ export interface PmReadOutputRecoveryBudget {
17
+ /** Rounded finite retry ceiling, or the only truthful safe fallback. */
18
+ output_budget: number | "unbounded";
19
+ /** Ratio to the binding request, absent when finite arithmetic is unsafe. */
20
+ recovery_budget_multiplier: number | null;
21
+ /** Stable algorithm revision for consumers and fixtures. */
22
+ rule_version: "v1";
23
+ }
24
+ /**
25
+ * Recommend a retry that is strictly larger than both the binding request and
26
+ * the pre-compaction result, with a 25% envelope margin rounded to 100 tokens.
27
+ */
28
+ export declare function resolveReadOutputRecoveryBudget(input: PmReadOutputRecoveryBudgetInput): PmReadOutputRecoveryBudget;
8
29
  /** Estimate the conservative token cost of a JSON-shaped result. */
9
30
  export declare function estimateReadOutputTokens(result: unknown): number;
10
31
  /** Update a receipt to the fixed-point estimate of the result containing it. */
@@ -1,8 +1,45 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="737ac274-c165-5d1a-8b8e-cb5d57a81c46")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="02a0bd0c-6ab0-5193-807b-00394a4712b7")}catch(e){}}();
3
3
  import { countReadOutputRows, readOutputBudgetCollections, } from "./read-output-rows.js";
4
4
  const MAX_ESTIMATE_ITERATIONS = 8;
5
5
  const MAX_COMPACTION_ITERATIONS = 64;
6
+ const RECOVERY_MARGIN_NUMERATOR = 5;
7
+ const RECOVERY_MARGIN_DENOMINATOR = 4;
8
+ const RECOVERY_ROUNDING_TOKENS = 100;
9
+ /**
10
+ * Recommend a retry that is strictly larger than both the binding request and
11
+ * the pre-compaction result, with a 25% envelope margin rounded to 100 tokens.
12
+ */
13
+ export function resolveReadOutputRecoveryBudget(input) {
14
+ const binding = Math.trunc(input.effective_budget_tokens);
15
+ const measured = Math.trunc(input.measured_result_tokens);
16
+ if (!Number.isSafeInteger(binding) ||
17
+ binding <= 0 ||
18
+ !Number.isSafeInteger(measured) ||
19
+ measured <= 0) {
20
+ return {
21
+ output_budget: "unbounded",
22
+ recovery_budget_multiplier: null,
23
+ rule_version: "v1",
24
+ };
25
+ }
26
+ const baseline = Math.max(binding + 1, measured);
27
+ const withMargin = Math.ceil((baseline * RECOVERY_MARGIN_NUMERATOR) / RECOVERY_MARGIN_DENOMINATOR);
28
+ const rounded = Math.ceil(withMargin / RECOVERY_ROUNDING_TOKENS) *
29
+ RECOVERY_ROUNDING_TOKENS;
30
+ if (!Number.isSafeInteger(rounded)) {
31
+ return {
32
+ output_budget: "unbounded",
33
+ recovery_budget_multiplier: null,
34
+ rule_version: "v1",
35
+ };
36
+ }
37
+ return {
38
+ output_budget: rounded,
39
+ recovery_budget_multiplier: rounded / binding,
40
+ rule_version: "v1",
41
+ };
42
+ }
6
43
  /** Estimate the conservative token cost of a JSON-shaped result. */
7
44
  export function estimateReadOutputTokens(result) {
8
45
  return Math.ceil(Buffer.byteLength(JSON.stringify(result), "utf8") / 4);
@@ -96,4 +133,4 @@ export function compactReadOutputToBudget(result, receipt, budget, minimumRowsBy
96
133
  return compacted;
97
134
  }
98
135
  //# sourceMappingURL=read-output-budget.js.map
99
- //# debugId=737ac274-c165-5d1a-8b8e-cb5d57a81c46
136
+ //# debugId=02a0bd0c-6ab0-5193-807b-00394a4712b7
@@ -1,3 +1,5 @@
1
+ export { resolveReadOutputRecoveryBudget } from "./read-output-budget.js";
2
+ export type { PmReadOutputRecoveryBudget, PmReadOutputRecoveryBudgetInput, } from "./read-output-budget.js";
1
3
  export { decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, } from "./read-output/continuation.js";
2
4
  import { type PmReadOutputSessionReceipt, type PmReadOutputSessionState } from "./read-output-session.js";
3
5
  /** Stable output dimensions shared by every read surface. */
@@ -142,7 +144,7 @@ export interface PmReadOutputTruncationDisclosure {
142
144
  /** Whether at least one declared row collection can be resumed within the budget. */
143
145
  continuation_available: boolean;
144
146
  /** Maximum next-page useful-result budget relative to the current budget. */
145
- recovery_budget_multiplier: 1;
147
+ recovery_budget_multiplier: number | null;
146
148
  /** Bounded continuation instructions for every compacted declared row path. */
147
149
  continuations: PmReadOutputContinuation[];
148
150
  /** Executable recovery instruction for retrieving the complete result. */
@@ -160,10 +162,10 @@ export interface PmReadOutputTruncationDisclosure {
160
162
  } | {
161
163
  cli: string;
162
164
  sdk: {
163
- outputBudget: number;
165
+ outputBudget: number | "unbounded";
164
166
  };
165
167
  mcp: {
166
- outputBudget: number;
168
+ outputBudget: number | "unbounded";
167
169
  };
168
170
  };
169
171
  }
@@ -5,10 +5,11 @@
5
5
  * surface without coupling package authors to command-specific option names.
6
6
  */
7
7
 
8
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a1272c1f-c03e-580c-8c44-6b3ddeedd240")}catch(e){}}();
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="76c9c2d0-951d-579e-916e-e8d54d4a8be9")}catch(e){}}();
9
9
  import { EXIT_CODE } from "../core/shared/constants.js";
10
10
  import { PmCliError } from "../core/shared/errors.js";
11
- import { compactReadOutputToBudget, estimateReadOutputTokens, updateReadOutputReceiptEstimate, } from "./read-output-budget.js";
11
+ import { compactReadOutputToBudget, estimateReadOutputTokens, resolveReadOutputRecoveryBudget, updateReadOutputReceiptEstimate, } from "./read-output-budget.js";
12
+ export { resolveReadOutputRecoveryBudget } from "./read-output-budget.js";
12
13
  import { resolvePmCommandOutputBudget } from "./cli-contracts/agent-output-contracts.js";
13
14
  import { boundReadOutputRows, countReadOutputRows, mapReadOutputRows, readOutputBudgetCollections, readOutputContinuationRowCollections, readOutputRowPaths, } from "./read-output-rows.js";
14
15
  import { applyReadOutputContinuation, decodeReadOutputContinuationCursor, encodeReadOutputContinuationCursor, prioritizeAssuranceAssertions, readOutputCollectionFingerprint, } from "./read-output/continuation.js";
@@ -979,7 +980,7 @@ function canReturnReadOutputUnchanged(resolved, session, result) {
979
980
  * without this an explicitly requested unbounded read is silently downgraded and
980
981
  * the only working recovery is never named.
981
982
  */
982
- function attachReadOutputTruncationDisclosure(projected, resolved, receipt, bindingBudget, continuationCursorRebased, collectionsBeforeBudget) {
983
+ function attachReadOutputTruncationDisclosure(projected, resolved, receipt, bindingBudget, continuationCursorRebased, measuredResultTokens, collectionsBeforeBudget) {
983
984
  if (!receipt.rows_compacted)
984
985
  return;
985
986
  const overridden = resolved.amount?.value === "unbounded" ? ["amount"] : [];
@@ -1013,6 +1014,10 @@ function attachReadOutputTruncationDisclosure(projected, resolved, receipt, bind
1013
1014
  ];
1014
1015
  });
1015
1016
  const primary = continuations[0];
1017
+ const recoveryBudget = resolveReadOutputRecoveryBudget({
1018
+ effective_budget_tokens: bindingBudget.tokens,
1019
+ measured_result_tokens: measuredResultTokens,
1020
+ });
1016
1021
  if (primary && typeof projected.next_cursor !== "string") {
1017
1022
  projected.next_cursor = primary.cursor;
1018
1023
  }
@@ -1029,11 +1034,13 @@ function attachReadOutputTruncationDisclosure(projected, resolved, receipt, bind
1029
1034
  compacted_row_paths: receipt.compacted_row_paths,
1030
1035
  continuation_cursor_rebased: continuationCursorRebased,
1031
1036
  continuation_available: continuations.length > 0,
1032
- recovery_budget_multiplier: 1,
1037
+ recovery_budget_multiplier: primary
1038
+ ? 1
1039
+ : recoveryBudget.recovery_budget_multiplier,
1033
1040
  continuations,
1034
1041
  restore_with: primary
1035
1042
  ? "Use recovery binding."
1036
- : "Increase --output-budget because no declared row collection can be continued.",
1043
+ : `Retry with --output-budget ${recoveryBudget.output_budget} because no declared row collection can be continued.`,
1037
1044
  recovery: primary
1038
1045
  ? {
1039
1046
  cursor: primary.cursor,
@@ -1042,9 +1049,9 @@ function attachReadOutputTruncationDisclosure(projected, resolved, receipt, bind
1042
1049
  mcp: "outputCursor",
1043
1050
  }
1044
1051
  : {
1045
- cli: "--output-budget 1200",
1046
- sdk: { outputBudget: 1200 },
1047
- mcp: { outputBudget: 1200 },
1052
+ cli: `--output-budget ${recoveryBudget.output_budget}`,
1053
+ sdk: { outputBudget: recoveryBudget.output_budget },
1054
+ mcp: { outputBudget: recoveryBudget.output_budget },
1048
1055
  },
1049
1056
  };
1050
1057
  }
@@ -1115,7 +1122,7 @@ function captureReadOutputContinuationState(projected, cursor, options) {
1115
1122
  : options.after,
1116
1123
  };
1117
1124
  }
1118
- function compactReadOutputProjection(projected, resolved, receipt, bindingBudget, session, continuationState) {
1125
+ function compactReadOutputProjection(projected, resolved, receipt, bindingBudget, session, continuationState, measuredResultTokens) {
1119
1126
  const assuranceMinimumRows = resolved.command === "assurance" && Array.isArray(projected.assertions)
1120
1127
  ? projected.assertions.filter((row) => isRecord(row) && row.verdict !== "pass").length
1121
1128
  : 0;
@@ -1123,7 +1130,7 @@ function compactReadOutputProjection(projected, resolved, receipt, bindingBudget
1123
1130
  ? new Map([["assertions", assuranceMinimumRows]])
1124
1131
  : new Map());
1125
1132
  const continuationCursorRebased = rebaseBudgetCompactedCursor(compacted, continuationState.originalItemCount, continuationState.cursorSource, continuationState.cursorContinuesExistingPage);
1126
- attachReadOutputTruncationDisclosure(compacted, resolved, receipt, bindingBudget, continuationCursorRebased, continuationState.collectionsBeforeBudget);
1133
+ attachReadOutputTruncationDisclosure(compacted, resolved, receipt, bindingBudget, continuationCursorRebased, measuredResultTokens, continuationState.collectionsBeforeBudget);
1127
1134
  if (session !== undefined) {
1128
1135
  compacted = attachReadOutputSessionContracts(compacted, session, receipt);
1129
1136
  }
@@ -1176,7 +1183,8 @@ export function applyReadOutputDimensions(command, options, result) {
1176
1183
  updateReadOutputReceiptEstimate(projected, receipt);
1177
1184
  if (bindingBudget !== undefined &&
1178
1185
  receipt.estimated_tokens > bindingBudget.tokens) {
1179
- projected = compactReadOutputProjection(projected, resolved, receipt, bindingBudget, session, continuationState);
1186
+ const measuredResultTokens = receipt.estimated_tokens;
1187
+ projected = compactReadOutputProjection(projected, resolved, receipt, bindingBudget, session, continuationState, measuredResultTokens);
1180
1188
  }
1181
1189
  if (bindingBudget !== undefined &&
1182
1190
  receipt.estimated_tokens > bindingBudget.tokens) {
@@ -1199,4 +1207,4 @@ export function resolveReadOutputEncoding(command, options) {
1199
1207
  : undefined;
1200
1208
  }
1201
1209
  //# sourceMappingURL=read-output-contracts.js.map
1202
- //# debugId=a1272c1f-c03e-580c-8c44-6b3ddeedd240
1210
+ //# debugId=76c9c2d0-951d-579e-916e-e8d54d4a8be9
@@ -0,0 +1,19 @@
1
+ import { type ReproducibleExecutionSettings, type ReproducibleExecutionRunner } from "../../core/reproducibility/context.js";
2
+ /** Stable environment-variable names understood by every pm process transport. */
3
+ export declare const PM_REPRODUCIBLE_PROCESS_ENV: Readonly<{
4
+ readonly clock: "PM_CLOCK";
5
+ readonly tickMs: "PM_CLOCK_TICK_MS";
6
+ readonly seed: "PM_SEED";
7
+ }>;
8
+ /** Environment-shaped input accepted by the reproducible process adapter. */
9
+ export type ReproducibleProcessEnvironment = Readonly<Record<string, string | undefined>>;
10
+ /** Public deterministic settings installed by recipes and process transports. */
11
+ export type { ReproducibleExecutionSettings };
12
+ /** Runner used by long-lived transports whose serial operations share one sequence. */
13
+ export type ReproducibleProcessRunner = ReproducibleExecutionRunner;
14
+ /** Resolve validated deterministic settings, or undefined when no opt-in is present. */
15
+ export declare function resolveReproducibleProcessEnvironment(environment: ReproducibleProcessEnvironment): ReproducibleExecutionSettings | undefined;
16
+ /** Create one process-lifetime runner for long-lived serial transports such as MCP. */
17
+ export declare function createReproducibleProcessRunner(environment: ReproducibleProcessEnvironment): ReproducibleProcessRunner;
18
+ /** Run one process transport operation under its declared deterministic context. */
19
+ export declare function runWithReproducibleProcessEnvironment<T>(environment: ReproducibleProcessEnvironment, operation: () => Promise<T>): Promise<T>;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @module sdk/reproducible-process
3
+ *
4
+ * Owns the process-environment contract that lets CLI and MCP transports enter
5
+ * the same deterministic execution context as SDK workspace recipes.
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]="ae031bac-f5a1-5762-9c58-0410b8f1f86d")}catch(e){}}();
9
+ import { EXIT_CODE } from "../../core/shared/constants.js";
10
+ import { PmCliError } from "../../core/shared/errors.js";
11
+ import { isRfc3339DateTime } from "../../core/shared/time.js";
12
+ import { createReproducibleExecutionRunner, validateReproducibleExecutionSettings, } from "../../core/reproducibility/context.js";
13
+ /** Stable environment-variable names understood by every pm process transport. */
14
+ export const PM_REPRODUCIBLE_PROCESS_ENV = Object.freeze({
15
+ clock: "PM_CLOCK",
16
+ tickMs: "PM_CLOCK_TICK_MS",
17
+ seed: "PM_SEED",
18
+ });
19
+ function invalidProcessEnvironment(message, reason, field, providedFields) {
20
+ return new PmCliError(message, EXIT_CODE.USAGE, {
21
+ code: "invalid_reproducible_process_environment",
22
+ reason,
23
+ field,
24
+ required: `${PM_REPRODUCIBLE_PROCESS_ENV.clock} and ${PM_REPRODUCIBLE_PROCESS_ENV.seed}; ${PM_REPRODUCIBLE_PROCESS_ENV.tickMs} is optional`,
25
+ nextSteps: [
26
+ `Set ${PM_REPRODUCIBLE_PROCESS_ENV.clock} to an ISO-8601 instant with Z or a numeric UTC offset and ${PM_REPRODUCIBLE_PROCESS_ENV.seed} to a non-empty reproducibility seed.`,
27
+ `Optionally set ${PM_REPRODUCIBLE_PROCESS_ENV.tickMs} to a non-negative integer; it defaults to 1.`,
28
+ `Unset all three variables to retain normal wall-clock and cryptographic-random behavior.`,
29
+ ],
30
+ recovery: {
31
+ recovery_mode: "compact",
32
+ provided_fields: providedFields,
33
+ missing_required_fields: reason === "incomplete"
34
+ ? [
35
+ PM_REPRODUCIBLE_PROCESS_ENV.clock,
36
+ PM_REPRODUCIBLE_PROCESS_ENV.seed,
37
+ ].filter((name) => !providedFields.includes(name))
38
+ : undefined,
39
+ },
40
+ });
41
+ }
42
+ /** Resolve validated deterministic settings, or undefined when no opt-in is present. */
43
+ export function resolveReproducibleProcessEnvironment(environment) {
44
+ const clock = environment[PM_REPRODUCIBLE_PROCESS_ENV.clock];
45
+ const tick = environment[PM_REPRODUCIBLE_PROCESS_ENV.tickMs];
46
+ const seed = environment[PM_REPRODUCIBLE_PROCESS_ENV.seed];
47
+ const providedFields = [
48
+ [PM_REPRODUCIBLE_PROCESS_ENV.clock, clock],
49
+ [PM_REPRODUCIBLE_PROCESS_ENV.tickMs, tick],
50
+ [PM_REPRODUCIBLE_PROCESS_ENV.seed, seed],
51
+ ]
52
+ .filter((entry) => entry[1] !== undefined)
53
+ .map(([name]) => name);
54
+ if (providedFields.length === 0) {
55
+ return undefined;
56
+ }
57
+ if (clock === undefined || seed === undefined) {
58
+ throw invalidProcessEnvironment("Reproducible process execution requires PM_CLOCK and PM_SEED together.", "incomplete", clock === undefined
59
+ ? PM_REPRODUCIBLE_PROCESS_ENV.clock
60
+ : PM_REPRODUCIBLE_PROCESS_ENV.seed, providedFields);
61
+ }
62
+ if (seed.trim().length === 0) {
63
+ throw invalidProcessEnvironment(`${PM_REPRODUCIBLE_PROCESS_ENV.seed} must not be empty.`, "invalid_value", PM_REPRODUCIBLE_PROCESS_ENV.seed, providedFields);
64
+ }
65
+ if (!isRfc3339DateTime(clock)) {
66
+ throw invalidProcessEnvironment(`${PM_REPRODUCIBLE_PROCESS_ENV.clock} must be a valid ISO-8601 instant with Z or a numeric UTC offset.`, "invalid_value", PM_REPRODUCIBLE_PROCESS_ENV.clock, providedFields);
67
+ }
68
+ const tickMs = tick === undefined ? 1 : Number(tick);
69
+ if (tick?.trim().length === 0 ||
70
+ !Number.isSafeInteger(tickMs) ||
71
+ tickMs < 0) {
72
+ throw invalidProcessEnvironment(`${PM_REPRODUCIBLE_PROCESS_ENV.tickMs} must be a non-negative integer.`, "invalid_value", PM_REPRODUCIBLE_PROCESS_ENV.tickMs, providedFields);
73
+ }
74
+ return validateReproducibleExecutionSettings({ clock, seed, tickMs });
75
+ }
76
+ /** Create one process-lifetime runner for long-lived serial transports such as MCP. */
77
+ export function createReproducibleProcessRunner(environment) {
78
+ const settings = resolveReproducibleProcessEnvironment(environment);
79
+ return settings === undefined
80
+ ? (operation) => operation()
81
+ : createReproducibleExecutionRunner(settings);
82
+ }
83
+ /** Run one process transport operation under its declared deterministic context. */
84
+ export async function runWithReproducibleProcessEnvironment(environment, operation) {
85
+ return createReproducibleProcessRunner(environment)(operation);
86
+ }
87
+ //# sourceMappingURL=process.js.map
88
+ //# debugId=ae031bac-f5a1-5762-9c58-0410b8f1f86d
@@ -1,7 +1,8 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="0492d773-2af2-5072-8164-9f8aab536191")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="8a3a82a1-9e3d-555f-9111-3c3e19887f75")}catch(e){}}();
3
3
  import { EXIT_CODE } from "../core/shared/constants.js";
4
4
  import { PmCliError } from "../core/shared/errors.js";
5
+ import { transferMutationStdinTokenPolicy, } from "./runtime-primitives.js";
5
6
  import { createUnknownSubcommandError } from "./agent/subcommand-recovery.js";
6
7
  import { resolvePmRoot } from "../core/store/paths.js";
7
8
  import { runEval } from "./eval.js";
@@ -14,7 +15,8 @@ import { parseRuntimeInteger, readRuntimeString, readRuntimeStringArray, } from
14
15
  import { runEvent, runMeet, runRemind, } from "./scheduling-shortcuts.js";
15
16
  import { createWorkspaceSnapshot, deleteWorkspaceSnapshot, inspectWorkspaceSnapshot, listWorkspaceSnapshots, planWorkspaceSnapshotRestore, restoreWorkspaceSnapshotWithRecovery, } from "./workspace-snapshot.js";
16
17
  function mergedInput(context) {
17
- return { ...context.args, ...context.options };
18
+ const input = { ...context.args, ...context.options };
19
+ return transferMutationStdinTokenPolicy(context.options, input);
18
20
  }
19
21
  function requiredString(input, key) {
20
22
  const value = readRuntimeString(input, key);
@@ -169,4 +171,4 @@ export function runRuntimeSchedulingAction(context) {
169
171
  return runRemind(title, input, context.global);
170
172
  }
171
173
  //# sourceMappingURL=runtime-extended-actions.js.map
172
- //# debugId=0492d773-2af2-5072-8164-9f8aab536191
174
+ //# debugId=8a3a82a1-9e3d-555f-9111-3c3e19887f75