@unbrained/pm-cli 2026.8.17 → 2026.8.18

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 (157) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/AGENTS.md +4 -3
  3. package/CHANGELOG.md +35 -3
  4. package/README.md +3 -3
  5. package/dist/cli/error-guidance.js +7 -4
  6. package/dist/cli/register-list-query.js +132 -51
  7. package/dist/cli-bundle/bundle-manifest.json +146 -146
  8. package/dist/cli-bundle/chunks/chunk-5UZZAJKR.js +3 -0
  9. package/dist/cli-bundle/chunks/{chunk-YM2YAMF7.js → chunk-ALDJGKAK.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-HBJAS566.js → chunk-BSK2IN3C.js} +2 -2
  11. package/dist/cli-bundle/chunks/chunk-DY4DMUMC.js +197 -0
  12. package/dist/cli-bundle/chunks/{chunk-JOKATURE.js → chunk-GNFAFIJI.js} +9 -9
  13. package/dist/cli-bundle/chunks/chunk-L5Q2CLPE.js +35 -0
  14. package/dist/cli-bundle/chunks/{chunk-TPXZIBIV.js → chunk-PVRUN5ZS.js} +2 -2
  15. package/dist/cli-bundle/chunks/{chunk-7IBRGCHX.js → chunk-RZQTVMRQ.js} +2 -2
  16. package/dist/cli-bundle/chunks/chunk-SARFF5H5.js +3 -0
  17. package/dist/cli-bundle/chunks/chunk-UYCLQVL2.js +13 -0
  18. package/dist/cli-bundle/chunks/{chunk-3UEGXBMR.js → chunk-YRGOLZA7.js} +58 -54
  19. package/dist/cli-bundle/chunks/register-list-query-I23LALEE.js +11 -0
  20. package/dist/cli-bundle/chunks/{register-mutation-4WBRPXLV.js → register-mutation-6YGU3GPH.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-operations-SSENDH5B.js → register-operations-4HTFC6J7.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-setup-DOSFBGKE.js → register-setup-PPPEF3SN.js} +2 -2
  23. package/dist/cli-bundle/focused-chunks/chunk-2PN4TJXH.js +2 -0
  24. package/dist/cli-bundle/focused-chunks/{chunk-ZQPGZZWQ.js → chunk-3TKWMNKF.js} +3 -3
  25. package/dist/cli-bundle/focused-chunks/chunk-5AF3ZBNB.js +155 -0
  26. package/dist/cli-bundle/focused-chunks/chunk-C5IW2NDA.js +2 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-SYZENPIT.js → chunk-EUEGXZ2A.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-XKAMP5OU.js → chunk-EX6MKP2X.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-CYFK5UPB.js → chunk-K43KKAFS.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/{chunk-ATEY76SX.js → chunk-M62NO7EI.js} +2 -2
  31. package/dist/cli-bundle/focused-chunks/{chunk-SALH6B6K.js → chunk-ODOVCP45.js} +5 -5
  32. package/dist/cli-bundle/focused-chunks/chunk-RNDNMARJ.js +16 -0
  33. package/dist/cli-bundle/focused-chunks/chunk-TN4AE665.js +26 -0
  34. package/dist/cli-bundle/focused-chunks/chunk-TVV2DONO.js +2 -0
  35. package/dist/cli-bundle/focused-chunks/chunk-UI6AJ5TD.js +4 -0
  36. package/dist/cli-bundle/focused-chunks/{chunk-MHPIL773.js → chunk-V5XTGLK7.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-KP2VQQVQ.js → chunk-WGHQVU6P.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-XYNBXTDQ.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/chunk-Z56ECT7I.js +2 -0
  40. package/dist/cli-bundle/main.js +7 -7
  41. package/dist/cli-bundle/sdk-authoring.js +1 -1
  42. package/dist/cli-bundle/sdk-contracts.js +1 -1
  43. package/dist/cli-bundle/sdk-core.js +31 -31
  44. package/dist/cli-bundle/sdk-governance.js +1 -1
  45. package/dist/cli-bundle/sdk-graph.js +1 -1
  46. package/dist/cli-bundle/sdk-merge.js +32 -32
  47. package/dist/cli-bundle/sdk-query.js +1 -1
  48. package/dist/cli-bundle/sdk-runtime.js +1 -1
  49. package/dist/cli-bundle/sdk-testing.js +1 -1
  50. package/dist/cli-bundle/sdk.js +4 -4
  51. package/dist/core/config/nested-settings.js +8 -2
  52. package/dist/core/extensions/exporter-output-contract.d.ts +12 -0
  53. package/dist/core/extensions/exporter-output-contract.js +67 -0
  54. package/dist/core/extensions/extension-types.d.ts +36 -1
  55. package/dist/core/extensions/extension-types.js +2 -2
  56. package/dist/core/extensions/loader.js +35 -44
  57. package/dist/core/history/event-index.d.ts +5 -0
  58. package/dist/core/history/event-index.js +133 -27
  59. package/dist/core/sentry/helpers.js +3 -3
  60. package/dist/core/shared/constants.js +5 -2
  61. package/dist/core/store/settings-validator.d.ts +4 -0
  62. package/dist/core/store/settings-validator.js +3 -2
  63. package/dist/core/store/settings.js +8 -2
  64. package/dist/mcp/tool-definitions.js +12 -7
  65. package/dist/sdk/agent/refusal-reachability.js +4 -4
  66. package/dist/sdk/authoring.d.ts +1 -1
  67. package/dist/sdk/authoring.js +2 -2
  68. package/dist/sdk/cli-bootstrap.d.ts +2 -2
  69. package/dist/sdk/cli-bootstrap.js +4 -4
  70. package/dist/sdk/cli-contracts/command-aliases.d.ts +34 -2
  71. package/dist/sdk/cli-contracts/command-aliases.js +64 -13
  72. package/dist/sdk/cli-contracts/enum-contracts.d.ts +4 -0
  73. package/dist/sdk/cli-contracts/enum-contracts.js +9 -2
  74. package/dist/sdk/cli-contracts/flag-contracts.js +11 -7
  75. package/dist/sdk/cli-contracts/grammar-contracts.d.ts +70 -0
  76. package/dist/sdk/cli-contracts/grammar-contracts.js +345 -0
  77. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +19 -2
  78. package/dist/sdk/cli-contracts/runtime-contracts.js +61 -14
  79. package/dist/sdk/cli-contracts/tool-parameter-tables.js +7 -2
  80. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  81. package/dist/sdk/cli-contracts/tool-schema.js +20 -11
  82. package/dist/sdk/cli-contracts.d.ts +2 -2
  83. package/dist/sdk/cli-contracts.js +4 -4
  84. package/dist/sdk/completion.js +13 -15
  85. package/dist/sdk/compose.d.ts +3 -3
  86. package/dist/sdk/compose.js +2 -2
  87. package/dist/sdk/contracts.d.ts +1 -0
  88. package/dist/sdk/contracts.js +3 -2
  89. package/dist/sdk/core.d.ts +1 -1
  90. package/dist/sdk/core.js +3 -3
  91. package/dist/sdk/environment/host-environment-errors.js +3 -3
  92. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +54 -14
  93. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -14
  94. package/dist/sdk/guide-topics.js +5 -5
  95. package/dist/sdk/index.d.ts +4 -3
  96. package/dist/sdk/index.js +6 -5
  97. package/dist/sdk/init-agent-guidance.js +3 -3
  98. package/dist/sdk/mutation-events.d.ts +18 -2
  99. package/dist/sdk/mutation-events.js +59 -16
  100. package/dist/sdk/output.d.ts +44 -0
  101. package/dist/sdk/output.js +28 -2
  102. package/dist/sdk/query/complete-list.d.ts +94 -0
  103. package/dist/sdk/query/complete-list.js +173 -0
  104. package/dist/sdk/query/list.js +5 -2
  105. package/dist/sdk/query.d.ts +1 -0
  106. package/dist/sdk/query.js +3 -2
  107. package/dist/sdk/read-output-contracts.d.ts +2 -2
  108. package/dist/sdk/read-output-contracts.js +36 -9
  109. package/dist/sdk/runtime-extended-actions.js +10 -2
  110. package/dist/sdk/runtime.d.ts +8 -2
  111. package/dist/sdk/runtime.js +11 -8
  112. package/dist/types.d.ts +5 -0
  113. package/dist/types.js +2 -2
  114. package/docs/AGENT_GUIDE.md +25 -9
  115. package/docs/CLI_GRAMMAR.md +106 -0
  116. package/docs/COMMANDS.md +23 -23
  117. package/docs/ONBOARDING.md +4 -4
  118. package/docs/QUICKSTART.md +1 -1
  119. package/docs/README.md +2 -0
  120. package/docs/RELEASING.md +30 -6
  121. package/docs/SDK.md +36 -2
  122. package/docs/SDK_ARTIFACT_OUTPUT.md +72 -0
  123. package/docs/SDK_CONTEXT_COORDINATION.md +46 -12
  124. package/docs/agent-task-token-baseline.json +5 -5
  125. package/marketplace.json +2 -2
  126. package/package.json +3 -2
  127. package/packages/pm-beads/package.json +1 -1
  128. package/packages/pm-calendar/package.json +1 -1
  129. package/packages/pm-command-kit/package.json +1 -1
  130. package/packages/pm-digital-twin/package.json +1 -1
  131. package/packages/pm-governance-audit/package.json +1 -1
  132. package/packages/pm-guide-shell/package.json +1 -1
  133. package/packages/pm-kanban/package.json +1 -1
  134. package/packages/pm-lifecycle-hooks/package.json +1 -1
  135. package/packages/pm-linked-test-adapters/package.json +1 -1
  136. package/packages/pm-search-advanced/package.json +1 -1
  137. package/packages/pm-templates/package.json +1 -1
  138. package/packages/pm-todos/package.json +1 -1
  139. package/packages/pm-vcs/package.json +1 -1
  140. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  141. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  142. package/sdk/public-surface.json +652 -31
  143. package/dist/cli-bundle/chunks/chunk-2QLOXC3V.js +0 -3
  144. package/dist/cli-bundle/chunks/chunk-4JPYF536.js +0 -35
  145. package/dist/cli-bundle/chunks/chunk-6VDLG2FC.js +0 -13
  146. package/dist/cli-bundle/chunks/chunk-ION3E43Q.js +0 -197
  147. package/dist/cli-bundle/chunks/chunk-OAC5NIV4.js +0 -3
  148. package/dist/cli-bundle/chunks/register-list-query-Q7KII4G5.js +0 -10
  149. package/dist/cli-bundle/focused-chunks/chunk-267MUUS6.js +0 -16
  150. package/dist/cli-bundle/focused-chunks/chunk-2NNFLLNG.js +0 -2
  151. package/dist/cli-bundle/focused-chunks/chunk-2QSAKMIH.js +0 -2
  152. package/dist/cli-bundle/focused-chunks/chunk-BUCG4ZI2.js +0 -2
  153. package/dist/cli-bundle/focused-chunks/chunk-EHXIKD6K.js +0 -2
  154. package/dist/cli-bundle/focused-chunks/chunk-KGEXTMPG.js +0 -2
  155. package/dist/cli-bundle/focused-chunks/chunk-POEEAD2V.js +0 -4
  156. package/dist/cli-bundle/focused-chunks/chunk-XPIC53VA.js +0 -26
  157. package/dist/cli-bundle/focused-chunks/chunk-ZT2DJS27.js +0 -155
@@ -0,0 +1,106 @@
1
+ # Noun–Verb CLI Grammar and Compatibility Policy
2
+
3
+ Tracked by [pm-pbyu](../.agents/pm/decisions/pm-pbyu.toon), implemented through [pm-0z7n](../.agents/pm/features/pm-0z7n.toon), [pm-pfqi](../.agents/pm/tasks/pm-pfqi.toon), [pm-yy8rmx](../.agents/pm/tasks/pm-yy8rmx.toon), and [pm-wt43zj](../.agents/pm/tasks/pm-wt43zj.toon).
4
+
5
+ ## Agent Quick Context
6
+
7
+ Use the canonical noun-first form when generating commands. Existing spellings remain executable, but deprecated compatibility aliases are absent from default help and completion discovery and emit one migration hint on stderr. Machine clients can read alias lifecycle and replacement tokens from `pm contracts --full --json`.
8
+
9
+ The first completed consolidation is the list family:
10
+
11
+ ```bash
12
+ pm list # active lifecycle rows
13
+ pm list --status open # one lifecycle class
14
+ pm list --status open,blocked # several classes
15
+ pm list --status blocked # status- or dependency-blocked semantics
16
+ pm list --all # every lifecycle status
17
+ ```
18
+
19
+ `list-all`, `list-draft`, `list-open`, `list-in-progress`, `list-blocked`, `list-closed`, and `list-canceled` preserve command results and stdout behavior. Their documented migration hint may add one stderr line.
20
+
21
+ ## Status
22
+
23
+ Accepted. The grammar contract, destination census, and compatibility policy are executable SDK data and mandatory static gates.
24
+
25
+ ## Context
26
+
27
+ pm grew by adding one top-level spelling per feature. That made help, completions, contracts, documentation, and agent routing grow linearly even when several commands represented the same concept. The list family alone repeated almost the same help surface eight times. A universal project-management tool needs extensible behavior without requiring every agent to memorize an ever-growing flat vocabulary.
28
+
29
+ The governing product principle is `project management = context management`: command discovery must route an agent to the smallest authoritative context, while compatibility must preserve scripts and historical instructions.
30
+
31
+ ## Decision Drivers
32
+
33
+ - Preserve every published invocation and its stdout behavior.
34
+ - Keep frequent operations concise without making aliases the discovery model.
35
+ - Make domain ownership explicit enough to generate routing, help, completions, SDK contracts, MCP projections, and documentation.
36
+ - Prevent surface regrowth with a fail-closed, bidirectional contract gate.
37
+ - Let packages add domain behavior without consuming the core noun budget.
38
+ - Make migration guidance suppressible for automation while keeping canonical replacements machine-readable.
39
+
40
+ ## Alternatives Considered
41
+
42
+ ### Flat surface status quo
43
+
44
+ Rejected. Each feature adds another root spelling and duplicates contract/help context. A byte-count snapshot records growth but does not decide whether the new command belongs in the architecture.
45
+
46
+ ### Pure git-style subcommands
47
+
48
+ Rejected as an exclusive rule. Noun-first paths are canonical, but forcing high-frequency operations such as `create`, `get`, `update`, `claim`, and `close` to pay an extra token on every invocation would regress the agent hot path. Named permanent aliases may remain visible and are distinguished from deprecated compatibility shims in contract data.
49
+
50
+ ### BusyBox-style multi-binary surface
51
+
52
+ Rejected. Separate binaries multiply distribution, signing, package resolution, documentation, and shell-discovery surfaces without improving domain routing.
53
+
54
+ ## Decision
55
+
56
+ 1. The core routing vocabulary has twelve nouns: `item`, `list`, `context`, `search`, `graph`, `history`, `workspace`, `package`, `ops`, `plan`, `contracts`, and `help`.
57
+ 2. Canonical forms are noun-first. Verbs and facets are subcommands; projections and predicates are flags.
58
+ 3. Shared semantics use a shared verb vocabulary. Noun-specific verbs require an explicit checked-in disposition.
59
+ 4. Scope precedes its operation: for example, `workspace snapshot create`, not `workspace create snapshot`.
60
+ 5. Package-owned commands are declared as such and do not silently expand the core noun set.
61
+ 6. Published spellings are not removed. Deprecated spellings are hidden aliases with a canonical token sequence, PM owner, lifecycle, and one stderr migration hint.
62
+ 7. Permanent hot-path aliases and deprecated aliases are different contract states. Permanent aliases are ergonomic API; deprecated aliases are compatibility state.
63
+ 8. Every live command has exactly one destination row. A row may name its target noun, a tracked consolidation owner, a package owner, or a reasoned keep-as-is exception.
64
+ 9. The census is bidirectional: missing live rows and stale checked-in rows both fail CI.
65
+ 10. Default-visible top-level growth is ceilinged. Lowering the ceiling is always valid; raising it requires a tracked noun-placement decision rather than regenerating a baseline.
66
+
67
+ ## SDK Contract
68
+
69
+ Package authors and embedded clients use the public exports:
70
+
71
+ ```ts
72
+ import {
73
+ PM_CLI_GRAMMAR_CONTRACT,
74
+ PM_COMMAND_ALIAS_CONTRACTS,
75
+ PM_COMMAND_DESTINATION_CONTRACTS,
76
+ resolvePmCommandAlias,
77
+ verifyPmCliGrammar,
78
+ } from "@unbrained/pm-cli/sdk";
79
+ ```
80
+
81
+ `PM_COMMAND_ALIAS_CONTRACTS` carries `alias`, `canonical`, `canonical_argv`, `lifecycle`, `hidden`, `registration`, and `owner`. `verifyPmCliGrammar` returns deterministic findings with an offending spelling and nearest conforming target.
82
+
83
+ Runtime contracts expose the compact noun/verb policy in summary output and include the exhaustive destination census in full output. Deprecated aliases remain queryable but are excluded from the default command-summary denominator.
84
+
85
+ ## Compatibility and Migration Hints
86
+
87
+ Hints go to stderr exactly once per deprecated-alias invocation and never alter stdout. Disable them for a project when an automation intentionally retains old spellings:
88
+
89
+ ```bash
90
+ pm config project set ux_deprecation_hints false
91
+ ```
92
+
93
+ This setting changes presentation only. It does not disable aliases or change command results. The uniform machine result-envelope receipt is intentionally deferred to its separately tracked cross-command contract so this implementation does not create a list-only shape.
94
+
95
+ ## Enforcement
96
+
97
+ `pnpm quality:command-grammar` builds the SDK, reads the live runtime command contracts, and compares them with the checked-in destination and alias tables. Package-owned destination rows are conditional because installed packages vary by workspace; every activated package command still requires a declared row, while an inactive package does not make its row stale. The gate also proves parity between discoverable SDK actions, the MCP `pm_run` action enum, and narrow MCP tools. The same gate runs inside `quality:static`, alongside contract drift checks. Its negative controls prove that unknown commands, stale core rows, broken alias targets, MCP drift, and surface-ceiling growth fail upward.
98
+
99
+ ## Consequences
100
+
101
+ - Agents discover one list command instead of eight repeated help pages.
102
+ - Existing scripts keep working and receive an actionable replacement.
103
+ - CLI, SDK, completion, and contract consumers share one alias table.
104
+ - New commands require an explicit architectural home and PM owner.
105
+ - The compatibility table is long-lived public API and must be reviewed like any other SDK contract.
106
+ - Consolidation proceeds incrementally: current legacy commands may remain only with a named disposition until their owning PM item lands.
package/docs/COMMANDS.md CHANGED
@@ -141,8 +141,8 @@ pm search "calendar reminder validation" --limit 10
141
141
  pm get pm-a1b2 # read one item; add --fields/--depth for lower-token projections
142
142
  pm get pm-a1b2 --tree --tree-depth 2 # item plus its descendant subtree
143
143
  pm get pm-a1b2 --at 7 # verified, mutation-free historical version
144
- pm list-open --type Task --priority 1 --limit 20
145
- pm list-in-progress --limit 20
144
+ pm list --status open --type Task --priority 1 --limit 20
145
+ pm list --status in_progress --limit 20
146
146
  pm aggregate --group-by parent,type --status open
147
147
  pm aggregate --group-by parent,type --completion --include-unparented
148
148
  pm duplicates --status all --threshold 0.8
@@ -173,7 +173,7 @@ Each aggregate row carries an explicit `group_label`: a blank/null group value (
173
173
  `--sort` accepts `priority|deadline|updated_at|created_at|title|parent`, plus the convenience aliases `updated` (→ `updated_at`) and `created` (→ `created_at`):
174
174
 
175
175
  ```bash
176
- pm list-all --sort updated --order desc
176
+ pm list --all --sort updated --order desc
177
177
  ```
178
178
 
179
179
  ### Incremental "what changed since" filters
@@ -182,16 +182,16 @@ Every `list*` command accepts `--updated-after`/`--updated-before`/`--created-af
182
182
 
183
183
  ```bash
184
184
  # Items touched since my last context window (feed back the previous run's `now`)
185
- pm list-all --updated-after 2026-06-04T15:18:32Z --brief
185
+ pm list --all --updated-after 2026-06-04T15:18:32Z --brief
186
186
 
187
187
  # Relative offsets are SIGNED: -2h/-7d reach into the past, +1d into the future.
188
188
  # Units are h/d/w/m (m = months — there is no minutes unit).
189
- pm list-open --updated-after=-2h --brief
190
- pm list-all --created-after=-7d --status open
189
+ pm list --status open --updated-after=-2h --brief
190
+ pm list --status open --created-after=-7d
191
191
 
192
- # Common list windows avoid date math (`list-open` keeps the view open-only).
193
- pm list-open --today --brief
194
- pm list-all --recent --brief
192
+ # Common list windows avoid date math (`pm list --status open` keeps the view open-only).
193
+ pm list --status open --today --brief
194
+ pm list --all --recent --brief
195
195
 
196
196
  # Search scoped to open work only (drops closed-history noise); statuses accept
197
197
  # all (no lifecycle restriction), open/closed/canceled aliases, or configured
@@ -293,12 +293,12 @@ pm eval --fail-under 0.6 --json # CI gate: exit non-zero when aggregate nDC
293
293
 
294
294
  ### Full results, totals, and bodies
295
295
 
296
- `pm list*` returns every matched row when neither `--limit` nor `--offset` is set. Every JSON/TOON result has the same pagination envelope: `total` is the pre-pagination match count, `has_more` and `truncated` are booleans, and `next_cursor` is either the continuation token or `null`. `completeness` reports whether the corpus was `complete`, `partial`, or `unchecked` (derived-index page), with unreadable item/directory counts. Use `--strict-read` when omissions must fail the command. The `filters` object omits unset values instead of emitting null placeholders, keeping long-running agent context stable and lean. Pass `--no-truncate` (alias `--all`) to force the entire matched set and override any `--limit` in one call the canonical "give me everything" flag for large-corpus audits:
296
+ `pm list` returns every matched row when neither `--limit` nor `--offset` is set. Every JSON/TOON result has the same pagination envelope: `total` is the pre-pagination match count, `has_more` and `truncated` are booleans, and `next_cursor` is either the continuation token or `null`. `completeness` reports whether the corpus was `complete`, `partial`, or `unchecked` (derived-index page), with unreadable item/directory counts. Use `--strict-read` when omissions must fail the command. The `filters` object omits unset values instead of emitting null placeholders, keeping long-running agent context stable and lean. Pass `--no-truncate` to force the entire matched set and override any `--limit` in one call. `--all` selects every lifecycle status; combine the flags for an unbounded all-status audit:
297
297
 
298
298
  ```bash
299
- pm list-all --no-truncate --brief # every matched row, ignoring any --limit
300
- pm list-open --limit 20 --json # stable total/has_more/truncated/next_cursor envelope
301
- pm list-all --strict-read --json # fail if any source item cannot be read
299
+ pm list --all --no-truncate --brief # every matched row, ignoring any --limit
300
+ pm list --status open --limit 20 --json # stable total/has_more/truncated/next_cursor envelope
301
+ pm list --all --strict-read --json # fail if any source item cannot be read
302
302
  ```
303
303
 
304
304
  Compatibility note: older responses emitted `total` only when pagination
@@ -312,7 +312,7 @@ unconditional pre-pagination match count, branch on `has_more` or
312
312
  JSON output is compact by default (id/status/type/title) for token efficiency. To pull item bodies in bulk in a single call — instead of one `pm get` per item — add `--include-body`, which expands each row to the full field set plus `body`:
313
313
 
314
314
  ```bash
315
- pm list-open --json --include-body # full fields + body for every returned row
315
+ pm list --status open --json --include-body # full fields + body for every returned row
316
316
  ```
317
317
 
318
318
  `pm get <id> --json` returns the item's `body` **inside** the `item` object (i.e. `.item.body`), matching where `list --include-body` places it and the long-form `description`/`acceptance_criteria` fields — so a single read exposes every field at a consistent path. Body is included at the default `standard` depth and above; `--depth brief` omits it.
@@ -322,10 +322,10 @@ pm list-open --json --include-body # full fields + body for every return
322
322
  `pm list*` accepts `--format <csv|table|json|ndjson|toon>` to choose how rows render. `csv` and `table` are **human export** modes — pipe them into a spreadsheet or read them directly in a terminal — while `json`/`toon` override the machine output format the same way the global `--json` flag does. `ndjson` writes each projected item as one self-contained JSON object per line, with no wrapper or trailing summary. The rendered fields follow the active projection, so combine `--format` with `--fields`/`--brief`/`--compact` to control exactly what appears:
323
323
 
324
324
  ```bash
325
- pm list-open --format table # aligned, monospace-friendly columns
326
- pm list-all --fields id,title,priority --format csv # spreadsheet export with chosen columns
327
- pm list-open --format csv > backlog.csv # capture for reporting
328
- pm list-all --brief --format ndjson | jq -c 'select(.status == "open")'
325
+ pm list --status open --format table # aligned, monospace-friendly columns
326
+ pm list --all --fields id,title,priority --format csv # spreadsheet export with chosen columns
327
+ pm list --status open --format csv > backlog.csv # capture for reporting
328
+ pm list --all --brief --format ndjson | jq -c 'select(.status == "open")'
329
329
  ```
330
330
 
331
331
  CSV output is RFC 4180 compliant (values with commas, quotes, or newlines are quoted; array fields such as `tags` join with `;`). `--format csv|table|ndjson` cannot be combined with the legacy envelope-oriented `--stream` mode.
@@ -338,13 +338,13 @@ The same `list*` commands and `pm search` extend this with governance-field pres
338
338
 
339
339
  ```bash
340
340
  # Find open Tasks that still need acceptance criteria
341
- pm list-open --type Task --filter-ac-missing --brief
341
+ pm list --status open --type Task --filter-ac-missing --brief
342
342
 
343
343
  # Closed items that were never given a resolution
344
- pm list-closed --filter-resolution-missing --json
344
+ pm list --status closed --filter-resolution-missing --json
345
345
 
346
346
  # Open items that still need a reviewer assigned
347
- pm list-open --filter-reviewer-missing --brief
347
+ pm list --status open --filter-reviewer-missing --brief
348
348
  ```
349
349
 
350
350
  ### Content-field presence filters
@@ -353,10 +353,10 @@ pm list-open --filter-reviewer-missing --brief
353
353
 
354
354
  ```bash
355
355
  # Closed items that shipped no documented learnings
356
- pm list-closed --no-learnings --brief
356
+ pm list --status closed --no-learnings --brief
357
357
 
358
358
  # Open work that has linked tests but no linked files yet
359
- pm list-open --has-tests --no-files --json
359
+ pm list --status open --has-tests --no-files --json
360
360
  ```
361
361
 
362
362
  ## Bulk Operations
@@ -41,8 +41,8 @@ Use progressive disclosure:
41
41
  ```bash
42
42
  pm context --limit 10
43
43
  pm search "<request keywords>" --limit 10
44
- pm list-open --limit 20
45
- pm list-in-progress --limit 20
44
+ pm list --status open --limit 20
45
+ pm list --status in_progress --limit 20
46
46
  pm install guide-shell --project
47
47
  pm guide workflows
48
48
  ```
@@ -82,8 +82,8 @@ The canonical loop is maintained in [AGENT_GUIDE.md](AGENT_GUIDE.md) — this is
82
82
  ```bash
83
83
  pm context --limit 10
84
84
  pm search "<keywords>" --limit 10
85
- pm list-open --limit 20
86
- pm list-in-progress --limit 20
85
+ pm list --status open --limit 20
86
+ pm list --status in_progress --limit 20
87
87
  ```
88
88
 
89
89
  2. Claim and start
@@ -94,7 +94,7 @@ Useful item types:
94
94
  ```bash
95
95
  pm context --limit 10
96
96
  pm search "restore lock retry" --limit 10
97
- pm list-open --limit 20
97
+ pm list --status open --limit 20
98
98
  pm claim <item-id>
99
99
  pm update <item-id> --status in_progress --message "Start implementation"
100
100
  pm update <item-id> --add-tags urgent,backend
package/docs/README.md CHANGED
@@ -40,9 +40,11 @@ pm guide release --json
40
40
  - [Testing](TESTING.md) - sandbox-safe local tests and linked-test orchestration.
41
41
  - [Security Governance](SECURITY_GOVERNANCE.md) - vulnerability reporting, review discipline, property fuzzing, and OpenSSF limitations.
42
42
  - [Architecture](ARCHITECTURE.md) - contributor internals: storage, mutation flow, search, extensions, and command contracts.
43
+ - [Noun–Verb CLI Grammar](CLI_GRAMMAR.md) - accepted command architecture, exhaustive destination census, hidden aliases, and the surface-growth gate.
43
44
  - [SDK Primitive Inventory](SDK_PRIMITIVE_INVENTORY.md) - SDK-first migration map and private-import ratchet for CLI/MCP layering.
44
45
  - [Package SDK Contract Conformance](PACKAGE_SDK_CONTRACT_CONFORMANCE.md) - authoritative public types, `typeof` module derivation, and the first-party parity gate.
45
46
  - [SDK Action and Boundary Conformance](SDK_ACTION_CONFORMANCE.md) - derived CLI/SDK/MCP action vocabulary, public-import ratchets, intent budget diagnostics, and package-runner proof.
47
+ - [SDK Artifact Output Contracts](SDK_ARTIFACT_OUTPUT.md) - clean stdout/file exporter channels, bounded receipts, binary-safe delivery, and shared NDJSON terminal framing.
46
48
  - [Context Relevance and Packing](CONTEXT_RELEVANCE.md) - shared CLI/SDK signals, derived-store provenance, ranking explanations, and token budgets.
47
49
  - [Output Projection and Omission Contracts](OUTPUT_PROJECTION_CONTRACTS.md) - explicit withheld-field receipts, mode-paired row keys, and completion resolver outcomes.
48
50
  - [Output Token Accounting](OUTPUT_TOKEN_ACCOUNTING.md) - opt-in CLI/MCP byte attribution, bounded receipt overhead, and release-level tokens-per-task baselines.
package/docs/RELEASING.md CHANGED
@@ -27,7 +27,8 @@ The local/hosted gate selection contract is tracked by
27
27
  [pm-ei6x66](../.agents/pm/tasks/pm-ei6x66.toon). Release-candidate analyzer
28
28
  provenance is tracked by [pm-u1baah](../.agents/pm/issues/pm-u1baah.toon), and
29
29
  authoritative blocker-recovery run selection by
30
- [pm-db8onn](../.agents/pm/issues/pm-db8onn.toon).
30
+ [pm-db8onn](../.agents/pm/issues/pm-db8onn.toon), and queued automatic
31
+ same-day recovery by [pm-dm2vfz](../.agents/pm/issues/pm-dm2vfz.toon).
31
32
 
32
33
  ## Version Policy
33
34
 
@@ -78,11 +79,11 @@ Policy:
78
79
  created, a non-`github-actions[bot]` closure of the exact bot-created
79
80
  `Auto Release blocked` issue on the same UTC day triggers one preparation
80
81
  retry
81
- - if today's tag already exists, blocker closure bypasses release-preparation
82
- provenance, dependency installation, and build work, then selects immutable
83
- Release evidence across both tag-push and guarded workflow-dispatch runs; a
84
- completed success is authoritative over stale failures and is recorded as
85
- recovered without republishing
82
+ - if today's tag already exists, a queued schedule or blocker closure bypasses
83
+ candidate preparation and accepts the immutable result only after independent
84
+ public-distribution evidence confirms the exact release; incomplete
85
+ publication continues through bounded recovery instead of being accepted
86
+ from tag presence alone
86
87
  - release preparation must pass all quality and compatibility gates before commit+tag push
87
88
  - before dependency installation or build, auto-release verifies that the
88
89
  candidate has exact-commit analyzer results or an immutable tree-identical
@@ -104,6 +105,10 @@ Policy:
104
105
  before release mutation and reported as `retry_already_attempted`, and
105
106
  workflow cleanup closures by `github-actions[bot]` are ignored.
106
107
  - after a scheduled run publishes a tag and the downstream release workflow succeeds, auto-release closes any open `Auto Release blocked` issue so the GitHub tracker reflects current release health
108
+ - workflow concurrency can leave a delayed schedule queued behind another
109
+ production run. The queued schedule resolves the current UTC-day immutable
110
+ result before candidate provenance, proves publication, and exits without
111
+ evaluating the generated release commit as a new candidate
107
112
 
108
113
  Pipeline entrypoint:
109
114
 
@@ -268,6 +273,25 @@ confirms that exact merge SHA, `main` base, and reviewed head. Remediate a
268
273
  refused direct-main candidate by landing the next tree-changing fix through a
269
274
  reviewed PR; never copy, synthesize, or bypass analyzer evidence.
270
275
 
276
+ ### Reviewed Delivery Closeout
277
+
278
+ The reviewed delivery includes its PM evidence, item closure, and generated
279
+ changelog. Complete those mutations on the implementation branch before merge
280
+ whenever their evidence is already available. A pull request is not complete
281
+ while known tracker or changelog closeout remains queued for a direct push.
282
+
283
+ When a repository update genuinely depends on the merge SHA or a post-merge
284
+ hosted result, create a normal follow-up branch from `main` and land that update
285
+ through another reviewed pull request. Do not push `.agents/pm/**` or
286
+ `CHANGELOG.md` closeout directly to `main`. Although tracker-only commits do not
287
+ create package-release eligibility by themselves, the direct commit still
288
+ becomes the default-branch head and lacks the reviewed analyzer evidence needed
289
+ by the next release-relevant candidate. `Release analyzer readiness (main)`
290
+ must fail closed in that state; its failure is a provenance control, not an
291
+ analyzer approval. Restore readiness only with a tree-changing, `main`-based,
292
+ reviewed pull request—never by copying statuses, weakening the gate, or
293
+ synthesizing a pull-request association.
294
+
271
295
  ```bash
272
296
  # Read-only parity check
273
297
  pnpm release:pipeline:dry-run
package/docs/SDK.md CHANGED
@@ -47,6 +47,9 @@ first-class recurrence relationships are tracked by
47
47
  [pm-rf120g](../.agents/pm/tasks/pm-rf120g.toon),
48
48
  [pm-3crymx](../.agents/pm/issues/pm-3crymx.toon), and
49
49
  [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon).
50
+ Fail-closed whole-corpus reads and package-catalog output controls are tracked by
51
+ [pm-y4aaol](../.agents/pm/issues/pm-y4aaol.toon) and
52
+ [pm-2firut](../.agents/pm/issues/pm-2firut.toon).
50
53
 
51
54
  Use it for extension authoring, package authoring, command/action contract discovery, and deterministic app or CI automation. Do not import private `src/core/...` modules from external integrations or packages.
52
55
 
@@ -199,6 +202,7 @@ Source of truth:
199
202
  - [`src/sdk/merge/index.ts`](../src/sdk/merge/index.ts)
200
203
  - [`src/sdk/workspace-transaction-gc.ts`](../src/sdk/workspace-transaction-gc.ts)
201
204
  - [`src/sdk/query/list.ts`](../src/sdk/query/list.ts)
205
+ - [`src/sdk/query/complete-list.ts`](../src/sdk/query/complete-list.ts)
202
206
  - [`src/sdk/query/search.ts`](../src/sdk/query/search.ts)
203
207
  - [`src/sdk/query/search-pagination.ts`](../src/sdk/query/search-pagination.ts)
204
208
  - [`src/sdk/query/search-rendering.ts`](../src/sdk/query/search-rendering.ts)
@@ -292,7 +296,7 @@ Storage format-version exports (under `@unbrained/pm-cli/sdk/runtime`):
292
296
  Command/action contract exports:
293
297
 
294
298
  - `PmClient` / `runAction` (high-level in-process action execution for custom tools, bots, CI, and embedded runtimes)
295
- - Typed read primitives on `PmClient`: `get` (including `GetOptions.at` point-in-time reads), `list`, `search`, `context`, `next`, `aggregate`, `stats`, and `duplicates`; direct `getItemAt` reconstructs a canonical historical document without mutation. `duplicates` performs one bounded all-status metadata sweep and returns deterministic canonical-candidate and close-command guidance without mutating items.
299
+ - Typed read primitives on `PmClient`: `get` (including `GetOptions.at` point-in-time reads), `list`, `listAllComplete`, `search`, `context`, `next`, `aggregate`, `stats`, and `duplicates`; direct `getItemAt` reconstructs a canonical historical document without mutation. `listAllComplete` forces an all-status, full, strict, unbounded read and fails closed unless the returned envelope proves source completeness, unique ids, exact counts, no pagination, no field or budget omission, and no session projection. `duplicates` performs one bounded all-status metadata sweep and returns deterministic canonical-candidate and close-command guidance without mutating items.
296
300
  - Read primitive option/result contracts: `GetOptions` / `GetResult`, `ListOptions` / `ListResult`, `SearchOptions` / `SearchResult`, `ContextOptions` / `ContextResult`, `NextOptions` / `NextResult`, `AggregateOptions` / `AggregateResult`, `StatsCommandOptions` / `StatsResult`. Standard and brief `get` projections omit note bodies but expose `item.notes_count`; deep/full reads return the notes themselves, and narrow consumers can request `notes_count` explicitly.
297
301
  - Stream projection primitive: `serializeNdjsonRows` frames SDK-owned object rows as newline-delimited JSON without a trailing newline and rejects scalar/array rows, so package transports can match list/search/context CLI semantics without importing presentation code.
298
302
  - Context relevance primitives: `buildItemContextRelevanceCandidates`, `buildContextSignalSnapshot`, `ContextSignalStore`, `JsonFileContextSignalStoreAdapter`, `parseContextSignalSnapshot`, `defaultScoreContextCandidates`, `scoreContextCandidates`, `scoreContextCandidatesWithActiveExtensions`, `evaluateContextRanking`, `runContextEvaluationScenario`, `runContextEvaluationCorpus`, and `summarizeContextEvaluationReports`
@@ -1468,6 +1472,10 @@ helpers return `ExtensionCommandResult`; both names describe the same lifecycle
1468
1472
  payload shape with vocabulary-appropriate SDK signatures. `UpgradeResult` is the
1469
1473
  same structured payload rendered by the CLI, so embedded tools can own their
1470
1474
  presentation layer while sharing pm's package/install/doctor semantics.
1475
+ `packageCatalog` is a read surface and accepts the universal output controls;
1476
+ the CLI-equivalent `pm --output-budget unbounded package --catalog --json`
1477
+ therefore composes with the same output contract while catalog-plus-mutation
1478
+ invocations fail before any package state can change.
1471
1479
 
1472
1480
  Annotation and relationship convenience methods turn "project management =
1473
1481
  context management" into a typed SDK surface. Use `pm.comments`, `pm.notes`,
@@ -1576,9 +1584,35 @@ compact or `fields` projections return `ListProjectedItem` dictionaries. Use
1576
1584
  a `partial` scan with unreadable item/directory counts, and an `unchecked`
1577
1585
  derived-index page. Set `ListOptions.strictRead` (CLI `--strict-read`) when an
1578
1586
  automation must fail instead of accepting omissions.
1579
- `full: true` when an integration requires complete item metadata; the overload
1587
+ Use `full: true` when an integration requires complete item metadata; the overload
1580
1588
  then returns `ListFullResult` without an assertion or cast.
1581
1589
 
1590
+ When correctness depends on the entire workspace rather than a page, use the
1591
+ certifying primitive instead of rebuilding these conditions at every call site:
1592
+
1593
+ ```ts
1594
+ import {
1595
+ PmClient,
1596
+ certifyCompleteListResult,
1597
+ createCompleteListOptions,
1598
+ } from "@unbrained/pm-cli/sdk/runtime";
1599
+
1600
+ const pm = new PmClient({ pmRoot: "/workspace/.agents/pm" });
1601
+ const corpus = await pm.listAllComplete({ includeBody: true });
1602
+ corpus.complete_list.source_complete; // true, otherwise the call throws
1603
+
1604
+ // Custom transports can apply the same request and certificate independently.
1605
+ const candidate = await pm.list(createCompleteListOptions());
1606
+ const certified = certifyCompleteListResult(candidate);
1607
+ ```
1608
+
1609
+ `PmCompleteListValidationError.receipt` lists every failed invariant and carries
1610
+ the exact recovery command
1611
+ `pm list-all --full --strict-read --no-truncate --output-budget unbounded --json`.
1612
+ The helper never infers completeness from a large limit: derived-index reads,
1613
+ terminal-state filtering, duplicate ids, cursor/session projection, compaction,
1614
+ and any omission receipt all prevent certification.
1615
+
1582
1616
  CLI JSON consumers can add `--lean` to compact null and empty values. On
1583
1617
  item-list envelopes, lean output also removes request echoes (`filters`, `now`,
1584
1618
  `projection`, and `sorting`) and removes `next_cursor` when `has_more` is not
@@ -0,0 +1,72 @@
1
+ # SDK artifact output contracts
2
+
3
+ Trackers: [pm-dilou2](../.agents/pm/issues/pm-dilou2.toon) and [pm-mav1ak](../.agents/pm/features/pm-mav1ak.toon).
4
+
5
+ Exporter artifacts are data streams, not command receipts. A package declares
6
+ the channel when it registers an exporter so the host never guesses whether a
7
+ returned value should be appended to artifact bytes.
8
+
9
+ ## Agent quick context
10
+
11
+ - Declare `output.channel: "stdout"` for JSON, NDJSON, CSV, or opaque bytes.
12
+ The host suppresses its receipt by default, including under global `--json`.
13
+ - Declare `output.channel: "file"` when the exporter writes a file. The host
14
+ renders the returned bounded receipt by default.
15
+ - An exporter may still return a structured result. Suppressed receipts remain
16
+ available to hooks, telemetry, and embedding hosts.
17
+ - Write optional human progress or summaries to stderr. Never mix them into a
18
+ stdout artifact.
19
+ - Legacy registrations without `output` retain their previous rendering.
20
+
21
+ ## Registration
22
+
23
+ ```ts
24
+ import type { ExtensionApi } from "@unbrained/pm-cli/sdk";
25
+
26
+ export function activate(api: ExtensionApi): void {
27
+ api.registerExporter(
28
+ "report-json",
29
+ async () => {
30
+ process.stdout.write('{"items":[]}\n');
31
+ return { exported: 0 };
32
+ },
33
+ {
34
+ description: "Export a complete JSON report to stdout.",
35
+ output: {
36
+ channel: "stdout",
37
+ media_type: "application/json",
38
+ },
39
+ },
40
+ );
41
+ }
42
+ ```
43
+
44
+ The normalized contract is visible in the extension contribution inventory.
45
+ Derived help also states that stdout artifact bytes are exclusive and host
46
+ receipt rendering is suppressed when the extension does not supply a custom
47
+ description.
48
+
49
+ ## Channel behavior
50
+
51
+ | Artifact channel | Default receipt | stdout | stderr |
52
+ | --- | --- | --- | --- |
53
+ | `stdout` | `suppress` | Artifact bytes only | Extension-owned diagnostics or summary |
54
+ | `file` | `render` | Bounded structured receipt | Extension-owned diagnostics |
55
+
56
+ File exporters may select `receipt: "render"` or `receipt: "suppress"` as an
57
+ explicit compatibility control. Stdout artifacts always suppress the host
58
+ receipt; declaring `receipt: "render"` with `channel: "stdout"` is rejected at
59
+ registration so redirection, `jq`, and binary output remain clean by
60
+ construction.
61
+
62
+ The host does not decode, re-encode, buffer, or inspect stdout artifact bytes.
63
+ Consequently NUL bytes and non-UTF-8 payloads pass through unchanged. The
64
+ extension owns media correctness and stream completion; the host owns only the
65
+ post-handler receipt policy.
66
+
67
+ ## Shared NDJSON framing
68
+
69
+ SDK-built producers can use `serializeNdjsonStream(rows, trailer)` to append one
70
+ typed `pm.stream.trailer` after a bounded row batch. It supplies one stable
71
+ place for counts, continuation cursors, source identity, and constant-size
72
+ producer metadata without adding per-row overhead.
@@ -1,6 +1,6 @@
1
1
  # SDK context coordination primitives
2
2
 
3
- Trackers: [pm-e200](../.agents/pm/features/pm-e200.toon), [pm-4ri6](../.agents/pm/features/pm-4ri6.toon), and [pm-hcrmye](../.agents/pm/issues/pm-hcrmye.toon).
3
+ Trackers: [pm-e200](../.agents/pm/features/pm-e200.toon), [pm-ez1dfg](../.agents/pm/tasks/pm-ez1dfg.toon), [pm-4ri6](../.agents/pm/features/pm-4ri6.toon), and [pm-hcrmye](../.agents/pm/issues/pm-hcrmye.toon).
4
4
 
5
5
  `pm` treats project management as context management. These primitives let an
6
6
  agent learn what changed, avoid creating redundant work, and keep that work
@@ -26,38 +26,72 @@ Read committed history facts as newline-delimited JSON:
26
26
  pm events --type create --author agent-a --limit 100
27
27
  pm events --since <cursor> --item pm-abcd
28
28
  pm events --since <cursor> --follow --interval-ms 250
29
+ pm events --cursor-mode row --since <cursor>
29
30
  ```
30
31
 
31
- Each line carries `cursor`, `item_id`, `version`, `ts`, `author`, `type`, and
32
- `patch_count`; `--full` also includes the complete authoritative history entry.
32
+ By default, event rows carry `item_id`, `version`, `ts`, `author`, `type`, and
33
+ `patch_count`, followed by one `pm.stream.trailer` record with `count`,
34
+ `has_more`, `next_cursor`, and `source`. Persist the trailer cursor only after
35
+ the batch is durable. A crash before cursor persistence can replay the last
36
+ batch repeatedly, including across multiple crashes. Consumers must process
37
+ idempotently or deduplicate replays. `--cursor-mode row` preserves the previous
38
+ shape with one `cursor` per event and no trailer for consumers that checkpoint
39
+ every row. Already issued version-1 cursors remain accepted by `--since`.
40
+
41
+ Node runtimes use the rebuildable SQLite event projection. Runtimes such as Bun
42
+ that do not expose `node:sqlite` transparently scan the authoritative history
43
+ streams with the same ordering, filters, pagination, and cursor contract; pages
44
+ identify that path with `source: "authoritative_history"`.
45
+
46
+ `--full` also includes the complete authoritative history entry.
33
47
  `--type`, `--author`, and `--item` accept repeatable or comma-separated values.
34
48
  `--since` accepts either a cursor or an ISO timestamp. The CLI emits only event
35
- rows, so it composes directly with standard NDJSON consumers.
49
+ rows and the typed terminal record, so consumers can distinguish data from
50
+ recovery metadata without relying on position alone. Under `--follow`, every
51
+ non-empty page ends at the same batch boundary and an empty boundary is emitted
52
+ as an idle heartbeat.
36
53
 
37
54
  The public SDK provides bounded pages and an abortable async iterator:
38
55
 
39
56
  ```ts
40
57
  import {
41
58
  listMutationEvents,
59
+ subscribeMutationEventBatches,
42
60
  subscribeMutationEvents,
43
61
  } from "@unbrained/pm-cli/sdk";
44
62
 
45
- const page = await listMutationEvents({
46
- pmRoot,
47
- type: ["create", "update"],
48
- limit: 100,
49
- });
63
+ const eventTypes = ["create", "update"] as const;
64
+ let cursor: string | undefined;
65
+ let hasMore = true;
66
+ while (hasMore) {
67
+ const page = await listMutationEvents({
68
+ pmRoot,
69
+ type: eventTypes,
70
+ limit: 100,
71
+ ...(cursor === undefined ? {} : { since: cursor }),
72
+ });
73
+ await consumeBatch(page.events);
74
+ await persistCursor(page.next_cursor);
75
+ cursor = page.next_cursor;
76
+ hasMore = page.has_more;
77
+ }
50
78
 
51
79
  const controller = new AbortController();
52
- for await (const event of subscribeMutationEvents({
80
+ for await (const batch of subscribeMutationEventBatches({
53
81
  pmRoot,
54
- since: page.next_cursor,
82
+ type: eventTypes,
83
+ ...(cursor === undefined ? {} : { since: cursor }),
55
84
  signal: controller.signal,
56
85
  })) {
57
- await consume(event);
86
+ await consumeBatch(batch.events);
87
+ await persistCursor(batch.next_cursor);
58
88
  }
59
89
  ```
60
90
 
91
+ `subscribeMutationEvents` remains the per-event compatibility iterator and
92
+ defaults to row cursors. `subscribeMutationEventBatches` is the token-efficient
93
+ coordination primitive; it exposes the same boundaries used by the CLI.
94
+
61
95
  The `pm_events` MCP tool exposes the same bounded page contract. Consumers such
62
96
  as notification packages can store `next_cursor`, catch up after a restart,
63
97
  then follow without requiring a daemon. A pm-slack migration can replace
@@ -6,20 +6,20 @@
6
6
  "scenarios": [
7
7
  {
8
8
  "id": "small-workspace",
9
- "max_estimated_tokens": 626
9
+ "max_estimated_tokens": 552
10
10
  },
11
11
  {
12
12
  "id": "large-workspace",
13
- "max_estimated_tokens": 1231
13
+ "max_estimated_tokens": 1055
14
14
  },
15
15
  {
16
16
  "id": "returning-agent",
17
- "max_estimated_tokens": 597
17
+ "max_estimated_tokens": 371
18
18
  },
19
19
  {
20
20
  "id": "failing-command",
21
- "max_estimated_tokens": 197
21
+ "max_estimated_tokens": 200
22
22
  }
23
23
  ],
24
- "composite_max_estimated_tokens": 2651
24
+ "composite_max_estimated_tokens": 2178
25
25
  }
package/marketplace.json CHANGED
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
9
- "version": "2026.8.17"
9
+ "version": "2026.8.18"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "pm-claude",
14
14
  "source": "./plugins/pm-claude",
15
15
  "description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
16
- "version": "2026.8.17",
16
+ "version": "2026.8.18",
17
17
  "author": {
18
18
  "name": "unbrained",
19
19
  "url": "https://github.com/unbraind/pm-cli"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-cli",
3
- "version": "2026.8.17",
3
+ "version": "2026.8.18",
4
4
  "description": "Git-native project management CLI for humans and agents.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.10.0",
@@ -120,7 +120,8 @@
120
120
  "lint:complexity:baseline": "eslint . --suppress-rule complexity --suppress-rule sonarjs/cognitive-complexity",
121
121
  "lint:duplicates": "jscpd --config .jscpd.json",
122
122
  "lint:codefactor": "pnpm quality:static",
123
- "quality:static": "pnpm build && node scripts/release/repository-assurance.mjs repository-static-quality --trigger ci --json && node scripts/release/audit-package-boundary.mjs && node scripts/release/package-sdk-contract-parity.mjs && node scripts/release/surface-replication-gate.mjs && node dist/cli.js assurance run tracker-context-quality --trigger ci --dry-run --json --output-budget unbounded && node scripts/release/gate-registry.mjs && node scripts/sdk-surface-snapshot.mjs --check && node scripts/bench/sdk-entrypoint-costs.mjs --check && node scripts/bench/cli-transport-floor.mjs --check && node dist/cli.js assurance run graph-composition --trigger ci --dry-run --json --output-budget unbounded && node dist/cli.js assurance run record-integrity --trigger ci --dry-run --json --output-budget unbounded",
123
+ "quality:static": "pnpm build && node scripts/release/repository-assurance.mjs repository-static-quality --trigger ci --json && node scripts/release/audit-package-boundary.mjs && node scripts/release/package-sdk-contract-parity.mjs && node scripts/release/surface-replication-gate.mjs && node scripts/release/command-grammar-gate.mjs && node dist/cli.js assurance run tracker-context-quality --trigger ci --dry-run --json --output-budget unbounded && node scripts/release/gate-registry.mjs && node scripts/sdk-surface-snapshot.mjs --check && node scripts/bench/sdk-entrypoint-costs.mjs --check && node scripts/bench/cli-transport-floor.mjs --check && node dist/cli.js assurance run graph-composition --trigger ci --dry-run --json --output-budget unbounded && node dist/cli.js assurance run record-integrity --trigger ci --dry-run --json --output-budget unbounded",
124
+ "quality:command-grammar": "pnpm build && node scripts/release/command-grammar-gate.mjs",
124
125
  "quality:token-budget": "node scripts/release/token-budget-gate.mjs",
125
126
  "quality:token-surface": "node scripts/measure-agent-token-surface.mjs --check",
126
127
  "quality:token-surface:update": "pnpm build && node scripts/measure-agent-token-surface.mjs --update",