@unbrained/pm-cli 2026.8.9 → 2026.8.10

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 +40 -0
  3. package/dist/cli/commander-usage.js +17 -12
  4. package/dist/cli/help-json-payload.js +51 -16
  5. package/dist/cli/main.js +7 -6
  6. package/dist/cli-bundle/bundle-manifest.json +165 -165
  7. package/dist/cli-bundle/chunks/chunk-2QYH4QMI.js +30 -0
  8. package/dist/cli-bundle/chunks/{chunk-YC3UF2IO.js → chunk-EBO7OUUE.js} +57 -57
  9. package/dist/cli-bundle/chunks/{chunk-GMX5YOI3.js → chunk-ETML5C6H.js} +48 -48
  10. package/dist/cli-bundle/chunks/chunk-JUDU4RO4.js +194 -0
  11. package/dist/cli-bundle/chunks/{chunk-PYO5GZU6.js → chunk-JZSNADRR.js} +5 -5
  12. package/dist/cli-bundle/chunks/{chunk-EF43KODO.js → chunk-MENWVGJW.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-5JO6R4BS.js → chunk-S4EITGLA.js} +2 -2
  14. package/dist/cli-bundle/chunks/{chunk-2DTCZXSD.js → chunk-TIGKWVLA.js} +9 -9
  15. package/dist/cli-bundle/chunks/{chunk-RJC7TPF4.js → chunk-TRWXF476.js} +2 -2
  16. package/dist/cli-bundle/chunks/chunk-TSLDTJLQ.js +2 -0
  17. package/dist/cli-bundle/chunks/{register-list-query-BUE7PTCU.js → register-list-query-OJ6ZXKV4.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-mutation-FC3XLVIK.js → register-mutation-DKI7QC7O.js} +2 -2
  19. package/dist/cli-bundle/chunks/register-operations-P5OGMT6I.js +2 -0
  20. package/dist/cli-bundle/chunks/{register-setup-UQDTNTLJ.js → register-setup-S3KT2LTH.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-6DO4YQWZ.js → chunk-2COZ67XT.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-2EXI2DKR.js +4 -0
  23. package/dist/cli-bundle/focused-chunks/{chunk-KNEHLPBF.js → chunk-34SX654S.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/chunk-36FTZ2NT.js +2 -0
  25. package/dist/cli-bundle/focused-chunks/chunk-3CQECMKR.js +16 -0
  26. package/dist/cli-bundle/focused-chunks/chunk-75774JWP.js +6 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-MRWVJ3ZG.js → chunk-7UN6BHHO.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-VRXJSGIT.js → chunk-CHIBMEZR.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/chunk-DZGAHZZV.js +3 -0
  30. package/dist/cli-bundle/focused-chunks/chunk-FF4MNAYB.js +153 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-ZG54B4XG.js → chunk-GHTN2ILR.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/chunk-I4YM2I7S.js +2 -0
  33. package/dist/cli-bundle/focused-chunks/chunk-IMDTEN7K.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/chunk-IW43E4XL.js +2 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-3WVHTUAW.js → chunk-JMVA4HKR.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-C3GCHDSQ.js → chunk-KR5RVXLQ.js} +31 -31
  37. package/dist/cli-bundle/focused-chunks/chunk-KSNJG4KI.js +16 -0
  38. package/dist/cli-bundle/focused-chunks/{chunk-73FIJONU.js → chunk-M6RPIXKC.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-MXYSIQ56.js +18 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-RIIN5V4N.js +2 -0
  41. package/dist/cli-bundle/focused-chunks/{chunk-U46GQJNY.js → chunk-RKWSCYYN.js} +2 -2
  42. package/dist/cli-bundle/main.js +13 -13
  43. package/dist/cli-bundle/sdk-authoring.js +1 -1
  44. package/dist/cli-bundle/sdk-contracts.js +1 -1
  45. package/dist/cli-bundle/sdk-core.js +38 -38
  46. package/dist/cli-bundle/sdk-governance.js +1 -1
  47. package/dist/cli-bundle/sdk-graph.js +1 -1
  48. package/dist/cli-bundle/sdk-merge.js +1 -1
  49. package/dist/cli-bundle/sdk-query.js +1 -1
  50. package/dist/cli-bundle/sdk-runtime.js +1 -1
  51. package/dist/cli-bundle/sdk-testing.js +1 -1
  52. package/dist/cli-bundle/sdk.js +2 -2
  53. package/dist/core/diagnostics/remediation.js +9 -9
  54. package/dist/core/fs/fs-utils.d.ts +10 -0
  55. package/dist/core/fs/fs-utils.js +16 -4
  56. package/dist/core/item/item-format.js +3 -32
  57. package/dist/core/schema/fields-file.d.ts +1 -2
  58. package/dist/core/schema/fields-file.js +4 -11
  59. package/dist/core/schema/runtime-schema.js +3 -10
  60. package/dist/core/schema/status-defs-file.d.ts +1 -2
  61. package/dist/core/schema/status-defs-file.js +4 -32
  62. package/dist/core/schema/status-token.d.ts +2 -0
  63. package/dist/core/schema/status-token.js +32 -0
  64. package/dist/core/schema/type-workflows.d.ts +1 -2
  65. package/dist/core/schema/type-workflows.js +4 -11
  66. package/dist/core/shared/author.d.ts +1 -1
  67. package/dist/core/shared/author.js +21 -8
  68. package/dist/core/shared/errors.d.ts +4 -0
  69. package/dist/core/shared/errors.js +2 -2
  70. package/dist/core/shared/text-normalization.d.ts +1 -1
  71. package/dist/core/shared/text-normalization.js +2 -2
  72. package/dist/sdk/agent/command-recovery.d.ts +4 -0
  73. package/dist/sdk/agent/command-recovery.js +52 -0
  74. package/dist/sdk/agent/command-suggestions.d.ts +4 -0
  75. package/dist/sdk/agent/command-suggestions.js +67 -0
  76. package/dist/sdk/agent/create-option-policy.d.ts +12 -0
  77. package/dist/sdk/agent/create-option-policy.js +32 -0
  78. package/dist/sdk/agent/item-addressing.d.ts +19 -0
  79. package/dist/sdk/agent/item-addressing.js +208 -0
  80. package/dist/sdk/cli-bootstrap.d.ts +1 -1
  81. package/dist/sdk/cli-bootstrap.js +20 -5
  82. package/dist/sdk/cli-contracts/commander-mutation-options.js +16 -4
  83. package/dist/sdk/cli-contracts/flag-contracts.js +62 -21
  84. package/dist/sdk/cli-contracts/registration-helpers.js +10 -2
  85. package/dist/sdk/cli-contracts/runtime-contracts.js +5 -3
  86. package/dist/sdk/cli-contracts/tool-option-contracts.d.ts +6 -0
  87. package/dist/sdk/cli-contracts/tool-option-contracts.js +4 -2
  88. package/dist/sdk/cli-contracts/tool-parameter-tables.js +19 -4
  89. package/dist/sdk/cli-contracts/tool-schema.js +17 -4
  90. package/dist/sdk/context-intent-runtime.js +8 -5
  91. package/dist/sdk/context-signal-store.d.ts +34 -0
  92. package/dist/sdk/context-signal-store.js +24 -2
  93. package/dist/sdk/dependency-flag-validation.d.ts +15 -1
  94. package/dist/sdk/dependency-flag-validation.js +54 -2
  95. package/dist/sdk/generated-error-code-catalog.js +74 -2
  96. package/dist/sdk/governance/health.js +14 -7
  97. package/dist/sdk/governance/provenance-health.d.ts +13 -0
  98. package/dist/sdk/governance/provenance-health.js +63 -17
  99. package/dist/sdk/governance/validate-item-reader.d.ts +13 -0
  100. package/dist/sdk/governance/validate-item-reader.js +18 -0
  101. package/dist/sdk/governance/validate.d.ts +2 -2
  102. package/dist/sdk/governance/validate.js +15 -6
  103. package/dist/sdk/index.d.ts +4 -0
  104. package/dist/sdk/index.js +6 -2
  105. package/dist/sdk/lifecycle/close.js +17 -14
  106. package/dist/sdk/lifecycle/create.d.ts +2 -0
  107. package/dist/sdk/lifecycle/create.js +62 -9
  108. package/dist/sdk/lifecycle/update-many.js +39 -27
  109. package/dist/sdk/lifecycle/update.d.ts +6 -1
  110. package/dist/sdk/lifecycle/update.js +47 -10
  111. package/dist/sdk/merge/index.d.ts +1 -1
  112. package/dist/sdk/merge/index.js +3 -3
  113. package/dist/sdk/merge/install.d.ts +4 -0
  114. package/dist/sdk/merge/install.js +28 -16
  115. package/dist/sdk/merge/receipts.d.ts +3 -0
  116. package/dist/sdk/merge/receipts.js +81 -17
  117. package/dist/sdk/output-projection.js +24 -4
  118. package/dist/sdk/query/context.d.ts +2 -0
  119. package/dist/sdk/query/context.js +7 -4
  120. package/dist/sdk/query/light-metadata.d.ts +3 -0
  121. package/dist/sdk/query/light-metadata.js +19 -0
  122. package/dist/sdk/runtime.d.ts +4 -1
  123. package/dist/sdk/runtime.js +8 -3
  124. package/dist/sdk/schema-migration.js +7 -9
  125. package/dist/sdk/similarity-scoring.d.ts +1 -2
  126. package/dist/sdk/similarity-scoring.js +4 -16
  127. package/dist/sdk/workspace-snapshot.d.ts +4 -0
  128. package/dist/sdk/workspace-snapshot.js +24 -11
  129. package/docs/AGENT_GUIDE.md +3 -1
  130. package/docs/COMMANDS.md +8 -5
  131. package/docs/MERGE_SAFETY.md +7 -5
  132. package/docs/README.md +2 -5
  133. package/docs/READ_OUTPUT_CONTRACTS.md +2 -2
  134. package/docs/SDK.md +33 -8
  135. package/docs/SDK_AGENT_SESSION_CONTEXT.md +3 -2
  136. package/docs/SDK_CONTEXT.md +97 -0
  137. package/docs/SDK_CONTEXT_INTEGRITY.md +18 -3
  138. package/docs/agent-task-token-baseline.json +2 -2
  139. package/marketplace.json +2 -2
  140. package/package.json +5 -4
  141. package/packages/pm-beads/package.json +1 -1
  142. package/packages/pm-calendar/package.json +1 -1
  143. package/packages/pm-command-kit/package.json +1 -1
  144. package/packages/pm-digital-twin/package.json +1 -1
  145. package/packages/pm-governance-audit/package.json +1 -1
  146. package/packages/pm-guide-shell/package.json +1 -1
  147. package/packages/pm-kanban/package.json +1 -1
  148. package/packages/pm-lifecycle-hooks/package.json +1 -1
  149. package/packages/pm-linked-test-adapters/package.json +1 -1
  150. package/packages/pm-search-advanced/package.json +1 -1
  151. package/packages/pm-templates/package.json +1 -1
  152. package/packages/pm-todos/package.json +1 -1
  153. package/packages/pm-vcs/package.json +1 -1
  154. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  155. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  156. package/sdk/public-surface.json +194 -26
  157. package/dist/cli-bundle/chunks/chunk-5KN4DZYV.js +0 -194
  158. package/dist/cli-bundle/chunks/chunk-HUV2Z7IS.js +0 -28
  159. package/dist/cli-bundle/chunks/chunk-MHBVCUF2.js +0 -2
  160. package/dist/cli-bundle/chunks/register-operations-YH2WAOXU.js +0 -2
  161. package/dist/cli-bundle/focused-chunks/chunk-2VVP5RAA.js +0 -153
  162. package/dist/cli-bundle/focused-chunks/chunk-3GSFUDAI.js +0 -2
  163. package/dist/cli-bundle/focused-chunks/chunk-4H6MVCK3.js +0 -16
  164. package/dist/cli-bundle/focused-chunks/chunk-54TZJ4BM.js +0 -2
  165. package/dist/cli-bundle/focused-chunks/chunk-5NK5TJ5D.js +0 -2
  166. package/dist/cli-bundle/focused-chunks/chunk-JGRSQZJT.js +0 -18
  167. package/dist/cli-bundle/focused-chunks/chunk-NL57J7BZ.js +0 -4
  168. package/dist/cli-bundle/focused-chunks/chunk-P6BBIQRG.js +0 -6
  169. package/dist/cli-bundle/focused-chunks/chunk-PZAGVQNN.js +0 -3
  170. package/dist/cli-bundle/focused-chunks/chunk-QDAO3XEK.js +0 -14
  171. package/dist/cli-bundle/focused-chunks/chunk-T4IGQCSY.js +0 -2
  172. package/dist/cli-bundle/focused-chunks/chunk-XC2ZW3CJ.js +0 -2
@@ -4,13 +4,14 @@
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]="67f8958d-60d5-5657-93ce-9803859acd9e")}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]="0f91de58-2cbc-52ba-97ea-42482d0c6ce1")}catch(e){}}();
8
8
  import { pathExists, 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, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
9
+ import { assertDependencyTargetsResolvable } from "../dependency-flag-validation.js";
9
10
  import { parseStatusFilterCsv } from "../../core/item/status-filter.js";
10
11
  import { hasListFilters } from "../query/list-filter-shared.js";
11
12
  import { runList, } from "../query/list.js";
12
13
  import { runRestore } from "./restore.js";
13
- import { runUpdate } from "./update.js";
14
+ import { assertUpdateMutationOptionCombinations, parseDependencyAdditions, runUpdate, } from "./update.js";
14
15
  import { derivePmBulkMutationEffect, } from "../cli-contracts/command-exit-contracts.js";
15
16
  const UPDATE_MANY_CHECKPOINT_SCHEMA_VERSION = 1;
16
17
  const UPDATE_MANY_CHECKPOINT_SUBDIR = "update-many";
@@ -20,6 +21,7 @@ const NON_MUTATION_UPDATE_OPTION_KEYS = new Set([
20
21
  "force",
21
22
  "ownershipMetadataBypass",
22
23
  "ownershipDependencyBypass",
24
+ "allowUnresolvedDeps",
23
25
  ]);
24
26
  const UPDATE_MANY_MUTATION_FLAG_GUIDANCE = [
25
27
  "--status",
@@ -379,19 +381,20 @@ const buildTagMutationPlan = (row, update) => {
379
381
  // --add-ac-only bulk update must NOT be treated as a no-op skip).
380
382
  const buildAcceptanceCriteriaMutationPlan = (row, update) => {
381
383
  const before = row.acceptance_criteria;
382
- const base = update.acceptanceCriteria === undefined
383
- ? before
384
- : String(update.acceptanceCriteria).trim();
385
- const mutation = applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(base), update.addAc, update.removeAc);
386
- const warnings = mutation.unmatchedRemovals.map((criterion) => `remove_ac_unmatched:${criterion}`);
384
+ const mutation = applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(before), update.addAc, update.removeAc);
385
+ if (mutation.unmatchedRemovals.length > 0) {
386
+ throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`, EXIT_CODE.NOT_FOUND, {
387
+ code: "acceptance_criteria_remove_unmatched",
388
+ reason: "exact_match_not_found",
389
+ field: "acceptance_criteria",
390
+ unmatched: mutation.unmatchedRemovals,
391
+ });
392
+ }
387
393
  const after = mutation.criteria.join("; ");
388
- if (areValuesEqual(before, after) || (before === undefined && after === "")) {
389
- return { warnings };
394
+ if (areValuesEqual(typeof before === "string" ? before : "", after)) {
395
+ return undefined;
390
396
  }
391
- return {
392
- change: { field: "acceptance_criteria", before, after },
393
- warnings,
394
- };
397
+ return { field: "acceptance_criteria", before, after };
395
398
  };
396
399
  /** Adds changed scalar options to a planned item diff. */
397
400
  const appendScalarMutationPlans = (changes, row, update) => {
@@ -431,7 +434,6 @@ const appendUnsetMutationPlans = (changes, row, unset) => {
431
434
  const buildPlannedItemDiff = (item, runtimeFieldRegistry, update = {}) => {
432
435
  const row = toItemRecord(item);
433
436
  const changes = [];
434
- const warnings = [];
435
437
  const tagPlan = buildTagMutationPlan(row, update);
436
438
  if (tagPlan) {
437
439
  changes.push(tagPlan);
@@ -439,13 +441,10 @@ const buildPlannedItemDiff = (item, runtimeFieldRegistry, update = {}) => {
439
441
  appendScalarMutationPlans(changes, row, update);
440
442
  if (updateArrayValueCount(update.addAc) > 0 ||
441
443
  updateArrayValueCount(update.removeAc) > 0) {
442
- const composed = buildAcceptanceCriteriaMutationPlan(row, update);
443
- const withoutAc = changes.filter((change) => change.field !== "acceptance_criteria");
444
- changes.splice(0, changes.length, ...withoutAc);
445
- if (composed.change !== undefined) {
446
- changes.push(composed.change);
444
+ const acceptanceCriteriaChange = buildAcceptanceCriteriaMutationPlan(row, update);
445
+ if (acceptanceCriteriaChange !== undefined) {
446
+ changes.push(acceptanceCriteriaChange);
447
447
  }
448
- warnings.push(...composed.warnings);
449
448
  }
450
449
  changes.push(...buildCollectionMutationPlans(row, update));
451
450
  appendRuntimeFieldMutationPlans(changes, row, update, runtimeFieldRegistry);
@@ -453,7 +452,6 @@ const buildPlannedItemDiff = (item, runtimeFieldRegistry, update = {}) => {
453
452
  return {
454
453
  id: item.id,
455
454
  changes,
456
- ...(warnings.length > 0 ? { warnings } : {}),
457
455
  };
458
456
  };
459
457
  /** Normalizes an optional list status against the runtime schema. */
@@ -631,7 +629,15 @@ const buildUpdateManyPlan = async (params) => {
631
629
  includeBody: true,
632
630
  full: true,
633
631
  }, params.global);
634
- const planned = listed.items.map((item) => buildPlannedItemDiff(item, params.runtime.runtimeFieldRegistry, params.options.update));
632
+ const planned = listed.items.map((item) => {
633
+ const diff = buildPlannedItemDiff(item, params.runtime.runtimeFieldRegistry, params.options.update);
634
+ return params.dependencyWarnings.length === 0
635
+ ? diff
636
+ : {
637
+ ...diff,
638
+ warnings: [...params.dependencyWarnings],
639
+ };
640
+ });
635
641
  const existenceItems = params.options.list?.ids == null
636
642
  ? []
637
643
  : (await runList(undefined, {
@@ -679,7 +685,6 @@ const buildUpdateManyNoopResult = (plan) => ({
679
685
  rows: plan.planned.map((row) => ({
680
686
  id: row.id,
681
687
  status: "skipped",
682
- ...(row.warnings ? { warnings: row.warnings } : {}),
683
688
  })),
684
689
  ids: [],
685
690
  ...buildUnmatchedIdFields(plan),
@@ -689,15 +694,12 @@ const applyUpdateManyRows = async (params) => {
689
694
  const rows = [];
690
695
  const updatedIds = [];
691
696
  const updateMessage = params.options.update.message ?? `update-many apply ${params.checkpointId}`;
692
- const plannedById = new Map(params.plans.map((row) => [row.id, row]));
693
697
  const actionableById = new Set(params.plans.filter((row) => row.changes.length > 0).map((row) => row.id));
694
698
  for (const item of params.items) {
695
699
  if (!actionableById.has(item.id)) {
696
- const warnings = plannedById.get(item.id)?.warnings;
697
700
  rows.push({
698
701
  id: item.id,
699
702
  status: "skipped",
700
- ...(warnings ? { warnings } : {}),
701
703
  });
702
704
  continue;
703
705
  }
@@ -800,11 +802,21 @@ export const runUpdateMany = async (options, global) => {
800
802
  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);
801
803
  }
802
804
  assertPlannedUpdateValuesValid(options.update, runtime.settings, runtime.statusRegistry, runtime.pmRoot);
805
+ assertUpdateMutationOptionCombinations(options.update);
806
+ const dependencyWarnings = await assertDependencyTargetsResolvable({
807
+ pmRoot: runtime.pmRoot,
808
+ dependencies: parseDependencyAdditions(options.update.dep, runtime.settings.id_prefix, nowIso(), resolveAuthor(options.update.author, runtime.settings.author_default)).additions,
809
+ idPrefix: runtime.settings.id_prefix,
810
+ itemFormat: runtime.settings.item_format,
811
+ typeToFolder: resolveItemTypeRegistry(runtime.settings, getActiveExtensionRegistrations()).type_to_folder,
812
+ allowUnresolved: options.update.allowUnresolvedDeps,
813
+ });
803
814
  const plan = await buildUpdateManyPlan({
804
815
  options,
805
816
  global,
806
817
  runtime,
807
818
  updateSummary,
819
+ dependencyWarnings,
808
820
  });
809
821
  return options.dryRun === true
810
822
  ? buildUpdateManyDryRunResult(plan)
@@ -828,4 +840,4 @@ export const _testOnlyUpdateManyCommand = {
828
840
  toComparablePreviewValue,
829
841
  };
830
842
  //# sourceMappingURL=update-many.js.map
831
- //# debugId=67f8958d-60d5-5657-93ce-9803859acd9e
843
+ //# debugId=0f91de58-2cbc-52ba-97ea-42482d0c6ce1
@@ -40,6 +40,8 @@ export interface UpdateCommandOptions extends MutationMetadataCommandOptions, Sh
40
40
  force?: boolean;
41
41
  /** Permit an intentional unresolved parent reference under strict validation. */
42
42
  allowMissingParent?: boolean;
43
+ /** Explicitly permit unresolved local dependency targets with warning receipts. */
44
+ allowUnresolvedDeps?: boolean;
43
45
  /** Value that configures or reports dep remove for this contract. */
44
46
  depRemove?: string[];
45
47
  /** Value that configures or reports replace deps for this contract. */
@@ -96,7 +98,8 @@ interface DependencyRemovalSelector {
96
98
  kind?: (typeof DEPENDENCY_KIND_VALUES)[number];
97
99
  source_kind?: string;
98
100
  }
99
- declare function parseDependencyAdditions(raw: string[] | undefined, prefix: string, nowIso: string, fallbackAuthor: string): ParsedDependencyUpdates;
101
+ /** Parse dependency additions into their canonical storage representation. */
102
+ export declare function parseDependencyAdditions(raw: string[] | undefined, prefix: string, nowIso: string, fallbackAuthor: string): ParsedDependencyUpdates;
100
103
  declare function parseDependencyRemovals(raw: string[] | undefined, prefix: string): DependencyRemovalSelector[];
101
104
  declare function reconcileBlockedByDependency(current: Dependency[] | undefined, nextBlockedById: string | undefined, nowIsoValue: string, author: string): {
102
105
  dependencies: Dependency[] | undefined;
@@ -130,6 +133,8 @@ interface UpdateMutationContext {
130
133
  author: string;
131
134
  pmRoot: string;
132
135
  }
136
+ /** Validate mutually exclusive and required update mutation option combinations. */
137
+ export declare function assertUpdateMutationOptionCombinations(options: UpdateCommandOptions): void;
133
138
  type UpdateStatusMutationContext = Pick<UpdateMutationContext, "options" | "statusRegistry" | "clearItemMetadataKeys" | "nowIso">;
134
139
  declare function applyStatusAndCloseReasonMutations(document: ItemDocument, context: UpdateStatusMutationContext, previousStatusNormalized: string, changedFields: string[]): void;
135
140
  /** Implements run update for the public runtime surface of this module. */
@@ -4,14 +4,14 @@
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]="233df258-47b7-571a-b445-9eab0c811702")}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]="244583b8-2ffd-5da4-a4d3-46396fb354c0")}catch(e){}}();
8
8
  import { pathExists, 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, mutateItem, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
9
9
  import { runClose } from "./close.js";
10
10
  import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
11
11
  import { applyLegacyNoneCollectionNormalizers, createLegacyNoneCollectionNormalizers, assertNoLegacyNoneToken, assertNoLegacyNoneTokens, isLegacyNoneToken, } from "./legacy-none-tokens.js";
12
12
  import { ensureEnumValue as ensureEnum } from "./recurrence-parsers.js";
13
13
  import { parseEventEntries, parseReminderEntries, parseTypeOptionEntries, } from "./repeatable-metadata-parsers.js";
14
- import { assertDependencyEdgesAllowed, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
14
+ import { assertDependencyEdgesAllowed, assertDependencyTargetsResolvable, assertValidBareDependencyFlagValue, } from "../dependency-flag-validation.js";
15
15
  import { normalizeDependencySeedId, normalizeDependencySourceKind, } from "../dependency-provenance.js";
16
16
  import { resolveCanonicalRelationshipKind } from "../relationships.js";
17
17
  import { collectNewOrderingCycleWarnings } from "../graph/mutation-advisory.js";
@@ -392,7 +392,8 @@ function normalizeDependencyKindInput(raw) {
392
392
  ? (resolveCanonicalRelationshipKind(raw) ?? raw.trim())
393
393
  : raw;
394
394
  }
395
- function parseDependencyAdditions(raw, prefix, nowIso, fallbackAuthor) {
395
+ /** Parse dependency additions into their canonical storage representation. */
396
+ export function parseDependencyAdditions(raw, prefix, nowIso, fallbackAuthor) {
396
397
  if (!raw) {
397
398
  return { additions: [] };
398
399
  }
@@ -917,7 +918,20 @@ function validateLinkedArtifactReplacement(params) {
917
918
  throw new PmCliError(`${params.replaceFlag} cannot be combined with ${params.clearFlag}`, EXIT_CODE.USAGE);
918
919
  }
919
920
  }
920
- function validateReplaceOptions(options) {
921
+ /** Validate mutually exclusive and required update mutation option combinations. */
922
+ export function assertUpdateMutationOptionCombinations(options) {
923
+ const hasAdditiveAcceptanceCriteriaMutation = (options.addAc?.length ?? 0) > 0 || (options.removeAc?.length ?? 0) > 0;
924
+ if (options.acceptanceCriteria !== undefined &&
925
+ hasAdditiveAcceptanceCriteriaMutation) {
926
+ throw new PmCliError("Cannot combine --acceptance-criteria replacement with --add-ac or --remove-ac. Use --remove-ac and --add-ac together for an atomic one-entry repair.", EXIT_CODE.USAGE, {
927
+ code: "acceptance_criteria_mutation_conflict",
928
+ reason: "replacement_and_additive_mutation_combined",
929
+ nextSteps: [
930
+ "Use --acceptance-criteria alone to replace the complete list.",
931
+ "Use --remove-ac <old> --add-ac <new> to repair one criterion without replacing unrelated entries.",
932
+ ],
933
+ });
934
+ }
921
935
  if (options.replaceDeps === true &&
922
936
  (options.dep === undefined || options.dep.length === 0)) {
923
937
  throw new PmCliError("--replace-deps requires at least one --dep entry", EXIT_CODE.USAGE);
@@ -1444,7 +1458,7 @@ function applyTagsAndPlanningMutations(document, context, scalarMutationContext)
1444
1458
  // concurrent branch edits with disjoint additions merge instead of clobbering
1445
1459
  // the whole acceptance_criteria value (tag-API parity). Runs after the scalar
1446
1460
  // mutations so composition with a `--ac` replace uses the replaced base.
1447
- function applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutationContext, warnings) {
1461
+ function applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutationContext) {
1448
1462
  const addValues = context.options.addAc;
1449
1463
  const removeValues = context.options.removeAc;
1450
1464
  if (!(Array.isArray(addValues) && addValues.length > 0) &&
@@ -1452,8 +1466,18 @@ function applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutati
1452
1466
  return;
1453
1467
  }
1454
1468
  const mutation = applyAcceptanceCriteriaMutations(splitAcceptanceCriteria(document.metadata.acceptance_criteria), addValues, removeValues);
1455
- for (const unmatched of mutation.unmatchedRemovals) {
1456
- warnings.push(`remove_ac_unmatched:${unmatched}`);
1469
+ if (mutation.unmatchedRemovals.length > 0) {
1470
+ throw new PmCliError(`Acceptance criteria removal did not match: ${mutation.unmatchedRemovals.join(", ")}`, EXIT_CODE.NOT_FOUND, {
1471
+ code: "acceptance_criteria_remove_unmatched",
1472
+ reason: "exact_match_not_found",
1473
+ field: "acceptance_criteria",
1474
+ unmatched: mutation.unmatchedRemovals,
1475
+ why: "Lossless removal fails instead of silently applying the remaining mutations when an exact selector is wrong.",
1476
+ nextSteps: [
1477
+ "Read the current acceptance_criteria value and retry with the exact criterion text.",
1478
+ "Use --acceptance-criteria alone only when replacing the complete list is intentional.",
1479
+ ],
1480
+ });
1457
1481
  }
1458
1482
  const nextValue = mutation.criteria.join("; ");
1459
1483
  if (document.metadata.acceptance_criteria === nextValue) {
@@ -1638,7 +1662,7 @@ function mutateUpdateDocument(document, context) {
1638
1662
  applyLogCollectionMutations(document, context, changedFields);
1639
1663
  applyEvidenceCollectionMutations(document, context, changedFields);
1640
1664
  applyTagsAndPlanningMutations(document, context, scalarMutationContext);
1641
- applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutationContext, warnings);
1665
+ applyAcceptanceCriteriaAdditiveMutation(document, context, scalarMutationContext);
1642
1666
  applyOwnershipAndIssueMutations(document, context, scalarMutationContext, warnings);
1643
1667
  if (context.options.dep !== undefined ||
1644
1668
  context.options.depRemove !== undefined ||
@@ -1669,6 +1693,10 @@ function mutateUpdateDocument(document, context) {
1669
1693
  const actualChangedFields = [...new Set(changedFields)].filter((field) => field === "body"
1670
1694
  ? document.body !== beforeBody
1671
1695
  : !stableValueEquals(beforeMetadata[field], afterMetadata[field]));
1696
+ if (context.options.acceptanceCriteria !== undefined &&
1697
+ actualChangedFields.includes("acceptance_criteria")) {
1698
+ warnings.push(`acceptance_criteria_replaced:${splitAcceptanceCriteria(beforeMetadata.acceptance_criteria).length}:${splitAcceptanceCriteria(afterMetadata.acceptance_criteria).length}`);
1699
+ }
1672
1700
  return { changedFields: actualChangedFields, warnings };
1673
1701
  }
1674
1702
  /** Implements run update for the public runtime surface of this module. */
@@ -1701,7 +1729,7 @@ export async function runUpdate(id, options, global) {
1701
1729
  const unsetTargets = parseUpdateUnsetTargets(options.unset, runtimeFieldRegistry, extensionFieldNames);
1702
1730
  const clearOptionKeys = new Set(unsetTargets.optionKeys);
1703
1731
  const clearItemMetadataKeys = new Set(unsetTargets.metadataKeys);
1704
- validateReplaceOptions(options);
1732
+ assertUpdateMutationOptionCombinations(options);
1705
1733
  applyClearCollectionDefinitions({
1706
1734
  definitions: buildClearCollectionDefinitions(options),
1707
1735
  options,
@@ -1715,6 +1743,14 @@ export async function runUpdate(id, options, global) {
1715
1743
  const nowValue = new Date();
1716
1744
  const nowIso = nowValue.toISOString();
1717
1745
  const dependencyUpdates = parseDependencyAdditions(options.dep, settings.id_prefix, nowIso, author);
1746
+ const dependencyTargetWarnings = await assertDependencyTargetsResolvable({
1747
+ pmRoot,
1748
+ dependencies: dependencyUpdates.additions,
1749
+ idPrefix: settings.id_prefix,
1750
+ itemFormat: settings.item_format,
1751
+ typeToFolder: typeRegistry.type_to_folder,
1752
+ allowUnresolved: options.allowUnresolvedDeps,
1753
+ });
1718
1754
  const dependencyRemovals = parseDependencyRemovals(options.depRemove, settings.id_prefix);
1719
1755
  const parsedCommentUpdates = parseLogSeed("--comment", options.comment, nowIso, author);
1720
1756
  const commentUpdates = options.ownershipMetadataBypass === true && parsedCommentUpdates.values
@@ -1837,6 +1873,7 @@ export async function runUpdate(id, options, global) {
1837
1873
  warnings: [
1838
1874
  ...workflowTransitionWarnings,
1839
1875
  ...parentReferenceWarnings,
1876
+ ...dependencyTargetWarnings,
1840
1877
  ...orderingCycleWarnings,
1841
1878
  ...result.warnings,
1842
1879
  ],
@@ -1860,4 +1897,4 @@ export const _testOnlyUpdateCommand = {
1860
1897
  resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
1861
1898
  };
1862
1899
  //# sourceMappingURL=update.js.map
1863
- //# debugId=233df258-47b7-571a-b445-9eab0c811702
1900
+ //# debugId=244583b8-2ffd-5da4-a4d3-46396fb354c0
@@ -9,5 +9,5 @@
9
9
  export { ITEM_LATEST_TIMESTAMP_FIELDS, ITEM_UNION_COLLECTION_FIELDS, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, type HistoryMergeResult, type HistoryMergeStrategy, type ItemDocumentMergeResult, type JsonDocumentMergeResult, type ItemMergeConflictDecision, type MergePreferredSide, type RelationshipStreamMergeResult, } from "./three-way.js";
10
10
  export { listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptReport, summarizeMergeReceipt, type MergeDecisionReceipt, type MergeDecisionReceiptSummary, type MergeReceiptReport, } from "./receipts.js";
11
11
  export { MERGE_DRIVER_ARTIFACT_VALUES, runMergeDriver, type MergeDriverArtifact, type MergeDriverOptions, type MergeDriverResult, } from "./driver.js";
12
- export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, type MergeFenceAuditResult, type MergeDriverConfigurationAuditResult, type MergeFenceRefreshOutcome, type MergeInstallOptions, type MergeInstallContextResolution, type MergeInstallResult, } from "./install.js";
12
+ export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_V2_END, PM_GITATTRIBUTES_V2_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, type MergeFenceAuditResult, type MergeDriverConfigurationAuditResult, type MergeFenceRefreshOutcome, type MergeInstallOptions, type MergeInstallContextResolution, type MergeInstallResult, } from "./install.js";
13
13
  export { runMergeReconcile, type MergeReconcileOptions, type MergeReconcileResult, } from "./reconcile.js";
@@ -7,11 +7,11 @@
7
7
  * this module so packages and hosts can reuse the same merge behavior.
8
8
  */
9
9
 
10
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="a8072065-092c-564b-a84f-cf687f795a92")}catch(e){}}();
10
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="687855bf-7432-5691-a809-1f0406b5d8a8")}catch(e){}}();
11
11
  export { ITEM_LATEST_TIMESTAMP_FIELDS, ITEM_UNION_COLLECTION_FIELDS, mergeHistoryStreams, mergeItemDocuments, mergeJsonDocuments, mergeRelationshipEventStreams, } from "./three-way.js";
12
12
  export { listMergeReceipts, markMergeReceiptReconciled, runMergeReceiptReport, summarizeMergeReceipt, } from "./receipts.js";
13
13
  export { MERGE_DRIVER_ARTIFACT_VALUES, runMergeDriver, } from "./driver.js";
14
- export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, } from "./install.js";
14
+ export { auditMergeAttributeFence, auditMergeDriverConfiguration, buildMergeAttributePatterns, findGitWorkspaceRoot, PM_GITATTRIBUTES_END, PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_V2_END, PM_GITATTRIBUTES_V2_START, refreshMergeAttributeFenceIfInstalled, resolveMergeInstallContext, runMergeInstall, } from "./install.js";
15
15
  export { runMergeReconcile, } from "./reconcile.js";
16
16
  //# sourceMappingURL=index.js.map
17
- //# debugId=a8072065-092c-564b-a84f-cf687f795a92
17
+ //# debugId=687855bf-7432-5691-a809-1f0406b5d8a8
@@ -5,6 +5,10 @@ import { resolveSourceContextWritePolicy } from "../environment/source-context.j
5
5
  export declare const PM_GITATTRIBUTES_START = "# pm-cli:merge-drivers:start";
6
6
  /** Closing marker for the pm-owned merge-driver `.gitattributes` block. */
7
7
  export declare const PM_GITATTRIBUTES_END = "# pm-cli:merge-drivers:end";
8
+ /** Opening marker for the versioned fence that older releases leave untouched. */
9
+ export declare const PM_GITATTRIBUTES_V2_START = "# pm-cli:merge-drivers:v2:start";
10
+ /** Closing marker for the versioned fence that older releases leave untouched. */
11
+ export declare const PM_GITATTRIBUTES_V2_END = "# pm-cli:merge-drivers:v2:end";
8
12
  /** Documents the merge install options payload exchanged by command, SDK, and package integrations. */
9
13
  export interface MergeInstallOptions {
10
14
  /** Preview the `.gitattributes` and `git config` changes without writing anything. */
@@ -8,7 +8,7 @@
8
8
  * mutations refresh the fenced block automatically once it is installed.
9
9
  */
10
10
 
11
- !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]="cb6dc38e-b317-5739-83ff-cf459b8bb31e")}catch(e){}}();
11
+ !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]="94d2a7a8-ce00-5689-b2f6-3d4813234b55")}catch(e){}}();
12
12
  import { readFile, realpath, writeFile } from "node:fs/promises";
13
13
  import { execFile } from "node:child_process";
14
14
  import path from "node:path";
@@ -30,6 +30,10 @@ const execFileAsync = promisify(execFile);
30
30
  export const PM_GITATTRIBUTES_START = "# pm-cli:merge-drivers:start";
31
31
  /** Closing marker for the pm-owned merge-driver `.gitattributes` block. */
32
32
  export const PM_GITATTRIBUTES_END = "# pm-cli:merge-drivers:end";
33
+ /** Opening marker for the versioned fence that older releases leave untouched. */
34
+ export const PM_GITATTRIBUTES_V2_START = "# pm-cli:merge-drivers:v2:start";
35
+ /** Closing marker for the versioned fence that older releases leave untouched. */
36
+ export const PM_GITATTRIBUTES_V2_END = "# pm-cli:merge-drivers:v2:end";
33
37
  const MERGE_FENCE_LOCK_ID = "merge-fence";
34
38
  /**
35
39
  * Quote one argument for the shell used by Git merge-driver configuration.
@@ -235,6 +239,13 @@ export function buildMergeAttributePatterns(trackerRelativeRoot, typeFolders) {
235
239
  patterns.push(`${quoteGitAttributePattern(`${prefix}extensions/.managed-extensions.json`)} merge=pm-json`);
236
240
  return patterns;
237
241
  }
242
+ function removeManagedBlock(content, startMarker, endMarker) {
243
+ const start = content.indexOf(startMarker);
244
+ const end = content.indexOf(endMarker);
245
+ return start >= 0 && end > start
246
+ ? `${content.slice(0, start)}${content.slice(end + endMarker.length)}`
247
+ : content.replace(startMarker, "").replace(endMarker, "");
248
+ }
238
249
  async function reconcileGitattributesBlock(workspaceRoot, patterns, dryRun) {
239
250
  const gitattributesPath = path.join(workspaceRoot, ".gitattributes");
240
251
  let current = "";
@@ -247,17 +258,11 @@ async function reconcileGitattributesBlock(workspaceRoot, patterns, dryRun) {
247
258
  }
248
259
  }
249
260
  const block = [
250
- PM_GITATTRIBUTES_START,
261
+ PM_GITATTRIBUTES_V2_START,
251
262
  ...patterns,
252
- PM_GITATTRIBUTES_END,
263
+ PM_GITATTRIBUTES_V2_END,
253
264
  ].join("\n");
254
- const start = current.indexOf(PM_GITATTRIBUTES_START);
255
- const end = current.indexOf(PM_GITATTRIBUTES_END);
256
- const withoutManagedBlock = start >= 0 && end > start
257
- ? `${current.slice(0, start)}${current.slice(end + PM_GITATTRIBUTES_END.length)}`
258
- : current
259
- .replace(PM_GITATTRIBUTES_START, "")
260
- .replace(PM_GITATTRIBUTES_END, "");
265
+ const withoutManagedBlock = removeManagedBlock(removeManagedBlock(current, PM_GITATTRIBUTES_V2_START, PM_GITATTRIBUTES_V2_END), PM_GITATTRIBUTES_START, PM_GITATTRIBUTES_END);
261
266
  const prefix = withoutManagedBlock.trimEnd();
262
267
  const next = `${prefix.length > 0 ? `${prefix}\n\n` : ""}${block}\n`;
263
268
  if (next === current) {
@@ -290,7 +295,8 @@ export async function auditMergeAttributeFence(pmRoot, typeFolders) {
290
295
  const candidate = path.join(directory, ".gitattributes");
291
296
  try {
292
297
  const raw = await readFile(candidate, "utf8");
293
- if (raw.includes(PM_GITATTRIBUTES_START)) {
298
+ if (raw.includes(PM_GITATTRIBUTES_V2_START) ||
299
+ raw.includes(PM_GITATTRIBUTES_START)) {
294
300
  fenceDirectory = directory;
295
301
  fenceContent = raw;
296
302
  break;
@@ -314,11 +320,16 @@ export async function auditMergeAttributeFence(pmRoot, typeFolders) {
314
320
  };
315
321
  }
316
322
  const fencePath = path.join(fenceDirectory, ".gitattributes");
317
- const start = fenceContent.indexOf(PM_GITATTRIBUTES_START);
318
- const end = fenceContent.indexOf(PM_GITATTRIBUTES_END);
323
+ const usesV2 = fenceContent.includes(PM_GITATTRIBUTES_V2_START);
324
+ const startMarker = usesV2
325
+ ? PM_GITATTRIBUTES_V2_START
326
+ : PM_GITATTRIBUTES_START;
327
+ const endMarker = usesV2 ? PM_GITATTRIBUTES_V2_END : PM_GITATTRIBUTES_END;
328
+ const start = fenceContent.indexOf(startMarker);
329
+ const end = fenceContent.indexOf(endMarker);
319
330
  const committed = end > start
320
331
  ? fenceContent
321
- .slice(start + PM_GITATTRIBUTES_START.length, end)
332
+ .slice(start + startMarker.length, end)
322
333
  .split("\n")
323
334
  .map((line) => line.trim())
324
335
  .filter((line) => line.length > 0)
@@ -408,7 +419,8 @@ export async function refreshMergeAttributeFenceIfInstalled(pmRoot) {
408
419
  }
409
420
  throw error;
410
421
  }
411
- if (!current.includes(PM_GITATTRIBUTES_START)) {
422
+ if (!current.includes(PM_GITATTRIBUTES_V2_START) &&
423
+ !current.includes(PM_GITATTRIBUTES_START)) {
412
424
  return { status: "not_installed", path: gitattributesPath };
413
425
  }
414
426
  // Re-read after acquiring the dedicated fence lock so every concurrent
@@ -548,4 +560,4 @@ export async function installMergeFence(options) {
548
560
  };
549
561
  }
550
562
  //# sourceMappingURL=install.js.map
551
- //# debugId=cb6dc38e-b317-5739-83ff-cf459b8bb31e
563
+ //# debugId=94d2a7a8-ce00-5689-b2f6-3d4813234b55
@@ -25,6 +25,8 @@ export interface MergeDecisionReceipt {
25
25
  created_at: string;
26
26
  /** Reconciliation timestamp, when consumed. */
27
27
  reconciled_at?: string;
28
+ /** Whether decision values are recoverable locally or represented by hashes only. */
29
+ value_availability?: "clone_local" | "hash_only";
28
30
  }
29
31
  /** Privacy-safe receipt summary suitable for committed history context. */
30
32
  export interface MergeDecisionReceiptSummary {
@@ -78,6 +80,7 @@ export declare function writeMergeReceipt(params: {
78
80
  export declare function listMergeReceipts(cwd: string, options?: {
79
81
  includeReconciled?: boolean;
80
82
  includeLossless?: boolean;
83
+ pmRoot?: string;
81
84
  }): Promise<MergeDecisionReceipt[]>;
82
85
  /** Split merge provenance into receipts with discarded values and receipts whose composition was lossless. */
83
86
  export declare function partitionMergeReceipts(receipts: MergeDecisionReceipt[]): {