openplanr 1.22.0 → 1.24.0

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 (40) hide show
  1. package/CHANGELOG.md +1423 -0
  2. package/dist/cli/commands/config.d.ts.map +1 -1
  3. package/dist/cli/commands/config.js +52 -0
  4. package/dist/cli/commands/config.js.map +1 -1
  5. package/dist/cli/commands/setup.d.ts.map +1 -1
  6. package/dist/cli/commands/setup.js +30 -0
  7. package/dist/cli/commands/setup.js.map +1 -1
  8. package/dist/cli/commands/upgrade.d.ts +9 -0
  9. package/dist/cli/commands/upgrade.d.ts.map +1 -0
  10. package/dist/cli/commands/upgrade.js +149 -0
  11. package/dist/cli/commands/upgrade.js.map +1 -0
  12. package/dist/cli/index.js +28 -2
  13. package/dist/cli/index.js.map +1 -1
  14. package/dist/models/schema.d.ts +12 -0
  15. package/dist/models/schema.d.ts.map +1 -1
  16. package/dist/models/schema.js +9 -0
  17. package/dist/models/schema.js.map +1 -1
  18. package/dist/models/types.d.ts +8 -0
  19. package/dist/models/types.d.ts.map +1 -1
  20. package/dist/services/claude-plugin-service.d.ts +9 -0
  21. package/dist/services/claude-plugin-service.d.ts.map +1 -1
  22. package/dist/services/claude-plugin-service.js +22 -0
  23. package/dist/services/claude-plugin-service.js.map +1 -1
  24. package/dist/services/migration-registry.d.ts +94 -0
  25. package/dist/services/migration-registry.d.ts.map +1 -0
  26. package/dist/services/migration-registry.js +106 -0
  27. package/dist/services/migration-registry.js.map +1 -0
  28. package/dist/services/runtime-manager-service.d.ts +32 -0
  29. package/dist/services/runtime-manager-service.d.ts.map +1 -1
  30. package/dist/services/runtime-manager-service.js +122 -17
  31. package/dist/services/runtime-manager-service.js.map +1 -1
  32. package/dist/services/upgrade-offer-service.d.ts +89 -0
  33. package/dist/services/upgrade-offer-service.d.ts.map +1 -0
  34. package/dist/services/upgrade-offer-service.js +256 -0
  35. package/dist/services/upgrade-offer-service.js.map +1 -0
  36. package/dist/services/upgrade-service.d.ts +156 -0
  37. package/dist/services/upgrade-service.d.ts.map +1 -0
  38. package/dist/services/upgrade-service.js +510 -0
  39. package/dist/services/upgrade-service.js.map +1 -0
  40. package/package.json +4 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,1423 @@
1
+ # Changelog
2
+
3
+ ## 1.24.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Make `planr setup` a front door that reports honestly, recovers cleanly, and remembers what you named things (SPEC-007 FR3, FR4, FR5).
8
+
9
+ **Every skip is reported.** The non-guided setup preview now prints a `Skipped:` block
10
+ naming each runtime the run dropped and why — one that requires project scope while the
11
+ run defaulted to user scope ("requires project scope"), and one that is not installed
12
+ ("not detected on PATH"). Previously this existed only in the guided wizard, so a
13
+ flag-driven install could skip a runtime silently. Detecting nothing was already a clear
14
+ error; now a partial skip is reported too.
15
+
16
+ **A partial apply is never reported as success.** At setup's one remaining partial-apply
17
+ seam, a failing Claude plugin step now restores the owned files from the backup taken
18
+ before mutating, and the error states plainly what was restored, naming every path. If
19
+ the restore itself fails, both failures surface with the backup location — the failure
20
+ during a failure is never swallowed. Proven by a forced-failure test that lets
21
+ inspection succeed so owned files are genuinely written, then fails the first mutating
22
+ command, and asserts the file is returned to its pre-setup state and the project record
23
+ cleared.
24
+
25
+ **Command names are your choice, and they persist.** `planr setup --no-prefix` installs
26
+ the workflows under bare verbs (`plan`, `ship`, `operate`, …); `--prefix` keeps the
27
+ namespaced names (`planr-plan`, …). For Codex the choice controls both the installed
28
+ skill directory and the skill's frontmatter `name:`; for Cursor it flows through the
29
+ installed rule filenames. The choice is recorded on the per-project runtime-state record
30
+ and read back on every later run, so an upgrade or a plain re-run never silently changes
31
+ what you type. The default stays namespaced and the transform is identity in that mode,
32
+ so an install that never opts in is byte-identical to before and existing installs keep
33
+ their current names — nothing is force-renamed. `planr doctor` honours the same persisted
34
+ choice: it now diagnoses the installed operate skill under the name the installer actually
35
+ wrote, so a bare install is validated on its content instead of being falsely reported
36
+ missing — which previously also caused the skill's content contract to be silently skipped.
37
+
38
+ ## 1.23.0
39
+
40
+ ### Minor Changes
41
+
42
+ - [`4353b7d`](https://github.com/openplanr/OpenPlanr/commit/4353b7d727cf5312ee684eb4dc96252ccc9f5f43) Installed-tuple reconciliation and a safe, honest upgrade path (SPEC-006).
43
+
44
+ Until now the CLI could tell you your install had drifted and then leave you to
45
+ derive the fix yourself across two package managers. `doctor` already computed
46
+ component, digest, adapter, and CLI drift correctly — nothing acted on it, and
47
+ nothing read back the compatibility ranges the ecosystem manifest already
48
+ publishes.
49
+
50
+ **Reconcile the installed tuple, not "is something newer".** A new
51
+ `planr upgrade status [--json]` reads the published compatibility manifest,
52
+ compares it against the real installed tuple — this CLI plus both host-plugin
53
+ versions — and reports `aligned`, `upgrade-available`, `incompatible`, or
54
+ `unknown`. The warn-versus-fail distinction is not re-derived: `doctor`'s inline
55
+ lock-drift classification is extracted into a single exported
56
+ `classifyComponentDrift` that both surfaces call, so a CLI merely trailing an
57
+ upgrade stays a warning while a genuinely incompatible tuple fails. Every
58
+ pre-existing `doctor` assertion passes unchanged as proof the extraction
59
+ preserved its behaviour. An absent plugin is recorded as absent, never as a
60
+ violation, so a planning-only install does not read as broken.
61
+
62
+ **Offline capability is preserved by construction.** The manifest fetch trusts a
63
+ short-TTL cache without any network round-trip, carries a hard timeout that wins
64
+ even when a fetch hangs, falls back to a stale cache when the network fails, and
65
+ reports `unknown` when there is neither — so a captive portal, a VPN, or an
66
+ airplane can never make `planr` block. Proven by offline and hung-network tests
67
+ and by a packed-install end-to-end test that reads the real installed version
68
+ rather than a fixture.
69
+
70
+ **Execute the half it owns; prescribe the half it cannot.**
71
+ `planr upgrade apply [--yes] [--json]` performs `npm install -g openplanr@<target>`
72
+ and prints the plugin commands it structurally cannot run — plugin installation is
73
+ a host command, not something a CLI can own. The prescription is rendered from the
74
+ plugin integration's own operation list, so the printed commands can never drift
75
+ from what an apply would really run, and the marketplace-refresh command is always
76
+ placed first: without it the installer reinstalls the stale version and the user
77
+ believes they upgraded. A grep gate proves the upgrade service never imports the
78
+ plugin-apply path, and an end-to-end test proves no mutating plugin command is
79
+ ever spawned.
80
+
81
+ **A partially-upgraded install can never report success.** The previously
82
+ installed version is captured as a restorable backup before any mutation, and the
83
+ on-disk version is re-read afterwards. A clean exit that did not land the target
84
+ restores the previous version automatically and states exactly what was restored
85
+ and how to retry. On success, the changelog entries strictly between the old and
86
+ new version are summarised verbatim — never inventing a change the changelog does
87
+ not carry — and `CHANGELOG.md` now ships in the package so that summary works on a
88
+ real installation rather than only in-repo.
89
+
90
+ **The offer comes to you.** An available upgrade now surfaces on an ordinary
91
+ interactive command as a four-way choice — upgrade now · always keep me current ·
92
+ not now · never ask — so nobody has to run a diagnostic to discover they are
93
+ stale; accepting resumes the command you originally invoked. "Not now" snoozes
94
+ with escalating backoff (24 hours, then 48, then a week) so it never nags.
95
+ `auto_upgrade` and `update_check` are real settings, neither inferred from a bare
96
+ invocation, and "never ask again" is a permanent opt-out that always states the
97
+ exact command reversing it. A snooze, a never-ask, or a disabled check
98
+ short-circuits before any reconcile, so a command that already declined touches no
99
+ network and adds no delay; the state file is read fail-open, and the offer never
100
+ surfaces for machine-readable or non-interactive invocations.
101
+
102
+ **Upgrades can now carry state forward.** Idempotent migrations keyed to a version
103
+ run automatically when an upgrade crosses that version, for state a reinstall
104
+ cannot repair — stale config, orphaned files, a changed on-disk layout. A strict
105
+ lower bound means a migration at or below the installed version never re-runs, and
106
+ one migration failing neither aborts the others nor is swallowed into an overall
107
+ success. The legacy operating-profile migration is registered as the proving case
108
+ by delegating to the existing implementation, reusing its exact-backup, journalled
109
+ write with rollback, and idempotency guarantees rather than forking them; the
110
+ standalone `operate profiles migrate` command keeps working unchanged. A migration
111
+ failure reports failure while still reporting the npm step's real success, so a
112
+ half-migrated install can never claim to be clean.
113
+
114
+ ## 1.22.0
115
+
116
+ ### Minor Changes
117
+
118
+ - [`5b525e2`](https://github.com/openplanr/OpenPlanr/commit/5b525e29c4843535f68a013c4d658b91ad9ed0d6) Operate durable orchestration (SPEC-005): per-role durability, honest state, and a
119
+ one-invocation review gate. Bundled pipeline dependency pinned to
120
+ `planr-pipeline@0.39.0`. Every claim below is backed by a named passing test;
121
+ coordinated sibling releases still in flight under this same version are described
122
+ as landing with the release, never as a phase this repository has already verified.
123
+
124
+ **The field fix that matters most: the advisor fan-out no longer deadlocks on a
125
+ hung lens.** The pre-driver fan-out awaited every advisor together, so one lens
126
+ stalling left the whole `Promise.all` unresolved while completed analyses sat
127
+ unrecorded and the shared lease expired underneath them. Dispatch now runs through
128
+ a deterministic lifecycle driver with bounded per-role retry, a per-attempt
129
+ timeout, and an automatic lease heartbeat that renews independently of any role
130
+ recording. A stalled non-required lens is resolved `not_evaluated` with a governed
131
+ gap while its siblings record and the cycle reaches Chair. Proven by
132
+ `tests/integration/operate-lifecycle-chair-wiring.test.ts` ("terminates a stalled
133
+ lens not_evaluated while siblings record, renews the lease, and reaches Chair") and
134
+ `tests/unit/operate-lifecycle-driver.test.ts` ("resolves a role past its retry
135
+ budget to not_evaluated with a governed gap without blocking siblings" and "renews
136
+ the lease as the window approaches without any role completing").
137
+
138
+ **Immediate per-role commit and an engine-managed heartbeat lease.** Each advisor
139
+ result is validated, recorded, persisted, and reflected in cycle progress the
140
+ moment it returns, and survives a sibling stalling; recording never waits on the
141
+ batch. Proven by the lifecycle-driver state-machine and heartbeat suites in
142
+ `tests/unit/operate-lifecycle-driver.test.ts`.
143
+
144
+ **Partial validated progress and honest status/report.** Every recorded lens is
145
+ inspectable before Chair finalizes, and a mid-cycle report renders recorded lenses
146
+ with their real analysis plus the exact recovery action for pending roles — an
147
+ active advising cycle is never described as quiet. Proven by
148
+ `tests/integration/operate-partial-report.test.ts` ("renders recorded lenses with
149
+ their real analysis and the exact recovery action for pending roles").
150
+
151
+ **Chair works with partial valid boards.** Chair consolidates the recorded,
152
+ verified board and surfaces an absent lens as an explicit gap; it never invents a
153
+ missing lens's conclusions, and it stays closed while a structurally-required role
154
+ is only `not_evaluated`. Proven by `tests/unit/operate-lifecycle-driver.test.ts`
155
+ ("holds the Chair closed while a structurally-required role is only
156
+ not_evaluated") and the chair-wiring happy-path test above ("records a five-lens
157
+ board and reaches Chair with no fabricated gap on the happy path").
158
+
159
+ **Owned scratch storage with a `doctor --fix` cleanup.** Operate scratch lives
160
+ under an OpenPlanr-owned, project-and-machine-keyed path recorded in an ownership
161
+ manifest, cleaned automatically after record/finalize, detected by `doctor` when
162
+ abandoned, and removed by the FR7-named `planr doctor --fix` — which acts only on
163
+ scratch a valid ownership manifest confirms is ours, never on an unrelated file
164
+ under the scratch tree. Proven by `tests/unit/operate-doctor-staleness.test.ts`
165
+ ("warns on abandoned owned scratch and removes only it, leaving other
166
+ machine-local caches") and `tests/unit/operate-doctor-fix-wiring.test.ts`
167
+ ("removes abandoned OpenPlanr-owned scratch and leaves an unrelated file
168
+ untouched").
169
+
170
+ **Completion discipline.** Completion requires on-disk verification of every
171
+ phase-F artifact and flips to incomplete when any is removed or abandoned owned
172
+ scratch remains. Proven by `tests/unit/operate-completion.test.ts` ("reports
173
+ complete only with every phase-F artifact, and flips when any is removed").
174
+
175
+ **Legacy operating-profile migration.** `planr operate profiles migrate
176
+ inspect|apply` detects a legacy profile, previews and converts the supported
177
+ subset, writes an exact pre-migration backup, and is idempotent — the CLI never
178
+ suggests a profile it will reject. Proven by
179
+ `tests/unit/operate-profile-migration.test.ts` ("writes an exact pre-migration
180
+ backup and rewrites the profile to the supported subset" and "is idempotent: a
181
+ second apply reports already-applied and makes no further change").
182
+
183
+ **Bundled pipeline pin.** The packed CLI carries
184
+ `optionalDependencies.planr-pipeline = 0.39.0`, asserted by
185
+ `tests/e2e/operate-packed-install.test.ts` and
186
+ `tests/e2e/operate-guided-packed-install.test.ts`.
187
+
188
+ Coordinated, not yet released with this changeset: `@openplanr/skills@1.24.0`
189
+ (thin workflow regeneration) and the marketplace ledger and real-runtime canary
190
+ land only after `planr-pipeline@0.39.0` and this `openplanr` version publish.
191
+
192
+ ## 1.21.2
193
+
194
+ ### Patch Changes
195
+
196
+ - [`2bc31c4`](https://github.com/openplanr/OpenPlanr/commit/2bc31c48c46912f542c1a52a143492d81e013e48) Align the bundled pipeline dependency with planr-pipeline 0.38.0.
197
+
198
+ ## 1.21.1
199
+
200
+ ### Patch Changes
201
+
202
+ - [`3c1101b`](https://github.com/openplanr/OpenPlanr/commit/3c1101b6699d1b7f0bdaedce3a41f37941228811) Align the bundled pipeline with planr-pipeline 0.37.2 so released Operate canaries execute correctly through the Windows command shim.
203
+
204
+ ## 1.21.0
205
+
206
+ ### Minor Changes
207
+
208
+ - [`fd81cd9`](https://github.com/openplanr/OpenPlanr/commit/fd81cd94ca4a13c3b590544b242cf7fe21078824) Rebuild `planr operate` around agent-native, runtime-bound research, six advisory roles, expressive cited reports, and approval-gated canonical proposal drafts across Claude Code, Codex, and Cursor.
209
+
210
+ ## 1.20.0
211
+
212
+ ### Minor Changes
213
+
214
+ - [`9a536c4`](https://github.com/openplanr/OpenPlanr/commit/9a536c47b36430bf0d8700d63fc11d3259b97bc7) The Operating Board harness pivot for `planr operate` (SPEC-004), the `openplanr` minor
215
+ bump 1.19.0 → 1.20.0 — the agent is the engine; the CLI harnesses, verifies, and records.
216
+ Every landed claim below is backed by a named proof; coordinated sibling work still
217
+ completing under this same version is described as landing with the release, never as a
218
+ phase this repository has already verified.
219
+
220
+ **The mandate replaces the collector as the unit of dispatch.** A per-role operating
221
+ mandate carries the lens question, declared read boundaries (workspace roots — including
222
+ the `.planr/` tree — a sensitivity ceiling, and forbidden paths), a required response
223
+ schema, and a citation requirement, and it carries no evidence bodies and no evidence
224
+ index — structurally forbidden rather than merely omitted. Proven by
225
+ `tests/unit/operate-adapter-mission-dispatch.test.ts` ("prepares a mandate (not a pack)
226
+ with declared boundaries and no evidence body ..."), whose fixture fails if any file body
227
+ ever leaks into the body-free, index-free mandate.
228
+
229
+ **Evidence is an output, not an input, and citation resolution is the universal gate.**
230
+ `adapter record` resolves every citation in a response fail-closed and mints the
231
+ evidence-of-record from what was actually cited. A fabricated path, a wrong line range, a
232
+ moved revision, or a citation above the role's sensitivity ceiling each becomes a governed
233
+ gap — on every dispatch path and every source — and a response resolving zero citations
234
+ records its role `not_evaluated` with a governed gap naming the empty grounding. Proven by
235
+ `tests/unit/operate-citation-resolution.test.ts` ("rejects a fabricated path, a wrong line
236
+ range, and a moved revision with distinct reasons and one gap each" and "commits a role
237
+ not_evaluated with a governed gap when its citations resolve zero evidence") and by the
238
+ above-ceiling refusal in `tests/unit/operate-mission-honeytoken-isolation.test.ts`
239
+ ("refuses a read above the sensitivity ceiling inside a granted root").
240
+
241
+ **Hard-blocked secrets in cited content are rejected, not redacted-and-accepted.** A
242
+ citation whose snapshot contains a hard-blocked secret category is refused as an
243
+ unresolvable citation gap instead of being persisted in redacted form. Proven by
244
+ `tests/unit/operate-citation-resolution.test.ts` ("rejects a citation into
245
+ HARD-blocked-secret content as unresolvable, never redacted-and-accepted"), with a
246
+ soft-secret assignment still redacted-and-accepted so the distinction is exercised both
247
+ ways.
248
+
249
+ **A gitignored `.planr/` tree is fully citable — by architecture.** The dispatched agent
250
+ reads the filesystem directly rather than `git ls-files`, so a project that gitignores its
251
+ `.planr/` control surface can still ground the three lenses (CPO, CMO, COO) that the
252
+ fourth field audit found unsatisfiable when candidates came only from tracked files — the
253
+ defect that starved three of six lenses is gone by construction, not by repair. Proven by
254
+ `tests/unit/operate-mission-honeytoken-isolation.test.ts` ("reads a gitignored .planr/
255
+ tree — the mission tool walks the filesystem, not git ls-files (finding 2)").
256
+
257
+ **Guided init has no livelock, no dead-end advice, and a revise path.** An answer envelope
258
+ is accepted on its binding validity (session id, questionnaire digest, project head)
259
+ rather than on wall-clock ordering, a transiently stale session un-latches when the tree
260
+ is restored, a genuinely terminal rejection names the resumable session id and its exact
261
+ `--resume` command, a previously answered question can be re-answered before apply, and the
262
+ questionnaire advertises `--answers-file` as a stdin-parity transport alternate with
263
+ per-question renderability metadata. Proven by
264
+ `tests/unit/operate-question-session.test.ts` ("accepts an answer envelope whose
265
+ submittedAt predates the session (livelock regression)" and "un-latches a transiently
266
+ stale session when the tree is restored"),
267
+ `tests/integration/operate-question-resume.test.ts` (the resume command surfaced in the
268
+ next actions), and `tests/unit/operate-question-engine.test.ts` ("advertises
269
+ --answers-file as a stdin-parity transport alternate with its exact argv" and "carries
270
+ repeated-text renderability metadata sufficient to present without improvisation").
271
+
272
+ **Completing the pivot in the same coordinated release.** Sibling work landing under this
273
+ version retires the now-dead evidence collector — its walks and budgets, role packs,
274
+ mission packets, and the `pack|mission` dispatch-mode split — behind the mandate contract;
275
+ renders cycle integrity (citation rejections, boundary refusals, `not_evaluated` roles) as
276
+ a first-class section of the readable tree and a `doctor` check; makes the persisted
277
+ `cycles/<id>/report.md` a self-contained record with complete registers; corrects the
278
+ "commit-safe root" claim to an honest, redaction-based statement; and collapses runtime
279
+ classification to mandate-capable-or-unsupported with no silent structured fallback. On the
280
+ same schedule, the CLI's own structured-provider advisor path and its `--ai` planning
281
+ surfaces are deprecated (FR4) — functional this release, pointed at the harness flow, and
282
+ scheduled for removal, never broken and never silently removed. These items land with this
283
+ release rather than ahead of it; their per-task proofs live under
284
+ `.planr/specs/SPEC-004-operate-agent-harness-architecture/`.
285
+
286
+ **Pins the optional `planr-pipeline` runtime to the exact `0.36.1`** — the build that
287
+ publishes the additive operating-mandate schema (the same additive pattern as
288
+ `create-quick-task`/`create-epic`), the regenerated mandate-flow command/skill
289
+ instructions, the registry investigation mandates, and the reclassified adapter capability
290
+ rows this release dispatches against. Verified:
291
+ `optionalDependencies["planr-pipeline"] === "0.36.1"`, the three workflow `ref: v0.36.1`
292
+ pins, and both packed-install e2e assertions.
293
+
294
+ ## Unreleased
295
+
296
+ ### Deprecations
297
+
298
+ - CLI-managed Operating Board structured-provider dispatch and the legacy
299
+ `--ai` planning surfaces remain functional in this release, but now emit one
300
+ shared deprecation notice. Agentic investigation and advisory work belongs in
301
+ the native runtime harness through Protocol v1.3 mandates. Both legacy surfaces
302
+ are scheduled for removal in OpenPlanr 2.0.0; see
303
+ https://openplanr.dev/docs/operate/agent-harness.
304
+
305
+ ## 1.19.0
306
+
307
+ ### Minor Changes
308
+
309
+ - [`acbdfed`](https://github.com/openplanr/OpenPlanr/commit/acbdfed8ab0fce13a65f7fd9c4ff58dc705c62ea) Operating Board outputs and epic-loop release for `planr operate` (SPEC-003), the
310
+ `openplanr` minor bump 1.18.0 → 1.19.0. Every claim below is backed by a named proof;
311
+ nothing describes a phase this repository has not actually reached.
312
+
313
+ Cycle reports and boards are now persisted as truthful on-disk artifacts: a single rich
314
+ assembly drives both `cycles/<id>/report.md` and every `board/<role>.md`, so `report.md`
315
+ is byte-identical to the review rendering and each evaluated board file carries its lens
316
+ recommendations with impact/confidence/ease (I/C/E) scores — proven by
317
+ `tests/unit/operate-projection-persistence.test.ts` ("renders cycles/<id>/report.md and
318
+ rich board files from the assembled lens artifacts"). The readable tree is consolidated:
319
+ the legacy `projections/` directory is retired (never written), the parked-findings
320
+ `backlog.md` is promoted to the top level, and `state.json` moves under `.state/` —
321
+ proven by `tests/integration/operate-preview-boundaries.test.ts` and the persistence
322
+ suite's asserted paths (`.planr/operate/backlog.md`, `.planr/operate/.state/state.json`,
323
+ no `projections/`).
324
+
325
+ Evidence loss is never silent. A capped repository walk names the last path it reached
326
+ and the top-level directories it never scanned, mission-index drops are counted and
327
+ surfaced as cycle warnings, sensitivity narrowing is scoped to the offending items, and a
328
+ starved role is gated not-ready with a governed data gap while every ready role still
329
+ dispatches — proven by `tests/integration/operate-evidence-recovery.test.ts` ("gates a
330
+ starved repository role with a governed gap while other roles still dispatch (FR2)").
331
+ Collection is prioritized and fair: per-top-level-directory round-robin plus git-recency
332
+ ordering, with split repository/planr file budgets replacing the shared `maxFiles`
333
+ counter — proven by `tests/integration/operate-evidence-monorepo-fairness.test.ts`
334
+ ("samples every product top-level directory under a cap the tree exceeds combined" and its
335
+ deterministic re-selection check).
336
+
337
+ Mission budgets are sized for real repositories: the derived mission-budget clamp ceiling
338
+ rises from 9 to 32 KiB against real index-item costs, per-role `maxEvidenceItems` caps are
339
+ enforced, and an oversized index is truncated to fit with the drop reported as a cycle
340
+ warning — never a silent drop and never an unexplained fail-closed on a healthy repo —
341
+ proven by `tests/unit/operate-mission-packet.test.ts` ("truncates a monorepo-scale index
342
+ to the cap, fits the budget, and reports the drop (FR4)" and "leaves a healthy repository
343
+ under its cap untouched — no warning, no fail-closed (FR4)"), with the field-scale pack
344
+ path still failing closed with no provider invocation in
345
+ `tests/unit/operate-advisor-pack-scale.test.ts`.
346
+
347
+ Re-initialization preserves machine-local preferences: a no-flag re-init carries
348
+ `dispatchModeOverrides`, `adapterLeaseDurationMs`, and `lastRunAt` forward, and the init
349
+ preview names exactly which preference a re-init will change — proven by
350
+ `tests/unit/operate-initialization-replay.test.ts` ("carries dispatchModeOverrides,
351
+ adapterLeaseDurationMs, and lastRunAt forward on a re-init with no flags (field repro)")
352
+ and `tests/integration/operate-guided-init.test.ts` ("names exactly which machine-local
353
+ preferences a re-init will change in the preview").
354
+
355
+ The epic loop closes: the report groups related accepted findings into a ready-to-run
356
+ `planr epic create --title …` suggestion naming the member findings, and the `create-epic`
357
+ route applies a real `.planr/epics/EPIC-NNN-<slug>.md` artifact through the write-ahead
358
+ journal with byte-exact rollback while never invoking PLAN or SHIP (R1 intact) — proven by
359
+ `tests/integration/operate-decision-brief-render.test.ts` ("renders one planr epic create
360
+ suggestion naming both accepted findings") and `tests/integration/operate-route-lanes.test.ts`
361
+ ("elects, applies, and byte-exact rolls back a grouped-finding epic without ever invoking
362
+ PLAN or SHIP").
363
+
364
+ Pins the optional `planr-pipeline` runtime to the exact `0.35.0` — the build that ships the
365
+ FR4 packet-enforcement half, the additive FR8 `create-epic` operating-route-plan schema,
366
+ the reviewed registry role budgets, and the regenerated operate assets this release proves
367
+ against (`optionalDependencies["planr-pipeline"] === "0.35.0"`, mirrored by the three
368
+ workflow `ref: v0.35.0` pins and both packed-install e2e assertions).
369
+
370
+ ## 1.18.0
371
+
372
+ ### Minor Changes
373
+
374
+ - [`0bd9c2a`](https://github.com/openplanr/OpenPlanr/commit/0bd9c2a8859631085c121bcd819e6cf45a4c33d1) Field-fix release for the `planr operate` Operating Board (SPEC-002), hardening the
375
+ Protocol v1.3 agentic engine against issues found once real field incidents drove the
376
+ board. Native mission dispatch is now wired end to end: a bound role prepares a mission
377
+ packet (not a v1.2 pack) and hands back a v1.3 mission record action on a claude-code
378
+ runtime, threading v1.3 citation-bearing responses through the recorded-proposal gate,
379
+ while codex/cursor fail closed to the pack path — proven by
380
+ `tests/unit/operate-adapter-mission-dispatch.test.ts` ("native mission dispatch reaches
381
+ the record action"). Advisor pack budgets now fail closed at field-incident scale:
382
+ `createOperatingAdvisorPack` throws before returning a field-scale pack, and both the
383
+ dispatch and adapter-lifecycle prepare call sites refuse with no provider invocation and
384
+ persist no session, with checkpoints holding at 10,000 events. The human review renderer
385
+ presents the write-free `review` stage — question, evidence, options, and blockers —
386
+ before any initialization is applied. Guided continuations return `ok: true` and hand the
387
+ runner a directly executable `confirmArgv` on a digest-confirmable action. Adapter sessions
388
+ bind to board identity so a re-inited board never collides with a prior generation, and
389
+ `doctor` gains two staleness diagnostics (FR11): a stale adapter session bound to a
390
+ superseded board generation and a stale incremental baseline whose `workspaceDigest`
391
+ drifted, each with a scoped fix. Provider bootstrap failures surface as typed
392
+ `E_OPERATE_ADVISOR_FAILED` errors with a remedy, the readiness preflight names a missing
393
+ provider key before a cycle starts, and runtime detection resolves the real host from env
394
+ markers instead of stamping `unknown`/`none`. The init questionnaire is on a diet with
395
+ preselection (only unanswered canonical questions are returned; the decision owner is
396
+ suggested from the git user) and accepts `--answers-file` as a bounded stdin-parity alias
397
+ under the same 64 KiB cap. Adapter leases surface their expiry and remaining time in prepare
398
+ output and the handoff (default 15 minutes), refresh on each successful record, and honor a
399
+ machine-local configured lease duration. Pins the optional `planr-pipeline` runtime to
400
+ `0.34.0`, the build that ships the regenerated v1.3 templates this release proves against.
401
+
402
+ ## 1.17.0
403
+
404
+ ### Minor Changes
405
+
406
+ - [`5e2fac8`](https://github.com/openplanr/OpenPlanr/commit/5e2fac89bd61d4095acb421fa26b987113573c65) Advance `planr operate` to the Protocol v1.3 agentic engine (OPERATE-SPEC-004):
407
+ automatic, lossless `.state/` layout migration that is journal-driven
408
+ (crash-safe) and byte-exactly reversible; a live evidence index with
409
+ digest-bound mission packets; bounded, read-only native dispatch guarded by a
410
+ mission honeytoken refusal suite and per-role `pack`/`mission` dispatch-mode
411
+ overrides; citation resolution as the audit mechanism, fail-closed and reporting
412
+ a distinct dirty-working-tree outcome; quick-task routing; self-contained
413
+ offline decision briefs that fail closed on any non-local reference; cadence
414
+ status that only reports and never requests an action; a skill-first operate
415
+ cycle; and v1.3 doctor checks. Pins the optional `planr-pipeline` runtime to
416
+ 0.33.1, the build that ships the `schemas/v1.3.0` mission-packet surface.
417
+
418
+ ## 1.16.2
419
+
420
+ ### Patch Changes
421
+
422
+ - [`7d85669`](https://github.com/openplanr/OpenPlanr/commit/7d8566968e6e75aa7f5d2fce05157b0257498e08) Manage compatible Claude Code marketplace plugins during confirmed setup and
423
+ runtime updates, and diagnose stale versions or invalid plugin identities.
424
+
425
+ ## 1.16.1
426
+
427
+ ### Patch Changes
428
+
429
+ - [`935e43b`](https://github.com/openplanr/OpenPlanr/commit/935e43b2ca4c07b2053a728ae2f90af24a151e6d) Complete bare Planr Operate invocations through the native runtime cycle, prevent Unicode evidence truncation from corrupting state, quarantine advisor-ineligible excerpts before readiness, make cancellation retry-safe, and diagnose stale questionnaire-first runtime skills.
430
+
431
+ ## 1.16.0
432
+
433
+ ### Minor Changes
434
+
435
+ - [`e1f5127`](https://github.com/openplanr/OpenPlanr/commit/e1f5127d7250ca785723c91cdf03c2ab08a2e614) Run Operating Board cycles through bounded native runtime advisors, quarantine unsafe evidence without blocking unrelated lenses, and add actionable Markdown/JSON executive reports.
436
+
437
+ ## 1.15.1
438
+
439
+ ### Patch Changes
440
+
441
+ - [`656b673`](https://github.com/openplanr/OpenPlanr/commit/656b673f5506c49e18b5ca3759027d6150cd7c9c) Make direct Operating Board initialization previews return a self-contained, digest-bound replay command that applies without restarting the questionnaire, and route focused integration gates through their executable Vitest configuration.
442
+
443
+ ## 1.15.0
444
+
445
+ ### Minor Changes
446
+
447
+ - [`1b829e8`](https://github.com/openplanr/OpenPlanr/commit/1b829e8ccd8b025a214811ecf02cc2ac9adb1b89) Add CLI-owned guided Operating Board questionnaires, resumable typed-answer
448
+ sessions, digest-scoped actions, deterministic charter assistance, value-free
449
+ evidence recovery, runtime-native presentation contracts, and setup/doctor
450
+ diagnostics without weakening PLAN, SHIP, provider, or route authority gates.
451
+
452
+ ## 1.14.4
453
+
454
+ ### Patch Changes
455
+
456
+ - [`e4fdfb3`](https://github.com/openplanr/OpenPlanr/commit/e4fdfb3ba9c44ac7da13de9ae9fbab52836048d6) Prevent Operating Board evidence redaction from quarantining safe assignments or reprocessing its own redaction sentinels.
457
+
458
+ ## 1.14.3
459
+
460
+ ### Patch Changes
461
+
462
+ - [`e986fc0`](https://github.com/openplanr/OpenPlanr/commit/e986fc02e552f6c9741bd9117bc02a1503335953) Derive Operating Board producer provenance from the installed OpenPlanr package version instead of a copied release literal.
463
+
464
+ - [`08349b3`](https://github.com/openplanr/OpenPlanr/commit/08349b3be8aa8acdc1b5c636f279550b291a4703) Report a missing OpenPlanr configuration as the actionable advisor error instead
465
+ of an unexpected internal failure. `planr operate init` writes
466
+ `.planr/operate/config.json`, not the project-wide `.planr/config.json`, so a
467
+ project that ran only the operate initializer reached the structured adapter
468
+ with no config at all and surfaced "an unexpected internal Operating Board
469
+ error" on the primary first-run path.
470
+
471
+ ## 1.14.2
472
+
473
+ ### Patch Changes
474
+
475
+ - [`0e792eb`](https://github.com/openplanr/OpenPlanr/commit/0e792ebed92f0d7e4a424388390236bb96b0e78e) Reject secrets in native Operating Board advisor results before any commit-safe event or projection is persisted, and pin Changesets' development-only YAML parsers to patched versions.
476
+
477
+ ## 1.14.1
478
+
479
+ ### Patch Changes
480
+
481
+ - [`c0136af`](https://github.com/openplanr/OpenPlanr/commit/c0136afcadef87fe9d3795e6223fea0cb5f559f0) Point `test:operate:packed` at the config that owns the packed-install suite.
482
+ The suite moved out of the default vitest project so it could not saturate the
483
+ shared worker pool, but the script still used the default config, where the file
484
+ is now excluded — so it exited "No test files found" instead of running.
485
+
486
+ - [`5c7c05b`](https://github.com/openplanr/OpenPlanr/commit/5c7c05b5188312e461e3464e8c7c27bf5d100ff8) Stabilize the native Operating Board lifecycle under parallel CI load and close
487
+ the operating lock file safely when its initial durable write fails.
488
+
489
+ ## 1.14.0
490
+
491
+ ### Minor Changes
492
+
493
+ - [`8e95efb`](https://github.com/openplanr/OpenPlanr/commit/8e95efbfedc0e23e341de1d130ab9df558d6a9d5) Add `planr operate`, an evidence-to-decision operating control plane with safe
494
+ workspace initialization, event-sourced cycles, isolated advisory lenses,
495
+ separate finding acceptance and route application, typed outcomes, recovery,
496
+ strict JSON automation, and cross-runtime workflow support.
497
+
498
+ ## 1.13.3
499
+
500
+ ### Patch Changes
501
+
502
+ - [`a4c61dc`](https://github.com/openplanr/OpenPlanr/commit/a4c61dc2bb09527783f44ed51d3cfabce3027cc2) Bundle artifacts from their own directory by default, and report safely vendored remote assets in local review output.
503
+
504
+ ## 1.13.2
505
+
506
+ ### Patch Changes
507
+
508
+ - [`d3e9314`](https://github.com/openplanr/OpenPlanr/commit/d3e9314bd0d3655a65b645d7a63c6dae23f45972) Update the optional `planr-pipeline` runtime to 0.29.0 so `planr artifact`
509
+ uses the released minimal document review chrome with the floating comments rail.
510
+
511
+ ## 1.13.1
512
+
513
+ ### Patch Changes
514
+
515
+ - [`ace659d`](https://github.com/openplanr/OpenPlanr/commit/ace659d7afcf55834e0a6f4610881863a4947b7c) Update the bundled pipeline to 0.28.5 so document artifacts use a single outer scrollbar instead of competing iframe scrolling.
516
+
517
+ ## 1.13.0
518
+
519
+ ### Minor Changes
520
+
521
+ - [`004ca3f`](https://github.com/openplanr/OpenPlanr/commit/004ca3f16451ceb7a47dd95ae897c473587a2ec4) Allow Linear setup to configure one, several, or all accessible teams, select a default, and target configured teams per push with `--team`.
522
+
523
+ ## 1.12.4
524
+
525
+ ### Patch Changes
526
+
527
+ - [`4f6c4c5`](https://github.com/openplanr/OpenPlanr/commit/4f6c4c51c62ad93447fc0caed64d20ad11fd30c5) Update the bundled pipeline to 0.28.4 for stable live-room sharing, clearer fragment limits, visible copy confirmation, reviewer identity feedback, and keyboard comment submission.
528
+
529
+ ## 1.12.3
530
+
531
+ ### Patch Changes
532
+
533
+ - [`ed010b3`](https://github.com/openplanr/OpenPlanr/commit/ed010b35fa57c855af89432fb622d1a31f34594d) Make `planr doctor --fix` preview and safely remove stale Planr-owned design and dashboard daemon state. Missing runtimes are now informational unless the current setup selected them.
534
+
535
+ ## 1.12.2
536
+
537
+ ### Patch Changes
538
+
539
+ - [`0784dbd`](https://github.com/openplanr/OpenPlanr/commit/0784dbd1d311a46f56451188199ab12c4f080407) Decode feedback from existing encrypted live artifact review rooms whose persisted events predate the room-event version field.
540
+
541
+ ## 1.12.1
542
+
543
+ ### Patch Changes
544
+
545
+ - [`a2b22ec`](https://github.com/openplanr/OpenPlanr/commit/a2b22ec0bbeb5131b6f2a2d5f6d0a99be3558dfa) Use planr-pipeline 0.28.1 so live collaborative rooms encrypt the compressed artifact payload correctly, including rooms created from legacy artifact shares.
546
+
547
+ ## 1.12.0
548
+
549
+ ### Minor Changes
550
+
551
+ - [`60fd19c`](https://github.com/openplanr/OpenPlanr/commit/60fd19cccd15fecf3cb00c189b8719dc92ee6fcf) Make encrypted live artifact review rooms the default sharing workflow, retain
552
+ immutable snapshots behind `--snapshot`, support live-room feedback imports,
553
+ and bundle `planr-pipeline` 0.28.0.
554
+
555
+ ## 1.11.0
556
+
557
+ ### Minor Changes
558
+
559
+ - [`0c14c9b`](https://github.com/openplanr/OpenPlanr/commit/0c14c9bbe05909da130d5e0bb03aa143444a7b56) Add headless document and zoomable canvas presentations to `planr artifact`,
560
+ including `--presentation auto|document|canvas`, resolved JSON output, and the
561
+ planr-pipeline 0.27.1 compatibility update.
562
+
563
+ ## 1.10.0
564
+
565
+ ### Minor Changes
566
+
567
+ - [`4438a9a`](https://github.com/openplanr/OpenPlanr/commit/4438a9a046beeaa1a0ac9201fc24fa635c36b470) Add `planr artifact` for secure local HTML review, private fragment or encrypted short-link sharing, returned-review import, and live-session export.
568
+
569
+ ## 1.9.1
570
+
571
+ ### Patch Changes
572
+
573
+ - [`392b50c`](https://github.com/openplanr/OpenPlanr/commit/392b50c26d31d4d3bc680471e7864ec1f1d8beca) Make installation quiet and configuration explicit, add guided runtime setup with safe user-scope defaults, prevent accidental project writes outside Git or initialized OpenPlanr projects, and diagnose legacy home-directory setup files.
574
+
575
+ ## 1.9.0
576
+
577
+ ### Minor Changes
578
+
579
+ - [`05a3088`](https://github.com/openplanr/OpenPlanr/commit/05a3088ef0af8628f0a38562062192c62fbbbf66) Add the unified cross-runtime distribution flow: `planr setup`, runtime adapter
580
+ lifecycle management, pipeline routing, unified doctor diagnostics, exact
581
+ runtime locks, and append-only planning provenance. The full
582
+ `planr-pipeline` package is installed by default with `--minimal` as the
583
+ planning-only escape hatch. Codex skills and Cursor rules now come from the
584
+ shared portable registries, while migrations preserve hand-written content,
585
+ back up exact bytes, retain shared user assets safely, and support conflict-safe
586
+ rollback and removal.
587
+
588
+ ## 1.8.1
589
+
590
+ ### Patch Changes
591
+
592
+ - [`29e89e6`](https://github.com/openplanr/OpenPlanr/commit/29e89e684c915a98603a715030f71ae8c2c7dc2b) Update generated rule templates to reference **Sonnet 5** (was Sonnet 4.6) for the analysis/decomposition tier, matching planr-pipeline v0.24.10. The cursor (`planr-pipeline.mdc.hbs`, `agents/designer-agent.md`, `agents/qa-agent.md`, `agents/specification-agent.md`) and codex (`_pipeline-section.md.hbs`) rule-generator templates now render the current analysis-tier model. The DEV/codegen tier stays on Opus 4.8.
593
+
594
+ ## 1.8.0
595
+
596
+ ### Minor Changes
597
+
598
+ - Add `planr graph --json`, a read-only artifact graph export for dashboard and
599
+ ecosystem conformance. The command emits the shared OpenPlanr Protocol graph
600
+ shape `{ nodes, edges }`, namespaces spec-local story/task ids, and preserves
601
+ `contains` and `depends_on` edges from frontmatter.
602
+
603
+ ## 1.7.2
604
+
605
+ ### Patch Changes
606
+
607
+ - [`e60983c`](https://github.com/openplanr/OpenPlanr/commit/e60983c02d49106d11c61c11719788ed1aace7eb) `planr status` is now the **whole-project delivery report**. With no argument it rolls up every Spec / Backlog item / Quick Task (or the agile epic→task tree) by status — **done** · **promoted/superseded** (addressed, never counted as done or outstanding) · **outstanding** — cross-referenced with the GitHub issue/PR and Linear identifiers recorded in frontmatter, ending with a Summary and an **Outstanding work** section. New: an optional `[scope]` argument (one spec/epic/feature id or slug), `--md` (paste-ready markdown report), `--json` (machine-readable for agents/CI), and `--github` / `--linear` to live-resolve PR + issue states (offline frontmatter by default). Powered by the new `delivery-status-service` (deterministic aggregation over the existing artifact/GitHub/Linear services); the previous truncated tree view is superseded by the delivery view (`--all` still controls terminal truncation).
608
+
609
+ ## 1.7.1
610
+
611
+ ### Patch Changes
612
+
613
+ - [`1c7b70a`](https://github.com/openplanr/OpenPlanr/commit/1c7b70a6d115f43389c3477d01aa8f895e505b25) Align generated rule templates and the spec-schema reference to **Opus 4.8** (was Opus 4.7). The cursor (`planr-pipeline.mdc.hbs`, `agents/specification-agent.md`) and codex (`_pipeline-section.md.hbs`) rule-generator templates, plus `docs/reference/spec-schema.md`, now render the current DEV-tier codegen model — matching the planr-pipeline plugin v0.10.0 bump to `claude-opus-4-8[1m]`.
614
+
615
+ ## 1.7.0
616
+
617
+ ### Minor Changes
618
+
619
+ - [`2a97c04`](https://github.com/openplanr/OpenPlanr/commit/2a97c04042591e4195bb4b84a4ae3486812877ed) feat: artifact integrity + rules generator managed-block markers
620
+
621
+ ### Managed-block markers for `rules generate` (fixes AGENTS.md clobber bug)
622
+
623
+ `planr rules generate --scope pipeline` no longer overwrites the entire AGENTS.md / CLAUDE.md. Generated content is now wrapped in `<!-- ##planr-pipeline:begin## -->` / `<!-- ##planr-pipeline:end## -->` HTML comment markers. On regeneration, only the content between markers is replaced — project headers, agile content, and hand-written sections are preserved. Same treatment for `--scope agile` via `<!-- ##planr-agile:begin## -->` markers.
624
+
625
+ ### Write-time artifact validation
626
+
627
+ `updateArtifact()` now validates structural invariants before writing: frontmatter fences present, YAML parses, `id:` field unchanged, and checkbox IDs preserved. On violation, throws `ArtifactInvariantError` with the specific violation. This stops AI-driven corruption from `planr refine` / `planr revise` at the door — the file on disk is never poisoned by malformed AI output.
628
+
629
+ ### AI contract: structured deltas for `planr refine`
630
+
631
+ `planr refine` now asks the AI for structured deltas (`frontmatterChanges` + `bodyChanges`) instead of a whole-file `improvedMarkdown` blob. Our code applies deltas deterministically — the AI never holds a pen on raw bytes. Legacy `improvedMarkdown` responses are validated and rejected if they break structural invariants.
632
+
633
+ ### Migration
634
+
635
+ - First run of `planr rules generate` on an existing project wraps content in markers automatically (non-destructive).
636
+ - `planr refine` change is transparent to users (AI contract is an implementation detail).
637
+ - Files previously corrupted by refine must be manually repaired or restored via `git checkout`.
638
+
639
+ ## 1.6.0
640
+
641
+ ### Minor Changes
642
+
643
+ - [`d56c9a7`](https://github.com/openplanr/OpenPlanr/commit/d56c9a73a68a302eb0bc10aaa6a00c72630fc3ef) feat(types): widen `TaskStatus` to include `'blocked'` for v0.8.0 plugin alignment
644
+
645
+ The planr-pipeline v0.8.0 task schema enum is `['pending', 'in-progress', 'done', 'blocked']`. Prior CLI versions silently coerced `blocked` → `pending` via `asTaskStatus()`, dropping the R6-failure signal that the pipeline writes alongside `T-NNN-error-report.md`.
646
+
647
+ Changes:
648
+
649
+ - `TaskStatus` union now includes `'blocked'` (`src/models/types.ts`)
650
+ - All four `asTaskStatus()` normalizers accept and preserve `'blocked'` (linear-pull, linear-push, scope-loaders)
651
+ - `DEFAULT_LINEAR_STATE_TO_OP` adds `['blocked', 'blocked']` so a Linear "Blocked" workflow state pulls back into a blocked task file
652
+ - `buildNameToStatusMap` accepts `'blocked'` from user `linear.statusMap` overrides
653
+ - `aggregateTaskStatus()` adds top-precedence rule: any blocked child → blocked parent (escalation, not averaging)
654
+
655
+ Migration: zero-friction. Tasks that don't carry `blocked` are unaffected. The CLI no longer demotes blocked back to pending on Linear pull.
656
+
657
+ ## 1.5.2
658
+
659
+ ### Patch Changes
660
+
661
+ - [`1eec762`](https://github.com/openplanr/OpenPlanr/commit/1eec7627c6d95167644d88f884716a1537a1fb0f) Fix a leftover `OpenPlanr-pipeline-aware` phrase in the cursor master rule template that the v1.5.1 rename sed missed (mixed-case compound adjective). After upgrade, regenerated `.cursor/rules/planr-pipeline.mdc` files use `planr-pipeline-aware` consistently with the renamed plugin.
662
+
663
+ No behavioural change. Run `planr rules generate --target cursor --scope pipeline` to refresh existing projects.
664
+
665
+ ## 1.5.1
666
+
667
+ ### Patch Changes
668
+
669
+ - [`03aa928`](https://github.com/openplanr/OpenPlanr/commit/03aa9289be7e784c3cd5b904af7459f7ee185dfa) Plugin rename: `openplanr-pipeline` → `planr-pipeline`. Brand convergence on the `planr` CLI binary. The CLI's TypeScript API is unchanged — only generated artifact names + slash command identifiers.
670
+
671
+ **What changes for users:**
672
+
673
+ - Generated cursor rule filenames: `openplanr-pipeline.mdc` → `planr-pipeline.mdc` (also `-plan.mdc` and `-ship.mdc` variants)
674
+ - Claude sibling reference card: `openplanr-pipeline.md` → `planr-pipeline.md`
675
+ - Slash commands: `/openplanr-pipeline:plan` → `/planr-pipeline:plan` (same for `:ship`)
676
+
677
+ **Migration:** re-run `planr rules generate` to pick up the new files. Legacy filenames trigger a one-line cleanup hint pointing at safe-to-delete paths — never auto-deleted.
678
+
679
+ **Pairs with:** `planr-pipeline` Claude Code plugin v0.7.0 (renamed from `openplanr-pipeline` v0.6.0); `openplanr` skill v1.4.0; marketplace pin updated to v0.7.0.
680
+
681
+ ## 1.5.0
682
+
683
+ ### Minor Changes
684
+
685
+ - [`b8e018c`](https://github.com/openplanr/OpenPlanr/commit/b8e018c895907bdb9bf69052d55552e3efec0229) Multi-runtime rules: extend `planr rules generate` with a `--scope` flag for cross-runtime pipeline support.
686
+
687
+ `planr rules generate` now accepts `--scope <agile|pipeline|all>` (default: `agile` — preserves existing behaviour byte-for-byte). The new `pipeline` scope generates rule files that drive the openplanr-pipeline two-phase spec-driven flow on the chosen runtime, giving Cursor and Codex first-class parity with the Claude Code plugin.
688
+
689
+ **Cursor (`--target cursor --scope pipeline`):**
690
+
691
+ - `.cursor/rules/openplanr-pipeline.mdc` — master rule (mode detection, R1 human gate, runtime parity notes)
692
+ - `.cursor/rules/openplanr-pipeline-plan.mdc` — PO Phase orchestration (Composer subagent dispatch)
693
+ - `.cursor/rules/openplanr-pipeline-ship.mdc` — DEV Phase orchestration (parallel subagents, qa gate, snapshot, marker)
694
+ - `.cursor/rules/agents/{db,designer,specification,frontend,backend,qa,devops,doc-gen}-agent.md` — 8 role bodies vendored verbatim from `openplanr-pipeline/agents/` (frontmatter stripped; Cursor uses different permission model)
695
+
696
+ **Codex (`--target codex --scope pipeline`):**
697
+
698
+ - `AGENTS.md` extended with a `## OpenPlanr Pipeline Orchestration` section. Roles modelled as personas (Codex doesn't have separate subagent processes); R1, R2, R5, R6, R8, R9 declared at prompt level with conformance-test enforcement.
699
+
700
+ **Claude (`--target claude --scope pipeline`):**
701
+
702
+ - `CLAUDE.md` gets a conditional `## OpenPlanr Pipeline (Path A)` block under `{{#if pipelineScope}}`
703
+ - Sibling `openplanr-pipeline.md` reference card with install commands, slash command list, and cross-runtime pointer
704
+
705
+ `--scope all` produces both agile and pipeline rules side-by-side.
706
+
707
+ **Compatibility matrix and OpenPlanr Protocol v1.0.0** documented in `openplanr-pipeline/docs/protocol/` and `openplanr-pipeline/docs/compatibility-matrix.md` (pipeline plugin v0.6.0+).
708
+
709
+ **`planr init` now auto-generates pipeline rules by default.** The init flow asks "Generate openplanr-pipeline rules?" with default `Yes` — meaning a single `planr init` produces a complete, ready-to-use cross-runtime project (Cursor + Codex pipeline rules pre-installed; Claude Code skill activates the same workflow via the plugin). Opt out with `planr init --no-pipeline-rules` to preserve the previous agile-only behaviour. This closes the cross-runtime DX gap so each tool (Cursor, Codex, Claude Code) is self-sufficient after a single command — no manual `planr rules generate --scope pipeline` step required for the common case.
710
+
711
+ **Migration:** none. Existing projects can either re-run `planr init` (it auto-detects existing config and asks to overwrite) or run `planr rules generate --scope all` to add pipeline rules without touching config. `--scope agile` (the previous default for `planr rules generate`) keeps producing the existing 6 Cursor `.mdc` files, single CLAUDE.md, single AGENTS.md outputs unchanged.
712
+
713
+ ## 1.4.3
714
+
715
+ ### Patch Changes
716
+
717
+ - [`e625a3b`](https://github.com/openplanr/OpenPlanr/commit/e625a3b69c331a45806fc3ff8197b0115f14b1f0) Four improvements that close real workflow gaps in `planr linear push`, `planr linear tasklist-sync`, and the per-type `update` commands.
718
+
719
+ **Granular push scope (BL-012).** `planr linear push` adds `--no-cascade` and redefines `--push-parents` to be upward-attachment only.
720
+
721
+ - `--no-cascade` on EPIC/FEAT pushes skips descendants (stories, tasklists, linked QT/BL). No-op for leaves.
722
+ - `--push-parents` no longer drags in the parent's other children. Pushing `TASK-004 --push-parents` now creates EPIC + parent FEAT + this tasklist only — not the feature's sibling stories.
723
+
724
+ **TASK status now propagates to Linear (BL-014).** `planr linear push` resolves a workflow stateId for the merged TaskList issue using an aggregation rule across all task files under the feature: all `done` → Linear Done, any `in-progress` → Linear In Progress, mix of done+pending → In Progress, all `pending` → Linear Todo. Closes the gap where `TASK-006 status: done` locally left Linear's TaskList in Backlog.
725
+
726
+ **Bulk subtask completion (BL-015).** `planr task update`, `planr quick update`, and `planr update` add `--all-done` and `--all-pending` flags that set the frontmatter status AND flip every `N.M` task checkbox in the body in one operation. Replaces the manual `sed`-or-edit-each-box workflow when shipping a feature.
727
+
728
+ **tasklist-sync no longer skips healthy issue UUIDs (BL-016).** `planr linear tasklist-sync` previously rejected every task file whose `linearIssueId` was a UUIDv4 — the entire population of healthy task files — because a shape-based pre-screen flagged them as "looks like a workflow state UUID." Linear issue ids and workflow-state ids are both UUIDv4 and indistinguishable by shape, so the pre-screen has been removed; the existing `isLikelyLinearIssueId` check still rejects truly malformed values like `ENG42`.
729
+
730
+ Backward-compat note: scripts that relied on `--push-parents` cascading downward will see fewer entities pushed.
731
+
732
+ ## 1.4.2
733
+
734
+ ### Patch Changes
735
+
736
+ - [`45f2714`](https://github.com/openplanr/OpenPlanr/commit/45f2714c45a8148f23de32ec10c6a07b04ae30cc) Spec-driven workflow polish: clearer errors, schema reference, readiness check.
737
+
738
+ - **Friendlier `planr spec decompose` error** when AI is unavailable — surfaces two actionable paths (configure AI, or hand-author from the schema reference) instead of one terse line.
739
+ - **`planr config show` now includes a "Spec-driven readiness" section** — at-a-glance view of whether `planr spec decompose` can run given the current AI config.
740
+ - **`planr init --no-ai` prints a warning** listing the AI-dependent commands (`spec decompose`, `refine`, `backlog prioritize`) that will be unavailable, with a one-liner to re-enable later.
741
+ - **Canonical schema reference at `docs/reference/spec-schema.md`** — single source of truth for spec / story / task frontmatter, body sections, lifecycle states, and the `.pipeline-shipped` marker. To be hosted at `openplanr.dev/docs/reference/spec-schema`.
742
+ - Spec template footnote updated with concrete pipeline / CLI handoff routes.
743
+
744
+ ## 1.4.1
745
+
746
+ ### Patch Changes
747
+
748
+ - [`2e36aee`](https://github.com/openplanr/OpenPlanr/commit/2e36aeec579dcac0e212eaabdce24a578f51f9c4) Fix `planr spec shape` UX — replace `$EDITOR`-opening prompts with single-line prompts.
749
+
750
+ Previously, `planr spec shape <SPEC-id>` opened `$EDITOR` (vim by default for many users) for the Context, Business Rules, and Decomposition Notes questions. This was hostile UX — users unfamiliar with vim couldn't navigate, and a single accidental Enter on an empty buffer aborted the entire interactive flow.
751
+
752
+ **v1.4.1 changes:**
753
+
754
+ - **Question 1 (Context)** is now three single-line prompts: primary user, problem solved, expected outcome. Each is optional; provide what you can. The shape skill composes the Context section from your answers using markdown subheadings.
755
+ - **Question 3 (Business Rules)** is now a single line. Hint guides the user to edit the spec markdown file directly for longer-form rules.
756
+ - **Optional Decomposition Notes** is now a single line. Same guidance — edit file directly for longer prose.
757
+ - Functional Requirements (Q2) and Acceptance Criteria (Q4) are unchanged — they were already comma-separated lists.
758
+
759
+ Net effect: the entire shape flow now runs in the terminal with single-line prompts only. No `$EDITOR` open. No accidentally-empty-buffer aborts.
760
+
761
+ For users who genuinely want long-form prose, the recommended path is: run `planr spec shape` for quick capture, then edit `.planr/specs/SPEC-NNN-{slug}/SPEC-NNN-{slug}.md` directly in your editor of choice afterward.
762
+
763
+ Origin: surfaced by real-world testing where a user pressed Enter past the vim buffer without writing anything and lost the entire shape flow.
764
+
765
+ ## 1.4.0
766
+
767
+ ### Minor Changes
768
+
769
+ - [`00e91df`](https://github.com/openplanr/OpenPlanr/commit/00e91dfc5020826bc9c180f057082daab4ebf14f) Add spec-driven planning mode — third planning posture alongside agile + QT, designed for humans planning _for_ AI coding agents.
770
+
771
+ A new `planr spec` command namespace authors specs that decompose into User Stories and Tasks with the **same artifact contract as the [openplanr-pipeline](https://github.com/openplanr/openplanr-pipeline) Claude Code plugin** — file Create/Modify/Preserve lists, Type=UI|Tech, agent assignment, DoD with build/test commands. The two products share one schema; no conversion adapter ever.
772
+
773
+ **Subcommands shipped:**
774
+
775
+ - `planr spec init` — Activate spec-driven mode in the current project
776
+ - `planr spec create [title]` — Create a self-contained `.planr/specs/SPEC-NNN-{slug}/` directory
777
+ - `planr spec shape <id>` — Interactive 4-question SPEC authoring (Context, Functional Requirements, Business Rules, Acceptance Criteria)
778
+ - `planr spec decompose <id>` — AI-driven generation of User Stories + Tasks; matches openplanr-pipeline schema; works with all 3 AI providers (Anthropic, OpenAI, Ollama). Flags: `--force`, `--no-code-context`, `--max-stories <n>`
779
+ - `planr spec sync [id]` — Validate spec integrity (orphaned tasks, stories without tasks, missing `specId`, schema drift); auto-fixes safe issues; `--dry-run` reports without writing
780
+ - `planr spec list` — List all specs with status + decomposition counts
781
+ - `planr spec show <id>` — Print a spec + its US/Task tree
782
+ - `planr spec status [id]` — Decomposition state across one or all specs
783
+ - `planr spec destroy <id>` — `rm -rf` of a single self-contained spec directory
784
+ - `planr spec attach-design <id> --files <png>...` — Attach UI mockups for the pipeline's designer-agent
785
+ - `planr spec promote <id>` — Validate completeness, mark `ready-for-pipeline`, print the `/openplanr-pipeline:plan {slug}` handoff command
786
+
787
+ **Directory layout (per spec, self-contained):**
788
+
789
+ ```
790
+ .planr/specs/SPEC-NNN-{slug}/
791
+ ├── SPEC-NNN-{slug}.md # the spec document
792
+ ├── design/ # PNG mockups + design-spec.md (written by pipeline's designer-agent)
793
+ ├── stories/US-NNN-{slug}.md # US-NNN scoped to this spec
794
+ └── tasks/T-NNN-{slug}.md # T-NNN scoped to this spec
795
+ ```
796
+
797
+ **ID scoping:** US-NNN and T-NNN are scoped to their parent SPEC (not project-globally unique). Two specs can each have their own US-001. Disambiguate via path or via `specId` frontmatter.
798
+
799
+ **Coexistence:** purely additive — agile (epic/feature/story/task) and QT modes work unchanged. Activate spec mode per project via `planr spec init`. Modes are independent; pick the posture that fits the work.
800
+
801
+ **Decompose AI behavior:**
802
+
803
+ - Always scans the project codebase via the existing `buildCodebaseContext()` so generated tasks reference real file paths matching the user's stack
804
+ - Reads `input/tech/stack.md` (best-effort) for stack-specific hints
805
+ - Detects `ui_files` in SPEC frontmatter to drive 1-vs-2 tasks per US (per openplanr-pipeline rule R2)
806
+ - Refuses to overwrite an existing decomposition unless `--force` is passed
807
+ - Status: pending|shaping → decomposing → decomposed
808
+
809
+ **Pipeline integration:** When this CLI marks a spec `ready-for-pipeline`, the openplanr-pipeline Claude Code plugin (v0.3.0+) reads `.planr/specs/SPEC-NNN-{slug}/` directly — no conversion. See `docs/proposals/spec-driven-mode.md` for the full design proposal and BL-011 for the original strategic feedback.
810
+
811
+ ## 1.3.0
812
+
813
+ ### Minor Changes
814
+
815
+ - [`61dc183`](https://github.com/openplanr/OpenPlanr/commit/61dc183e2a1ef7397682b6d7ba871c37c82c2c7a) **`planr linear`** — full Linear.app integration for OpenPlanr (EPIC-004).
816
+
817
+ ### Subcommands
818
+
819
+ - `planr linear init` — validate a Linear PAT, pick a team, save settings.
820
+ - `planr linear push <artifactId>` — create/update Linear entities at any scope:
821
+ - `EPIC-XXX` → project + features + stories + tasklists
822
+ - `FEAT-XXX` → feature + its stories + its tasklist
823
+ - `US-XXX` → one story sub-issue
824
+ - `TASK-XXX` → one tasklist sub-issue
825
+ - `QT-XXX` → quick task in the standalone project
826
+ - `BL-XXX` → backlog item (auto-labeled) in the standalone project
827
+ - `planr linear sync` — pull workflow status + bidirectional task checkboxes.
828
+ - `planr linear tasklist-sync` — sync TASK checkbox lines with Linear issue bodies.
829
+ - `planr linear status` — local mapping table (no API calls).
830
+
831
+ ### Flags on `push`
832
+
833
+ `--dry-run`, `--update-only`, `--push-parents`, `--as <strategy>`.
834
+
835
+ ### Epic mapping strategies (chosen once, stored in `linearMappingStrategy`)
836
+
837
+ - `project` (default) — Epic = Linear Project, one-to-one.
838
+ - `milestone-of:<projectId>` — Epic becomes a `ProjectMilestone` in an existing project; descendants carry `projectMilestoneId`.
839
+ - `label-on:<projectId>` — Epic becomes a team-scoped label; descendants carry `labelIds` (merged with user-added labels, never stomped).
840
+
841
+ First-time push prompts interactively. CI consumers use `--as` or `linear.defaultEpicStrategy`.
842
+
843
+ ### Parent-chain pre-flight
844
+
845
+ Granular pushes (`FEAT-/US-/TASK-`) refuse to run when the parent chain is not yet in Linear — unless `--push-parents` is set, which cascades up. Unsupported prefixes (`ADR-/SPRINT-/checklist-`) error with a pointer to the parent epic.
846
+
847
+ ### Standalone project for `QT-` / `BL-`
848
+
849
+ Quick tasks and backlog items push as top-level issues in a user-chosen Linear project (`linear.standaloneProjectId`, set once via an interactive first-push prompt). Backlog items auto-apply a team-scoped `backlog` label for filtering.
850
+
851
+ ### Security & reliability
852
+
853
+ - Linear IDs validated before every API call — accepts UUID or `ENG-42` identifier; corrupted frontmatter falls through to create instead of 404-ing.
854
+ - Frontmatter writer preserves regex-special sequences (`$1`, `$&`, `$$`) literally — Linear values can contain them.
855
+ - SDK error fallback sanitizes raw GraphQL bodies; known error types keep their user-friendly guidance.
856
+ - Rate-limit retries honor Linear's `Retry-After` (never retry sooner than the server asked, never faster than our exponential backoff).
857
+ - Non-interactive conflict decisions audited to `.planr/reports/`.
858
+ - Three-way checkbox merge warns when a baseline looks corrupted.
859
+ - PATs stored via keychain-first credentials service, never in `config.json`.
860
+
861
+ ### Bidirectional status sync with three-way merge (fixes silent data loss)
862
+
863
+ `planr linear sync` now reconciles workflow status in **both directions** via a three-way merge:
864
+
865
+ - **Local changed, Linear unchanged** → pushes local to Linear (fixes the data-loss bug where `planr quick update --status done` followed by `planr linear sync` silently reverted local back to Linear's stale state).
866
+ - **Linear changed, local unchanged** → pulls Linear to local (existing behavior, preserved).
867
+ - **Both changed** → conflict resolved per `--on-conflict prompt|local|linear`. Interactive runs prompt per artifact; CI/non-interactive runs auto-resolve to `linear` and log the decision to `.planr/reports/linear-sync-conflicts-<date>.md`.
868
+
869
+ Baseline is stored per-artifact in new frontmatter fields `linearStatusReconciled` and `linearStatusSyncedAt`, written on every successful sync. `planr quick update --status` and `planr backlog update --status` automatically clear `linearStatusReconciled` so the next sync recognizes the local change and pushes it up.
870
+
871
+ `--on-conflict` now applies to both status and checkbox conflicts (previously checkbox-only). Applies to FEAT / US / QT / BL. TASK stays deferred (aggregate issue, needs its own aggregation rules).
872
+
873
+ ### Status sync now covers QT + BL (zero-config)
874
+
875
+ `planr linear push QT-XXX` and `planr linear push BL-XXX` now write local status to Linear's workflow state. `planr linear sync` pulls state changes back into QT and BL frontmatter alongside features and stories.
876
+
877
+ - **Zero-config:** push auto-derives the status→stateId map from Linear's canonical state types (`backlog` / `unstarted` / `started` / `completed` / `canceled`) on every run. `linear.pushStateIds` is now an optional override, not a requirement.
878
+ - Quick tasks use the task vocabulary (`pending` / `in-progress` / `done`), plus transparent aliases for Linear-native wording (`completed` / `cancelled` / `canceled` / `todo`).
879
+ - Backlog items use their own vocabulary (`open` / `closed` / `promoted`). Pull is asymmetric by design: any Linear "in flight" state maps to `open`, `Done`/`Cancelled` maps to `closed`, and local `promoted` is never overwritten (it implies a target pointer Linear can't know about).
880
+ - TASK status sync stays on the TODO list. One Linear TaskList issue aggregates many task files, so a 1:1 status mapping doesn't apply; use `planr linear tasklist-sync` for per-checkbox state.
881
+
882
+ **Fix:** Linear's API rejects `stateId: null` on update (`InvalidInput`). All push paths — feature, story, QT, BL — now omit the `stateId` field entirely when unmapped instead of sending an explicit null, so pushes without any state configuration continue to succeed.
883
+
884
+ ### `planr revise` — unchanged-content short-circuit
885
+
886
+ Revise now detects when the agent returns content that is effectively identical to the original (byte-exact, or differs only in trailing whitespace that LLM markdown serializers routinely strip). Behavior in that case:
887
+
888
+ - No file write, no backup sidecar produced, no confirm prompt.
889
+ - New audit outcome `unchanged-by-agent` (distinct from `skipped-by-agent` / `flagged`).
890
+ - UI renders "(no changes — agent's revised output matches the current file; nothing to apply)" in place of an empty diff block.
891
+
892
+ Prevents the confusing `Outcome: applied` report when the only on-disk delta was a trailing newline strip.
893
+
894
+ ### `planr linear status` — full URLs, no truncation
895
+
896
+ Reordered the table so the URL column is last and never truncated. Clickable URLs are the primary value of the table; the previous 28-char ellipsis made them useless for copy-paste.
897
+
898
+ ### Estimate sync for FEAT / US / QT / BL
899
+
900
+ `planr linear push` now writes local `estimatedPoints` (from `planr estimate --save`, or hand-edited `storyPoints`) to Linear's native Issue estimation field, snapped to the team's configured scale:
901
+
902
+ - **Fibonacci** — snap to `{0, 1, 2, 3, 5, 8, 13, 21}` (e.g. `4 → 5`, `7 → 8`).
903
+ - **Linear** — snap to `{0, 1, 2, 3, 4, 5}`.
904
+ - **Exponential** — snap to `{0, 1, 2, 4, 8, 16}`.
905
+ - **tShirt** — skipped with one-per-run warning (no reliable numeric → XS/S/M/L/XL mapping).
906
+ - **notUsed** — skipped silently.
907
+
908
+ Zero-config: the team's `issueEstimationType` is auto-detected per push run (one extra API round-trip, cached). TASK is deferred — one Linear TaskList issue aggregates multiple task files, so 1:1 estimate mapping doesn't apply.
909
+
910
+ ### Story body fixes
911
+
912
+ - **Empty role/goal/benefit no longer renders `As a \*\***, I want \***\* so that \*\***.`\*\* Suppresses the "As a" sentence entirely when any of the three fields is blank (or whitespace-only).
913
+ - **Gherkin scenarios now push to Linear.** Stories following the OpenPlanr convention store acceptance criteria as Gherkin in a sibling `<storyId>-gherkin.feature` file. Before this fix the push path never loaded the `.feature` content and Linear stories rendered empty for convention-following teams.
914
+ - **Epic project description trims whitespace-only fields** — no more empty `**Risks**` headers.
915
+
916
+ ### Linear label case + workspace-scope fix
917
+
918
+ `ensureIssueLabel` lookup is now **case-insensitive and workspace-wide** (matching Linear's own uniqueness rule). Previously a workspace with a `Feature` label blocked creation of `feature` with an `InvalidInput: Label already exists` error. Push now adopts the existing cross-team label instead of failing.
919
+
920
+ ### Revise — next-step guidance + rejected-proposal preservation
921
+
922
+ - Flagged outcomes now print actionable next steps (read the audit log, hand-edit, re-run with `--scope-to prose`, re-run with `--no-code-context`) instead of leaving users in a dead end.
923
+ - Demoted `revise → flag` decisions preserve the agent's rejected rewrite in the audit log as a `REJECTED by verifier` diff so users can inspect and hand-apply the parts that make sense. The file is still not written (action remains `flag`); the markdown is kept for audit purposes only.
924
+
925
+ ### BL → QT promote is now AI-driven
926
+
927
+ `planr backlog promote BL-XXX --quick` feeds the full BL markdown body (description, acceptance criteria, notes, threat models) through the same AI pipeline used by `planr quick create`, producing a realistic task breakdown instead of a single checkbox that restates the title. The new QT carries `sourceBacklog: "BL-XXX"` as provenance and inherits `epicId` from the BL (or an explicit `--epic` override) so `planr linear push EPIC-XXX` cascades to it. Use `--manual` to opt out of AI and keep the legacy single-task behavior.
928
+
929
+ ### Config additions
930
+
931
+ ```jsonc
932
+ {
933
+ "linear": {
934
+ "teamId": "UUID",
935
+ "teamKey": "ENG",
936
+ "defaultProjectLead": "UUID",
937
+ "pushStateIds": {
938
+ "pending": "UUID",
939
+ "in-progress": "UUID",
940
+ "done": "UUID"
941
+ },
942
+ "statusMap": { "In Review": "in-progress" },
943
+ "standaloneProjectId": "UUID",
944
+ "standaloneProjectName": "Planr",
945
+ "defaultEpicStrategy": "project"
946
+ }
947
+ }
948
+ ```
949
+
950
+ ## 1.2.8
951
+
952
+ ### Patch Changes
953
+
954
+ - [`2d9c113`](https://github.com/openplanr/OpenPlanr/commit/2d9c113627c0eae69611af7ee2adbde366c2799f) Add `planr revise` — agent-driven alignment of planning artifacts with codebase reality
955
+
956
+ New command complementing `planr refine` (prose polish) with a focus on _factual_ alignment:
957
+
958
+ - `planr revise <ID>` — revise a single artifact (epic / feature / story / task)
959
+ - `planr revise <ID> --cascade` — top-down revision of an artifact and its descendants (epic → features → stories → tasks); children see the _revised_ parent in their context
960
+ - `planr revise --all` — revise every epic in the project, with a content-hash cache that skips unchanged artifacts
961
+ - `--dry-run`, `--yes`, `--allow-dirty`, `--scope-to prose|references|paths|all`, `--no-code-context`, `--no-sibling-context`, `--audit-format md|json`, `--max-writes-per-run`
962
+
963
+ Four-layer safety pipeline (every run):
964
+
965
+ 1. **Clean-tree gate** — refuses to run on a dirty git working tree (override with `--allow-dirty`)
966
+ 2. **Evidence verification** — every AI citation uses a typed kind (`file_exists`, `file_absent`, `grep_match`, `sibling_artifact`, `source_quote`, `pattern_rule`); unverifiable citations are dropped. When a majority of evidence fails to verify, the decision is demoted from `revise` to `flag` so a human reviews instead of silently applying
967
+ 3. **Diff preview + confirmation** — per-artifact menu: `[a]pply / [s]kip / [e]dit rationale / [d]iff again / [q]uit`; `--yes` still requires typed "YES" at start in an interactive TTY, skipped in non-TTY (CI) environments
968
+ 4. **Post-flight graph-integrity check + git rollback** — after writes, `syncParentChildLinks` runs; if any cross-reference broke, affected artifact paths are restored via `git checkout`. This is the only v1 mechanism allowed to use the word "rollback"; atomic writes are called atomicity
969
+
970
+ Template-conformance guardrail:
971
+
972
+ - Revise is taught the canonical `## Section` set for each artifact type (from the Handlebars templates) and instructed to flag rather than add sections outside it. Prevents task-level conventions like `## Relevant Files` from leaking into epics
973
+ - Existing user-maintained custom sections are preserved byte-for-byte
974
+
975
+ Other safety properties:
976
+
977
+ - **Atomic writes** with sidecar backups (`.planr/reports/revise-<scope>-<date>/backup/`) — no partial files ever on disk
978
+ - **Facts win from code, plan wins on intent** — concrete paths and symbols are rewritten to match the repo; what the feature is _supposed to do_ is never rewritten (intent conflicts surface as `flag` with ambiguous entries)
979
+ - **Graceful mid-cascade interrupt** — Ctrl+C and `[q]uit` let any in-flight atomic write complete, stop cleanly, and flush the audit log immediately; already-applied artifacts stay applied
980
+ - **SIGINT closes the audit log cleanly** with an `interrupted: sigint` footer, so Ctrl+C at the confirmation prompt doesn't leave a half-written log
981
+
982
+ Every run emits a Markdown or JSON audit log under `.planr/reports/` capturing applied / skipped / flagged / failed artifacts with rationale, evidence, ambiguities, and unified diffs — dry-run included.
983
+
984
+ After a successful apply, revise prints:
985
+
986
+ ```
987
+ git commit -am "chore(plan): revise <SCOPE> against codebase"
988
+ ```
989
+
990
+ See the [README section on `planr revise`](https://github.com/openplanr/OpenPlanr/blob/main/README.md#planr-revise--align-planning-with-reality) for workflow examples.
991
+
992
+ ## 1.2.7
993
+
994
+ ### Patch Changes
995
+
996
+ - [`57d07b3`](https://github.com/openplanr/OpenPlanr/commit/57d07b324cd34bc8461d09ae3fc2225dc5da610f) Add stakeholder reporting & PM intelligence layer
997
+
998
+ New commands:
999
+
1000
+ - `planr report <type>` — generate `sprint`, `weekly`, `executive`, `standup`, `retro`, or `release` reports from `.planr/` artifacts and (optionally) recent GitHub commits/PRs, written as Markdown + HTML under `.planr/reports/`
1001
+ - `planr report-linter [file]` — validate stakeholder markdown against configurable rules (vague language, evidence density, required sections per report type) with coaching hints
1002
+ - `planr context` — emit the report context pack (artifacts + sprint state + GitHub signals + flat evidence index) as JSON for piping
1003
+ - `planr voice standup` — convert a transcript file or stdin into a structured Yesterday / Today / Blockers standup, with optional `--lint`, `--edit`, `--reload-file`, and `--append-story`
1004
+ - `planr story standup --story <ID>` — append linted standup notes onto an existing user story
1005
+
1006
+ Reporting features:
1007
+
1008
+ - `--lint` and `--strict-evidence` quality gates so vague or unsupported claims do not ship
1009
+ - `--push slack` via [Incoming Webhooks](https://api.slack.com/messaging/webhooks) (`distribution.slackWebhookUrl` in `.planr/config.json`); `--dry-run` works without a webhook configured
1010
+ - `--push github` archives the report as a `planr:report` GitHub issue via the local `gh` CLI
1011
+ - Optional org branding and extra sections via the `reports` block in config; optional rule overrides via the `reportLinter` block
1012
+
1013
+ Out of scope for this release (deferred):
1014
+
1015
+ - Bundled PDF rendering (`--format pdf` exits with a clear "not in this build" message)
1016
+ - SMTP email delivery (the email path is a documented stub)
1017
+ - Live microphone capture and bundled speech-to-text — pair `planr voice standup` with any STT or OS dictation tool
1018
+ - Per-segment audio replay, Slack OAuth / multi-channel routing, native git-tree report commits, persistent cross-session coaching history
1019
+
1020
+ See [docs/EPIC-PM-REPORTING-LAYER.md](https://github.com/openplanr/OpenPlanr/blob/main/docs/EPIC-PM-REPORTING-LAYER.md) for the design and shipped-vs-deferred matrix.
1021
+
1022
+ ## 1.2.6
1023
+
1024
+ ### Patch Changes
1025
+
1026
+ - [`4cf5bcc`](https://github.com/openplanr/OpenPlanr/commit/4cf5bcc5e6e4f56bb0d59cda9cb9ba7f57115277) Replace gray-matter with yaml package to eliminate eval() vulnerability
1027
+
1028
+ - Remove gray-matter dependency (+ 6 transitive deps including js-yaml with eval)
1029
+ - Add yaml package (zero deps, YAML 1.2 spec, no eval, maintained by YAML spec editors)
1030
+ - Custom frontmatter parse/stringify in ~15 lines with robust regex handling
1031
+
1032
+ ## 1.2.5
1033
+
1034
+ ### Patch Changes
1035
+
1036
+ - [`97e34be`](https://github.com/openplanr/OpenPlanr/commit/97e34bee794585c50d6ba774d1ba0b586a130030) Add artifact update commands and GitHub issue type auto-assignment
1037
+
1038
+ - Add `planr update <ids...>` top-level command with batch support, status validation, and `--force` override
1039
+ - Add `update` subcommand to all artifact types: epic, feature, story, task, quick, backlog
1040
+ - Supported fields: `--status` (all types), `--owner` (epic/feature), `--priority` (backlog)
1041
+ - Auto-set GitHub issue types (Task, Feature) via GraphQL when pushing with `planr github push`
1042
+ - Extract shared `updateArtifactFields()` using regex-based replacement to preserve file formatting
1043
+ - Harden environment variable access with explicit allowlist in credentials-service
1044
+
1045
+ ## 1.2.4
1046
+
1047
+ ### Patch Changes
1048
+
1049
+ - [`64a0f80`](https://github.com/openplanr/OpenPlanr/commit/64a0f80fda6d6d44faff957d7064a55d6833682c) Code quality and performance improvements
1050
+
1051
+ - Faster sprint and sync commands via parallelized artifact loading
1052
+ - Consistent error messages across all AI-powered commands
1053
+ - Shared formatting utilities to reduce internal code duplication
1054
+ - JSDoc documentation added to all core service functions
1055
+
1056
+ ## 1.2.3
1057
+
1058
+ ### Patch Changes
1059
+
1060
+ - [`5551aea`](https://github.com/openplanr/OpenPlanr/commit/5551aea8113ae17af67306219c9eb22bd5405667) Add prompt injection protection with input boundary delimiters and file size validation for --file arguments
1061
+
1062
+ ## 1.2.2
1063
+
1064
+ - [`45836f9`](https://github.com/openplanr/OpenPlanr/commit/45836f99ad88605ba4aac5fab4f318b20badf5b0) Reduce AI over-engineering in plan generation with scope discipline rules, count guidance per artifact level, and anti-enumeration batching ([#62](https://github.com/openplanr/OpenPlanr/pull/62))
1065
+
1066
+ ## 1.2.1
1067
+
1068
+ - [`696da73`](https://github.com/openplanr/OpenPlanr/commit/696da735d7cdb88c3d11022233d2b17bb274ca02) Fix project root resolution for monorepos — planr now walks up the directory tree to find `.planr/config.json`, so commands work from any subdirectory ([#55](https://github.com/openplanr/OpenPlanr/pull/55))
1069
+
1070
+ ## 1.2.0
1071
+
1072
+ - [`3f47e3c`](https://github.com/openplanr/OpenPlanr/commit/3f47e3c7524cd54827cc4e63830de4bacb9f2df6) Add agent-friendly non-interactive mode and API key UX improvements
1073
+ - Add `--yes`/`-y` flag for fully unattended planning workflows (Claude Code, Cursor, Codex)
1074
+ - Auto-detect non-interactive terminals via TTY detection
1075
+ - All prompts return sensible defaults when non-interactive
1076
+ - Add `planr config remove-key` command to delete stored API keys
1077
+ - Show clear multi-line guidance when API key is not configured
1078
+ - Detect existing API keys (env var, OS keychain, encrypted file) during init
1079
+ - Replace magic numbers with named CHECKLIST constants
1080
+ - Fix TOCTOU race condition in checklist reads
1081
+
1082
+ All notable changes to this project will be documented in this file.
1083
+
1084
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
1085
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1086
+
1087
+ ## [1.1.0] - 2026-04-06
1088
+
1089
+ ### Added
1090
+
1091
+ - **`.planr/` directory** — all config and planning artifacts now live under `.planr/` instead of polluting the project root with `planr.config.json` and `docs/agile/`. IDE-required files (`CLAUDE.md`, `AGENTS.md`, `.cursor/rules/`) remain at their mandated locations
1092
+ - **Auto-generate AI agent rules on `planr init`** — creates `CLAUDE.md`, `AGENTS.md`, and `.cursor/rules/` immediately so users get working agent rules without a separate `planr rules generate` step
1093
+ - **`planr checklist toggle 1 3 5`** — direct argument support alongside interactive mode, with validation of item indices
1094
+ - **Auto-check checklist items** — `checkItem()` automatically marks checklist items as done when relevant commands complete (epic→1, feature→2, story→3, task→10)
1095
+
1096
+ ### Changed
1097
+
1098
+ - **Config path** — `planr.config.json` → `.planr/config.json`
1099
+ - **Artifact root** — `docs/agile/` → `.planr/`
1100
+ - **Cursor rule templates** — renamed from numeric prefixes (`2000-agile-checklist.mdc`) to clean descriptive names (`agile-checklist.mdc`) to avoid colliding with user's existing rule files
1101
+
1102
+ ### Fixed
1103
+
1104
+ - **Broken checklist paths** — `{{agilePath}}` template variable was missing from `createChecklist()` template data, producing broken file references
1105
+ - **Checklist toggle reporting** — direct-args mode now validates indices against actual checklist items and reports accurate update counts
1106
+
1107
+ ### Breaking Changes
1108
+
1109
+ - Existing v1.0.x projects need to re-run `planr init`
1110
+
1111
+ ## [1.0.0] - 2026-04-05
1112
+
1113
+ ### Added
1114
+
1115
+ - **`planr backlog`** — capture, prioritize, and promote work items from a lightweight backlog
1116
+ - `planr backlog add` — capture ideas with priority and tags without breaking your flow
1117
+ - `planr backlog list` — filter by tag, priority, or status; sorted by priority
1118
+ - `planr backlog prioritize` — AI scores items by impact/effort and reorders them
1119
+ - `planr backlog promote` — promote to quick task (`--quick`) or story (`--story --feature`)
1120
+ - `planr backlog close` — archive completed or irrelevant items
1121
+ - **`planr sprint`** — time-boxed iterations with velocity tracking
1122
+ - `planr sprint create` — create a sprint with name and duration (1–4 weeks); enforces one-active-at-a-time
1123
+ - `planr sprint add` — assign tasks manually or with `--auto` AI selection based on priority and velocity
1124
+ - `planr sprint status` — progress dashboard with per-task completion, progress bars, and days remaining
1125
+ - `planr sprint close` — archive sprint, list incomplete tasks, optional retrospective
1126
+ - `planr sprint list` — all sprints with status badges and task counts
1127
+ - `planr sprint history` — velocity chart with bar visualization across closed sprints
1128
+ - **`planr template`** — reusable task templates for common development workflows
1129
+ - `planr template list` — list built-in and custom templates with task counts
1130
+ - `planr template show` — preview template contents and variables
1131
+ - `planr template use` — generate task list from a template with variable substitution
1132
+ - `planr template save` — save an existing task list as a reusable custom template
1133
+ - `planr template delete` — remove a custom template
1134
+ - **5 built-in task templates** — `rest-endpoint`, `react-component`, `database-migration`, `api-integration`, `auth-flow`
1135
+ - **User-defined AI rules** — `.planr/rules.md` injected into AI prompts as mandatory project rules
1136
+ - **Auto-extracted pattern rules** — 5 heuristic detectors (generic CRUD, command registration, central types, ID generation, template rendering) produce explicit rules from architecture files
1137
+ - **Post-generation validation** — warns about modify-on-missing, create-on-existing, dependency gaps, and unknown directories before user accepts AI output
1138
+ - **Dependency chain detection** — import-based file dependency hints injected into AI context
1139
+ - **`display` utility** — 13 methods for formatted user-facing output (tables, progress bars, key-value pairs, status badges)
1140
+ - **`ArtifactFrontmatter` type** — shared typed interface for artifact frontmatter across all parsers
1141
+ - **Shared task-creation helpers** — extracted `buildTaskItems`, `displayTaskPreview`, `displayValidationWarnings`, and related helpers into reusable module
1142
+ - **ESM `exports` field** — `package.json` now declares explicit ESM entry point
1143
+ - **Dynamic CLI version** — `planr --version` reads version from `package.json` at runtime instead of hardcoding
1144
+
1145
+ ### Changed
1146
+
1147
+ - **Version** — bumped to 1.0.0
1148
+ - **Package description** — updated to reflect full planning platform: backlog, sprints, task templates, estimation, GitHub sync, and AI agent rules
1149
+ - **README** — complete rewrite with expanded feature list, backlog/sprint/template quick start, and organized command tables
1150
+ - **CLI.md** — added backlog, sprint, template, and quick task command sections; updated ID convention table, config example, workflow diagram
1151
+ - **`planr status`** — now shows backlog items with priority badges and active sprint with days remaining
1152
+ - **`planr search`** — now searches backlog and sprint artifacts
1153
+ - **Codebase context builder** — dynamic `src/` subdirectory discovery instead of hardcoded directory list; pattern rules and dependency hints injected into AI prompts
1154
+ - **Rules templates rewritten** — Cursor, Claude Code, and Codex templates replaced with 4-step context-gathering protocol (read task → walk parent chain → read ADRs → scan codebase)
1155
+ - **Sprint task entries** — now include task title and relative file link (`- [ ] **TASK-001** title — [view](...)`)
1156
+ - **Sprint auto-select** — sends subtask counts and parent feature context to AI for smarter velocity-aware selection
1157
+ - **Bare catch blocks eliminated** — 39 bare `catch {}` blocks converted to `catch (err) { logger.debug(..., err) }` for `--verbose` debuggability
1158
+ - **Strict Biome rules** — enabled `noExplicitAny`, `noNonNullAssertion`, `noConsole` as errors
1159
+ - **`@anthropic-ai/sdk`** — bumped from 0.80.0 to 0.81.0
1160
+
1161
+ ### Removed
1162
+
1163
+ - **`planr task implement` and `planr quick implement`** — coding agents (Claude Code, Cursor, Codex) handle implementation directly via generated rules
1164
+ - **`planr task fix` and `planr quick fix`** — replaced by iterative agent workflows
1165
+ - **8 agent adapter files** (~1,150 lines) — `agent-factory`, `claude-agent`, `codex-agent`, `cursor-agent`, `implementation-bridge`, `progress`, `prompt-composer`, `types`
1166
+ - **Orphaned retry utilities** — dead `MAX_RETRIES`, `isRetryableError`, `sleep` removed after agent deletion
1167
+ - **Duplicate `CodingAgentName` type** — consolidated to single definition in `models/types.ts`
1168
+
1169
+ ### Fixed
1170
+
1171
+ - **Hardcoded source inventory directories** — replaced 7-directory list with dynamic `readdir` discovery that expands into leaf directories
1172
+ - **Source inventory listing directories as files** — uses `readdir` with `withFileTypes` and `.isFile()` filter
1173
+ - **`countInventoryMatches` counting lines** — now parses comma-separated file names per inventory line
1174
+ - **Dependency chain warning wording** — "modified but" changed to "referenced but" for accuracy
1175
+ - **`displayValidationWarnings` loose typing** — `action?: string` replaced with `action: 'modify' | 'create'`
1176
+ - **`--file` flag error handling** — stack trace on bad file path replaced with user-friendly error message in quick.ts and epic.ts
1177
+ - **Rules reader empty vs missing** — `!content` replaced with explicit `content === null` check
1178
+ - **Slugify `ENAMETOOLONG` crash** — filenames truncated at 80 chars with word-boundary trimming
1179
+ - **Backlog title triplication** — title no longer repeated three times in generated backlog items
1180
+ - **Task parser bold ID regex** — fixed regex that caused empty template saves when IDs were bold-formatted
1181
+ - **Sprint "untitled" filename** — sprint creation now uses sprint name for slug instead of falling back to "untitled"
1182
+ - **Plan summary overcounting** — reports only artifacts created in current run; task generation failures no longer miscounted
1183
+ - **`truncateTitle` empty input** — guards against empty description producing empty artifact titles
1184
+ - **`progressBar` percent clamping** — clamps to [0,100] to prevent `String.repeat()` with negative count
1185
+ - **`logger.debug` Error formatting** — formats Error instances with stack traces instead of `[object Object]`
1186
+ - **Safer Map access patterns** — guarded `Map.get()` returns in sync and dependency-chains to prevent silent no-ops
1187
+
1188
+ ### Developer Experience
1189
+
1190
+ - **47 new tests** — display utility (22), task-creation helpers (21), E2E smoke (4), edge cases
1191
+ - **Coverage thresholds raised** — from 3% to 14% (lines, functions, branches, statements)
1192
+ - **`display.*` / `logger.*` separation** — formatted user-facing output vs operational messages
1193
+
1194
+ ## [0.9.0] - 2026-04-01
1195
+
1196
+ ### Added
1197
+
1198
+ - **`planr github push`** — push planning artifacts to GitHub Issues. Supports single artifact (`planr github push EPIC-001`), all artifacts under an epic (`--epic EPIC-001`), or everything (`--all`). Creates labeled issues with type-aware formatting, metadata tables, and collapsible artifact sources. Stores the GitHub issue number in artifact frontmatter for bi-directional linking
1199
+ - **`planr github sync`** — bi-directional status sync between local artifacts and GitHub Issues. Supports `--direction pull` (GitHub→local), `push` (local→GitHub), or `both` (interactive conflict resolution). Detects open/closed state changes and maps them to artifact status fields
1200
+ - **`planr github status`** — show sync status of all linked artifacts (local status vs GitHub issue state)
1201
+ - **`planr export`** — generate consolidated planning reports in markdown (`--format markdown`), JSON (`--format json`), or HTML (`--format html`). Supports epic scoping (`--scope EPIC-001`) and custom output path (`--output ./reports`). HTML reports are self-contained with collapsible sections, status badges, and inline CSS
1202
+ - **`planr epic create --file <path>`** — read epic description from a file (e.g., a PRD or requirements document) instead of single-line input. Supports multi-line documents of any size
1203
+ - **Type-aware GitHub issue formatting** — different body builders for task, epic, feature, and story artifacts with metadata tables, section reordering, and collapsible details
1204
+ - **Temp file body delivery** — uses `--body-file` for GitHub issue creation/update to avoid OS argument length limits on large artifacts
1205
+ - **Graceful deleted issue handling** — when a linked GitHub issue has been deleted, falls back to creating a new one instead of failing
1206
+ - **HTML export template** — self-contained Handlebars template with collapsible `<details>` sections, color-coded status badges, and full hierarchy rendering
1207
+
1208
+ ### Changed
1209
+
1210
+ - **Epic prompt framing** — `buildEpicPrompt()` detects detailed input (>5 lines) and uses document extraction framing instead of "brief description" framing, so AI faithfully processes large PRDs
1211
+ - **Epic system prompt** — updated to explicitly handle detailed PRD input: "extract and incorporate ALL sections — do not summarize or ignore content"
1212
+ - **Epic token budget** — increased from 4096 to 8192 to support richer output from detailed PRD input
1213
+
1214
+ ## [0.8.0] - 2026-03-31
1215
+
1216
+ ### Added
1217
+
1218
+ - **`planr estimate <id>`** — AI-powered effort estimation for any artifact (task, story, feature, epic, quick). Returns story points (Fibonacci 1-21), estimated hours, complexity, risk factors, and reasoning
1219
+ - **`planr estimate --epic <id>`** — Estimates all tasks under an epic and produces a rollup table with total points and hours
1220
+ - **`planr estimate --calibrate`** — Accuracy report from past estimates on completed artifacts
1221
+ - **`planr estimate --save`** — Persists estimate to artifact frontmatter (`estimatedPoints`, `estimatedHours`, `complexity`) and appends a full `## Estimate` section to the artifact body
1222
+ - **Interactive estimate prompt** — After displaying results, prompts to save, re-estimate, or discard (single artifact) or save all / discard all (epic rollup)
1223
+ - **`planr search <query>`** — Full-text search across all artifact types with highlighted snippets and 1 line of context
1224
+ - **`planr search --type <type>`** — Filter search by artifact type (epic, feature, story, task, quick, adr)
1225
+ - **`planr search --status <status>`** — Filter search results by artifact status
1226
+ - **`docs/agile/ESTIMATION.md`** — Estimation rubric generated by `planr init` with the full Fibonacci scale, complexity levels, risk categories, and team calibration guidance
1227
+
1228
+ ### Fixed
1229
+
1230
+ - **Estimate save preserves frontmatter formatting** — Injects estimate fields directly into raw YAML without re-serializing through gray-matter, so original quoting and structure is preserved
1231
+ - **Legacy `estimatedEffort` field cleanup** — Free-text `estimatedEffort` fields added by AI during task generation are removed when saving a structured estimate
1232
+
1233
+ ### Changed
1234
+
1235
+ - **Estimation AI prompt** — Embeds the full story point rubric (Fibonacci scale definitions, complexity levels, risk categories) for consistent and calibrated scoring across all artifacts
1236
+
1237
+ ## [0.7.0] - 2026-03-31
1238
+
1239
+ ### Added
1240
+
1241
+ - **`planr quick`** — standalone task lists without the full agile hierarchy (Epic → Feature → Story → Task). Ideal for prototyping, bug fixes, hackathons, or any work that doesn't need agile ceremony
1242
+ - **`planr quick create`** — AI generates a structured task list from a one-line description, with codebase-aware context and relevant file detection
1243
+ - **`planr quick --manual`** — interactive task entry without AI
1244
+ - **`planr quick list`** — list all quick task lists
1245
+ - **`planr quick promote`** — graduate a quick task into the agile hierarchy by attaching to a story or feature
1246
+ - **Auto-mark subtasks as done** — after a coding agent completes successfully, implemented subtask checkboxes are automatically checked off in the task markdown
1247
+ - **Quick tasks in `planr status`** — standalone quick tasks shown in their own section with completion metrics
1248
+
1249
+ ### Fixed
1250
+
1251
+ - **Claude retry for stdout API errors** — "API Error: 400 due to tool use concurrency" was emitted via stdout (stream-json) rather than stderr, so the retry logic never caught it. Now checks both streams for retryable errors
1252
+
1253
+ ### Type System
1254
+
1255
+ - Added `'quick'` to `ArtifactType` union
1256
+ - Made `TaskList.storyId` optional (quick tasks have no parent story)
1257
+ - Added `QT` prefix to ID system and `quick/` directory to artifact mapping
1258
+
1259
+ ## [0.6.0] - 2026-03-29
1260
+
1261
+ ### Added
1262
+
1263
+ - **Error context helper** — truncates large build logs for clearer failure output
1264
+
1265
+ ### Fixed
1266
+
1267
+ - **Agent hangs on large prompts** — implementation prompt is delivered via temp file + stdin pipe instead of a giant CLI argument (avoids OS argv limits and interactive “wait forever” behavior)
1268
+ - **Stream backpressure** — prompt delivery uses `createReadStream` → `stdin` pipe instead of buffered `stdin.write`
1269
+ - **Codex sandbox** — `--full-auto` and `--json` so Codex can write files and emit structured events (matches Claude-style progress output)
1270
+ - **Claude stderr** — retryable 400/429/5xx errors detected while still showing output in real time
1271
+
1272
+ ### Changed
1273
+
1274
+ - **Agent stdout/stderr** — `stdio: inherit` for live agent output where applicable
1275
+ - **Safety** — system prompt guidance to reduce destructive cross-project commands
1276
+
1277
+ ### Developer Experience
1278
+
1279
+ - **Linting and formatting** — ESLint and Prettier replaced with [Biome](https://biomejs.dev/) (`biome check` / `biome format`)
1280
+
1281
+ ## [0.5.0] - 2026-03-28
1282
+
1283
+ ### Added
1284
+
1285
+ - **Secure credential storage** — API keys are now stored in the OS keychain (macOS Keychain, Windows Credential Manager, Linux Secret Service) via `@napi-rs/keyring`, with AES-256-GCM encrypted file fallback for environments without a keychain (CI, Docker, SSH)
1286
+ - **Automatic credential migration** — existing plaintext `~/.planr/credentials.json` keys are migrated to the secure backend on first access, then the plaintext file is deleted
1287
+ - **Credential source display** — `planr config show` now shows where the API key is stored: `(OS keychain)`, `(encrypted file)`, or `(env: ANTHROPIC_API_KEY)`
1288
+ - **Per-command token budgets** — each command uses a tuned `maxTokens` limit (epic: 4K, feature/story/refine: 8K, task: 16K, task --feature: 32K) instead of a one-size-fits-all default
1289
+ - **Definitive truncation detection** — uses `stop_reason` (Anthropic) / `finish_reason` (OpenAI) to detect truncated responses instead of heuristic token thresholds
1290
+ - **8 new truncation unit tests** covering skip-retry, per-attempt token reporting, and streaming truncation
1291
+
1292
+ ### Changed
1293
+
1294
+ - **`planr config set-key`** now shows the storage backend: `"saved to OS keychain"` or `"saved to encrypted file"`
1295
+ - **AI service refactored** — `generateJSON` and `generateStreamingJSON` now share a common `generateCore()` function, eliminating duplicated validation/retry/truncation logic
1296
+ - **GitHub Actions** updated to v6 (checkout, setup-node) and v7 (upload-artifact) with Node.js 24
1297
+
1298
+ ### Fixed
1299
+
1300
+ - **Task generation from features failing** — `planr task create --feature` was truncating AI responses at 4,096 tokens, producing invalid JSON. Now uses 32K budget
1301
+ - **Spinner not stopping on API errors** — spinner animation no longer mixes with error messages when the AI provider throws
1302
+ - **Spinner showing ✓ before validation** — `succeed()` now only fires after successful parse/validation, not before
1303
+ - **Truncation error over-reporting tokens** — error messages now show per-attempt output tokens instead of cumulative totals
1304
+ - **Keychain write failures crashing** — `saveCredential` now catches keychain errors and falls back to encrypted file
1305
+ - **Migration flag set before completion** — `migrateCredentials` now resets the flag on failure so it retries next invocation
1306
+ - **`resolveApiKeySource` skipping migration** — `config show` now properly triggers legacy credential migration
1307
+
1308
+ ### Security
1309
+
1310
+ - API keys no longer stored in plaintext on disk
1311
+ - Encrypted file uses AES-256-GCM with machine-derived key (hostname + username + per-installation salt via scrypt)
1312
+ - File permissions set to `0o600` on all credential files
1313
+
1314
+ ### Developer Experience
1315
+
1316
+ - Test coverage: 261 → 269 tests across 23 test files
1317
+ - Added `tests/unit/ai-service-truncation.test.ts` (8 tests)
1318
+ - Added `tests/unit/credential-backends.test.ts` (8 tests)
1319
+ - Expanded `tests/unit/credentials-service.test.ts` with mocked backends (13 tests)
1320
+
1321
+ ## [0.4.0] - 2026-03-28
1322
+
1323
+ ### Added
1324
+
1325
+ - **Token usage display** — shows input/output token counts after every AI call (`✓ Done (1,240 in → 860 out tokens)`)
1326
+ - **`planr refine --cascade`** — refines an artifact then cascades to all children down the full hierarchy (epic → features → stories → tasks)
1327
+ - **Parent-aligned refinements** — child refinements receive updated parent content as context so AI aligns changes with the parent
1328
+ - **Post-refine next steps** — after applying without `--cascade`, suggests which children may need re-alignment
1329
+ - **Cumulative token usage** for cascade operations (`Cascade complete: 7 artifacts refined (12,400 in → 8,200 out tokens total)`)
1330
+ - **Spinner `succeed()` method** — shows green checkmark with completion message instead of silently clearing
1331
+
1332
+ ### Changed
1333
+
1334
+ - **Updated all dependencies** to latest major versions: `@anthropic-ai/sdk` 0.80, `openai` 6.x, `zod` 4.x, `commander` 14.x, `@inquirer/prompts` 8.x, `typescript` 6.x, `vitest` 4.x
1335
+ - **Removed `fs-extra`** dependency — replaced with Node.js built-in `fs/promises`
1336
+ - **Removed `ora`** dependency — replaced with lightweight built-in spinner
1337
+ - **Dropped Node 18 support** — minimum Node version is now 20
1338
+ - **Refine prompt** now preserves existing cross-reference links instead of adding phantom references
1339
+ - **"Suggestions" renamed to "Improvements"** in refine output for clearer UX
1340
+
1341
+ ### Fixed
1342
+
1343
+ - **Refine command** no longer adds feature/story references that don't exist on disk
1344
+ - **CI publish workflow** — fixed npm trusted publishing with bypass 2FA token
1345
+
1346
+ ## [0.3.0] - 2026-03-28
1347
+
1348
+ ### Added
1349
+
1350
+ - **`planr story create --epic <ID>`** — batch-generate stories for all features under an epic
1351
+ - **`planr checklist toggle`** — interactively toggle checklist items with multi-select prompt
1352
+ - **`planr config set-provider/set-key/set-model/set-agent`** — full AI configuration commands
1353
+ - **`--verbose` global flag** — debug logging across all commands
1354
+ - **`--all` flag on `planr status`** — show all items without truncation
1355
+ - **`--manual` flag** on epic, feature, story, and task create commands
1356
+ - **`--feature` filter** on `planr story list`
1357
+ - **Integration test suite** with real file system tests for artifact lifecycle and sync
1358
+ - **Test helpers** (`createTestProject`, `writeSampleEpic/Feature/Story`) for integration testing
1359
+ - **Pre-commit hooks** with husky + lint-staged (runs related tests on commit)
1360
+ - **Coverage reporting** with `@vitest/coverage-v8` and CI artifact upload
1361
+ - **CODEOWNERS** file for automatic review assignment
1362
+ - **Architecture guide** (`docs/ARCHITECTURE.md`)
1363
+ - **Troubleshooting guide** (`docs/TROUBLESHOOTING.md`)
1364
+ - **Security policy**, issue templates, and PR template
1365
+
1366
+ ### Changed
1367
+
1368
+ - **`planr status`** — enhanced with tree view (epic → features → stories), task completion metrics with color-coded progress, and overall completion summary
1369
+ - **`planr refine`** — apply action now works: writes improved markdown to disk with view/apply/skip options
1370
+ - **`planr checklist show`** — now displays color-coded completion progress
1371
+ - **Documentation** — CLI.md now covers all 25 command variants with complete option tables
1372
+ - **README commands table** — expanded from 19 to 25 entries
1373
+
1374
+ ### Fixed
1375
+
1376
+ - **Refine command** returning JSON instead of markdown in `improvedMarkdown` field — added explicit prompt instructions and JSON-detection fallback
1377
+ - **ID gap-filling** — `getNextId()` now reuses gaps (e.g., TASK-001 if only TASK-002 exists)
1378
+ - **npm bin paths** — added `./` prefix to suppress publish warnings
1379
+
1380
+ ### Security
1381
+
1382
+ - Bumped `handlebars` from 4.7.8 to 4.7.9 (fixes critical vulnerability)
1383
+ - Dropped Node 18 support (EOL) — minimum Node 20
1384
+
1385
+ ### Developer Experience
1386
+
1387
+ - Test coverage: 3 → 15 test files, 167 tests passing
1388
+ - Unit tests for: task-parser, markdown, fs, id-service, artifact-service, config-service, template-service, prompt-builder, logger, checklist-service
1389
+ - Integration tests for: artifact lifecycle, sync command
1390
+ - CI runs coverage on Node 22 with summary artifact upload
1391
+ - Upgraded to vitest 4.x
1392
+
1393
+ ## [0.2.0] - 2026-03-27
1394
+
1395
+ ### Added
1396
+
1397
+ - **`planr plan`** — full automated flow (Epic → Features → Stories → Tasks)
1398
+ - **`planr refine <ID>`** — AI-powered review and improvement suggestions
1399
+ - **`planr sync`** — validate and fix cross-references across artifacts
1400
+ - **`planr config show`** — display current configuration
1401
+ - **`planr task create --feature <ID>`** — AI task list from every story under the feature, with parent feature and epic, all Gherkin files for those stories, all ADRs, and codebase-derived context (higher output token budget than per-story task create)
1402
+ - Feature-level task generation shares the same rich context model as `--story`, aggregated across the feature
1403
+
1404
+ ## [0.1.0] - 2026-03-26
1405
+
1406
+ ### Added
1407
+
1408
+ - **CLI tool** with `planr` command (alias: `opr`)
1409
+ - **`planr init`** — initialize project with config and agile directory structure
1410
+ - **`planr epic create/list`** — create and list epics
1411
+ - **`planr feature create/list`** — create features from epics
1412
+ - **`planr story create/list`** — create user stories with Gherkin acceptance criteria
1413
+ - **`planr task create/list`** — task lists from a story or from all stories in a feature (AI mode includes epic, feature, Gherkin, ADRs, codebase context)
1414
+ - **`planr checklist show/reset`** — agile development checklist
1415
+ - **`planr rules generate`** — generate AI agent rule files
1416
+ - Cursor (`.cursor/rules/*.mdc`)
1417
+ - Claude Code (`CLAUDE.md`)
1418
+ - Codex (`AGENTS.md`)
1419
+ - **`planr status`** — project planning progress overview
1420
+ - Handlebars template system for all artifact generation
1421
+ - Zod schema validation for configuration
1422
+ - Auto-incrementing ID system (EPIC-001, FEAT-001, US-001, TASK-001)
1423
+ - Full agile hierarchy enforcement (epic > feature > story > task)