# Release notes

Changes per released version of the Architecture MCP server, newest first. Starts at 26.3.1;
earlier versions shipped without release notes.

---

## 26.3.4 — 2026-08-11

### Changed

- The product is now called **Zügel**. The configuration file is `zugel.json`; the server jar is
  `Zugel-<version>.jar`; the MCP server reports itself as `zugel`.
- **Existing projects keep working.** The server reads the previous `architecture-mcp.json` if no
  `zugel.json` is present, and the launcher renames the file for you the first time it starts a
  26.3.4 or newer server. It never renames when a `zugel.json` already exists, and never when the
  server it is about to start is older than 26.3.4 and could not read the new name.
- Update the server key in `.mcp.json` to `zugel` if you want the tools to appear as
  `mcp__zugel__*`; the old key keeps working.

---

## 26.3.3 — 2026-08-10

### Added

- **`release_notes`** — the server's own release notes, per version, read from the copy inside the
  running jar. It pairs with `server_version`: that answers which build you are talking to, this
  answers what is in it. Call it with no arguments for the running version, `since` for everything
  released after a version you were on, or `version` for one in particular.
- Each section carries an **`upgrading`** field when that release has one: what it does TO you —
  a forced re-parse, a changed reply shape, a moved configuration key — as opposed to what it
  offers. It stays in the section text as well, so nothing is lost by reading only `notes`.
- The notes are bundled at build time, so they work with no network and cannot describe a version
  newer than the server you are asking. Naming one is an error that lists what is available.

---

## 26.3.2 — 2026-08-10

### Improved

- `generate_config` writes JSON arrays with one entry per line, instead of putting a module's
  entire `classpath` on one line. Existing files keep working; re-run `generate_config` to
  reflow the current one.

---

## 26.3.1 — 2026-08-05

### Upgrading

- **The first scan after upgrading is a full re-parse.** The parse cache is now keyed to the
  build that produced it, so older cached models are refused. Minutes once on a large reactor;
  warm again afterwards.
- **Re-run `generate_config`** to pick up `moduleRoot`. Older configurations keep working
  without it.
- **Reply shape change:** `remove_baseline` returns `removed` as an array of names in both
  modes, previously a bare string. Everything else is additive.

### Added

- **`moduleFilter`** in `zugel.json` — `includes`/`excludes` patterns selecting which
  modules `generate_config` writes into the `project` section, replacing the flat exclusion
  list. Patterns use the product's wildcard syntax (`**`, `*` within one dot-separated segment,
  `?`) against the whole module name. `generate_config` gains `includeModules`,
  `excludeModules` and `removeModulePatterns`, all additive against what is persisted.
- **`moduleRoot`** per module — the module's own directory. Lets the loader settle a source root
  two modules claim, by the same rule the generators use.
- **`configWarnings`** on every scan: source root that is not a directory, `dependsOn` naming no
  configured module, source root claimed by two modules, module that indexed nothing. Warnings
  only — no scan fails and no configuration is rewritten.
- **`architectureWarnings`** on every scan: non-`optional` artifacts that matched no component,
  and deprecated artifacts that still hold components.
- **`baselineDrift`** on scans, at startup, and on all four baseline tools — baselines that have
  outlived the configuration they were captured under. While the active baseline has drifted,
  `diff.sinceSessionBaseline` is withheld. Adding a module does not drift a baseline; removing
  one or moving its source roots does.
- Baselines written before this release are reported with `status: UNVERIFIABLE` — no recorded
  scope to check. Their diffs are still served, and they are not deleted by the bulk cleanup.
- **`remove_baseline {"drifted": true}`** deletes every drifted baseline in one call. The active
  baseline is skipped rather than failing the call.
- **`server_version`** — reports the running build. The same version is now used for the startup
  log line and for `serverInfo.version` in the handshake (previously a hardcoded `1.0.0`).
- **`generate_config` reply carries a `rescan` object** with the same payload `rescan_sources`
  returns, plus an `arcFilesLoaded` count. `generate_config` was always a reload; a following
  `reload_all` is unnecessary.

### Changed

- **`diff.addedDependencies` is now `diff.problematicAddedDependencies`** and lists only new
  couplings that break a rule, sit inside a flagged cycle, or sit inside a newly created
  tolerated cycle. Ordered violations first, then cycle members, capped at 50, with
  `problematicAddedDependenciesTotal` giving the real count. Edges of pre-existing tolerated
  cycles and ordinary new dependencies are no longer listed. `addedViolations` is never capped.

### Fixed

- Member references are attributed to the receiver's static type rather than the declaring type,
  which differ when a subclass re-exposes an inherited API. Removes false violations. Unqualified
  and statically imported calls are distinguished.
- `list_artifact_components` returns a declared-but-empty artifact instead of `Artifact not
  found`; "matched nothing" and "never declared" are now separate states.
- External components are assigned in the standing index, so an artifact capturing a third-party
  library reports its contents. `list_reachable_components` still excludes externals.
- A source root claimed by two modules is settled at load time when `moduleRoot` is recorded,
  instead of by scan order. Without that evidence the collision is reported, as before.
- `generate_config` no longer reports "no .arc files configured (cycles-only mode)" when the
  project has `.arc` files.
- A source root that is not on disk is dropped and reported by name, instead of reaching ecj and
  surfacing as a compiler bug.
- The parse cache is keyed to the build that produced it, so a stale model is no longer reused
  after an upgrade.

### Known issues

ecj does not close the classpath jars it opens. The open set does not accumulate across rescans
(macOS and Windows). On Windows those jars stay locked while the server idles until a garbage
collection releases them. Generated configurations put only immutable cache jars under `~/.m2`
and `~/.gradle` on the parse classpath, and class directories hold no handle, so `mvn clean` is
unaffected. Restarting the server releases everything.
