Tags give the ability to mark specific points in history as being important
-
-
-
-
-
-
-
-
v0.28.0
Release: v0.28.0 — the log reconciles itself3512fd73 · ·v0.28.0 — the log reconciles itself
-
-
-
-
v0.25.1
Release: v0.25.1cd1eed7a · ·v0.25.1 — maintenance cycle C3 - Maintenance cycle C3, no behaviour change: the live doc numbers and the fixture-name comments truthed up; `scripts/check.sh`'s tier table collapsed to one owner (each tier's label now rides its own command) with new witnesses for the Node-floor probe, the armed hook's `SKIP=check` escape and the dev `.venv` against `uv.lock`; the mutation sweep's whole-suite `--cross-check` repaired and witnessed; `src/batch.py`'s failure boundary covered; C2's eight mutation survivors killed or dispositioned (98.5 %, zero survivors); and two class-A dedupes (the plan flip rule written twice inside `src/logbook.py`, the `refusal()`/finite-number helpers duplicated across the extension's tool groups). A fresh-context review lane read the pass and found three defects, all fixed before this tag.
-
v0.25.0
Release: v0.25.092d2a61b · ·v0.25.0 — coach_doctor - **`coach_doctor` — one health command for env, credentials, state and version.** Ask for a health check (or run `python3 -m src.doctor` from the clone): one read-only digest reports the product version and how it is registered, the state dir (git remote, schema vs the shipped one), the engine environment, whether the Garmin credential env vars are set (their **names**, never their values) and the dev-ticket setup. Every failing check names the exact command to run; the tool writes nothing and repairs nothing. Blockers (env, state, schema, credentials) decide the exit code; the dev-ticket lane is reported as an optional gap, because a missing `glab` degrades a feature without making the install unhealthy. No state-schema or environment change; the tool set grows to 23.
-
v0.24.0
Release: v0.24.0314613e6 · ·v0.24.0 — one owner for the state dir and the ticket repo - **One owner for "which state dir".** The rule existed five times with different fallbacks, `~` was expanded in only two of them, and an empty `state_dir=` resolved to the *current working directory* in the engine — it read whichever repo the session happened to start in. Now there is one rule — `COACH_STATE_DIR` → the config's `state_dir=` → `~/coach-state`, with `~` expanded, a relative value made absolute and an empty value treated as unset — owned by `scripts/env_lib.sh`'s `coach_state_dir` for the shell, `src/state_path.py` for the engine and mirrored by the extension. The same case list runs through all three planes, so editing one alone fails the gate. - **One owner for "which ticket repo"** (`COACH_AGENT_TICKET_REPO` → the config's `ticket_repo=` → the product default), with the shell and TypeScript copies parity-tested against one fixture. - **The extension is inside the "one writer per key" guard.** That rule was enforced for `src/` only and the extension's writers were described in a string nothing read; a scan of `extensions/coach/*.ts` now fails the gate when the extension composes a state key nobody declared — and it caught two stale pointers in the ownership table, now corrected. No tool, state-schema version or environment change: the env contract (`COACH_*` names and order) is unchanged, and the state-dir order the docs always promised is now what the engine does.
-
v0.23.0
Release: v0.23.04af472cb · ·v0.23.0 — the live battery's staleness rule - **The live E2E battery has a staleness rule.** The live tiers — `tests/e2e_garmin_live.sh` and the pi-loop T2 — stay human-run on purpose (no Garmin credential in CI), but they are no longer unbounded. `scripts/check.sh` now prints one advisory line in its summary: it goes stale when more than five releases have shipped since the newest live entry in `tests/E2E.md` § 9, and it always reports the newest pi-loop entry's tool coverage against the registry. The line **never changes the gate's exit status** — a red gate would block every release on a Garmin 429 — and recording a live run in § 9 is what clears it. No tool, state-schema or environment change.
-
v0.22.0
Release: v0.22.0c4df5b83 · ·v0.22.0 — state_migrate's JSON boundary - **`state_migrate` keeps the engine's JSON-stdio contract on every failure.** It was the one verb that could fail as a Python traceback with no JSON on stdout — and it writes files *and* shells to git, so that was realistic, not theoretical. Every failure is now one `{"ok": false, "code": …, "error": …}` object at exit 1, with a named cause: `STATE_DIR_MISSING`, `TEMPLATES_MISSING`, `SCHEMA_UNREADABLE`, `STATE_NEWER_THAN_PRODUCT`, `MIGRATION_PATH_MISSING`, `COMMIT_FAILED`, or `MIGRATE_FAILED` for anything unexpected. A missing `templates/state` is a named preflight instead of a silently unrefreshed persona. - **A skipped normalization is named, not swallowed.** When a step meets a state file it cannot read (schema drift) it still leaves it alone and never guesses — but it now records an action of kind `skip` and the result carries `"skipped": true`, so a partially normalized state no longer reads as an unqualified success. A skipped path is never staged (staging it could sweep up an unrelated uncommitted edit of your own), and `update.sh` warns instead of printing "state is current". No tool, state-schema version or environment change: state files, the schema marker and every successful migration write exactly what they wrote before. -
v0.21.0
Release: v0.21.01e530b34 · ·v0.21.0 — release notes and honest dependency pins - **Release notes have an owner.** `CHANGELOG.md` (this file) — one section per release, newest first, and the same section is published as the tag's GitLab release body, so there is one text and not two. The publication step is part of the release checklist (`docs/ARCHITECTURE.md` § Portability & evolution) and `docs/INSTALL.md` § Updating points a returning user here: what changed between two tags is now readable without `git log` or the dev index in `ROADMAP.md`. - **The extension's `devDependencies` are a declared window, not `"*"`.** `@earendil-works/pi-coding-agent@^0.87.1` and `typebox@^1.3.34` are the versions the type-check and the test suite are verified against; `tests/test_lock_contract.py` fails when a range floats back to `"*"`, when the lock resolves outside the declared range, or when `package.json` and the lock's root disagree on the specifier — a pi API change is a red gate, not a silent recompile against an untested tree. - `tests/spec_audit.py` gains claim I4: the changelog leads with the released version and the checklist names the publication step. No engine, tool, state-schema or environment change.
-