@unbrained/pm-cli 2026.9.4 → 2026.9.6

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 (277) hide show
  1. package/.agents/skills/HARNESS_COMPATIBILITY.md +1 -1
  2. package/.agents/skills/README.md +2 -2
  3. package/.agents/skills/pm-developer/SKILL.md +4 -1
  4. package/.agents/skills/pm-developer/references/COMMAND_PLAYBOOK.md +10 -0
  5. package/.agents/skills/pm-developer/references/GRAPH_AND_RELATIONSHIPS.md +3 -1
  6. package/.agents/skills/pm-extensions/SKILL.md +2 -2
  7. package/.agents/skills/pm-extensions/references/LIFECYCLE.md +3 -3
  8. package/.agents/skills/pm-extensions/references/TROUBLESHOOTING.md +3 -3
  9. package/.agents/skills/pm-user/SKILL.md +2 -0
  10. package/.agents/skills/pm-user/references/BACKLOG_SHAPING.md +5 -0
  11. package/.agents/skills/pm-user/references/WORKFLOWS.md +20 -5
  12. package/.claude-plugin/marketplace.json +2 -2
  13. package/CHANGELOG.md +58 -3
  14. package/dist/cli/commander-usage.d.ts +2 -0
  15. package/dist/cli/commander-usage.js +15 -12
  16. package/dist/cli/help-json-payload.js +12 -7
  17. package/dist/cli/main.js +22 -11
  18. package/dist/cli/register-list-query.js +4 -2
  19. package/dist/cli/register-mutation.js +4 -2
  20. package/dist/cli/register-operations.js +17 -8
  21. package/dist/cli-bundle/bundle-manifest.json +153 -161
  22. package/dist/cli-bundle/chunks/chunk-AZDFJGH6.js +9 -0
  23. package/dist/cli-bundle/chunks/{chunk-V72UV7QS.js → chunk-BAX2BYUW.js} +73 -73
  24. package/dist/cli-bundle/chunks/{chunk-HI6BHPCU.js → chunk-CKOL5U7J.js} +51 -51
  25. package/dist/cli-bundle/chunks/{chunk-A24WAVE6.js → chunk-JT6XF6GE.js} +2 -2
  26. package/dist/cli-bundle/chunks/{chunk-I2AS367G.js → chunk-JX4DH4WC.js} +2 -2
  27. package/dist/cli-bundle/chunks/{chunk-YW4QK2G7.js → chunk-NPN5I67J.js} +2 -2
  28. package/dist/cli-bundle/chunks/chunk-OF76PSDQ.js +5 -0
  29. package/dist/cli-bundle/chunks/chunk-QUWFABDM.js +232 -0
  30. package/dist/cli-bundle/chunks/{chunk-RI4XNOYS.js → chunk-RWWBOWJ5.js} +2 -2
  31. package/dist/cli-bundle/chunks/chunk-WGAOYSYH.js +40 -0
  32. package/dist/cli-bundle/chunks/{chunk-X6CMGV6L.js → chunk-WI2AYPA7.js} +2 -2
  33. package/dist/cli-bundle/chunks/{register-list-query-Z5YYSJJG.js → register-list-query-5JL52D33.js} +3 -3
  34. package/dist/cli-bundle/chunks/{register-mutation-ELSP6I4I.js → register-mutation-ZPG7KMVP.js} +4 -4
  35. package/dist/cli-bundle/chunks/register-operations-I5W3KMGB.js +2 -0
  36. package/dist/cli-bundle/chunks/{register-setup-E2AE72QG.js → register-setup-H4SVAVX7.js} +2 -2
  37. package/dist/cli-bundle/focused-chunks/{chunk-3646BZ4W.js → chunk-3BZEOXLT.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/chunk-AL5ON6K6.js +2 -0
  39. package/dist/cli-bundle/focused-chunks/chunk-CHC2IDXA.js +6 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-CK6QFAPZ.js +20 -0
  41. package/dist/cli-bundle/focused-chunks/{chunk-NBMJD6MK.js → chunk-EZR3GHFE.js} +2 -2
  42. package/dist/cli-bundle/focused-chunks/chunk-H2WJWK7L.js +56 -0
  43. package/dist/cli-bundle/focused-chunks/{chunk-53IHPICX.js → chunk-LIJIA4TY.js} +2 -2
  44. package/dist/cli-bundle/focused-chunks/{chunk-25UJBH4M.js → chunk-M6PBRFSH.js} +2 -2
  45. package/dist/cli-bundle/focused-chunks/{chunk-AJR3OP2E.js → chunk-NTPY5GSO.js} +2 -2
  46. package/dist/cli-bundle/focused-chunks/chunk-P5O7MP5Y.js +2 -0
  47. package/dist/cli-bundle/focused-chunks/chunk-PDMW2E36.js +177 -0
  48. package/dist/cli-bundle/focused-chunks/{chunk-MHKUIPJW.js → chunk-PEFABF7E.js} +2 -2
  49. package/dist/cli-bundle/focused-chunks/{chunk-6PWPQKDN.js → chunk-QTVCLMSZ.js} +2 -2
  50. package/dist/cli-bundle/focused-chunks/{chunk-7N2TV7WZ.js → chunk-QTZRBUYA.js} +2 -2
  51. package/dist/cli-bundle/focused-chunks/chunk-SGQST3PQ.js +12 -0
  52. package/dist/cli-bundle/focused-chunks/chunk-UKHASMMP.js +10 -0
  53. package/dist/cli-bundle/focused-chunks/chunk-ZPEKQHOC.js +2 -0
  54. package/dist/cli-bundle/main.js +22 -15
  55. package/dist/cli-bundle/sdk-authoring.js +1 -1
  56. package/dist/cli-bundle/sdk-contracts.js +2 -2
  57. package/dist/cli-bundle/sdk-core.js +37 -37
  58. package/dist/cli-bundle/sdk-governance.js +1 -1
  59. package/dist/cli-bundle/sdk-graph.js +1 -1
  60. package/dist/cli-bundle/sdk-merge.js +42 -39
  61. package/dist/cli-bundle/sdk-query.js +1 -1
  62. package/dist/cli-bundle/sdk-runtime.js +1 -1
  63. package/dist/cli-bundle/sdk-testing.js +1 -1
  64. package/dist/cli-bundle/sdk.js +9 -9
  65. package/dist/core/extensions/extension-types.d.ts +2 -0
  66. package/dist/core/extensions/extension-types.js +2 -2
  67. package/dist/core/extensions/module-graph-snapshot.js +5 -4
  68. package/dist/core/fs/host-environment-errors.d.ts +27 -0
  69. package/dist/core/fs/host-environment-errors.js +142 -0
  70. package/dist/core/history/drift-scan.d.ts +5 -0
  71. package/dist/core/history/drift-scan.js +16 -6
  72. package/dist/core/history/event-classification.d.ts +1 -1
  73. package/dist/core/history/event-classification.js +3 -2
  74. package/dist/core/history/history.js +37 -5
  75. package/dist/core/history/identity.d.ts +15 -0
  76. package/dist/core/history/identity.js +31 -0
  77. package/dist/core/history/projection.js +50 -17
  78. package/dist/core/history/read.js +6 -3
  79. package/dist/core/history/replay.d.ts +1 -2
  80. package/dist/core/history/replay.js +4 -4
  81. package/dist/core/history/version-address.d.ts +13 -0
  82. package/dist/core/history/version-address.js +33 -0
  83. package/dist/core/item/actionability.d.ts +21 -1
  84. package/dist/core/item/actionability.js +45 -10
  85. package/dist/core/item/id.js +8 -4
  86. package/dist/core/item/item-type-definition.d.ts +2 -0
  87. package/dist/core/item/item-type-definition.js +9 -2
  88. package/dist/core/item/type-registry.d.ts +5 -1
  89. package/dist/core/item/type-registry.js +9 -4
  90. package/dist/core/output/mutation-projection.js +12 -5
  91. package/dist/core/shared/errors.d.ts +8 -0
  92. package/dist/core/shared/errors.js +2 -2
  93. package/dist/core/store/item-metadata-query-index.js +13 -10
  94. package/dist/core/store/item-metadata-read-work.d.ts +19 -0
  95. package/dist/core/store/item-metadata-read-work.js +44 -0
  96. package/dist/core/store/item-store.d.ts +14 -0
  97. package/dist/core/store/item-store.js +52 -10
  98. package/dist/core/store/settings-validator.js +3 -2
  99. package/dist/core/validate/fix-planning.d.ts +1 -1
  100. package/dist/core/validate/fix-planning.js +2 -2
  101. package/dist/core/validate/missing-link-owners.d.ts +1 -1
  102. package/dist/core/validate/missing-link-owners.js +5 -3
  103. package/dist/core/validate/stale-file-classification.d.ts +6 -4
  104. package/dist/core/validate/stale-file-classification.js +20 -5
  105. package/dist/mcp/server.js +12 -5
  106. package/dist/sdk/actionability.d.ts +1 -1
  107. package/dist/sdk/actionability.js +3 -3
  108. package/dist/sdk/cli-contracts/command-aliases.js +11 -2
  109. package/dist/sdk/cli-contracts/completeness.js +4 -3
  110. package/dist/sdk/cli-contracts/flag-contracts.d.ts +2 -0
  111. package/dist/sdk/cli-contracts/flag-contracts.js +31 -5
  112. package/dist/sdk/cli-contracts/flag-lexicon-contracts.js +21 -13
  113. package/dist/sdk/cli-contracts/grammar-contracts.js +11 -2
  114. package/dist/sdk/cli-contracts/runtime-contracts.js +5 -2
  115. package/dist/sdk/cli-contracts/schemas/assurance-definition.d.ts +254 -5
  116. package/dist/sdk/cli-contracts/schemas/assurance-definition.js +52 -2
  117. package/dist/sdk/cli-contracts/tool-parameter-tables.js +30 -6
  118. package/dist/sdk/cli-contracts/tool-schema.d.ts +2 -2
  119. package/dist/sdk/cli-contracts/tool-schema.js +32 -7
  120. package/dist/sdk/context/usage-ledger.d.ts +41 -0
  121. package/dist/sdk/context/usage-ledger.js +186 -0
  122. package/dist/sdk/context-intent-contracts.js +3 -3
  123. package/dist/sdk/context-usage.d.ts +18 -9
  124. package/dist/sdk/context-usage.js +44 -121
  125. package/dist/sdk/define.d.ts +1 -1
  126. package/dist/sdk/define.js +2 -2
  127. package/dist/sdk/dependency-provenance.d.ts +7 -0
  128. package/dist/sdk/dependency-provenance.js +14 -4
  129. package/dist/sdk/duplicates.d.ts +2 -0
  130. package/dist/sdk/duplicates.js +3 -2
  131. package/dist/sdk/environment/host-environment-errors.d.ts +5 -27
  132. package/dist/sdk/environment/host-environment-errors.js +4 -137
  133. package/dist/sdk/extension/install-runtime.js +9 -6
  134. package/dist/sdk/extension/install-snapshot.js +7 -6
  135. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +104 -56
  136. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +50 -2
  137. package/dist/sdk/governance/assurance-action.d.ts +3 -2
  138. package/dist/sdk/governance/assurance-action.js +23 -11
  139. package/dist/sdk/governance/assurance-runtime.d.ts +2 -0
  140. package/dist/sdk/governance/assurance-runtime.js +6 -3
  141. package/dist/sdk/governance/defect-recurrence-coverage.d.ts +93 -0
  142. package/dist/sdk/governance/defect-recurrence-coverage.js +189 -0
  143. package/dist/sdk/governance/defect-recurrence-graph.d.ts +33 -0
  144. package/dist/sdk/governance/defect-recurrence-graph.js +121 -0
  145. package/dist/sdk/governance/defect-recurrence.d.ts +8 -0
  146. package/dist/sdk/governance/defect-recurrence.js +118 -17
  147. package/dist/sdk/governance/health.d.ts +17 -2
  148. package/dist/sdk/governance/health.js +31 -10
  149. package/dist/sdk/governance/linked-file-report.d.ts +41 -0
  150. package/dist/sdk/governance/linked-file-report.js +72 -0
  151. package/dist/sdk/governance/validate-history-drift.js +16 -5
  152. package/dist/sdk/governance/validate.d.ts +5 -2
  153. package/dist/sdk/governance/validate.js +21 -37
  154. package/dist/sdk/governance.d.ts +2 -0
  155. package/dist/sdk/governance.js +4 -2
  156. package/dist/sdk/guide-topics.js +116 -2
  157. package/dist/sdk/history/salvage.d.ts +35 -0
  158. package/dist/sdk/history/salvage.js +248 -0
  159. package/dist/sdk/history-compact.js +32 -37
  160. package/dist/sdk/history-read.d.ts +3 -2
  161. package/dist/sdk/history-read.js +6 -3
  162. package/dist/sdk/history-repair.d.ts +12 -0
  163. package/dist/sdk/history-repair.js +60 -13
  164. package/dist/sdk/lifecycle/claim.d.ts +4 -0
  165. package/dist/sdk/lifecycle/claim.js +9 -3
  166. package/dist/sdk/lifecycle/close.d.ts +8 -0
  167. package/dist/sdk/lifecycle/close.js +16 -8
  168. package/dist/sdk/lifecycle/create.js +9 -12
  169. package/dist/sdk/lifecycle/restore.d.ts +1 -0
  170. package/dist/sdk/lifecycle/restore.js +19 -7
  171. package/dist/sdk/lifecycle/update.js +12 -12
  172. package/dist/sdk/lifecycle-policy.d.ts +3 -0
  173. package/dist/sdk/lifecycle-policy.js +2 -2
  174. package/dist/sdk/merge/abandoned-receipts.d.ts +15 -0
  175. package/dist/sdk/merge/abandoned-receipts.js +47 -0
  176. package/dist/sdk/merge/driver.js +4 -2
  177. package/dist/sdk/merge/index.d.ts +1 -0
  178. package/dist/sdk/merge/index.js +2 -2
  179. package/dist/sdk/merge/receipt-operation.d.ts +15 -0
  180. package/dist/sdk/merge/receipt-operation.js +97 -0
  181. package/dist/sdk/merge/receipt-schema.d.ts +20 -0
  182. package/dist/sdk/merge/receipt-schema.js +398 -0
  183. package/dist/sdk/merge/receipts.d.ts +16 -7
  184. package/dist/sdk/merge/receipts.js +54 -340
  185. package/dist/sdk/merge/reconcile.d.ts +2 -0
  186. package/dist/sdk/merge/reconcile.js +11 -4
  187. package/dist/sdk/output-projection.d.ts +3 -1
  188. package/dist/sdk/output-projection.js +11 -3
  189. package/dist/sdk/public-surface.json +1 -0
  190. package/dist/sdk/query/context.d.ts +9 -0
  191. package/dist/sdk/query/context.js +33 -21
  192. package/dist/sdk/query/duplicate-candidates.d.ts +7 -0
  193. package/dist/sdk/query/duplicate-candidates.js +71 -0
  194. package/dist/sdk/query/get.d.ts +2 -2
  195. package/dist/sdk/query/get.js +9 -8
  196. package/dist/sdk/query/history.d.ts +11 -0
  197. package/dist/sdk/query/history.js +34 -10
  198. package/dist/sdk/query/next.d.ts +15 -1
  199. package/dist/sdk/query/next.js +43 -20
  200. package/dist/sdk/query.d.ts +3 -0
  201. package/dist/sdk/query.js +5 -2
  202. package/dist/sdk/read-output-session.js +5 -3
  203. package/dist/sdk/runtime-primitives.d.ts +1 -1
  204. package/dist/sdk/runtime-primitives.js +3 -3
  205. package/dist/sdk/runtime.js +4 -2
  206. package/dist/sdk/similarity.d.ts +24 -3
  207. package/dist/sdk/similarity.js +50 -55
  208. package/dist/types.d.ts +2 -0
  209. package/dist/types.js +2 -2
  210. package/docs/AGENT_GUIDE.md +58 -1
  211. package/docs/BOUNDED_CONTEXT_READS.md +185 -0
  212. package/docs/CLOSE_EVIDENCE_RECOVERY.md +35 -0
  213. package/docs/COMMANDS.md +30 -8
  214. package/docs/CONTEXT_RELEVANCE.md +16 -4
  215. package/docs/DEFECT_RECURRENCE.md +80 -6
  216. package/docs/EXTENSIONS.md +18 -19
  217. package/docs/HISTORY_RECOVERY.md +146 -0
  218. package/docs/MERGE_SAFETY.md +50 -0
  219. package/docs/OUTPUT_PROJECTION_CONTRACTS.md +66 -0
  220. package/docs/PR_REVIEW_LOOP.md +18 -3
  221. package/docs/README.md +19 -1
  222. package/docs/RELEASING.md +31 -13
  223. package/docs/SDK_CONTEXT_TRUTH_CONTRACTS.md +24 -1
  224. package/docs/SDK_EXECUTION_CONTRACTS.md +105 -0
  225. package/docs/SDK_LIFECYCLE.md +27 -0
  226. package/docs/SDK_RUNTIME_BOUNDARIES.md +11 -0
  227. package/docs/TESTING.md +5 -0
  228. package/docs/agent-task-token-baseline.json +17 -17
  229. package/docs/agent-task-transcripts.json +2 -1
  230. package/docs/generated/FLAG_LEXICON_BUDGETS.md +11 -11
  231. package/docs/generated/REFUSAL_CLOSURE_CENSUS.md +11 -3
  232. package/marketplace.json +2 -2
  233. package/package.json +8 -6
  234. package/packages/pm-beads/package.json +1 -1
  235. package/packages/pm-calendar/package.json +1 -1
  236. package/packages/pm-command-kit/package.json +1 -1
  237. package/packages/pm-digital-twin/package.json +1 -1
  238. package/packages/pm-governance-audit/README.md +10 -1
  239. package/packages/pm-governance-audit/extensions/governance-audit/dedupe-audit.ts +50 -65
  240. package/packages/pm-governance-audit/extensions/governance-audit/index.ts +2 -2
  241. package/packages/pm-governance-audit/extensions/governance-audit/sdk.ts +1 -0
  242. package/packages/pm-governance-audit/package.json +1 -1
  243. package/packages/pm-guide-shell/package.json +1 -1
  244. package/packages/pm-kanban/package.json +1 -1
  245. package/packages/pm-lifecycle-hooks/package.json +1 -1
  246. package/packages/pm-linked-test-adapters/package.json +1 -1
  247. package/packages/pm-search-advanced/package.json +1 -1
  248. package/packages/pm-templates/package.json +1 -1
  249. package/packages/pm-todos/package.json +1 -1
  250. package/packages/pm-vcs/package.json +1 -1
  251. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  252. package/plugins/pm-claude/skills/pm-audit/SKILL.md +2 -2
  253. package/plugins/pm-claude/skills/pm-developer/SKILL.md +2 -2
  254. package/plugins/pm-claude/skills/pm-planner/SKILL.md +2 -2
  255. package/plugins/pm-claude/skills/pm-release/SKILL.md +2 -2
  256. package/plugins/pm-claude/skills/pm-workflow/SKILL.md +3 -3
  257. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  258. package/plugins/pm-codex/skills/pm-auditor/SKILL.md +2 -2
  259. package/plugins/pm-codex/skills/pm-native/SKILL.md +3 -4
  260. package/plugins/pm-codex/skills/pm-release/SKILL.md +2 -2
  261. package/scripts/finalize-build.mjs +13 -1
  262. package/dist/cli-bundle/chunks/chunk-6XSKPNCF.js +0 -230
  263. package/dist/cli-bundle/chunks/chunk-OGBVU67G.js +0 -5
  264. package/dist/cli-bundle/chunks/chunk-TXW6VL33.js +0 -38
  265. package/dist/cli-bundle/chunks/chunk-VGLHECAP.js +0 -9
  266. package/dist/cli-bundle/chunks/register-operations-OH7R3ZT4.js +0 -2
  267. package/dist/cli-bundle/focused-chunks/chunk-4YRAVI43.js +0 -12
  268. package/dist/cli-bundle/focused-chunks/chunk-5P4HVOWG.js +0 -176
  269. package/dist/cli-bundle/focused-chunks/chunk-636VVQ7F.js +0 -54
  270. package/dist/cli-bundle/focused-chunks/chunk-B3A6MJYE.js +0 -2
  271. package/dist/cli-bundle/focused-chunks/chunk-BFDDJ2T2.js +0 -2
  272. package/dist/cli-bundle/focused-chunks/chunk-BHUIRZWQ.js +0 -9
  273. package/dist/cli-bundle/focused-chunks/chunk-JADHHPY6.js +0 -6
  274. package/dist/cli-bundle/focused-chunks/chunk-NSKBLHVI.js +0 -20
  275. package/dist/cli-bundle/focused-chunks/chunk-P2GOAOQN.js +0 -2
  276. package/dist/cli-bundle/focused-chunks/chunk-YARWJM2B.js +0 -2
  277. package/sdk/public-surface.json +0 -33034
@@ -91,11 +91,15 @@ Package roots declare resources in `package.json` under `pm`:
91
91
  ```
92
92
 
93
93
  Installation activates `pm.extensions`. `pm.docs`, `pm.examples`, `pm.assets`, and `pm.prompts` are catalog metadata (metadata-only — they are discovered and surfaced in the catalog but not executed). Declare agent-facing prompt/slash-command markdown under `pm.prompts` and non-code assets (images, skills, fixtures) under `pm.assets`; their conventional roots are `prompts/` (also `.agents/pm/prompts/`) and `assets/` (also `.agents/pm/assets/`).
94
- `pm package init` and its compatibility spelling `pm extension init` emit the same publishable root-extension artifact (`"extensions": ["."]`): package metadata, a typed `index.ts`, a colocated `node:test` suite, a strict type-check-only `tsconfig.json`, and `typecheck`/`test` scripts. Both results report the canonical `package_name` and exact `invocation_command`; an already prefixed target such as `pm-my-workflow` stays `pm-my-workflow` instead of becoming `pm-pm-my-workflow`. The manifest `entry` points at `./index.ts` itself (ADR [pm-2c28](../.agents/pm/decisions/pm-2c28.toon) / [pm-m1uz](../.agents/pm/decisions/pm-m1uz.toon)). pm loads that `.ts` entry directly via Node's native type stripping (Node >=22.18), so there is no build step — run `npm install` (for the peer SDK and type-checking) before `pm package install`. The generated README shows how to author exported command/hook definitions with the SDK [define\* builders](../.agents/pm/decisions/pm-3mph.toon). `--capability` selects one of ten scaffold starters (`commands`, `hooks`, `search`, `importers`, `schema`, `profile`, `renderers`, `parser`, `preflight`, `services`), each keeping a runnable starter command and adding the selected registration pattern plus a colocated `node:test` suite built on the matching SDK `assertRegistered*`/`runRegistered*ForTest` helpers. These are authoring selectors, not a one-to-one manifest-capability vocabulary: the `profile` starter registers a profile but declares the supported `schema` manifest capability because `api.registerProfile` is schema-governed. The option is repeatable for shell and config composition: repeating the same capability is idempotent, while combining distinct starter shapes fails with a usage error that asks the author to select one explicit scaffold capability. The full per-capability matrix (what each starter registers, which starters also declare `schema` because flag metadata is schema-governed, and why `schema`/`profile` omit `activation.commands` so their global contributions activate conservatively for every command) lives in [SDK.md — Minimal Command Extension](./SDK.md#minimal-command-extension). Starter manifests use the same least-privilege policy metadata as pure first-party command packages: `trusted: true`, `sandbox_profile: "strict"`, and explicit `false` permissions for `fs_read`, `fs_write`, `network`, `env_read`, `env_write`, and `process_spawn`. Declarative starters import `manifest.json` in their generated test and call `assertExtensionManifestMatchesBlueprint`, so capability drift fails locally before publication. Larger packages may point at nested extension directories after declaring runtime dependencies, relaxing only the permissions they actually need, and validating with `pm package doctor`, which additionally emits the advisory `extension_schema_narrow_activation` warning when a package registers custom item types/fields yet declares narrow `activation.commands` (the schema footgun above), recommending the field be dropped so the type stays globally available.
95
- Package tests can pair `readPmPackageManifest(packageRoot)` with
96
- `assertPackageManifest(manifest, { resources: ... })` from
97
- `@unbrained/pm-cli/sdk` to prove aliases and resource paths without duplicating
98
- pm's manifest normalization logic.
94
+ `pm package init` (and compatible `pm extension init`) creates a publishable root extension (`"extensions": ["."]`):
95
+
96
+ - The artifact includes package metadata, typed `index.ts`, a colocated `node:test` suite, strict type-check-only `tsconfig.json`, and `typecheck`/`test` scripts. Results report canonical `package_name` and exact `invocation_command`; an existing `pm-` prefix is retained once.
97
+ - The manifest points to `./index.ts`, loaded by native TypeScript stripping on Node >=22.18 ([pm-2c28](../.agents/pm/decisions/pm-2c28.toon), [pm-m1uz](../.agents/pm/decisions/pm-m1uz.toon)). Run `npm install` for the peer SDK and type checking before package installation; no build step is required. The README demonstrates the SDK [define* builders](../.agents/pm/decisions/pm-3mph.toon).
98
+ - `--capability` selects `commands`, `hooks`, `search`, `importers`, `schema`, `profile`, `renderers`, `parser`, `preflight`, or `services`. Every starter keeps a runnable command and adds matching SDK `assertRegistered*`/`runRegistered*ForTest` tests. Repeating one selection is idempotent; distinct selections fail with an actionable usage error.
99
+ - Scaffold selectors and manifest capabilities differ: `profile` registers a profile under `schema`. The [capability matrix](SDK.md#minimal-command-extension) explains each registration, schema-governed flags, and why `schema`/`profile` omit narrow `activation.commands` so their contributions stay globally available.
100
+ - Starter manifests declare `trusted: true`, `sandbox_profile: "strict"`, and explicit false permissions for filesystem, network, environment, and subprocess access. Declarative tests import `manifest.json` and call `assertExtensionManifestMatchesBlueprint`, detecting capability drift before publication.
101
+ - Larger packages may use nested extension directories and declare required runtime dependencies and permissions. Validate with `pm package doctor`; its advisory `extension_schema_narrow_activation` finding recommends removing narrow activation when custom item types or fields need global availability.
102
+ Package tests can pair `readPmPackageManifest(packageRoot)` with `assertPackageManifest(manifest, { resources: ... })` from `@unbrained/pm-cli/sdk` to prove aliases and resource paths without duplicating pm's manifest normalization logic.
99
103
 
100
104
  When no package manifest is present, `pm` discovers conventional extension directories:
101
105
 
@@ -115,7 +119,11 @@ Runtime path overrides:
115
119
  - `PM_PATH`: project tracker root
116
120
  - `PM_GLOBAL_PATH`: global profile root
117
121
 
118
- Extensions are authored **and loaded** as TypeScript (ADR [pm-2c28](../.agents/pm/decisions/pm-2c28.toon) / [pm-m1uz](../.agents/pm/decisions/pm-m1uz.toon)): a minimal standalone extension has a `manifest.json` and a TypeScript `index.ts` entrypoint the loader imports directly by file URL via Node's native type stripping (Node >=22.18) — there is no compile step and no `./index.js`. Author against the SDK types with `import type { ExtensionApi }` — the type-only import is erased on load, so the `.ts` entry carries **no runtime import** of `@unbrained/pm-cli` (standalone entries are loaded outside any `node_modules`, so a runtime SDK import would fail). Type-check with `npx tsc --noEmit` after installing `typescript` and `@unbrained/pm-cli` for the type resolution.
122
+ Extensions are authored and loaded as TypeScript ([pm-2c28](../.agents/pm/decisions/pm-2c28.toon), [pm-m1uz](../.agents/pm/decisions/pm-m1uz.toon)):
123
+
124
+ - A minimal standalone extension has `manifest.json` and `index.ts`. Node >=22.18 loads that entry directly with native type stripping; no compilation or `index.js` is required.
125
+ - Use `import type { ExtensionApi }` for erased SDK types. Standalone entries outside `node_modules` need the host SDK link described below before using runtime SDK imports.
126
+ - Install `typescript` and `@unbrained/pm-cli`, then run `npx tsc --noEmit` to check authoring types.
119
127
 
120
128
  ```json
121
129
  {
@@ -279,7 +287,7 @@ Surface tokens include command handlers/overrides, parser/preflight/services/ren
279
287
 
280
288
  Some extension surfaces are intentionally single-winner: command handlers and overrides, parser overrides, preflight overrides, and format renderers. Activation is deterministic: lower manifest `priority` values load first, omitted priority defaults to `100`, equal priorities sort by package identity/path, and the last registration wins. If multiple packages register the same single-winner surface, `pm package doctor` / `pm health` report deterministic `extension_*_collision` warnings whose suffix names the winning layer/package before the displaced layer/package. `pm package describe --json` also exposes `command_ownership`: every claimant in activation order, the effective winner, collision state, and the explicit `last_activated_wins` policy. SDK hosts can build the identical table with `buildExtensionDescribeResult` and the exported `ExtensionCommandOwnership` contracts. Renderer ownership is evaluated per command: same-format renderers with disjoint `commands` lists safely coexist, while an unscoped or overlapping claim still warns; runtime `resultDiscriminator` predicates alone cannot prove static disjointness. Tracked by [pm-6mjxgq](../.agents/pm/issues/pm-6mjxgq.toon).
281
289
 
282
- For definition-based commands, validation is isolated per command: a malformed definition is recorded as `extension_command_quarantined:*` with a registration trace while valid siblings continue to activate. Unknown-command recovery reports that failure without recommending reinstallation.
290
+ For definition-based commands, a malformed definition is recorded as `extension_command_quarantined:*` with a registration trace. Activation then rolls back all registrations from that extension, preserving atomic package activation. Fix the failed definition before expecting sibling commands to load. Other valid extensions retain their registrations.
283
291
  Use the warning details to resolve the overlap:
284
292
 
285
293
  ```bash
@@ -294,12 +302,6 @@ Doctor JSON also includes `triage.collision_plan` with grouped surfaces, ranked
294
302
 
295
303
  Use the public SDK barrel. Do not deep-import from `src/core` or `dist/core`.
296
304
 
297
- ```ts
298
- import { defineExtension } from "@unbrained/pm-cli/sdk";
299
- ```
300
-
301
- Common APIs:
302
-
303
305
  - `api.extension` is a read-only identity (`name`, `layer`, `version`, `capabilities`, `pm_min_version?`, `pm_max_version?`, `source_package?`) for self-identifying logs and version gating without re-reading the manifest.
304
306
  - `api.registerCommand(definition)` adds package-owned commands.
305
307
  - `api.registerFlags(command, flags)` adds runtime command flags. A flag may declare `value_type` (canonical; the legacy `type` alias is honored only when `value_type` is absent), `list: true` to accumulate repeated/comma-joined values like core `--tags`, and a `default` applied when the flag is omitted.
@@ -331,6 +333,8 @@ pm contracts --runtime-only --schema-only --json
331
333
  pm contracts --command <command> --flags-only --json
332
334
  ```
333
335
 
336
+ `CliFlagContract.reservation_scope` tells package authors which host flags are reserved: `inherited` flags (including their aliases) cannot be redeclared by extensions; `root_only` flags belong only to the root command. The public `GLOBAL_FLAG_CONTRACTS` table from `@unbrained/pm-cli/sdk/contracts` exposes the same classification used by runtime validation. For example, an extension may define its own boolean `--explain`; root `pm --explain` keeps its host meaning. Redeclaring inherited `--json` fails validation and rolls back that package's activation. See [pm-2h8t6y](../.agents/pm/issues/pm-2h8t6y.toon).
337
+
334
338
  List-valued inline flags and `registerFlags` entries share one ordered
335
339
  accumulator across their long and short aliases. For a variadic positional that
336
340
  must receive values such as `-h` or `--json`, put the end-of-options separator
@@ -381,8 +385,6 @@ pm package reload --project
381
385
  pm package reload --project --watch
382
386
  ```
383
387
 
384
- Compatibility equivalents remain available through `pm extension ...` for existing automation.
385
-
386
388
  ## Upgrade Workflow
387
389
 
388
390
  `pm package upgrade` is the package-first update entrypoint:
@@ -443,7 +445,4 @@ Prefer `createExtensionTestHarness(module, { capabilities })` in package unit te
443
445
 
444
446
  ## Runnable Examples
445
447
 
446
- - `docs/examples/starter-extension/`
447
- - `docs/examples/policy-restricted-extension/`
448
- - `docs/examples/sdk-contract-consumer/`
449
- - `docs/examples/sdk-app-embedding/`
448
+ See the [starter](examples/starter-extension/README.md), [policy-restricted](examples/policy-restricted-extension/README.md), [SDK contract consumer](examples/sdk-contract-consumer/README.md), and [SDK application](examples/sdk-app-embedding/README.md) examples.
@@ -0,0 +1,146 @@
1
+ # History durability and recovery
2
+
3
+ Tracked by [pm-96fsma](../.agents/pm/issues/pm-96fsma.toon),
4
+ [pm-m0yjtg](../.agents/pm/issues/pm-m0yjtg.toon),
5
+ [pm-qw1uw6](../.agents/pm/issues/pm-qw1uw6.toon),
6
+ [pm-e3gn0z](../.agents/pm/issues/pm-e3gn0z.toon), and
7
+ [pm-wlqxg3](../.agents/pm/tasks/pm-wlqxg3.toon).
8
+
9
+ Project management depends on trustworthy context. History is not just an
10
+ activity feed: it is the reconstructable source for prior item states, including
11
+ their evidence, relationships, and lifecycle transitions. Recovery must not
12
+ manufacture missing context or silently change an item's identity.
13
+
14
+ ## Stable addresses after compaction
15
+
16
+ `pm get <id> --at <version>` and `pm restore <id> <version>` use durable,
17
+ one-based version addresses. Compaction checkpoints the last compacted state
18
+ at its original version. Retained entries keep their addresses, including after
19
+ repeated compactions. Versions before the checkpoint fail with
20
+ `history_version_pruned`; they never select a different retained entry.
21
+
22
+ The checkpoint records `history_compaction.version_offset`. Add that offset to
23
+ a physical one-based stream position to obtain its durable version. `pm history`
24
+ reports `version_addressing`, and compact rows include their `version` alongside
25
+ the physical `index`. Verification error ordinals and diff indices remain
26
+ physical positions in the current stream. The checkpoint timestamp is the last
27
+ compacted entry's timestamp; the maintenance audit event records compaction time.
28
+
29
+ Legacy checkpoints without a recorded offset cannot prove their original
30
+ numeric addresses. Numeric reads fail with `history_version_mapping_unavailable`.
31
+ Use a retained timestamp instead; the SDK then returns `as_of_version: null`.
32
+ SDK consumers must handle this nullable value. `target.historyIndex` is always
33
+ the resolved physical zero-based position, not an original version number.
34
+ Default and timestamp-based compaction remain available for these legacy
35
+ streams. They preserve an unknown offset as `null`, including no-op results;
36
+ compaction never manufactures a numeric mapping from physical positions.
37
+
38
+ ## Recover an unreadable item file
39
+
40
+ ```bash
41
+ pm history <id> --full
42
+ pm restore <id> <version>
43
+ pm history <id> --verify --strict-exit
44
+ ```
45
+
46
+ Restore accepts an absent file or an unparsable item document when intact
47
+ history can reconstruct it. It verifies the history before using the recovered
48
+ state, preserves the original unreadable bytes for rollback, and uses the normal
49
+ ownership and lock checks. Successful recovery reports
50
+ `restore_unreadable_item_recovered`. Permission errors and unresolved merge
51
+ conflicts are not treated as missing files. A missing initial baseline returns
52
+ `history_baseline_unavailable` with recovery guidance rather than inventing
53
+ metadata from a partial patch.
54
+
55
+ CLI shape errors name the item ID, file path, and zero-length files. The SDK
56
+ error context also includes byte length and an explicit empty-file flag.
57
+ `pm health --check-only` names malformed item paths and invalid
58
+ history lines without mutating either file; use those diagnostics to select the
59
+ specific recovery operation above.
60
+
61
+ Invalid UTF-8 is a separate refusal (`item_document_encoding_invalid`), not a
62
+ recoverable text parse failure. Preserve a binary backup before recovering such
63
+ a file; text decoding must never silently replace original bytes.
64
+ Its SDK error context identifies the item ID, path, byte length, and nonempty
65
+ state just as text-shape diagnostics do.
66
+
67
+ ## Recover an invalid history tail
68
+
69
+ Keep a local backup before applying destructive history maintenance. Preview
70
+ exactly one stream, inspect the receipt, then explicitly apply:
71
+
72
+ ```bash
73
+ pm history-repair <id> --salvage-tail --dry-run --json
74
+ pm history-repair <id> --salvage-tail --json
75
+ pm history <id> --verify --strict-exit
76
+ ```
77
+
78
+ Salvage requires a nonempty, hash-verified prefix and retains its bytes unchanged.
79
+ The receipt records the first invalid physical line, discarded UTF-8 byte count,
80
+ discarded-suffix SHA-256, and retained record count. An appended `history_salvage`
81
+ event records that receipt without copying potentially private damaged contents.
82
+ Salvage does not rehash prior entries, reconcile item state, or normalize
83
+ provenance. It refuses bulk selection, conflicting repair modes, merge conflict
84
+ markers, parseable records after corruption, and potentially complete records
85
+ with attached corruption. Recover those cases from version control or a backup.
86
+ Non-UTF-8 streams are also refused, so receipt hashes and rollback snapshots
87
+ always describe the original bytes rather than a lossy decoded approximation.
88
+
89
+ The public SDK uses the same operation:
90
+
91
+ ```ts
92
+ import { PmClient } from "@unbrained/pm-cli";
93
+
94
+ const client = new PmClient({ pmRoot: "/project/.agents/pm" });
95
+ const preview = await client.historyRepair("pm-example", {
96
+ salvageTail: true,
97
+ dryRun: true,
98
+ });
99
+ console.log(preview.salvage);
100
+ ```
101
+
102
+ The CLI and MCP expose this SDK-owned contract; package authors do not need a
103
+ separate recovery implementation.
104
+
105
+ ## Permanent item identities
106
+
107
+ Deleting an item retains its identity reservation through its history file.
108
+ Generated IDs skip those reservations, even under reproducible execution.
109
+ Explicit recreation fails with `item_identity_reserved`; use restore to recover
110
+ the original subject, or create a new ID for unrelated work.
111
+ The first `create` append exclusively creates its effective history file, so
112
+ concurrent SDK callers and extension redirects cannot both reserve it. A failed
113
+ partial first write keeps the reservation for diagnosis; it is never deleted
114
+ to make the identity reusable. Subsequent large-record appenders still need the
115
+ normal item lock or an equivalent caller-owned serialization boundary.
116
+
117
+ Verification refuses a second `create` event, including one imported through
118
+ branch union, and names both physical ordinals. Point-in-time reads cannot cross
119
+ that discontinuity silently. Recover the original streams rather than rehashing
120
+ two unrelated subjects into a single supposedly valid item.
121
+
122
+ `pm validate --check-history-drift` reports this as an error, with item ID,
123
+ original and repeated genesis ordinals, and the observed sequence. The public
124
+ `findHistoryIdentityDiscontinuities` SDK primitive provides the same evidence
125
+ for importers. A delete followed by create is distinguished from multiple creates
126
+ or a checkpoint followed by create; these observations do not prove which
127
+ writer or branch introduced the records. Old drift caches are invalidated, and
128
+ known-invalid streams are reread even in metadata-cache mode.
129
+
130
+ ## Regression verification
131
+
132
+ ```bash
133
+ node scripts/run-tests.mjs test -- tests/integration/history-durability.integration.spec.ts
134
+ node scripts/run-tests.mjs test -- tests/integration/history-maintenance-replay.integration.spec.ts
135
+ ```
136
+
137
+ The fixture drives real CLI lifecycle mutations, independently captures each
138
+ serialized state, removes the live item file, and compares every addressable
139
+ version against those captures. Companion cases exercise repeated compaction,
140
+ legacy mapping refusal, seeded identity reuse, invalid-tail preservation,
141
+ unreadable-file recovery, and missing baselines. Maintenance fixtures additionally
142
+ perform redaction and a real divergent Git merge, compare every version with an
143
+ independent strict patch fold, and compare the final state with a separately
144
+ read item. Concurrent writes and binary corruption are negative controls, not
145
+ mocked successful outcomes. All fixtures use temporary trackers, never repository
146
+ tracker data.
@@ -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
@@ -81,6 +81,7 @@ pm guide release --json
81
81
  - [Extension Lifecycle Contracts](EXTENSION_LIFECYCLE.md) - source identity, durable migrations, and scoped preflight ownership.
82
82
  - [Extension Author Contracts](EXTENSION_AUTHOR_CONTRACTS.md) - the stability guarantees and contract surface package authors build against.
83
83
  - [SDK](SDK.md) - public import surfaces and typed authoring examples.
84
+ - [SDK execution and recovery contracts](SDK_EXECUTION_CONTRACTS.md): schema-driven scheduling, handoff, and command recovery.
84
85
  - [Multi-Branch Merge Safety](MERGE_SAFETY.md) - semantic tracker merge drivers, post-merge integrity gates, delete/modify policy, and recovery-receipt retention.
85
86
  - [Codex Plugin](CODEX_PLUGIN.md) - native MCP plugin install, tools, skills, and safety notes.
86
87
  - [Native ChatGPT and Codex Plugin Implementation Plan](CHATGPT_CODEX_PLUGIN_IMPLEMENTATION.md) - official-source
@@ -90,6 +91,17 @@ pm guide release --json
90
91
  - [Releasing](RELEASING.md) - maintainer release checklist and failure handling.
91
92
  - [starter extension](examples/starter-extension/README.md) - compact extension scaffold reference.
92
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
+
93
105
  ## Guide Topic Map
94
106
 
95
107
  | Optional `pm guide` topic | Primary docs |
@@ -151,4 +163,10 @@ Public docs must not link to ignored local operations artifacts, unpublished evi
151
163
  - Put a short "Agent Quick Context" near the top of deep docs.
152
164
  - Prefer commands that agents can copy exactly.
153
165
  - Use `pm` item IDs as durable references when docs explain tracked work.
154
- - 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
@@ -30,7 +30,10 @@ authoritative blocker-recovery run selection by
30
30
  [pm-db8onn](../.agents/pm/issues/pm-db8onn.toon), and queued automatic
31
31
  same-day recovery by [pm-dm2vfz](../.agents/pm/issues/pm-dm2vfz.toon).
32
32
  Bounded Sentry request latency is tracked by
33
- [pm-b9g2cs](../.agents/pm/issues/pm-b9g2cs.toon).
33
+ [pm-b9g2cs](../.agents/pm/issues/pm-b9g2cs.toon), and exact-tag changelog
34
+ stabilization by [pm-e63v1x](../.agents/pm/issues/pm-e63v1x.toon). Dual-phase
35
+ package sizing around Sentry injection is tracked by
36
+ [pm-llbnua](../.agents/pm/issues/pm-llbnua.toon).
34
37
 
35
38
  ## Version Policy
36
39
 
@@ -278,8 +281,12 @@ The automatic release commit is the sole non-identical-tree derivation. The
278
281
  gate requires one parent, the canonical release subject and body, an immutable
279
282
  `v<version>` tag resolving to the candidate, the complete expected manifest
280
283
  inventory, exact old-version to new-version substitutions in every manifest,
281
- and an exact `Unreleased` changelog-heading replacement. It then resolves the
282
- parent through the same exact or reviewed identical-tree analyzer contract.
284
+ and an exact `Unreleased` changelog-heading replacement. The package-generated
285
+ replacement may be `## <version>` or the historical
286
+ `## <version> - <YYYY-MM-DD>` form, with the date matching the calendar version.
287
+ The complete heading must match and every other changelog byte must remain
288
+ unchanged. The gate then resolves the parent through the same exact or reviewed
289
+ identical-tree analyzer contract.
283
290
  Added, deleted, renamed, missing, or otherwise modified paths are refused, as
284
291
  are malformed manifests, changelog edits, untagged commits, and parents without
285
292
  successful analyzer evidence. The receipt reports
@@ -333,7 +340,12 @@ The static phase includes `pnpm sdk:surface:check`,
333
340
  `pnpm benchmark:transport:check`. The packaging phase runs
334
341
  `pnpm quality:package-artifact`, which evaluates npm's actual packlist against
335
342
  the committed unpacked-size, file-count, required-runtime-file, and forbidden
336
- source-map budgets. Additive SDK exports require a reviewed
343
+ source-map budgets. Release additionally reruns the packlist gate immediately
344
+ after Sentry debug-ID injection and before any Sentry upload or finalization,
345
+ using the separately committed `sentry-injected` ceiling. CI constrains the base
346
+ build, publication constrains the exact mutated artifact users install, and a
347
+ rejected package cannot leave finalized observability artifacts. Additive SDK
348
+ exports require a reviewed
337
349
  snapshot refresh. A removal or semantic signature change fails until the
338
350
  maintainer supplies
339
351
  `pnpm sdk:surface:update -- --acknowledge-breaking "<release rationale>"`;
@@ -353,23 +365,27 @@ git push origin v<version>
353
365
  `.github/workflows/release.yml` runs on `v*.*.*` tags and handles:
354
366
 
355
367
  - full-history checkout
356
- - 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
368
+ - 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 preserves the reviewed package gate and budget in runner-temporary storage before checking out that exact tagged source. The controls inspect the untouched tagged package without becoming part of it, so recovery applies the current fail-closed distribution policy while retaining the original version guard and immutable package bytes.
357
369
  - pnpm install with frozen lockfile
358
370
  - version policy and tag guard
359
371
  - secret scan
360
372
  - build, clone-local merge-driver installation, typecheck, test, and coverage
361
373
  - generated changelog verification and `pm-changelog` installation before the
362
374
  tracker-bearing static gate, so a clean checkout does not misclassify the
363
- managed extension's linked files as missing. Recovery of an unpublished
364
- immutable tag regenerates only `CHANGELOG.md` with the tagged checkout's
365
- canonical package script and fails if that operation changes any other
366
- tracked source path (apart from managed-extension install metadata).
375
+ managed extension's linked files as missing. Every exact-tag source,
376
+ including an ordinary tag push and recovery of an unpublished immutable tag,
377
+ regenerates only `CHANGELOG.md` with the tagged checkout's canonical package
378
+ script and fails if that operation changes any other tracked source path
379
+ (apart from managed-extension install metadata). Reviewed `main` recovery
380
+ sources retain the non-mutating drift check.
367
381
  - static quality gate (shared complexity, duplication, dead/orphan module, file/folder hygiene, source/exported docstring coverage profile)
368
382
  - temporary-project compatibility gate against latest published tracker data
369
383
  - reliability threshold gate (Sentry severity threshold, bounded to a recent-activity window via `--sentry-window-days` (default `14`, `0` = unbounded) so a stale benign unresolved issue cannot block every scheduled release; Sentry requests use the fail-closed bounded `--sentry-request-timeout-ms` contract (default `120000`, maximum `300000`); `--telemetry-mode` gate policy: `off` | `best-effort` | `required`). Scheduled `auto-release.yml` failures open/update an `Auto Release blocked` GitHub issue so blocked daily releases are never silently skipped.
370
384
  - sandboxed `pm` coverage
371
- - optional Sentry release metadata and sourcemap upload when `SENTRY_AUTH_TOKEN` is configured
372
- - npm pack dry run and npx tarball smoke test
385
+ - a base npm pack dry run, optional Sentry debug-ID injection, a second
386
+ `sentry-injected` packlist budget over the exact publishable bytes, and only
387
+ then optional Sentry release metadata/upload/finalization and the npx tarball
388
+ smoke test
373
389
  - generated release notes from changelog plus sanitized tracker metadata
374
390
  - artifact uploads
375
391
  - `npm publish --access public --provenance --tag latest`, skipped on retry
@@ -458,8 +474,10 @@ Use the npm registry package for maintainer global updates. Do not use `npm inst
458
474
  the existing immutable tag, reapplies the version guard, installs the managed
459
475
  changelog extension, regenerates the package changelog with the tagged
460
476
  checkout's canonical policy under a tracked-path mutation guard, and permits
461
- first publication only from that tagged source. Other registry failures stop
462
- before source selection or publication.
477
+ first publication only from that tagged source. Ordinary tag-push releases
478
+ use the same guarded regeneration because their tag did not exist when the
479
+ release commit's changelog was prepared. Other registry failures stop before
480
+ source selection or publication.
463
481
  - If an immutable published package contains a defect that cannot be repaired
464
482
  by rerunning the same tag workflow, document the incident and ship the code
465
483
  fix in the next UTC day's release.
@@ -1,7 +1,9 @@
1
1
  # SDK Context Truth Contracts
2
2
 
3
3
  Tracker references: [pm-23xkss](../.agents/pm/issues/pm-23xkss.toon) and
4
- [pm-r8u2g6](../.agents/pm/issues/pm-r8u2g6.toon).
4
+ [pm-r8u2g6](../.agents/pm/issues/pm-r8u2g6.toon),
5
+ [pm-79gv6q](../.agents/pm/issues/pm-79gv6q.toon), and
6
+ [pm-08mt4k](../.agents/pm/issues/pm-08mt4k.toon).
5
7
 
6
8
  ## Agent Quick Context
7
9
 
@@ -68,3 +70,24 @@ silently route tracker files through the wrong merge behavior. Run
68
70
  This policy does not weaken storage, history, merge-fence, or pending-receipt
69
71
  checks. It only distinguishes an optional never-installed clone capability
70
72
  from a broken capability that the repository appears to rely on.
73
+
74
+ ## Population and Focus Are Separate
75
+
76
+ `context.summary.scope` is `matching_items`: lifecycle totals describe all items
77
+ matching the request filters and parent subtree before the focus limit, intent
78
+ projection, and token packing. Without filters this is the workspace population.
79
+ `active_items`, `in_progress`, `open`, and `blocked` use that same population as
80
+ `total_items`, `closed`, and `canceled`. `open` includes active statuses other than
81
+ in-progress; `blocked` is an overlapping classification that includes unresolved
82
+ dependency edges as well as blocked lifecycle states.
83
+
84
+ `summary.returned_focus` reports the bounded focus selection. The existing
85
+ `high_level` and `low_level` counts describe their emitted rows. An orient or
86
+ handoff response limited to one row can therefore still report hundreds of open
87
+ items. `omission_receipt.summary_scope` repeats `matching_items` so a consumer
88
+ reading projection metadata cannot confuse omitted detail with absent work.
89
+
90
+ Never infer a population count from an array length. To visit individual items,
91
+ follow the response's continuation and omission receipts. To schedule work, use
92
+ the shared [execution contracts](SDK_EXECUTION_CONTRACTS.md), which keep human
93
+ input, gates, and containers visible without dispatching them by default.