@unbrained/pm-cli 2026.5.1 → 2026.5.2

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 (201) hide show
  1. package/CHANGELOG.md +20 -4
  2. package/CONTRIBUTING.md +11 -5
  3. package/PRD.md +17 -1
  4. package/README.md +49 -1101
  5. package/SECURITY.md +6 -11
  6. package/dist/cli/commands/activity.d.ts +10 -0
  7. package/dist/cli/commands/activity.js +13 -1
  8. package/dist/cli/commands/activity.js.map +1 -1
  9. package/dist/cli/commands/aggregate.js.map +1 -1
  10. package/dist/cli/commands/append.js.map +1 -1
  11. package/dist/cli/commands/calendar.js +16 -5
  12. package/dist/cli/commands/calendar.js.map +1 -1
  13. package/dist/cli/commands/claim.js.map +1 -1
  14. package/dist/cli/commands/close.js.map +1 -1
  15. package/dist/cli/commands/comments-audit.js.map +1 -1
  16. package/dist/cli/commands/comments.js.map +1 -1
  17. package/dist/cli/commands/completion.js.map +1 -1
  18. package/dist/cli/commands/config.js.map +1 -1
  19. package/dist/cli/commands/context.js +22 -0
  20. package/dist/cli/commands/context.js.map +1 -1
  21. package/dist/cli/commands/contracts.js.map +1 -1
  22. package/dist/cli/commands/create.js +2 -2
  23. package/dist/cli/commands/create.js.map +1 -1
  24. package/dist/cli/commands/dedupe-audit.js.map +1 -1
  25. package/dist/cli/commands/delete.js.map +1 -1
  26. package/dist/cli/commands/deps.js.map +1 -1
  27. package/dist/cli/commands/docs.js.map +1 -1
  28. package/dist/cli/commands/extension.js.map +1 -1
  29. package/dist/cli/commands/files.js +14 -2
  30. package/dist/cli/commands/files.js.map +1 -1
  31. package/dist/cli/commands/gc.js.map +1 -1
  32. package/dist/cli/commands/get.js.map +1 -1
  33. package/dist/cli/commands/health.js +16 -12
  34. package/dist/cli/commands/health.js.map +1 -1
  35. package/dist/cli/commands/history.js.map +1 -1
  36. package/dist/cli/commands/index.js.map +1 -1
  37. package/dist/cli/commands/init.js.map +1 -1
  38. package/dist/cli/commands/learnings.js.map +1 -1
  39. package/dist/cli/commands/list.d.ts +1 -0
  40. package/dist/cli/commands/list.js +10 -2
  41. package/dist/cli/commands/list.js.map +1 -1
  42. package/dist/cli/commands/normalize.js +5 -17
  43. package/dist/cli/commands/normalize.js.map +1 -1
  44. package/dist/cli/commands/notes.js.map +1 -1
  45. package/dist/cli/commands/reindex.js.map +1 -1
  46. package/dist/cli/commands/restore.js.map +1 -1
  47. package/dist/cli/commands/search.js.map +1 -1
  48. package/dist/cli/commands/stats.js.map +1 -1
  49. package/dist/cli/commands/templates.js.map +1 -1
  50. package/dist/cli/commands/test-all.js.map +1 -1
  51. package/dist/cli/commands/test-runs.js.map +1 -1
  52. package/dist/cli/commands/test.js.map +1 -1
  53. package/dist/cli/commands/update-many.js +1 -6
  54. package/dist/cli/commands/update-many.js.map +1 -1
  55. package/dist/cli/commands/update.js +2 -2
  56. package/dist/cli/commands/update.js.map +1 -1
  57. package/dist/cli/commands/validate.js +23 -18
  58. package/dist/cli/commands/validate.js.map +1 -1
  59. package/dist/cli/error-guidance.js +13 -2
  60. package/dist/cli/error-guidance.js.map +1 -1
  61. package/dist/cli/extension-command-options.js.map +1 -1
  62. package/dist/cli/help-content.js.map +1 -1
  63. package/dist/cli/main.js +29 -13
  64. package/dist/cli/main.js.map +1 -1
  65. package/dist/cli.d.ts +1 -1
  66. package/dist/cli.js +3 -1
  67. package/dist/cli.js.map +1 -1
  68. package/dist/core/extensions/extension-types.d.ts +605 -0
  69. package/dist/core/extensions/extension-types.js +22 -0
  70. package/dist/core/extensions/extension-types.js.map +1 -0
  71. package/dist/core/extensions/index.js.map +1 -1
  72. package/dist/core/extensions/item-fields.js.map +1 -1
  73. package/dist/core/extensions/loader.d.ts +2 -586
  74. package/dist/core/extensions/loader.js +3 -21
  75. package/dist/core/extensions/loader.js.map +1 -1
  76. package/dist/core/extensions/runtime-registrations.js.map +1 -1
  77. package/dist/core/fs/fs-utils.js.map +1 -1
  78. package/dist/core/fs/index.js.map +1 -1
  79. package/dist/core/history/history-stream-policy.js.map +1 -1
  80. package/dist/core/history/history.js.map +1 -1
  81. package/dist/core/history/index.js.map +1 -1
  82. package/dist/core/item/id.js.map +1 -1
  83. package/dist/core/item/index.js.map +1 -1
  84. package/dist/core/item/item-format.js.map +1 -1
  85. package/dist/core/item/parent-reference-policy.js.map +1 -1
  86. package/dist/core/item/parse.js +6 -0
  87. package/dist/core/item/parse.js.map +1 -1
  88. package/dist/core/item/sprint-release-format.js.map +1 -1
  89. package/dist/core/item/status.js.map +1 -1
  90. package/dist/core/item/type-registry.js.map +1 -1
  91. package/dist/core/lock/index.js.map +1 -1
  92. package/dist/core/lock/lock.js +1 -6
  93. package/dist/core/lock/lock.js.map +1 -1
  94. package/dist/core/output/command-aware.js.map +1 -1
  95. package/dist/core/output/output.js.map +1 -1
  96. package/dist/core/schema/runtime-field-filters.js.map +1 -1
  97. package/dist/core/schema/runtime-field-values.js.map +1 -1
  98. package/dist/core/schema/runtime-schema.js.map +1 -1
  99. package/dist/core/search/cache.js +1 -7
  100. package/dist/core/search/cache.js.map +1 -1
  101. package/dist/core/search/embedding-batches.js +4 -0
  102. package/dist/core/search/embedding-batches.js.map +1 -1
  103. package/dist/core/search/providers.js +1 -20
  104. package/dist/core/search/providers.js.map +1 -1
  105. package/dist/core/search/semantic-defaults.js.map +1 -1
  106. package/dist/core/search/vector-stores.d.ts +1 -0
  107. package/dist/core/search/vector-stores.js +23 -27
  108. package/dist/core/search/vector-stores.js.map +1 -1
  109. package/dist/core/sentry/helpers.d.ts +6 -0
  110. package/dist/core/sentry/helpers.js +73 -0
  111. package/dist/core/sentry/helpers.js.map +1 -0
  112. package/dist/core/sentry/instrument.d.ts +4 -0
  113. package/dist/core/sentry/instrument.js +173 -0
  114. package/dist/core/sentry/instrument.js.map +1 -0
  115. package/dist/core/shared/command-types.js.map +1 -1
  116. package/dist/core/shared/conflict-markers.js.map +1 -1
  117. package/dist/core/shared/constants.js.map +1 -1
  118. package/dist/core/shared/errors.js.map +1 -1
  119. package/dist/core/shared/index.d.ts +1 -0
  120. package/dist/core/shared/index.js +1 -0
  121. package/dist/core/shared/index.js.map +1 -1
  122. package/dist/core/shared/primitives.d.ts +13 -0
  123. package/dist/core/shared/primitives.js +33 -0
  124. package/dist/core/shared/primitives.js.map +1 -0
  125. package/dist/core/shared/serialization.js.map +1 -1
  126. package/dist/core/shared/text-normalization.js.map +1 -1
  127. package/dist/core/shared/time.js.map +1 -1
  128. package/dist/core/store/index.js.map +1 -1
  129. package/dist/core/store/item-format-migration.js.map +1 -1
  130. package/dist/core/store/item-store.js +44 -35
  131. package/dist/core/store/item-store.js.map +1 -1
  132. package/dist/core/store/paths.js.map +1 -1
  133. package/dist/core/store/settings.js.map +1 -1
  134. package/dist/core/telemetry/consent.js.map +1 -1
  135. package/dist/core/telemetry/runtime.d.ts +2 -0
  136. package/dist/core/telemetry/runtime.js +40 -13
  137. package/dist/core/telemetry/runtime.js.map +1 -1
  138. package/dist/core/test/background-runs.js.map +1 -1
  139. package/dist/core/test/item-test-run-tracking.js.map +1 -1
  140. package/dist/sdk/cli-contracts.js.map +1 -1
  141. package/dist/sdk/index.d.ts +1 -1
  142. package/dist/sdk/index.js.map +1 -1
  143. package/dist/types/index.js.map +1 -1
  144. package/dist/types.js.map +1 -1
  145. package/docs/AGENT_GUIDE.md +125 -0
  146. package/docs/ARCHITECTURE.md +195 -478
  147. package/docs/COMMANDS.md +199 -0
  148. package/docs/CONFIGURATION.md +146 -0
  149. package/docs/EXTENSIONS.md +146 -645
  150. package/docs/QUICKSTART.md +108 -0
  151. package/docs/README.md +70 -0
  152. package/docs/RELEASING.md +51 -36
  153. package/docs/SDK.md +127 -68
  154. package/docs/TESTING.md +125 -0
  155. package/docs/examples/starter-extension/README.md +39 -25
  156. package/package.json +17 -9
  157. package/dist/command-types.d.ts +0 -1
  158. package/dist/command-types.js +0 -2
  159. package/dist/command-types.js.map +0 -1
  160. package/dist/constants.d.ts +0 -1
  161. package/dist/constants.js +0 -2
  162. package/dist/constants.js.map +0 -1
  163. package/dist/errors.d.ts +0 -1
  164. package/dist/errors.js +0 -2
  165. package/dist/errors.js.map +0 -1
  166. package/dist/fs-utils.d.ts +0 -1
  167. package/dist/fs-utils.js +0 -2
  168. package/dist/fs-utils.js.map +0 -1
  169. package/dist/history.d.ts +0 -1
  170. package/dist/history.js +0 -2
  171. package/dist/history.js.map +0 -1
  172. package/dist/id.d.ts +0 -1
  173. package/dist/id.js +0 -2
  174. package/dist/id.js.map +0 -1
  175. package/dist/item-format.d.ts +0 -1
  176. package/dist/item-format.js +0 -2
  177. package/dist/item-format.js.map +0 -1
  178. package/dist/item-store.d.ts +0 -1
  179. package/dist/item-store.js +0 -2
  180. package/dist/item-store.js.map +0 -1
  181. package/dist/lock.d.ts +0 -1
  182. package/dist/lock.js +0 -2
  183. package/dist/lock.js.map +0 -1
  184. package/dist/output.d.ts +0 -1
  185. package/dist/output.js +0 -2
  186. package/dist/output.js.map +0 -1
  187. package/dist/parse.d.ts +0 -1
  188. package/dist/parse.js +0 -2
  189. package/dist/parse.js.map +0 -1
  190. package/dist/paths.d.ts +0 -1
  191. package/dist/paths.js +0 -2
  192. package/dist/paths.js.map +0 -1
  193. package/dist/serialization.d.ts +0 -1
  194. package/dist/serialization.js +0 -2
  195. package/dist/serialization.js.map +0 -1
  196. package/dist/settings.d.ts +0 -1
  197. package/dist/settings.js +0 -2
  198. package/dist/settings.js.map +0 -1
  199. package/dist/time.d.ts +0 -1
  200. package/dist/time.js +0 -2
  201. package/dist/time.js.map +0 -1
@@ -1,575 +1,292 @@
1
- # pm-cli Architecture
1
+ # Architecture
2
2
 
3
- This document describes the internal architecture of `pm-cli` for contributors and maintainers.
3
+ This page is for contributors changing `pm-cli` internals. Users should start with [Quickstart](QUICKSTART.md). Agents should start with [Agent Guide](AGENT_GUIDE.md).
4
4
 
5
- ## Overview
5
+ ## Agent Quick Context
6
6
 
7
- `pm-cli` is a TypeScript ESM CLI built on Node.js 20+. It follows a clean separation between CLI wiring and domain logic:
7
+ - CLI wiring lives in `src/cli/`.
8
+ - Domain behavior lives in `src/core/`.
9
+ - Public SDK exports live in `src/sdk/`.
10
+ - Items are stored as TOON by default; history is append-only JSONL.
11
+ - `pm contracts` is the machine-readable runtime contract source.
8
12
 
9
- ```
10
- src/
11
- cli/ CLI layer: command registration, option parsing, output rendering
12
- core/ Domain logic: storage, locking, history, search, extensions
13
- extensions/ Optional extension authoring sources (non-bundled)
14
- types/ Shared TypeScript type definitions
15
- .agents/
16
- pm/extensions/ Bundled managed extension sources shipped with package (beads, todos)
17
- ```
13
+ Tracked documentation work: [pm-1sb2](../.agents/pm/tasks/pm-1sb2.toon).
14
+
15
+ ## System Overview
16
+
17
+ `pm-cli` is a TypeScript ESM CLI for Node.js 20+. It is file-backed, git-native, deterministic, and designed for concurrent human plus agent workflows.
18
+
19
+ High-level flow:
20
+
21
+ 1. Commander parses CLI input in `src/cli/main.ts`.
22
+ 2. Command modules normalize options and call domain services.
23
+ 3. Domain services load settings, acquire locks when needed, mutate canonical item documents, and append history.
24
+ 4. Renderers emit TOON by default, JSON when requested, and markdown for calendar views.
25
+ 5. Extensions can add commands, schema, renderers, import/export handlers, search providers, lifecycle hooks, and selected service overrides.
18
26
 
19
27
  ## Source Tree
20
28
 
21
- ```
29
+ ```text
22
30
  src/
23
- cli.ts Main CLI entry (shim that imports cli/main.ts)
31
+ cli.ts
24
32
  cli/
25
- main.ts Command registration with commander; global option wiring
33
+ main.ts
26
34
  commands/
27
- init.ts pm init
28
- create.ts pm create (full schema flag surface)
29
- templates.ts pm templates save/list/show
30
- get.ts pm get
31
- update.ts pm update (including ownership-safe metadata audits via --allow-audit-update and dependency-only audits via --allow-audit-dep-update)
32
- update-many.ts pm update-many (bulk apply/dry-run/rollback checkpoint workflow)
33
- normalize.ts pm normalize (lifecycle metadata dry-run planning + optional apply workflow)
34
- append.ts pm append
35
- close.ts pm close (includes optional close-time validation mode)
36
- delete.ts pm delete
37
- claim.ts pm claim / release
38
- release.ts (re-exports from claim.ts)
39
- list.ts pm list (active-only: excludes closed/canceled) / list-all / list-* commands with projection, sorting, offset, and JSON stream controls
40
- aggregate.ts pm aggregate (default grouped child-count governance queries)
41
- dedupe-audit.ts pm dedupe-audit (exact/fuzzy/parent-scoped duplicate clustering)
42
- calendar.ts pm calendar / pm cal (agenda/day/week/month views)
43
- context.ts pm context / pm ctx (critical work + agenda snapshot)
44
- comments.ts pm comments
45
- notes.ts pm notes
46
- learnings.ts pm learnings
47
- files.ts pm files
48
- docs.ts pm docs
49
- deps.ts pm deps (dependency tree/graph projection)
50
- test.ts pm test (add/remove/run linked tests; optional forced progress visibility)
51
- test-all.ts pm test-all (orchestration; optional forced progress visibility + pre-run limit/offset pagination)
52
- test-runs.ts pm test-runs (background run lifecycle: list/status/logs/stop/resume; bare command defaults to list)
53
- search.ts pm search (keyword / semantic / hybrid)
54
- reindex.ts pm reindex (optional forced progress visibility)
55
- history.ts pm history
56
- activity.ts pm activity (timeline filters + JSON stream mode)
57
- restore.ts pm restore
58
- stats.ts pm stats
59
- health.ts pm health
60
- validate.ts pm validate (metadata/resolution/lifecycle/files/command-reference/history drift checks)
61
- gc.ts pm gc (dry-run and scoped cache cleanup)
62
- contracts.ts pm contracts (machine-readable contracts/schema surface)
63
- config.ts pm config
64
- extension.ts pm extension lifecycle manager (install/uninstall/explore/manage/activate/deactivate)
65
- completion.ts pm completion (lazy/eager tag completion modes)
66
- beads.ts Beads import runtime used by bundled managed extension
67
- todos.ts Todos import/export runtime used by bundled managed extension
68
- index.ts barrel re-export
69
- extension-command-options.ts Loose option parser for dynamic extension commands
35
+ help-content.ts
36
+ error-guidance.ts
37
+ extension-command-options.ts
70
38
  core/
71
39
  extensions/
72
- loader.ts Extension manifest discovery, load, activate
73
- index.ts barrel
74
40
  fs/
75
- fs-utils.ts Atomic write, path existence, mkdirp
76
- index.ts barrel
77
41
  history/
78
- history.ts RFC6902 patch generation, history append, replay
79
- index.ts barrel
80
42
  item/
81
- id.ts ID generation (cryptographic random base36) and normalization
82
- item-format.ts Item front-matter serializer (canonical key order, determinism)
83
- parse.ts Markdown item file parser (JSON front-matter + body)
84
- parent-reference-policy.ts Parent-reference policy normalization + warning/strict validation helpers
85
- type-registry.ts Runtime item-type registry (built-ins + settings + extensions)
86
- index.ts barrel
87
43
  lock/
88
- lock.ts Exclusive lock acquire/release with TTL and stale detection
89
- index.ts barrel
90
44
  output/
91
- output.ts TOON / JSON output rendering
92
45
  search/
93
- cache.ts Keyword index artifact read/write (manifest.json + embeddings.jsonl)
94
- embedding-batches.ts Deterministic batch embedding generation with retry
95
- providers.ts OpenAI / Ollama embedding provider abstraction
96
- vector-stores.ts Qdrant / LanceDB vector store abstraction
46
+ store/
97
47
  test/
98
- background-runs.ts Background linked-test run registry/worker lifecycle + dedupe
99
- item-test-run-tracking.ts Settings-gated bounded item `test_runs` summary persistence
100
- telemetry/
101
- consent.ts First-run telemetry consent prompt + non-interactive guardrails
102
- runtime.ts Telemetry event capture, redaction, queueing, and exporter retry flow
103
48
  shared/
104
- command-types.ts GlobalOptions, shared command type definitions
105
- constants.ts Exit codes, required directory names
106
- conflict-markers.ts Merge-conflict marker detection helpers
107
- errors.ts PmCliError with exit code + optional guidance context
108
- serialization.ts Deterministic JSON serialization (stable key order)
109
- time.ts ISO/date parsing helpers, relative offsets, and field-attributed parse diagnostics
110
- index.ts barrel
111
- store/
112
- item-store.ts File-backed item CRUD with lock/atomic write contract
113
- paths.ts PM root resolution (PM_PATH, --path, cwd)
114
- settings.ts settings.json read/write
115
- index.ts barrel
116
- types/
117
- index.ts ItemFrontMatter, ItemType, ItemStatus, Dependency, etc.
118
49
  sdk/
119
- cli-contracts.ts Canonical command/action contracts + JSON Schema exports
120
- index.ts Public SDK exports
121
- command-types.ts (re-export shim)
122
- constants.ts (re-export shim)
123
- errors.ts (re-export shim)
124
- ... (other re-export shims for backward compat)
50
+ cli-contracts.ts
51
+ index.ts
52
+ types/
53
+ tests/
54
+ unit/
55
+ integration/
125
56
  .agents/
126
57
  pm/
127
58
  extensions/
128
- beads/
129
- manifest.json Bundled managed beads extension manifest
130
- index.js Registers `beads import` command and loads runtime from dist
131
- todos/
132
- manifest.json Bundled managed todos extension manifest
133
- index.js Registers `todos import` / `todos export` and loads runtime from dist
59
+ docs/
60
+ scripts/
134
61
  ```
135
62
 
136
- ## Command Contract Registry
63
+ Important public docs:
137
64
 
138
- Command/action contract metadata is centralized in `src/sdk/cli-contracts.ts`.
65
+ - [Command Reference](COMMANDS.md)
66
+ - [Configuration](CONFIGURATION.md)
67
+ - [Testing](TESTING.md)
68
+ - [Extensions](EXTENSIONS.md)
69
+ - [SDK](SDK.md)
139
70
 
140
- The same registry drives:
71
+ ## Storage Layout
141
72
 
142
- - commander option normalization in `src/cli/main.ts`
143
- - shell completion flag/command surfaces in `src/cli/commands/completion.ts`
144
- - Pi wrapper action enum, tool `inputSchema`, and CLI arg mapping in `.pi/extensions/pm-cli/index.ts`
145
- - runtime `pm contracts` payload generation for action/command/schema introspection
146
- - runtime schema augmentation for active extension commands/actions (including extension source metadata and extension-defined flag surfaces)
147
- - additive command surfaces such as `templates-*` actions, extension lifecycle actions (`extension-install`, `extension-uninstall`, `extension-explore`, `extension-manage`, `extension-doctor`, `extension-adopt`, `extension-adopt-all`, `extension-activate`, `extension-deactivate`), `history --diff/--verify`, files/docs path hygiene flags (`--add-glob`, `--migrate`, `--append-stable`, `--validate-paths`, `--audit`), validate governance/file drift flags (`--check-lifecycle`, `--check-stale-blockers`, `--scan-mode`, `--include-pm-internals`), list projection/sort controls (`--compact`, `--fields`, `--sort`, `--order`), `aggregate`/`dedupe-audit` action surfaces, comments-audit governance filters/export controls (`--parent`, `--tag`, `--sprint`, `--release`, `--priority`, `--latest`, `--full-history`, `--limit` alias), lifecycle aliases (`start-task`, `pause-task`, `close-task`), bulk mutation (`update-many`), lifecycle metadata normalization (`normalize`), and ownership-safe audit update controls (`update --allow-audit-update`, `update --allow-audit-dep-update`), health vector refresh controls (`--check-only`, `--no-refresh`, `--refresh-vectors`), contracts projections (`--flags-only`, `--availability-only`), completion mode controls (`--eager-tags` + lazy `completion-tags` path), calendar period control (`--full-period`), activity filtering/stream controls (`--id`, `--op`, `--author`, `--from`, `--to`, `--stream`), global pager suppression (`--no-pager`), `create --create-mode`, `comments --allow-audit-comment`, `release --allow-audit-release`, `test-all --limit/--offset`, run-level PM-context override (`--override-linked-pm-context`), linked-test preflight/remediation controls (`--check-context`, `--auto-pm-context`), `gc --dry-run/--scope`, `update --replace-deps`, richer `deps` traversal controls, and `contracts` create-required metadata projections
73
+ Project tracker root defaults to `.agents/pm/`.
148
74
 
149
- This keeps human CLI UX and machine-facing contracts aligned while preserving additive evolution; new projection flags such as `--command`, `--flags-only`, and `--availability-only` provide lower-noise machine payloads without replacing the full default contract corpus.
75
+ ```text
76
+ .agents/pm/
77
+ settings.json
78
+ epics/
79
+ features/
80
+ tasks/
81
+ chores/
82
+ issues/
83
+ decisions/
84
+ events/
85
+ reminders/
86
+ milestones/
87
+ meetings/
88
+ history/
89
+ locks/
90
+ index/
91
+ search/
92
+ extensions/
93
+ ```
150
94
 
151
- Contract projection behavior also keeps action filters deterministic: when `pm contracts --flags-only` is called with `--action` and no `--command`, the emitted `command_flags` rows are scoped to commands that implement the selected action(s).
95
+ Required data:
152
96
 
153
- ## Item Storage
97
+ - item documents under type folders
98
+ - `history/<id>.jsonl`
99
+ - `settings.json`
154
100
 
155
- Each item is stored as a format-configured document file:
101
+ Optional rebuildable data:
156
102
 
157
- ```
158
- .agents/pm/
159
- <type-folder>/<id>.toon default item storage (TOON root-object fields)
160
- <type-folder>/<id>.md fully supported JSON metadata object + markdown body
161
- history/<id>.jsonl append-only RFC6902 patch log
162
- locks/<id>.lock exclusive lock metadata (JSON)
163
- settings.json project configuration
164
- index/manifest.json keyword index cache (optional, rebuildable)
165
- search/embeddings.jsonl keyword corpus records (optional, rebuildable)
166
- search/vectorization-status.json semantic vector freshness ledger (optional, rebuildable)
167
- extensions/ project-local extensions
168
- extensions/.managed-extensions.json scope-local extension manager state (optional, lifecycle-managed)
169
- ```
103
+ - keyword and vector search cache files
104
+ - generated index metadata
170
105
 
171
- ### Item File Format
106
+ ## Item Documents
172
107
 
173
- Default TOON item document:
108
+ Default format is TOON:
174
109
 
175
110
  ```toon
176
111
  id: pm-a1b2
177
- title: ...
178
- # ...
112
+ title: Implement restore replay
113
+ description: Restore should rebuild target item state from history.
114
+ type: Task
115
+ status: in_progress
116
+ priority: 1
117
+ tags[2]: history,restore
179
118
  body: |
180
- Optional markdown body here.
181
- ```
182
-
183
- Alternative markdown item document:
184
-
185
- ```md
119
+ Implementation notes.
186
120
  ```
187
- {
188
- "id": "pm-a1b2",
189
- "title": "...",
190
- ...
191
- }
192
-
193
- Optional markdown body here.
194
- ```
195
-
196
- Fields are normalized and serialized in canonical key order (defined in `item-format.ts`) before hashing/history patch generation, regardless of on-disk item format.
197
-
198
- `front_matter` is the internal object key used by the TypeScript document model; TOON files store identical metadata as top-level keys (no YAML front matter layer).
199
-
200
- Type resolution is centralized in the runtime type registry:
201
121
 
202
- - built-in types (`Epic`, `Feature`, `Task`, `Chore`, `Issue`, `Event`, `Reminder`, `Milestone`, `Meeting`)
203
- - `settings.item_types.definitions`
204
- - extension `registerItemTypes(...)` registrations
122
+ Alternative format is JSON-front-matter markdown. `front_matter` is the internal TypeScript model key; TOON stores the same metadata as top-level fields.
205
123
 
206
- The registry is used by create/update validation, list/search/calendar type filters, completion scripts, and store path routing.
124
+ Built-in item types:
207
125
 
208
- Type definitions can additionally provide `command_option_policies` entries (`create`/`update`) to mark options as required, disabled, or hidden in policy-aware help guidance while preserving default behavior when unset.
126
+ - `Epic`
127
+ - `Feature`
128
+ - `Task`
129
+ - `Chore`
130
+ - `Issue`
131
+ - `Decision`
132
+ - `Event`
133
+ - `Reminder`
134
+ - `Milestone`
135
+ - `Meeting`
209
136
 
210
- Scheduling metadata is persisted directly in item metadata:
137
+ Runtime type resolution merges built-ins, `settings.item_types.definitions`, and extension `registerItemTypes(...)` registrations.
211
138
 
212
- - `reminders?: Array<{ at: ISO timestamp; text: string }>`
213
- - reminders are normalized and sorted deterministically by `at` then `text`
214
- - `events?: Array<{ start_at: ISO timestamp; end_at?: ISO timestamp; title?: string; description?: string; location?: string; timezone?: string; all_day?: boolean; recurrence?: RecurrenceRule }>`
215
- - recurrence supports `freq`, `interval`, `count`, `until`, `by_weekday`, `by_month_day`, and `exdates`
216
- - event and recurrence arrays are normalized/sorted deterministically for stable serialization
217
- - `pm create` and `pm update` support repeatable `--reminder` and `--event` values with explicit clear flags (`--clear-reminders`, `--clear-events`)
218
-
219
- ### Parallel Git/Worktree Safety
220
-
221
- `pm` storage is designed for high-concurrency git workflows (branches, worktrees, and multi-host collaboration):
222
-
223
- 1. **First-class dual formats** — `.toon` and `.md` are both supported for item storage.
224
- 2. **Single format of record per repo** — `settings.item_format` defines the canonical extension; migration removes alternate-extension drift.
225
- 3. **Deterministic canonicalization** — normalized fields and stable ordering reduce diff noise and improve merge predictability.
226
- 4. **Atomic writes** — item files are replaced via temp + `rename`, preventing torn writes.
227
- 5. **Append-only history** — `history/<id>.jsonl` records RFC6902 patches with before/after hashes for auditability and restore.
139
+ ## Mutation Contract
228
140
 
229
- If concurrent edits modify the same semantic fields on separate branches, git can still surface textual conflicts. In those cases, the deterministic canonical model plus append-only history is intended to make reconciliation explicit and loss-resistant rather than silent.
141
+ Every item mutation follows the same safety path:
230
142
 
231
- ## Mutation Contract
143
+ 1. Resolve project root and settings.
144
+ 2. Acquire item lock when mutating existing item state.
145
+ 3. Read and parse the current canonical item document.
146
+ 4. Enforce ownership and policy gates.
147
+ 5. Compute `before_hash`.
148
+ 6. Apply mutation in memory.
149
+ 7. Set `updated_at`.
150
+ 8. Compute RFC6902 patch and `after_hash`.
151
+ 9. Write item atomically through temp-file plus rename.
152
+ 10. Append one history JSONL line.
153
+ 11. Release lock.
232
154
 
233
- Every item mutation follows this sequence:
234
-
235
- 1. **Acquire lock** — exclusive open on `locks/<id>.lock`; reject if stale and no `--force`
236
- 2. **Read current item** — parse configured-format item (`.toon` or `.md`) into canonical `{ front_matter, body }`
237
- 3. **Enforce history stream policy** — for existing-item mutations, apply `settings.history.missing_stream` (`auto_create` or `strict_error`) before mutation writes
238
- 4. **Compute `before_hash`** — SHA-256 of canonical `{ front_matter, body }` JSON
239
- 5. **Apply mutation** — in-memory model update
240
- 6. **Update `updated_at`** — every mutation must change this timestamp
241
- 7. **Compute patch + `after_hash`** — RFC6902 diff; SHA-256 of new canonical state
242
- 8. **Atomic write** — write configured-format item file via temp + `rename` (single syscall, OS-atomic)
243
- 9. **Append history line** — JSONL append to `history/<id>.jsonl`
244
- 10. **Release lock** — unlink lock file
245
-
246
- If step 7 or 8 fails, the item file is rolled back (if write succeeded) before returning failure.
247
-
248
- When `update --type` changes an item's resolved type folder, mutation logic performs a safe file move to the target folder and rolls back on failure.
249
- `pm update` now supports transactional linked/log collection mutations (`--comment`, `--note`, `--learning`, `--file`, `--test`, `--doc`) so metadata and linked surfaces can be updated under one lock/history entry. Dedicated commands (`pm comments|notes|learnings|files|test|docs`) remain available for focused single-surface operations.
250
-
251
- ### Additive Diagnostics and Path Hygiene
252
-
253
- - `pm history --diff` adds field-level patch summaries without changing base history output.
254
- - `pm history --verify` validates stream hash-chain replay and current-item hash alignment.
255
- - `pm close --validate-close [warn|strict]` adds optional close-time resolution-field validation without changing default close semantics.
256
- - `pm files` and `pm docs` support additive linked-path hygiene options:
257
- - `--add-glob <pattern>` for deterministic batch expansion into linked entries
258
- - `--migrate from=<old>,to=<new>` for bulk prefix migration
259
- - `--append-stable` on `pm files` to append/dedupe without full-array resorting
260
- - `--validate-paths` for resolved path-existence checks
261
- - `--audit` for cross-item linked-path usage inspection
262
- - `pm files --list` for explicit non-mutating linked-file listing
263
- - `pm files discover <ID>` scans item text fields for existing project/global file paths, reports addable vs already linked candidates, and only writes missing links when `--apply` is supplied
264
- - `pm comments|notes|learnings --allow-audit-comment` enables append-only audit log entries on items assigned to other owners without broad ownership override semantics.
265
- - `pm release --allow-audit-release` enables non-owner release handoffs that only clear assignee metadata without broad ownership override semantics.
266
- - `pm comments-audit` now emits additive top-level governance `summary` metrics (`totals`, coverage ratio/percent, and `by_type`) across latest and full-history export modes while preserving existing item/export payloads; `--limit` is available as an alias for legacy `--limit-items`.
267
- - `pm test-runs` now defaults bare command execution to list output, aligning CLI behavior with explicit `pm test-runs list`.
268
- - `pm create --create-mode strict|progressive` keeps strict mode as default while enabling staged progressive creation for governance triage workflows.
269
- - Strict create-mode missing-required guidance now includes direct remediation hints (`--create-mode progressive`, and scheduling-type `--schedule-preset lightweight` guidance for `Reminder`/`Meeting`/`Event`).
270
- - Time/date parse errors are field-attributed (for example `event.end`, `reminder.at`, `--from`, `deadline-before`) with explicit guidance when unsupported compound relative expressions (for example `+3d+1h`) are provided.
271
- - `pm create` log-seed repeatables (`--comment`, `--note`, `--learning`) now enforce explicit key boundaries (`author`, `created_at`, `text`) and reject parsed extra keys with usage guidance so unquoted key:value-like comma continuations cannot silently truncate seeded narrative text.
272
- - `pm deps --format tree|graph --max-depth <n> --collapse none|repeated --summary` provides read-only dependency traversal from stored front matter, with deterministic ordering, cycle markers, missing-node reporting, and governance-friendly bounded projections.
273
- - `pm update --replace-deps` enables one-shot atomic dependency replacement without separate clear/add mutations.
274
- - `pm update --allow-audit-update` provides ownership-safe non-owner metadata mutation mode with explicit lifecycle/ownership guardrails.
275
- - `pm update --allow-audit-dep-update` provides ownership-safe non-owner append-only dependency additions (`--dep`) without broad force semantics.
276
- - `pm update-many` adds native bulk mutation orchestration with deterministic filter targeting, dry-run planning, checkpoint capture, and rollback-by-checkpoint-id flow; apply payload parity now includes linked-array mutation flags (`--dep/--comment/--note/--learning/--file/--test/--doc/--reminder/--event`), explicit `--clear-*` controls, and atomic `--replace-deps`/`--replace-tests` semantics while dry-run planning reports linked-array mutation intent per item.
277
- - Lifecycle aliases (`pm start-task`, `pm pause-task`, `pm close-task`) compose claim/update/close/release primitives into discoverable single commands while preserving canonical history entries.
278
- - `pm get` now returns `claim_state` metadata (active assignee plus latest claim/release history context) for ownership-aware automation.
279
- - `pm get --json` payload shape is deterministic: `{ item, body, linked, claim_state }`, with body intentionally top-level for single-item diff/merge workflows.
280
- - `pm list` / `pm list-*` support additive projection (`--compact`, `--fields`, `--include-body`), configurable sorting (`--sort`, `--order`), `--offset` pagination, and JSON-only `--stream` line-delimited output for large datasets.
281
- - `pm aggregate` provides grouped count projections (default `--group-by parent,type`; supported dimensions: `parent,type,priority,status,assignee,tags,sprint,release`; `--count` accepted for explicit parity) for governance decomposition and triage checks.
282
- - `pm gc` now supports no-side-effect previews (`--dry-run`) and scoped cleanup (`--scope index|embeddings|runtime`) with output guidance for reindex follow-up when search artifacts are removed.
283
- - `pm dedupe-audit` provides exact-title, fuzzy-title, and parent-scoped duplicate cluster detection with machine-readable merge suggestions.
284
- - `pm validate` runs standalone repository checks (`metadata`, `resolution`, `lifecycle`, `files`, `command_references`, `history_drift`), supports metadata policy selection via `--metadata-profile core|strict|custom`, supports lifecycle-governance drift targeting via `--check-lifecycle` plus optional stale-blocker heuristics via `--check-stale-blockers`, reads lifecycle pattern lists from `settings.validation.lifecycle_*_patterns` (tunable through config criteria-list keys), reports deterministic pattern-source metadata (`default|settings`) and effective pattern arrays in lifecycle check details, supports file candidate selection via `--scan-mode default|tracked-all|tracked-all-strict`, supports additive internal-audit coverage with `--include-pm-internals`, and returns deterministic filtered + raw file scan metrics, structured `excluded_by_reason` summaries, plus stale PM-id command-reference diagnostics.
285
-
286
- ## Calendar Pipeline
287
-
288
- `pm calendar` (`pm cal`) is a read-only projection command that derives scheduling events from existing item metadata.
289
-
290
- Pipeline:
291
-
292
- 1. Resolve PM root and load settings.
293
- 2. Read all item front matter records.
294
- 3. Apply deterministic item filters (`type`, `tag`, `priority`, `status`, `assignee`, `sprint`, `release`).
295
- 4. Expand each item into calendar events:
296
- - deadline event (if `deadline` is set)
297
- - reminder events (for each `reminders[]` entry)
298
- - one-off scheduled events (`events[]` entries without recurrence)
299
- - recurring event occurrences (`events[].recurrence`) expanded inside a bounded recurrence window
300
- 5. Apply source controls and recurrence bounds:
301
- - `--include deadlines|reminders|events|all`
302
- - `--recurrence-lookahead-days`, `--recurrence-lookback-days`
303
- - `--occurrence-limit` (cap per recurring event expansion)
304
- 6. Apply view windows:
305
- - `agenda` (default, optional `--from`/`--to`)
306
- - `day`, `week`, `month` (anchored by `--date`)
307
- - `--past` toggles lower-bound behavior for bounded views
308
- - `--full-period` (day/week/month only) keeps full anchored-period lower bounds instead of now-clipping
309
- 7. Sort events deterministically by timestamp, priority, item id, event kind, event title, then reminder text.
310
- 8. Bucket events by UTC date and compute summary counts (`events`, `items`, `deadlines`, `reminders`, `scheduled`) plus deterministic aggregate breakdowns (`by_kind`, `by_type`, `by_status`, `recurring_events`).
311
- 9. Render markdown event rows with deterministic detail tokens (item type, recurrence markers/rules, end-time derivation, timezone/location metadata, and description context when present).
312
-
313
- Output behavior is command-specific: `pm calendar` defaults to markdown for agent/human readability while keeping explicit `--format`/`--json` overrides. Calendar range payloads include `period_start`/`period_end` and `full_period` metadata for deterministic downstream interpretation. Global TOON defaults for other commands are unchanged.
314
-
315
- ## Context Pipeline
316
-
317
- `pm context` (`pm ctx`) is a read-only context-assembly command that combines prioritized active work with agenda/reminder visibility.
318
-
319
- Pipeline:
320
-
321
- 1. Run `list` logic with non-terminal filtering and optional shared filters (`type`, `tag`, `priority`, `parent`, `assignee`, `sprint`, `release`).
322
- 2. Rank candidate items deterministically by status (`in_progress` before `open`), then priority, explicit `order`, deadline proximity, recency, and id tie-break.
323
- 3. Split ranked active items into:
324
- - high-level focus (`Epic`, `Feature`)
325
- - low-level focus (all other item types, including calendar-native built-ins such as `Event`, `Reminder`, `Milestone`, and `Meeting`)
326
- 4. If active focus is empty, project top blocked items into a blocked fallback section.
327
- 5. Run `calendar` logic in agenda mode with shared filters and context window controls (`--date`, `--from`, `--to`, `--past`).
328
- 6. Filter agenda projection to non-terminal items and summarize deadlines/reminders/events counts.
329
- 7. Return deterministic context payload (`output_default`, `window`, `filters`, `summary`, focus sections, and agenda section) with TOON default output and optional `--format`/`--json` overrides.
330
-
331
- ## Activity Pipeline
332
-
333
- `pm activity` is a read-only history projection command for timeline inspection and automation export.
334
-
335
- Pipeline:
336
-
337
- 1. Resolve PM root and enumerate history stream files.
338
- 2. Parse history records in deterministic timestamp order.
339
- 3. Apply optional filters (`--id`, `--op`, `--author`, `--from`, `--to`) before row materialization.
340
- 4. Validate time-window bounds (`--from <= --to`) and return usage errors deterministically on invalid windows.
341
- 5. Apply `--limit` to bounded result sets.
342
- 6. Render either:
343
- - standard payload `{ activity, count, limit, filters }`, or
344
- - JSON stream mode (`--json --stream [rows|ndjson|jsonl]`) with deterministic `meta` then `entry` records.
345
-
346
- ## Terminal and Process I/O Compatibility
347
-
348
- `pm-cli` keeps runtime behavior terminal-neutral so commands behave consistently across native shells, IDE-integrated terminals, and emulated PTY backends:
349
-
350
- 1. **Plain deterministic output** — core output paths emit TOON/JSON/markdown text with stable key ordering and no required custom terminal control protocol.
351
- 2. **Sparse TOON fallback output** — default TOON output renders command payloads directly and recursively omits `null`/`undefined`/empty arrays/empty objects to reduce token overhead while preserving meaningful scalar values.
352
- 3. **Fail-fast stdin semantics** — stdin token readers reject interactive TTY stdin for piped-only flows (`-`) and provide explicit EOF guidance instead of waiting indefinitely.
353
- 4. **Graceful error exits** — CLI error handling preserves canonical exit codes using graceful `process.exitCode` semantics to reduce output truncation risk under buffered writes.
354
- 5. **Broken-pipe-safe output writes** — stream error handlers treat `EPIPE` as expected pipeline behavior: stdout writes preserve successful exits (pipeline-friendly readers) while stderr `EPIPE` remains non-zero, and both suppress unhandled stack traces.
355
- 6. **Linked test runtime hardening** — linked test subprocess execution uses shell-compatible spawn orchestration, closes child stdin immediately, applies deterministic runtime environment defaults, supports additive run-level/per-test env directives (`--env-set`, `--env-clear`, `--shared-host-safe`, plus linked metadata `env_set`/`env_clear`/`shared_host_safe`), supports additive PM-context controls (`--pm-context schema|tracker|auto`, `--override-linked-pm-context`, `--check-context`, `--auto-pm-context`, linked metadata `pm_context_mode=schema|tracker|auto`, `--fail-on-context-mismatch`, `--fail-on-skipped`, `--fail-on-empty-test-run`, `--require-assertions-for-pm`), enforces default schema-mode mismatch failures for PM tracker-read linked commands, emits mismatch guidance that explicitly calls out per-test `pm_context_mode` overrides when they supersede run-level context mode (unless explicitly overridden), can emit deterministic `context_preflight` warning summaries when requested, evaluates optional linked-test assertions (stdout/stderr contains/regex, min-lines, JSON equals/gte), detects high-confidence empty-selection runner signals when `--fail-on-empty-test-run` is enabled, emits per-run `execution_context` metadata for PM-command parity diagnostics (including tracker-read classification, `requested_pm_context_mode`, and `auto_pm_context_applied`), emits interactive stderr heartbeat progress for long runs (with explicit non-interactive `--progress`), supports managed background execution (`--background`) with `pm test-runs` lifecycle controls and duplicate-run fingerprints plus hardened `requested_by` fallback attribution, supports pre-run blast-radius pagination in `pm test-all` via `--offset`/`--limit`, enforces timeout/maxBuffer diagnostics with force-kill fallback plus structured failure categorization (`infra_collision`, `assertion_failure`, `empty_run`, etc.), and maps `pm test --run` linked failures to dependency-failed exit code (`5`) for CI-safe gating parity with `pm test-all`.
356
-
357
- ## Help and Error Guidance Pipeline
358
-
359
- Help and error UX is centralized to reduce per-command drift:
360
-
361
- 1. `src/cli/help-content.ts` defines command-path help bundles (`why`, `examples`, optional `tips`) and attaches compact help by default (`Intent` + one example) with deep help enabled via `--explain`.
362
- 2. `src/cli/main.ts` performs bootstrap routing for help paths so `pm help`/`pm help <command>` are deterministic success flows, non-interactive help routes suppress pager blocking (auto-disable when stdout is not TTY), global `--no-pager` provides explicit pager suppression, and `--help --json` emits machine-readable help payloads.
363
- 3. Dynamic extension command descriptors (intent/action/examples/failure hints/arguments/flags) are merged into runtime help surfaces when available, with graceful fallback for legacy extensions that only register command handlers/flags.
364
- 4. `src/cli/error-guidance.ts` defines canonical guidance descriptors and renders either structured text sections or machine-readable JSON envelopes (`type`, `code`, `title`, `detail`, `required`, `exit_code`, optional remediation fields), with `PmCliError.context` overrides for precise runtime guidance.
365
- 5. `src/cli/main.ts` routes commander usage failures and `PmCliError` failures through these renderers, emitting JSON diagnostics when `--json` is active.
366
- 6. Commander native stderr writes are suppressed so the CLI emits a single high-signal guidance payload per failure path.
155
+ If a write fails after state changes begin, mutation code attempts rollback before returning the error.
367
156
 
368
157
  ## History and Restore
369
158
 
370
- Each history entry is a JSONL line:
159
+ History entries are append-only JSONL records:
371
160
 
372
161
  ```json
373
162
  {
374
- "ts": "ISO timestamp",
375
- "author": "string",
376
- "op": "create|update|append|...|restore",
377
- "patch": [ /* RFC6902 ops */ ],
378
- "before_hash": "sha256-hex",
379
- "after_hash": "sha256-hex",
380
- "message": "optional"
163
+ "ts": "2026-05-01T12:00:00.000Z",
164
+ "author": "codex-agent",
165
+ "op": "update",
166
+ "patch": [],
167
+ "before_hash": "sha256...",
168
+ "after_hash": "sha256...",
169
+ "message": "Start implementation"
381
170
  }
382
171
  ```
383
172
 
384
- `pm restore <ID> <TIMESTAMP|VERSION>` replays patches from `op=create` through the target entry, rebuilding exact canonical state.
385
-
386
- ## Extension System
173
+ `pm restore <id> <timestamp-or-version>` replays history from create through the target record and appends a restore event. Restore does not rewrite prior history.
387
174
 
388
- Extensions are Node.js modules with an `activate(api)` export. For package consumers, extension types and helpers are exported through `@unbrained/pm-cli/sdk`.
175
+ Useful diagnostics:
389
176
 
390
- ```ts
391
- export function activate(api: ExtensionApi): void {
392
- api.registerCommand({
393
- name: "my command",
394
- action: "my-command",
395
- intent: "Short command intent shown in runtime help/contracts.",
396
- examples: ["pm my command --limit 5"],
397
- run: async (context) => ({ ok: true, command: context.command }),
398
- });
399
- api.hooks.beforeCommand((ctx) => { /* ... */ });
400
- }
177
+ ```bash
178
+ pm history <id> --diff --verify
179
+ pm activity --id <id> --limit 50
180
+ pm validate --check-history-drift
401
181
  ```
402
182
 
403
- Load order: **core built-ins → global (`~/.pm-cli/extensions/`) → project (`.agents/pm/extensions/`)**.
183
+ ## Command Contracts
404
184
 
405
- Project-local extensions override global by default. Runtime dispatch is extension-first: if an extension registers a command handler for an existing core command path, the extension handler executes instead of the core action. Command result overrides and renderer overrides are still evaluated after dispatch with deterministic "last registration wins" precedence.
185
+ Command/action metadata is centralized in `src/sdk/cli-contracts.ts` and used by:
406
186
 
407
- Lifecycle manager command architecture:
187
+ - CLI option normalization
188
+ - help output
189
+ - completion generation
190
+ - Pi wrapper schema
191
+ - `pm contracts`
192
+ - extension command/action contract exposure
408
193
 
409
- - `src/cli/commands/extension.ts` implements `pm extension` actions (`install`, `uninstall`, `explore`, `manage`, `doctor`, `adopt`, `adopt-all`, `activate`, `deactivate`) with deterministic validation, mutually-exclusive action routing, doctor-only strict warning exit controls (`--strict-exit`, alias `--fail-on-warn`), optional doctor trace payloads (`--trace` with `--detail deep`), manage runtime parity probes (`--runtime-probe`), optional managed-state remediation (`--fix-managed-state`), and explicit extension state semantics (`active` compatibility alias + `enabled`/`runtime_active`/`activation_status`).
410
- - Install sources support local directories, GitHub HTTPS URLs, `github.com/<owner>/<repo>[/path]`, and forced shorthand via `--gh/--github`.
411
- - Scope-local managed state is persisted at `<extensions-root>/.managed-extensions.json` for deterministic source metadata, install/update timestamps, and update-check status.
412
- - `--manage` executes GitHub remote checks (`git ls-remote`) for managed GitHub entries, updates managed-state metadata, and emits deterministic per-extension `update_check_status`/`update_check_reason` fields plus `details.triage` status totals/remediation hints. With `--runtime-probe`, manage performs doctor-like runtime activation probes and annotates runtime probe execution metadata.
413
- - `--adopt-all` bulk-adopts unmanaged scope extensions into managed-state metadata without reinstalling files.
414
- - Health diagnostics include managed extension summaries/warnings for both project and global extension roots and a condensed `details.triage` surface for load/activation/migration triage, including update-coverage parity warning codes (`extension_update_health_partial_coverage`) when unmanaged extensions are action-required, capability guidance metadata, and machine-readable capability contract metadata for unknown manifest capabilities.
194
+ Use runtime contracts instead of duplicating flag lists:
415
195
 
416
- Extension Host V2 adds three additional override planes:
196
+ ```bash
197
+ pm contracts --json
198
+ pm contracts --command create --flags-only --json
199
+ pm help create --json
200
+ ```
417
201
 
418
- 1. **Parser overrides** (`registerParser`) run before command dispatch and can normalize/replace `args`, `options`, and `global` command context.
419
- 2. **Preflight overrides** (`registerPreflight`) run before mutation gates and can control whether item-format write gates, pre-mutation format sync, extension migrations, and mandatory-migration write blocking are enforced.
420
- 3. **Service overrides** (`registerService`) expose deterministic replacement points for output/error/help formatting plus internal lock/history/item-store operations.
202
+ ## Output Pipeline
421
203
 
422
- Runtime registration wiring now includes:
204
+ Core output formats:
423
205
 
424
- - `registerFlags(...)` deterministic shape validation (`long`/`short` presence plus typed metadata) before dynamic help registration.
425
- - `registerCommand({ ... })` optional metadata (`action`, `description`, `intent`, `examples`, `failure_hints`, `arguments`, `flags`) is validated and stored for runtime help/contracts introspection.
426
- - `registerItemFields(...)` defaults/validation on create and update write paths.
427
- - `registerItemTypes(...)` deterministic schema validation for required type/policy/option fields before type-registry merge.
428
- - `registerMigration(...)` mandatory migration execution + write gating in command preflight.
429
- - `registerMigration(...)` activation-time validation for typed migration metadata (`id`, `description`, `status`, `mandatory`, `run`) when provided.
430
- - `registerParser(...)` command-scoped parser override registry with deterministic last-wins behavior.
431
- - `registerPreflight(...)` preAction decision override registry for mutation gate and migration orchestration.
432
- - `registerService(...)` service override registry for output/error/help/lock/history/item-store runtime hooks.
433
- - `registerSearchProvider(...)` selected by `settings.search.provider` for live `pm search` execution.
434
- - `registerVectorStoreAdapter(...)` selected by `settings.vector_store.adapter` for live `pm search` query and `pm reindex` upsert execution.
206
+ - TOON for sparse, token-efficient default command output
207
+ - JSON for strict machine parsing
208
+ - markdown for calendar-oriented views
435
209
 
436
- See [EXTENSIONS.md](./EXTENSIONS.md) for the full API reference.
210
+ The renderer omits null, undefined, empty arrays, and empty objects from sparse TOON fallback output. JSON preserves the machine payload.
437
211
 
438
212
  ## Search Architecture
439
213
 
440
- - **Keyword mode** (always available): multi-factor lexical scoring with configurable field weights
441
- - **Semantic mode** (requires embedding + vector query capability): embedding-based vector similarity
442
- - **Hybrid mode** (default when semantic capability is available): blended lexical + semantic ranking
443
-
444
- Providers: OpenAI-compatible, Ollama
445
- Vector stores: Qdrant, LanceDB
446
-
447
- Runtime semantic defaults:
448
-
449
- - When semantic settings are otherwise unset and local Ollama is installed, search/reindex runtime resolves built-in semantic defaults (Ollama provider + local LanceDB path) so semantic-capable behavior is available out of the box.
450
- - Auto-default model resolution order: `PM_OLLAMA_MODEL` env override, then `ollama list` discovery (prefers embedding-like model names), then deterministic fallback `qwen3-embedding:0.6b`.
451
- - Explicit semantic settings always win over auto-defaults (`settings.search.provider`, `settings.vector_store.adapter`, `providers.*`, `vector_store.*`).
452
- - For implicit default-mode search, auto-default semantic execution failures degrade to keyword mode to preserve compatibility for existing users.
453
- - Auto-defaults can be disabled with `PM_DISABLE_OLLAMA_AUTO_DEFAULTS=1`.
454
-
455
- Health-time integrity and semantic/vector diagnostics:
456
-
457
- - `pm health` runs a `directories` check that separates required tracker directories from optional built-in type directories and supports `--strict-directories` for stricter warning semantics plus `--strict-exit`/`--fail-on-warn` for non-zero exit gating when warnings are present.
458
- - `pm health` runs an `integrity` check that scans item/history files for merge-conflict markers and parse/JSONL anomalies.
459
- - `pm health` now runs a `history_drift` check that compares each current item's canonical hash to the latest history `after_hash`.
460
- - `pm health` also runs a `vectorization` check that compares current item `updated_at` values to `search/vectorization-status.json`.
461
- - When stale IDs are detected and semantic runtime is available, `pm health` defaults to targeted semantic refresh for stale IDs only (not a full reindex), while `--check-only`/`--no-refresh` keep diagnostics read-only and `--refresh-vectors` makes refresh intent explicit.
462
- - `pm reindex --mode semantic|hybrid` rewrites the vectorization-status ledger for the full indexed corpus, keeping health diagnostics and index state aligned.
463
-
464
- Extension runtime can supply equivalents for both sides of semantic execution:
214
+ Search supports:
465
215
 
466
- - Search provider selection: `settings.search.provider` -> `registerSearchProvider(...)`.
467
- - Vector adapter selection: `settings.vector_store.adapter` -> `registerVectorStoreAdapter(...)`.
216
+ - keyword mode, always available
217
+ - semantic mode, when an embedding provider and vector store are available
218
+ - hybrid mode, combining keyword and semantic results
468
219
 
469
- If an extension provider/adapter fails and built-in provider/vector settings are configured, runtime falls back to built-in semantic components and records deterministic warnings.
220
+ Keyword scoring uses weighted fields such as title, description, tags, status, body, comments, notes, learnings, and dependencies.
470
221
 
471
- ### Keyword Scoring
222
+ Runtime semantic components can come from built-ins or extensions:
472
223
 
473
- Each item is scored across: `title` (8×), `description` (5×), `tags` (6×), `status` (2×), `body` (1×), `comments`/`notes`/`learnings` (1× each), `dependencies` (3×). Exact title token matches add a bonus (10×).
224
+ - provider selection: `settings.search.provider`
225
+ - vector adapter selection: `settings.vector_store.adapter`
226
+ - extension registration: `registerSearchProvider(...)` and `registerVectorStoreAdapter(...)`
474
227
 
475
- Weights are configurable via `settings.json` under `search.tuning`.
228
+ Useful commands:
476
229
 
477
- ## Configuration
478
-
479
- `settings.json` is read from the PM root at startup. Key sections:
480
-
481
- | Key | Description |
482
- |-----|-------------|
483
- | `id_prefix` | Prefix for generated IDs (default `pm-`) |
484
- | `author_default` | Default author for mutations |
485
- | `item_format` | Item storage format: `toon` (default) or `json_markdown` |
486
- | `locks.ttl_seconds` | Lock TTL (default 1800) |
487
- | `output.default_format` | `toon` or `json` |
488
- | `history.missing_stream` | Missing history-stream policy: `auto_create` (default) or `strict_error` |
489
- | `validation.sprint_release_format` | Sprint/release format policy: `warn` (default) or `strict_error` |
490
- | `validation.parent_reference` | Parent-reference policy for create/update: `warn` (default) or `strict_error` |
491
- | `testing.record_results_to_items` | Item-level test summary persistence toggle: `false` (default) / `true` |
492
- | `telemetry.enabled` | Telemetry export toggle: `true` (default) / `false` |
493
- | `telemetry.capture_level` | Runtime capture profile (`redacted` default, `max`, `minimal`) |
494
- | `telemetry.endpoint` | Remote telemetry ingestion endpoint URL |
495
- | `telemetry.installation_id` | Pseudonymous global installation identifier |
496
- | `telemetry.retention_days` | Telemetry retention window (days) used for local queue pruning during flush and remote worker cleanup |
497
- | `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` / `OTEL_EXPORTER_OTLP_ENDPOINT` (env) | Optional local OTLP trace export target for command spans |
498
- | `item_types.definitions[]` | Custom type names, aliases, folders, required fields/repeatables, `--type-option` definitions, and `command_option_policies` (`required`/`enabled`/`visible`) |
499
- | `search.*` | Search provider and tuning settings |
500
- | `providers.openai` / `providers.ollama` | Embedding provider config |
501
- | `vector_store.qdrant` / `vector_store.lancedb` | Vector store config |
502
-
503
- Precedence: CLI flags > env vars (`PM_PATH`, `PM_AUTHOR`, etc.) > `settings.json` > hard defaults.
504
-
505
- For repositories created before `item_format` existed, the first mutating item command auto-selects the current default format and runs pre-mutation item-file migration. Explicit `pm config ... item-format --format ...` selections remain supported; once selected or changed, item files are automatically migrated to the configured format, and when both `.md` and `.toon` exist for an item, the configured format is the source of truth.
230
+ ```bash
231
+ pm search "restore history" --mode keyword --limit 10
232
+ pm reindex --mode hybrid --progress
233
+ pm health --check-only
234
+ ```
506
235
 
507
- History stream policy can be configured via `pm config ... history-missing-stream-policy --policy ...`. In `auto_create`, required missing streams for existing item IDs are created before history-touching command paths continue; in `strict_error`, those command paths fail fast. Restore also supports history-only recovery when an item file is missing/deleted but the stream exists.
236
+ ## Extension Host
508
237
 
509
- Validation policies can be configured via:
238
+ Load order:
510
239
 
511
- - `pm config ... sprint-release-format-policy --policy warn|strict_error`
512
- - `pm config ... parent-reference-policy --policy warn|strict_error`
513
- - `pm config ... test-result-tracking --policy enabled|disabled`
514
- - `pm config ... telemetry-tracking --policy enabled|disabled`
515
- - `pm config ... list|export` for key discovery and one-shot resolved snapshot export
240
+ 1. core commands
241
+ 2. global extensions
242
+ 3. project extensions
516
243
 
517
- Under `warn`, create/update continue and return deterministic validation warnings; under `strict_error`, invalid values are rejected with usage errors.
244
+ Project extensions take precedence over global extensions for matching command or renderer keys. Extension dispatch is extension-first when a registered handler matches a core command path.
518
245
 
519
- ## Telemetry Pipeline
246
+ Extension override planes:
520
247
 
521
- Command lifecycle telemetry is integrated as an additive runtime path:
248
+ - commands
249
+ - parser overrides
250
+ - preflight overrides
251
+ - service overrides
252
+ - renderers
253
+ - import/export handlers
254
+ - item fields and item types
255
+ - migrations
256
+ - search providers and vector adapters
257
+ - lifecycle hooks
522
258
 
523
- - `src/cli/main.ts`
524
- - initializes first-run consent behavior
525
- - starts telemetry capture during pre-action bootstrap
526
- - finalizes telemetry with command outcome in post-action and error paths
527
- - `src/core/telemetry/consent.ts`
528
- - interactive first-run consent prompt
529
- - deterministic skip behavior for non-interactive/CI/json contexts
530
- - `src/core/telemetry/runtime.ts`
531
- - sanitizes args/options/result summaries
532
- - emits `command_start` + `command_finish` events with additive `pm_version` and `source_context` metadata
533
- - spools local JSONL queue entries under global runtime storage
534
- - exports batched events to `settings.telemetry.endpoint` with retry/backoff
535
- - optionally exports command spans to OTLP (`OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` or `OTEL_EXPORTER_OTLP_ENDPOINT`)
536
- - supports explicit source-context overrides via `PM_TELEMETRY_SOURCE_CONTEXT` (`user|automation|test|dogfood|audit_smoke`)
259
+ See [Extensions](EXTENSIONS.md) and [SDK](SDK.md).
537
260
 
538
- Design constraints:
261
+ ## Testing Architecture
539
262
 
540
- - telemetry failures never block command execution
541
- - sensitive fields are redacted before transport
542
- - pseudonymous identifiers are used for host/path metadata
543
- - source-context classification uses coarse categories only (no raw session/operator identifiers)
263
+ Tests live under:
544
264
 
545
- ## Exit Codes
265
+ ```text
266
+ tests/unit/
267
+ tests/integration/
268
+ ```
546
269
 
547
- | Code | Meaning |
548
- |------|---------|
549
- | 0 | Success |
550
- | 1 | Generic failure |
551
- | 2 | Usage / invalid args |
552
- | 3 | Not found |
553
- | 4 | Conflict (lock / ownership) |
554
- | 5 | Dependency failed (test-all) |
270
+ All tests must run with sandboxed `PM_PATH` and `PM_GLOBAL_PATH`. Use:
555
271
 
556
- ## Testing
272
+ ```bash
273
+ node scripts/run-tests.mjs test
274
+ node scripts/run-tests.mjs coverage
275
+ ```
557
276
 
558
- Tests live in `tests/`:
277
+ Linked-test execution also creates sandbox roots and can seed settings/extensions for schema parity. See [Testing](TESTING.md).
559
278
 
560
- ```
561
- tests/
562
- unit/ Unit tests (item format, lock, search, commands, extensions, etc.)
563
- integration/ Integration tests (CLI subprocess spawn, runtime/readiness coverage)
564
- ```
279
+ ## Terminal Compatibility
565
280
 
566
- All tests run in sandboxed temp directories (`PM_PATH` + `PM_GLOBAL_PATH` isolated per suite). Coverage is enforced at 100% for lines, branches, functions, and statements.
281
+ Runtime behavior should remain terminal-neutral:
567
282
 
568
- Run all tests:
283
+ - no required ANSI or custom terminal protocol
284
+ - deterministic TOON/JSON/markdown output
285
+ - graceful `process.exitCode` handling
286
+ - broken-pipe-safe output writes
287
+ - explicit TTY rejection for stdin token paths that require piped input
288
+ - non-interactive linked-test subprocess handling
569
289
 
570
- ```bash
571
- node scripts/run-tests.mjs test # sandbox-safe, tests only
572
- node scripts/run-tests.mjs coverage # sandbox-safe, with coverage gate
573
- ```
290
+ ## Public Documentation Boundary
574
291
 
575
- The `scripts/run-tests.mjs` wrapper creates a temp directory, sets `PM_PATH` and `PM_GLOBAL_PATH`, runs Vitest, then cleans up.
292
+ Architecture docs should describe source structure and public runtime behavior only. Ignored local operations material and host-specific runbooks must stay out of tracked docs.