@unbrained/pm-cli 2026.8.27 → 2026.8.29

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 (148) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +49 -1
  3. package/dist/cli/error-guidance.js +61 -7
  4. package/dist/cli/register-annotations.js +58 -41
  5. package/dist/cli-bundle/bundle-manifest.json +142 -142
  6. package/dist/cli-bundle/chunks/{chunk-TNX6HC54.js → chunk-2MKLQL2E.js} +2 -2
  7. package/dist/cli-bundle/chunks/{chunk-SKXLJIEK.js → chunk-2UETTHY6.js} +49 -49
  8. package/dist/cli-bundle/chunks/{chunk-SHMDY36D.js → chunk-3TEF3HM5.js} +2 -2
  9. package/dist/cli-bundle/chunks/{chunk-SH6P7FXI.js → chunk-7SKMLSMX.js} +2 -2
  10. package/dist/cli-bundle/chunks/chunk-7X6OZEIV.js +34 -0
  11. package/dist/cli-bundle/chunks/{chunk-CVBBGWW5.js → chunk-CMIEDWAY.js} +54 -50
  12. package/dist/cli-bundle/chunks/{chunk-3OO3W6FW.js → chunk-GNWPTEBW.js} +64 -61
  13. package/dist/cli-bundle/chunks/chunk-MTTKAUBX.js +2 -0
  14. package/dist/cli-bundle/chunks/chunk-N6OR6FAR.js +13 -0
  15. package/dist/cli-bundle/chunks/{chunk-R4ETAOJC.js → chunk-TGNAA66W.js} +2 -2
  16. package/dist/cli-bundle/chunks/{chunk-52EKTW6V.js → chunk-WS2GJQVG.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-list-query-EUWM6VII.js → register-list-query-OMKJ5ONN.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-mutation-FD4HSAVU.js → register-mutation-QBSNCOY3.js} +4 -4
  19. package/dist/cli-bundle/chunks/{register-operations-HRMNFEC3.js → register-operations-UC77FQZC.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-setup-33GNICLX.js → register-setup-GLQ5SYV3.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-HC7ODMH3.js → chunk-3AVAWVZA.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-3UMBF26I.js +158 -0
  23. package/dist/cli-bundle/focused-chunks/{chunk-YVVZ3LQ6.js → chunk-73EDXGYE.js} +16 -15
  24. package/dist/cli-bundle/focused-chunks/{chunk-4BR5UU52.js → chunk-AXZ5AJAF.js} +45 -45
  25. package/dist/cli-bundle/focused-chunks/{chunk-MXTYGECH.js → chunk-G6PATS5E.js} +3 -3
  26. package/dist/cli-bundle/focused-chunks/{chunk-SUBSWYW3.js → chunk-JZYPPMXF.js} +2 -2
  27. package/dist/cli-bundle/focused-chunks/chunk-LLNTHF5X.js +2 -0
  28. package/dist/cli-bundle/focused-chunks/chunk-LYFWQMVC.js +2 -0
  29. package/dist/cli-bundle/focused-chunks/chunk-RKOKG43G.js +2 -0
  30. package/dist/cli-bundle/focused-chunks/chunk-TDK3OCX3.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-EKX37ZHA.js → chunk-THEPQMLX.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/{chunk-FC2AXLB5.js → chunk-XXOWRJZ5.js} +2 -2
  33. package/dist/cli-bundle/main.js +14 -14
  34. package/dist/cli-bundle/sdk-authoring.js +1 -1
  35. package/dist/cli-bundle/sdk-contracts.js +2 -2
  36. package/dist/cli-bundle/sdk-core.js +31 -32
  37. package/dist/cli-bundle/sdk-governance.js +1 -1
  38. package/dist/cli-bundle/sdk-graph.js +1 -1
  39. package/dist/cli-bundle/sdk-merge.js +34 -32
  40. package/dist/cli-bundle/sdk-query.js +1 -1
  41. package/dist/cli-bundle/sdk-runtime.js +1 -1
  42. package/dist/cli-bundle/sdk-testing.js +1 -1
  43. package/dist/cli-bundle/sdk.js +10 -10
  44. package/dist/core/diagnostics/remediation.js +16 -6
  45. package/dist/core/history/drift-scan.d.ts +2 -0
  46. package/dist/core/history/drift-scan.js +72 -36
  47. package/dist/core/history/history.d.ts +3 -3
  48. package/dist/core/history/history.js +5 -5
  49. package/dist/core/history/replay.d.ts +1 -1
  50. package/dist/core/history/replay.js +50 -19
  51. package/dist/core/item/actionability.d.ts +7 -1
  52. package/dist/core/item/actionability.js +44 -11
  53. package/dist/core/item/dependency-reference.d.ts +10 -0
  54. package/dist/core/item/dependency-reference.js +21 -0
  55. package/dist/core/item/parse.d.ts +4 -0
  56. package/dist/core/item/parse.js +38 -16
  57. package/dist/core/shared/author.js +69 -17
  58. package/dist/mcp/tool-definitions.js +5 -5
  59. package/dist/sdk/agent/command-recovery.js +3 -3
  60. package/dist/sdk/agent/task-transcript-contracts.d.ts +52 -0
  61. package/dist/sdk/agent/task-transcript-contracts.js +198 -0
  62. package/dist/sdk/annotations.d.ts +5 -2
  63. package/dist/sdk/annotations.js +66 -36
  64. package/dist/sdk/cli-bootstrap.d.ts +2 -8
  65. package/dist/sdk/cli-bootstrap.js +7 -67
  66. package/dist/sdk/cli-contracts/bootstrap-command-scanner.d.ts +23 -0
  67. package/dist/sdk/cli-contracts/bootstrap-command-scanner.js +80 -0
  68. package/dist/sdk/cli-contracts/flag-contracts.js +5 -2
  69. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +5 -5
  70. package/dist/sdk/cli-contracts/tool-parameter-tables.js +15 -2
  71. package/dist/sdk/cli-contracts/tool-schema.d.ts +1 -1
  72. package/dist/sdk/cli-contracts/tool-schema.js +16 -3
  73. package/dist/sdk/comments.d.ts +4 -0
  74. package/dist/sdk/comments.js +2 -2
  75. package/dist/sdk/completion.js +9 -5
  76. package/dist/sdk/contracts.d.ts +1 -0
  77. package/dist/sdk/contracts.js +3 -2
  78. package/dist/sdk/dependency-provenance.d.ts +51 -2
  79. package/dist/sdk/dependency-provenance.js +91 -7
  80. package/dist/sdk/extension/install-sources.d.ts +8 -1
  81. package/dist/sdk/extension/install-sources.js +132 -39
  82. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +74 -14
  83. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +86 -38
  84. package/dist/sdk/governance/health.js +86 -22
  85. package/dist/sdk/governance/validate-history-drift.js +5 -2
  86. package/dist/sdk/graph/assembly.js +51 -22
  87. package/dist/sdk/history-repair.d.ts +1 -1
  88. package/dist/sdk/history-repair.js +20 -10
  89. package/dist/sdk/index.d.ts +1 -0
  90. package/dist/sdk/index.js +3 -2
  91. package/dist/sdk/learnings.d.ts +4 -0
  92. package/dist/sdk/learnings.js +7 -4
  93. package/dist/sdk/lifecycle/close.js +4 -3
  94. package/dist/sdk/lifecycle/create.js +43 -19
  95. package/dist/sdk/linked-artifacts.js +21 -31
  96. package/dist/sdk/merge/reconcile.js +3 -16
  97. package/dist/sdk/notes.d.ts +4 -0
  98. package/dist/sdk/notes.js +2 -2
  99. package/dist/sdk/query/next.d.ts +6 -0
  100. package/dist/sdk/query/next.js +7 -2
  101. package/dist/sdk/runtime-input.js +5 -2
  102. package/dist/sdk/runtime.d.ts +6 -6
  103. package/dist/sdk/runtime.js +8 -8
  104. package/dist/sdk/test/entry.d.ts +1 -1
  105. package/dist/sdk/test/entry.js +5 -9
  106. package/dist/sdk/test/execution.d.ts +3 -0
  107. package/dist/sdk/test/execution.js +54 -13
  108. package/docs/COMMANDS.md +4 -3
  109. package/docs/CONTEXT_RECOVERY_PRIMITIVES.md +67 -0
  110. package/docs/MERGE_SAFETY.md +23 -10
  111. package/docs/OUTPUT_TOKEN_ACCOUNTING.md +20 -7
  112. package/docs/README.md +1 -0
  113. package/docs/RELEASING.md +9 -1
  114. package/docs/SDK.md +12 -0
  115. package/docs/SDK_CONTEXT_INTEGRITY.md +12 -1
  116. package/docs/SDK_RUNTIME_BOUNDARIES.md +10 -0
  117. package/docs/TESTING.md +6 -2
  118. package/docs/agent-task-token-baseline.json +97 -11
  119. package/docs/agent-task-transcripts.json +211 -0
  120. package/docs/generated/FLAG_LEXICON_BUDGETS.md +3 -3
  121. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +13 -4
  122. package/docs/performance/cli-transport-overhead.md +10 -2
  123. package/marketplace.json +2 -2
  124. package/package.json +8 -8
  125. package/packages/pm-beads/package.json +1 -1
  126. package/packages/pm-calendar/package.json +1 -1
  127. package/packages/pm-command-kit/package.json +1 -1
  128. package/packages/pm-digital-twin/package.json +1 -1
  129. package/packages/pm-governance-audit/package.json +1 -1
  130. package/packages/pm-guide-shell/package.json +1 -1
  131. package/packages/pm-kanban/package.json +1 -1
  132. package/packages/pm-lifecycle-hooks/package.json +1 -1
  133. package/packages/pm-linked-test-adapters/package.json +1 -1
  134. package/packages/pm-search-advanced/package.json +1 -1
  135. package/packages/pm-templates/package.json +1 -1
  136. package/packages/pm-todos/package.json +1 -1
  137. package/packages/pm-vcs/package.json +1 -1
  138. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  139. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  140. package/sdk/public-surface.json +297 -36
  141. package/dist/cli-bundle/chunks/chunk-MFNTKMTI.js +0 -13
  142. package/dist/cli-bundle/chunks/chunk-OS27HHBN.js +0 -35
  143. package/dist/cli-bundle/chunks/chunk-QTO7USTH.js +0 -2
  144. package/dist/cli-bundle/focused-chunks/chunk-2AGZ5BRT.js +0 -2
  145. package/dist/cli-bundle/focused-chunks/chunk-AQ5IYEZZ.js +0 -2
  146. package/dist/cli-bundle/focused-chunks/chunk-XDPYBQCF.js +0 -156
  147. package/dist/cli-bundle/focused-chunks/chunk-Y5A7SJJ7.js +0 -2
  148. package/dist/cli-bundle/focused-chunks/chunk-YHWHX6YY.js +0 -2
@@ -1,7 +1,7 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9a6974b3-63d7-5dc7-8329-0f15f0dc83ec")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="e04a91fa-4625-50fd-9bfd-c712126baf0d")}catch(e){}}();
3
3
  import { RelationshipGraph, } from "../relationships.js";
4
- import { isExternalDependencySourceKind } from "../dependency-provenance.js";
4
+ import { isExternalDependencyReference, isExternalDependencySourceKind, } from "../dependency-provenance.js";
5
5
  import { analyzeHierarchyIntegrity, } from "./hierarchy-integrity.js";
6
6
  import { resolveWorkspaceRelationshipKindRegistry } from "./workspace-relationship-kind-registry.js";
7
7
  export { resolveWorkspaceRelationshipKindRegistry } from "./workspace-relationship-kind-registry.js";
@@ -22,6 +22,25 @@ export function normalizeDependencyGraphTarget(target) {
22
22
  ? undefined
23
23
  : normalized;
24
24
  }
25
+ /** Return whether edge provenance assigns a normalized target to the external graph namespace. */
26
+ function isExternalGraphReference(target, sourceKind, externalAllowed = true) {
27
+ const normalized = normalizeDependencyReferenceTarget(target);
28
+ return (externalAllowed &&
29
+ (isExternalDependencySourceKind(sourceKind) ||
30
+ (normalized !== undefined && isExternalDependencyReference(normalized))));
31
+ }
32
+ /** Build a namespace-aware reference identity: local ids are case-folded while external locators retain case. */
33
+ function dependencyReferenceIdentityKey(target, sourceKind) {
34
+ return isExternalGraphReference(target, sourceKind)
35
+ ? `external\u0000${target}`
36
+ : `local\u0000${target.toLowerCase()}`;
37
+ }
38
+ /** Resolve one normalized edge target through the namespace selected by its provenance. */
39
+ function resolveGraphReferenceTarget(target, sourceKind, canonicalIds, externalGraphIds) {
40
+ return isExternalGraphReference(target, sourceKind)
41
+ ? externalGraphIds.get(target)
42
+ : canonicalIds.get(target.toLowerCase());
43
+ }
25
44
  /** Compare text case-insensitively with an exact-spelling deterministic tie-breaker. */
26
45
  function compareCaseFoldedText(left, right) {
27
46
  const normalizedLeft = left.toLowerCase();
@@ -45,7 +64,7 @@ function countDependencyRowIdentities(item) {
45
64
  const kind = typeof legacyDependency.kind === "string"
46
65
  ? legacyDependency.kind
47
66
  : "related";
48
- const key = `${kind}\u0000${target.toLowerCase()}`;
67
+ const key = `${kind}\u0000${dependencyReferenceIdentityKey(target, legacyDependency.source_kind)}`;
49
68
  const existing = occurrences.get(key);
50
69
  if (existing)
51
70
  existing.count += 1;
@@ -94,7 +113,9 @@ function decodeOrderingStorageContradiction(item, blocker, dependency, isTermina
94
113
  if (typeof dependency !== "object" || dependency === null)
95
114
  return undefined;
96
115
  const target = normalizeDependencyReferenceTarget(dependency.id);
97
- if (!target || target.toLowerCase() !== blocker.toLowerCase())
116
+ if (!target ||
117
+ dependencyReferenceIdentityKey(target, dependency.source_kind) !==
118
+ dependencyReferenceIdentityKey(blocker))
98
119
  return undefined;
99
120
  const definition = registry.resolve(typeof dependency.kind === "string" ? dependency.kind : "related");
100
121
  if (definition?.ordering !== true ||
@@ -151,9 +172,11 @@ export function collectDanglingDependencyReferences(items, isTerminal = (status)
151
172
  const safeItems = items.filter((item) => typeof item?.id === "string" && item.id.trim().length > 0);
152
173
  const knownIds = new Set(safeItems.map((item) => item.id.trim().toLowerCase()));
153
174
  const rows = new Map();
154
- const addReference = (item, target, kind, source) => {
175
+ const addReference = (item, target, kind, source, externalAllowed) => {
155
176
  const normalized = normalizeDependencyReferenceTarget(target);
156
- if (!normalized || knownIds.has(normalized.toLowerCase())) {
177
+ if (!normalized ||
178
+ knownIds.has(normalized.toLowerCase()) ||
179
+ isExternalGraphReference(normalized, undefined, externalAllowed)) {
157
180
  return;
158
181
  }
159
182
  const row = {
@@ -168,8 +191,8 @@ export function collectDanglingDependencyReferences(items, isTerminal = (status)
168
191
  rows.set(`${row.holder_id}::${row.target_id}::${row.kind}::${row.source}`, row);
169
192
  };
170
193
  for (const item of safeItems) {
171
- addReference(item, item.parent, "parent", "parent");
172
- addReference(item, item.blocked_by, "blocked_by", "blocked_by");
194
+ addReference(item, item.parent, "parent", "parent", false);
195
+ addReference(item, item.blocked_by, "blocked_by", "blocked_by", true);
173
196
  for (const dependency of item.dependencies ?? []) {
174
197
  // Public SDK callers may supply legacy or JSON-decoded payloads that do
175
198
  // not yet satisfy the current structured dependency contract.
@@ -182,7 +205,7 @@ export function collectDanglingDependencyReferences(items, isTerminal = (status)
182
205
  }
183
206
  addReference(item, legacyDependency.id, typeof legacyDependency.kind === "string"
184
207
  ? legacyDependency.kind
185
- : "related", "dependency");
208
+ : "related", "dependency", true);
186
209
  }
187
210
  }
188
211
  const sorted = [...rows.values()].sort((left, right) => left.holder_id.localeCompare(right.holder_id) ||
@@ -213,15 +236,21 @@ export function collectMissingDependencyTargetIds(dangling) {
213
236
  export function collectExternalDependencyTargetIds(items) {
214
237
  const targets = new Map();
215
238
  for (const item of items) {
239
+ const scalarBlocker = normalizeDependencyGraphTarget(item.blocked_by);
240
+ if (scalarBlocker &&
241
+ isExternalGraphReference(scalarBlocker) &&
242
+ !targets.has(scalarBlocker)) {
243
+ targets.set(scalarBlocker, scalarBlocker);
244
+ }
216
245
  for (const dependency of item.dependencies ?? []) {
217
246
  if (typeof dependency !== "object" ||
218
247
  dependency === null ||
219
- !isExternalDependencySourceKind(dependency.source_kind)) {
248
+ !isExternalGraphReference(dependency.id, dependency.source_kind)) {
220
249
  continue;
221
250
  }
222
- const id = normalizeDependencyReferenceTarget(dependency.id);
223
- if (id && !targets.has(id.toLowerCase())) {
224
- targets.set(id.toLowerCase(), id);
251
+ const id = normalizeDependencyGraphTarget(dependency.id);
252
+ if (id && !targets.has(id)) {
253
+ targets.set(id, id);
225
254
  }
226
255
  }
227
256
  }
@@ -230,7 +259,7 @@ export function collectExternalDependencyTargetIds(items) {
230
259
  const hierarchyIntegrityByAssembly = new WeakMap();
231
260
  /** Read the hierarchy analysis paired with an assembly created by this module. */
232
261
  export function getWorkspaceHierarchyIntegrity(assembly) {
233
- return assembly.hierarchyIntegrity ?? hierarchyIntegrityByAssembly.get(assembly);
262
+ return (assembly.hierarchyIntegrity ?? hierarchyIntegrityByAssembly.get(assembly));
234
263
  }
235
264
  /** Count raw dependency rows that use a registered compatibility alias instead of its canonical kind. */
236
265
  export function collectLegacyDependencyAliasCounts(items, registry = resolveWorkspaceRelationshipKindRegistry()) {
@@ -274,7 +303,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
274
303
  while (usedGraphIds.has(graphId.toLowerCase())) {
275
304
  graphId = `external:${graphId}`;
276
305
  }
277
- externalGraphIds.set(id.toLowerCase(), graphId);
306
+ externalGraphIds.set(id, graphId);
278
307
  usedGraphIds.add(graphId.toLowerCase());
279
308
  }
280
309
  const graphItems = safeItems.map((item) => {
@@ -287,9 +316,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
287
316
  const target = normalizeDependencyGraphTarget(dependency.id);
288
317
  if (!target)
289
318
  return [];
290
- const targetId = isExternalDependencySourceKind(dependency.source_kind)
291
- ? externalGraphIds.get(target.toLowerCase())
292
- : canonicalIds.get(target.toLowerCase());
319
+ const targetId = resolveGraphReferenceTarget(target, dependency.source_kind, canonicalIds, externalGraphIds);
293
320
  return [
294
321
  {
295
322
  id: targetId,
@@ -301,7 +328,9 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
301
328
  id: item.id.trim(),
302
329
  ...(parent ? { parent: canonicalIds.get(parent.toLowerCase()) } : {}),
303
330
  ...(blocker
304
- ? { blocked_by: canonicalIds.get(blocker.toLowerCase()) }
331
+ ? {
332
+ blocked_by: resolveGraphReferenceTarget(blocker, undefined, canonicalIds, externalGraphIds),
333
+ }
305
334
  : {}),
306
335
  dependencies,
307
336
  };
@@ -312,7 +341,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
312
341
  ...graphItems,
313
342
  ...missingIds.map((id) => ({ id })),
314
343
  ...externalIds.map((id) => ({
315
- id: externalGraphIds.get(id.toLowerCase()),
344
+ id: externalGraphIds.get(id),
316
345
  })),
317
346
  ], relationshipRegistry),
318
347
  details: [
@@ -330,7 +359,7 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
330
359
  status: "missing",
331
360
  })),
332
361
  ...externalIds.map((id) => ({
333
- id: externalGraphIds.get(id.toLowerCase()),
362
+ id: externalGraphIds.get(id),
334
363
  title: `[external] ${id}`,
335
364
  status: "external",
336
365
  })),
@@ -346,4 +375,4 @@ export function assembleWorkspaceRelationshipGraph(items, isTerminal, registry)
346
375
  return assembly;
347
376
  }
348
377
  //# sourceMappingURL=assembly.js.map
349
- //# debugId=9a6974b3-63d7-5dc7-8329-0f15f0dc83ec
378
+ //# debugId=e04a91fa-4625-50fd-9bfd-c712126baf0d
@@ -83,7 +83,7 @@ export interface MergeReceiptProofResult {
83
83
  /** Whether exact receipt identity, path, field, and value-hash evidence proves the snapshot. */
84
84
  trusted: boolean;
85
85
  /** Stable explanation for the trust decision. */
86
- reason: "trusted_clone_local_driver_evidence" | "git_workspace_unavailable" | "item_path_unavailable" | "no_item_receipts" | "no_receipt_set_proves_snapshot";
86
+ reason: "trusted_merge_driver_hash_evidence" | "git_workspace_unavailable" | "item_path_unavailable" | "no_item_receipts" | "no_receipt_set_proves_snapshot";
87
87
  /** Exact receipt identities accepted as proof; empty when proof is refused. */
88
88
  receipt_ids: string[];
89
89
  }
@@ -4,7 +4,7 @@
4
4
  * Implements the pm history repair 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]="7a21ee76-ed53-57a0-9776-c787297ed7b6")}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]="04dbdc08-ad98-543f-96dc-fde635bae92e")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "./environment/tracker-preflight.js";
9
9
  import { realpath } from "node:fs/promises";
10
10
  import path from "node:path";
@@ -27,7 +27,7 @@ import { listAllItemMetadataWithBody, readLocatedItem, } from "../core/store/ite
27
27
  import { resolvePmRoot } from "../core/store/paths.js";
28
28
  import { readSettings } from "../core/store/settings.js";
29
29
  import { resolveHistorySubject } from "./history-redact.js";
30
- import { summarizeMergeReceipt, } from "./merge/receipts.js";
30
+ import { inspectMergeReceiptEvidence, summarizeMergeReceipt, } from "./merge/receipts.js";
31
31
  import { listInvalidProvenanceHistoryStreamIds, normalizeInvalidHistoryProvenance, } from "./governance/provenance-health.js";
32
32
  function replayFieldValue(document, field) {
33
33
  return field === "body"
@@ -148,8 +148,6 @@ async function canonicalRealPath(value) {
148
148
  }
149
149
  }
150
150
  async function verifyReceiptAgainstSnapshot(params) {
151
- if (params.receipt.evidence_source !== "clone_local")
152
- return null;
153
151
  const receiptPath = await canonicalRealPath(path.resolve(params.gitWorkspaceRoot, params.receipt.item_path));
154
152
  if (receiptPath !== params.currentPath)
155
153
  return null;
@@ -159,11 +157,11 @@ async function verifyReceiptAgainstSnapshot(params) {
159
157
  ...params.receipt.union_fields,
160
158
  ...params.receipt.decisions.map((decision) => decision.field),
161
159
  ]),
162
- ].sort((left, right) => left.localeCompare(right));
160
+ ].sort();
163
161
  const hashes = params.receipt.merged_field_hashes;
164
162
  if (!hashes || declaredFields.length === 0)
165
163
  return null;
166
- const hashFields = Object.keys(hashes).sort((left, right) => left.localeCompare(right));
164
+ const hashFields = Object.keys(hashes).sort();
167
165
  if (declaredFields.length !== hashFields.length ||
168
166
  declaredFields.some((field, index) => field !== hashFields[index])) {
169
167
  return null;
@@ -214,7 +212,7 @@ async function verifyMergeReceiptProof(params) {
214
212
  reconciliationFields.every((field) => trustedFields.has(field))))) {
215
213
  return {
216
214
  trusted: true,
217
- reason: "trusted_clone_local_driver_evidence",
215
+ reason: "trusted_merge_driver_hash_evidence",
218
216
  receipt_ids: trustedReceipts.map(({ receipt }) => receipt.id),
219
217
  };
220
218
  }
@@ -225,7 +223,18 @@ async function verifyMergeReceiptProof(params) {
225
223
  };
226
224
  }
227
225
  async function resolveHistoryRepairMergeEvidence(params) {
228
- const subjectMergeReceipts = params.options.mergeReceiptProof?.receipts.filter((receipt) => receipt.item_id === params.subjectId) ?? [];
226
+ const requestedReceiptIds = new Set(params.options.mergeReceiptProof?.receipts
227
+ .filter((receipt) => receipt.item_id === params.subjectId)
228
+ .map((receipt) => receipt.id) ?? []);
229
+ const authoritativeReceiptEvidence = params.options.mergeReceiptProof
230
+ ? await inspectMergeReceiptEvidence(params.options.mergeReceiptProof.gitWorkspaceRoot ?? process.cwd(), {
231
+ includeReconciled: true,
232
+ includeLossless: true,
233
+ pmRoot: params.pmRoot,
234
+ })
235
+ : undefined;
236
+ const subjectMergeReceipts = authoritativeReceiptEvidence?.receipts.filter((receipt) => receipt.item_id === params.subjectId &&
237
+ requestedReceiptIds.has(receipt.id)) ?? [];
229
238
  const mergeReceiptProof = params.options.mergeReceiptProof
230
239
  ? await verifyMergeReceiptProof({
231
240
  proof: {
@@ -244,7 +253,7 @@ async function resolveHistoryRepairMergeEvidence(params) {
244
253
  params.options.force !== true) {
245
254
  throw new PmCliError(`Merge receipt evidence for ${params.subjectId} does not prove the exact item snapshot (${mergeReceiptProof.reason}).`, EXIT_CODE.CONFLICT, {
246
255
  code: "merge_reconcile_receipt_evidence_untrusted",
247
- required: "Use clone-local driver evidence whose canonical path, declared fields, and merged-value hashes match the current item, or review the mismatch and rerun with --force.",
256
+ required: "Use authoritative clone-local or durable receipt evidence whose canonical path, declared fields, and merged-value hashes match the current item, or review the mismatch and rerun with --force.",
248
257
  recovery: { suggested_retry: "pm merge reconcile --dry-run" },
249
258
  });
250
259
  }
@@ -405,6 +414,7 @@ export async function runHistoryRepair(id, options, global) {
405
414
  : undefined;
406
415
  const { mergeReceiptProof, effectiveAuditContext } = await resolveHistoryRepairMergeEvidence({
407
416
  options,
417
+ pmRoot,
408
418
  subjectId: subject.id,
409
419
  itemReplayContext,
410
420
  reconciliation,
@@ -581,4 +591,4 @@ export async function runHistoryRepairAll(options, global) {
581
591
  };
582
592
  }
583
593
  //# sourceMappingURL=history-repair.js.map
584
- //# debugId=7a21ee76-ed53-57a0-9776-c787297ed7b6
594
+ //# debugId=04dbdc08-ad98-543f-96dc-fde635bae92e
@@ -118,6 +118,7 @@ export * from "./query/item-filter-options.js";
118
118
  export * from "./query/parsers.js";
119
119
  export * from "./output.js";
120
120
  export * from "./output-contracts.js";
121
+ export * from "./agent/task-transcript-contracts.js";
121
122
  export * from "./relationship-analytics.js";
122
123
  export * from "./relationship-context.js";
123
124
  export * from "./relationship-history.js";
package/dist/sdk/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Defines public SDK APIs and package-author helpers for Index.
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]="ae931d1f-b7c6-5f15-aa9a-cda07f375b74")}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]="ea1845ab-34f5-5a1c-ad49-ac81495c1840")}catch(e){}}();
8
8
  export { PM_COMMAND_CAPABILITY_CONTRACTS, PM_COMMAND_VISIBILITY_CONTRACTS, PM_MCP_PROMPT_CONTRACTS, PM_MCP_RESOURCE_CONTRACTS, PM_MCP_TOOL_COMMAND_CONTRACTS, listPmCommandsForFamily, listPmCommandsForTier, listPmMcpToolsForProfile, renderPmCommandVisibilityMarkdown, resolvePmCommandCapabilityFamily, resolvePmCommandVisibilityTier, } from "./agent-capability-contracts.js";
9
9
  export * from "./mcp/protocol.js";
10
10
  export * from "./mcp/interactions.js";
@@ -115,6 +115,7 @@ export * from "./query/item-filter-options.js";
115
115
  export * from "./query/parsers.js";
116
116
  export * from "./output.js";
117
117
  export * from "./output-contracts.js";
118
+ export * from "./agent/task-transcript-contracts.js";
118
119
  export * from "./relationship-analytics.js";
119
120
  export * from "./relationship-context.js";
120
121
  export * from "./relationship-history.js";
@@ -175,4 +176,4 @@ export * from "./governance.js";
175
176
  export * from "./query.js";
176
177
  export * from "./testing.js";
177
178
  //# sourceMappingURL=index.js.map
178
- //# debugId=ae931d1f-b7c6-5f15-aa9a-cda07f375b74
179
+ //# debugId=ea1845ab-34f5-5a1c-ad49-ac81495c1840
@@ -22,6 +22,8 @@ export interface LearningsCommandOptions {
22
22
  limit?: string;
23
23
  /** Return complete learning history after a mutation instead of a bounded receipt. */
24
24
  fullHistory?: boolean;
25
+ /** Append only when no learning has the same resolved author and text. */
26
+ ifAbsent?: boolean;
25
27
  /** Value that configures or reports author for this contract. */
26
28
  author?: string;
27
29
  /** Human-readable explanation suitable for logs and agent-facing output. */
@@ -49,6 +51,8 @@ export interface LearningsResult {
49
51
  mutation_receipt?: AnnotationMutationReceipt;
50
52
  /** Declares whether older learnings were withheld from a mutation response. */
51
53
  omission_receipt?: AnnotationOmissionReceipt;
54
+ /** Whether a requested mutation changed persisted state. */
55
+ changed?: boolean;
52
56
  }
53
57
  /** Implements run learnings for the public runtime surface of this module. */
54
58
  export declare function runLearnings(id: string, options: LearningsCommandOptions, global: GlobalOptions): Promise<LearningsResult>;
@@ -1,5 +1,5 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="93184f29-f215-5413-9628-fb5b34523995")}catch(e){}}();
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="972816c9-b407-5b89-a744-249c9771451f")}catch(e){}}();
3
3
  import { parseAnnotationTextInput, resolveAnnotationInput, runAnnotationCommand, } from "./annotations.js";
4
4
  /** Implements run learnings for the public runtime surface of this module. */
5
5
  export async function runLearnings(id, options, global) {
@@ -11,11 +11,14 @@ export async function runLearnings(id, options, global) {
11
11
  deleteOp: "learning_delete",
12
12
  parseText: (raw) => parseAnnotationTextInput(raw),
13
13
  createEntry: (entry) => entry,
14
- bypassOwnershipConflict: Boolean(options.edit === undefined && options.delete === undefined &&
14
+ bypassOwnershipConflict: Boolean(options.edit === undefined &&
15
+ options.delete === undefined &&
15
16
  options.ownershipAppendBypass),
16
17
  conflictGuidance: {
17
18
  required: "For an approved append-only handoff on another owner's item, use the package-provided ownership bypass before considering --force.",
18
- examples: ['pm learnings pm-a1b2 --add "review learning" --author "reviewer" --force'],
19
+ examples: [
20
+ 'pm learnings pm-a1b2 --add "review learning" --author "reviewer" --force',
21
+ ],
19
22
  nextSteps: [
20
23
  "Use an installed package's narrow append-only ownership bypass when available.",
21
24
  "Use --force only when an ownership override is explicitly approved.",
@@ -24,4 +27,4 @@ export async function runLearnings(id, options, global) {
24
27
  });
25
28
  }
26
29
  //# sourceMappingURL=learnings.js.map
27
- //# debugId=93184f29-f215-5413-9628-fb5b34523995
30
+ //# debugId=972816c9-b407-5b89-a744-249c9771451f
@@ -4,11 +4,12 @@
4
4
  * Implements the pm close 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]="781b5118-7b07-53c7-802f-c889cb797a96")}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]="9f28f7d8-993b-5201-b606-d1eab0c3ff5c")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
9
  import { toItemRecord, isTerminalStatus, resolveItemTypeRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, PmCliError, buildItemNotFoundError, listAllItemMetadataLight, locateItem, mutateItem, readLocatedItem, resolvePmRoot, readSettings, resolveAuthor, resolveIsoOrRelative, shouldCompletePlanOnClose, getActiveExtensionRegistrations, } from "../runtime-primitives.js";
10
10
  import { collectBlockedByIds, indexBlockedByIds } from "../actionability.js";
11
11
  import { applyTerminalOrderingPolicy, requireTerminalReason, } from "../lifecycle-policy.js";
12
+ import { nowIso } from "../../core/shared/time.js";
12
13
  import { renderPmCommand } from "../command-line.js";
13
14
  const CLOSE_VALIDATION_FIELDS = [
14
15
  { key: "resolution", label: "resolution (--resolution)" },
@@ -415,7 +416,7 @@ export async function closeItem(id, closeReasonText, options, global) {
415
416
  // informational note instead of the warn/strict validation warning.
416
417
  const trackerItems = await listAllItemMetadataLight(pmRoot, settings.item_format, typeToFolder, undefined, settings.schema);
417
418
  const activeChildIds = findActiveChildIds(trackerItems, located.id, statusRegistry);
418
- const closedAt = new Date().toISOString();
419
+ const closedAt = nowIso();
419
420
  const completedAt = options.completedAt === undefined
420
421
  ? closedAt
421
422
  : resolveIsoOrRelative(options.completedAt, new Date(closedAt), "completed-at");
@@ -457,4 +458,4 @@ export function runClose(id, closeReasonText, options, global) {
457
458
  return closeItem(id, closeReasonText, options, global);
458
459
  }
459
460
  //# sourceMappingURL=close.js.map
460
- //# debugId=781b5118-7b07-53c7-802f-c889cb797a96
461
+ //# debugId=9f28f7d8-993b-5201-b606-d1eab0c3ff5c
@@ -4,9 +4,9 @@
4
4
  * Implements the pm create 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]="02c41ea1-8d4e-5239-b95a-a07210b63d7f")}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]="c9bfbfd4-3d34-5fa7-b264-6bf9ed5f7f81")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "../environment/tracker-preflight.js";
9
- import { resolveMutationStdinTokenFields } from "../../core/item/parse.js";
9
+ import { assertNoAmbiguousBareCommaEntry, looksLikeStructuredKeyValueEntry, resolveMutationStdinTokenFields, } from "../../core/item/parse.js";
10
10
  import { removeFileIfExists, writeFileAtomic, appendHistoryEntry, createHistoryEntry, generateItemId, normalizeItemId, canonicalDocument, normalizeItemMetadata, serializeItemDocument, assertParentReferenceIsNotSelf, isPlaceholderReferenceToken, normalizeParentReferenceValue, validateMissingParentReference, validateSprintOrReleaseValue, assertNoUnknownCsvKeys, looksLikeGenericKeyValueEntry, mergeAdditiveTags, parseCsvKv, parseOptionalNonNegativeInteger, parseOptionalNumber, parseTags, shouldResolveMutationStdinTokens, transferMutationStdinTokenPolicy, resolvePriority, getFocusedItem, normalizeStatusInput, isTerminalStatus, canonicalizeCommandOptionKey, commandOptionFlagLabel, resolveItemTypeRegistry, resolveCommandOptionPolicyState, resolveTypeDefinition, resolveTypeName, validateTypeOptions, acquireLock, printError, buildInvalidTypeError, resolveTypeSynonym, collectRuntimeCreateFieldValues, resolveItemTypesFilePath, resolveRuntimeFieldRegistry, resolveRuntimeStatusRegistry, EXIT_CODE, ITEM_METADATA_KEY_ORDER, PmCliError, nowIso, resolveIsoOrRelative, getActiveExtensionRegistrations, projectAfterCommandItemSnapshot, recordAfterCommandAffectedItem, runActiveCommandHandler, runActiveBeforeMutationHooks, runActiveOnWriteHooks, collectRegisteredItemFieldNames, applyRegisteredItemFieldDefaultsAndValidation, parseRegisteredItemFieldAssignments, listAllItemMetadataLight, locateItem, createMutationGuardSdk, getHistoryPath, getItemPath, resolvePmRoot, readSettings, resolveAuthor, } from "../runtime-primitives.js";
11
11
  import { requireTerminalReasonWithRecovery } from "../lifecycle-policy.js";
12
12
  import { evaluateSimilarityGovernance, similarityAdvisoryWarnings, } from "../similarity.js";
@@ -19,7 +19,7 @@ import { normalizeRiskInput, normalizeSeverityInput, parseConfidenceInput, parse
19
19
  import { applyLegacyNoneCollectionNormalizers, createLegacyNoneCollectionNormalizers, assertNoLegacyNoneToken, assertNoLegacyNoneTokens, isLegacyNoneToken, } from "./legacy-none-tokens.js";
20
20
  import { suggestNextLifecycleTransition, } from "./lifecycle-transitions.js";
21
21
  import { parseLinkedTestAssertionEqualsMap, parseLinkedTestAssertionGteMap, parseLinkedTestBoolean, parseLinkedTestContextMode, parseLinkedTestEnvClear, parseLinkedTestEnvSet, parseLinkedTestMinLines, parseLinkedTestRegexList, parseLinkedTestStringList, parseLinkedTestWorkspaceContextMode, } from "../test/parsers.js";
22
- import { looksLikeStructuredLinkedTestEntry, normalizeStructuredLinkedTestEntry, } from "../test/entry.js";
22
+ import { STRUCTURED_LINKED_TEST_KEYS, normalizeStructuredLinkedTestEntry, } from "../test/entry.js";
23
23
  import { attachLinkedTestMutationProvenance } from "../test/trust.js";
24
24
  import { COMMON_UNSET_FIELD_DEFINITIONS_AFTER_AUTHOR, COMMON_UNSET_FIELD_DEFINITIONS_BEFORE_AUTHOR, parseCommandUnsetTargets, resolveRuntimeUnsetFieldDefinition, } from "./shared-unset-fields.js";
25
25
  import { ensureEnumValue } from "./recurrence-parsers.js";
@@ -202,13 +202,7 @@ function normalizeDependencyKindInput(raw) {
202
202
  : raw;
203
203
  }
204
204
  function looksLikeStructuredEntry(raw, keys) {
205
- if (raw.startsWith("```") || raw.includes("\n")) {
206
- return true;
207
- }
208
- const keyPattern = keys
209
- .map((key) => key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
210
- .join("|");
211
- if (new RegExp(`^(?:[-*+]\\s+)?(?:${keyPattern})\\s*[:=]`, "i").test(raw)) {
205
+ if (looksLikeStructuredKeyValueEntry(raw, keys)) {
212
206
  return true;
213
207
  }
214
208
  // A first-key typo (e.g. `bogus=v,id=pm-2`) must still be parsed so the unknown
@@ -281,6 +275,7 @@ export function parseFiles(raw) {
281
275
  const values = raw.map((entry) => {
282
276
  const trimmedEntry = entry.trim();
283
277
  const isStructured = looksLikeStructuredEntry(trimmedEntry, LINKED_ARTIFACT_SEED_KEYS);
278
+ assertNoAmbiguousBareCommaEntry(trimmedEntry, "--file", "file path", isStructured);
284
279
  const kv = isStructured
285
280
  ? parseCsvKv(entry, "--file")
286
281
  : { path: trimmedEntry };
@@ -305,7 +300,9 @@ export function parseTests(raw) {
305
300
  assertNoLegacyNoneTokens(raw, "--test", "Use --clear-tests to clear linked tests.");
306
301
  const values = raw.map((entry) => {
307
302
  const trimmedEntry = entry.trim();
308
- const kv = looksLikeStructuredLinkedTestEntry(trimmedEntry)
303
+ const isStructured = looksLikeStructuredEntry(trimmedEntry, STRUCTURED_LINKED_TEST_KEYS);
304
+ assertNoAmbiguousBareCommaEntry(trimmedEntry, "--test", "test command", isStructured);
305
+ const kv = isStructured
309
306
  ? normalizeStructuredLinkedTestEntry(parseCsvKv(entry, "--test"), "--test")
310
307
  : { command: trimmedEntry };
311
308
  const command = parseOptionalString(kv.command);
@@ -1331,6 +1328,19 @@ function assertNoCreateFieldUnsetConflicts(registeredItemFieldValues, runtimeCre
1331
1328
  }
1332
1329
  }
1333
1330
  /** Throw the aggregated `missing_required_option` error when a type's required create options and/or required type-option keys were not all supplied in one invocation. Builds a type-aware valid example and staged-onboarding next steps (a strict-mode invocation also carries a compact recovery envelope). A no-op when nothing is missing. */
1331
+ /** Truthful empty-collection alternatives for strict required create fields. */
1332
+ const CLEAR_FLAG_BY_REQUIRED_CREATE_FLAG = {
1333
+ "--comment": "--clear-comments",
1334
+ "--dep": "--clear-deps",
1335
+ "--doc": "--clear-docs",
1336
+ "--event": "--clear-events",
1337
+ "--file": "--clear-files",
1338
+ "--learning": "--clear-learnings",
1339
+ "--note": "--clear-notes",
1340
+ "--reminder": "--clear-reminders",
1341
+ "--test": "--clear-tests",
1342
+ "--type-option": "--clear-type-options",
1343
+ };
1334
1344
  function assertNoMissingRequiredCreateOptions(params) {
1335
1345
  const { combinedMissingFlags, typeDefinition, missingRequiredCreateFlags, missingRequiredTypeOptionKeys, openStatus, type, createMode, missingRequiredRuntimeFields, } = params;
1336
1346
  if (combinedMissingFlags.length === 0) {
@@ -1359,12 +1369,12 @@ function assertNoMissingRequiredCreateOptions(params) {
1359
1369
  ].join(" ");
1360
1370
  const nextSteps = [
1361
1371
  `Run "pm create --help --type ${type}" for type-aware required option guidance.`,
1362
- ];
1363
- if (combinedMissingFlags.includes("--title")) {
1364
- nextSteps.push('Title can also be passed as the first positional argument (example: pm create "Your title" --type ' +
1372
+ ...combinedMissingFlags
1373
+ .filter((flag) => flag === "--title")
1374
+ .map(() => 'Title can also be passed as the first positional argument (example: pm create "Your title" --type ' +
1365
1375
  type +
1366
- ").");
1367
- }
1376
+ ")."),
1377
+ ];
1368
1378
  if (createMode === "strict") {
1369
1379
  nextSteps.push('For staged onboarding, retry with "--create-mode progressive".');
1370
1380
  if (SCHEDULE_CREATE_PRESET_TYPES.has(type)) {
@@ -1374,21 +1384,35 @@ function assertNoMissingRequiredCreateOptions(params) {
1374
1384
  if (runtimeFieldSyntax.length > 0) {
1375
1385
  nextSteps.push(`Required custom field formats: ${runtimeFieldSyntax.map((field) => field.description).join("; ")}.`);
1376
1386
  }
1387
+ const collectionClearFlags = [
1388
+ ...new Set(combinedMissingFlags.flatMap((flag) => {
1389
+ const normalizedFlag = flag.split(" ", 1)[0];
1390
+ const clearFlag = CLEAR_FLAG_BY_REQUIRED_CREATE_FLAG[normalizedFlag];
1391
+ return clearFlag ? [clearFlag] : [];
1392
+ })),
1393
+ ];
1394
+ if (collectionClearFlags.length > 0) {
1395
+ nextSteps.push(`If the truthful value is an empty collection, use ${collectionClearFlags.join(", ")} instead of inventing metadata.`);
1396
+ }
1377
1397
  const errorMessage = combinedMissingFlags.length === 1
1378
1398
  ? `Missing required option ${combinedMissingFlags[0]} for type "${type}"`
1379
1399
  : `Missing required options ${combinedMissingFlags.join(", ")} for type "${type}"`;
1380
1400
  throw new PmCliError(errorMessage, EXIT_CODE.USAGE, {
1381
1401
  code: "missing_required_option",
1382
1402
  required: `Provide all required create options and type options for type "${type}" in one invocation.`,
1383
- examples: [nextValidExample],
1403
+ examples: [
1404
+ ...collectionClearFlags.map((flag) => `pm create --type ${type} ${flag} ...`),
1405
+ nextValidExample,
1406
+ ],
1384
1407
  nextSteps,
1385
1408
  recovery: createMode === "strict"
1386
1409
  ? {
1387
1410
  recovery_mode: "compact",
1388
1411
  missing_required_fields: combinedMissingFlags,
1389
1412
  suggested_flags: [
1390
- "--create-mode progressive",
1413
+ ...collectionClearFlags,
1391
1414
  ...combinedMissingFlags,
1415
+ "--create-mode progressive",
1392
1416
  ],
1393
1417
  }
1394
1418
  : undefined,
@@ -1926,4 +1950,4 @@ export const _testOnlyCreateCommand = {
1926
1950
  typeOptionExampleValue,
1927
1951
  };
1928
1952
  //# sourceMappingURL=create.js.map
1929
- //# debugId=02c41ea1-8d4e-5239-b95a-a07210b63d7f
1953
+ //# debugId=c9bfbfd4-3d34-5fa7-b264-6bf9ed5f7f81
@@ -4,22 +4,21 @@
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]="1832e2b3-0ece-523d-8f38-598303d3f590")}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]="accd0229-6974-5950-8cea-74f517706878")}catch(e){}}();
8
8
  import { assertInitializedTracker } from "./environment/tracker-preflight.js";
9
9
  import fs from "node:fs/promises";
10
10
  import path from "node:path";
11
11
  import fg from "fast-glob";
12
12
  import { isFileAbsentError } from "../core/fs/fs-utils.js";
13
13
  import { getActiveExtensionRegistrations } from "../core/extensions/index.js";
14
- import { assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, parseCsvKv, } from "../core/item/parse.js";
14
+ import { assertNoAmbiguousBareCommaEntry, assertNoUnknownCsvKeys, createStdinTokenResolver, looksLikeGenericKeyValueEntry, parseCsvKv, } from "../core/item/parse.js";
15
15
  import { resolveItemTypeRegistry } from "../core/item/type-registry.js";
16
16
  import { isRemoteLinkedArtifactReference } from "../core/validate/linked-artifact-reference.js";
17
17
  import { EXIT_CODE } from "../core/shared/constants.js";
18
18
  import { PmCliError } from "../core/shared/errors.js";
19
- import { splitCommaList } from "../core/shared/split-comma-list.js";
20
19
  import { stableValueEquals } from "../core/shared/serialization.js";
21
20
  import { locateItem, mutateItem, readLocatedItem, } from "../core/store/item-store.js";
22
- import { resolvePmRoot, resolveWorkspaceRoot, } from "../core/store/paths.js";
21
+ import { resolvePmRoot, resolveWorkspaceRoot } from "../core/store/paths.js";
23
22
  import { readSettings } from "../core/store/settings.js";
24
23
  import { SCOPE_VALUES } from "../types/index.js";
25
24
  import { resolveAuthor } from "../core/shared/author.js";
@@ -63,7 +62,9 @@ export function looksLikeStructuredPathEntry(raw) {
63
62
  // leading assignment syntax through the structured-key allowlist so typos
64
63
  // and malformed URL-plus-note input remain atomic failures (GH-258,
65
64
  // GH-1000).
66
- const equalsIndex = raw.indexOf("=");
65
+ const firstCommaIndex = raw.indexOf(",");
66
+ const leadingSegment = raw.slice(0, firstCommaIndex >= 0 ? firstCommaIndex : raw.length);
67
+ const equalsIndex = leadingSegment.indexOf("=");
67
68
  if (equalsIndex >= 0 &&
68
69
  !/\s/u.test(raw) &&
69
70
  (/^[A-Za-z][A-Za-z0-9+.-]*:\/\//u.test(raw) ||
@@ -71,18 +72,7 @@ export function looksLikeStructuredPathEntry(raw) {
71
72
  [raw.indexOf("/"), raw.indexOf("\\")].some((separatorIndex) => separatorIndex >= 0 && separatorIndex < equalsIndex))) {
72
73
  return false;
73
74
  }
74
- return raw.includes("=") || looksLikeGenericKeyValueEntry(raw);
75
- }
76
- function expandBareCommaSeparatedAddEntries(raw) {
77
- return raw.flatMap((entry) => {
78
- const trimmed = entry.trim();
79
- if (trimmed.length === 0 ||
80
- looksLikeStructuredPathEntry(trimmed) ||
81
- !trimmed.includes(",")) {
82
- return [entry];
83
- }
84
- return splitCommaList(trimmed);
85
- });
75
+ return leadingSegment.includes("=") || looksLikeGenericKeyValueEntry(raw);
86
76
  }
87
77
  /** Whether a Markdown destination contains only balanced parentheses. */
88
78
  function hasBalancedParentheses(value) {
@@ -136,21 +126,21 @@ export function parseAddEntries(raw, bareNoun) {
136
126
  if (reference !== undefined)
137
127
  return [reference];
138
128
  }
139
- return expandBareCommaSeparatedAddEntries([entry]).map((expanded) => {
140
- const expandedTrimmed = expanded.trim();
141
- const kv = looksLikeStructuredPathEntry(expandedTrimmed)
142
- ? parseCsvKv(expanded, "--add")
143
- : { path: expandedTrimmed };
144
- assertNoUnknownCsvKeys(kv, "--add", LINKED_ARTIFACT_ADD_KEYS);
145
- if (!kv.path) {
146
- throw new PmCliError(`--add requires path=<value> or a bare ${bareNoun} path`, EXIT_CODE.USAGE);
147
- }
148
- return {
129
+ assertNoAmbiguousBareCommaEntry(trimmed, "--add", `${bareNoun} path`, looksLikeStructuredPathEntry(trimmed));
130
+ const kv = looksLikeStructuredPathEntry(trimmed)
131
+ ? parseCsvKv(entry, "--add")
132
+ : { path: trimmed };
133
+ assertNoUnknownCsvKeys(kv, "--add", LINKED_ARTIFACT_ADD_KEYS);
134
+ if (!kv.path) {
135
+ throw new PmCliError(`--add requires path=<value> or a bare ${bareNoun} path`, EXIT_CODE.USAGE);
136
+ }
137
+ return [
138
+ {
149
139
  path: kv.path,
150
140
  scope: ensureScope(kv.scope),
151
141
  note: kv.note?.trim() || undefined,
152
- };
153
- });
142
+ },
143
+ ];
154
144
  });
155
145
  }
156
146
  /** Implements parse add glob entries for the public runtime surface of this module. */
@@ -439,7 +429,7 @@ async function buildLinkedArtifactResult(params) {
439
429
  migrations_applied: params.migrationsApplied && params.migrationsApplied > 0
440
430
  ? params.migrationsApplied
441
431
  : undefined,
442
- validation: params.options.validatePaths
432
+ validation: params.options.validatePaths || params.changed
443
433
  ? await validateLinkedPaths(paths, params.workspaceRoot)
444
434
  : undefined,
445
435
  };
@@ -538,4 +528,4 @@ export function renameArtifactsResultKey(result, key) {
538
528
  return out;
539
529
  }
540
530
  //# sourceMappingURL=linked-artifacts.js.map
541
- //# debugId=1832e2b3-0ece-523d-8f38-598303d3f590
531
+ //# debugId=accd0229-6974-5950-8cea-74f517706878