@unbrained/pm-cli 2026.8.20 → 2026.8.22

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 (228) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +38 -0
  3. package/dist/cli/error-guidance.d.ts +29 -4
  4. package/dist/cli/error-guidance.js +43 -43
  5. package/dist/cli/main.d.ts +3 -0
  6. package/dist/cli/main.js +40 -7
  7. package/dist/cli-bundle/bundle-manifest.json +150 -150
  8. package/dist/cli-bundle/chunks/{chunk-L4LGPBJU.js → chunk-BWX4SK46.js} +58 -58
  9. package/dist/cli-bundle/chunks/chunk-EMWDM5FI.js +13 -0
  10. package/dist/cli-bundle/chunks/chunk-HYG6LRL4.js +200 -0
  11. package/dist/cli-bundle/chunks/{chunk-TSMWLCHS.js → chunk-MYYI3ZOA.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-4GB2LTOQ.js → chunk-MZTZQTMS.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-7BRF2BX2.js → chunk-QI2CT3IX.js} +2 -2
  14. package/dist/cli-bundle/chunks/chunk-SMWXHMVB.js +35 -0
  15. package/dist/cli-bundle/chunks/{chunk-US2ZQW2M.js → chunk-U6GQ4VMV.js} +47 -47
  16. package/dist/cli-bundle/chunks/{chunk-K3EN3LK2.js → chunk-VMMIL3SI.js} +2 -2
  17. package/dist/cli-bundle/chunks/chunk-WG4STC36.js +5 -0
  18. package/dist/cli-bundle/chunks/{chunk-XYDDWBZN.js → chunk-YBPJAOQQ.js} +3 -3
  19. package/dist/cli-bundle/chunks/{register-list-query-JSAQCVOC.js → register-list-query-HZKBQNWW.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-mutation-XJPAW63D.js → register-mutation-HTKEEGRD.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-operations-DSOSB2XQ.js → register-operations-6EMRWJJY.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-setup-QUR6QL2C.js → register-setup-QK4OTOXN.js} +2 -2
  23. package/dist/cli-bundle/focused-chunks/{chunk-TDR5OGG3.js → chunk-2ARQGDDW.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/{chunk-AZBACT5T.js → chunk-2AZT5WXZ.js} +2 -2
  25. package/dist/cli-bundle/focused-chunks/{chunk-M32HFIQB.js → chunk-2POVTNLY.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-3LKU6PTJ.js +4 -0
  27. package/dist/cli-bundle/focused-chunks/chunk-5SHSBMX2.js +2 -0
  28. package/dist/cli-bundle/focused-chunks/{chunk-UGSS4F5X.js → chunk-6S2MO3Q3.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-5L7M4AI7.js → chunk-A2BC5PQL.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-C4S4A4JJ.js +5 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-OM65KHGF.js → chunk-D6RBZEJJ.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/chunk-E2EWYPY6.js +16 -0
  33. package/dist/cli-bundle/focused-chunks/{chunk-G3C5ERXG.js → chunk-GMYPD4FX.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/chunk-L5LDSRO2.js +155 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-BLJCGGID.js → chunk-MB37AYN6.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-MCOR37QK.js +2 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-FUREQLQN.js → chunk-PH2OXXVZ.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-325UXIO7.js → chunk-PMGJUFNQ.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-R6SR45XU.js +50 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-WZE4LIPW.js +8 -0
  41. package/dist/cli-bundle/main.js +13 -13
  42. package/dist/cli-bundle/sdk-authoring.js +1 -1
  43. package/dist/cli-bundle/sdk-contracts.js +2 -2
  44. package/dist/cli-bundle/sdk-core.js +40 -40
  45. package/dist/cli-bundle/sdk-governance.js +1 -1
  46. package/dist/cli-bundle/sdk-graph.js +1 -1
  47. package/dist/cli-bundle/sdk-merge.js +32 -32
  48. package/dist/cli-bundle/sdk-query.js +1 -1
  49. package/dist/cli-bundle/sdk-runtime.js +1 -1
  50. package/dist/cli-bundle/sdk-testing.js +1 -1
  51. package/dist/cli-bundle/sdk.js +5 -5
  52. package/dist/core/extensions/extension-hook-runtime.js +22 -20
  53. package/dist/core/extensions/extension-types.d.ts +8 -1
  54. package/dist/core/extensions/extension-types.js +2 -2
  55. package/dist/core/extensions/loader.js +7 -3
  56. package/dist/core/extensions/service-ownership.d.ts +8 -0
  57. package/dist/core/extensions/service-ownership.js +20 -0
  58. package/dist/core/item/id.js +20 -5
  59. package/dist/core/item/item-format.js +27 -2
  60. package/dist/core/shared/errors.d.ts +20 -0
  61. package/dist/core/shared/errors.js +2 -2
  62. package/dist/core/store/item-store.js +6 -91
  63. package/dist/core/store/tracker-preflight.d.ts +7 -0
  64. package/dist/core/store/tracker-preflight.js +142 -0
  65. package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
  66. package/dist/sdk/agent/tracker-preflight-contracts.d.ts +63 -0
  67. package/dist/sdk/agent/tracker-preflight-contracts.js +127 -0
  68. package/dist/sdk/annotations.js +6 -7
  69. package/dist/sdk/authoring.d.ts +1 -1
  70. package/dist/sdk/authoring.js +2 -2
  71. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
  72. package/dist/sdk/cli-contracts/agent-output-contracts.js +324 -2
  73. package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
  74. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
  75. package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
  76. package/dist/sdk/cli-contracts.d.ts +1 -1
  77. package/dist/sdk/cli-contracts.js +3 -3
  78. package/dist/sdk/config.d.ts +5 -0
  79. package/dist/sdk/config.js +5 -5
  80. package/dist/sdk/context-intent-runtime.js +7 -4
  81. package/dist/sdk/contracts.d.ts +1 -0
  82. package/dist/sdk/contracts.js +3 -2
  83. package/dist/sdk/dependencies.js +5 -7
  84. package/dist/sdk/dependency-flag-validation.d.ts +1 -1
  85. package/dist/sdk/dependency-flag-validation.js +10 -4
  86. package/dist/sdk/environment/tracker-preflight.d.ts +6 -0
  87. package/dist/sdk/environment/tracker-preflight.js +10 -0
  88. package/dist/sdk/eval.js +5 -7
  89. package/dist/sdk/extension/install-sources.d.ts +1 -1
  90. package/dist/sdk/extension/install-sources.js +6 -3
  91. package/dist/sdk/extension/output-ownership.d.ts +1 -0
  92. package/dist/sdk/extension/output-ownership.js +3 -2
  93. package/dist/sdk/files.js +6 -10
  94. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +75 -15
  95. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +81 -8
  96. package/dist/sdk/governance/assurance.d.ts +36 -2
  97. package/dist/sdk/governance/assurance.js +184 -10
  98. package/dist/sdk/governance/gc.js +5 -6
  99. package/dist/sdk/governance/health.d.ts +3 -0
  100. package/dist/sdk/governance/health.js +42 -11
  101. package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
  102. package/dist/sdk/governance/hierarchy-validation.js +109 -0
  103. package/dist/sdk/governance/reindex.js +5 -6
  104. package/dist/sdk/governance/validate.d.ts +2 -9
  105. package/dist/sdk/governance/validate.js +51 -109
  106. package/dist/sdk/graph/assembly.d.ts +6 -1
  107. package/dist/sdk/graph/assembly.js +16 -22
  108. package/dist/sdk/graph/governance-contracts.d.ts +1 -1
  109. package/dist/sdk/graph/governance-contracts.js +8 -2
  110. package/dist/sdk/graph/governance.d.ts +7 -5
  111. package/dist/sdk/graph/governance.js +76 -16
  112. package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
  113. package/dist/sdk/graph/hierarchy-integrity.js +311 -0
  114. package/dist/sdk/graph/index.d.ts +2 -1
  115. package/dist/sdk/graph/index.js +3 -2
  116. package/dist/sdk/graph/remediation.js +32 -2
  117. package/dist/sdk/graph/run.d.ts +31 -2
  118. package/dist/sdk/graph/run.js +83 -36
  119. package/dist/sdk/graph/traversal.js +14 -5
  120. package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
  121. package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
  122. package/dist/sdk/history-compact.js +6 -9
  123. package/dist/sdk/history-read.js +5 -7
  124. package/dist/sdk/history-redact.js +5 -6
  125. package/dist/sdk/history-repair.js +6 -9
  126. package/dist/sdk/improvement-ledger.js +7 -10
  127. package/dist/sdk/index.d.ts +4 -2
  128. package/dist/sdk/index.js +5 -3
  129. package/dist/sdk/item-children.js +21 -8
  130. package/dist/sdk/lifecycle/append.d.ts +0 -5
  131. package/dist/sdk/lifecycle/append.js +5 -6
  132. package/dist/sdk/lifecycle/claim.d.ts +0 -5
  133. package/dist/sdk/lifecycle/claim.js +6 -9
  134. package/dist/sdk/lifecycle/close-many.d.ts +0 -5
  135. package/dist/sdk/lifecycle/close-many.js +5 -6
  136. package/dist/sdk/lifecycle/close.d.ts +0 -5
  137. package/dist/sdk/lifecycle/close.js +5 -6
  138. package/dist/sdk/lifecycle/copy.d.ts +0 -5
  139. package/dist/sdk/lifecycle/copy.js +5 -6
  140. package/dist/sdk/lifecycle/create.d.ts +0 -5
  141. package/dist/sdk/lifecycle/create.js +127 -102
  142. package/dist/sdk/lifecycle/delete.js +5 -6
  143. package/dist/sdk/lifecycle/focus.d.ts +0 -5
  144. package/dist/sdk/lifecycle/focus.js +5 -6
  145. package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
  146. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
  147. package/dist/sdk/lifecycle/plan.d.ts +0 -5
  148. package/dist/sdk/lifecycle/plan.js +5 -6
  149. package/dist/sdk/lifecycle/restore.js +5 -6
  150. package/dist/sdk/lifecycle/update-many.d.ts +0 -5
  151. package/dist/sdk/lifecycle/update-many.js +5 -6
  152. package/dist/sdk/lifecycle/update.d.ts +2 -5
  153. package/dist/sdk/lifecycle/update.js +211 -84
  154. package/dist/sdk/linked-artifacts.js +6 -7
  155. package/dist/sdk/merge/install.js +5 -6
  156. package/dist/sdk/mutation-events.js +5 -7
  157. package/dist/sdk/package-import-adapters.js +6 -8
  158. package/dist/sdk/profile.js +6 -7
  159. package/dist/sdk/query/activity.js +5 -6
  160. package/dist/sdk/query/calendar.js +5 -6
  161. package/dist/sdk/query/complete-list.d.ts +3 -3
  162. package/dist/sdk/query/complete-list.js +46 -3
  163. package/dist/sdk/query/get.d.ts +0 -5
  164. package/dist/sdk/query/get.js +5 -6
  165. package/dist/sdk/query/history.d.ts +0 -5
  166. package/dist/sdk/query/history.js +5 -6
  167. package/dist/sdk/query/list.d.ts +4 -3
  168. package/dist/sdk/query/list.js +92 -54
  169. package/dist/sdk/query/search.js +5 -7
  170. package/dist/sdk/read-output-contracts.d.ts +5 -1
  171. package/dist/sdk/read-output-contracts.js +87 -22
  172. package/dist/sdk/relationship-context.js +3 -4
  173. package/dist/sdk/relationship-kinds/contract.d.ts +8 -0
  174. package/dist/sdk/relationship-kinds/contract.js +13 -13
  175. package/dist/sdk/relationships.d.ts +1 -1
  176. package/dist/sdk/relationships.js +27 -2
  177. package/dist/sdk/runtime.d.ts +3 -2
  178. package/dist/sdk/runtime.js +3 -2
  179. package/dist/sdk/schema-migration.js +6 -7
  180. package/dist/sdk/schema.js +5 -6
  181. package/dist/sdk/stats.js +5 -8
  182. package/dist/sdk/templates.js +5 -6
  183. package/dist/sdk/test/batch.js +15 -9
  184. package/dist/sdk/test/execution.js +12 -5
  185. package/dist/sdk/test/runs.js +5 -7
  186. package/dist/types.d.ts +11 -0
  187. package/dist/types.js +2 -2
  188. package/docs/AGENT_UX_CONTRACTS.md +24 -1
  189. package/docs/COMMANDS.md +29 -14
  190. package/docs/DEPENDENCY_KIND_CONTRACT.md +40 -1
  191. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +98 -0
  192. package/docs/EXTENSIONS.md +2 -1
  193. package/docs/README.md +1 -0
  194. package/docs/READ_OUTPUT_CONTRACTS.md +9 -2
  195. package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +37 -0
  196. package/docs/RELATIONSHIP_GRAPH.md +97 -12
  197. package/docs/SDK_PRIMITIVE_INVENTORY.md +15 -1
  198. package/docs/TESTING.md +15 -0
  199. package/marketplace.json +2 -2
  200. package/package.json +1 -1
  201. package/packages/pm-beads/package.json +1 -1
  202. package/packages/pm-calendar/package.json +1 -1
  203. package/packages/pm-command-kit/package.json +1 -1
  204. package/packages/pm-digital-twin/package.json +1 -1
  205. package/packages/pm-governance-audit/package.json +1 -1
  206. package/packages/pm-guide-shell/package.json +1 -1
  207. package/packages/pm-kanban/package.json +1 -1
  208. package/packages/pm-lifecycle-hooks/package.json +1 -1
  209. package/packages/pm-linked-test-adapters/package.json +1 -1
  210. package/packages/pm-search-advanced/package.json +1 -1
  211. package/packages/pm-templates/package.json +1 -1
  212. package/packages/pm-todos/package.json +1 -1
  213. package/packages/pm-vcs/package.json +1 -1
  214. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  215. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  216. package/sdk/public-surface.json +848 -56
  217. package/dist/cli-bundle/chunks/chunk-2RDVGYWE.js +0 -13
  218. package/dist/cli-bundle/chunks/chunk-BLVQHFSY.js +0 -35
  219. package/dist/cli-bundle/chunks/chunk-CU25EQVV.js +0 -5
  220. package/dist/cli-bundle/chunks/chunk-RS3IV2R6.js +0 -197
  221. package/dist/cli-bundle/focused-chunks/chunk-6AHG2YW7.js +0 -50
  222. package/dist/cli-bundle/focused-chunks/chunk-GXWQBE3T.js +0 -8
  223. package/dist/cli-bundle/focused-chunks/chunk-JWKEDZJI.js +0 -4
  224. package/dist/cli-bundle/focused-chunks/chunk-KYZ6JGPL.js +0 -155
  225. package/dist/cli-bundle/focused-chunks/chunk-Q47EX4DI.js +0 -2
  226. package/dist/cli-bundle/focused-chunks/chunk-RIHDMCUM.js +0 -2
  227. package/dist/cli-bundle/focused-chunks/chunk-T4ZFY7ZJ.js +0 -16
  228. package/dist/cli-bundle/focused-chunks/chunk-Z3PLWSGM.js +0 -2
@@ -0,0 +1,15 @@
1
+ /** Inputs for the internal workspace-wide hierarchy mutation lock. */
2
+ export interface HierarchyMutationLockOptions {
3
+ /** Tracker root whose hierarchy is being changed. */
4
+ pmRoot: string;
5
+ /** Principal recorded as the lock owner. */
6
+ author: string;
7
+ /** Tracker-configured stale-lock lifetime. */
8
+ ttlSeconds: number;
9
+ /** Tracker-configured bounded lock wait. */
10
+ waitMs: number;
11
+ /** Whether this mutation can add hierarchy evidence. */
12
+ required: boolean;
13
+ }
14
+ /** Acquire the shared hierarchy writer lock, or return a no-op release. */
15
+ export declare function acquireHierarchyMutationLock(options: HierarchyMutationLockOptions): Promise<() => Promise<void>>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @module sdk/lifecycle/hierarchy-mutation-lock
3
+ *
4
+ * Serializes hierarchy-affecting create and update transactions so each
5
+ * before/after integrity decision is made from a fresh workspace snapshot.
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]="39a36d42-29b1-5f0f-a8b2-f3bfc0ef78c2")}catch(e){}}();
9
+ import { acquireLock } from "../../core/lock/lock.js";
10
+ const HIERARCHY_MUTATION_LOCK_ID = "hierarchy-integrity";
11
+ /** Acquire the shared hierarchy writer lock, or return a no-op release. */
12
+ export async function acquireHierarchyMutationLock(options) {
13
+ const release = options.required
14
+ ? await acquireLock(options.pmRoot, HIERARCHY_MUTATION_LOCK_ID, options.ttlSeconds, options.author, false, false, options.waitMs)
15
+ : async () => { };
16
+ let released = false;
17
+ return async () => {
18
+ if (released)
19
+ return;
20
+ released = true;
21
+ await release();
22
+ };
23
+ }
24
+ //# sourceMappingURL=hierarchy-mutation-lock.js.map
25
+ //# debugId=39a36d42-29b1-5f0f-a8b2-f3bfc0ef78c2
@@ -1,8 +1,3 @@
1
- /**
2
- * @module sdk/lifecycle/plan
3
- *
4
- * Implements the pm plan command surface and its agent-facing runtime behavior.
5
- */
6
1
  import { type GlobalOptions } from "../runtime-primitives.js";
7
2
  import type { DependencyKind, ItemMetadata, PlanDecision, PlanDiscovery, PlanHarness, PlanMode, PlanStep, PlanStepStatus, PlanValidationCheck } from "../../types/index.js";
8
3
  import type { MutationMetadataCommandOptions, SharedLinkedResourceOptions } from "./mutation-command-options.js";
@@ -4,8 +4,9 @@
4
4
  * Implements the pm plan 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]="3d5ea029-26ef-51bc-bacc-b1d4d807a024")}catch(e){}}();
8
- import { pathExists, getActiveExtensionRegistrations, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, resolveTypeName, EXIT_CODE, PmCliError, splitCommaList, nowIso, locateItem, mutateItem, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, isTerminalPlanMode, } from "../runtime-primitives.js";
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]="49fd5730-99c2-5a93-a80e-83c806a124bf")}catch(e){}}();
8
+ import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
+ import { getActiveExtensionRegistrations, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, resolveTypeName, EXIT_CODE, PmCliError, splitCommaList, nowIso, locateItem, mutateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, isTerminalPlanMode, } from "../runtime-primitives.js";
9
10
  import { PLAN_HARNESS_VALUES, PLAN_MODE_VALUES, PLAN_STEP_LINK_KIND_VALUES, PLAN_STEP_STATUS_VALUES, } from "../../types/index.js";
10
11
  import { runCreate, } from "./create.js";
11
12
  import { createUnknownSubcommandError } from "../agent/subcommand-recovery.js";
@@ -547,9 +548,7 @@ function ensurePlanItem(item) {
547
548
  }
548
549
  async function loadContext(global) {
549
550
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
550
- if (!(await pathExists(getSettingsPath(pmRoot)))) {
551
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
552
- }
551
+ await assertInitializedTracker(pmRoot);
553
552
  const settings = await readSettings(pmRoot);
554
553
  return { pmRoot, settings };
555
554
  }
@@ -1587,4 +1586,4 @@ export const _testOnlyPlanCommand = {
1587
1586
  changedPlanMetadataFields,
1588
1587
  };
1589
1588
  //# sourceMappingURL=plan.js.map
1590
- //# debugId=3d5ea029-26ef-51bc-bacc-b1d4d807a024
1589
+ //# debugId=49fd5730-99c2-5a93-a80e-83c806a124bf
@@ -4,10 +4,11 @@
4
4
  * Implements the SDK-owned restore lifecycle operation shared by every surface.
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]="353be665-9f67-5d0e-99c9-6bbb7e927e0b")}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]="db5f3a6d-9ae5-5f9b-bedf-766b2b79324c")}catch(e){}}();
8
+ import { assertInitializedTracker } from "../environment/tracker-preflight.js";
8
9
  import jsonPatch from "fast-json-patch";
9
10
  import fs from "node:fs/promises";
10
- import { pathExists, readFileIfExists, writeFileAtomic, appendHistoryEntry, createHistoryEntry, replayToCanonicalItemDocument, replayToItemDocument, toReplayDocument, enforceHistoryStreamPolicyForItem, normalizeItemId, normalizeRawItemId, canonicalDocument, serializeItemDocument, resolveItemTypeRegistry, acquireLock, EXIT_CODE, PmCliError, nowIso, getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveOnWriteHooks, runActiveBeforeMutationHooks, locateItem, createMutationGuardSdk, readLocatedItem, getHistoryPath, getItemPath, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
11
+ import { pathExists, readFileIfExists, writeFileAtomic, appendHistoryEntry, createHistoryEntry, replayToCanonicalItemDocument, replayToItemDocument, toReplayDocument, enforceHistoryStreamPolicyForItem, normalizeItemId, normalizeRawItemId, canonicalDocument, serializeItemDocument, resolveItemTypeRegistry, acquireLock, EXIT_CODE, PmCliError, nowIso, getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveOnWriteHooks, runActiveBeforeMutationHooks, locateItem, createMutationGuardSdk, readLocatedItem, getHistoryPath, getItemPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
11
12
  import { applyHistoryPatch, ensureMaterializedHistoryTarget as ensureMaterializedRestoreTarget, extractPatchFailureContext, readHistoryEntries, replayHistoryToTarget as replayToTarget, resolveHistoryTarget, } from "../history-read.js";
12
13
  import { acquireItemMetadataDerivedIndexLock, refreshItemMetadataDerivedIndex, } from "../item-metadata-index.js";
13
14
  /** Resolve restore targets with the command's established wording and at-or-before timestamp semantics. */
@@ -163,9 +164,7 @@ async function runRestoreWriteHooks(params) {
163
164
  /** Implements run restore for the public runtime surface of this module. */
164
165
  export async function runRestore(id, target, options, global) {
165
166
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
166
- if (!(await pathExists(getSettingsPath(pmRoot)))) {
167
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
168
- }
167
+ await assertInitializedTracker(pmRoot);
169
168
  const settings = await readSettings(pmRoot);
170
169
  const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
171
170
  const subject = await resolveRestoreSubject(pmRoot, id, settings, typeRegistry.type_to_folder);
@@ -317,4 +316,4 @@ export const _testOnlyRestoreCommand = {
317
316
  resolveRestoreSubject,
318
317
  };
319
318
  //# sourceMappingURL=restore.js.map
320
- //# debugId=353be665-9f67-5d0e-99c9-6bbb7e927e0b
319
+ //# debugId=db5f3a6d-9ae5-5f9b-bedf-766b2b79324c
@@ -1,8 +1,3 @@
1
- /**
2
- * @module cli/commands/update-many
3
- *
4
- * Implements the pm update many command surface and its agent-facing runtime behavior.
5
- */
6
1
  import { type RuntimeFieldRegistry, type RuntimeStatusRegistry, type GlobalOptions } from "../runtime-primitives.js";
7
2
  import type { ItemStatus, PmSettings } from "../../types/index.js";
8
3
  import { hasListFilters } from "../query/list-filter-shared.js";
@@ -4,8 +4,9 @@
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]="e797d654-df89-554b-876b-cb2faa350bd0")}catch(e){}}();
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";
7
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="7a157c2e-e9e6-5bce-b124-0a7d34e3c7dc")}catch(e){}}();
8
+ import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
+ import { createCheckpointId, loadMutationCheckpoint, restoreCheckpointItems, writeMutationCheckpoint, toItemRecord, applyAcceptanceCriteriaMutations, applyTagRemovals, mergeAdditiveTags, parseOptionalNonNegativeInteger, parseTags, splitAcceptanceCriteria, resolvePriority, normalizeStatusInput, resolveItemTypeRegistry, resolveTypeName, collectRuntimeUpdateFieldValues, buildInvalidTypeError, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, toErrorMessage, stableValueEquals, nowIso, resolveIsoOrRelative, getActiveExtensionRegistrations, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
9
10
  import { assertDependencyTargetsResolvable } from "../dependency-flag-validation.js";
10
11
  import { parseStatusFilterCsv } from "../../core/item/status-filter.js";
11
12
  import { hasListFilters } from "../query/list-filter-shared.js";
@@ -588,9 +589,7 @@ const buildUnmatchedIdFields = (plan) => plan.unmatchedIds === undefined
588
589
  /** Loads tracker settings and runtime registries for update-many execution. */
589
590
  const loadUpdateManyRuntimeContext = async (global) => {
590
591
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
591
- if (!(await pathExists(getSettingsPath(pmRoot)))) {
592
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
593
- }
592
+ await assertInitializedTracker(pmRoot);
594
593
  const settings = await readSettings(pmRoot);
595
594
  return {
596
595
  pmRoot,
@@ -853,4 +852,4 @@ export const _testOnlyUpdateManyCommand = {
853
852
  toComparablePreviewValue,
854
853
  };
855
854
  //# sourceMappingURL=update-many.js.map
856
- //# debugId=e797d654-df89-554b-876b-cb2faa350bd0
855
+ //# debugId=7a157c2e-e9e6-5bce-b124-0a7d34e3c7dc
@@ -1,8 +1,3 @@
1
- /**
2
- * @module sdk/lifecycle/update
3
- *
4
- * Implements the pm update command surface and its agent-facing runtime behavior.
5
- */
6
1
  import { resolveItemTypeRegistry, type RuntimeFieldRegistry, type RuntimeStatusRegistry, type NormalizedTypeWorkflow, type GlobalOptions, PmCliError, getActiveExtensionRegistrations, readSettings } from "../runtime-primitives.js";
7
2
  import type { Dependency, GovernanceWorkflowEnforcement, ItemDocument } from "../../types/index.js";
8
3
  import { DEPENDENCY_KIND_VALUES } from "../../types/index.js";
@@ -126,6 +121,8 @@ interface DependencyRemovalSelector {
126
121
  id: string;
127
122
  kind?: (typeof DEPENDENCY_KIND_VALUES)[number];
128
123
  source_kind?: string;
124
+ author?: string;
125
+ created_at?: string;
129
126
  }
130
127
  /** Parse dependency additions into their canonical storage representation. */
131
128
  export declare function parseDependencyAdditions(raw: string[] | undefined, prefix: string, nowIso: string, fallbackAuthor: string): ParsedDependencyUpdates;
@@ -4,8 +4,9 @@
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]="3ab4f16d-ce37-546e-a2f6-0495fd1967c7")}catch(e){}}();
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, readLocatedItem, getSettingsPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
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){}}();
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
10
  import { mutateItemWithHistoryContextResolver } from "../../core/store/item-store.js";
10
11
  import { runClose } from "./close.js";
11
12
  import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parseRegressionInput, } from "./metadata-normalizers.js";
@@ -16,6 +17,9 @@ import { assertDependencyEdgesAllowed, assertDependencyTargetsResolvable, assert
16
17
  import { normalizeDependencySeedId, normalizeDependencySourceKind, } from "../dependency-provenance.js";
17
18
  import { resolveCanonicalRelationshipKind } from "../relationships.js";
18
19
  import { collectNewOrderingCycleWarnings } from "../graph/mutation-advisory.js";
20
+ import { assertHierarchyMutationAllowed } from "../graph/hierarchy-integrity.js";
21
+ import { resolveWorkspaceRelationshipKindRegistry } from "../graph/assembly.js";
22
+ import { acquireHierarchyMutationLock } from "./hierarchy-mutation-lock.js";
19
23
  import { DEPENDENCY_KIND_VALUES, ISSUE_SEVERITY_VALUES, RISK_VALUES, } from "../../types/index.js";
20
24
  import { parseDocs, parseFiles, parseLogSeed, parseTests, requireStringOption, } from "./create.js";
21
25
  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";
@@ -354,6 +358,9 @@ function parseDependencyCreatedAt(value, currentIso) {
354
358
  if (!value || value.trim() === "" || value.trim().toLowerCase() === "now") {
355
359
  return currentIso;
356
360
  }
361
+ return normalizeDependencyTimestamp(value);
362
+ }
363
+ function normalizeDependencyTimestamp(value) {
357
364
  const parsed = Date.parse(value);
358
365
  if (!Number.isFinite(parsed)) {
359
366
  throw new PmCliError(`Invalid dependency created_at timestamp "${value}"`, EXIT_CODE.USAGE);
@@ -376,7 +383,14 @@ const DEP_ADDITION_KEYS = [
376
383
  "source_kind",
377
384
  ];
378
385
  /** Allowed CSV/markdown keys for the `--dep-remove` selector (GH-258). */
379
- const DEP_REMOVE_KEYS = ["id", "kind", "type", "source_kind"];
386
+ const DEP_REMOVE_KEYS = [
387
+ "id",
388
+ "kind",
389
+ "type",
390
+ "author",
391
+ "created_at",
392
+ "source_kind",
393
+ ];
380
394
  function looksLikeStructuredDependencyEntry(raw) {
381
395
  if (raw.startsWith("```") || raw.includes("\n")) {
382
396
  return true;
@@ -440,9 +454,9 @@ function parseDependencyRemovals(raw, prefix) {
440
454
  if (!trimmed) {
441
455
  throw new PmCliError("--dep-remove requires id or key/value selectors", EXIT_CODE.USAGE);
442
456
  }
443
- if (trimmed.includes("=") ||
444
- /^(?:[-*+]\s+)?(?:id|kind|type|source_kind)\s*[:=]/i.test(trimmed) ||
445
- trimmed.startsWith("```")) {
457
+ const isStructured = looksLikeStructuredDependencyEntry(trimmed);
458
+ assertValidBareDependencyFlagValue(trimmed, isStructured, "--dep-remove");
459
+ if (isStructured) {
446
460
  const kv = parseCsvKv(trimmed, "--dep-remove");
447
461
  assertNoUnknownCsvKeys(kv, "--dep-remove", DEP_REMOVE_KEYS);
448
462
  const idRaw = kv.id?.trim();
@@ -454,12 +468,18 @@ function parseDependencyRemovals(raw, prefix) {
454
468
  }
455
469
  const kindRaw = normalizeDependencyKindInput(parseOptionalDependencyString(kv.kind ?? kv.type));
456
470
  const sourceKind = normalizeDependencySourceKind(parseOptionalDependencyString(kv.source_kind));
471
+ const author = parseOptionalDependencyString(kv.author);
472
+ const createdAt = parseOptionalDependencyString(kv.created_at);
457
473
  return {
458
474
  id: normalizeDependencySeedId(idRaw, prefix, sourceKind),
459
475
  kind: kindRaw
460
476
  ? ensureEnum(kindRaw, DEPENDENCY_KIND_VALUES, "dependency kind")
461
477
  : undefined,
462
478
  source_kind: sourceKind,
479
+ author,
480
+ created_at: createdAt
481
+ ? normalizeDependencyTimestamp(createdAt)
482
+ : undefined,
463
483
  };
464
484
  }
465
485
  if (trimmed.toLowerCase() === "undefined") {
@@ -472,7 +492,24 @@ function parseDependencyRemovals(raw, prefix) {
472
492
  }
473
493
  function dependencyKey(value) {
474
494
  const sourceKind = value.source_kind?.trim().toLowerCase() ?? "";
475
- return `${value.id.trim().toLowerCase()}::${value.kind}::${sourceKind}`;
495
+ return [value.id.trim().toLowerCase(), value.kind, sourceKind].join("\u0000");
496
+ }
497
+ /** Return the complete normalized identity of one stored dependency row. */
498
+ function storedDependencyIdentityKey(value) {
499
+ const sourceKind = value.source_kind?.trim().toLowerCase() ?? "";
500
+ const author = value.author?.trim().toLowerCase() ?? "";
501
+ const rawCreatedAt = value.created_at?.trim() ?? "";
502
+ const parsedCreatedAt = Date.parse(rawCreatedAt);
503
+ const createdAt = Number.isFinite(parsedCreatedAt)
504
+ ? new Date(parsedCreatedAt).toISOString()
505
+ : rawCreatedAt;
506
+ return [
507
+ value.id.trim().toLowerCase(),
508
+ value.kind,
509
+ sourceKind,
510
+ author,
511
+ createdAt,
512
+ ].join("\u0000");
476
513
  }
477
514
  // pm-kyd6: `--blocked-by` writes the `blocked_by` scalar, but the dependency
478
515
  // graph (`pm deps`) is built only from the `dependencies` array. Mirror the
@@ -567,6 +604,17 @@ function matchesDependencySelector(value, selector) {
567
604
  selector.source_kind.trim().toLowerCase()) {
568
605
  return false;
569
606
  }
607
+ if (selector.author !== undefined &&
608
+ value.author?.trim().toLowerCase() !== selector.author.trim().toLowerCase()) {
609
+ return false;
610
+ }
611
+ if (selector.created_at !== undefined &&
612
+ (value.created_at === undefined ||
613
+ !Number.isFinite(Date.parse(value.created_at)) ||
614
+ new Date(Date.parse(value.created_at)).toISOString() !==
615
+ selector.created_at)) {
616
+ return false;
617
+ }
570
618
  return true;
571
619
  }
572
620
  function ensurePriority(raw) {
@@ -1081,10 +1129,21 @@ async function buildNoopUpdateResult(params) {
1081
1129
  warnings: ["noop_no_update_fields"],
1082
1130
  };
1083
1131
  }
1132
+ async function loadUpdateRelationshipGraph(params) {
1133
+ if (!params.fieldFlags.dep &&
1134
+ !params.fieldFlags.blockedBy &&
1135
+ !params.fieldFlags.parent &&
1136
+ !params.clearedMetadataKeys.has("parent"))
1137
+ return undefined;
1138
+ return listAllItemMetadataLight(params.pmRoot, params.settings.item_format, params.typeToFolder, undefined, params.settings.schema);
1139
+ }
1140
+ function assertUpdateHierarchyIntegrity(params) {
1141
+ if (!params.before)
1142
+ return;
1143
+ assertHierarchyMutationAllowed(params.before, params.before.map((item) => item.id === params.document.metadata.id ? params.document.metadata : item), params.document.metadata.id, (status) => isTerminalStatus(status, params.statusRegistry), resolveWorkspaceRelationshipKindRegistry());
1144
+ }
1084
1145
  async function assertUpdateTrackerInitialized(pmRoot) {
1085
- if (!(await pathExists(getSettingsPath(pmRoot)))) {
1086
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
1087
- }
1146
+ await assertInitializedTracker(pmRoot);
1088
1147
  }
1089
1148
  function assertMatchingOrderRank(options) {
1090
1149
  if (options.order !== undefined &&
@@ -1313,6 +1372,46 @@ function applyTypeOptionMutation(document, context, activeTypeName, changedField
1313
1372
  }
1314
1373
  document.metadata.type_options = validation.normalized;
1315
1374
  }
1375
+ /** Collapse duplicate rows only for identities explicitly touched by this mutation. */
1376
+ function normalizeTouchedDependencyIdentities(current, additions) {
1377
+ const touchedKeys = new Set(additions.map((entry) => dependencyKey(entry)));
1378
+ const retainedStoredIdentities = new Set();
1379
+ return current.filter((entry) => {
1380
+ if (!touchedKeys.has(dependencyKey(entry))) {
1381
+ return true;
1382
+ }
1383
+ const storedIdentity = storedDependencyIdentityKey(entry);
1384
+ if (retainedStoredIdentities.has(storedIdentity)) {
1385
+ return false;
1386
+ }
1387
+ retainedStoredIdentities.add(storedIdentity);
1388
+ return true;
1389
+ });
1390
+ }
1391
+ /** Refuse lossless removals unless every selector resolves against stored edges. */
1392
+ function assertDependencyRemovalSelectorsMatch(current, selectors, itemId) {
1393
+ const unmatchedSelectors = selectors.filter((selector) => !current.some((entry) => matchesDependencySelector(entry, selector)));
1394
+ if (unmatchedSelectors.length === 0) {
1395
+ return;
1396
+ }
1397
+ throw new PmCliError(`Dependency removal did not match ${unmatchedSelectors.length === 1 ? "a stored edge" : "stored edges"}.`, EXIT_CODE.NOT_FOUND, {
1398
+ code: "dependency_remove_no_match",
1399
+ reason: "selector_not_found",
1400
+ unmatched_selectors: unmatchedSelectors,
1401
+ available_dependencies: current.map((entry) => ({
1402
+ id: entry.id,
1403
+ kind: entry.kind,
1404
+ source_kind: entry.source_kind,
1405
+ author: entry.author,
1406
+ created_at: entry.created_at,
1407
+ })),
1408
+ why: "Failing on a zero-match selector prevents a mistyped dependency removal from being reported as successful.",
1409
+ nextSteps: [
1410
+ `Inspect the current item with: pm get ${itemId} --full`,
1411
+ "Retry --dep-remove with the exact id plus any kind, source_kind, author, or created_at selectors needed to identify one stored row.",
1412
+ ],
1413
+ });
1414
+ }
1316
1415
  function applyDependencyMutations(document, context, changedFields) {
1317
1416
  if (context.options.dep === undefined &&
1318
1417
  context.options.depRemove === undefined &&
@@ -1323,6 +1422,7 @@ function applyDependencyMutations(document, context, changedFields) {
1323
1422
  ? []
1324
1423
  : [...(document.metadata.dependencies ?? [])];
1325
1424
  if (context.dependencyUpdates.additions.length > 0) {
1425
+ nextDependencies = normalizeTouchedDependencyIdentities(nextDependencies, context.dependencyUpdates.additions);
1326
1426
  const seen = new Set(nextDependencies.map((entry) => dependencyKey(entry)));
1327
1427
  for (const addition of context.dependencyUpdates.additions) {
1328
1428
  const key = dependencyKey(addition);
@@ -1333,6 +1433,7 @@ function applyDependencyMutations(document, context, changedFields) {
1333
1433
  }
1334
1434
  }
1335
1435
  if (context.dependencyRemovals.length > 0) {
1436
+ assertDependencyRemovalSelectorsMatch(nextDependencies, context.dependencyRemovals, document.metadata.id);
1336
1437
  nextDependencies = nextDependencies.filter((entry) => !context.dependencyRemovals.some((selector) => matchesDependencySelector(entry, selector)));
1337
1438
  }
1338
1439
  if (nextDependencies.length === 0) {
@@ -1818,82 +1919,108 @@ async function runUpdateWithContext(id, options, global, execution = {}) {
1818
1919
  return routedClose;
1819
1920
  }
1820
1921
  assertMatchingOrderRank(options);
1821
- let graphBeforeUpdate = fieldFlags.dep || fieldFlags.depRemove || fieldFlags.blockedBy
1822
- ? await listAllItemMetadataLight(pmRoot, settings.item_format, typeRegistry.type_to_folder, undefined, settings.schema)
1823
- : undefined;
1824
- let lifecycleTransition;
1825
- let recurrenceHistoryContext;
1826
- const result = await mutateItemWithHistoryContextResolver({
1922
+ const relationshipRegistry = resolveWorkspaceRelationshipKindRegistry();
1923
+ const hierarchyMutationRequired = (fieldFlags.parent && !clearItemMetadataKeys.has("parent")) ||
1924
+ dependencyUpdates.additions.some((dependency) => relationshipRegistry.resolve(dependency.kind)?.hierarchy);
1925
+ const releaseHierarchyMutationLock = await acquireHierarchyMutationLock({
1827
1926
  pmRoot,
1828
- settings,
1829
- typeToFolder: typeRegistry.type_to_folder,
1830
- id,
1831
- op: resolveUpdateHistoryOperation(options, execution),
1832
1927
  author,
1833
- message: options.message,
1834
- resolveHistoryContext: () => recurrenceHistoryContext,
1835
- force: options.force,
1836
- bypassAssigneeConflict: options.ownershipMetadataBypass === true ||
1837
- options.ownershipDependencyBypass === true,
1838
- extensionFieldNames,
1839
- skipNoop: true,
1840
- mutate(document) {
1841
- lifecycleTransition = prepareRecurrenceTransition({
1842
- document,
1843
- recurrenceReason: execution.recurrenceReason,
1844
- requestedStatus: options.status,
1845
- statusRegistry,
1846
- });
1847
- recurrenceHistoryContext = lifecycleTransition
1848
- ? { recurrence: lifecycleTransition }
1849
- : undefined;
1850
- graphBeforeUpdate = graphBeforeUpdate?.map((item) => item.id === document.metadata.id
1851
- ? structuredClone(document.metadata)
1852
- : item);
1853
- return mutateUpdateDocument(document, {
1854
- options,
1855
- settings,
1856
- typeRegistry,
1857
- statusRegistry,
1858
- runtimeFieldRegistry,
1859
- extensionRegistrations,
1860
- extensionFieldNames,
1861
- clearItemMetadataKeys,
1862
- dependencyUpdates,
1863
- dependencyRemovals,
1864
- commentUpdates,
1865
- noteUpdates,
1866
- learningUpdates,
1867
- fileUpdates,
1868
- testUpdates,
1869
- docUpdates,
1870
- resolvedParentValue: parentReference.resolvedParentValue,
1871
- resolvedBlockedByDependencyId,
1872
- runtimeFieldUpdates,
1873
- nowValue,
1874
- nowIso,
1875
- author,
1876
- pmRoot,
1877
- });
1878
- },
1928
+ ttlSeconds: settings.locks.ttl_seconds,
1929
+ waitMs: settings.locks.wait_ms,
1930
+ required: hierarchyMutationRequired,
1879
1931
  });
1880
- const orderingCycleWarnings = graphBeforeUpdate
1881
- ? collectNewOrderingCycleWarnings(graphBeforeUpdate, graphBeforeUpdate.map((item) => item.id === result.item.id ? result.item : item), result.item.id)
1882
- : [];
1883
- return {
1884
- item: toItemRecord(result.item),
1885
- changed_fields: result.changedFields,
1886
- warnings: [
1887
- ...workflowTransitionWarnings,
1888
- ...parentReferenceWarnings,
1889
- ...dependencyTargetWarnings,
1890
- ...orderingCycleWarnings,
1891
- ...result.warnings,
1892
- ],
1893
- ...(lifecycleTransition === undefined
1894
- ? {}
1895
- : { lifecycle_transition: lifecycleTransition }),
1896
- };
1932
+ try {
1933
+ let graphBeforeUpdate = await loadUpdateRelationshipGraph({
1934
+ fieldFlags,
1935
+ clearedMetadataKeys: clearItemMetadataKeys,
1936
+ pmRoot,
1937
+ settings,
1938
+ typeToFolder: typeRegistry.type_to_folder,
1939
+ });
1940
+ let lifecycleTransition;
1941
+ let recurrenceHistoryContext;
1942
+ const result = await mutateItemWithHistoryContextResolver({
1943
+ pmRoot,
1944
+ settings,
1945
+ typeToFolder: typeRegistry.type_to_folder,
1946
+ id,
1947
+ op: resolveUpdateHistoryOperation(options, execution),
1948
+ author,
1949
+ message: options.message,
1950
+ resolveHistoryContext: () => recurrenceHistoryContext,
1951
+ force: options.force,
1952
+ bypassAssigneeConflict: options.ownershipMetadataBypass === true ||
1953
+ options.ownershipDependencyBypass === true,
1954
+ extensionFieldNames,
1955
+ skipNoop: true,
1956
+ mutate(document) {
1957
+ lifecycleTransition = prepareRecurrenceTransition({
1958
+ document,
1959
+ recurrenceReason: execution.recurrenceReason,
1960
+ requestedStatus: options.status,
1961
+ statusRegistry,
1962
+ });
1963
+ recurrenceHistoryContext = lifecycleTransition
1964
+ ? { recurrence: lifecycleTransition }
1965
+ : undefined;
1966
+ graphBeforeUpdate = graphBeforeUpdate?.map((item) => item.id === document.metadata.id
1967
+ ? structuredClone(document.metadata)
1968
+ : item);
1969
+ const mutation = mutateUpdateDocument(document, {
1970
+ options,
1971
+ settings,
1972
+ typeRegistry,
1973
+ statusRegistry,
1974
+ runtimeFieldRegistry,
1975
+ extensionRegistrations,
1976
+ extensionFieldNames,
1977
+ clearItemMetadataKeys,
1978
+ dependencyUpdates,
1979
+ dependencyRemovals,
1980
+ commentUpdates,
1981
+ noteUpdates,
1982
+ learningUpdates,
1983
+ fileUpdates,
1984
+ testUpdates,
1985
+ docUpdates,
1986
+ resolvedParentValue: parentReference.resolvedParentValue,
1987
+ resolvedBlockedByDependencyId,
1988
+ runtimeFieldUpdates,
1989
+ nowValue,
1990
+ nowIso,
1991
+ author,
1992
+ pmRoot,
1993
+ });
1994
+ assertUpdateHierarchyIntegrity({
1995
+ before: graphBeforeUpdate,
1996
+ document,
1997
+ statusRegistry,
1998
+ });
1999
+ return mutation;
2000
+ },
2001
+ });
2002
+ await releaseHierarchyMutationLock();
2003
+ const orderingCycleWarnings = graphBeforeUpdate
2004
+ ? collectNewOrderingCycleWarnings(graphBeforeUpdate, graphBeforeUpdate.map((item) => item.id === result.item.id ? result.item : item), result.item.id)
2005
+ : [];
2006
+ return {
2007
+ item: toItemRecord(result.item),
2008
+ changed_fields: result.changedFields,
2009
+ warnings: [
2010
+ ...workflowTransitionWarnings,
2011
+ ...parentReferenceWarnings,
2012
+ ...dependencyTargetWarnings,
2013
+ ...orderingCycleWarnings,
2014
+ ...result.warnings,
2015
+ ],
2016
+ ...(lifecycleTransition === undefined
2017
+ ? {}
2018
+ : { lifecycle_transition: lifecycleTransition }),
2019
+ };
2020
+ }
2021
+ finally {
2022
+ await releaseHierarchyMutationLock();
2023
+ }
1897
2024
  }
1898
2025
  /** Resolve the immutable operation name for ordinary, bypass, and recurrence updates. */
1899
2026
  function resolveUpdateHistoryOperation(options, execution) {
@@ -1982,4 +2109,4 @@ export const _testOnlyUpdateCommand = {
1982
2109
  resolveRuntimeUnsetDefinition: (token, registry) => resolveRuntimeUnsetFieldDefinition(token, "update", registry),
1983
2110
  };
1984
2111
  //# sourceMappingURL=update.js.map
1985
- //# debugId=3ab4f16d-ce37-546e-a2f6-0495fd1967c7
2112
+ //# debugId=7c1729f8-4a67-5746-a1bf-351f862ceb66
@@ -4,11 +4,12 @@
4
4
  * Implements the pm linked artifacts 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]="72f57c4d-65c5-57f1-a16a-f6c970aca680")}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]="1832e2b3-0ece-523d-8f38-598303d3f590")}catch(e){}}();
8
+ import { assertInitializedTracker } from "./environment/tracker-preflight.js";
8
9
  import fs from "node:fs/promises";
9
10
  import path from "node:path";
10
11
  import fg from "fast-glob";
11
- import { isFileAbsentError, pathExists } from "../core/fs/fs-utils.js";
12
+ import { isFileAbsentError } from "../core/fs/fs-utils.js";
12
13
  import { getActiveExtensionRegistrations } from "../core/extensions/index.js";
13
14
  import { assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, parseCsvKv, } from "../core/item/parse.js";
14
15
  import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
@@ -18,7 +19,7 @@ import { PmCliError } from "../core/shared/errors.js";
18
19
  import { splitCommaList } from "../core/shared/split-comma-list.js";
19
20
  import { stableValueEquals } from "../core/shared/serialization.js";
20
21
  import { locateItem, mutateItem, readLocatedItem, } from "../core/store/item-store.js";
21
- import { getSettingsPath, resolvePmRoot, resolveWorkspaceRoot, } from "../core/store/paths.js";
22
+ import { resolvePmRoot, resolveWorkspaceRoot, } from "../core/store/paths.js";
22
23
  import { readSettings } from "../core/store/settings.js";
23
24
  import { SCOPE_VALUES } from "../types/index.js";
24
25
  import { resolveAuthor } from "../core/shared/author.js";
@@ -450,9 +451,7 @@ export async function runLinkedArtifacts(id, options, global, config) {
450
451
  const pmRoot = resolvePmRoot(process.cwd(), global.path);
451
452
  const workspaceRoot = resolveWorkspaceRoot(pmRoot);
452
453
  const invocationRoot = process.cwd();
453
- if (!(await pathExists(getSettingsPath(pmRoot)))) {
454
- throw new PmCliError(`Tracker is not initialized at ${pmRoot}. Run pm init first.`, EXIT_CODE.NOT_FOUND);
455
- }
454
+ await assertInitializedTracker(pmRoot);
456
455
  const settings = await readSettings(pmRoot);
457
456
  const typeRegistry = resolveItemTypeRegistry(settings, getActiveExtensionRegistrations());
458
457
  const resolvedAdds = await stdinResolver.resolveList(options.add, "--add");
@@ -539,4 +538,4 @@ export function renameArtifactsResultKey(result, key) {
539
538
  return out;
540
539
  }
541
540
  //# sourceMappingURL=linked-artifacts.js.map
542
- //# debugId=72f57c4d-65c5-57f1-a16a-f6c970aca680
541
+ //# debugId=1832e2b3-0ece-523d-8f38-598303d3f590