# Changelog Every release, newest first, with the reasoning behind each change. # Swallowtail changelog All notable changes to this project are documented here. Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this project aims to follow [Semantic Versioning](https://semver.org/). ## [Unreleased] ## [1.2.0] - 2026-10-08 ### Added - **Every skill file and install guide opens with a Contents list**. Each entry links to its section and gives the exact line range, so an agent that reads only the first 100 lines of a file can read the rest one section at a time. The lists are generated by `go run ./tools/docindex`, and `go test` fails when a heading changes without a regenerate. The skill now tells agents to read a reference's Contents first. - **`automate` plans can capture values, assert with operators, and wait**. A step's `capture` stores a result value under a name, and later `params` and assertion values use it as `{{name}}`. An exact `{{name}}` keeps the value's JSON type; inside longer text it is spliced in. `assert` takes `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `contains` and `exists`, the operator names `test run-scenario` uses, with a `tolerance` for numeric `eq` and `neq`. `wait_until` repeats a step until its checks pass, for up to 10 minutes at intervals of 50 ms or more. A plan that references a name no earlier step captures exits with code 2 before anything runs. Under `--continue-on-error`, a step whose variable was never captured is skipped with the reason in the report. The report adds `captures`, `failed_assertions`, `attempts` and `skip_reason`; every earlier field is unchanged, and `expect` works as before. - **`automate --report` and `--junit` write report files for CI**. `--report FILE` saves the same JSON document printed on stdout. `--junit FILE` writes JUnit XML with one test case per step: assertion failures are `` entries, and command, transport and preflight errors are `` entries. Both files are written when the run fails, including when the editor cannot be reached, and a file that cannot be written makes the exit code 1. - **Playtest sessions recorded in the running game**. `swallowtail playtest start` records every frame's wall-clock time, engine counters every 30 frames (FPS, process and physics time, memory, object and node counts, draw calls), and each input the agent sends, checkpoint, game event and runtime error with a timestamp. `playtest mark --label` starts a section, `playtest event --name --data` posts a game fact, and game code posts its own with `MCPGameInspector.playtest_event("death", {"wave": 3})`, which does nothing when no session records. `playtest stop` writes the session as JSON to the game's `user://swallowtail-playtests/`. The five commands also reach a standalone game with `--game`, and MCP clients get them as typed tools with the same `game` switch. - **`playtest report` and `playtest compare`**. Both run locally with no editor, on a session file or `--latest`. A report gives frame-time percentiles and 1% lows, each spike with the input or event just before it (with the event's data, so a report says which coin or which wave) and the memory change on that frame, memory and node trends, runtime errors, per-section numbers, event counts per section, input rate, and findings that name what to look at. `compare` sets two sessions side by side with a verdict per metric, leaves noisy frame-time tails ungraded on short runs unless they moved 50% or more, and first lists any difference in how they ran, such as a headless run or another window size. Output is Markdown or JSON, on stdout or written to `--out FILE`. ### Fixed - **A quoted value means the string inside the quotes**. A JSON string such as `--value '"../Child/Target"'` was stored with its quote marks, so `batch cross-scene-set-property` wrote `NodePath("\"../Child/Target\"")`, which resolves nothing, and still answered `Changes applied.` Values that commands infer a type for now read a JSON string literal as its contents, and escaped quotes inside it are kept. - **`scene open` answers with the same fields every time**. An open, a no-op on the active scene, and a forced reload each returned a different set of keys, so a command plan that checked `opened` failed on a second run. Every success now carries `path`, `active`, `opened`, `already_active`, `was_already_open` and `reloaded`; `active` is always true and is the field to check. - **Headings and code comments restored in the multiplayer and tile-constraint guides**. A punctuation sweep in August turned every leading `#` in those two files into a space, so neither guide had a heading, and the comment lines in the tile guide's shell examples ran as commands when pasted. All 38 lines are back as they were. - **`scene save` no longer logs six editor errors per save**. In a windowed editor every save logged six `progress_dialog.cpp` errors, though the file was written. The save now runs on the next editor frame and returns `-32009` if the active scene changes before it can. `editor errors` no longer hides those lines as noise. - **Spatial placement docs match the commands**. The `align` and `distribute` examples use real flags, the `relate` example uses `--other` and shows the actual result fields, and the floating-geometry tip gives the 0.5 m support gap and the 5 cm contact slack. - **Craft guide corrections**. The C# guide describes the `csharp` group and C#-aware `script` commands. The environment-art and tile guides no longer offer `authoring checkpoint` as a way to undo a scatter or WFC run, since it restores transforms only. The level-design guide says which props seat on their own collider: CSG props with `use_collision`, while props with a body node are excluded. - **`go test` passes on the public mirror**. The QA worker contract test skips when the maintainer-only script is absent. ### Verified - **Godot 4.3 through 4.8-dev7**. The official 4.3, 4.4.1, 4.5.2, 4.6.3 and 4.7.2 stables and 4.8-dev7 (`c971f93e7`, released 1 October 2026) each ran a headless editor on its own copy of the test project. On every one, all 337 commands registered with no group skipped, the game channel answered, and a playtest session recorded and wrote its file. - **Godot 4.8-dev7 in a windowed editor**, run on the candidate before the playtest work landed. The dev7 doc cache reads, a screenshot from the game is not black, a planted parse error reaches `editor errors`, `scene save` writes only the edited property and logs no editor errors, `spatial raycast` returns the same hit as 4.7.2, and the HTTP MCP conformance sweep passes 37/37. dev7 adds typed result classes for the physics space queries (`PhysicsIntersectRayResult3D` and eleven others) and an `*_into` variant of each query. `intersect_ray` and the existing queries still return a Dictionary, so the raycast and seating commands are unaffected. Against 4.7.2 in the same inspector state, dev7 adds 57 classes and removes 8. ## [1.1.0] - 2026-09-26 ### Added - **Release QA commands and skill**. `qa init`, `qa run`, `qa compare`, `qa attest`, and `qa report` retain logs, build hashes, named frame phases and screenshots, distinguish source scenarios from packaged tests, and generate a branded PDF with the Swallowtail mascot. Games extend the runner with GDScript `run(qa)` scenarios. Python 3.10+ runs the embedded worker; ReportLab 4 renders PDFs. Optional PresentMon capture targets the spawned Windows process. The `swallowtail-qa` skill documents coverage, evidence and baseline comparisons. - **QA conclusions and readiness assessments**. Reports include per-test conclusions, fix status and closure work. `qa report --assessment` accepts a reviewed assessment JSON and records its hash. Passing checks alone do not imply ship approval. - **Companion QA skill bundles**. Platform archives include both skills, with a separate QA skill archive. Checksums cover all nine archives. - **The butler in the banner**. Running `swallowtail` with no arguments now draws the mascot beside the wordmark, in colour as half-block cells on a terminal that takes escapes, and as a textured silhouette under `NO_COLOR` or a dumb terminal. Piped output and every command's output are unchanged. - **The `at-your-service` sample**. A getting-started film that follows one lighthouse coast through terminal commands, a repeatable command plan, a live playtest, an agent task, and an MCP readback, with the playable scene beside it. The film is thirteen chapter scenes and an AnimationPlayer timeline, editable in the Godot editor and rendered by Godot's movie writer; the CLI and MCP results it shows were recorded against the project. `samples/at-your-service/`. ### Changed - **`scene3d add-body --from-mesh` seats the body on the mesh and fits the shape to it**. The body takes the mesh's rotation and origin, the mesh's scale is baked into the collider, and a box, sphere, or capsule is sized to the mesh bounds unless `--size`, `--radius`, or `--height` is given. Before this the body landed at `--position` with the collider at the mesh's unit size, so a collider for a mesh anywhere but the origin was seated wrong. `--reparent-mesh true` moves the MeshInstance3D under the new body so the two move together, and the whole call is one undo step. `--position` is refused together with `--from-mesh`. ### Fixed - Named and keypad input resolves through Godot key-name APIs without invalid GlobalScope ClassDB lookups. - PDF frame-timing headings stay with their explanatory text across page breaks. - QA shell completion lists its subcommands and command-specific flags, including assessment files and manual attestations. - Release verification checks both skill payloads, the standalone QA skill archive, and the complete checksum manifest. - **`gridmap meshlibrary-from-scene` keeps each piece's mesh and collider offsets**. The kit scene is instantiated without entering the tree, where `global_transform` reads identity, so every item's mesh and every collider landed on the item origin: a wall's box blocked only its lower half. Offsets are now accumulated from local transforms. - **`scene3d setup-camera --look-at` aims a new camera**. For a camera the command was creating, the look-at ran before the node was in the tree, so the engine refused it and the camera kept an identity rotation inside a success envelope. The aim is now set from the basis, with the target carried into the parent's space. An existing camera was never affected. - **`scene3d setup-environment` builds a sky by default**. Sky is the default background mode, but the Sky resource was only built when `--sky` was passed, so a bare call answered success and the game came up on a black background. The default mode now builds the procedural sky with its default colours; an existing environment keeps the sky it has. - **`editor run-script` and `runtime eval` report a runtime fault instead of a clean run**. A snippet that hit a script error (an invalid call, a null dereference) aborted at that line and came back with whatever it had emitted so far and no error, so the only trace was a line in the Output panel. Both now capture what the engine logged around the run and answer `-32603` naming the line of the caller's code, with the partial `output` and the captured `errors` attached. A `push_error` or an engine error inside a called method does not fail the call and is attached as `errors`, with the snippet's own line where the backtrace names it. A parse error now names its line too. On Godot 4.3 and 4.4, which have no `Logger`, the reply carries `error_capture: "unavailable"`. A game launched from the editor still breaks into the debugger on a script error before the reply can be built, and the timeout message already reports that break; the new reply is what a standalone game answers over the direct channel. - **`editor errors` no longer reads a game's log from a windowed editor**. When the Output panel held nothing after filtering (an empty panel, or `--internal=false` dropping every line), the command fell through to `user://logs/godot.log`, which every game run of the project writes under the same user-data directory and which outlives the session. A clean editor could therefore report a script error a game had raised days earlier, with no way to tell it from a live one. The log is now read only when the Output panel is unreachable, which is the headless case it was written for. Found retesting on Godot 4.8-dev6 and reproduced on 4.7.2. - **Screenshots of an HDR 2D viewport are encoded as sRGB**. With `rendering/viewport/hdr_2d` on (which `lighting glow-2d` enables), the viewport hands back a half-float linear image, and `runtime screenshot`, `runtime capture-frames`, and `editor screenshot` saved those values straight to PNG, so every capture read far darker than the window. The three captures now convert to 8-bit sRGB first and report `hdr_2d` in the result. On Godot 4.3 the engine has no conversion method, so the frame stays linear and the result carries `color_space: "linear"`. ### Verified - **Godot 4.8-dev6** (`8898c2b3d`, released 15 September 2026). All 336 commands across 51 groups register with no group skipped, the live ClassDB and the dev6 doc cache read, the game IPC answers, a planted parse error reaches a windowed `editor errors`, `scene save` writes the same text as 4.7.2 apart from the edited property, and the HTTP MCP conformance sweep passes 37/37. No code change was needed for 4.8; the one finding, the log fallback in `editor errors` above, reproduces on 4.7.2. Against 4.7.2 in the same inspector state, dev6 adds 42 classes and removes 7; since dev5 the only movement is `OpenXRFoveatedInsetViewport` added and `GodotPhysicsDirectSpaceState2D` back again. dev6 is the newest snapshot, and there is no 4.8 beta yet. ## [1.0.1] - 2026-09-10 A hotfix for `swallowtail migrate`. The addon is unchanged apart from its version; reinstalling it is optional. Projects already migrated with 1.0.0 that carry custom commands under `mcp_commands/` should fix each file's `extends` path by hand or roll back and migrate again with this release. ### Fixed - `node set` refuses scalar text it cannot read instead of coercing it to zero. `--value abc` on a float property set it to `0.0` and `--value maybe` on a bool set it to `false`, both inside a success envelope; each now returns `-32602` naming the property and the text. Numbers, `true`/`false`/`yes`/`no`/`1`/`0`, and native JSON scalars parse as before. - The test project's two project-local command files (`mcp_commands/example_commands.gd`, `mcp_commands/refs_commands.gd`) extend the addon at its migrated path. Since the 1.0.0 rename they failed to parse on every editor launch and the `custom` group never registered; found while retesting against Godot 4.8 dev5. - `swallowtail migrate` rewrites the old addon path inside project-local command files under `mcp_commands/`. A migrated project's custom commands used to fail to parse and vanish from the catalog with only an editor warning. The preview names each file, the journal keeps its original bytes, and rollback restores it unless you edited it after migration. - `task test:http:failures` runs again: it loads the HTTP server with the test project as `res://`, which the server's `identity.gd` preload has needed since the rename. - The web dashboard's wordmark reads Swallowtail. ## [1.0.0] - 2026-09-07 The first release under the Swallowtail name. Versions 0.12.0 and 0.13.0 were prepared but never published; their entries are folded in here. The last release under the old name is 0.11.0. ### Added - `swallowtail automate`: JSON command plans with project identity checks, method preflight, result assertions, per-step reports, and stop-on-failure execution. - Swallowtail editor dock connection setup, error detail inspection, copying failed requests as automation plans, and JSON activity export. - Swallowtail is the primary CLI. Every platform bundle also ships the deprecated `godot-mcp` executable with identical functionality and no scheduled removal date. - `swallowtail migrate` previews addon migration; `--apply` installs the renamed addon with a recovery journal, and `--rollback` restores the original installation. - `SWALLOWTAIL_*` environment variables, renamed settings, and compatible discovery reads. The addon writes both discovery names for older clients. - Bash and PowerShell completion for commands and parameter names. Project-scoped cached help remains available offline with a timestamped notice. - Global `--project DIR` selects a project for editor commands and rejects an explicit project/port mismatch before dispatch. - `--params-file FILE` or `--params-file -` reads a JSON parameter object from a UTF-8 file or stdin. Inline parameters override matching keys. - `--errors json` provides structured stderr for editor-command failures. - `scene validate --path` checks a saved scene, including inherited scenes and nested instances, while the active tab and unsaved edits stay in place. It reports missing dependencies, unresolved stored node paths, animation track targets, and missing node classes. Absolute runtime paths need a running tree. - GDScript `script validate` returns compiler diagnostics with file, line, severity, and message on Godot 4.5+. Older engines report `diagnostics_available: false`. Relative preloads resolve from the script's directory, and repeated validation avoids temporary resource-cache collisions. - Scenario steps have nested schemas in both MCP transports. `test run-scenario` checks the whole plan before playback or input, rejecting unknown fields, missing values, invalid types, unsupported operators, and numeric bounds with the zero-based step index. - Stdio MCP progress and cooperative cancellation for scenario steps, validation batches, and imports. Clients request progress with `_meta.progressToken` and cancel with `notifications/cancelled`. Cancellation skips remaining work at safe boundaries and preserves completed effects. A native compile/import or game command already underway can finish. HTTP cancellation is not supported. - A "Before you ship" page of its own, with the two steps that keep the addon out of an exported game and a pck scan that proves they worked; the installation page and quickstart point at it. - Documentation for reaching an editor on another machine over an SSH port forward, for Windows, Linux and macOS, plus running `serve` remotely for stdio clients. - The homepage shows four typed CLI sessions (run commands, automate, custom commands, connect tools) captured from the real tool, and the samples page leads with the Reversi game. ### Changed - Editor dock branding now uses the Swallowtail butler, mulberry accents, and speech bubbles with light/dark theme support. - Activity records retain bounded error details and replayable parameters, with common credential fields redacted. - CLI response failures identify timeouts, cancellation, and uncertain outcomes; Ctrl+C cancels editor requests. - Public branding becomes Swallowtail, with a butler mascot and a warm ivory, ink, and mulberry documentation theme. The homepage and README lead with automation from your terminal, scripts, and connected tools. New addon and skill directories use `swallowtail`; existing projects migrate explicitly. Runtime autoload identifiers and MCP methods remain compatible. Client configuration refuses duplicate legacy/new server entries. - Terminal onboarding builds and plays a scene from an empty project without an agent or MCP client. Installation documents the optional agent skill. - Typo errors suggest nearby commands. Pretty scene/runtime trees use branches, and validation output shows verdicts and diagnostic file locations. - Stdio tool catalogs refresh on list requests, before typed calls, and after successful generic editor calls. Editor shutdown clears stale tools; a restart restores them in the same MCP session. Changed descriptors emit `notifications/tools/list_changed`; identical catalogs stay quiet. - The README and the migration page state why the name changed, and a dismissible announcement on the docs site links to it. ### Fixed - Linux and macOS release archives built on Windows now preserve executable permissions on the CLI binary. - Upgrade recovery reports restoration failures, restores only captured paths, and refreshes editor scenes, scripts, and settings. Unrelated files survive recovery, and a partial restore cannot be reported as a successful rollback. - Invalid editor or game port configuration fails before dialing or launching. - MCP initialization negotiates only supported protocol revisions. - HTTP limits apply to headers, bodies, and buffered input while a request is busy, including requests using unsupported HTTP methods. - `script validate` no longer leaves a `