@unbrained/pm-cli 2026.8.23 → 2026.8.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +27 -1
  3. package/dist/cli/description-stdin.js +5 -4
  4. package/dist/cli/extension-command-help.d.ts +5 -0
  5. package/dist/cli/extension-command-help.js +6 -2
  6. package/dist/cli/help-content.d.ts +5 -0
  7. package/dist/cli/help-content.js +56 -3
  8. package/dist/cli/help-json-payload.d.ts +5 -2
  9. package/dist/cli/help-json-payload.js +57 -17
  10. package/dist/cli/main.d.ts +3 -0
  11. package/dist/cli/main.js +28 -3
  12. package/dist/cli/register-annotations.js +5 -5
  13. package/dist/cli/register-mutation.js +73 -27
  14. package/dist/cli-bundle/bundle-manifest.json +152 -152
  15. package/dist/cli-bundle/chunks/{chunk-HWZ6CELB.js → chunk-244MI4GS.js} +3 -3
  16. package/dist/cli-bundle/chunks/{chunk-QDVHNHAQ.js → chunk-2F3LUFMW.js} +2 -2
  17. package/dist/cli-bundle/chunks/{chunk-EG6CLDZT.js → chunk-5I5RWIJC.js} +2 -2
  18. package/dist/cli-bundle/chunks/{chunk-KPH73XXJ.js → chunk-65MHLHAA.js} +2 -2
  19. package/dist/cli-bundle/chunks/chunk-6C7GIMIL.js +13 -0
  20. package/dist/cli-bundle/chunks/chunk-OWHNAR2B.js +2 -0
  21. package/dist/cli-bundle/chunks/chunk-QKGMHGEI.js +202 -0
  22. package/dist/cli-bundle/chunks/chunk-QLUORNIB.js +2092 -0
  23. package/dist/cli-bundle/chunks/{chunk-JB4KZWBF.js → chunk-T2ENPRXF.js} +2 -2
  24. package/dist/cli-bundle/chunks/{chunk-F3AI2JFL.js → chunk-TPQIBSL2.js} +2 -2
  25. package/dist/cli-bundle/chunks/chunk-YQMYF3YD.js +35 -0
  26. package/dist/cli-bundle/chunks/{register-list-query-UJB5FMV2.js → register-list-query-XVN2ZLI7.js} +2 -2
  27. package/dist/cli-bundle/chunks/register-mutation-QCKAEGIJ.js +20 -0
  28. package/dist/cli-bundle/chunks/{register-operations-RXIJIYXC.js → register-operations-SDEAXE7E.js} +2 -2
  29. package/dist/cli-bundle/chunks/{register-setup-GFUZEKRE.js → register-setup-LXVBRCJ3.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-QGFNI65N.js → chunk-2UIWOP3O.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/chunk-42S3GGZ7.js +50 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-OGLQBL46.js → chunk-7I23XGWO.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/chunk-7YCDTCBC.js +2 -0
  34. package/dist/cli-bundle/focused-chunks/{chunk-OFVUGTLJ.js → chunk-A644DUFQ.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/{chunk-AUFH5H35.js → chunk-GQR3WH3F.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/{chunk-3UPTYG44.js → chunk-H5JZEIQV.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/chunk-IBZZZGK3.js +2 -0
  38. package/dist/cli-bundle/focused-chunks/chunk-LMKG3DFE.js +5 -0
  39. package/dist/cli-bundle/focused-chunks/{chunk-LYVSW5VM.js → chunk-N7W67YIG.js} +2 -2
  40. package/dist/cli-bundle/focused-chunks/{chunk-37Z4OEAP.js → chunk-NOOZGIXP.js} +2 -2
  41. package/dist/cli-bundle/focused-chunks/{chunk-FZS4H32O.js → chunk-OHIHZ7HS.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-ONYQCALA.js +19 -0
  43. package/dist/cli-bundle/focused-chunks/chunk-OVJL6NZE.js +4 -0
  44. package/dist/cli-bundle/focused-chunks/chunk-RAFKLNZX.js +16 -0
  45. package/dist/cli-bundle/focused-chunks/{chunk-IFLWKY2R.js → chunk-VXWATRFL.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/{chunk-R27IDGHD.js → chunk-XUQPEKRN.js} +2 -2
  47. package/dist/cli-bundle/focused-chunks/{chunk-JOWDB2MH.js → chunk-YO3ZF3FI.js} +2 -2
  48. package/dist/cli-bundle/main.js +18 -17
  49. package/dist/cli-bundle/sdk-authoring.js +1 -1
  50. package/dist/cli-bundle/sdk-contracts.js +2 -2
  51. package/dist/cli-bundle/sdk-core.js +32 -32
  52. package/dist/cli-bundle/sdk-governance.js +1 -1
  53. package/dist/cli-bundle/sdk-graph.js +1 -1
  54. package/dist/cli-bundle/sdk-merge.js +32 -33
  55. package/dist/cli-bundle/sdk-query.js +1 -1
  56. package/dist/cli-bundle/sdk-runtime.js +1 -1
  57. package/dist/cli-bundle/sdk-testing.js +1 -1
  58. package/dist/cli-bundle/sdk.js +6 -5
  59. package/dist/core/diagnostics/remediation.js +17 -2
  60. package/dist/core/extensions/command-metadata-contract.d.ts +10 -0
  61. package/dist/core/extensions/command-metadata-contract.js +23 -0
  62. package/dist/core/extensions/command-visibility-tier.js +12 -2
  63. package/dist/core/extensions/extension-types.d.ts +6 -0
  64. package/dist/core/extensions/extension-types.js +2 -2
  65. package/dist/core/extensions/loader.js +4 -3
  66. package/dist/core/io/body-file.js +7 -2
  67. package/dist/core/io/bulk-ids-input.d.ts +24 -0
  68. package/dist/core/io/bulk-ids-input.js +113 -0
  69. package/dist/core/item/parse.d.ts +22 -2
  70. package/dist/core/item/parse.js +97 -4
  71. package/dist/mcp/server.d.ts +3 -2
  72. package/dist/mcp/server.js +16 -9
  73. package/dist/sdk/agent/refusal-closure-census.d.ts +66 -0
  74. package/dist/sdk/agent/refusal-closure-census.js +144 -0
  75. package/dist/sdk/agent-capability-contracts.d.ts +34 -1
  76. package/dist/sdk/agent-capability-contracts.js +104 -6
  77. package/dist/sdk/annotations.d.ts +2 -0
  78. package/dist/sdk/annotations.js +25 -7
  79. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +10 -0
  80. package/dist/sdk/cli-contracts/runtime-contracts.js +20 -3
  81. package/dist/sdk/cli-contracts/tool-parameter-tables.js +38 -2
  82. package/dist/sdk/cli-contracts/typed-action-inputs.d.ts +4 -1
  83. package/dist/sdk/cli-contracts/typed-action-inputs.js +2 -2
  84. package/dist/sdk/comments.js +15 -7
  85. package/dist/sdk/flag-invocation-contracts.d.ts +2 -0
  86. package/dist/sdk/flag-invocation-contracts.js +28 -3
  87. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +109 -52
  88. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +62 -2
  89. package/dist/sdk/governance/health.js +98 -11
  90. package/dist/sdk/governance/validate.js +15 -9
  91. package/dist/sdk/guide-topics.d.ts +0 -5
  92. package/dist/sdk/guide-topics.js +28 -2
  93. package/dist/sdk/history-compact.d.ts +2 -1
  94. package/dist/sdk/history-compact.js +24 -5
  95. package/dist/sdk/history-mcp.js +11 -10
  96. package/dist/sdk/history-repair.d.ts +24 -0
  97. package/dist/sdk/history-repair.js +145 -4
  98. package/dist/sdk/index.d.ts +1 -0
  99. package/dist/sdk/index.js +3 -2
  100. package/dist/sdk/item-transaction.js +19 -12
  101. package/dist/sdk/lifecycle/append.js +4 -4
  102. package/dist/sdk/lifecycle/close-many.js +16 -7
  103. package/dist/sdk/lifecycle/create.js +29 -21
  104. package/dist/sdk/lifecycle/plan.js +24 -6
  105. package/dist/sdk/lifecycle/update-many.js +15 -8
  106. package/dist/sdk/lifecycle/update.d.ts +2 -0
  107. package/dist/sdk/lifecycle/update.js +34 -24
  108. package/dist/sdk/merge/driver.js +25 -4
  109. package/dist/sdk/merge/receipt-file-boundary.d.ts +21 -0
  110. package/dist/sdk/merge/receipt-file-boundary.js +47 -0
  111. package/dist/sdk/merge/receipts.d.ts +24 -1
  112. package/dist/sdk/merge/receipts.js +342 -36
  113. package/dist/sdk/merge/reconcile.js +117 -47
  114. package/dist/sdk/read-output/continuation.d.ts +15 -2
  115. package/dist/sdk/read-output/continuation.js +86 -6
  116. package/dist/sdk/read-output-contracts.d.ts +4 -1
  117. package/dist/sdk/read-output-contracts.js +9 -6
  118. package/dist/sdk/runtime-extended-actions.js +5 -3
  119. package/dist/sdk/runtime-input.d.ts +4 -0
  120. package/dist/sdk/runtime-input.js +98 -23
  121. package/dist/sdk/runtime-primitives.d.ts +2 -1
  122. package/dist/sdk/runtime-primitives.js +4 -3
  123. package/dist/sdk/runtime.js +7 -20
  124. package/dist/sdk/scheduling-shortcuts.js +5 -3
  125. package/dist/sdk/structured-mutations.js +10 -3
  126. package/dist/sdk/workspace-contracts.d.ts +3 -0
  127. package/dist/sdk/workspace-contracts.js +3 -2
  128. package/docs/MERGE_SAFETY.md +34 -5
  129. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +13 -1
  130. package/docs/README.md +2 -0
  131. package/docs/READ_OUTPUT_CONTRACTS.md +25 -2
  132. package/docs/RELEASING.md +40 -21
  133. package/docs/SCRIPTING.md +62 -3
  134. package/docs/SDK.md +8 -0
  135. package/docs/generated/AGENT_CAPABILITY_ROUTING.md +17 -0
  136. package/docs/generated/AGENT_COMMAND_SURFACE.md +1 -1
  137. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +359 -0
  138. package/marketplace.json +2 -2
  139. package/package.json +1 -1
  140. package/packages/pm-beads/package.json +1 -1
  141. package/packages/pm-calendar/package.json +1 -1
  142. package/packages/pm-command-kit/README.md +9 -11
  143. package/packages/pm-command-kit/extensions/command-kit/index.ts +3 -1
  144. package/packages/pm-command-kit/package.json +1 -1
  145. package/packages/pm-digital-twin/package.json +1 -1
  146. package/packages/pm-governance-audit/package.json +1 -1
  147. package/packages/pm-guide-shell/extensions/guide-shell/index.ts +10 -0
  148. package/packages/pm-guide-shell/package.json +1 -1
  149. package/packages/pm-kanban/package.json +1 -1
  150. package/packages/pm-lifecycle-hooks/package.json +1 -1
  151. package/packages/pm-linked-test-adapters/package.json +1 -1
  152. package/packages/pm-search-advanced/package.json +1 -1
  153. package/packages/pm-templates/package.json +1 -1
  154. package/packages/pm-todos/package.json +1 -1
  155. package/packages/pm-vcs/package.json +1 -1
  156. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  157. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  158. package/scripts/generate-agent-capability-surfaces.mjs +27 -1
  159. package/sdk/public-surface.json +351 -26
  160. package/dist/cli-bundle/chunks/chunk-3ENVHX6C.js +0 -36
  161. package/dist/cli-bundle/chunks/chunk-DW2CGEMU.js +0 -2
  162. package/dist/cli-bundle/chunks/chunk-HZBMLSZI.js +0 -201
  163. package/dist/cli-bundle/chunks/chunk-KXPMB2YL.js +0 -2092
  164. package/dist/cli-bundle/chunks/chunk-TFI5V5N2.js +0 -13
  165. package/dist/cli-bundle/chunks/register-mutation-NX5XE4VX.js +0 -20
  166. package/dist/cli-bundle/focused-chunks/chunk-5S7E72FY.js +0 -16
  167. package/dist/cli-bundle/focused-chunks/chunk-E7X25GC3.js +0 -2
  168. package/dist/cli-bundle/focused-chunks/chunk-FQCSTBWE.js +0 -4
  169. package/dist/cli-bundle/focused-chunks/chunk-MRCNF3U6.js +0 -2
  170. package/dist/cli-bundle/focused-chunks/chunk-OY7QAV4Y.js +0 -51
  171. package/dist/cli-bundle/focused-chunks/chunk-UYRFYCDQ.js +0 -5
  172. package/dist/cli-bundle/focused-chunks/chunk-ZHVA42R5.js +0 -18
@@ -1,5 +1,6 @@
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]="32223457-5f57-5049-99cf-c5d766413fb6")}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]="c7c75b13-7317-5089-9869-7e6e22ed95b2")}catch(e){}}();
3
+ import { transferMutationStdinTokenPolicy, } from "./runtime-primitives.js";
3
4
  import { runCreate, } from "./lifecycle/create.js";
4
5
  const DEFAULT_DURATION = "1h";
5
6
  const DEFAULT_START = "now";
@@ -10,7 +11,7 @@ function appendQuotedPair(pairs, key, value) {
10
11
  }
11
12
  }
12
13
  function buildCommonOptions(type, title, options) {
13
- return {
14
+ const createOptions = {
14
15
  type,
15
16
  title,
16
17
  schedulePreset: "lightweight",
@@ -23,6 +24,7 @@ function buildCommonOptions(type, title, options) {
23
24
  author: options.author,
24
25
  message: options.message,
25
26
  };
27
+ return transferMutationStdinTokenPolicy(options, createOptions);
26
28
  }
27
29
  async function createMeetingOrEvent(type, title, options, global) {
28
30
  const createOptions = buildCommonOptions(type, title, options);
@@ -59,4 +61,4 @@ export function runRemind(title, options, global) {
59
61
  return runCreate(createOptions, global);
60
62
  }
61
63
  //# sourceMappingURL=scheduling-shortcuts.js.map
62
- //# debugId=32223457-5f57-5049-99cf-c5d766413fb6
64
+ //# debugId=c7c75b13-7317-5089-9869-7e6e22ed95b2
@@ -5,9 +5,10 @@
5
5
  * transaction contract and normalizes full item documents for CLI round trips.
6
6
  */
7
7
 
8
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="07876c03-63a8-5c69-9c6c-c3446076a382")}catch(e){}}();
8
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="3f348972-0c8f-52da-abeb-46690df967d8")}catch(e){}}();
9
9
  import crypto from "node:crypto";
10
10
  import { normalizeItemId, normalizePrefix } from "../core/item/id.js";
11
+ import { preserveMutationStdinTokenLiterals } from "../core/item/parse.js";
11
12
  import { EXIT_CODE, ITEM_PROJECT_CONTEXT_KEYS, } from "../core/shared/constants.js";
12
13
  import { PmCliError } from "../core/shared/errors.js";
13
14
  import { levenshteinDistanceWithinLimit } from "../core/shared/levenshtein.js";
@@ -244,7 +245,13 @@ export function parseItemMutationBatch(input) {
244
245
  if (rows === undefined || rows.length === 0) {
245
246
  throw new PmCliError("Mutation batch must be a non-empty JSON array or an object with a non-empty mutations array.", EXIT_CODE.USAGE);
246
247
  }
247
- return rows.map((row, index) => validateMutationRow(row, index));
248
+ return rows.map((row, index) => {
249
+ const mutation = validateMutationRow(row, index);
250
+ if (mutation.options !== undefined) {
251
+ preserveMutationStdinTokenLiterals(mutation.options);
252
+ }
253
+ return mutation;
254
+ });
248
255
  }
249
256
  function deriveReferencedItemId(transactionId, reference, idPrefix) {
250
257
  const digest = crypto
@@ -571,4 +578,4 @@ export function validateItemMutationRows(value) {
571
578
  return parseItemMutationBatch(JSON.stringify(value));
572
579
  }
573
580
  //# sourceMappingURL=structured-mutations.js.map
574
- //# debugId=07876c03-63a8-5c69-9c6c-c3446076a382
581
+ //# debugId=3f348972-0c8f-52da-abeb-46690df967d8
@@ -4,6 +4,7 @@
4
4
  * Declares live workspace customization metadata for SDK and MCP consumers.
5
5
  */
6
6
  import type { RegisteredExtensionCommandDefinition } from "../core/extensions/extension-types.js";
7
+ import type { PmCommandCapabilityFamily } from "./agent-capability-contracts.js";
7
8
  import { type RuntimeFieldDefinitionResolved } from "../core/schema/runtime-schema.js";
8
9
  import type { RuntimeFieldType } from "../types/index.js";
9
10
  /** Runtime custom-field metadata exposed to SDK and MCP consumers. */
@@ -46,6 +47,8 @@ export interface WorkspaceExtensionCommandContract {
46
47
  description?: string;
47
48
  /** Minimum agent surface tier requested by the extension. */
48
49
  tier: "core" | "standard" | "full" | "internal";
50
+ /** Capability family declared by the extension. */
51
+ family: PmCommandCapabilityFamily;
49
52
  }
50
53
  /** Project resolved custom-field definitions into the public workspace shape. */
51
54
  export declare function buildWorkspaceFieldContracts(definitions: RuntimeFieldDefinitionResolved[]): WorkspaceFieldContract[];
@@ -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]="b9eae1a3-3eb6-5415-86c3-a8e8e1fedd1f")}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]="10052b6f-216f-5b50-81ec-ee373cc13d17")}catch(e){}}();
3
3
  import { runtimeFieldOptionTarget, } from "../core/schema/runtime-schema.js";
4
4
  /** Project resolved custom-field definitions into the public workspace shape. */
5
5
  export function buildWorkspaceFieldContracts(definitions) {
@@ -27,7 +27,8 @@ export function buildWorkspaceExtensionCommandContracts(definitions) {
27
27
  })),
28
28
  description: definition.description,
29
29
  tier: definition.tier ?? "standard",
30
+ family: definition.family ?? "extensions",
30
31
  }));
31
32
  }
32
33
  //# sourceMappingURL=workspace-contracts.js.map
33
- //# debugId=b9eae1a3-3eb6-5415-86c3-a8e8e1fedd1f
34
+ //# debugId=10052b6f-216f-5b50-81ec-ee373cc13d17
@@ -2,6 +2,9 @@
2
2
 
3
3
  Tracked by [pm-wc1r](../.agents/pm/features/pm-wc1r.toon), with the integrity and concurrency fixes [pm-9q2t](../.agents/pm/issues/pm-9q2t.toon), [pm-cxyv](../.agents/pm/issues/pm-cxyv.toon), [pm-gpo7](../.agents/pm/issues/pm-gpo7.toon), [pm-m3nl](../.agents/pm/issues/pm-m3nl.toon), [pm-wwfd](../.agents/pm/issues/pm-wwfd.toon), and [pm-xdn6](../.agents/pm/issues/pm-xdn6.toon). Fresh-init fence ownership is tracked by [pm-1w3ljt](../.agents/pm/issues/pm-1w3ljt.toon); runtime-cache index governance by [pm-hous](../.agents/pm/issues/pm-hous.toon); local allocation safety by [pm-khdq](../.agents/pm/issues/pm-khdq.toon); fence-coverage completeness and drift detection by [pm-i4fx](../.agents/pm/issues/pm-i4fx.toon); package-defined item coverage by [pm-5rexki](../.agents/pm/issues/pm-5rexki.toon); non-item JSON coverage by [pm-gjicmx](../.agents/pm/issues/pm-gjicmx.toon); portable driver identity by [pm-w91mvg](../.agents/pm/issues/pm-w91mvg.toon); pending receipt validation by [pm-ysqb6n](../.agents/pm/issues/pm-ysqb6n.toon); receipt classification by [pm-jtwsct](../.agents/pm/issues/pm-jtwsct.toon); direction-independent item conflict selection by [pm-dlx7v7](../.agents/pm/issues/pm-dlx7v7.toon); corrected reconciliation guidance by [pm-lwmstb](../.agents/pm/issues/pm-lwmstb.toon); cross-branch id collision safety by [pm-pibw](../.agents/pm/issues/pm-pibw.toon); auditable merge history by [pm-9j2r3b](../.agents/pm/tasks/pm-9j2r3b.toon); durable conflict decisions by [pm-rh98vo](../.agents/pm/issues/pm-rh98vo.toon); continuous conformance by [pm-76dnfg](../.agents/pm/tasks/pm-76dnfg.toon); workspace-wide CI enforcement by [pm-pdr8t1](../.agents/pm/tasks/pm-pdr8t1.toon); post-merge reconciliation by [pm-mfkv92](../.agents/pm/issues/pm-mfkv92.toon); linked-command execution trust by [pm-ed28wi](../.agents/pm/issues/pm-ed28wi.toon); this repository's own adoption by [pm-iwsj](../.agents/pm/chores/pm-iwsj.toon).
4
4
 
5
+ Lossless receipt health gating is tracked by
6
+ [pm-baksix](../.agents/pm/issues/pm-baksix.toon).
7
+
5
8
  pm stores project context as reviewable repository files. Concurrent agents can therefore use ordinary branches and worktrees, but tracker artifacts need semantic merge behavior: raw line merging cannot preserve TOON collection counts, JSON object structure, or append-only history hash chains.
6
9
 
7
10
  ## Install the repository merge contract
@@ -118,11 +121,37 @@ pm merge reconcile --force --message "Accept reviewed merge decisions" --json
118
121
  ```
119
122
 
120
123
  The preview reports every drifted stream and pending receipt without mutation.
121
- Lossless receipts are reported as provenance but do not become blocking merge
122
- decisions. Receipts with discarded scalar values remain blocking and the apply
123
- pass refuses them unless the coordinator explicitly supplies `--force` after
124
- review. This prevents a routine history repair from silently accepting data
125
- loss while preserving a zero-noise path for merges that retained both changes.
124
+ Lossless receipts do not become discarded-value decisions and reconcile without
125
+ `--force`, but `pm health` reports `merge_receipts_pending:<n>` and remains
126
+ non-green until the apply pass settles them. `pm history-repair` cannot clear
127
+ that receipt finding. When a drifted item also has a pending receipt, the
128
+ `history_drift` remediation map prioritizes `pm merge reconcile --dry-run` only
129
+ when canonical item path, changed-field, and merged-value hash evidence all
130
+ attribute that finding to one or more receipts loaded from the clone-local Git
131
+ evidence store. Every field declared by each receipt must match its current merged-value
132
+ hash, even when only a subset appears in the history reconciliation diff.
133
+ Disjoint valid receipts may collectively cover a multi-field reconciliation;
134
+ the audit and settlement then retain every individually proven receipt id.
135
+ Serialized source claims are ignored. Receipt readers validate the complete
136
+ bounded schema, safe identifiers, filename and item-path identity, timestamps,
137
+ and bounded decision structure before a sidecar enters health or
138
+ reconciliation. Reads use size-preflighted, no-follow regular-file descriptors;
139
+ durable decisions must retain hash-only values. Legacy or durable-only receipts,
140
+ receipts whose declared fields disagree with their hashes, same-item tampering,
141
+ and drift on unrelated items fail closed to the normal `pm history-repair`
142
+ guidance. Health indexes clone-local evidence once by item and reconciliation
143
+ uses the same per-item groups with a fixed receipt-only worker pool, so committed
144
+ sidecars cannot amplify drift scans into unbounded parallel repair work.
145
+ Apply-mode reconciliation repeats the same proof against the exact
146
+ item snapshot used by the audited history rewrite. The audit event and
147
+ settlement include only the individually proven receipt id, so one valid receipt
148
+ cannot authorize an untrusted same-item sibling. Failed or unproven receipts
149
+ remain pending unless the coordinator explicitly reviews and supplies `--force`.
150
+ Receipts with discarded scalar values retain the distinct
151
+ `merge_decisions_unreviewed:<n>` finding, and the apply pass refuses them unless
152
+ the coordinator explicitly supplies `--force` after review. This prevents a
153
+ routine history repair from hiding unfinished reconciliation or silently
154
+ accepting data loss.
126
155
  It exits nonzero while either merge-critical validation check is non-green, so
127
156
  CI and explicit post-merge hooks cannot approve unresolved receipts or drift.
128
157
  The apply pass uses the audited history rewrite boundary to append a
@@ -16,7 +16,10 @@ selectors are tracked by
16
16
  and canonical TOON tables are tracked by
17
17
  [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon) and
18
18
  [pm-5y05kq](../.agents/pm/issues/pm-5y05kq.toon). Nested evidence continuation
19
- is tracked by [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon).
19
+ is tracked by [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon) and
20
+ [pm-oahhyc](../.agents/pm/issues/pm-oahhyc.toon). Exact command-local
21
+ projection discovery is tracked by
22
+ [pm-q4isdq](../.agents/pm/issues/pm-q4isdq.toon).
20
23
 
21
24
  ## Agent Quick Context
22
25
 
@@ -112,6 +115,15 @@ machine-iterable without a command-specific selector. `fields` is always explici
112
115
  shape. NDJSON event streams do not carry an envelope and therefore do not
113
116
  publish a row contract.
114
117
 
118
+ Projection mode discovery is command-local even though the compatibility
119
+ degradation ladder is global. Read
120
+ `output_projection_contracts.commands` from a command-scoped contracts call or
121
+ the full contracts matrix before selecting a whole-result mode. The
122
+ contract labels the global ladder `union_not_per_command`, so clients cannot
123
+ infer that `list` accepts `summary` or that `health` accepts `compact`.
124
+ `PM_READ_OUTPUT_SURFACE_CONTRACTS[].projection_modes` provides the identical
125
+ canonical matrix to SDK and package consumers.
126
+
115
127
  SDK and package authors can import `PM_READ_ROW_CONTRACTS`,
116
128
  `PM_READ_ROW_JQ_SELECTOR`, and `resolveReadRowContract` from
117
129
  `@unbrained/pm-cli/sdk`. Existing package declarations are preserved only
package/docs/README.md CHANGED
@@ -50,6 +50,8 @@ pm guide release --json
50
50
  - [Output Token Accounting](OUTPUT_TOKEN_ACCOUNTING.md) - opt-in CLI/MCP byte attribution, bounded receipt overhead, and release-level tokens-per-task baselines.
51
51
  - [SDK Context Platform](SDK_CONTEXT.md) - task-oriented entry point for authoritative reads, ranking, package workflows, diagnostics, recovery, and verification.
52
52
  - [Self-Describing Context Contracts](SELF_DESCRIBING_CONTEXT_CONTRACTS.md) - intent-scoped reads, semantic flag invocation metadata, visibility parity, and generated error vocabulary.
53
+ - [Generated Agent Capability Routing](generated/AGENT_CAPABILITY_ROUTING.md) - contract-derived command families shared by help, guide, skills, completion, MCP, and extensions.
54
+ - [Generated Refusal Closure Census](generated/REFUSAL_CLOSURE_CENSUS.md) - complete error-catalog join to executable refusal evidence and explicit uncovered obligations.
53
55
  - [Universal Read Output Contracts](READ_OUTPUT_CONTRACTS.md) - cross-command include, amount, cost, and encoding controls for CLI, SDK, MCP, and packages.
54
56
  - [Diagnostic Output Contracts](DIAGNOSTIC_OUTPUT_CONTRACTS.md) - action-first error budgets, deterministic degradation, SDK projection, and executable refusal assurance.
55
57
  - [Mutation Integrity](MUTATION_INTEGRITY.md) - shared CLI/SDK/MCP author, secret, append-only disposition, and stale-work guardrails.
@@ -1,6 +1,6 @@
1
1
  # Universal Read Output Contracts
2
2
 
3
- Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon), and [pm-xam9bt](../.agents/pm/issues/pm-xam9bt.toon).
3
+ Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-oahhyc](../.agents/pm/issues/pm-oahhyc.toon), [pm-q4isdq](../.agents/pm/issues/pm-q4isdq.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon), and [pm-xam9bt](../.agents/pm/issues/pm-xam9bt.toon).
4
4
 
5
5
  ## Agent Quick Context
6
6
 
@@ -60,6 +60,17 @@ removing spelling receipts and volatile run metadata. A selector that matches
60
60
  neither a declared mode nor any field on any returned row is refused with the
61
61
  legal domain, rather than returning rows with every field removed.
62
62
 
63
+ Runtime discovery publishes the same exact vocabulary before invocation.
64
+ `pm contracts --command <command> --summary` returns
65
+ `output_projection_contracts.commands`, while
66
+ `output_projection_contracts.global_ladder_scope: "union_not_per_command"`
67
+ explicitly marks `output_policy.degradation_ladder` as a cross-command union,
68
+ not a promise that every member is accepted by the selected command. For
69
+ example, `list` declares `brief`, `compact`, and `full`; `health` declares
70
+ `brief`, `full`, and `summary`. The full `read_output_dimensions` matrix also
71
+ includes `projection_modes` for every canonical read surface, including an
72
+ explicit empty array when a surface has no whole-result modes.
73
+
63
74
  ## Cross-Call Context Sessions
64
75
 
65
76
  `--output-session <json>` / `outputSession` composes the four per-call
@@ -164,6 +175,18 @@ an unbounded multi-megabyte response;
164
175
  `recovery_budget_multiplier: 1` declares that each next page retains the same
165
176
  useful-result ceiling.
166
177
 
178
+ Health continuation fingerprints use a versioned nonvolatile-snapshot policy
179
+ for the `checks` row. Command-lifecycle telemetry may refresh timestamps, queue
180
+ counters, and pending spans between pages, so the policy excludes only those
181
+ explicit direct fields from the `telemetry` row's `details`. The row identity,
182
+ verdict, enabled state, capture level, endpoint, environment overrides, probe
183
+ result, and failure errors remain fingerprinted. Every other health check also
184
+ remains fully fingerprinted; changing storage, integrity, history, or another
185
+ stable check fails closed. `PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES`
186
+ publishes the exact ignored detail fields per dynamic row. Other commands still
187
+ fingerprint every field, including fields with the same spelling, and any
188
+ policy-version change fails closed against an older cursor.
189
+
167
190
  When compaction affects a nested collection that is not declared resumable,
168
191
  the recovery budget is derived from the larger of the binding ceiling plus one
169
192
  and the measured pre-compaction result. The SDK adds a 25% envelope margin and
@@ -221,7 +244,7 @@ const result = await pm.list({
221
244
  });
222
245
  ```
223
246
 
224
- Package authors should use the exported read-output contracts instead of inventing package-local limit or projection vocabularies. `PM_READ_OUTPUT_SURFACE_CONTRACTS` is the machine-readable matrix and `resolveReadOutputDimensions` plus `applyReadOutputDimensions` are the shared execution primitives.
247
+ Package authors should use the exported read-output contracts instead of inventing package-local limit or projection vocabularies. `PM_READ_OUTPUT_SURFACE_CONTRACTS` is the machine-readable matrix, `PM_READ_OUTPUT_CONTINUATION_FINGERPRINT_POLICIES` declares stable-snapshot exceptions, and `resolveReadOutputDimensions` plus `applyReadOutputDimensions` are the shared execution primitives.
225
248
 
226
249
  ## Drift Gates
227
250
 
package/docs/RELEASING.md CHANGED
@@ -59,13 +59,13 @@ pnpm version:check
59
59
 
60
60
  ## One-Time Setup
61
61
 
62
- - Use npm provenance publishing for `.github/workflows/release.yml` so GitHub-hosted release jobs publish signed packages. Keep `id-token: write`, Node 24 or newer, npm 11.5.1 or newer, `NODE_AUTH_TOKEN` from the `release` environment `NPM_TOKEN` secret, and `npm publish --access public --provenance`. The token must authenticate as a maintainer with read-write access to `@unbrained/pm-cli`.
62
+ - Use npm trusted publishing for `.github/workflows/release.yml` so GitHub-hosted release jobs exchange their OIDC identity for a short-lived npm publish credential and publish signed packages. Keep `id-token: write`, the `release` environment, Node 24 or newer, npm 11.5.1 or newer, and `npm publish --access public --provenance`. The npm Trusted Publisher must match repository `unbraind/pm-cli`, workflow `release.yml`, and environment `release`. The release job performs a tokenless `npm publish --dry-run` OIDC exchange before the long release gates and fails early with npm's sanitized exchange diagnostic when the registry refuses the configured identity. Do not pass `registry-url` to `actions/setup-node`: its generated token-placeholder npmrc can suppress npm's OIDC exchange when no token is present. Keep `@unbrained/pm-cli` public; trusted publishing authorizes `npm publish`, not `npm access`, so restore package visibility manually before retrying if an anonymous metadata probe fails. Do not expose `NODE_AUTH_TOKEN` or `NPM_TOKEN` to the publish step; if private dependencies ever require a read token, scope it only to the install step.
63
63
  - Add `RELEASE_PAT` to the `release` environment from a maintainer token with `contents:write` and branch-protection bypass rights. Auto Release creates a checked version/changelog commit and tag on `main`; the default `GITHUB_TOKEN` has `contents:write` but cannot satisfy protected-branch required status checks for that freshly-created commit. The workflow does not persist this elevated token during checkout or dependency installation; `run-release-pipeline.mjs` scopes it to the git push process.
64
64
  - Add `SENTRY_AUTH_TOKEN` as an optional GitHub Environment or repository secret when Sentry release creation and sourcemap upload should run. Add `SENTRY_PERSONAL_ADMIN_TOKEN` for the GitHub-hosted Sentry issue-threshold gate; CI-scoped release tokens may not have issue-read scope. The release workflow skips Sentry upload cleanly when `SENTRY_AUTH_TOKEN` is absent, but fails the reliability threshold gate when `SENTRY_PERSONAL_ADMIN_TOKEN` is absent; local maintainers should still run the token-backed Sentry gate before release.
65
65
  - Keep any `release` environment compatible with free GitHub features. This repository is public, so environment secrets and tag/branch deployment rules are compatible with the free GitHub path; do not add paid-only release gates.
66
66
  - Ensure `GITHUB_TOKEN` has `contents: write` for GitHub Release creation.
67
67
  - Keep `package.json` repository, homepage, and bugs URLs aligned with `https://github.com/unbraind/pm-cli`.
68
- - Keep npm publishing compatible with provenance. The release workflow must keep `id-token: write`, a GitHub-hosted runner, Node 24 or newer, npm 11.5.1 or newer, a valid `NPM_TOKEN`, and `npm publish --access public --provenance`.
68
+ - Keep npm publishing compatible with provenance. The release workflow must keep `id-token: write`, a GitHub-hosted runner, Node 24 or newer, npm 11.5.1 or newer, tokenless public metadata probes, and `npm publish --access public --provenance` through the configured Trusted Publisher.
69
69
 
70
70
  ## Automated Daily Driver
71
71
 
@@ -88,6 +88,11 @@ Policy:
88
88
  - before dependency installation or build, auto-release verifies that the
89
89
  candidate has exact-commit analyzer results or an immutable tree-identical
90
90
  reviewed PR head with successful DeepScan and CodeFactor results
91
+ - after the automatic version commit lands, main CI accepts its parent's
92
+ analyzer evidence only when the commit is the exact immutable-tagged release
93
+ projection: the canonical commit message, every expected distribution
94
+ manifest changed by version substitution alone, and only the generated
95
+ changelog heading changed. Any other path or content still fails closed
91
96
  - `CHANGELOG.md` is generated by the latest npm `pm-changelog` package (`pm install npm:pm-changelog --project`, then `pm changelog generate --mode replace --all-release-tags`) from closed tracker items across git release tag windows and checked in CI; do not edit it by hand
92
97
  - protected-branch pushes require `RELEASE_PAT`; Auto Release fails fast before the expensive release gates when `push=true`, `dry_run=false`, and that secret is not configured
93
98
  - release reliability gating requires `SENTRY_PERSONAL_ADMIN_TOKEN` for issue-threshold checks; Auto Release fails before creating the version commit/tag when the token is missing and `push=true`, while sourcemap upload remains optional through `SENTRY_AUTH_TOKEN`
@@ -248,8 +253,9 @@ protection is enabled and enforced, and CodeFactor plus DeepScan are effective
248
253
  required contexts. That summary intentionally cannot attest the admin-only
249
254
  strict-update setting: its receipt reports `strict: null`,
250
255
  `strict_verified: false`, and `verification_scope: effective_required_checks`
251
- instead of inventing a positive result. Exact or immutable identical-tree
252
- analyzer provenance remains mandatory and is emitted beside the policy receipt,
256
+ instead of inventing a positive result. Exact, immutable identical-tree, or
257
+ fully validated deterministic-release analyzer provenance remains mandatory
258
+ and is emitted beside the policy receipt,
253
259
  so the restricted-token recovery cannot admit an unanalyzed or different-tree
254
260
  candidate. A maintainer token with administration-read access still verifies
255
261
  and reports `strict: true` through REST or paginated GraphQL. It reads the
@@ -260,9 +266,23 @@ Squash provenance additionally requires one unambiguous GitHub association to a
260
266
  closed PR merged into `main` with the release commit as its merge commit.
261
267
  Missing, ambiguous, or different-tree provenance fails closed.
262
268
 
269
+ The automatic release commit is the sole non-identical-tree derivation. The
270
+ gate requires one parent, the canonical release subject and body, an immutable
271
+ `v<version>` tag resolving to the candidate, the complete expected manifest
272
+ inventory, exact old-version to new-version substitutions in every manifest,
273
+ and an exact `Unreleased` changelog-heading replacement. It then resolves the
274
+ parent through the same exact or reviewed identical-tree analyzer contract.
275
+ Added, deleted, renamed, missing, or otherwise modified paths are refused, as
276
+ are malformed manifests, changelog edits, untagged commits, and parents without
277
+ successful analyzer evidence. The receipt reports
278
+ `analysis_source: deterministic_release_transform` and names both the release
279
+ parent and the parent's analyzer source; it never describes the changed release
280
+ tree as identical to the analyzed tree.
281
+
263
282
  The supported default-branch arrival path is a reviewed pull request. A direct
264
283
  push to `main` is releasable only if both analyzers attached successful evidence
265
- to that exact commit; when they did not, the gate explicitly refuses the
284
+ to that exact commit or it is the narrowly validated automatic release
285
+ projection above; when neither condition holds, the gate explicitly refuses the
266
286
  candidate instead of letting the next scheduled release discover the missing
267
287
  precondition after expensive work. CI runs `Release analyzer readiness (main)`
268
288
  on every product-relevant push to `main`, providing continuous visibility
@@ -325,7 +345,7 @@ git push origin v<version>
325
345
  `.github/workflows/release.yml` runs on `v*.*.*` tags and handles:
326
346
 
327
347
  - full-history checkout
328
- - manual `workflow_dispatch` by tag for recovery. An authenticated exact-version probe keeps already-published access recovery on the reviewed dispatch-time `main` source; when the immutable tag exists but npm publication never completed, recovery checks out that exact tagged source and retains the original version guard
348
+ - manual `workflow_dispatch` by tag for recovery. An isolated anonymous exact-version probe keeps already-published recovery on the reviewed dispatch-time `main` source; when the immutable tag exists but npm publication never completed, recovery checks out that exact tagged source and retains the original version guard
329
349
  - pnpm install with frozen lockfile
330
350
  - version policy and tag guard
331
351
  - secret scan
@@ -351,13 +371,12 @@ git push origin v<version>
351
371
  dispatch may do so only when its source-selection preflight pinned the
352
372
  checkout to the requested immutable tag; reviewed-main recovery continues
353
373
  to refuse publication of a missing target. Only
354
- when neither the target nor package metadata is anonymously visible does the
355
- same-tag recovery path attempt to restore public package access, because a
356
- hidden version can also return 404 to authenticated metadata reads. After a
357
- successful access recovery it rechecks anonymous metadata, then either skips
358
- the now-visible target or publishes the still-missing version. Permission,
359
- authentication, and registry failures stop the workflow instead of risking
360
- an immutable-version overwrite. The checked-out tag's `package.json` supplies
374
+ when neither the target nor package metadata is anonymously visible, the
375
+ same-tag recovery path fails closed and instructs the maintainer to restore
376
+ public package visibility outside the workflow. Trusted publishing does not
377
+ authorize package-access mutations. Permission, authentication, and registry
378
+ failures stop the workflow instead of risking an immutable-version overwrite.
379
+ The checked-out tag's `package.json` supplies
361
380
  the canonical package identity to both the publish guard and the
362
381
  post-publish npm/npx/bunx verifier so those identities cannot drift. The
363
382
  explicit stable dist-tag also preserves
@@ -415,8 +434,8 @@ Use the npm registry package for maintainer global updates. Do not use `npm inst
415
434
  `workflow_dispatch` and `tag=v<version>` (or close the current bot-created
416
435
  blocker once to trigger the guarded exact-run recovery). The workflow skips
417
436
  duplicate npm publication for an anonymously visible version. Before
418
- installing or running gates, dispatch performs an authenticated exact-version
419
- probe. An
437
+ installing or running gates, dispatch performs an isolated anonymous
438
+ exact-version probe. An
420
439
  existing version keeps the reviewed dispatch-time `main` source and cannot
421
440
  be republished. A definitive missing-version response pins the checkout to
422
441
  the existing immutable tag, reapplies the version guard, installs the managed
@@ -428,12 +447,12 @@ Use the npm registry package for maintainer global updates. Do not use `npm inst
428
447
  by rerunning the same tag workflow, document the incident and ship the code
429
448
  fix in the next UTC day's release.
430
449
  - A manual exact-tag `workflow_dispatch` recovery uses isolated anonymous
431
- registry probes before any account-level access mutation. A visible package
432
- with a missing target version proceeds directly to exact-tag publication, so
433
- a publish-capable automation token is not required to change package access.
434
- Access recovery is reserved for the ambiguous case where neither the package
435
- nor target version is anonymously visible. An already-visible immutable
436
- version is still verified and never republished. Recovery starts from the
450
+ registry probes and never mutates package access. A visible package with a
451
+ missing target version proceeds directly to exact-tag OIDC publication. When
452
+ neither the package nor target version is anonymously visible, recovery fails
453
+ closed until a maintainer restores public visibility outside the workflow. An
454
+ already-visible immutable version is still verified and never republished.
455
+ Recovery starts from the
437
456
  dispatch-time commit SHA and fails unless the dispatch ref is the repository
438
457
  default branch (`main`). It remains on that reviewed source when the exact
439
458
  npm version exists. When the version is definitively absent, it switches to
package/docs/SCRIPTING.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # CLI Scripting Contract
2
2
 
3
- Tracked by [pm-psy1](../.agents/pm/tasks/pm-psy1.toon), [pm-hqa8g1](../.agents/pm/tasks/pm-hqa8g1.toon), [pm-gknu](../.agents/pm/issues/pm-gknu.toon), [pm-999jh7](../.agents/pm/issues/pm-999jh7.toon), and [pm-srns](../.agents/pm/issues/pm-srns.toon).
3
+ Tracked by [pm-psy1](../.agents/pm/tasks/pm-psy1.toon), [pm-hqa8g1](../.agents/pm/tasks/pm-hqa8g1.toon), [pm-gknu](../.agents/pm/issues/pm-gknu.toon), [pm-999jh7](../.agents/pm/issues/pm-999jh7.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-3oq022](../.agents/pm/issues/pm-3oq022.toon), [pm-iktj](../.agents/pm/tasks/pm-iktj.toon), and [pm-kexu](../.agents/pm/issues/pm-kexu.toon).
4
4
 
5
5
  Use this contract when composing `pm` with shells, CI runners, `jq`, or another process. Exact flags remain discoverable from `pm <command> --help --json` and `pm contracts --command <command> --flags-only --json`.
6
6
 
@@ -14,8 +14,8 @@ Use this contract when composing `pm` with shells, CI runners, `jq`, or another
14
14
  | `3` | Requested tracker or resource was not found. | Correct the path or ID. |
15
15
  | `4` | State or concurrency conflict. | Refresh live state before deciding whether to retry. |
16
16
  | `5` | A required dependency operation failed. | Inspect the dependency evidence before retrying. |
17
- | `6` | The request succeeded but matched nothing to change. | Treat as success and inspect the effect receipt. |
18
- | `7` | The request succeeded and changed only part of the selected targets. | Treat as success and inspect unmatched/skipped rows. |
17
+ | `6` | The request succeeded but matched nothing to change. | Treat as success and inspect the effect receipt. |
18
+ | `7` | The request succeeded and changed only part of the selected targets. | Treat as success and inspect unmatched/skipped rows. |
19
19
 
20
20
  Exits `0`, `6`, and `7` are successful outcomes. Bulk mutation envelopes repeat
21
21
  the distinction as `outcome: effect`, `outcome: no_effect`, or `outcome:
@@ -134,6 +134,65 @@ else
134
134
  fi
135
135
  ```
136
136
 
137
+ Bulk selectors on `update-many`, `close-many`, and `history-compact` accept the
138
+ same explicit ID grammar through three CLI channels: comma/newline-delimited
139
+ argv text, `-` for stdin, and `@path` for a UTF-8 file. This makes a
140
+ read-selector-write pipeline executable without `xargs` command fan-out:
141
+
142
+ ```bash
143
+ pm list --status open,in_progress --fields id,priority --json |
144
+ jq -r '.items[] | select(.priority >= 2) | .id' |
145
+ pm update-many --ids - --priority 1 --dry-run --json
146
+
147
+ pm close-many --ids @reviewed-ids.txt \
148
+ --reason "Reviewed batch completed" --dry-run --json
149
+
150
+ pm list --status closed --fields id --json |
151
+ jq -r '.items[].id' |
152
+ pm history-compact --ids - --dry-run --json
153
+ ```
154
+
155
+ An unreadable `@path`, empty stdin, or empty file fails before the tracker is
156
+ read or mutated. `unmatched_ids` means the requested ID does not exist; an
157
+ existing ID excluded by another filter is not misreported as nonexistent.
158
+ Apply-mode exit `6`/`7` and the structured effect receipt remain authoritative.
159
+
160
+ `update-many --dry-run` may be filter-only. It returns the matched rows with an
161
+ empty `planned_update_options` object and empty per-row `changes`, which is a
162
+ bounded way to validate a selector before choosing a mutation. The same
163
+ filter-only invocation without `--dry-run` is rejected with exit `2`.
164
+
165
+ Direct SDK and MCP callers may pass `ids` as a string, a finite numeric scalar,
166
+ or an array of string and finite numeric IDs. The SDK normalizes every accepted
167
+ shape through the same stable-deduplicating parser; non-finite numbers and
168
+ unsupported explicit selector values are rejected before target selection:
169
+
170
+ ```ts
171
+ import { PmClient } from "@unbrained/pm-cli/sdk";
172
+
173
+ const pm = new PmClient({ pmRoot: ".agents/pm" });
174
+ await pm.run("update-many", {
175
+ options: {
176
+ ids: ["pm-a1b2", "pm-c3d4"],
177
+ priority: 1,
178
+ dryRun: true,
179
+ },
180
+ });
181
+ ```
182
+
183
+ File-reading text flags use the same stdin sentinel. `--body-file -` reads a
184
+ create/update body, while `comments`, `notes`, and `learnings` accept
185
+ `--file -`. Real file paths remain compatible:
186
+
187
+ ```bash
188
+ generate_body | pm create --title "Generated plan" --body-file -
189
+ render_review | pm comments pm-a1b2 --file -
190
+ ```
191
+
192
+ Each command invocation may consume stdin for only one option. Competing
193
+ stdin-backed inputs such as `--description - --body-file -` are rejected before
194
+ the stream is read.
195
+
137
196
  Use NDJSON for streaming row-by-row tools:
138
197
 
139
198
  ```bash
package/docs/SDK.md CHANGED
@@ -2046,6 +2046,8 @@ export default defineExtension({
2046
2046
  api.registerCommand({
2047
2047
  name: "hello",
2048
2048
  action: "hello",
2049
+ tier: "standard",
2050
+ family: "extensions",
2049
2051
  description: "Return a deterministic hello payload.",
2050
2052
  intent: "verify SDK extension activation",
2051
2053
  examples: ["pm hello"],
@@ -2100,6 +2102,12 @@ For a complete commands-capability package that combines `registerCommand`,
2100
2102
  `registerFlags`, and `registerParser`, see the first-party
2101
2103
  [pm-command-kit exemplar](../packages/pm-command-kit/README.md).
2102
2104
 
2105
+ Every command definition can declare its agent-surface `tier` (`core`,
2106
+ `standard`, `full`, or `internal`) and capability `family`. These are the same
2107
+ fields projected into CLI help, completion, MCP profiles, workspace contracts,
2108
+ and generated routing documentation. Omitted package values normalize to
2109
+ `standard` and `extensions`.
2110
+
2103
2111
  For a generated starter, use `pm package init ./my-package`. Pass
2104
2112
  `--capability hooks` to scaffold a command plus an `afterCommand` lifecycle
2105
2113
  reactor and a runnable `node:test` file that exercises
@@ -0,0 +1,17 @@
1
+ # Generated agent capability routing
2
+
3
+ Tracker: `pm-kxci8x`.
4
+
5
+ This file is generated from `PM_COMMAND_CAPABILITY_CONTRACTS`. Do not edit it manually.
6
+
7
+ | Capability family | Commands |
8
+ | --- | --- |
9
+ | workspace | `init`, `config`, `merge`, `schema`, `profile`, `telemetry`, `health`, `gc`, `workspace` |
10
+ | intake | `create`, `copy`, `focus`, `restore` |
11
+ | context | `list`, `aggregate`, `context`, `get`, `search`, `duplicates`, `eval`, `next`, `activity`, `stats`, `help` |
12
+ | lifecycle | `update`, `update-many`, `close`, `close-many`, `delete`, `claim`, `release`, `start-task`, `pause-task`, `close-task` |
13
+ | evidence | `history`, `events`, `history-redact`, `history-repair`, `history-compact`, `history-author-acknowledge`, `append`, `comments`, `notes`, `learnings`, `files`, `docs` |
14
+ | graph | `graph`, `deps`, `plan` |
15
+ | quality | `test`, `test-all`, `validate`, `assurance`, `contracts` |
16
+ | automation | `meet`, `event`, `remind` |
17
+ | extensions | `extension`, `package`, `packages`, `install`, `upgrade` |
@@ -4,7 +4,7 @@ This file is generated from `PM_COMMAND_CAPABILITY_CONTRACTS`. Do not edit it ma
4
4
 
5
5
  | Command | Minimum visibility tier | Capability family |
6
6
  | --- | --- | --- |
7
- | `init` | full | workspace |
7
+ | `init` | core | workspace |
8
8
  | `config` | standard | workspace |
9
9
  | `extension` | full | extensions |
10
10
  | `package` | full | extensions |