@unbrained/pm-cli 2026.9.5 → 2026.9.7

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 (185) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +39 -3
  3. package/dist/cli/main.js +10 -8
  4. package/dist/cli/register-operations.js +13 -8
  5. package/dist/cli-bundle/bundle-manifest.json +150 -158
  6. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +9 -0
  7. package/dist/cli-bundle/chunks/{chunk-WWAEGW4V.js → chunk-BAX2BYUW.js} +66 -66
  8. package/dist/cli-bundle/chunks/{chunk-IBYREGSP.js → chunk-CKOL5U7J.js} +51 -51
  9. package/dist/cli-bundle/chunks/{chunk-ZRAQS3UA.js → chunk-JT6XF6GE.js} +2 -2
  10. package/dist/cli-bundle/chunks/{chunk-HUAQITVW.js → chunk-JX4DH4WC.js} +2 -2
  11. package/dist/cli-bundle/chunks/{chunk-QPZHQY2O.js → chunk-NPN5I67J.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-66VPKFP2.js → chunk-OF76PSDQ.js} +2 -2
  13. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +232 -0
  14. package/dist/cli-bundle/chunks/{chunk-3HBDTJRK.js → chunk-RWWBOWJ5.js} +2 -2
  15. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +40 -0
  16. package/dist/cli-bundle/chunks/{chunk-SF6SM6U5.js → chunk-WI2AYPA7.js} +2 -2
  17. package/dist/cli-bundle/chunks/{register-list-query-AYKGODWT.js → register-list-query-5JL52D33.js} +2 -2
  18. package/dist/cli-bundle/chunks/{register-mutation-YZYG53SQ.js → register-mutation-ZPG7KMVP.js} +2 -2
  19. package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +2 -0
  20. package/dist/cli-bundle/chunks/{register-setup-UJCRVGBG.js → register-setup-H4SVAVX7.js} +2 -2
  21. package/dist/cli-bundle/focused-chunks/{chunk-QL66QNWG.js → chunk-3BZEOXLT.js} +2 -2
  22. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +2 -0
  23. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +6 -0
  24. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +20 -0
  25. package/dist/cli-bundle/focused-chunks/{chunk-WOCIPMW7.js → chunk-EZR3GHFE.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +56 -0
  27. package/dist/cli-bundle/focused-chunks/{chunk-3ASU6WGI.js → chunk-LIJIA4TY.js} +2 -2
  28. package/dist/cli-bundle/focused-chunks/{chunk-H5FOGAVD.js → chunk-M6PBRFSH.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-B2TTQGFG.js → chunk-NTPY5GSO.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +2 -0
  31. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +177 -0
  32. package/dist/cli-bundle/focused-chunks/{chunk-YEF5PQQ2.js → chunk-PEFABF7E.js} +2 -2
  33. package/dist/cli-bundle/focused-chunks/{chunk-KWWCBWFO.js → chunk-QTVCLMSZ.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/{chunk-4OSHLNUE.js → chunk-QTZRBUYA.js} +2 -2
  35. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +12 -0
  36. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +10 -0
  37. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +2 -0
  38. package/dist/cli-bundle/main.js +20 -20
  39. package/dist/cli-bundle/sdk-authoring.js +1 -1
  40. package/dist/cli-bundle/sdk-contracts.js +2 -2
  41. package/dist/cli-bundle/sdk-core.js +37 -37
  42. package/dist/cli-bundle/sdk-governance.js +1 -1
  43. package/dist/cli-bundle/sdk-graph.js +1 -1
  44. package/dist/cli-bundle/sdk-merge.js +42 -42
  45. package/dist/cli-bundle/sdk-query.js +1 -1
  46. package/dist/cli-bundle/sdk-runtime.js +1 -1
  47. package/dist/cli-bundle/sdk-testing.js +1 -1
  48. package/dist/cli-bundle/sdk.js +9 -9
  49. package/dist/core/extensions/module-graph-snapshot.js +5 -4
  50. package/dist/core/fs/host-environment-errors.d.ts +27 -0
  51. package/dist/core/fs/host-environment-errors.js +142 -0
  52. package/dist/core/output/mutation-projection.js +12 -5
  53. package/dist/core/store/item-metadata-query-index.js +13 -10
  54. package/dist/core/store/item-metadata-read-work.d.ts +19 -0
  55. package/dist/core/store/item-metadata-read-work.js +44 -0
  56. package/dist/core/store/item-store.js +6 -2
  57. package/dist/core/validate/fix-planning.d.ts +1 -1
  58. package/dist/core/validate/fix-planning.js +2 -2
  59. package/dist/core/validate/missing-link-owners.d.ts +1 -1
  60. package/dist/core/validate/missing-link-owners.js +5 -3
  61. package/dist/core/validate/stale-file-classification.d.ts +6 -4
  62. package/dist/core/validate/stale-file-classification.js +20 -5
  63. package/dist/mcp/server.js +12 -5
  64. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  65. package/dist/sdk/cli-contracts/flag-contracts.js +7 -5
  66. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +4 -3
  67. package/dist/sdk/cli-contracts/grammar-contracts.js +11 -2
  68. package/dist/sdk/cli-contracts/runtime-contracts.js +5 -2
  69. package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +254 -5
  70. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +52 -2
  71. package/dist/sdk/cli-contracts/tool-parameter-tables.js +18 -6
  72. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  73. package/dist/sdk/cli-contracts/tool-schema.js +17 -5
  74. package/dist/sdk/context/usage-ledger.d.ts +41 -0
  75. package/dist/sdk/context/usage-ledger.js +186 -0
  76. package/dist/sdk/context-usage.d.ts +18 -9
  77. package/dist/sdk/context-usage.js +37 -112
  78. package/dist/sdk/dependency-provenance.d.ts +7 -0
  79. package/dist/sdk/dependency-provenance.js +14 -4
  80. package/dist/sdk/duplicates.d.ts +2 -0
  81. package/dist/sdk/duplicates.js +3 -2
  82. package/dist/sdk/environment/host-environment-errors.d.ts +5 -27
  83. package/dist/sdk/environment/host-environment-errors.js +4 -137
  84. package/dist/sdk/extension/install-runtime.js +9 -6
  85. package/dist/sdk/extension/install-snapshot.js +7 -6
  86. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +8 -8
  87. package/dist/sdk/governance/assurance-action.d.ts +3 -2
  88. package/dist/sdk/governance/assurance-action.js +23 -11
  89. package/dist/sdk/governance/assurance-runtime.d.ts +2 -0
  90. package/dist/sdk/governance/assurance-runtime.js +6 -3
  91. package/dist/sdk/governance/defect-recurrence-coverage.d.ts +93 -0
  92. package/dist/sdk/governance/defect-recurrence-coverage.js +189 -0
  93. package/dist/sdk/governance/defect-recurrence-graph.d.ts +33 -0
  94. package/dist/sdk/governance/defect-recurrence-graph.js +121 -0
  95. package/dist/sdk/governance/defect-recurrence.d.ts +8 -0
  96. package/dist/sdk/governance/defect-recurrence.js +118 -17
  97. package/dist/sdk/governance/health.d.ts +17 -2
  98. package/dist/sdk/governance/health.js +31 -10
  99. package/dist/sdk/governance/linked-file-report.d.ts +41 -0
  100. package/dist/sdk/governance/linked-file-report.js +72 -0
  101. package/dist/sdk/governance/validate.d.ts +5 -2
  102. package/dist/sdk/governance/validate.js +21 -37
  103. package/dist/sdk/governance.d.ts +2 -0
  104. package/dist/sdk/governance.js +4 -2
  105. package/dist/sdk/history-repair.d.ts +7 -0
  106. package/dist/sdk/history-repair.js +48 -13
  107. package/dist/sdk/lifecycle/close.d.ts +8 -0
  108. package/dist/sdk/lifecycle/close.js +16 -8
  109. package/dist/sdk/lifecycle/create.js +9 -12
  110. package/dist/sdk/lifecycle/update.js +12 -12
  111. package/dist/sdk/lifecycle-policy.d.ts +3 -0
  112. package/dist/sdk/lifecycle-policy.js +2 -2
  113. package/dist/sdk/merge/abandoned-receipts.d.ts +15 -0
  114. package/dist/sdk/merge/abandoned-receipts.js +47 -0
  115. package/dist/sdk/merge/driver.js +4 -2
  116. package/dist/sdk/merge/index.d.ts +1 -0
  117. package/dist/sdk/merge/index.js +2 -2
  118. package/dist/sdk/merge/receipt-operation.d.ts +15 -0
  119. package/dist/sdk/merge/receipt-operation.js +97 -0
  120. package/dist/sdk/merge/receipt-schema.d.ts +20 -0
  121. package/dist/sdk/merge/receipt-schema.js +398 -0
  122. package/dist/sdk/merge/receipts.d.ts +16 -7
  123. package/dist/sdk/merge/receipts.js +54 -340
  124. package/dist/sdk/merge/reconcile.d.ts +2 -0
  125. package/dist/sdk/merge/reconcile.js +11 -4
  126. package/dist/sdk/public-surface.json +1 -1
  127. package/dist/sdk/query/duplicate-candidates.d.ts +7 -0
  128. package/dist/sdk/query/duplicate-candidates.js +71 -0
  129. package/dist/sdk/query/get.js +7 -7
  130. package/dist/sdk/query.d.ts +2 -0
  131. package/dist/sdk/query.js +4 -2
  132. package/dist/sdk/read-output-session.js +5 -3
  133. package/dist/sdk/runtime.js +4 -2
  134. package/dist/sdk/similarity.d.ts +24 -3
  135. package/dist/sdk/similarity.js +50 -55
  136. package/docs/AGENT_GUIDE.md +23 -2
  137. package/docs/BOUNDED_CONTEXT_READS.md +185 -0
  138. package/docs/CLOSE_EVIDENCE_RECOVERY.md +35 -0
  139. package/docs/COMMANDS.md +30 -8
  140. package/docs/CONTEXT_RELEVANCE.md +16 -4
  141. package/docs/DEFECT_RECURRENCE.md +80 -6
  142. package/docs/EXTENSIONS.md +18 -19
  143. package/docs/MERGE_SAFETY.md +50 -0
  144. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +66 -0
  145. package/docs/PR_REVIEW_LOOP.md +18 -3
  146. package/docs/README.md +18 -1
  147. package/docs/RELEASING.md +7 -2
  148. package/docs/SDK_LIFECYCLE.md +27 -0
  149. package/docs/SDK_RUNTIME_BOUNDARIES.md +11 -0
  150. package/docs/generated/FLAG_LEXICON_BUDGETS.md +1 -1
  151. package/marketplace.json +2 -2
  152. package/package.json +6 -3
  153. package/packages/pm-beads/package.json +1 -1
  154. package/packages/pm-calendar/package.json +1 -1
  155. package/packages/pm-command-kit/package.json +1 -1
  156. package/packages/pm-digital-twin/package.json +1 -1
  157. package/packages/pm-governance-audit/README.md +10 -1
  158. package/packages/pm-governance-audit/extensions/governance-audit/dedupe-audit.ts +50 -65
  159. package/packages/pm-governance-audit/extensions/governance-audit/index.ts +2 -2
  160. package/packages/pm-governance-audit/extensions/governance-audit/sdk.ts +1 -0
  161. package/packages/pm-governance-audit/package.json +1 -1
  162. package/packages/pm-guide-shell/package.json +1 -1
  163. package/packages/pm-kanban/package.json +1 -1
  164. package/packages/pm-lifecycle-hooks/package.json +1 -1
  165. package/packages/pm-linked-test-adapters/package.json +1 -1
  166. package/packages/pm-search-advanced/package.json +1 -1
  167. package/packages/pm-templates/package.json +1 -1
  168. package/packages/pm-todos/package.json +1 -1
  169. package/packages/pm-vcs/package.json +1 -1
  170. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  171. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  172. package/dist/cli-bundle/chunks/chunk-LUI4E32I.js +0 -231
  173. package/dist/cli-bundle/chunks/chunk-SVK5Y64D.js +0 -40
  174. package/dist/cli-bundle/chunks/chunk-V5GBD5KV.js +0 -9
  175. package/dist/cli-bundle/chunks/register-operations-KFSCC7QV.js +0 -2
  176. package/dist/cli-bundle/focused-chunks/chunk-24IG6ONG.js +0 -2
  177. package/dist/cli-bundle/focused-chunks/chunk-3ITLIBKS.js +0 -56
  178. package/dist/cli-bundle/focused-chunks/chunk-3NQD5YDG.js +0 -2
  179. package/dist/cli-bundle/focused-chunks/chunk-65N6JHAN.js +0 -2
  180. package/dist/cli-bundle/focused-chunks/chunk-GUBM3RGY.js +0 -20
  181. package/dist/cli-bundle/focused-chunks/chunk-JX3RCVCX.js +0 -2
  182. package/dist/cli-bundle/focused-chunks/chunk-MV752SUC.js +0 -12
  183. package/dist/cli-bundle/focused-chunks/chunk-PKIPMCFS.js +0 -6
  184. package/dist/cli-bundle/focused-chunks/chunk-RJMR2JIF.js +0 -9
  185. package/dist/cli-bundle/focused-chunks/chunk-WIUPWIZR.js +0 -177
@@ -186,6 +186,53 @@ receipt file that the older writer never created. Incomplete, contradictory, or
186
186
  modern summaries still fail closed. `runMergeReceiptReport` remains the
187
187
  compatible valid-only report.
188
188
 
189
+ ## Historical receipt reader compatibility
190
+
191
+ Tracked by [pm-2xtv84](../.agents/pm/issues/pm-2xtv84.toon) and
192
+ [pm-v66zir](../.agents/pm/issues/pm-v66zir.toon). Version-1 preferred-era and
193
+ identified `requested_preference`/`clone_local` receipts may omit `base`, `ours`,
194
+ or `theirs` when the original value was undefined. Readers normalize those slots to the explicit missing-value marker
195
+ in memory. They still require retained/discarded evidence and valid collections;
196
+ reading never rewrites the original file. Collection failures expose a bounded
197
+ `validation_path`, such as `union_fields` or `decisions[0]`. The diagnostic
198
+ category `collections` is not a property that should be added to a receipt.
199
+ The writer now encodes all five scalar slots itself, including undefined
200
+ retained/discarded values supplied directly through the SDK, before JSON storage.
201
+
202
+ Paired clone-local and historical hash-only copies accept the original scalar
203
+ hash encoding throughout inspection and settlement. Compatibility does not
204
+ apply to durable copies declaring the modern value policy. Changed values or
205
+ immutable coordinates remain copy-provenance failures. Hash-only evidence
206
+ does not recover the original private value.
207
+
208
+ ## Receipts from an aborted rebase
209
+
210
+ Tracked by [pm-466m0j](../.agents/pm/issues/pm-466m0j.toon). New receipts
211
+ created during a rebase capture only its original commit and item blob in the
212
+ typed `MergeReceiptOperation` contract. After aborting, run:
213
+
214
+ ```bash
215
+ pm merge reconcile --dry-run --json
216
+ pm merge reconcile --message "Record restored original rebase state" --json
217
+ ```
218
+
219
+ Settlement requires Git to have left every active merge/rebase/cherry-pick/revert
220
+ operation, HEAD to match the original commit, and the item in HEAD, index, and
221
+ working tree to match the original blob. The item history must already be clean.
222
+ The history transaction rechecks the proof against its exact protected item
223
+ snapshot. Apply appends an explicit `merge_reconcile` event with
224
+ `abandoned_receipts` and the reason `original_git_state_restored`; it then marks
225
+ both copies reconciled with that settlement reason. The result counts these in
226
+ `receipts.abandoned`, separately from applied merge decisions. Preview performs
227
+ the same eligibility checks and leaves both history and receipts untouched.
228
+ If receipt persistence fails after the audit commits, retry reuses the identical
229
+ verified disposition and finishes the receipt writes without appending another
230
+ audit event. An unrelated earlier audit does not satisfy this check.
231
+
232
+ Old receipts without operation coordinates remain pending for ordinary review.
233
+ Tracked `merge-receipts/` sidecars are durable provenance and must remain tracked.
234
+ Deleting or ignoring them would lose the evidence needed by other clones.
235
+
189
236
  ## Cross-branch id collision safety
190
237
 
191
238
  Item ids are `<prefix>` plus random base36 characters, and uniqueness is only probed against the local working tree — two agents branching from the same commit can mint the same id for different items (GH-600 / pm-pibw). Two controls bound that risk:
@@ -210,6 +257,9 @@ pm merge reconcile --force --message "Accept reviewed merge decisions" --json
210
257
  ```
211
258
 
212
259
  The preview reports every drifted stream and pending receipt without mutation.
260
+ It applies the same exact-snapshot proof requirement as apply: stale or
261
+ unprovable receipts appear as failed streams in both modes, tracked by
262
+ [pm-ao0bu9](../.agents/pm/issues/pm-ao0bu9.toon).
213
263
  Lossless receipts do not become discarded-value decisions and reconcile without
214
264
  `--force`, but `pm health` reports `merge_receipts_pending:<n>` and remains
215
265
  non-green until the apply pass settles them. `pm history-repair` cannot clear
@@ -265,11 +265,77 @@ These are corpus-generated figures, not live tracker payloads. The generated
265
265
  corpus contains 2,243 items; the `status:all` query intentionally excludes 245
266
266
  canceled fixtures under the command's current status-selection contract.
267
267
 
268
+ ## Health Verdicts
269
+
270
+ Tracked by [pm-fkohe8](../.agents/pm/issues/pm-fkohe8.toon) and
271
+ [pm-du93sr](../.agents/pm/issues/pm-du93sr.toon).
272
+
268
273
  `health --check-only` defaults to a summary verdict: all checks still run, but
269
274
  passing check evidence bodies are empty. Use `health --check-only --full` when
270
275
  diagnostic evidence is required. Explicit `--brief` or `--summary` retains the
271
276
  existing fast check-only mode that skips expensive optional scans.
272
277
 
278
+ Use top-level `ok` to decide health. Each `checks[].ok` uses the same rule:
279
+ true means no gate-failing findings belong to that check. A check can therefore
280
+ have `status: "warn"` and `ok: true` when all its findings are advisory.
281
+ `failed_because` names every deciding warning, including findings beyond the
282
+ bounded warning sample. `findings[].severity` distinguishes advisory from
283
+ `gate_failing` evidence without parsing prose.
284
+
285
+ The `verdict` receipt names `authority: "ok"` and the invocation's `exit_code`.
286
+ `strict_exit: true` and `require_merge_drivers: true` appear only when enabled;
287
+ omission means false. The default invocation reports blocking findings without
288
+ changing the process exit code. `--strict-exit` (alias `--fail-on-warn`) requires
289
+ clone-local merge drivers and exits `1` when `ok` is false. Other advisory
290
+ warnings retain their policy. Compare invocations with the same scan and policy
291
+ options: enabling strict mode can legitimately change a missing-driver finding
292
+ from advisory to blocking. The SDK accepts `strictExit` and `failOnWarn` with
293
+ the same semantics, including MCP dispatch. Required merge-driver enforcement
294
+ always runs the integrity check, even when `skipIntegrity` or an explicit compact
295
+ check-only projection would otherwise skip optional integrity work.
296
+
297
+ The required token corpus measures `health --check-only` on its medium workspace
298
+ under the `health-default` ceiling. Its positive and negative controls run in
299
+ the same repository quality composition as the other answer budgets. Full
300
+ evidence remains an explicit restore path; the verdict receipt does not raise
301
+ the existing default token ceiling.
302
+
303
+ ## Linked-File Repair Rows
304
+
305
+ Tracked by [pm-zw9188](../.agents/pm/issues/pm-zw9188.toon).
306
+
307
+ `validate --check-files` joins each missing path with its holders, lifecycle
308
+ states, link fields, and candidate destinations before applying output limits.
309
+ `missing_linked_path_rows` contains structured objects in both default and
310
+ `--verbose-file-lists` output. The default caps paths and holders per path at
311
+ 40; verbose output restores both collections. `items_truncated` and
312
+ `missing_linked_path_rows_truncated` identify the two independent omissions.
313
+
314
+ `validate --counts` omits false `*_truncated` markers to keep its summary compact.
315
+ True truncation markers, ordinary false values, and every zero count remain;
316
+ its projection receipt declares that diagnostic rows were omitted.
317
+
318
+ Counts describe the complete scanned population:
319
+
320
+ - `missing_linked_links_count` counts distinct path, holder, and field triples.
321
+ - `missing_linked_path_rows_count` counts distinct paths.
322
+ - `active_missing_linked_links_count` and `active_missing_linked_paths_count`
323
+ identify actionable work under the configured workflow registry.
324
+ - `legacy_closed_missing_linked_links_count` is the close-status subset of
325
+ `legacy_terminal_missing_linked_links_count`.
326
+
327
+ Only active missing paths cause the missing-link warning. Historical terminal
328
+ links remain visible for context reconstruction. Unknown statuses and absent
329
+ holder metadata remain actionable. Rows and holders prioritize active work.
330
+ Package authors can build the same pure report with
331
+ `buildLinkedFileRepairReport` from `@unbrained/pm-cli/sdk/governance` and choose
332
+ an explicit finite ceiling or `Infinity` for full output.
333
+
334
+ Same-basename destinations are possibilities requiring review. Missing CSV or
335
+ `path:note` literals receive `malformed` classification and no inferred move;
336
+ explicit pruning never removes that category. Existing literal filenames are
337
+ checked before classification, including names containing commas or colons.
338
+
273
339
  ## Completion Resolver Contract
274
340
 
275
341
  `resolveCompletionTimestamp` accepts legacy metadata where all timestamp fields
@@ -1,19 +1,24 @@
1
1
  # Pull Request Review Loop
2
2
 
3
- Trackers: [pm-hq28](../.agents/pm/tasks/pm-hq28.toon), [pm-cp5pbo](../.agents/pm/tasks/pm-cp5pbo.toon)
3
+ Trackers: [pm-hq28](../.agents/pm/tasks/pm-hq28.toon), [pm-cp5pbo](../.agents/pm/tasks/pm-cp5pbo.toon), [pm-8we38i](../.agents/pm/issues/pm-8we38i.toon)
4
4
 
5
5
  Use `scripts/reviews/pr-review-loop.mjs` to inventory every GitHub pull-request
6
6
  conversation surface before deciding that review is complete. The inventory includes
7
7
  top-level comments, submitted reviews, inline review threads, edited timestamps,
8
8
  reaction state, thread resolution, outdated markers, and the reviewed head SHA.
9
9
 
10
+ GitHub command responses have a 64 MiB transport bound and fail visibly on overflow;
11
+ an overflow never certifies a complete inventory. Acknowledgement lookups retain
12
+ every page but project only comment IDs, bodies, and reply-parent IDs before
13
+ capture, avoiding repeated diff hunks that are irrelevant to marker matching.
14
+
10
15
  ```bash
11
16
  node scripts/reviews/pr-review-loop.mjs inventory --pr 123 > /tmp/pr-123-review-inventory.json
12
17
  node scripts/reviews/pr-review-loop.mjs watch --pr 123 --interval 30 > /tmp/pr-123-review-inventory.json
13
18
  node scripts/reviews/pr-review-loop.mjs react --node-id IC_kw... --reaction THUMBS_UP
14
- node scripts/reviews/pr-review-loop.mjs acknowledge --pr 123 --node-id PRR_kw... --reaction THUMBS_UP --body "CodeRabbit feedback implemented: https://github.com/owner/repo/pull/123#pullrequestreview-456. The suggested edge case is covered by test X."
19
+ node scripts/reviews/pr-review-loop.mjs acknowledge --pr 123 --node-id PRR_kw... --revision '<revision>' --reaction THUMBS_UP --body "CodeRabbit feedback implemented: https://github.com/owner/repo/pull/123#pullrequestreview-456. The suggested edge case is covered by test X."
15
20
  node scripts/reviews/pr-review-loop.mjs reply-inline --pr 123 --comment-id 456 --body "Addressed in abc123."
16
- node scripts/reviews/pr-review-loop.mjs acknowledge-inline --pr 123 --comment-id 456 --node-id PRRC_kw... --reaction THUMBS_UP --body "Addressed in abc123."
21
+ node scripts/reviews/pr-review-loop.mjs acknowledge-inline --pr 123 --comment-id 456 --node-id PRRC_kw... --revision '<revision>' --reaction THUMBS_UP --body "Addressed in abc123."
17
22
  ```
18
23
 
19
24
  Choose `THUMBS_UP` when feedback is useful or correct and `THUMBS_DOWN` when a
@@ -28,6 +33,16 @@ retry, so a lost response cannot create duplicate acknowledgements. It reports a
28
33
  partial result and exits unsuccessfully when either the comment or reaction write
29
34
  fails, allowing the missing write to be retried safely.
30
35
 
36
+ Each comment and review also carries a `revision`: a SHA-256 identity of its
37
+ body and review state. Compare these identities after each completed check watch
38
+ and immediately before merge. A changed body or review verdict needs fresh
39
+ triage even when its node ID already has an acknowledgement. Reaction timestamp
40
+ changes alone do not create a new revision. Pass the observed revision to both
41
+ `acknowledge` and `acknowledge-inline` with `--revision <revision>`; their hidden
42
+ markers then distinguish revised feedback and suppress duplicate retry replies
43
+ for that same revision. Inline markers are matched only within the selected
44
+ reply thread. Legacy calls without the flag retain their existing behavior.
45
+
31
46
  After every push or reviewer retrigger, run `watch`. It delegates waiting to
32
47
  `gh pr checks --watch`, because reviewer agents report completion through GitHub
33
48
  checks, and only fetches the complete conversation inventory after those checks
package/docs/README.md CHANGED
@@ -91,6 +91,17 @@ pm guide release --json
91
91
  - [Releasing](RELEASING.md) - maintainer release checklist and failure handling.
92
92
  - [starter extension](examples/starter-extension/README.md) - compact extension scaffold reference.
93
93
 
94
+ Additional SDK, operations, and generated contracts:
95
+
96
+ - [Item Read Projections](ITEM_READ_PROJECTIONS.md) - identity, projections, and read completeness.
97
+ - [MCP Capability Surfaces](MCP_CAPABILITY_SURFACES.md) - negotiated MCP discovery contracts.
98
+ - [PR Review Loop](PR_REVIEW_LOOP.md) - complete review inventories and feedback acknowledgment.
99
+ - [SDK Lifecycle](SDK_LIFECYCLE.md) - lifecycle primitives and package integration.
100
+ - [SDK Runtime Boundaries](SDK_RUNTIME_BOUNDARIES.md) - runtime ownership and import boundaries.
101
+ - [Sentry Contract Epochs](SENTRY_CONTRACT_EPOCHS.md) - diagnostic compatibility and release epochs.
102
+ - [Generated Agent Command Surface](generated/AGENT_COMMAND_SURFACE.md) - command routing inventory.
103
+ - [Generated Flag Lexicon Budgets](generated/FLAG_LEXICON_BUDGETS.md) - flag vocabulary and budget inventory.
104
+
94
105
  ## Guide Topic Map
95
106
 
96
107
  | Optional `pm guide` topic | Primary docs |
@@ -152,4 +163,10 @@ Public docs must not link to ignored local operations artifacts, unpublished evi
152
163
  - Put a short "Agent Quick Context" near the top of deep docs.
153
164
  - Prefer commands that agents can copy exactly.
154
165
  - Use `pm` item IDs as durable references when docs explain tracked work.
155
- - Run link/search checks before closing documentation tasks.
166
+ - Run `pnpm quality:docs-links` before closing documentation tasks. Every Markdown
167
+ page under `docs/` must be reachable transitively from this index, and links to
168
+ heading fragments must resolve. Fenced examples do not create navigation edges.
169
+ - A deliberately standalone page requires an individual path and nonempty reason
170
+ in `scripts/release/docs-reachability-exceptions.json`; stale exceptions fail.
171
+ This policy is tracked by [pm-s4y3z4](../.agents/pm/chores/pm-s4y3z4.toon)
172
+ and [pm-esbt](../.agents/pm/tasks/pm-esbt.toon).
package/docs/RELEASING.md CHANGED
@@ -99,6 +99,7 @@ Policy:
99
99
  manifest changed by version substitution alone, and only the generated
100
100
  changelog heading changed. Any other path or content still fails closed
101
101
  - `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
102
+ - Release preparation passes `--date-from-version` with the target calendar version so the generated heading already has its UTC release date before the tag exists. This keeps the preparation commit consistent with canonical post-tag generation and the normal `main` changelog check.
102
103
  - 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
103
104
  - 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`
104
105
  - after creating and pushing a new tag, auto-release waits for the tag-push `.github/workflows/release.yml` run to finish instead of dispatching a second publish workflow
@@ -281,8 +282,12 @@ The automatic release commit is the sole non-identical-tree derivation. The
281
282
  gate requires one parent, the canonical release subject and body, an immutable
282
283
  `v<version>` tag resolving to the candidate, the complete expected manifest
283
284
  inventory, exact old-version to new-version substitutions in every manifest,
284
- and an exact `Unreleased` changelog-heading replacement. It then resolves the
285
- parent through the same exact or reviewed identical-tree analyzer contract.
285
+ and an exact `Unreleased` changelog-heading replacement. The package-generated
286
+ replacement may be `## <version>` or the historical
287
+ `## <version> - <YYYY-MM-DD>` form, with the date matching the calendar version.
288
+ The complete heading must match and every other changelog byte must remain
289
+ unchanged. The gate then resolves the parent through the same exact or reviewed
290
+ identical-tree analyzer contract.
286
291
  Added, deleted, renamed, missing, or otherwise modified paths are refused, as
287
292
  are malformed manifests, changelog edits, untagged commits, and parents without
288
293
  successful analyzer evidence. The receipt reports
@@ -39,6 +39,33 @@ Package authors can import these operations from `@unbrained/pm-cli/sdk`
39
39
  without importing CLI modules or spawning the executable. Existing CLI import
40
40
  paths remain source-compatible while integrations migrate.
41
41
 
42
+ ## Relationship Identity
43
+
44
+ Tracked by [pm-olcoon](../.agents/pm/issues/pm-olcoon.toon).
45
+
46
+ `normalizeItemReference(reference, prefix, sourceKind?)` is the shared public
47
+ SDK primitive for parent and dependency identities. Local shorthand, optional
48
+ leading `#`, and case variants normalize to the workspace's canonical prefix.
49
+ Explicit URL or provider locators (`github:`, `gitlab:`, `jira:`, `linear:`)
50
+ retain their spelling and case; externally sourced dependency IDs do too.
51
+ Only surrounding whitespace is trimmed from remote identities.
52
+
53
+ Create, update, and plan materialization persist the canonical local parent,
54
+ so lookup success cannot leave an unresolved shorthand in the stored graph.
55
+ Explicit remote parents remain external references without a local
56
+ missing-parent warning. Local missing parents still follow workspace policy,
57
+ and self-parent and hierarchy-cycle checks remain enforced. A foreign-looking
58
+ bare string is treated as local unless external provenance is supplied; the
59
+ SDK does not guess a remote workspace from punctuation.
60
+
61
+ ```ts
62
+ import { normalizeItemReference } from "@unbrained/pm-cli/sdk";
63
+
64
+ normalizeItemReference("#ABC", "team-"); // team-abc
65
+ normalizeItemReference("github:Org/Repo#42", "team-"); // unchanged
66
+ normalizeItemReference("OTHER-Case", "team-", "external"); // unchanged
67
+ ```
68
+
42
69
  ## Reason Contract
43
70
 
44
71
  `resolveTerminalReason` is the pure precedence primitive. It chooses the first
@@ -72,6 +72,17 @@ exceeds temporary-filesystem capacity fails with a stable recovery contract,
72
72
  while linked tests whose effective context is schema avoid materializing
73
73
  tracker data at all.
74
74
 
75
+ Package installation applies the same boundary to `extension_install_copy`,
76
+ `extension_install_backup`, `extension_install_rollback`, and
77
+ `extension_module_graph_snapshot`. These fixed operation labels identify the
78
+ failed stage without exposing source, destination, backup, or temporary paths.
79
+ Capacity and permission faults are not transient copy races and are not retried;
80
+ existing bounded retries for concurrent filesystem changes remain available.
81
+ The shared implementation lives under `core/fs`, while the public SDK exports
82
+ remain stable for package authors. This coverage does not imply that every
83
+ filesystem operation in the repository has adopted the boundary; the complete
84
+ migration and recurrence-gate obligation remains tracked in `pm-3lhth4`.
85
+
75
86
  Existing SDK surfaces can supply category-specific `codes` to preserve their
76
87
  published error vocabulary while still sharing classification, path redaction,
77
88
  and recovery guidance. Workspace snapshots use this compatibility path for
@@ -28,7 +28,7 @@ This file is generated by `listPmFlagLexicon()`. Compatibility aliases do not co
28
28
  | `get` | context | 30 | 30 |
29
29
  | `graph` | graph | 34 | 34 |
30
30
  | `search` | context | 78 | 78 |
31
- | `duplicates` | context | 24 | 24 |
31
+ | `duplicates` | context | 25 | 25 |
32
32
  | `eval` | context | 25 | 25 |
33
33
  | `next` | context | 38 | 38 |
34
34
  | `history` | evidence | 35 | 35 |
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.9.5"
9
+ "version": "2026.9.7"
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.9.5",
16
+ "version": "2026.9.7",
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.9.5",
3
+ "version": "2026.9.7",
4
4
  "description": "Git-native project management CLI for humans and agents.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.10.0",
@@ -224,12 +224,15 @@
224
224
  "@types/npm-package-arg": "^6.1.4",
225
225
  "@vitest/coverage-v8": "^4.1.11",
226
226
  "esbuild": "0.28.2",
227
- "eslint": "^10.9.1",
227
+ "eslint": "^10.10.0",
228
228
  "eslint-plugin-sonarjs": "^4.2.0",
229
229
  "eslint-plugin-unicorn": "74.0.0",
230
230
  "fast-check": "^4.9.0",
231
- "greptile": "^3.5.0",
231
+ "github-slugger": "2.0.0",
232
+ "greptile": "^3.5.2",
232
233
  "jscpd": "^5.1.2",
234
+ "marked": "18.0.11",
235
+ "parse5": "8.0.1",
233
236
  "tsx": "^4.23.13",
234
237
  "typescript": "^6.0.3",
235
238
  "typescript-eslint": "^8.69.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-beads",
3
- "version": "2026.9.5",
3
+ "version": "2026.9.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for importing Beads JSONL records.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-calendar",
3
- "version": "2026.9.5",
3
+ "version": "2026.9.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for calendar and agenda views.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-command-kit",
3
- "version": "2026.9.5",
3
+ "version": "2026.9.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm exemplar package for the commands capability: registerCommand, registerFlags, and registerParser.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-digital-twin",
3
- "version": "2026.9.5",
3
+ "version": "2026.9.7",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "Beyond-PM exemplar: a temporal production-facility digital twin built entirely on public pm SDK and extension primitives.",
@@ -67,7 +67,16 @@ pm normalize --dry-run --json
67
67
  ```
68
68
 
69
69
  `dedupe-audit --status all` explicitly selects every status and is equivalent
70
- to omitting the filter. For `comments-audit`, `--limit-items` caps item
70
+ to omitting the filter. The receipt retains `filters.status: "all"` for an
71
+ explicit all-status request. Configured status aliases and comma-separated OR
72
+ filters use the host SDK parser; combining `all` with another status or using
73
+ an unknown status fails. `--limit` caps returned clusters after the complete
74
+ matching item population is scanned, and unreadable source items fail the read.
75
+ Workflow terminality is captured per invocation so concurrent SDK calls cannot
76
+ exchange workspace policy. These contracts are tracked by
77
+ [pm-449do9](../../.agents/pm/issues/pm-449do9.toon).
78
+
79
+ For `comments-audit`, `--limit-items` caps item
71
80
  scanning while `--limit-rows` caps emitted comment rows across the whole
72
81
  result. The older `--limit` spelling remains a deprecated alias for
73
82
  `--limit-rows`; do not combine the two row-limit spellings.