---
title: openplanr 2.2639.4
description: Published 2026-09-27. Positional artifact ids must now look like an artifact id such as US-001 (an uppercase prefix, a hyphen and three or more digits).
url: https://openplanr.dev/docs/changelog/2.2639.4
updated: 2026-09-27
related:
  - https://openplanr.dev/docs/changelog/2.2640.0.md
  - https://openplanr.dev/docs/changelog/2.2639.5.md
  - https://openplanr.dev/docs/changelog/2.2639.3.md
---

# openplanr 2.2639.4

Published 2026-09-27.

[Release on GitHub](https://github.com/openplanr/OpenPlanr/releases/tag/openplanr%402.2639.4)

## Patch Changes

Positional artifact ids must now look like an artifact id such as `US-001` (an uppercase prefix, a hyphen and three or more digits). `planr <type> show|update`, `openplanr update`, `openplanr spec shape|show|status|destroy|attach-design|promote|sync`, `openplanr sprint refinement|diff|close|apply`, `openplanr template save`, `openplanr github push` and `openplanr linear push` reject anything else with `E_ARTIFACT_ID_INVALID` instead of printing another artifact for `.*`, resolving the bare prefix `SPEC` to the first spec, or crashing on `(`. Artifact, Gherkin, spec, managed-block and id-prefix lookups now match names literally.

The one-time migration of `~/.planr/credentials.json` now moves only the CLI's own keys and leaves other entries, such as the design engine's `openai_api_key`, in the file, deleting it only when nothing else remains. If an earlier run moved the design engine's key, store it again with the design engine's `setup` command or set `OPENAI_API_KEY`.

`--verbose` now prints the stack of a failed command and every cause it wraps, while the default output stays one line and `--json` output stays one envelope. JSON mode and the `upgrade` exemption from the inline upgrade offer are read from the parsed command instead of scanning the raw arguments, so an option value spelled `--json` no longer switches the output to JSON and an argument that is merely the word `upgrade` no longer suppresses the offer. A thrown non-`Error` value is reported as its text instead of `undefined`, and `--verbose` explains why the compatibility manifest could not be fetched or read.

JSON the CLI reads from `gh`, `claude` and `codex`, from the credential store and from the published compatibility manifest is now validated against a schema where it is parsed. A malformed or changed payload fails with `E_EXTERNAL_JSON_INVALID`, naming the command or file and each offending field, instead of a `TypeError` deep in a service; credential documents never echo their contents in the message. A legacy `~/.planr/credentials.json` that cannot be read is now kept for a later migration instead of being deleted as empty, and an off-schema compatibility manifest is ignored rather than cached.

`openplanr template save --name` and `openplanr template delete` now accept only lowercase words joined by hyphens (such as `rest-endpoint`, at most 64 characters) and fail with `E_TEMPLATE_NAME_INVALID` for anything else, so a name like `../../package` or an absolute path can no longer write or delete a file outside `.planr/templates`. Both commands refuse a templates directory that links outside the planning directory (`E_TEMPLATE_DIR_OUTSIDE`), and `save` replaces an existing template file atomically instead of writing through a link.

`openplanr operate dashboard` and `planr-pipeline dashboard` now load `startDashboard` from `planr-pipeline/dashboard` instead of the deprecated package-root alias. Behavior is unchanged; the command registry and its projection record the two changed command sources.

The remaining source modules over 800 lines open with a short comment that names what the module owns and its entry points, and three module comments that misdescribed their files now match the code. Only comments change: code, exports and behaviour are unchanged, and the bundled dashboard assets differ only in their source-derived build id.

Source modules over 800 lines open with a short comment that names what the module owns and its entry points, and several stale comments now match the code. Only comments change: code, exports and behaviour are unchanged, and the bundled dashboard assets differ only in their source-derived build id.

`PLANR_HOME` now also relocates the CLI's runtime state and backups, the pipeline runtime lookup and `doctor`, and design share custody, as it already did for the design engine and the review and dashboard daemons. `OPENPLANR_HOME` is deprecated: when `PLANR_HOME` is unset it still resolves to `$OPENPLANR_HOME/.planr`, and it prints a one-time warning on stderr; when both are set, `PLANR_HOME` wins. Design share custody kept under `OPENPLANR_HOME` moves from `$OPENPLANR_HOME/design-shares` to `$OPENPLANR_HOME/.planr/design-shares`, so move that directory if you set the variable. The doctor skill documents both variables.
