@unbrained/pm-cli 2026.8.20 → 2026.8.22

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 (228) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/CHANGELOG.md +38 -0
  3. package/dist/cli/error-guidance.d.ts +29 -4
  4. package/dist/cli/error-guidance.js +43 -43
  5. package/dist/cli/main.d.ts +3 -0
  6. package/dist/cli/main.js +40 -7
  7. package/dist/cli-bundle/bundle-manifest.json +150 -150
  8. package/dist/cli-bundle/chunks/{chunk-L4LGPBJU.js → chunk-BWX4SK46.js} +58 -58
  9. package/dist/cli-bundle/chunks/chunk-EMWDM5FI.js +13 -0
  10. package/dist/cli-bundle/chunks/chunk-HYG6LRL4.js +200 -0
  11. package/dist/cli-bundle/chunks/{chunk-TSMWLCHS.js → chunk-MYYI3ZOA.js} +2 -2
  12. package/dist/cli-bundle/chunks/{chunk-4GB2LTOQ.js → chunk-MZTZQTMS.js} +2 -2
  13. package/dist/cli-bundle/chunks/{chunk-7BRF2BX2.js → chunk-QI2CT3IX.js} +2 -2
  14. package/dist/cli-bundle/chunks/chunk-SMWXHMVB.js +35 -0
  15. package/dist/cli-bundle/chunks/{chunk-US2ZQW2M.js → chunk-U6GQ4VMV.js} +47 -47
  16. package/dist/cli-bundle/chunks/{chunk-K3EN3LK2.js → chunk-VMMIL3SI.js} +2 -2
  17. package/dist/cli-bundle/chunks/chunk-WG4STC36.js +5 -0
  18. package/dist/cli-bundle/chunks/{chunk-XYDDWBZN.js → chunk-YBPJAOQQ.js} +3 -3
  19. package/dist/cli-bundle/chunks/{register-list-query-JSAQCVOC.js → register-list-query-HZKBQNWW.js} +2 -2
  20. package/dist/cli-bundle/chunks/{register-mutation-XJPAW63D.js → register-mutation-HTKEEGRD.js} +2 -2
  21. package/dist/cli-bundle/chunks/{register-operations-DSOSB2XQ.js → register-operations-6EMRWJJY.js} +2 -2
  22. package/dist/cli-bundle/chunks/{register-setup-QUR6QL2C.js → register-setup-QK4OTOXN.js} +2 -2
  23. package/dist/cli-bundle/focused-chunks/{chunk-TDR5OGG3.js → chunk-2ARQGDDW.js} +2 -2
  24. package/dist/cli-bundle/focused-chunks/{chunk-AZBACT5T.js → chunk-2AZT5WXZ.js} +2 -2
  25. package/dist/cli-bundle/focused-chunks/{chunk-M32HFIQB.js → chunk-2POVTNLY.js} +2 -2
  26. package/dist/cli-bundle/focused-chunks/chunk-3LKU6PTJ.js +4 -0
  27. package/dist/cli-bundle/focused-chunks/chunk-5SHSBMX2.js +2 -0
  28. package/dist/cli-bundle/focused-chunks/{chunk-UGSS4F5X.js → chunk-6S2MO3Q3.js} +2 -2
  29. package/dist/cli-bundle/focused-chunks/{chunk-5L7M4AI7.js → chunk-A2BC5PQL.js} +2 -2
  30. package/dist/cli-bundle/focused-chunks/chunk-C4S4A4JJ.js +5 -0
  31. package/dist/cli-bundle/focused-chunks/{chunk-OM65KHGF.js → chunk-D6RBZEJJ.js} +2 -2
  32. package/dist/cli-bundle/focused-chunks/chunk-E2EWYPY6.js +16 -0
  33. package/dist/cli-bundle/focused-chunks/{chunk-G3C5ERXG.js → chunk-GMYPD4FX.js} +2 -2
  34. package/dist/cli-bundle/focused-chunks/chunk-L5LDSRO2.js +155 -0
  35. package/dist/cli-bundle/focused-chunks/{chunk-BLJCGGID.js → chunk-MB37AYN6.js} +2 -2
  36. package/dist/cli-bundle/focused-chunks/chunk-MCOR37QK.js +2 -0
  37. package/dist/cli-bundle/focused-chunks/{chunk-FUREQLQN.js → chunk-PH2OXXVZ.js} +2 -2
  38. package/dist/cli-bundle/focused-chunks/{chunk-325UXIO7.js → chunk-PMGJUFNQ.js} +2 -2
  39. package/dist/cli-bundle/focused-chunks/chunk-R6SR45XU.js +50 -0
  40. package/dist/cli-bundle/focused-chunks/chunk-WZE4LIPW.js +8 -0
  41. package/dist/cli-bundle/main.js +13 -13
  42. package/dist/cli-bundle/sdk-authoring.js +1 -1
  43. package/dist/cli-bundle/sdk-contracts.js +2 -2
  44. package/dist/cli-bundle/sdk-core.js +40 -40
  45. package/dist/cli-bundle/sdk-governance.js +1 -1
  46. package/dist/cli-bundle/sdk-graph.js +1 -1
  47. package/dist/cli-bundle/sdk-merge.js +32 -32
  48. package/dist/cli-bundle/sdk-query.js +1 -1
  49. package/dist/cli-bundle/sdk-runtime.js +1 -1
  50. package/dist/cli-bundle/sdk-testing.js +1 -1
  51. package/dist/cli-bundle/sdk.js +5 -5
  52. package/dist/core/extensions/extension-hook-runtime.js +22 -20
  53. package/dist/core/extensions/extension-types.d.ts +8 -1
  54. package/dist/core/extensions/extension-types.js +2 -2
  55. package/dist/core/extensions/loader.js +7 -3
  56. package/dist/core/extensions/service-ownership.d.ts +8 -0
  57. package/dist/core/extensions/service-ownership.js +20 -0
  58. package/dist/core/item/id.js +20 -5
  59. package/dist/core/item/item-format.js +27 -2
  60. package/dist/core/shared/errors.d.ts +20 -0
  61. package/dist/core/shared/errors.js +2 -2
  62. package/dist/core/store/item-store.js +6 -91
  63. package/dist/core/store/tracker-preflight.d.ts +7 -0
  64. package/dist/core/store/tracker-preflight.js +142 -0
  65. package/dist/sdk/agent/refusal-reachability.d.ts +1 -1
  66. package/dist/sdk/agent/tracker-preflight-contracts.d.ts +63 -0
  67. package/dist/sdk/agent/tracker-preflight-contracts.js +127 -0
  68. package/dist/sdk/annotations.js +6 -7
  69. package/dist/sdk/authoring.d.ts +1 -1
  70. package/dist/sdk/authoring.js +2 -2
  71. package/dist/sdk/cli-contracts/agent-output-contracts.d.ts +77 -0
  72. package/dist/sdk/cli-contracts/agent-output-contracts.js +324 -2
  73. package/dist/sdk/cli-contracts/commander-mutation-options.js +3 -3
  74. package/dist/sdk/cli-contracts/runtime-contracts.d.ts +3 -1
  75. package/dist/sdk/cli-contracts/runtime-contracts.js +4 -3
  76. package/dist/sdk/cli-contracts.d.ts +1 -1
  77. package/dist/sdk/cli-contracts.js +3 -3
  78. package/dist/sdk/config.d.ts +5 -0
  79. package/dist/sdk/config.js +5 -5
  80. package/dist/sdk/context-intent-runtime.js +7 -4
  81. package/dist/sdk/contracts.d.ts +1 -0
  82. package/dist/sdk/contracts.js +3 -2
  83. package/dist/sdk/dependencies.js +5 -7
  84. package/dist/sdk/dependency-flag-validation.d.ts +1 -1
  85. package/dist/sdk/dependency-flag-validation.js +10 -4
  86. package/dist/sdk/environment/tracker-preflight.d.ts +6 -0
  87. package/dist/sdk/environment/tracker-preflight.js +10 -0
  88. package/dist/sdk/eval.js +5 -7
  89. package/dist/sdk/extension/install-sources.d.ts +1 -1
  90. package/dist/sdk/extension/install-sources.js +6 -3
  91. package/dist/sdk/extension/output-ownership.d.ts +1 -0
  92. package/dist/sdk/extension/output-ownership.js +3 -2
  93. package/dist/sdk/files.js +6 -10
  94. package/dist/sdk/generated/generated-error-code-catalog-part-1.js +75 -15
  95. package/dist/sdk/generated/generated-error-code-catalog-part-2.js +81 -8
  96. package/dist/sdk/governance/assurance.d.ts +36 -2
  97. package/dist/sdk/governance/assurance.js +184 -10
  98. package/dist/sdk/governance/gc.js +5 -6
  99. package/dist/sdk/governance/health.d.ts +3 -0
  100. package/dist/sdk/governance/health.js +42 -11
  101. package/dist/sdk/governance/hierarchy-validation.d.ts +29 -0
  102. package/dist/sdk/governance/hierarchy-validation.js +109 -0
  103. package/dist/sdk/governance/reindex.js +5 -6
  104. package/dist/sdk/governance/validate.d.ts +2 -9
  105. package/dist/sdk/governance/validate.js +51 -109
  106. package/dist/sdk/graph/assembly.d.ts +6 -1
  107. package/dist/sdk/graph/assembly.js +16 -22
  108. package/dist/sdk/graph/governance-contracts.d.ts +1 -1
  109. package/dist/sdk/graph/governance-contracts.js +8 -2
  110. package/dist/sdk/graph/governance.d.ts +7 -5
  111. package/dist/sdk/graph/governance.js +76 -16
  112. package/dist/sdk/graph/hierarchy-integrity.d.ts +94 -0
  113. package/dist/sdk/graph/hierarchy-integrity.js +311 -0
  114. package/dist/sdk/graph/index.d.ts +2 -1
  115. package/dist/sdk/graph/index.js +3 -2
  116. package/dist/sdk/graph/remediation.js +32 -2
  117. package/dist/sdk/graph/run.d.ts +31 -2
  118. package/dist/sdk/graph/run.js +83 -36
  119. package/dist/sdk/graph/traversal.js +14 -5
  120. package/dist/sdk/graph/workspace-relationship-kind-registry.d.ts +8 -0
  121. package/dist/sdk/graph/workspace-relationship-kind-registry.js +28 -0
  122. package/dist/sdk/history-compact.js +6 -9
  123. package/dist/sdk/history-read.js +5 -7
  124. package/dist/sdk/history-redact.js +5 -6
  125. package/dist/sdk/history-repair.js +6 -9
  126. package/dist/sdk/improvement-ledger.js +7 -10
  127. package/dist/sdk/index.d.ts +4 -2
  128. package/dist/sdk/index.js +5 -3
  129. package/dist/sdk/item-children.js +21 -8
  130. package/dist/sdk/lifecycle/append.d.ts +0 -5
  131. package/dist/sdk/lifecycle/append.js +5 -6
  132. package/dist/sdk/lifecycle/claim.d.ts +0 -5
  133. package/dist/sdk/lifecycle/claim.js +6 -9
  134. package/dist/sdk/lifecycle/close-many.d.ts +0 -5
  135. package/dist/sdk/lifecycle/close-many.js +5 -6
  136. package/dist/sdk/lifecycle/close.d.ts +0 -5
  137. package/dist/sdk/lifecycle/close.js +5 -6
  138. package/dist/sdk/lifecycle/copy.d.ts +0 -5
  139. package/dist/sdk/lifecycle/copy.js +5 -6
  140. package/dist/sdk/lifecycle/create.d.ts +0 -5
  141. package/dist/sdk/lifecycle/create.js +127 -102
  142. package/dist/sdk/lifecycle/delete.js +5 -6
  143. package/dist/sdk/lifecycle/focus.d.ts +0 -5
  144. package/dist/sdk/lifecycle/focus.js +5 -6
  145. package/dist/sdk/lifecycle/hierarchy-mutation-lock.d.ts +15 -0
  146. package/dist/sdk/lifecycle/hierarchy-mutation-lock.js +25 -0
  147. package/dist/sdk/lifecycle/plan.d.ts +0 -5
  148. package/dist/sdk/lifecycle/plan.js +5 -6
  149. package/dist/sdk/lifecycle/restore.js +5 -6
  150. package/dist/sdk/lifecycle/update-many.d.ts +0 -5
  151. package/dist/sdk/lifecycle/update-many.js +5 -6
  152. package/dist/sdk/lifecycle/update.d.ts +2 -5
  153. package/dist/sdk/lifecycle/update.js +211 -84
  154. package/dist/sdk/linked-artifacts.js +6 -7
  155. package/dist/sdk/merge/install.js +5 -6
  156. package/dist/sdk/mutation-events.js +5 -7
  157. package/dist/sdk/package-import-adapters.js +6 -8
  158. package/dist/sdk/profile.js +6 -7
  159. package/dist/sdk/query/activity.js +5 -6
  160. package/dist/sdk/query/calendar.js +5 -6
  161. package/dist/sdk/query/complete-list.d.ts +3 -3
  162. package/dist/sdk/query/complete-list.js +46 -3
  163. package/dist/sdk/query/get.d.ts +0 -5
  164. package/dist/sdk/query/get.js +5 -6
  165. package/dist/sdk/query/history.d.ts +0 -5
  166. package/dist/sdk/query/history.js +5 -6
  167. package/dist/sdk/query/list.d.ts +4 -3
  168. package/dist/sdk/query/list.js +92 -54
  169. package/dist/sdk/query/search.js +5 -7
  170. package/dist/sdk/read-output-contracts.d.ts +5 -1
  171. package/dist/sdk/read-output-contracts.js +87 -22
  172. package/dist/sdk/relationship-context.js +3 -4
  173. package/dist/sdk/relationship-kinds/contract.d.ts +8 -0
  174. package/dist/sdk/relationship-kinds/contract.js +13 -13
  175. package/dist/sdk/relationships.d.ts +1 -1
  176. package/dist/sdk/relationships.js +27 -2
  177. package/dist/sdk/runtime.d.ts +3 -2
  178. package/dist/sdk/runtime.js +3 -2
  179. package/dist/sdk/schema-migration.js +6 -7
  180. package/dist/sdk/schema.js +5 -6
  181. package/dist/sdk/stats.js +5 -8
  182. package/dist/sdk/templates.js +5 -6
  183. package/dist/sdk/test/batch.js +15 -9
  184. package/dist/sdk/test/execution.js +12 -5
  185. package/dist/sdk/test/runs.js +5 -7
  186. package/dist/types.d.ts +11 -0
  187. package/dist/types.js +2 -2
  188. package/docs/AGENT_UX_CONTRACTS.md +24 -1
  189. package/docs/COMMANDS.md +29 -14
  190. package/docs/DEPENDENCY_KIND_CONTRACT.md +40 -1
  191. package/docs/DIAGNOSTIC_OUTPUT_CONTRACTS.md +98 -0
  192. package/docs/EXTENSIONS.md +2 -1
  193. package/docs/README.md +1 -0
  194. package/docs/READ_OUTPUT_CONTRACTS.md +9 -2
  195. package/docs/RECURRENCE_RECOVERY_CONTRACTS.md +37 -0
  196. package/docs/RELATIONSHIP_GRAPH.md +97 -12
  197. package/docs/SDK_PRIMITIVE_INVENTORY.md +15 -1
  198. package/docs/TESTING.md +15 -0
  199. package/marketplace.json +2 -2
  200. package/package.json +1 -1
  201. package/packages/pm-beads/package.json +1 -1
  202. package/packages/pm-calendar/package.json +1 -1
  203. package/packages/pm-command-kit/package.json +1 -1
  204. package/packages/pm-digital-twin/package.json +1 -1
  205. package/packages/pm-governance-audit/package.json +1 -1
  206. package/packages/pm-guide-shell/package.json +1 -1
  207. package/packages/pm-kanban/package.json +1 -1
  208. package/packages/pm-lifecycle-hooks/package.json +1 -1
  209. package/packages/pm-linked-test-adapters/package.json +1 -1
  210. package/packages/pm-search-advanced/package.json +1 -1
  211. package/packages/pm-templates/package.json +1 -1
  212. package/packages/pm-todos/package.json +1 -1
  213. package/packages/pm-vcs/package.json +1 -1
  214. package/plugins/pm-claude/.claude-plugin/plugin.json +1 -1
  215. package/plugins/pm-codex/.codex-plugin/plugin.json +1 -1
  216. package/sdk/public-surface.json +848 -56
  217. package/dist/cli-bundle/chunks/chunk-2RDVGYWE.js +0 -13
  218. package/dist/cli-bundle/chunks/chunk-BLVQHFSY.js +0 -35
  219. package/dist/cli-bundle/chunks/chunk-CU25EQVV.js +0 -5
  220. package/dist/cli-bundle/chunks/chunk-RS3IV2R6.js +0 -197
  221. package/dist/cli-bundle/focused-chunks/chunk-6AHG2YW7.js +0 -50
  222. package/dist/cli-bundle/focused-chunks/chunk-GXWQBE3T.js +0 -8
  223. package/dist/cli-bundle/focused-chunks/chunk-JWKEDZJI.js +0 -4
  224. package/dist/cli-bundle/focused-chunks/chunk-KYZ6JGPL.js +0 -155
  225. package/dist/cli-bundle/focused-chunks/chunk-Q47EX4DI.js +0 -2
  226. package/dist/cli-bundle/focused-chunks/chunk-RIHDMCUM.js +0 -2
  227. package/dist/cli-bundle/focused-chunks/chunk-T4ZFY7ZJ.js +0 -16
  228. package/dist/cli-bundle/focused-chunks/chunk-Z3PLWSGM.js +0 -2
package/docs/COMMANDS.md CHANGED
@@ -6,6 +6,8 @@ Tracked implementation updates: [pm-52eh](../.agents/pm/features/pm-52eh.toon),
6
6
 
7
7
  Workspace-integrity contracts are tracked by [pm-22rzjp](../.agents/pm/issues/pm-22rzjp.toon), [pm-76fkpp](../.agents/pm/issues/pm-76fkpp.toon), [pm-igdvfq](../.agents/pm/issues/pm-igdvfq.toon), [pm-643e0k](../.agents/pm/issues/pm-643e0k.toon), and [pm-larv4r](../.agents/pm/issues/pm-larv4r.toon).
8
8
 
9
+ Create-safe init prefix normalization is tracked by [pm-gh1073](../.agents/pm/issues/pm-gh1073.toon).
10
+
9
11
  ```bash
10
12
  pm <command> --help
11
13
  pm <command> --help --json
@@ -49,21 +51,21 @@ JSON ceiling; TOON uses the smaller default agent ceiling.
49
51
 
50
52
  ## Command Families
51
53
 
52
- | Family | Commands | Purpose |
53
- | ------------ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
54
- | Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
54
+ | Family | Commands | Purpose |
55
+ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
56
+ | Bootstrap | `init`, `config`, `health`, `telemetry` | create and inspect tracker setup |
55
57
  | Lifecycle | `create`, `copy`, `focus`, `claim`, `update`, `item reopen`, `append`, `close`, `release`, `delete`, `start-task`, `pause-task`, `close-task` | mutate item state, including terminal-work recurrence without duplicate creation |
56
- | Bulk | `item mutate`, `item complete`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches or evidence-backed completion, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
57
- | Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
58
- | Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
59
- | Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
60
- | Verification | `test`, `test-all`, `test-runs`†, `validate`, `gc` | run linked tests and repository checks |
61
- | History | `history`, `history-compact`, `history-redact`, `history-repair`, `activity`, `restore`, `stats` | inspect, compact, redact, re-anchor, and recover item state |
62
- | Schema | `schema add/remove-*` / `rename-type` / `rename-field` / `remap-status` / `apply-preset` | manage config-driven types, statuses, and fields; losslessly migrate existing items when definitions evolve; adopt presets or infer types |
63
- | Profiles | `profile list` / `show` / `apply` / `lint` | compose item types, statuses, fields, workflows, config, templates, and recommended packages into archetype bundles (agile/ops/research); `apply` stages every dimension idempotently; `lint` reports author-time consistency findings without writing |
64
- | Calendar | `calendar`, `cal` | project deadlines, reminders, and events |
65
- | Packages | `install`, `upgrade`, `package`, `packages`, `extension`, package/extension command groups | install, upgrade, manage, and run package-backed extension commands |
66
- | Machines | `contracts`, `help`, optional `guide`/`completion` | command contracts plus optional guide-shell docs routing and shell helpers |
58
+ | Bulk | `item mutate`, `item complete`, `update-many`, `close-many` | atomically commit heterogeneous SDK mutation batches or evidence-backed completion, or apply one change across a matched, dry-run-previewed set with a rollback checkpoint |
59
+ | Scheduling | `meet`, `event`, `remind` | low-friction Meeting/Event/Reminder creation |
60
+ | Planning | `plan create`, `plan add-step`, `plan update-step`, `plan complete-step`, `plan link`, `plan approve`, `plan materialize` | agent-optimized living plans with ordered steps, evidence, decisions, validation, and materialization |
61
+ | Links | `files`, `docs`, `test`, `deps` | connect items to artifacts, tests, and relationships |
62
+ | Verification | `test`, `test-all`, `test-runs`†, `validate`, `gc` | run linked tests and repository checks |
63
+ | History | `history`, `history-compact`, `history-redact`, `history-repair`, `activity`, `restore`, `stats` | inspect, compact, redact, re-anchor, and recover item state |
64
+ | Schema | `schema add/remove-*` / `rename-type` / `rename-field` / `remap-status` / `apply-preset` | manage config-driven types, statuses, and fields; losslessly migrate existing items when definitions evolve; adopt presets or infer types |
65
+ | Profiles | `profile list` / `show` / `apply` / `lint` | compose item types, statuses, fields, workflows, config, templates, and recommended packages into archetype bundles (agile/ops/research); `apply` stages every dimension idempotently; `lint` reports author-time consistency findings without writing |
66
+ | Calendar | `calendar`, `cal` | project deadlines, reminders, and events |
67
+ | Packages | `install`, `upgrade`, `package`, `packages`, `extension`, package/extension command groups | install, upgrade, manage, and run package-backed extension commands |
68
+ | Machines | `contracts`, `help`, optional `guide`/`completion` | command contracts plus optional guide-shell docs routing and shell helpers |
67
69
 
68
70
  `†` `test-runs` subcommands are provided by the optional `linked-test-adapters` package (`pm install linked-test-adapters --project`).
69
71
 
@@ -89,6 +91,15 @@ ID prefix without relying on the legacy positional form. `pm init ops` remains
89
91
  compatible, and supplying both forms is accepted only when they normalize to the
90
92
  same prefix; conflicting values fail with `init_id_prefix_conflict` instead of
91
93
  silently choosing one.
94
+ Prefixes normalize through the same primitive used by item creation: letters
95
+ become lowercase, each run of whitespace or punctuation becomes one `-`, edge
96
+ separators are removed, and exactly one trailing `-` is stored. For example,
97
+ `"Release Candidate"` persists as `release-candidate-`; an input with no ASCII
98
+ letters or digits falls back to `pm-`. Path-like values remain invalid tracker
99
+ prefixes when passed through `--id-prefix`; a path-like positional value remains
100
+ the advanced tracker-root target described below. To repair an older unsafe
101
+ value, rerun init with a safe prefix and explicit replacement intent, for example
102
+ `pm init --id-prefix "release candidate" --force --defaults`.
92
103
  Use `pm init --workspace <dir>` when `<dir>` is a project root; it creates `<dir>/.agents/pm`. A path-like positional remains the advanced tracker-root form and writes tracker files directly at that path. Both explicit target forms return `target.mode`, `target.tracker_root`, and tracker-scoped executable `next_steps` so agents can run the suggestions from any working directory.
93
104
  Implicit init discovery also reports whether the selected tracker is local or was found in an ancestor. If `pm init <name>` would change an ancestor tracker, the refusal names both directories and gives the safe current-directory retry: `pm init <name> --pm-path "$PWD/.agents/pm" --defaults`.
94
105
  `pm init --agent-guidance ask` is the default behavior: prompt in TTY only when AGENTS/CLAUDE guidance is missing and no decline is recorded.
@@ -163,6 +174,10 @@ Use `duplicates --status all` for a true whole-history duplicate check. The
163
174
  result echoes `filters.statuses: null` for the unrestricted corpus; named or
164
175
  custom statuses are normalized through the runtime status registry and an
165
176
  unknown status fails instead of returning a false-clean result.
177
+ As a read-only structured surface, `duplicates` accepts the universal output
178
+ controls, including `--output-format json`, `--lean`, projection/amount
179
+ controls, and token accounting, while its default TOON output remains bounded.
180
+ Tracked by [pm-gh1076](../.agents/pm/issues/pm-gh1076.toon).
166
181
  Use `pm get <id>` to read a single item by ID — the single-item read primitive used throughout the agent loop. It accepts `--fields <list>` and `--depth brief|standard|deep|full` for token-minimal projections, and `--tree`/`--tree-depth <n>` to include descendants. Standard/deep reads expose a normalized `schedule` facet (`deadline`, `start_at`, `end_at`, `location`, reminders, and events) when scheduling metadata exists. Container-oriented built-ins (Epic, Feature, Milestone, and Plan) plus custom types automatically expose type-agnostic child counts and continuation metadata. Standard depth keeps that rollup counts-only; `--depth deep|full` or an explicit `--fields id,children` request adds the deterministic bounded child sample. Built-in leaf reads avoid a workspace scan unless children are explicitly requested. `pm get <id> --json` returns the `body` inside the `item` object (`.item.body`); see [Full results, totals, and bodies](#full-results-totals-and-bodies). To duplicate an existing item as a starting point, `pm copy <id> --title "New title"` clones it into a fresh id with lifecycle fields reset.
167
182
 
168
183
  When the strongest duplicate match is terminal because the same work recurred,
@@ -1,6 +1,6 @@
1
1
  # Dependency-kind contract
2
2
 
3
- Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon)
3
+ Tracker: [pm-4020c5](../.agents/pm/issues/pm-4020c5.toon), [pm-jkbqt8](../.agents/pm/issues/pm-jkbqt8.toon), [pm-q6n8sj](../.agents/pm/issues/pm-q6n8sj.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-gos426](../.agents/pm/issues/pm-gos426.toon), [pm-flnefm](../.agents/pm/issues/pm-flnefm.toon), [pm-rggtvd](../.agents/pm/issues/pm-rggtvd.toon), and [pm-vk7zek](../.agents/pm/issues/pm-vk7zek.toon).
4
4
 
5
5
  Dependency rows have one canonical stored spelling per relationship meaning. Command inputs remain compatibility-friendly: hyphens normalize to underscores and the aliases below are accepted, but `pm create` and `pm update` persist the canonical kind. Existing historical rows are never rewritten implicitly.
6
6
 
@@ -15,6 +15,45 @@ Dependency rows have one canonical stored spelling per relationship meaning. Com
15
15
 
16
16
  The SDK relationship registry is authoritative. `canonicalizeRelationshipKind()` rejects unknown spellings, while `resolveCanonicalRelationshipKind()` supports validation flows that need an undefined result. `pm contracts` publishes `relationship_kind_contracts` with canonical names, aliases, inverses, and ordering/hierarchy semantics.
17
17
 
18
+ Extension kinds may opt into both ordering and hierarchy semantics. Unless they
19
+ declare an explicit `traversal`, ordering is the primary traversal and context
20
+ role family; hierarchy direction and cardinality remain enforceable integrity
21
+ constraints. This ordering-first precedence is shared by registry snapshots and
22
+ direct-edge context explanations.
23
+
24
+ Dependency additions and removals share the same lossless input grammar. A
25
+ bare value is an item id; structured removal input uses `id=<id>` plus optional
26
+ canonical `kind` (with `type` accepted only as an input alias), `source_kind`, `author`, and ISO `created_at`
27
+ selectors. Supplying all stored coordinates retires exactly one dependency row
28
+ without deleting siblings that share an id and kind. Punctuation-shaped shorthand such as
29
+ `OTHER,related` is rejected with `dependency_flag_value_invalid` on both
30
+ `--dep` and `--dep-remove`, before prefix normalization can turn it into a
31
+ dangling id. A removal selector that matches no stored row fails with
32
+ `dependency_remove_no_match` and returns the unmatched selectors plus compact
33
+ available identities. Re-adding a stored dependency identity is idempotent; if
34
+ legacy storage contains that exact identity more than once, the same mutation
35
+ collapses the touched copies to one without creating an edge-absence window.
36
+ The stored identity includes normalized `id`, `kind`, `source_kind`, `author`,
37
+ and creation instant, so provenance-distinct sibling rows remain independent.
38
+
39
+ ## Hierarchy integrity
40
+
41
+ The registry's `hierarchy`, `hierarchyDirection`, `outgoing`, and `incoming`
42
+ fields are executable contracts. Scalar `parent` metadata and every registered
43
+ hierarchy dependency spelling normalize into the same parent-to-child relation.
44
+ That normalized relation powers `pm list --parent`, list/get tree projections,
45
+ child rollups, graph traversal, graph analysis, graph audit, validate, and
46
+ health. Extensions therefore gain hierarchy behavior by registering semantics;
47
+ consumers do not hard-code kind names.
48
+
49
+ Create and update transactions reject a newly introduced hierarchy cycle,
50
+ registry cardinality violation, or scalar/dependency direction contradiction
51
+ before persistence. Existing debt remains readable and repairable. Active debt
52
+ is gate-failing in graph governance and health; defects confined to terminal
53
+ items are labeled legacy and are never mutated automatically. `pm validate`
54
+ reports cycle, cardinality, and parent-divergence counts and exact bounded rows,
55
+ while `pm graph analyze` exposes a compact `hierarchy` summary.
56
+
18
57
  `recurs_from` has no alias: a later occurrence points to an earlier occurrence.
19
58
  It is persistent after both items become terminal and carries temporal identity,
20
59
  not execution precedence. `supersedes` keeps replacement semantics, while
@@ -0,0 +1,98 @@
1
+ # Diagnostic Output Contracts
2
+
3
+ Tracker references: [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-f05lsg](../.agents/pm/features/pm-f05lsg.toon), and [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon).
4
+
5
+ ## Agent Quick Context
6
+
7
+ Failures are context-management surfaces. Every diagnostic family now declares
8
+ a format-aware token ceiling and one degradation ladder in the public SDK:
9
+
10
+ | Class | Text | JSON | Corrective action that survives degradation |
11
+ | -------------------- | ---: | ---: | ------------------------------------------- |
12
+ | `error` | 768 | 2000 | required action, retry/domain, or next step |
13
+ | `warning` | 768 | 2000 | required action, retry/domain, or next step |
14
+ | `validation_summary` | 1500 | 3000 | required action, retry/domain, or next step |
15
+ | `recovery_bundle` | 768 | 2000 | required action, retry/domain, or next step |
16
+
17
+ The smallest explicit ceiling is 192 estimated tokens. At that floor, the
18
+ projector may reduce the diagnostic to its code, required action, compact
19
+ recovery, and exit status. It never removes the first corrective action.
20
+
21
+ ## SDK Contract
22
+
23
+ Use the public contract surface rather than maintaining a package-local error
24
+ budget:
25
+
26
+ ```ts
27
+ import {
28
+ PM_DIAGNOSTIC_OUTPUT_BUDGET_CONTRACTS,
29
+ projectPmDiagnosticOutput,
30
+ projectPmDiagnosticText,
31
+ resolvePmDiagnosticOutputBudget,
32
+ } from "@unbrained/pm-cli/sdk/contracts";
33
+
34
+ const contract = resolvePmDiagnosticOutputBudget("error");
35
+ const projected = projectPmDiagnosticOutput(
36
+ {
37
+ code: "invalid_argument_value",
38
+ required: "Use --status open and retry.",
39
+ recovery: { suggested_retry: "pm list --status open" },
40
+ detail: "The supplied status is not declared.",
41
+ exit_code: 2,
42
+ },
43
+ { maxEstimatedTokens: contract.minimum_max_estimated_tokens },
44
+ );
45
+
46
+ const text = projectPmDiagnosticText(
47
+ "A long rendered diagnostic",
48
+ "Use --status open and retry.",
49
+ ).output;
50
+ ```
51
+
52
+ The JSON projector orders `code`, `required`, recovery, and next steps before
53
+ explanation. Untruncated diagnostics add no per-call receipt overhead; their
54
+ binding declaration is discoverable from `pm contracts --full --json` under
55
+ `diagnostic_output_contracts`. When degradation occurs, the returned
56
+ `diagnostic_output` receipt records the effective budget, original and emitted
57
+ estimates, applied stages, and omitted top-level fields. Minimal fallbacks bound
58
+ the named omission list and disclose any additional count through
59
+ `omitted_fields_overflow_count`.
60
+
61
+ The deterministic ladder is:
62
+
63
+ 1. full diagnostic;
64
+ 2. omit explanation;
65
+ 3. limit diagnostic collections;
66
+ 4. compact recovery to actionable keys;
67
+ 5. retain the action-only envelope.
68
+
69
+ Human diagnostics lead with `What is required` and next steps before explaining
70
+ what happened. If their declared ceiling binds, the compact text still begins
71
+ with the required action and points to structured JSON for the bounded recovery
72
+ envelope.
73
+
74
+ ## Executable Assurance
75
+
76
+ `pnpm quality:recovery-closure` builds the current CLI and replays 22 refusal
77
+ contracts in isolated trackers. Ten representative, high-frequency failure
78
+ paths are also ratcheted by
79
+ `scripts/release/diagnostic-output-baseline.json`. The gate requires every row
80
+ to remain within the SDK-declared JSON ceiling and retain a mechanically
81
+ actionable correction. It reports the aggregate original and emitted token
82
+ estimates without claiming a reduction when no degradation was required.
83
+
84
+ The baseline is a coverage ratchet, not permission to weaken a ceiling. Its
85
+ negative control requires a missing baseline probe to fail. The existing
86
+ refusal-closure negative controls independently prove that incomplete domains,
87
+ broken retries, and malformed recovery envelopes remain blocking findings.
88
+
89
+ Run the focused proof with:
90
+
91
+ ```bash
92
+ pnpm build
93
+ node scripts/release/refusal-closure-gate.mjs
94
+ node scripts/run-tests.mjs test -- \
95
+ tests/unit/sdk/agent-output-contracts.spec.ts \
96
+ tests/unit/cli/error-guidance.spec.ts \
97
+ tests/unit/scripts/refusal-closure-gate.spec.ts
98
+ ```
@@ -45,6 +45,7 @@ pm install kanban --project
45
45
  External registry packages are installed by exact package name. If `npm:<name>` returns a registry 404, JSON error output includes `fallback_candidates` and `next_best_command`; unpublished first-party packages fall back to `pm install --project github.com/unbraind/<name>`. Install results include package-owned `command_paths`, `action_paths`, `contributions`, `command_discovery`, and a light `verification` block covering the target tracker, activation status, registered commands/actions/item types, and health verdict. Agents should consume those fields instead of guessing from the package name or immediately spending another invocation on doctor. A successful activation persists the versioned contribution inventory in `.managed-extensions.json`; subsequent discovery can enumerate command handlers, hooks, parser/renderer targets, schema names, and the other registered surfaces without importing the package module. A failed runtime activation returns `ok: false`, `activated: false`, a non-zero CLI exit, and actionable diagnostics; missing SDK resolution adds an explicit dependency recovery step. Local installs are containment-safe when the extension destination is nested inside the source checkout: pm stages the package outside the source and prunes the destination, `.agents`, `node_modules`, and install-backup directories before copying, so reinstalling cannot recursively copy tracker history, host dependencies, or prior backups.
46
46
  Local `.tgz` and `.tar.gz` npm archives are inspected and extracted in an isolated temporary directory without invoking a shell. Archives must contain one `package/package.json` root, regular files/directories only, and bounded entry and expanded-byte totals. Absolute paths, traversal, alternate roots, links, device entries, oversized entries, and decompression-ratio abuse fail before installation. The managed source remains the original archive path, so reload and upgrade provenance do not point at a temporary extraction directory.
47
47
  Registry dependency names and versions are parsed as npm package specs before the install subprocess starts. Leading-option names and shell control syntax are rejected. npm reads those validated dependencies from an isolated runtime-only manifest; no caller-controlled spec is forwarded through the Windows command shell, and the fixed invocation still ends option parsing with `--`. Runtime verification then activates a temporary snapshot of the complete installed extension directory, so an upgrade cannot silently reuse stale transitive ESM dependencies from the current process. Successful install details expose `module_graph_verification: "fresh_snapshot"` for this check.
48
+ pm-owned npm subprocesses clear any inherited, case-insensitive `npm_config_allow_scripts` value while retaining registry, auth, proxy, and executable-path environment; `--ignore-scripts` remains authoritative. Tracked by [pm-gh1072](../.agents/pm/issues/pm-gh1072.toon).
48
49
  An explicit `--pm-path` scopes project installs to that tracker root, including extension files, managed state, settings, type-folder scaffolding, and verification output. This is the safe form for temporary package testing from inside another repository checkout.
49
50
 
50
51
  ```bash
@@ -308,7 +309,7 @@ Common APIs:
308
309
  - `api.registerMigration(definition)` adds schema migrations.
309
310
  - `api.registerProfile(profile)` contributes a project profile — a declarative archetype bundling item types, statuses, fields, per-type workflows, config, templates, and package recommendations. Once active it resolves by name through `pm profile list/show/apply` alongside the core `agile`/`ops`/`research` archetypes (built-in names are reserved; a colliding registration is ignored with a warning). Requires the `schema` capability.
310
311
  - `api.registerAssuranceMeasurementProvider(provider)` contributes typed measurements to assurance. It requires `services`; network providers also require manifest `permissions.network: true`. Gates allow providers and cost/network limits per trigger. See [Project Assurance Primitives](ASSURANCE.md#extension-measurement-providers) for examples.
311
- - `api.registerService("output_format", handler)` customizes output formatting through the service override API. Use `handleServiceOverride(result)` to claim a payload and return the scaffold-compatible literal `{ handled: false }` (or `declineServiceOverride()`) for commands the extension does not own. Legacy `null`/`undefined` declines remain supported; returning the original payload is now an unambiguous handled result.
312
+ - `api.registerService("output_format", handler, ownership?)` customizes output formatting through the service override API. Use `handleServiceOverride(result)` to claim a payload and return the scaffold-compatible literal `{ handled: false }` (or `declineServiceOverride()`) for commands the extension does not own. An override that is unconditionally inert can declare `{ passThrough: true }`; the host then ignores and diagnoses any handled result, and package doctor treats the registration as statically safe. Legacy `null`/`undefined` declines remain supported; returning the original payload is now an unambiguous handled result. Tracked by [pm-gh1074](../.agents/pm/issues/pm-gh1074.toon).
312
313
  - `api.registerRenderer("toon" | "json", renderer, ownership?)` adds format-specific renderers. Scope ownership with `commands` and/or a `resultDiscriminator`; the host checks both before invoking the renderer and falls back to native rendering for unrelated output. The legacy unscoped callback remains supported, but doctor warns because package ownership cannot be proven statically.
313
314
  - `suppressHostOutput(result?)` from `@unbrained/pm-cli/sdk` marks commands that already wrote output, preventing a second CLI payload while retaining the optional result for hooks, telemetry, and embedded hosts.
314
315
  - `api.hooks.beforeCommand(handler)`, `api.hooks.beforeMutation(handler)`, `api.hooks.afterCommand(handler)`, `api.hooks.onWrite(handler)`, `api.hooks.onRead(handler)`, and `api.hooks.onIndex(handler)` add lifecycle hooks.
package/docs/README.md CHANGED
@@ -51,6 +51,7 @@ pm guide release --json
51
51
  - [SDK Context Platform](SDK_CONTEXT.md) - task-oriented entry point for authoritative reads, ranking, package workflows, diagnostics, recovery, and verification.
52
52
  - [Self-Describing Context Contracts](SELF_DESCRIBING_CONTEXT_CONTRACTS.md) - intent-scoped reads, semantic flag invocation metadata, visibility parity, and generated error vocabulary.
53
53
  - [Universal Read Output Contracts](READ_OUTPUT_CONTRACTS.md) - cross-command include, amount, cost, and encoding controls for CLI, SDK, MCP, and packages.
54
+ - [Diagnostic Output Contracts](DIAGNOSTIC_OUTPUT_CONTRACTS.md) - action-first error budgets, deterministic degradation, SDK projection, and executable refusal assurance.
54
55
  - [Mutation Integrity](MUTATION_INTEGRITY.md) - shared CLI/SDK/MCP author, secret, append-only disposition, and stale-work guardrails.
55
56
  - [Agent Provenance ADR Amendment](AGENT_PROVENANCE_ADR.md) - extensible model, effort, role, and host provenance with privacy and compatibility boundaries.
56
57
  - [SDK Agent Session and Episode Context](SDK_AGENT_SESSION_CONTEXT.md) - inherited role/topic context, cross-process episode identity, and deterministic history grouping.
@@ -1,6 +1,6 @@
1
1
  # Universal Read Output Contracts
2
2
 
3
- Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), and [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon).
3
+ Tracker references: [pm-hb7ug8](../.agents/pm/features/pm-hb7ug8.toon), [pm-cxr0jb](../.agents/pm/features/pm-cxr0jb.toon), [pm-hid9g1](../.agents/pm/features/pm-hid9g1.toon), [pm-h8tpeh](../.agents/pm/features/pm-h8tpeh.toon), [pm-5t33or](../.agents/pm/features/pm-5t33or.toon), [pm-srns](../.agents/pm/issues/pm-srns.toon), [pm-sb0tns](../.agents/pm/issues/pm-sb0tns.toon), [pm-gjjurs](../.agents/pm/issues/pm-gjjurs.toon), [pm-eugaqy](../.agents/pm/issues/pm-eugaqy.toon), [pm-jt8aa2](../.agents/pm/issues/pm-jt8aa2.toon), [pm-kyjdne](../.agents/pm/issues/pm-kyjdne.toon), [pm-8nev0o](../.agents/pm/issues/pm-8nev0o.toon), [pm-e5gl05](../.agents/pm/issues/pm-e5gl05.toon), [pm-cha95z](../.agents/pm/tasks/pm-cha95z.toon), and [pm-2qvq7a](../.agents/pm/issues/pm-2qvq7a.toon).
4
4
 
5
5
  ## Agent Quick Context
6
6
 
@@ -140,7 +140,7 @@ pm stats --output-row-contract
140
140
  pm contracts --full --json
141
141
  ```
142
142
 
143
- Every projected result carries a `read_output` receipt with the requested dimensions, precedence, observed compatibility aliases, deterministic estimated token count, string/row compaction signals, and budget outcome. Budget degradation discovers nested arrays as well as declared result rows, so validation diagnostics and other governance payloads compact their inner findings before the useful result is omitted. `compacted_row_paths` names every reduced collection without redefining those nested arrays as ordinary pagination rows.
143
+ Every projected result carries a `read_output` receipt with the requested dimensions, precedence, observed option provenance, deterministic estimated token count, string/row compaction signals, and budget outcome. When canonical controls are present, `canonical_options_used` records spellings such as `--output-include`; the optional field is omitted when no canonical control was supplied so minimum-budget session receipts remain compact. `legacy_aliases_used` and `migration_hints` record only compatibility flags the caller actually supplied. A command-local flag synthesized internally to execute a canonical projection mode is therefore never misreported as deprecated syntax. When both spellings are supplied, both provenance arrays report that mixed invocation. Budget degradation discovers nested arrays as well as declared result rows, so validation diagnostics and other governance payloads compact their inner findings before the useful result is omitted. `compacted_row_paths` names every reduced collection without redefining those nested arrays as ordinary pagination rows.
144
144
 
145
145
  When rows are dropped to satisfy a ceiling, the result also carries `output_budget_truncation`, naming the binding budget and its source, any explicitly requested dimension the budget overrode, every compacted collection path, and executable CLI/SDK/MCP recovery options — a default ceiling can override an explicit `--output-limit unbounded`, and that override is reported rather than silent. If a producer supplied an opaque item-page cursor, compaction rebases it to the last row actually returned and reports `continuation_cursor_rebased: true`; following the cursor therefore cannot skip rows removed from the middle of a producer page. If no useful content can fit, `PmReadOutputBudgetExceeded` provides a discriminated omission result, a compact `{ outputBudget: "unbounded" }` recovery object, and `omitted_result_estimated_tokens`, the last useful-result estimate before omission; use `isReadOutputBudgetExceeded` before accessing result-specific fields. Universal controls are rejected on mutation commands and on the mutation mode of hybrid commands such as `comments`, `notes`, `files`, and `docs`.
146
146
 
@@ -179,6 +179,13 @@ key. Health retains at most 100 warning rows and reports `warning_count`,
179
179
  projection unless `--full` is explicit, keeping the failing check identities
180
180
  and warning codes inside the ordinary budget.
181
181
 
182
+ Failure transports use the companion
183
+ [Diagnostic Output Contracts](DIAGNOSTIC_OUTPUT_CONTRACTS.md). Those contracts
184
+ bind errors, warnings, validation summaries, and recovery bundles independently
185
+ from successful command results. Corrective actions precede explanation and
186
+ survive every degradation stage, while untruncated JSON avoids a per-call
187
+ receipt tax.
188
+
182
189
  ## SDK and Package Usage
183
190
 
184
191
  Typed `PmClient` read methods accept `PmReadOutputOptions` directly:
@@ -65,6 +65,43 @@ Generic action hosts use `item-reopen` with required `id` and `reason` fields.
65
65
  The action participates in the generated action schema, SDK dispatch coverage,
66
66
  CLI/SDK parameter parity, command grammar, and MCP `pm_run` surface.
67
67
 
68
+ ## Tracker Preflight Recovery
69
+
70
+ Every SDK command that requires project state now enters through one shared
71
+ filesystem preflight instead of maintaining a command-local settings check.
72
+ The public aggregate SDK exposes the same primitive for packages and embedded
73
+ hosts:
74
+
75
+ ```ts
76
+ import {
77
+ assertInitializedTracker,
78
+ assertReadableTrackerRoot,
79
+ } from "@unbrained/pm-cli/sdk";
80
+
81
+ await assertReadableTrackerRoot(candidateRoot); // an empty directory is valid
82
+ await assertInitializedTracker(projectRoot); // settings.json is required
83
+ ```
84
+
85
+ The refusal contract distinguishes four states before any command-specific
86
+ read or mutation begins:
87
+
88
+ | Selected root state | Code | Exit | Recovery |
89
+ | --- | --- | ---: | --- |
90
+ | Path does not exist | `tracker_root_missing` | 3 | Tokenized, non-interactive `pm --pm-path <path> init --defaults --agent-guidance skip` |
91
+ | Directory exists but `settings.json` does not | `tracker_not_initialized` | 3 | The same initialization retry |
92
+ | Path or ancestor is a regular file | `tracker_root_not_directory` | 2 | Select a directory; never suggest `pm init` against the file |
93
+ | Directory cannot be read or searched | `tracker_root_unreadable` | 1 | Repair permissions, then retry the same selected root |
94
+
95
+ `listTrackerPreflightRecoveryContracts` publishes this four-state corpus from
96
+ `@unbrained/pm-cli/sdk/contracts`.
97
+ `scoreTrackerPreflightRecoveryClosure` verifies code, exit class, recovery kind,
98
+ and executable retry evidence. The repository recovery gate runs these probes
99
+ beside the 18 closed-domain probes, so its ratcheted corpus is 22 and a removed
100
+ state, failed retry, or unsafe file-path initialization suggestion blocks the
101
+ release. The surface-replication gate separately requires at least 50 shared
102
+ preflight invocations across the 45 migrated SDK modules and forbids the former
103
+ inline error body from returning.
104
+
68
105
  ## Duplicate Intake
69
106
 
70
107
  Create and copy similarity governance inspect all lifecycle statuses. The
@@ -1,6 +1,6 @@
1
1
  # Relationship graph semantics
2
2
 
3
- Tracked by [pm-4jqm](../.agents/pm/decisions/pm-4jqm.toon), [pm-dwj33e](../.agents/pm/decisions/pm-dwj33e.toon), [pm-ju83](../.agents/pm/features/pm-ju83.toon), [pm-8xr8](../.agents/pm/stories/pm-8xr8.toon), [pm-m2il](../.agents/pm/chores/pm-m2il.toon), [pm-jiusod](../.agents/pm/issues/pm-jiusod.toon), [pm-mfvsng](../.agents/pm/issues/pm-mfvsng.toon), [pm-9gzr4r](../.agents/pm/issues/pm-9gzr4r.toon), [pm-xvt7ps](../.agents/pm/issues/pm-xvt7ps.toon), and [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon).
3
+ Tracked by [pm-4jqm](../.agents/pm/decisions/pm-4jqm.toon), [pm-dwj33e](../.agents/pm/decisions/pm-dwj33e.toon), [pm-ju83](../.agents/pm/features/pm-ju83.toon), [pm-8xr8](../.agents/pm/stories/pm-8xr8.toon), [pm-m2il](../.agents/pm/chores/pm-m2il.toon), [pm-jiusod](../.agents/pm/issues/pm-jiusod.toon), [pm-mfvsng](../.agents/pm/issues/pm-mfvsng.toon), [pm-9gzr4r](../.agents/pm/issues/pm-9gzr4r.toon), [pm-xvt7ps](../.agents/pm/issues/pm-xvt7ps.toon), [pm-ouyq3n](../.agents/pm/issues/pm-ouyq3n.toon), [pm-ayg31c](../.agents/pm/issues/pm-ayg31c.toon), [pm-3dyec2](../.agents/pm/issues/pm-3dyec2.toon), [pm-c90tfh](../.agents/pm/issues/pm-c90tfh.toon), and [pm-ob9z4y](../.agents/pm/features/pm-ob9z4y.toon).
4
4
 
5
5
  ## Decision
6
6
 
@@ -10,7 +10,17 @@ The alternatives were rejected as follows: a closed enum cannot model applicatio
10
10
 
11
11
  ## Contract
12
12
 
13
- Each relationship kind declares direction, inverse, ordering and hierarchy participation, optional temporal order, incoming and outgoing cardinality, lifecycle, aliases, payload schema, self-edge policy, and compatibility version. Built-ins normalize legacy `related_to`, `depends_on`, `child_of`, `parent_child`, `epic`, and `task` spellings. Unknown custom kinds remain importable only after their definitions are registered, preventing algorithms from guessing their meaning.
13
+ Each relationship kind declares direction, inverse, a traversal family,
14
+ optional typed-outcome traversal direction, ordering and hierarchy
15
+ participation, optional temporal order, incoming and outgoing cardinality,
16
+ lifecycle, aliases, payload schema, self-edge policy, and compatibility version.
17
+ Built-ins normalize legacy `related_to`, `depends_on`, `child_of`,
18
+ `parent_child`, `epic`, and `task` spellings. Unknown custom kinds remain
19
+ importable only after their definitions are registered, preventing algorithms
20
+ from guessing their meaning. Omitted custom traversal metadata remains
21
+ compatible: hierarchy and ordering declarations select their corresponding
22
+ families, undirected kinds are associative, and other directed kinds are
23
+ semantic.
14
24
 
15
25
  `recurs_from` is the canonical recurrence relation: `new --recurs_from--> old`
16
26
  means the source is a later event with the same observable failure identity as
@@ -153,10 +163,9 @@ await assertRelationshipGraphAdapterConformance(adapter, {
153
163
  workspace: "isolated-conformance-workspace",
154
164
  });
155
165
 
156
- const portfolio = federateRelationshipGraphSnapshots(
157
- [productA, productB],
158
- { createdAt: new Date().toISOString() },
159
- );
166
+ const portfolio = federateRelationshipGraphSnapshots([productA, productB], {
167
+ createdAt: new Date().toISOString(),
168
+ });
160
169
  ```
161
170
 
162
171
  `createRelationshipGraphScaleFixture` supplies reiterable lazy `nodes` and
@@ -251,6 +260,14 @@ for domain packages that need more than generic adjacency:
251
260
  - `enumerateRelationshipPaths` returns bounded simple paths with edge evidence,
252
261
  cost metadata, cancellation, direction/kind filters, and explicit truncation.
253
262
 
263
+ An explicit kind filter may include `traversal: "semantic"` kinds on either
264
+ hierarchy or ordering walks, giving package-defined lineage edges a bounded
265
+ semantic traversal surface without pretending that they are structural or
266
+ scheduling edges. Default walks remain family-strict when no kind filter is
267
+ provided. Association kinds refuse these walks with an `impact --direction
268
+ both` recovery route; selecting the other structural family points to the
269
+ matching hierarchy or ordering commands.
270
+
254
271
  All semantic walks are breadth-first and deterministic. `limit`, `maxDepth`,
255
272
  and `after` provide bounded continuation for hierarchy and ordering walks;
256
273
  path enumeration separately bounds returned paths and expanded partial paths.
@@ -281,17 +298,28 @@ identities and structured rows proven to contradict scalar blocker precedence.
281
298
  censuses so repair can tighten their ceilings without weakening the
282
299
  information-bearing floor. `articulation_points` and `bridge_edges` reuse the exact cut-structure
283
300
  algorithm; outcome metrics count explicit `Milestone` titles beginning with
284
- `Outcome milestone:` and follow only hierarchy or `implements` edges toward
285
- them. Active and terminal populations are reported separately, with integer
301
+ `Outcome milestone:` and follow the registry's declared
302
+ `outcomeTraversal` directions toward them. The audit publishes that exact
303
+ `outcome_reachability_basis` direction groups beside the rates, using sorted
304
+ comma-separated kind names so consumers never infer lineage meaning from
305
+ labels while repeated direction labels stay out of the token surface. Built-in
306
+ hierarchy, implementation, verification,
307
+ discovery, incident, recurrence, and supersession edges opt in explicitly;
308
+ `supersedes` traverses both directions so an archived predecessor remains
309
+ connected to the replacement outcome lineage. Generic `related` and ordering
310
+ edges declare no outcome traversal and cannot satisfy the metric. Active and
311
+ terminal populations are reported separately, with integer
286
312
  basis-point rates and all-status reachable/unreachable totals; the explicit
287
313
  outcome milestones are roots, not work subjects, and are excluded from those
288
314
  populations. Rate or
289
315
  all-status floors are lifecycle-stable; an absolute active-population floor is
290
316
  invalid because completing reachable work legitimately moves it into the
291
- terminal population. `finding_subjects_by_code` includes every known finding
292
- code even when its population is zero, so assurance selectors never confuse a
293
- clean class with a missing contract field. Generic `related` edges cannot
294
- satisfy outcome reachability.
317
+ terminal population. Detailed output's nested SDK profile census,
318
+ `finding_subjects_by_code`, includes every known finding code even when its
319
+ population is zero, so assurance selectors never confuse a clean class with a
320
+ missing contract field. The top-level audit and persisted-baseline census is
321
+ `affected_subjects_by_code`; both fields count affected subjects, but their
322
+ locations and consumers differ and neither is an alias for the other.
295
323
 
296
324
  ```ts
297
325
  import {
@@ -318,6 +346,63 @@ policy findings. A VCS, company operating model, digital twin, or other
318
346
  non-project domain can replace the assembly adapter while reusing the same
319
347
  registry, traversal, event, context, and audit contracts.
320
348
 
349
+ ### Relationship assurance sources
350
+
351
+ Repository assurance can ratchet graph quality without baking one project's
352
+ policy into the graph kernel. A `dependency_kind` measurement may partition a
353
+ canonical dependency kind by exact `source_kind`, by `source_kind_prefix`, or
354
+ by whether provenance is present or missing. These filters are mutually
355
+ exclusive and preserve the unfiltered measurement contract. This supports
356
+ independent evidence-backed and uncited-edge floors or ceilings while keeping
357
+ the dependency vocabulary extensible.
358
+
359
+ The `prose_edge_gap` source measures distinct holder-target pairs where item
360
+ descriptions, bodies, comments, notes, or learnings mention another canonical
361
+ item but no structured relationship exists in either direction. It performs one
362
+ bounded pass over the supplied items, resolves the collected mentions after the
363
+ canonical id set is complete, reports the exact gap count, partitions the result
364
+ into `explicit_subject` and `implicit_subject` pairs, and caps contributor
365
+ diagnostics with `sample_limit`. Reasoned exemptions may name a whole holder,
366
+ one holder-target pair, or a text fragment within one holder; an exemption
367
+ without a non-empty reason is invalid. This makes roadmap ledgers, negative
368
+ statements, and analysis subjects explicit policy rather than hidden
369
+ false-positive suppression.
370
+
371
+ ```ts
372
+ const evidenceBlocks = {
373
+ kind: "dependency_kind" as const,
374
+ dependency_kind: "blocks",
375
+ source_kind_prefix: "evidence:",
376
+ };
377
+
378
+ const unlinkedMentions = {
379
+ kind: "prose_edge_gap" as const,
380
+ sample_limit: 25,
381
+ exemptions: [
382
+ {
383
+ holder_id: "roadmap-ledger",
384
+ reason: "The ledger inventories work without asserting pairwise edges.",
385
+ },
386
+ ],
387
+ };
388
+ ```
389
+
390
+ Assurance assertions should pin these measurements to observed repository
391
+ baselines: an evidence partition uses a non-regression floor, while uncited
392
+ edges and prose gaps use ceilings. Negative controls must prove the observed
393
+ value passes and a one-unit regression fails before the assertions join the
394
+ repository's graph-composition gate.
395
+
396
+ The scale acceptance runs the public SDK over one million items whose 999,999
397
+ prose mentions each have a corresponding structured edge. It verifies an exact
398
+ zero-gap result, bounded empty diagnostics, a 2,999,998-unit cost receipt, and
399
+ the real item scan count:
400
+
401
+ ```bash
402
+ pnpm build
403
+ node --max-old-space-size=4096 scripts/benchmarks/prose-edge-gap-scale.mjs
404
+ ```
405
+
321
406
  The native workspace adapter is `pm graph <subcommand>`, also available as
322
407
  `PmClient.graph`, `runAction({ action: "graph" })`, and the MCP `pm_graph`
323
408
  tool. `ancestors`/`descendants`/`predecessors`/`successors` expose the
@@ -1,6 +1,6 @@
1
1
  # SDK Primitive Inventory
2
2
 
3
- Tracked work: [pm-lodl](../.agents/pm/tasks/pm-lodl.toon), [pm-8778](../.agents/pm/tasks/pm-8778.toon), [pm-rjqr](../.agents/pm/features/pm-rjqr.toon), [pm-oslr](../.agents/pm/features/pm-oslr.toon), capstone [pm-9x6e](../.agents/pm/tasks/pm-9x6e.toon), parent [pm-usfg](../.agents/pm/epics/pm-usfg.toon).
3
+ Tracked work: [pm-lodl](../.agents/pm/tasks/pm-lodl.toon), [pm-8778](../.agents/pm/tasks/pm-8778.toon), [pm-rjqr](../.agents/pm/features/pm-rjqr.toon), [pm-oslr](../.agents/pm/features/pm-oslr.toon), [pm-6qiwan](../.agents/pm/chores/pm-6qiwan.toon), capstone [pm-9x6e](../.agents/pm/tasks/pm-9x6e.toon), parent [pm-usfg](../.agents/pm/epics/pm-usfg.toon).
4
4
 
5
5
  This inventory records the completed SDK-first migration for the principle `project management = context management`.
6
6
  CLI and MCP modules now import shared host services through `src/sdk/runtime-primitives.ts`; direct `src/core` imports, type-only edges, re-exports, and computed dynamic imports are unconditionally rejected by the static quality gate. There is no allowance file or ratchet escape hatch.
@@ -18,6 +18,20 @@ CLI and MCP modules now import shared host services through `src/sdk/runtime-pri
18
18
 
19
19
  `src/sdk/runtime-primitives.ts` is the curated low-level seam for presentation hosts. It exposes filesystem, schema, history, extension-runtime, telemetry, search, output, and storage services needed to compose the shipped CLI and MCP adapters. External integrations should still prefer typed `PmClient` and top-level SDK operations; runtime primitives exist for embedded hosts that need to build an equivalent presentation layer without private imports.
20
20
 
21
+ ## Tracker Preflight Primitive
22
+
23
+ `assertInitializedTracker` is the shared SDK boundary for commands that require
24
+ an initialized project, while `assertReadableTrackerRoot` supports low-level
25
+ metadata enumeration that intentionally accepts an empty directory. The former
26
+ replaced 50 literal checks across 45 SDK modules. It preserves one structured
27
+ error vocabulary and one exact recovery contract for CLI, MCP dispatch through
28
+ the SDK runtime, first-party packages, and external SDK consumers.
29
+
30
+ The preflight is public from the aggregate SDK; its four-state static recovery
31
+ corpus is also public from `@unbrained/pm-cli/sdk/contracts`. A source-derived
32
+ ratchet prevents the adoption count from falling below 50 and refuses the old
33
+ inline tracker-not-initialized message anywhere under `src/sdk`.
34
+
21
35
  ## Promotion Partition
22
36
 
23
37
  | Promotion item | Primitive family | Primary private domains to promote |
package/docs/TESTING.md CHANGED
@@ -366,6 +366,18 @@ The manifest records baseline bytes and estimated tokens for visible review
366
366
  deltas. Updating it cannot raise answer ceilings, which remain owned by
367
367
  `PM_COMMAND_OUTPUT_BUDGET_CONTRACTS`.
368
368
 
369
+ Diagnostic ceilings share the executable refusal gate:
370
+
371
+ ```bash
372
+ pnpm quality:recovery-closure
373
+ ```
374
+
375
+ The gate replays 22 refusal contracts and ratchets ten representative failure
376
+ paths against `PM_DIAGNOSTIC_OUTPUT_BUDGET_CONTRACTS`. Every diagnostic must fit
377
+ its declared JSON ceiling and preserve a mechanically actionable correction;
378
+ the missing-probe negative control proves that the diagnostic corpus cannot
379
+ silently shrink.
380
+
369
381
  The gate derives every supported harness, model, session, and provenance
370
382
  environment key from the SDK-owned harness descriptor registry. It deletes
371
383
  those host inputs before each fixture invocation, then supplies only the
@@ -480,6 +492,9 @@ pm test <item-id> --metric-below coverage=100 --metric-diff p95_latency
480
492
 
481
493
  Measurements are stored on the producing `test_runs` row, retained with the
482
494
  bounded run history, and exposed consistently by CLI, SDK, MCP, and contracts.
495
+ Each recorded row also keeps a bounded `executions` list with the exact linked
496
+ command plus its requested and effective `pm_context_mode`, so tracker-backed
497
+ verification remains attributable after the transient process logs are gone.
483
498
 
484
499
  ## Linked-Test Assertions
485
500
 
package/marketplace.json CHANGED
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Official marketplace for pm CLI — native git-based project management for Claude Code and AI coding agents.",
9
- "version": "2026.8.20"
9
+ "version": "2026.8.22"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "pm-claude",
14
14
  "source": "./plugins/pm-claude",
15
15
  "description": "Native pm CLI integration for Claude Code — 28 MCP tools, 5 workflow skills, 14 slash commands, 4 subagents, hybrid TUI task tracking, session context injection, and coordination subagents for git-based project management without leaving Claude Code.",
16
- "version": "2026.8.20",
16
+ "version": "2026.8.22",
17
17
  "author": {
18
18
  "name": "unbrained",
19
19
  "url": "https://github.com/unbraind/pm-cli"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-cli",
3
- "version": "2026.8.20",
3
+ "version": "2026.8.22",
4
4
  "description": "Git-native project management CLI for humans and agents.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@11.10.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unbrained/pm-beads",
3
- "version": "2026.8.20",
3
+ "version": "2026.8.22",
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.8.20",
3
+ "version": "2026.8.22",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "description": "First-party pm package for calendar and agenda views.",