# Changelog All notable changes to MSD will be documented in this file. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] ## [2.0.1] - 2026-10-11 ### Fixed - **A passed UAT is no longer discarded or re-requested after gap closure** — a phase whose human UAT passed could loop forever between `/msd-execute-phase` and `/msd-verify-work`: a gap-closure plan (or a later phase editing a covered file) made the report `stale`, the re-run verifier could not see the UAT file, and execute-phase then rewrote `*-UAT.md` with every row back to `[pending]`. The verifier now reads recorded UAT results as evidence (`verification.uat-evidence`) and re-requests only rows whose tested code changed; the UAT file is merged, never overwritten (`verification.seed-uat`); `verify-work` and `progress` re-run the verifier themselves for a stale report instead of routing to `execute-phase`; and `progress` offers every stale-but-executed phase as one re-verify action. `verification.status` now reports `stale_reason`. A real change to covered code still makes the report stale. (#2) ## [2.0.0] - 2026-10-09 First release of MSD, the golem15 hard fork of GSD. It renames everything GSD → MSD, keeps six runtimes (Claude Code, Codex, OpenCode, Cursor, ZCode, Antigravity), and installs and updates from git release tags instead of npm: `curl -fsSL https://msd.golem15.com | bash`. It also includes all GSD changes made after 1.14.0. See **Changed**, **Removed** and **Fixed** below for the fork-specific entries. ### Added - **Opted-in bracket phase IDs now render consistently on progress surfaces** — `progress`, `stats`, manager init, and both statusline formats display canonical `[CODE.MM] NN` identities only when `phase_id_convention` is exactly `"bracket"`; other conventions retain their existing patterns and output shape. `config-set` now validates the convention's three supported values. (#3638) (#4111) - **Planning documents are now read and written through one parse → mutate → serialize seam** — a new internal `PlanningDoc` layer composes the existing markdown-sectionizer, markdown-table and frontmatter seams so a verb can no longer bring its own regex to a `.planning/` artifact. A field write reaches only its own value token, leaving hand-written prose on the same line intact by construction; serialization splices into the original buffer, so untouched regions stay byte-identical; and a write refuses outright on a document containing any region the parser could not read. No command changes behavior yet — this phase adds the seam and migrates no call site. (#4906) (#4918) - **`/gsd-ui-review` can capture post-interaction UI states** — a new default-off `workflow.ui_interaction_capture` key on the `ui` capability lets `gsd-ui-auditor` add hover, focus-ring, open-menu and filled-form captures through the `chrome-devtools` CLI, driven from Bash with no MCP server and no tool-surface change. Requires an installed Chrome; when off, or when none resolves, the Playwright-only static capture runs exactly as before. (#4223) (#4477) ### Changed - Internal (ADR-4629 section 8.1, epic #4629 child C1): introduce the `StateWriteIntent` type, extending `StateTransaction`, and a `readModifyWriteStateMd` opaque-transform recognition capability in the STATE.md write-path drift guard. This is the foundation for verified, bounded STATE.md writes. No user-facing behavior changes and no caller is migrated (that is Phase 2 and later). (#4676) - **The planner and the phase researcher now query the knowledge graph through the `graphify` CLI when it is on `PATH`, falling back to the built-in reader otherwise** — the planner gets one graph query per phase and the researcher two or three, and that single shot decides which modules the plan treats as related, and therefore how tasks are ordered into waves. It was spent on `seedAndExpand`, which seeds by case-insensitive substring match over a node label and description and then expands a hardcoded two hops: the phase "User Authentication" seeds on `author`, `authoring` and `unauthorized` with the same weight as `authenticate`, and when the inflated payload exceeds `--budget` the trimmer drops edges by confidence tier. The CLI, already a hard dependency of `/gsd-graphify build`, ranks seeds (IDF weighting, trigram fuzzy matching) and context-filters before traversal; the planner additionally runs `graphify affected`, reverse traversal for the exact question its reference states as its own goal, which the built-in reader has no equivalent for and which is skipped on the fallback path. The branch is `command -v graphify`, the same degradation shape already used for Context7 to `ctx7` — no new config key (a graph can only exist if the binary built it, so binary presence is a self-satisfying gate) and no new tool grant (both agents already have `Bash`). `gsd-tools graphify status` now returns `graph_path`, the resolved absolute graph location, on both the present and the missing branch: the CLI takes the graph as `--graph`, and re-deriving `.planning/graphs/graph.json` would point it at a non-existent local mirror in exactly the umbrella multi-repo setup `graphify.graph_path` (#1825) exists to serve — for the same reason the presence gate in both prompts is now the `status` call rather than a bare `ls`, which was already blind to the override. Declared limit: the two paths return different shapes (CLI prose with no `--json`, built-in JSON with confidence tiers and `budget_met`/`budget_estimate`) and `--budget` counts rendered output on one and estimated payload bytes on the other; both prompts state this instead of implying a stable shape. With `graphify` absent from `PATH` the injected context is byte-identical to before. (#4836) (#4874) - **`checkpoint:decision` auto-selection is now opt-in via `auto_select`** — in auto-mode, a decision checkpoint with no `auto_select=""` attribute now escalates to a human instead of silently picking the first `