Changelog
Unreleased
0.1.0 - 2026-10-27
PowerShell review: six bugs fixed, four new syntax-tree checks.
bench -Sweep 'particles=100 0',5000named' 'instead of the values ($Matcheswas overwritten before the message); elevenResolve-Pathcalls on the kit's own tools now take-LiteralPath(a kit under a folder with[ ]found nothing);Start-Process -ArgumentListin four self-tests quotes its paths;-replacereplacements built from a version line, a[dotnet]entry, a home folder, a licence line and a csproj block are script blocks, so a$in the data is not read as a group; the Stop hook and every childpwshin the scripts start with-NonInteractive;Test-SkillFixtures.ps1pins strict mode.Test-PowerShellPatterns.ps1gainsresolve-path-wildcard,start-process-arglist,replace-interpolatedandpwsh-interactive, a strict-mode check for every entry and test script, and a check of the hook's arguments;Test-BenchSweep.ps1checks the refusal's message.PowerShell review, second pass. Every
ConvertTo-Jsonnow passes-Depth(nested data was cut at depth 2 and a warning reached stdout);Plan.ps1'sfile:check,Publish-Release.ps1and the Godot templates copy read their paths literally;Test-ReportPins.ps1calledInstall-Godot, which does not exist (it failed on any machine withoutGODOT_BIN). New checks inTest-PowerShellPatterns.ps1:json-depth,path-wildcard,duplicate-parameterandundefined-command.Set-ProjectVersionLine(export's version patch) is a function so a$in the line is tested, andtests/Test-KitPaths.ps1runs the textsize runner from a folder namedkit [v2]and keeps a$insolution_directory.- The first mid run of the staged programme, stopped halfway (token-benchmark run 44, $34.53, 294 of 540 sessions graded;benchmark/PLAN.md). The owner's plan ran out of usage after 65 minutes of twenty parallel jobs, and a git race ended four parts early (fixed in nick-vas/hyperdot#134). Milestones cost about $0.40 to $0.50, not the guessed ten Sonnet tasks:cost-model.jsonnow uses the measured means, and the mid tier is priced at $67.71. It also found a grading fault to decide on: theunchangedrule fails sessions that only add tests to a kept test file.The judge's calibration applies the owner's rule over every set at once.
Get-JudgeAgreement.ps1 -Calibration benchmark/calibrationholds a judge to the owner's own agreement on a blind re-judge (6 of 10, read fromcalibration/retest-1.json, whose stated result it checks against its pairs) and to 90% agreement with itself over every pair of every set; it measures agreement on every set but one markedforAgreement: false(the first, judged with the old rubric shown), with each re-judged pair's newer verdict, turned back where A and B were swapped. The workflow'scalibrateinput is now a switch: it rebuilds every set's pairs from its run and tries the judgescost-model.jsonprices, cheapest first, in place of one run at fixed bars of 80% and 90%. Recomputed from the saved judgements, it reproduces every recorded agreement and corrects one figure: Haiku's agreement with itself in the fourth calibration was 81%, not 84% (tests/Test-ReviewPairs.ps1).A benchmark run can be split into parts.
Invoke-TokenBenchmark.ps1 -Shard k/nruns every n-th session of the run from the k-th, with its own estimate and its share of the ceiling; the n parts together hold each session once (tests/Test-GameBenchmark.ps1). The workflow'sshardsinput runs each configuration as n parallel jobs: the mid tier, 135 sessions a configuration at three to four minutes each, outlasts one job's 330 minutes.The staged programme's first run over all ten genres (the min tier, token-benchmark run 43, $6.58): 66 of 80 sessions passed and no task failed for every configuration (
benchmark/PLAN.md). It found two faults in the kit, both fixed with regression tests: isolated sessions inherited no writable XDG folders, so Godot's config ended up inside a game (Isolation.ps1now gives each session its own, checked intests/Test-BenchmarkIsolation.ps1), and thevalidaterunner read.tresfiles intest-results/andTestResults/, which it now skips like the kit's file search (tests/Test-StaleTres.ps1).cost-model.json's task prices are this run's mean costs.The staged programme's min and mid tiers cover all ten genres. min runs one stage of each genre (every language and stage pair at least once), 20 tasks a configuration, estimated at $5.70 for all four configurations; mid runs one stage of each genre in each language, 40 tasks and 5 milestones a configuration, three times, estimated at $100.20 under a ceiling raised from $50 to $120. The runner now refuses a tier milestone that starts from none of the tier's cells, which it used to drop without a word.
The eval graders are tested against real sessions.
tests/Test-EvalGraders.ps1checks every regex and tool_used grader inevals/against 14 sessions from Evals runs 4 to 7 (tests/eval-grader-fixtures/, made from the workflow's artifact bytests/New-EvalGraderFixture.ps1). A stand-in forclaude plugin evalfirst gives all 21 verdicts the runs recorded; then each grader as it is now must agree with a person's reading of each session, and each needs a real session to pass and one to fail, or a reason ingaps.json. It foundexplain-failure'slocationgrader failing three right answers that put a number between the file and "line 7" (runs 5 and 6); its pattern now allows that. Model graders are not checked: they need a model.The side-by-side judge can vote.
Invoke-SideBySide.ps1 -Votes <n>(and the token benchmark'svotesinput withcalibrate) judges each order of a pair n times in fresh sessions; the order's choice is the majority, a tie is even, and an order where fewer than half the votes named a choice is an error. Each pair keeps its votes inpreferences.json. A cheap judge that changes its mind between runs can then be calibrated by its majority.A PowerShell guide, PSScriptAnalyzer on every script, and a check for the anti-patterns the code has dropped.
docs/powershell.mdholds 78 lessons for anyone writing PowerShell here, merged from the official PowerShell documentation and the PowerShell Community blog, by theme (errors and exit codes, strict mode and the pipeline, culture and encoding, native commands, paths, parameters, JSON, concurrency, performance, secrets, tooling), each with why, a quoted source and whether it was run; the ten that cost most come first, then the sources' advice that does not hold on 7.6 under strict mode on Linux, and what checks each lesson. AGENTS.md's "Working here" gains the most consequential ones. The lint job's PSScriptAnalyzer step pins 1.25.0, scans every tracked.ps1(tests and the GitLab run step too) with Information severity, annotates each finding and fails on any; the wider scope found two dead variables in tests, now gone.tests/Test-PowerShellPatterns.ps1reads every script's syntax tree for ten patterns with no use left (continuein a pipeline block,$nullon the right,Invoke-Expression,[IO.Path]::Combine,$PSBoundParameters.Name, a lowered$ErrorActionPreference, relative literal paths to .NET,-Version Latest, Windows-only aliases, one file read and written in one pipeline), each proven on a fixture file of its own.PowerShell 7.6 or newer is required (breaking for PowerShell 7.2 to 7.5). Every script now starts with
#Requires -Version 7.6, the current LTS release: 7.2 left support on 8 November 2024, and 7.4 and 7.5 leave it on 10 November 2026, while 7.6 is supported until 14 November 2028. GitHub's runner images already ship 7.6 (Ubuntu 22.04 and 24.04, Windows Server 2022 and 2025, macOS 15), so the action and the workflow need nothing; on an older PowerShell the kit stops at once with PowerShell's own "#requires" message. To upgrade:winget install Microsoft.PowerShell(orwinget upgrade) on Windows,brew upgrade --cask powershellon macOS, and Microsoft's package repository (apt install powershell) or the release tarball on Linux; self-hosted runners need the same. The GitLab template's .NET 8 SDK image carries PowerShell 7.4 (the global tool follows .NET 8, and 7.6 is built on .NET 10), so itsbefore_scriptnow unpacks PowerShell 7.6.9's self-contained Linux build into.hyperdot-cache/pwsh/(cached), puts it first on PATH and stops the job ifpwshis still older; games still build with the image's .NET 8 SDK.tests/Test-GitLabTemplate.ps1holds the template to the floor ofhyperdot.ps1.A staged-programme task's
unchangedfiles may now gain lines. The rule failed a session withchanged <file>for any difference, so every session that added regression tests to the existing test file failed (run 44'sracing.alpha.csharp.fix-bugpassed 0 of 10 although they had removed nothing). A kept file now passes when every original line is still there in its order, line endings aside; a missing file and a changed, removed or reordered line still fail. Before the hidden tests, mutants and the suite run, the kept files are put back as they were, so added code cannot weaken the original tests (newTestscounts the additions first). Self-tested intests/Test-GameBenchmark.ps1.The GDScript arena game turns the server relay off, as the C# port already did.
NetSession.hostleftSceneMultiplayer.server_relayon, so when a player connected the engine sent news of it to every other peer, also to one whose disconnect it had received but not yet reported (its channels are closed by then): an engine error, "Unable to send packet on channel 0, max channels: 0", that failedsoakwithengine-errorsnow and then (2 runs in 20 on the reference ofarena.beta.gdscript.fix-performance, whose clients leave and rejoin all the time). Players only talk to the server, so nothing else changes. The base game and itsmilestone-alphasolution are fixed.The self-test runs what a change needs. It ran 35 jobs and about 500 runner-minutes for any change, 84% of them in the 20 pairs of the staged programme, and every push to a pull request branch started two runs. Now a
changesjob (.github/scripts/Select-Jobs.ps1, held bytests/Test-SelectJobs.ps1) lists the changed files and a pull request runs lint alone for documentation, the jobs that exercise the changed libs, tools and tests otherwise, one pair for a changed game and a sample of three pairs for the programme's own code; a push tomain, the nightly run (02:23 UTC) and a manual run still run everything, and keep a few slow steps that have never failed for the full runs only. Branches are tested through their pull request, not on push, and the coverage floors are enforced on the full runs. Git's background maintenance is off in CI. docs/ci.md has the rules, the measured cost and the failure record of the last 100 runs; faster game jobs were measured and not shipped (no gain beyond noise).Game copies no longer race git's background maintenance. Since git 2.54 a commit's automatic maintenance packs loose objects in a detached process ("geometric" strategy), and a beta or release game commits over a hundred: the benchmark's copy of the game or its
.git, made a moment later, lost files under it ("Could not find a part of the path .git/objects/..."), which ended four parts of token-benchmark run 44 and two self-test jobs on the runners' git 2.55.New-GameWorkspacenow setsgc.auto 0,gc.autoDetach falseandmaintenance.auto falsebefore the first commit, which also covers the git commands a session runs, andtests/Test-GameProgramme.ps1checks every workspace it grades.A website, built from the docs.
site/Build-Site.ps1turnsREADME.md,CHANGELOG.mdand everydocs/**/*.mdinto a GitHub Pages site (https://nick-vas.github.io/hyperdot/): the home page, the quick start, the label page with the labels and information sheets indocs/label/, a benchmark page with the reference runs, a docs index with each doc's first sentence and a search over titles and headings, and the changelog. It uses Markdig, the engineConvertFrom-Markdownloads, with GitHub's extensions only, so heading ids, carets and escaped pipes in tables come out as on GitHub; links to other repository files go to GitHub at the built commit. No framework and nothing from another host; light and dark colours at WCAG 2.2 AA; readable at 360 px..github/workflows/pages.ymlbuilds, checks and publishes it on every push tomainthat changes the docs;tests/Test-Site.ps1checks every page, link, anchor and label, and proves the check fails on a broken link and anchor.pwsh site/Build-Site.ps1 -Servepreviews it; docs/site.md has the one owner step (Settings, Pages, Source: GitHub Actions).The staged programme's CI check runs one job per genre and language, and only for the pairs whose game changed (every pair when the harness or the programme changed, or when started by hand). One job per language ran every genre in turn and no longer fitted its 150 minutes with ten genres; a pull request that adds one genre now checks that genre alone.
Two C# test runs at once no longer take each other's results. gdUnit4Net's adapter reaches the Godot it starts over a pipe with a fixed name,
gdunit4-message-pipe, which .NET on Linux and macOS keeps as a socket in the temp folder. Twodotnet testruns that sharedTMPDIR(twotestruns on C# projects, two staged-programme checks) shared that socket: the second run's Godot replaced the first's, both adapters reached the second Godot, and the first run failed withgdUnit4 (tests not run)("found 32 tests but ran 0") although its tests were fine. Thedotnetandgdunit4runners now give eachdotnet testa temp folder of its own through the.runsettings, in/tmpwhenTMPDIRis too long for a socket path (which made every gdUnit4 run fail before), and remove it after the run.tests/Test-DotnetTempDir.ps1runs two at once against a stand-indotnetand Godot. Windows names its pipes globally and is unchanged.The racing game in C#. Cinderloop now has its C# version (
benchmark/games/racing/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, scene tree, node names, data files, flows, bot and juice runs and log lines, with 69 gdUnit4 tests in place of the GUT ones and a Linux export only. Its race keeps GDScript's arithmetic, doubles for numbers and float vectors with the number cast where they meet, the engine'sGeometry2Dand itswrapf,posmodandroundias the engine defines them, so a race runs the same to the last bit: the bot run prints the same log lines as the GDScript one, line for line, for seed 1 and for other seeds, rival counts and starting tracks. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C# and a reference solution, five with a decoy; all passtests/Test-GameProgramme.ps1 -Genre racing -Language csharp.DESIGN.md's "As built" records the port's choices.The idle game in C#. Duskhive now has its C# version (
benchmark/games/idle/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, scene tree, node names, data files, flows, portrait layout, bot and juice runs and log lines, with 62 gdUnit4 tests in place of the GUT ones and Linux and Android exports. Glow is a double in both, worked out with the same operations in the same order and noMath.PoworMath.Login the simulation, and every number is written with the invariant culture, so the bot run prints the same 3,487 lines as the GDScript version, game times included, on a machine set to German too. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C#, a reference solution and a decoy; all passtests/Test-GameProgramme.ps1 -Genre idle -Language csharp.DESIGN.md's "As built" records the port's choices.The multiplayer arena in C#. Glimmerpit now has its C# version (
benchmark/games/arena/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, scene tree, node names, data files, flows, wire messages, bot and juice runs and log lines, the same dedicated server and soak roles, with 54 gdUnit4 tests in place of the GUT ones and Linux exports only. Both versions move in whole pixels and trace shots and steer bots with the engine's 32-bit vectors and seeded generator, so the bot matches of seeds 1-20 end alike and the bot run prints the same 485 lines, line for line. Its messages are the engine'svar_to_bytesbytes, written in managed code (a test holds them toGD.VarToBytesbyte for byte), since engine dictionaries for every message kept the server's memory climbing until the garbage collector ran; the dedicated server collects its first generation once a second, stops with 0 on SIGTERM, and passes a 120-secondsoakat 200 MB/h. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C# and a reference solution, five with a decoy; all passtests/Test-GameProgramme.ps1 -Genre arena -Language csharp.DESIGN.md's "As built" records the port's choices.The roguelite in C#. Wickerdeep now has its C# version (
benchmark/games/roguelite/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, scene tree, node names, data files, flows, bot and juice runs and log lines, the same--swarm=Nload, with 44 gdUnit4 tests in place of the GUT ones and a Linux export only. Both versions generate with the engine's seeded generator, its draws in the same order, so a seed gives the same floor and the enemies the same paths: the floors of seeds 1-20 and the bot's play of each match, and the bot run prints the same log lines, line for line. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C# and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre roguelite -Language csharp.DESIGN.md's "As built" records the port's choices.The judge's calibration runs in CI.
token-benchmark.ymlwithcalibrate: <run id>rebuilds the blind pairs of that run, checks they are the ones the owner judged (benchmark/calibration/pilot-1.jsonholds the verdicts and the answer key's hash), and has the candidate judges, cheapest first, judge them both ways until one agrees with the owner on 80% and with itself on 90%. A judgement that fails or names no choice is now an error, not "even": it fails the side-by-side run and counts as neither agreeing nor consistent, so a broken judge cannot pass.The judge's rubric rewritten from the owner's verdicts. The first calibration (Haiku and Sonnet both agreed with the owner on 53%) showed the rubric discounting what the owner values: an answer that explains the change with the context the next developer needs now counts for the work, "as small as the task allows" is gone, and work that does different parts of a task is even. A second blind set (
Invoke-SideBySide.ps1 -ReviewIdPrefix q, shown without the rubric) checks it on pairs it was not written from. On it (run 34) neither judge passes either: Haiku agreed with the owner on 56% and with itself on 81%, Sonnet on 50% and 63%, mostly by picking the same position in both orders;benchmark/PLAN.mdrecords it. Opus (runs 35 and 36) no longer depends on the order (2 flips in 31 pairs) but agrees with the owner on 53% and 69% of the two sets, so no judge is pinned yet. The owner's blind re-judge of ten pairs (benchmark/calibration/retest-1.json) agreed with their earlier verdicts on 6, and on 2 of 5 from the first set, judged under the old rubric. Against that, Haiku and Sonnet with the rewritten rubric agree with the owner on 62% and with themselves on 81% and 74%; Opus on 71% and 94%. Haiku with ten votes per order (runs 41 and 42) stays at 62% and 81%: its order bias is steady, not noise. The judge is pinned: Opus (claude-opus-5-5), by the owner's rule: at least the owner's own agreement with themselves on the re-judge (60%), and 90% with itself.cost-model.jsonprices its judgement at $0.05.The staged game programme's idle genre, Duskhive, in GDScript (
benchmark/games/idle/). A moth hive gathers glow at dusk: five producers whose prices grow geometrically, Buy 1, 10 or as many as the glow pays for, upgrades, and a dawn that trades a run's glow for embers. Every number is in data checked by thedatarunner; glow is a double printed with suffixes and two-letter groups past 2^53 and 1e36, never in scientific notation, with a tested tolerance and nopow()orlog()in its simulation code; time away is paid from the saved clock, capped at eight hours and immune to a clock set back; saves of the previous version keep their embers. The release candidate is a portrait layout for phones, tablets and the Web (a SafeArea autoload, thelayoutandtextsizechecks; English, German and French), 62 GUT tests, five flows, a bot that greets six dawns with--speed=60, juice for every event, Linux, Web and Android presets, store art, credits and a plan; its four stages, tasks and milestones each have hidden checks, a reference and a decoy, and passtests/Test-GameProgramme.ps1 -Genre idle.The staged game programme's racing genre, Cinderloop, in GDScript (
benchmark/games/racing/). Four little cars race from above on three loops of cinder road: a car on a fixed physics step whose rates are all per second (drag taken implicitly, so the top speed and a lap's time are the same at any tick rate and nothing in the simulation callsexp()), laps counted by checkpoint gates crossed in order and direction, three AI rivals braking to a speed profile of the racing line, the best lap kept as a ghost of quantised inputs that drives it again exactly, a chase camera that looks ahead and eases by the second, and keys rebound in Settings while the gamepad keeps its bindings. The release candidate has 69 GUT tests, five flows, a bot that wins the championship from the back of the grid, juice, three languages, store art captured from the game and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, several with a decoy; all passtests/Test-GameProgramme.ps1 -Genre racing -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port, which is still to come.The staged game programme's multiplayer arena, Glimmerpit, in GDScript (
benchmark/games/arena/). Up to four glimmers fight last-one-standing rounds in a walled pit, first to three; bots fill every empty slot, so tests and the bot run need no second machine, and players join and leave in the middle of a match. An authoritative server, client prediction and reconciliation in whole pixels, hits decided by the server's own trace, an in-process link that simulates the delay ENet cannot, ENet throughsend_bytes, and a dedicated server that takes part insoakwith clients that leave and rejoin. The release candidate has 51 GUT tests (ENet in one process among them), four flows, a bot run with a guest who walks out and rejoins, juice, three languages, store art rendered from the game and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre arena -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port, which is still to come.The narrative game in C#. Saltmere Crossing now has its C# version (
benchmark/games/narrative/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, scene tree, node names, story data, translations, flows, bot and juice runs, with 53 gdUnit4 tests in place of the GUT ones and a Linux export only. The story check searches in the same order, so the bot takes the same ways and its run prints the same log lines, line for line. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C# and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre narrative -Language csharp.DESIGN.md's "As built" records the port's choices.The tower defence in C#. Bramblegate now has its C# version (
benchmark/games/towerdefence/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, scene tree, node names, data files, flows, swarm bench scene, bot and juice runs and log lines, with 63 gdUnit4 tests in place of the GUT ones and a Linux export only. Paths come fromAStarGrid2Dwith the same settings, pest speeds from the engine's seeded generator, and movement keeps GDScript's mix of doubles and 32-bit vectors, so a seed plays the same battle in both: the bot run prints the same lines at the same game times, and the bot's results on every map match for seeds 1 to 10, path searches included. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C# and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre towerdefence -Language csharp.DESIGN.md's "As built" records the port's choices.Bug reports pinned on their level.
ci/godot/templates/addons/hyperdot_report_pins/, an add-on a game copies:bug_report.gdsaves the feedback key's report (user://reports/<time>.json: the line typed, the scene, the player's position and the camera's view in 2D or 3D, the seed, the commit, a screenshot), and the editor plugin pins each report of the open scene on it (a dot where the player stood, a ring where the camera was) and lists them in a Reports dock with the seed to replay. GDScript, so C# games use it too with no build.tests/Test-ReportPins.ps1.doctor's Steam names follow constants and the solution. An achievement, stat orsteam_displayvalue passed as a string constant (C#const stringorstatic readonly string, several to a line; GDScriptconst) is checked like a literal, and the solution's C# outside the Godot folder is read too, less its test projects. The C# example'sBreakoutProgressnames were invisible before; the example now keepssteam/achievements.jsonandsteam/rich_presence.vdf, whichdoctorchecks them against.placementreads limits from C# too. Aplacement.jsonlimit may name a C# file and field ("res://Tuning.cs:Reach"): aconstorstatic readonlyfield set to a number,true,false, a plain string or arithmetic on the file's other such fields (JumpVelocity * JumpVelocity / (2f * Gravity) + BodyHeight, divided as C# divides), read from the source past comments, since Godot gives no constants for a C# script. A field it cannot work out (Mathf.Pi * 2) is refused by name. The standard build reads it as well as the .NET one.The staged game programme's seventh genre: a narrative game, Saltmere Crossing, in GDScript (
benchmark/games/narrative/). A ferrywoman takes a stranger across a foggy river at night; the story is data (nodes, choices that need and change flags in the kit's criteria grammar, three endings) checked by thedatarunner, and a search the game ships finds every node and ending reachable, no dead end and no flag set but never read. Every line is a translation key in English, French and German with a length limit per row for thel10nrunner, and the story is saved at every line with its flags and history, with old saves replayed into the new form. The release candidate has 53 GUT tests, five flows, a bot that plans its way to every ending, juice, store art rendered from the game and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre narrative -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port.The staged game programme's fifth genre: a top-down roguelite, Wickerdeep, in GDScript (
benchmark/games/roguelite/). A candle-bearer goes down four floors of a crypt, each generated from the run's seed (rooms joined by a spanning tree of corridors, every cell reachable, checked over sweeps of seeds), while shades, cinder bats and tallow brutes wander until they see it and then hunt it down one shared distance field. The rules live in a plain grid simulation stepped in ticks, so a floor replays exactly from its seed;--swarm=Nadds hundreds of hunters forbench. Embers banked across runs buy vigor at a shrine, and the save keeps that meta progress and the run in progress for Continue, with version 1 saves migrated. The release candidate has 44 GUT tests, five flows, a bot that reaches the bottom, juice, three languages, store art rendered from the game and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre roguelite -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port, which is still to come.The staged game programme's sixth genre: a tower defence, Bramblegate, in GDScript (
benchmark/games/towerdefence/), one of the mid tier's three genres. Pests walk the shortest way across a grid (AStarGrid2D) from a gate to a seed store; every tower planted reroutes the pests on the field at once, and a tower that would leave the gate or any pest without a way is refused. Towers and their upgrades, pests, maps, waves and their groups are JSON checked by thedatarunner; a rule-based bot that builds a maze holds every map to a measured balance (cleared over several seeds, lost without towers); a swarm scene loads the field forbench; the save keeps each map's best stars. The release candidate has 63 GUT tests, five flows, a bot run through all three maps, juice, three languages, store art rendered from the game and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre towerdefence -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port.The card game in C#. Lanternfen now has its C# version (
benchmark/games/cards/csharp/), written from the language-neutral contract in itsDESIGN.md: the same scenes, node names, data files, flows, named phases, bot and juice runs, with 55 gdUnit4 tests in place of the GUT ones and a Linux export only. Both versions shuffle with the engine's seeded generator and score with the same arithmetic, so a seed deals the same duel and the AI makes the same choices: the bot run prints the same log lines, line for line. Its four stages carry the same 17 tasks and three milestones as the GDScript version, each with hidden checks in C# and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre cards -Language csharp.DESIGN.md's "As built" records the port's choices.The platformer in C#. Glowmoss Ridge now has its C# version (
benchmark/games/platformer/csharp/), written from the language-neutral contract in itsDESIGN.md: the same level scenes, scene tree, node names, data files, flows, bot and juice runs and log lines, with 34 gdUnit4 tests in place of the GUT ones and a Linux export only. Its four stages carry the same tasks and milestones as the GDScript version, each with hidden checks in C# and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre platformer -Language csharp. Itsplacement.jsonnamesMovement.Reachin the C# source;DESIGN.md's "As built" records the port's choices.The staged game programme's fourth genre: a turn-based card game, Lanternfen, in GDScript (
benchmark/games/cards/). Two lantern-keepers duel with wisps that strike across three lanes and rites that act once; a turn is written as named phases (Draw, Main, Clash, End) in a plain class, each transition logged and tested. Cards, decks and five rivals are JSON checked by thedatarunner, the rivals are played by a utility AI with per-rival weights, every duel shuffles from its own seed, fatigue ends every duel, and the save keeps the duel in progress for Continue. The release candidate has 55 GUT tests, five flows, a bot that plays the AI against itself up the whole ladder, juice, three languages, store art rendered from the game and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre cards -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port, which is still to come.The puzzle Frostmote in C# (
benchmark/games/puzzle/csharp), the third genre's port: the same scenes, node names, data files, levels, flows, bot and juice logs as the GDScript build, with gdUnit4 tests (45 in the release candidate) run by the kit's .NET runner. The daily drift draws from Godot'sRandomNumberGeneratorwith the same seed formula and draw order, and compares its rolls as doubles as GDScript does, so a seed gives the same level in both languages; seed 7 is pinned by the same rows in each. Its four stages carry the same 17 tasks and 3 milestones, each with hidden gdUnit4 checks, a reference solution and the same decoys; all passtests/Test-GameProgramme.ps1 -Genre puzzle -Language csharp. The C# build exports to Linux only, as Godot 4.7 cannot export C# to the Web. the C# port.Blind review and the judge's calibration.
benchmark/Invoke-SideBySide.ps1 -ReviewOutwrites the pairs the judge sees for a person instead (A and B in a seeded order, nothing naming the plugin, the key kept apart);benchmark/review-page.htmlshows them and keeps the owner's verdicts in its own store;benchmark/Get-JudgeAgreement.ps1scores the judge against those verdicts and against itself (80% and 90%, frombenchmark/PLAN.md). Self-test:tests/Test-ReviewPairs.ps1.A coverage map (docs/coverage.md, made by
tests/Get-CoverageMap.ps1): every command, documented error code, lib file, tool, skill, subagent and workflow job, with the self-tests andself-test.ymlsteps behind it and a list of gaps. It joins what the tests say (commands run, codes checked, files named) with what their kit runs reached: a run recorded underHYPERDOT_COVERAGEnow names theTest-*.ps1that started it, andtests/coverage-records.jsonkeeps each test's commands, codes and functions.tests/Test-CoverageMap.ps1(in thelintjob) fails when something has no row; thecoveragejob adds the map from that run's records to its artifact. New cases for the gaps it showed:import-failed(aproject.godotGodot cannot parse) andno-browserintests/Test-ErrorCodes.ps1,audio-clippingintests/Test-Audio.ps1 -Mix(audio-fixture/loud.tscn).Argument mistakes come back as JSON. An unknown command, a value outside a parameter's set (
-Do,-Mcp,-Profile,-Retryabove 5), an unknown flag or a word that belongs to no parameter used to be refused by PowerShell before the script started, with nothing on stdout under-Json. They now giveinvalid-argumentswith the parameter, the value, what it takes and the nearest name (-Projct→-Project). The sets stay in the param block, as[ArgumentCompletions](tab completion, not enforced while binding), checked byAssert-KitArguments;help, the skill and context checks and the coverage report read the same attributes. A flag without its value and a value of the wrong type (-Retry abc) are still PowerShell's. Self-test:tests/Test-ErrorCodes.ps1 -NoGodot.The staged programme's first pilot (min tier, 32 sessions, $1.89;
benchmark/PLAN.md): five of the eight arcade GDScript tasks were solved by every configuration, Haiku's fix-playthrough sessions ran out of time (the template now allows 1800 s), the plugin used about twice the tokens again, andcost-model.jsonnow holds the measured costs. The arcade explain-failure task asked for a bare2, which the prompt'sGodot 4.7.2already contains, so the runner refused every tier holding it; its number terms now skip digits after a point, andtests/Test-GameProgramme.ps1first runs the runner's dry run on the programme, which catches such a task before any grading.Design prompts placed.
godot-progressionsection 6: saving as a difficulty lever, pressure against stalling, sinks players want, fixed costs as a share of wealth, and charges on limited-use items shown, each ending in a number a test holds. A camera cost checklist ingodot-camera, asked for by theconcept.decisionsgate. A premise in five Ws and a story summary with the player's verbs in bold (godot-narrative, and an optional Story section in the GDD template). A turn written as named phases with a test per transition (godot-patterns). The retro asks who owns each recurring job ("What recurring job has no owner?").Intentional mistakes in
godot-game-ai(mistakes.md, a side file: the skill is at its size limit): Lars Lidén's "Artificial Stupidity" (AI Game Programming Wisdom 2) as rules with a test each: move before firing, miss the first time, be visible, poor aim on purpose, a few attackers at a time, tell the player, ease off at the end, openings on purpose. The chapter could not be read here, so only the two points the citing papers quote are marked verified;docs/roadmap.mdasks for the text.templates/ARCHITECTURE.md, the shape of a game's code on one page: autoloads (each with its decision), the scene tree, signals that cross scenes, authored versus runtime data, the save schema version with its migrations, the minimum spec and the open technical questions an ADR answers. Thegodot-architectsubagent creates it from the code with its first decision and adds what each proposal would change;/game's review flags it missing or out of step withstatus's inventory.First-session steps as stubs.
status -Jsonlists the GDD's "First session, step by step" asgdd.firstSession[](S1... from each step's number), with the flows, tests andplaythrough.jsontaggedGDD:S<n>that play it and the*.stub.jsonfiles that only stub it; a confirmed GDD warns about steps with neither, and about tags for steps it lacks. Stubs never count as a feature's tests./gamewrites the stubs (test/flows/first_session_s<n>.stub.jsonandplaythrough.stub.json, which no runner plays, so a run stays green) and a task per step; starting the task turns the stub into a failing.flow.jsonfirst.playthrough.jsonmay name the steps it plays in"covers". Self-test:tests/Test-Plan.ps1.A GDScript playtest tracker (
examples/gdscript/playtest/playtest_tracker.gd): the C# example'sPlaytestTracker, its consent rule andPlaytestFileSinkin one class. It raises the seven events oftemplates/playtest-events.jsonfrom the player's position and the game's calls, records nothing before the player agrees, andflush()appends one batch a line touser://playtests/<session>.jsonl; refusing consent deletes those files. Ten GUT tests (test/test_playtest_tracker.gd) repeat the C# cases with a fake clock and check every event against the template;godot-playtestanddocs/telemetry.mdpoint to it (the latter also had the sink's folder wrong).doctornow countsPlaytestTrackerin the code as collecting player data, so a game using it without a privacy policy is warned; the GDScript example has one (store/privacy-policy.md).GitLab CI template (
ci/gitlab/hyperdot.gitlab-ci.yml, untested on GitLab):hyperdot-testandhyperdot-exportjobs, the GitHub action's steps and inputs asHYPERDOT_*variables (ci/gitlab/Invoke-Hyperdot.ps1), in the .NET 8 SDK image, with Godot, NuGet and templates cached inside the checkout. Test results reach merge requests throughartifacts:reports:junitand coverage throughcoverage_report(Cobertura). For it,testnow also writes every runner's results as JUnit into<results>/junit/(dotnet's andgdunit4's TRX converted;junitDirin-Json).tests/Test-GitLabTemplate.ps1parses the template, holds it to GitLab's keywords and matches its report paths against what the kit writes. Docs:docs/usage.md, "GitLab CI".bench -Sweep <name>=<v1,v2,...>: one bench per value, the game getting--<name>=<value>after-GameArgs, onebench.csvrow each (labelled<-Label> <name>=<value>) and a table of p99, p50, fps, draw calls and load time against the value in the log and in-Json(sweep). A value over-BudgetMs,-MaxDrawCallsor-MaxLoadMsis marked (withinLimits,lastWithinLimits), not a failure; a run that cannot be measured fails the sweep with the new codebench-sweep-failedafter every value ran.godot-performanceandgodot-shaders-vfxuse it for particle counts and quality tiers. Self-test:tests/Test-BenchSweep.ps1(tests/bench-fixture/sweep.tscn, headless).Known-status list for add-ons (
ci/godot/addons-status.json):doctorwarns about Godot Jolt on Godot 4.7, godot-steam-audio (archived), Godot-PerfBullets (Godot 4.1 and 4.2) and py4godot (a prototype), found by their folder in any letter case or, renamed, by their.gdextensionfile name andentry_symbol. Each name was confirmed from the add-on's repository (docs/addons.md says which files).ci/godot/tools/Update-AddonStatus.ps1refreshes each entry's newest commit and archived state; the canary runs it, puts what moved in its pull request and opens an issue for what needs a person. Tests:tests/Test-Addons.ps1(detection, the refresh on made-up repositories),tests/Test-UpdatePins.ps1(the canary).The canary tracks aseprite-mcp's pins.
Update-Versions.ps1reads the commit and MCP SDK thatinit -McpAsepritewrites (lib/Init.ps1) and proposes the server's newest commit (git ls-remote) and the newestmcprelease on PyPI within the pinned major (a newer major is a note: SDK 2.x renamed theFastMCPthe server imports).-Applyrewriteslib/Init.ps1anddocs/mcp.md.Invoke-Canary.ps1tries them by starting the server throughuvxand listing its tools (-Uvx, a stand-in intests/Test-UpdatePins.ps1), without the example projects, which these pins do not touch;canary.ymlinstalls uv.A third genre for the staged game programme: the puzzle Frostmote, in GDScript (
benchmark/games/puzzle). A mote slides on ice until a wall, snow stops it, sparks open the exit: eight hand-made levels as JSON, checked by thedatarunner and held to their pars by a solver test, a daily drift from a seeded generator, undo, and a line that says when the exit can no longer be reached. Four stages with 17 tasks and 3 milestones, each with a reference solution and most with a decoy;tests/Test-GameProgramme.ps1 -Genre puzzle -Language gdscriptchecks them all. ItsDESIGN.mdis the contract the C# port follows.The staged game programme's second genre: a platformer, Glowmoss Ridge, in GDScript (
benchmark/games/platformer/). A side view of a 3D world, so theplacementrunner measures every tuft of glowmoss against the climber's reach, read from the movement code. The jump has coyote time, a jump buffer and a short hop, and moves by each tick's average velocity, so it peaks at the same height at any tick rate. The release candidate has 34 GUT tests, four flows, a bot that finishes five levels, juice, three languages, store art and credits. Its four stages carry 17 tasks and three milestones, each with hidden checks and a reference solution, most with a decoy; all passtests/Test-GameProgramme.ps1 -Genre platformer -Language gdscript.DESIGN.mdholds the language-neutral contract for the C# port.Benchmark sessions as a separate user (
-Isolate,benchmark/Isolation.ps1; benchmark/PLAN.md stage 5). Each session runs as a user made for the run (useradd;runuseras root,sudo -n -uotherwise) whose only folder is its game copy: the runner's temporary files move into a folder it cannot list, the checkout is closed to other users for the run, and Godot (or a .NET SDK in the runner's home) is copied where it can run them. Credentials pass by inheritance, nothing else of the runner's environment does. After each session its processes are ended, links out of the game are removed and the game's.gitis put back before grading. On in the Token benchmark workflow (inputisolate); on Windows or without root or passwordless sudo it warns and runs as before. Self-test:tests/Test-BenchmarkIsolation.ps1.The private field test (
-GameSource <folder>,benchmark/FieldTest.ps1,benchmark/field-test.json; stage 8):fix-mutant,write-tests,doctor-greenandbot-finishon a copy of an owner's game, under the four configurations, reported as numbers only infield-test.md. Defects are planted generically: one flipped operator or changed number in the game's GDScript or C#, in an order a seed fixes, kept only when the game's own checks find it.docs/token-benchmark.mdhas the owner's steps on Windows, anddocs/label.mda field-test table beside the label, outside the class. Self-test:tests/Test-FieldTest.ps1(both examples, with the stand-in).Two installs of one Godot take turns. Runs on one machine installing the same Godot (parallel jobs, two agent sessions) used to share the download's
.partfile and could start a half-unpacked editor.setupnow holds a lock file per Godot build while it downloads and unpacks, unpacks beside the final folder and renames it into place (a run killed halfway leaves nothing that looks installed), and stops with the new codeinstall-busyafter waitingHYPERDOT_TIMEOUTseconds. Self-test:tests/Test-InstallLock.ps1.Coverage counts the reusable workflow's jobs.
godot.ymltakes akit-coverageinput (for the self-test only): its test and export jobs then record what the kit ran and upload it, and the self-test'scoveragejob adds thezero-config,csharpandexplicit-runnersjobs to its count.Precision qualifiers in
godot-shaders-vfx: whenlowpandmediumphelp on phones, what must stayhighp, and a quoted shader using all three thattests/Test-SkillShaders.ps1compiles.Lights per mesh on phones in
godot-mobile-web. The Mobile renderer's limit, 8 OmniLights and 8 SpotLights per mesh instance, is not a project setting: it is read from 4.7.2's Mobile scene shader, which packs each instance's lights as 8-bit indices in two 32-bit words (sc_omni_lights(8)). Compatibility's two settings sit beside it.Commissioning a composer in
godot-audio(commissioning.md, from Untold History lesson 30): send something playable, say why it has to be them, hand over the adaptive plan and settle the rights.Build size breakdown on
export -Json(exports[].size,ci/godot/lib/BuildSize.ps1): the output folder item by item, and Godot's pack (a.pck, one embedded in the executable, or one in a.zip) by top-level folder and by kind of source file, with imported textures and sounds and compiled scripts counted as their sources. The log names the largest folders.tests/Test-BuildSize.ps1reads a synthetic pack three ways and a real Linux export, separate and embedded.Three
doctorwarnings, each with a case both ways intests/doctor-fixture(tests/Test-DoctorFixture.ps1):- asset files with the same content (size, then SHA-256), outside
addons/and.godot/; OccluderInstance3Dnodes whilerendering/occlusion_culling/use_occlusion_cullingis off, so they cull nothing;- a
CharacterBodyorRigidBodyscript that moves the body in_physics_process/_PhysicsProcesswhilephysics/common/physics_interpolationis off, unless the frame rate is capped at the tick rate (application/run/max_fpsorEngine.max_fps/Engine.MaxFps).
- asset files with the same content (size, then SHA-256), outside
Add-on licences without an
assets.jsonentry (doctor): anaddons/<name>/LICENSE*whose add-on code no entry covers is a warning, sincecreditsthen writes no notice for code that ships. The fix is the entry, with the licence read from the text,copyrightfrom its firstCopyrightline andlicenceFile. GUT, gdUnit4 and the git plugin are left out.Placeholders in
assets.json:"placeholder": true, with an optional"due"(yyyy-MM-dd) and"status"(neededorin-progress).doctorwarns with the list and fails for one past its due date, as for an ended quarantine;statuscounts them (placeholders:count,pastDue,entries[]) and warns about those past due. The TECH-DEBT template points at the field.doctorreports MPL-2.0 entries (file-level copyleft) as INFO instead of an unrecognised licence.MPL-2.0 in
credits(gdext and other Rust bindings): the licence text ships with the kit (ci/godot/templates/licences/MPL-2.0.txt, SPDX 3.29.0), and the notice tells players where the source of those files is, as section 3.2(a) asks. An MPL entry whosesourceis not a URL fails (source-offer-missing); a modified one warns (mpl-modified) that the changes are MPL-2.0 too.copyrightis optional for it.helpand/kit.hyperdot.ps1 helpprints one line for each command, skill and subagent, andhelp <name>the short page of one (with-Json:entries[]orentry); it needs no project. Thekitskill (/kit,/kit <name>) prints the same. The text has one source,docs/help.md;tests/Test-Help.ps1fails when a command, skill or subagent has no entry there./gamereviews design and architecture. Besides the feature marks,plan/STATUS.mdgets a "Review" section: at most five design and architecture problems with their evidence (features that serve no kind of fun, scope drift,architecturewarnings, autoloads no decision covers, subagent verdicts nobody acted on).Handoff log.
status -Handoff <subagent> -Checked <what> -Verdict <answer>appends one line (time, subagent, what was checked, verdict, commit) to.godot/hyperdot-handoffs.jsonl, keeping the newest 200;statusreturns the 20 newest ashandoffs[]. Both subagents record their handoff before replying, and/gameand/retroread the log.tests/Test-Handoffs.ps1checks it.Kit notes.
init -Agentsand-Plugincreatedocs/kit-notes.mdin the game (templateci/godot/templates/kit-notes.md): one line each time the kit gets in the way. Thegameskill and the game'sAGENTS.mdsay to append a line;/retroandweekly-reviewread it, and the weekly review proposes up to three kit changes for the owner to approve.Start with
/game. The README's quick start,docs/usage.md,docs/plan.mdand the game'sAGENTS.mdtemplate say to start every Claude Code session in a game with/game.initpins the kit's workflow at@v1instead of@main, so a kit change reaches a game only when a release moves thev1tag, and a game moves up on purpose. The docs' snippets use@v1too. The tag is created at the 0.1.0 release; a workflowinitwrote earlier keeps its ref.The Stop hook says what it checks. The README,
docs/reference.md, the hook, the plugin's description andgodot-verify-before-donesay plainly that it only checks that the tests passed after the last edit; it is not a design or code review.deck, the Steam Deck check in one command (note 15 of the question round): at 1280x800, thetextsizerunner, thelayoutrunner on the newsteam_deckprofile (anything off screen),shot, andbenchwith a 33.3 ms (30 fps) budget unless-BudgetMsis given. Every part runs even after one fails; one verdict (deck-failed) with each part's own code indeck.parts.-Scenenames the screens for all four. The parts are the existing commands and runners, run in one process.tests/Test-Deck.ps1ontests/deck-fixture.benchholds three more budgets.-MaxDrawCallsfails a scene that averages more draw calls a frame (bench-over-draw-calls);loadMs, withloadBreakdownMs(resource, instantiate, first frame), is the time fromload()to the scene's first frame, and-MaxLoadMsfails a slower load (bench-over-load-time);frameHistogramputs every frame in a fixed bucket: 120, 60, 30 and 20 fps or better, and slower. A run over several limits names them all.tests/bench-fixture/heavy.tscn(a 300 ms_ready, 24 boxes with their own materials) checks each.-GpuValidationforbench,shotandexport -Run: Godot's--gpu-validationand--accurate-breadcrumbs, and the run fails on the Vulkan validation layer's errors (gpu-validation-errors, each VUID ingpuValidation). A run that could not be validated (Compatibility renderer, headless, no layer installed) fails withno-gpu-validationinstead of passing unchecked;export -Runlaunches the build with a window for it.tests/Test-GpuValidation.ps1binds a float texture to an unsigned-integer image in a compute shader, which Godot lets through and the layer reports asVUID-vkCmdDispatch-format-07753; it runs on Mesa's lavapipe in the web job.Plan tasks and the board sync: the six bugs from the connector test.
plan -Do move,addandlinktake a board list's name as-Column("To Do", "testing", "Done" with an emoji), case-insensitive and by prefix as sync matches lists, as well as the column id;plan.jsonstores the id. A name that is neither fails withinvalid-argumentsand lists both.plan -Do remove -Id <task>deletes a task. Its id is never given again (lastTaskNumber), and its card goes on the plan's archive list, which the nextplan -Do syncarchives (sync.archived).- A card a person adds on the board becomes a task in its list's column on
plan -Do sync(sync.imported). A card the kit made for a task no task links now (plan task <id>in its description) is reported, not imported. plan -Do syncrecords the board's column (boardColumn) of a task it moves; the self-test now checks it.move,removeandlinkreturntaskwith-Json, likeadd.
plan -Do reopen -Id <gate>opens a manual gate marked done again, without editingplan.json(note 13). An automatic gate is refused withauto-gate: it opens by itself when the project stops meeting it.Plan gates for what was prose.
concept.riskswantsdocs/RISKS.md;concept.budget(docs/BUDGET.md) is the first optional gate ("optional": true: listed while open, withoptionalinnextActions[], but it does not hold its phase back);beta.placeholdersuses a new check,placeholders, met when noassets.jsonentry has"placeholder": trueand the Placeholders table ofdocs/TECH-DEBT.mdhas no row (open while neither file exists).file:<path>checks now want a file with something in it (or a folder): an empty file no longer meets a gate. A plan made before keeps its gates (plan.json is the game's);godot-game-planoffers to add them.plan -Do init -Profile jam: a plan for a game jam of 2 to 9 days (ci/godot/templates/plan-jam.json), five phases sized in days (timeboxDays, for a 7-day jam) with the gates ofGDD-jam.md's day table (jam.platformfirst: "browser build?").plan -JsongivestimeboxDaysandelapsedDaysbeside the weeks, PLAN.md sizes jam phases in days, and a jam phase over its timebox warns in days.The
placementrunner (lib/Placement.ps1,tools/placement.gd):templates/placement_check.gdon every level aplacement.jsonnames, each limit read from the GDScript constant it names, with no test to write. One case per scene with its findings; the summary per group, exemptions and wayfinding inplacement/placement.txt. Selected whenplacement.jsonexists.tests/Test-Placement.ps1runs it on the fixture after the GUT path, and with a missing constant and a limit of the wrong type.The
datarunner checks soft-locks, sinks and translations.- A table of
"kind": "softlock"holds levels as areas, passages, pickups, supplies and goals, and the runner searches each the way Example.Core'sSoftLockCheckdoes, with the same counterexample text, so GDScript games get it too;SoftLockTable.Loadreads the same file in C#. The ten levels ofsoftlock-examples.jsonrun in both. "economy": { "currency", "rate" }on a table of money flows fails a currency with a source and no sink, and, when the currency is aref, one no flow moves (EconomySim.WithoutSinkchecked it in code only)."locales"on a responses table fails a line missing a locale's text or voice file, or naming a locale the table does not list;ResponseTable.Load(..., locale: "fr")reads them, and the C# example's barks are in French too.- An unknown
kindnow lists both kinds.
- A table of
Playtest telemetry from a real level in the C# example.
MainraisesPlaytestTracker's events from each floor (deaths with the floor as checkpoint, the upgrade taken as the item found, a floor's time as finished, failed or quit),DiagnosticsaddsPlaytestEventsto its schema, and a playtest build (the custom featureplaytest, or--playtest) writes its batches with the newPlaytestFileSink, one<session>.jsonlline a batch, every 30 s and on quit, forhyperdot.ps1 playtest.DiagnosticsTestplays a floor and checks the file gets the events only after consent.The maths conventions pinned in the C# example (
game/test/gdunit4/MathConventionsTest.cs): on Godot's types, a positive yaw turnsVector3.Forwardto the left,Right x Upis +Z and the book's cross product has area 26.94; and where Example.Core'sSystem.Numericsdiffers (no forward axis, matrices composed left first).godot-mathpoints to it.DifficultyDirectorin the C# example (Ai/DifficultyDirector.cs): dynamic difficulty from a window of attempts, with a dead band, one bounded step at a time and the window emptied after each change, so two changes are always a window apart. In 600 simulated attempts it changed 20 times where moving on every result changed 500 times and reversed 311.godot-progressionpoints to it.The C# example's replicator packs bits and keeps to the client's rate.
GhostFormatgives each state group ofGhostReplicatorits own width (a ghost's creation: 14 bytes against 27 at 4 bytes a value) andGhostReceiverreads the packed payload; a value too wide for its group throws before anything is marked sent.LinkBudgetholds the packets a second and bytes a packet the client asked for, capped by the tick rate and the server's uplink;ReplicationTestschecks that no packet and no second carries more than was asked, through two changes of rate.The C# example draws from
DeterministicRandomeverywhere a run must repeat.Steering.WanderandAim.Scattertake it byref,PacingDirectorandResponseSystemtake one at construction (the director exposesRandomStatefor saves), asgodot-game-aiasks;DeterministicRandom.NextDoublereplacesEconomySim's private copy.The Hyperdot label (
docs/label.md,benchmark/Get-HyperdotLabel.ps1,benchmark/label-scale.json), modelled on the EU energy label (Regulation (EU) 2017/1369; washing machines, 2019/2014):- an agent-efficiency class from A to G, from the Agent Efficiency Index: tokens per solved task over a standard, per task, geometric mean, × 100, with the washing machine's thresholds;
- a minimum requirement (half the answers pass);
- a product information sheet and an SVG label per configuration (model, with or without the plugin), and a tested class;
- verification as Annex IX does it: one unit, then three more whose mean decides;
- a rescale review when 30% of what is rated reaches class A;
- a new scale reports whether class A starts empty.
Scale 2026-10 was set from 216 sessions of 0.1.0. Haiku 5.5 rates D (AEI 74.2, 96% of answers pass), Sonnet 5.5 F (92.8, 54%, nearly every failure over the stated word limit). The plugin makes both worse on these tasks, which are about Hyperdot's own code.
The game programme (
benchmark/game-benchmark.json): five tasks on a small Godot game, built fromevals/and made deterministic (explain a failing test, fix a bug from a player report, add a feature with tests, write tests that catch planted bugs, expose a value to the editor). Each session works in its own copy of the game with Bash, Edit and Write, and is graded afterwards by the kit's owntest: the game's tests and hidden ones, files that must not change, and five mutants its tests must catch. The label now has two classes per version, tool efficiency and game-making efficiency (-Programme tool|game), each with its own standard tokens.tests/Test-GameBenchmark.ps1checks the grading with a stand-in that does every task well and badly.CI pipelines, sanity pass.
- The web job's 11-minute install of Playwright's system packages (Ubuntu's mirror at 35 kB/s) now comes from the
Actions cache, through
.github/actions/apt. That action replaces.github/actions/ffmpegand also serves ffmpeg and the evals' sandbox. - A push to a branch with an open pull request no longer runs Self-test twice, and a newer push cancels an older run (not on main).
- The game benchmark's self-tests have a job of their own, with Godot set up for them; before, the staged check had
no
GODOT_BINthere. - Four lint steps ran no-Godot parts of tests that run whole in later jobs; they are gone.
- A second
doctorrun on Windows is gone. - The inline version-update check moved into
tests/Test-UpdatePins.ps1. - Three job comments sat above the wrong job.
- The runner lists in the workflow and action inputs were missing eight runners.
- The web job's 11-minute install of Playwright's system packages (Ubuntu's mirror at 35 kB/s) now comes from the
Actions cache, through
Judged grading for the game programme: a task can be scored by a pinned judge model against a rubric (median of three), and
benchmark/Invoke-SideBySide.ps1judges each model's work with and without the plugin blind, both ways round. The plugin's win rate becomes a quality factor on its index (Get-HyperdotLabel.ps1 -Preferences).tests/Test-GameProgramme.ps1checks every staged task without a model: the planted defect is caught, the reference solution passes, the decoy fails.The staged game programme, stage 1 (
benchmark/PLAN.md): the benchmark runs programmes made of genres, stages (prototype to release candidate), languages and task templates, chosen by a tier (min under $10, mid under $50, max) and narrowed by genre, stage, language or task. A stage is built from the genre's whole game. Milestones take a game to the next stage. The runner estimates a run's cost (benchmark/cost-model.json), refuses one over its ceiling, and stops starting sessions once the real cost passes it. The workflow runs all four configurations in parallel after a dry run of each.Token benchmark: a grader that cannot be fooled.
- Whole-word terms,
re:regular expressions,mustAddfor a diff's added lines, forbidden commands found where a statement starts. Markup is not counted as words. - A spec whose required term is in the task's own prompt is refused.
- Sessions run in a copy of the repository without the benchmark, so they cannot read the expected answers.
- Only an answer that never came is retried. A run with an ungraded session exits 1.
- Profiles rotate so no profile always meets a cold cache.
maxCallsholds with retries. - CI-PS-003 replaces CI-PS-002, which needed the spec. CI-PS-001 and CODE-PS-001 no longer require a word good answers do without.
- Whole-word terms,
Coverage:
HYPERDOT_COVERAGEmakes the kit record the commands, functions and error codes a run reaches.tests/Get-KitCoverage.ps1reports them.- Every self-test job collects them, and a
coveragejob fails below its floors. - The first full run found 27 of the 50 documented error codes raised by no test.
tests/Test-ErrorCodes.ps1raises them.
An adversarial review of every area (core, planning, measurement, skills and plugin, CI and benchmark, examples and docs) found 62 defects. 59 are fixed, each with a regression test. One (a fuzzy PO comment) is how Godot itself behaves, so it stays. Binding errors that print no JSON are documented, and a download race is recorded in the roadmap. Among the fixes:
- Results folder:
test -Resultsnaming a folder inside the project deleted it; nowunsafe-results-dir. - GUT: a test script that fails to parse left the gut runner green.
- Solution detection: outside a git checkout,
detectpicked the C# example's csproj instead of its solution, so 552 of 580 tests never ran. A solution that lists a project of the same name elsewhere was also taken. - Stop hook: any passing
testrun satisfied it (-Runners none, a-Filter). It also missed deletions, commits, non-ASCII names and data files. - Board sync:
- undid a local
plan -Do move; - duplicated cards after a failure halfway;
- dropped a custom list mapping.
- undid a local
- Plan and status:
- the
testsgate and doctor counted the data and l10n runners as tests; statusfailed outright on a plan problem.
- the
- Measurement:
- the palette check missed off-palette colours close together;
shotoverwrote pictures of scenes that share a file name;bench -Seconds 0passed any budget andaudio -Mix -Seconds 0hung;- the hitch count was capped at 50;
- CSV numbers followed the machine's culture.
- Data and soak:
datacomparedenumandpatternwithout regard to case;- soak metrics in scientific notation were misread.
- Error codes and logs:
- a game printing "Error:" failed with an empty error list;
- paths with brackets broke a GUT upgrade;
- paths with spaces lost their failure location;
- the time limit was not enforced on a program that closed its output.
- Release and canary:
- a tag push would have published the C# example as the kit's release;
- the canary mapped Godot 4.7 to GUT's 4.8 release;
- anyone's marker comment could stop the PR summary;
- a fork could set the coverage baseline.
- Examples: the C# example's tests deleted a developer's own telemetry consent and saved key bindings.
New self-tests:
Test-Detect,Test-InstallAddon,Test-StopGate,Test-ResultsDir,Test-HyperdotLabel,Test-ErrorCodes.- Results folder:
Versioning: the first Hyperdot release will be 0.1.0 (Semantic Versioning; 0.x while it is used on its first real game, 1.0.0 once the criteria in
docs/roadmap.mdhold).plugin.jsongoes from 0.4.0 to 0.1.0 with the new name.Licensed under the Apache License 2.0 (
LICENSE,NOTICE); before this the repository had no licence. The files a game receives (ci/godot/templates/, the starter testsinitwrites) are MIT No Attribution (ci/godot/templates/LICENSE.md).NOTICElists the third-party parts and their licences: Sfxr (Apache-2.0 and MIT), the University of Washington genre vocabulary (CC BY-NC-SA 4.0, with permission), Wikidata genres (CC0).README: a mascot logo (
docs/assets/hyperdot-logo.svg, a muscular robot in wraparound sports sunglasses, flat clip-art style), a one-line pitch, badges, a sample of the JSON an agent reads, collapsible prerequisites and FAQ, and a licence and trademark section.Renamed to Hyperdot (breaking, no aliases). The script is
ci/godot/hyperdot.ps1, the pluginhyperdot, the repositorynick-vas/hyperdot, the environment variablesHYPERDOT_TIMEOUT,HYPERDOT_IGNORE_ERRORS,HYPERDOT_PLAYWRIGHT,HYPERDOT_STOP_GATE,HYPERDOT_WEB_HEADED(GODOT_BIN,GODOT_VERSIONandGODOT_TOOLS_DIRkeep their names), the log prefix[hyperdot], the run loghyperdot.logand the JSONschemavaluehyperdot/1. Error codes keep their names. Old state moves once:.godot/godot-ci-history.jsonlto.godot/hyperdot-history.jsonl, GUT's.godot-ci-versionstamp and~/.godot-cion any run; oninit, a game'sgodot-ci.ymlworkflow becomeshyperdot.ymlcallingnick-vas/hyperdot, and.claude/settings.json'sgodot-agent-kitplugin entry becomeshyperdot. The C# example isexamples/csharp(Example.sln,Example.Core, project name "CSharp Example"), so it is no longer confused with Breakout Roguelike.Docs cleanup for the first release. README: a prerequisites section (Node.js for Web runs and two MCP servers, uv, ffmpeg, a display), the
-Projectform throughout, 50 skills grouped by area, every page indocs/linked, what each command writes into a project, and a refreshed status (exports run, eval results).docs/roadmap.mdkeeps only what is open (44 KB to 24 KB): the release plan, what was decided, the open sync work (the live run waits for the repository's secrets) and three to-do groups.docs/strategies.mdis retired into the roadmap's decisions. AGENTS.md lists the self-tests once, in a table;docs/reference.mddocuments-Templatesand the environment variables.A self-test of
plan -Do sync: cards created in the right lists (a prefix match on "Done" plus an emoji), a second sync that changes nothing, a card moved on the board, an archived card, a short link as-Board, a missing list, missing and rejected credentials, and no token in the output or a URL. It runs against a stand-in service in the self-test, and live against the real API (a manual workflow with repository secrets).planworks on PCs with a day-first date format (Greek, and most of Europe): every plan command afterinitfailed with "String '10/23/2026 05:57:27' was not recognized as a valid DateTime", because the phase's start time was read back through text in the PC's culture. Stored times now go throughConvertTo-UtcTime(Common.ps1), which also keepsstatus's error history from shifting by the UTC offset.Test-Plan.ps1runsplanunder el-GR.Fixes before the first release.
benchandaudio -Mixsplit-Sceneon commas asshotdoes and refuse several scenes withinvalid-argumentsbefore any setup, instead of passinga.tscn,b.tscnon as one scene. The run log (log,hyperdot.log) now sits with each command's own results:bench-results,soak-results,audio-results, andshot's-Output, nottest-results.no-displayadvises starting Xvfb and settingDISPLAY(notxvfb-run, which breaks-Json) and prints the kit's real command.sfxno longer counts<project>-assets/...as inside the project (no../entry inassets.json). The PR summary comment pages through every comment, so a busy pull request gets its summary updated instead of a new one per run.Update-Versions.ps1fails on a pinned file that is missing instead of skipping it. Errors that fell back tofailednow carryexport-failed(an export with noexport_path, a file not created, an exported build exiting non-zero) orinvalid-arguments(an unknown runner, a badHYPERDOT_TIMEOUTorHYPERDOT_IGNORE_ERRORS);docs/json.mdlistsinvalid-argumentsas a general code and sayssoakandcreditswrite the log and history line too.textsizeandlayoutjoin the runners that collect no coverage. New self-tests:Test-SceneCount.ps1,Test-UpdatePins.ps1,Test-PrComment.ps1;Test-Sfx.ps1andTest-Audio.ps1cover the path check and the log folder.Skills cleanup for the first release: 55 skills become 50.
godot-test-frameworksmerged intogodot-test-loop,godot-ui-layoutintogodot-ui-accessibility(layout.md),godot-steam-deckintogodot-console-cert,godot-creditsintogodot-asset-pipeline, andgodot-architectureintogodot-patterns, its other sections going togodot-procgen,godot-progression,godot-multiplayer,godot-modding,godot-shaders-vfx,godot-game-designandgodot-algorithms. Contradictions fixed (Steam Auto-Cloud roots, seeded random in game AI, bot flags only in debug builds, MIT credits, hit-stop length, VRAM compression for 3D only, saving on suspend per platform, volume buses, one--capture=nohudflag); theplaythroughrunner replaces grepping for an ending;/gamewrites board cards the wayplan -Do syncdoes, and the board sync is marked experimental. Descriptions are narrower and no longer share triggers; legal, audio and game AI moved detail to side files; duplicated advice has one owner. The skill validator now checks kit commands in side files too (tests/skill-fixtures/bad-side-file).Update-Versions.ps1and the credits error name the merged skills.Evals: the cases now run with
TMPDIRon the runner's temp disk. Under/tmp, Claude Code's sandbox refused every write in a run's own folder, so no case could run Godot (run 6); with the change, Godot and GUT run (run 7).fix-score-bug'sused-kitgrader now matches the kit called by a quoted path.docs/research.mdrecords runs 6 and 7.Evals: run 5 (after the bwrap fix) found every write in a case refused as
Read-only file system, the workspace included. The setup step's sandbox probe now also needs a writable mount, the run fails when a result mentions a read-only file system, and each run's transcript is uploaded with the result (--keep-temp).docs/research.mdrecords run 5.docs/publisher-contracts.mdnow covers a second public sample agreement, cited by name with the owner's permission: Whitethorn Games' "Generic Whitethorn Service Contract" (2020), shared by its CEO for comments. What it does that the Raw Fury draft does not (services not recouped, no markup, a 24-month income term with the rights returning, ownership from inception), what to read twice (a share of gross, the pro-rata exit cost, exclusivity scope, soft words), and the developer's share at 10%, 20% and 25% of gross next to the Raw Fury draft and Nijman's benchmark.godot-legalgains the gross-to-net rule (20% of gross is 29% of net after a 30% store cut). The roadmap drops the rest of The Untold History of Japanese Game Developers, at the owner's request.init -McpAseprite <Aseprite.exe or its folder>registers aseprite-mcp (MIT) in.mcp.json, so an agent can draw, animate and export pixel art in Aseprite (batch mode, 123 tools,view_spriteto see its work). It runs throughuvxat a pinned commit with MCP SDK 1.30.0: unpinned, the server did not start (itsmcp[cli]>=1.6.0resolved to SDK 2.x, which renamed what it imports).ASEPRITE_PATHis set from the path given;aseprite-not-foundwhen there is no program there.docs/mcp.md,godot-asset-pipeline.exportruns an export again, up to twice, when Godot crashed (an exit code of 128 or more, or a negative one on Windows): Godot 4.7.2 headless aborted with 134 after finished exports 4 times in 23 runs. The crashed run's file is deleted first and the entry getsretried; an ordinary failure, a hang and a crash on every run still fail. The import and the Web debug export share the sameInvoke-GodotRetried(Test-CrashRetry.ps1).Rotation as a UI flow, from the roadmap (Elder Scrolls: Blades tested rotating mid-action, during loading and between a press and its release):
flowsgainsresize: [width, height](sets the root window's size, which headless Godot 4.7.2 handles as an OS resize: the stretch mode and aspect apply, the viewport'ssize_changedfires once and anchored Controls resize;DisplayServer.window_set_sizedoes nothing headless),hold: "action"(pressed until a later step) andrelease: "action". A flow that ends with an action still held fails, and anactionstep on a held action is refused. Each flow now starts at the project's window size: headless Godot opened a 64x64 window, so a game with theexpandaspect saw a square screen, and a resize leaked into the next flow. Bad sizes, an unknown or numericholdand areleaseof an action not held fail with their reason. Self-test:Test-Flows.ps1(tests/flows-fixture, needs Godot).From the roadmap's art to-do list:
shotchecks every screenshot against the palette table indocs/STYLE.md(every#RRGGBBin its rows). Distances are CIEDE2000 (checked against Sharma, Wu and Dalal's test pairs) with a tolerance of 3 (-PaletteTolerance; one 8-bit level moves a colour by at most 2.40); anti-aliased edges, filtering and translucency pass as blends of two palette colours, in sRGB or linear light; off-palette colours are grouped and only groups over 0.1% of the picture count, so noise does not. Each shot getspalette(offPalettePercent,blendPercent,scatteredPercent, the largest off colours with their nearest palette colour, and<name>.palette.pngwith them in magenta); it warns, and-MaxOffPalettePercent <n>fails withshot-off-palette(no-palettewhen there is nothing to check against). The pixels are read byci/godot/tools/Palette.cs, compiled withAdd-Type(no Godot, no Python; about 0.3 s a 1080p picture). The style guide template says the table is read. Self-test:Test-Palette.ps1(-NoGodotfor its synthetic part); method and measurements indocs/art.md.Playtest telemetry, from the roadmap's Valve list: the events
godot-playtestnames (stuck,revisit,solved_but_stayed,item_found,death,hint_requested,level_time, each with level, position and level time) as a ready schema,ci/godot/templates/playtest-events.json, and in Example.Core asPlaytestEventsfor the existingTelemetrySchema(consent, no free text).PlaytestTrackerraises them from the player's position and the game's progress calls: a stall is no progress and no new ground for 120 s, a revisit is re-entering a cell after 10 s away, solved-but-stayed is still near a solved puzzle 30 s later (PlaytestTests, with a fake clock). New commandplaytest -Sessions <folder>: reads the session files playtest builds wrote (.json,.jsonl; repeated batches counted once, broken files and events that do not fit listed) and writes per-level counts and medians (level time, deaths and stalls per session, items found) and a PNG heat map per level and event type, alone or over a level screenshot that the newplaytest.jsonplaces in the world. The PNGs are drawn byci/godot/tools/Heatmap.cs, compiled withAdd-Type, so no Godot is needed. New error codesno-playtest-sessionsandinvalid-playtest-config;-HotspotCellalso sets the maps' cell. Self-test:Test-Playtest.ps1withtests/playtest-fixture.From the roadmap's Valve list ("never a soft-lock",
docs/valve.mdlesson 30): Example.Core gainsSoftLockCheck. A level is written down as areas, passages (one-way, needing an item held, or using items up once: a key, three rounds for a cracked wall), one-time pickups, supplies that top an item back up (Portal's box delivery tubes), items that can be lost at any moment, and goals. A breadth-first search over area, items held, pickups taken and ways opened (packed into 128 bits, capped bymaxStateswith a clear error) and a backward search from the goal find every reachable state the goal cannot be reached from, and return the shortest counterexample ("pick up key in Hall; use key on closet door, go Hall -> Closet. Stuck in Closet, holding nothing").everyItemCanBeLostis the stress test. A game's test callsSoftLockCheck.AssertNoSoftLock(level);godot-playtestgains a section on it. WithLookTrigger, the roadmap item is done.Localization, from the roadmap's to-do list: the
l10nrunner gains a seventh case,missing glyphs, a glyph-coverage check per locale without a display. It reads every translated string from the CSV and PO tables (an imported, compressed.translationlists no keys, measured), drops placeholders, BBCode tags and invisible characters, and runsci/godot/tools/glyphs.gdin headless Godot to check each character withFont.has_charagainst the default font (the project theme's,gui/theme/custom_fontor Godot's Open Sans) and every font of a.trestheme, fallbacks included. Each finding names the locale, font, characters with code points and up to five keys; characters only aSystemFontcould draw are asystem-fontwarning (they depend on the player's OS), andl10n.json'sglyphIgnoreFontsleaves out fonts that never draw translated text.test -Jsonaddsglyphsto the l10n entry ofrunnerResults. Measured on 4.7.2 (docs/localization.md):has_charwalksFontFileandFontVariationfallbacks but never the system fontsallow_system_fallbackdraws from. Fixture:tests/l10n-fixture/glyphs(text-only bitmap fonts, no font file committed);tests/Test-Localization.ps1gains-NoGodot.Dialogue tables, from the roadmap's Valve list: a
data.jsontable of"kind": "responses"holdsResponseSystem's rules (id, who, concept, criteria, lines with optional voice files, then, remember, once), and thedatarunner fails criteria syntax errors with the column, athenno rule answers (across all responses tables, with the near name), voice files that do not exist (and lines without one when"voiced": true), rules with the same who, concept and criteria, and criteria that contradict each other; a fact read but never remembered nor listed infactsis afact-never-writtenwarning."type": "criteria"checks the grammar in any table. Example.Core gainsResponseTable.Load(rules from the same JSON, every bad row reported at once),Rule.VoicesandRule.VoiceOf, and one strict criteria grammar,CriteriaSyntax(Criterion.Parseno longer acceptsa=ora=1;b=2as one criterion); 37 shared cases incriteria-examples.jsonkeep the C# and PowerShell parsers in agreement. The C# example has a green dialogue table (game/data/barks.json), andtests/data-fixturea broken one per check.Design and production practice. The GDD template gains audience and expected age rating, a core fantasy, the loop at three scales (moment, session, playthrough), the first session step by step (for flows and
playthrough.jsonmilestones), world rules, what failing costs, content counts and length, optional modes, open questions and a change log; the parsed parts (pitch,### F<n>features) are unchanged. Newtemplates/GDD-jam.mdand a jam mode ingodot-game-plan(days, not weeks; "browser build?" first, since Godot 4.7 cannot export C# to the Web), with a concept risk log, budget and runway categories, a business model and fairness rule, and sharper alpha and beta exit criteria (a placeholders table intemplates/TECH-DEBT.md, bug classes A and B).godot-store-pagegains a marketing cadence and a release ladder;godot-legala checklist of other agreements (unpaid teams, the studio as contractor, the game's own source licence, tabletop rules text: SRD 5.1 under CC BY 4.0 or OGL 1.0a, checked at Wizards of the Coast's SRD page) and parody permissions;godot-narrativecharacter sheets, events from the player's relationships and quest templates asdatatables;godot-game-designcomparable-game teardowns, world size by traversal time and Bartle's player types kept apart from MDA. Untold History read again: lessons 16-39 indocs/studio-lessons.md(quotes checked word for word), each placed in one skill line where it adds something.From the TRIBES networking paper, Mathematics for Game Developers, a Unity performance checklist and Adam Sawicki's GPU debugging talk: Example.Core gains
BitPacker(BitWriter/BitReader: bools, ints in the bits their range needs, floats quantised in a range; a reader that disagrees with its writer throws) andEventStream(TRIBES' events in the same packets as ghost state: numbered, a lost packet's events resent ahead of newer ones, and an event naming an object sent only once its creation is in the packet or acknowledged; at 20% loss, 0 events before their object, 11 without the wait), plusEconomySim(currency sources and sinks per hour, seeded over 10 to 1000 hours, currencies without a sink, hours a player ran short). Skills: physics interpolation, events with state, bit packing and client-set rates ingodot-multiplayer; the 3D turn direction, the cross product as an area and the exercise key's errors ingodot-math(its worked examples match, its answer key does not); Godot 4.7 counterparts of the Unity checklist ingodot-performance;--gpu-validation,--gpu-abort,--accurate-breadcrumbsand--single-threaded-sceneingodot-diagnose; RenderDoc labels ingodot-debug-tools; currencies ingodot-progression. What could not be run or checked here (Vulkan-only flags, shader precision, Mobile light limits, dialogue tool licences) is indocs/roadmap.md.Publisher contracts: Jan Willem Nijman's red flags from his comments on a 2020 publishing agreement draft (
docs/publisher-contracts.md, clause by clause with what to ask for;godot-legalsection 6): markups and fixed splits, recoup before any revenue, one-sided termination and breach clauses, unpublishing, reserves, sequel fees, and a worked example of what a 15% markup and a 50/50 split cost against his 70/30 benchmark.Add-ons and GDExtensions (
docs/addons.md, skillgodot-addons,ci/godot/lib/Addons.ps1): the state of 25 popular add-ons on Godot 4.7, cross-checked with garciamarquez.dev's ranking.doctor's GDExtension check now picks each library as Godot does (measured on 4.7.2: every tag of a key must be a feature of the build, the most tags wins), for each preset's release and debug builds and Android ABIs, with paths relative to the.gdextensionand multi-line[dependencies]. Before, it saw onlyres://paths, so the official template's and Debug Draw 3D's libraries were never checked, and a build no key fits (Godot exports it with exit code 0 and no library) passed. New: an editor-only extension exported,compatibility_minimumand_maximumagainst the project's Godot, the Godot Jolt extension on 4.4+, an add-on autoload the game uses butproject.godotlacks, test add-ons shipped, andforced_dd3din a preset.doctorchecks the instructions every agent session loads (IBM's context engineering: stale context poisons every session):AGENTS.md,CLAUDE.mdand their@imports. It warns about kit calls with a command or flag the script does not have (read from its own parameters), files andres://paths that do not exist, imports that load nothing, and files over 200 lines; lines kept from the kit's template are skipped.tests/Test-Context.ps1also holds the template, skills and docs to the real flags. The kit's ownAGENTS.mdnamedlicences/without its folder.Evals: bwrap is allowed to make its sandbox on GitHub's Ubuntu 24.04 runners (AppArmor stopped bwrap from making user namespaces, so every command in run 4 failed and its scores measured that); the workflow checks the sandbox before any case and fails when a result reports a bwrap error. Run 4's scores and what they do and do not show are in
docs/research.md.Release checks from the store, legal and Steam research (
docs/store-and-legal.md,docs/steam.md): plan.json gains an optionalreleaseblock (date,steamFeePaid,comingSoon,storePageSubmitted,buildSubmitted,nextFest,demoSubmitted,pressPreview), andplanandstatuswarn when Steam's dates cannot be kept (21 days after the fee, 2 weeks of Coming Soon, 7 business days per review with the page first, the Next Fest demo 3 or 5 weeks ahead);plan -Jsonreturns the timeline asrelease.doctorreadsstore/steam/trailer*with ffprobe (H.264, AAC, 30 or 60 fps, 44.1 or 48 kHz, up to 1920x1080) andstore/steam/tags.txt(5 to 20, one per line, no duplicates); warns when telemetry, apolicyVersionor an Android or iOS preset has no privacy policy (store/privacy-policy.mdorPRIVACY.md; the C# example now has one, written from what its telemetry records), or the policy does not say the version the code asks consent for; and checks the Steamworks files a game keeps insteam/against its code with a new VDF reader (ci/godot/lib/Steam.ps1): rich presence tokens set assteam_display, achievement and stat names againststeam/achievements.json, and steamcmd app build scripts (a numericAppID, aFileMappingper depot, no secrets, noSetLive "default", nosteam_appid.txtuploaded).CI, more from GameCI's documentation:
export -GameVersion autoreads the version from git (the nearestv*tag and the commits since:1.2.3.4,1.2.3+4.gabc1234;0.0.0.<commits>without a tag) and stops withshallow-checkoutin a shallow clone, before Godot is set up. Any-GameVersionalso sets Android presets'version/codefor the export only (major*1,000,000 + minor*1,000 + patch,gameVersion.androidVersionCode). The action outputsversion,android-version-codeandbuild-path, keeps Git LFS objects (lfsinput) and Android's Gradle caches in the Actions cache, and finds export templates on macOS;setupdownloads the macOS build of Godot instead of stopping.godot.ymltakes optional signing secrets (Android keystore, Windows certificate, macOS certificate and notarization key) and anenvironmentfor its export jobs, agame-versionfor runs that are not for a tag, and sends iOS presets tomacos-latest. New page:docs/self-hosted-runners.md. Self-test:Test-GameVersion.ps1.Audio, from the roadmap's to-do list: a mono option after all.
AudioEffectStereoEnhancewithpan_pullout0 on Master makes each side (L+R)/2, measured in the engine bytests/Test-MonoAudio.ps1(left-only tone 0.353/0 becomes 0.177/0.177, centred unchanged, opposite phase cancels), sogodot-audionow gives the recipe for Xbox Accessibility Guideline 105. Example.Core gainsVoiceBudget: a global voice cap with categories, priorities, oldest-first stealing and protected categories, the part Godot leaves to games.From the roadmap's to-do list: Example.Core's steering gains
AlignmentandCohesion(withSeparation, a flock: 30 boids head the same way within ten seconds without overlapping),FollowPath(Reynolds' corridor following, stopping at the end) andAvoidObstacles; andLookTrigger(Valve's look target with a fallback timer: fires when the player has looked at a point long enough, or when time runs out). A new architecture rule,nondeterministic-sim, flags platform maths,System.Random, global random, clocks, per-process hashes andDictionaryiteration in the foldersarchitecture.jsonlists assimulation.validatefails a.tresthat keeps a key its class no longer has (a renamed export, whose value Godot drops on load).Valve, from its own public material (talk slides, the 2012 handbook, the Cabal article, seven games' developer commentary;
docs/valve.md, 115 quotes checked word for word): Example.Core gainsPacingDirectorandIntensity(Left 4 Dead's AI Director: build up, sustain the peak 3-5 s, fade, relax 30-45 s; pacing, never difficulty) andResponseSystem(the dialogue rule database of Left 4 Dead 2, Portal 2 and Dota 2: a flat query, most criteria wins, random ties, memory that expires, follow-ups looked up when a line ends, rules that remove themselves). New skillgodot-playtest; Valve's process ingodot-game-plan; story that serves play and dialogue rules ingodot-narrative; scarce-but-never-empty resources and worst-case drop streaks ingodot-progression; readability rules in theSTYLE.mdtemplate.The second-pass test features from Croteam's CI talk: a
playthroughrunner (playthrough.json: the game's bot plays at a fixed 60 fps of game time and must log every milestone in order, the ending last;smokepassed a bot stuck in the first room), and the plan gateproduction.playthroughis now checked by it (runner:<name>, a new gate check).smoke -FixedFpsruns smoke at fixed game time.shot -Baseline -MaxChangedPercentfails a changed screen with the new codeshot-changed.statusreportstestDuration(the median of recent passing full test runs against the ten before) and warns overtestBudgetSecondsinplan.json(900 in new plans) or when runs grow by half.Test-LibNames.ps1fails when two lib files define the same function (status had calledAudio.ps1'sGet-Medianinstead of its own).Blizzplanet's interviews (69 posts, 2002 to 2014: Mists of Pandaria's developers, Hellgate: London, the World of Warcraft card game, PopCap, voice actors, tie-in writers, mod teams;
docs/studio-lessons.md):godot-progression(rewards that become chores, nothing missable, pity and consolation, difficulty tuned on enemies and tested with the strongest stats, update cadence) andgodot-narrative(a bible, timeline, canon tiers, reserved reveals and decisions in the repository; voice recorded after content lock). Thedatarunner gainstotals(what a group's rows add up to must reach a number or another table's field: the zones that left players 10% short of the next level) andnames(proper nouns one or two letters from a canonical name in dialogue, translations and scenes).sfx: placeholder sound effects from a seed (coin, laser, explosion, powerup, hit, jump, blip), so a prototype has sounds on day one. bfxr2's Bfxr synth ported to C# (ci/godot/tools/Sfxr.cs, Apache-2.0 and MIT) and compiled into the session, so it needs no Godot; the same seed gives bfxr2's sound sample for sample. WAVs at-PeakDb(-6 dBFS),.bfxrfiles bfxr2's editor opens,-Varyfor variations of one sound, and anassets.jsonentry.Google for Games' open source (Agones, Open Match, Quilkin, Open Saves, clean-chat, the GenAI demos; Apache-2.0;
docs/googleforgames.md), without their Google Cloud setup:godot-serversandgodot-llmskills; Example.Core gains a server lifecycle with a health watchdog, Agones' HTTP SDK, join tokens for Godot's authentication step, a matchmaker, a rate limiter and chat moderation.soakstops the server with SIGTERM at the end and reportssoak.stop(headless Godot dies at once with 143 unless the game handles it; C# can);-RequireCleanStopfailssoak-unclean-stop, and-StopGraceSecondssets the wait.CI, from GameCI's documentation: the action's cache keys name the Godot build (.NET or standard) so a repository with both no longer restores the wrong one, the import cache's key covers the source assets (a
.importfile does not change when its picture does), and Godot, its templates and the import cache are saved when the tests fail too.godot.ymljobs stop aftertimeout-minutes(60); the self-test's after 45; actionlint is pinned (1.7.12). Tags with a hyphen are published as pre-releases; pull requests from forks get a notice instead of a misleading PR-comment warning.doctorfails on Git LFS pointers left in place of assets, committed keystores, certificates andconfig.vdf, names Windows cannot create and paths that differ only in case, and warns onres://paths whose case differs from the file.Test-DocLinks.ps1checks every link and quoted path in the docs and skills. The self-test installs ffmpeg through.github/actions/ffmpeg, which keeps its packages in the Actions cache: Ubuntu's mirror took 12 minutes for them in one run.Algorithms (TheAlgorithms/C-Sharp, GPL-3.0, studied and measured, not copied; its MIT explanations read too;
docs/algorithms.md): agodot-algorithmsskill; Example.Core gains a Dijkstra map for crowds and fleeing (DistanceField), region labelling and union-find (Regions,DisjointSet) and "did you mean" (Suggest). Thedatarunner reports loops among prerequisites ("acyclic": true) and names the near id, enum value, column or table for a typo;test -Runnerssuggests the runner a mistyped name meant.Fixes found by the first CI runs after the GDC work:
test -Filterno longer fails when the filter leaves out every gdUnit4 test (they were counted as found but not run); a successful command now exits 0 explicitly, instead of leaving the exit code of its lastgitcall (128 in a repository without commits), which GitHub's PowerShell steps report as the step's result.GDC talks: 45 talks turned into a pull request each and 76 folded in as a line or two, each read in full from its transcript; the index, with what the kit took from each, is
docs/gdc/README.md.test:failureDeltanames failures that are new, still failing or fixed since the last run of the same scope;-Retry <n>reruns a failed runner and lists what passed only on a retry inflaky[];quarantine.json(owner, end date) keeps a known-flaky test from failing the run without hiding it (invalid-quarantine);statusreports repeat offenders and quarantines. Godot error lines become error keys (numbers and line numbers taken out) recorded with the commit in the run history,engineErrors[]items get akeyand their file, andstatuslistsrecurringErrors[]with when and at which commit each was first and last seen.setup: a failed Godot or template download stops withdownload-failed.- Runners and commands:
benchhotspots (where a level is slow),soak -JunkPps(when an ENet server falls over),shot -ColorVision, a subtitle size check intextsize,audio'sonsetMsfor late action sounds,layoutmeasures TouchScreenButtons and an opt-insmall-controlminimum (minControlDp), andl10nchecks length limits, translation remaps, localized voice, tables Godot cannot read as UTF-8 and Chinese locales without a script. doctor: commissioned assets without their agreement, text-to-speech off when the game speaks, screen readers disabled, an incomplete press kit instore/press/, expired or long quarantines.- Plan gates:
slice.debt,slice.budget,prototype.trailer(with aTRAILER.mdtemplate) andconcept.name. The placement checker checks placed objects against the game's limits and landmarks and routes for wayfinding; thedatarunner holds puzzle levels to one solution sentence and a purpose. - Tested code in Example.Core a game can copy: statistics for comparing versions, Eldritch-style mazes, GOAP costs, perception, aim and projectiles, squad decisions, a FrameBudget scheduler, forgiveness timings, stick settings, dead reckoning, a rollback session, Overwatch-style input handling, a rewind log, an input log for replays, a voice limiter, a beat clock, an assist narrator, a balance report from run data, an expressive-range map, shuffle bags and pity timers, an orbit camera, jump arcs, haptic patterns and menu wraps, touch pads.
- Skills: a new
godot-camera; most others gained sections, and the largest moved detail into reference files besideSKILL.mdto stay under 16 KB.
test: thedotnetrunner no longer passes when gdUnit4Net found tests but ran none. When its in-Godot rebuild failed or timed out (20 s by default, easily reached on a busy machine), the adapter exited 0 with no results, so a green run hid a skipped engine suite. Found-but-not-run tests are now one failure,gdUnit4 (tests not run), with the cause; the generated.runsettingsallows the rebuild 3 minutes.Phones, tablets and browsers:
layoutrunner (layout.json): each screen laid out, headless, on a portrait and a landscape phone, a tablet, an ultrawide and custom profiles; controls off screen, under the notch or system bars, or under 48 dp (touch) or 24 CSS px (mouse) fail. A game'sSafeAreaautoload gets each profile's notch, so its own safe-area code is what is tested.export -Runfor Web presets: a debug export opened in real browsers (-Browser chromium,firefox,webkit,chrome,msedge) through Playwright, served with cross-origin isolation headers only for threads builds; fails on an engine that does not start, page errors, failed requests and script errors, which release builds hide (web-run-failed,no-browser). Web exports report their size raw and gzipped. An output folder inside the project gets a.gdignore.doctor: a C# game with a Web preset, threads builds (no headers on itch.io or GitHub Pages), Android without ETC2/ASTC or an icon, C# Android without Gradle on net8.0, presets exporting into the project. 4.7.2's Android "No project icon specified" log line no longer fails an export.- Skill
godot-mobile-web;godot-inputandgodot-ui-layoutpoint to it. Measurements and sources:docs/mobile-web.md.
Store pages, legal basics, credits and release readiness:
creditscommand:CREDITS.md,credits.json(sections with translation-key headings, for a credits screen) andTHIRD-PARTY-NOTICES.txtfromassets.json, with Godot's MIT text and its third-party components read from the engine, and the .NET runtime's notices for C# games (a C# export ships none). It fails (credits-invalid) on credits without an author or a source URL, MIT, BSD, ISC, OFL and Apache entries without their copyright line or licence text, and non-commercial or GPL-family licences.exportcopies the notices next to each executable.doctorchecks Steam store art instore/steam/against the sizes in force since August 2024, at least five 16:9 screenshots at 1920x1080 or more, and the short description.- Plan template: launch gates for credits, privacy and age ratings; the store gate names Steam's two-week Coming Soon minimum.
- Skills:
godot-store-page,godot-legal,godot-creditsandgodot-release-readiness. Sources and what was tested:docs/store-and-legal.md.
The TRIBES networking model (Frohnmayer and Gift, GDC 2000) in Example.Core (
Net/Replication.cs): a connection layer that reports every packet delivered or dropped, in order, and never resends; a ghost replicator per client with scope, priority, a byte budget and per-object state masks, where lost state is resent only if no newer value was sent; creations and deletions resent until they arrive. Tested against the paper's four loss cases and a lossy run (5% of the bytes of full snapshots, no older value ever applied).godot-multiplayergains the delivery classes and how they map to Godot 4.7 (OnChangereplication is reliable: wrong for state that changes all the time).Steam and Steam Deck:
- Skills:
godot-steam(which C# binding works in Godot 4.7.2 and which does not, start-up without Steam, achievements, stats, leaderboards, rich presence, Cloud conflicts, DLC, demos, dedicated servers, branches) andgodot-steam-deck(Verified criteria, text size, defaults per device, text entry, sleep and resume). Sources:docs/steam.md. textsizerunner: every visible text measured in real pixels at 1280x800 (or the sizestextsize.jsonlists), headless; under 9 px fails, capitals under 9 px or text under 12 px warn, integer scaling that cuts the game off fails.- Architecture rules
steam-removed-apiandsteam-env-dotnet.doctorfails when a.gdextensionnames a library missing for an exported platform, and flags Steam packages that cannot work (Steamworks.NET.AnyCPU 2026.165.0 to .2 on Linux, the stale Steamworks.NET, Facepunch.Steamworks for Windows only). Runs of a game that uses Steam setSteamAppId=480, soRestartAppIfNecessarycannot end a smoke run early. - Example.Core: platform services (achievements, stats, a leaderboard, rich presence) with a local backend that
behaves like Steam, and
SaveStore.SaveResolved, which ends a cloud conflict so the next sync goes one way. godot-console-cert: PlayStation and Nintendo details are out of scope (NDA); "save on suspend" is now "save often".
- Skills:
Token benchmark (
benchmark/,docs/token-benchmark.md): tasks from this repository run as read-onlyclaude -psessions under three profiles (baseline, scoped, plan then answer), repeated, with tokens counted including cache reads and writes, Claude Code's own cost, turns, time and answer checks; medians and 90th percentiles per profile and task. A manual workflow (Token benchmark) and a self-test against a stand-in CLI.Data, determinism, modding, anti-cheat, console certification, debug tools, profiling and release pipelines:
- Skills:
godot-data,godot-determinism,godot-modding,godot-anti-cheat,godot-console-certandgodot-debug-tools;godot-performancegains C# profiling (dotnet-trace,dotnet-gcdump, starting the countersdotnet-countersneeds) and measured GC settings,godot-export-releaseversions, signing and store uploads. Sources and measurements:docs/data.md,docs/determinism.md,docs/modding.md,docs/anti-cheat.md,docs/console-cert.md,docs/debug-tools.md,docs/profiling-and-builds.md. datarunner: tables in JSON or CSV checked againstdata.json(types, ranges, enums, patterns, references between tables, unknown columns, duplicate ids), and a CSV still imported as a translation, which the export would drop.- Example.Core: a determinism toolkit (
IDeterministic,DeterminismCheck.Record,Verifyand GGPO'sSyncTest, FNV-1a checksums, a saveable random generator); the server now grants one input per tick of real time, so a client that sends extra inputs no longer moves faster (InputsRejected). Example.Core has 83 unit tests. export -GameVersion(and the action'sgame-version, passed on tags by the release workflow): the numbers go intoconfig/versionfor that export only, the whole version into the C# assembly.exportfails when a desktop C# build has nodata_*folder with the game's assembly. The action caches Godot's import cache.- Architecture rules:
untrusted-load(a Godot resource loaded fromuser://runs any script embedded in it) andculture-parse(number parsing without an invariant culture reads "0.5" as 5 on a German system). doctorwarns whenconfig/versionis not numbers and dots, and when a Windows preset does not write the game's version and icon into the exe (the C# example's now does).
- Skills:
Game AI, multiplayer, crash reports and telemetry:
- Skills:
godot-game-ai(choosing a decision structure, behaviour trees that interrupt, utility with momentum, GOAP, steering, Godot 4.7 navigation readiness),godot-multiplayer(choosing a model, prediction, reconciliation, interpolation, lag compensation, rollback, Godot 4.7 specifics) andgodot-telemetry(consent, no free text, catching C# errors through aLogger, Sentry's defaults, export and erasure). Sources and measurements:docs/game-ai.md,docs/multiplayer.md,docs/telemetry.md. - Example.Core: utility scoring, a reactive behaviour tree, a backward-searching GOAP planner and Reynolds steering; a netcode model (lossy link, server input queue, prediction, interpolation, lag compensation) tested at 50, 100 and 250 ms; a telemetry client with consent per purpose, a schema without free text, persistence, sampling, export and erasure; crash fingerprints and a session marker. Example.Core now has 73 unit tests.
- The C# example: crash reports through a Godot
Logger, with consent, installed only by the running game. soakcommand: one headless server and-Clientsclients run together for-Seconds; fails on a crash, an engine error, a process that never got ready (soak-failed) or memory that keeps growing (soak-leak,-MaxGrowthMbPerHour).- The
architecturerunner warns when ENet'screate_servergets a channel count (enet-server-channels): Godot 4.7.2 uses it as the server's incoming bandwidth limit. doctorwarns when the Sentry addon starts before the player is asked, attaches the whole log, or sends personal data.- Release exports of the C# example map source paths to
/_/, so stack traces do not carry the developer's paths.
- Skills:
Saves, localization and input:
- Skills:
godot-saves(where and how to write so a crash or power cut loses nothing, plain-data formats, migrations and golden saves, cloud conflicts decided by lineage, saving without a freeze),godot-localization(keys, CSV or gettext, plurals, fonts for every script, right-to-left, pseudolocalization) andgodot-input(actions, rebinding and saving bindings, keyboard and controller at once, prompts that follow the device, Steam Input, accessibility). Sources and what was measured:docs/saves.md,docs/localization.md,docs/input.md. - The C# example saves through a versioned, checksummed
SaveStore: written to a temporary file, flushed and swapped in with a backup; loads recover from an interrupted write or the backup, chosen by a generation counter, and put the good copy back. Golden saves from versions 1 to 3 load in CI, and tests truncate and flip a bit at every byte. - The C# example's paddle takes keyboard and controller input at once (it still plays itself otherwise), with rebinding, bindings saved as JSON, and prompts that follow the device; gdUnit4 tests cover each.
l10nrunner: fails on duplicate keys, untranslated entries (empty, fuzzy, short of plural forms) and keys the code uses that no table has. It reads Godot 4.6+?contextand?pluralcolumns.shot -Locale fr,ar,jaand-Pseudotake each scene in each language and pseudolocalized, and fail (shot-text) on text that is cut off, off screen, or has characters none of its fonts can draw.- A fresh checkout of a localized game no longer fails its first import: Godot logs "Cannot open file" for the
.translationfiles it is about to make. - The
architecturerunner'sper-frame-allocalso catches action names passed as string literals in C# (Input.IsActionPressed("jump")allocates aStringNameon every call).
- Skills:
Art and technical art:
- Skills:
godot-asset-pipeline(texture compression and pixel art, presets, atlases, Blender to glTF, naming, LODs, palettes, free libraries and their licences),godot-shaders-vfx(four tested shaders, shader cost, particles, post-processing per renderer, Low to Ultra tiers) andgodot-animation(state machines with interruption rules, blend spaces, root motion versus in place, the twelve principles). Sources and what was tested:docs/art.md. assets.json:doctorwarns about images, sounds, models, fonts and shaders with no source or licence, and about non-commercial, GPL-family and unrecognised licences. It also counts the credits owed.doctoralso warns, in a pixel art project (Nearest filter), about textures with mipmaps, Lossy or VRAM compression, and stretch settings that are not integer.validatecompiles every.gdshader, used or not. Godot exits 0 on a broken shader, and headless loading does not compile one. The log scan now also capturesSHADER ERRORlines, which name the file and line.benchreports GPU time per frame, primitives drawn, and texture and video memory.- CI compiles every shader quoted in a skill (
tests/Test-SkillShaders.ps1).
- Skills:
Audio:
godot-audioskill: a bus per kind of sound with the player's sliders kept apart from the mix, adaptive music (AudioStreamInteractive,AudioStreamSynchronized,AudioStreamPlaylist), variation and voice limits, 3D sound, reverb and occlusion, ducking and pause, and loudness targets. Its sources, from FMOD, Wwise and Unreal to the Godot source and the loudness recommendations, are indocs/audio.md.audiocommand: every sound file's integrated loudness, true peak and range (ffmpeg), by category, with warnings for files over -1 dBTP and voice or music files out of step.-Mixrecords the game's own mix with Movie Maker and fails it asaudio-off-target(more than 2 LU from-TargetLufs, default -24),audio-clipping(over -1 dBTP) oraudio-silent.doctornames the kinds of sound with no bus of their own. Thearchitecturerunner warns about sound players left on Master (audio-on-master).- Godot 4.7.2's "resources still in use at exit" line, printed when a windowed run quits while a sound plays, is ignored.
Before this,
benchandshotfailed on any game whose music played at the end of the run.
Every program the kit runs has a time limit (30 minutes;
HYPERDOT_TIMEOUTin seconds,0for none). A hung Godot is stopped with its child processes and fails with exit code 124, instead of stalling the run and the agent waiting on it.Lessons from studios, second pass: the captions of Croteam's Talos Principle post-mortem and Sasko's quest design talk replace their press write-ups, Croteam's talk on CI and automated testing is added, and Bohemia's published DayZ Central Economy files and Arma Reforger samples stand in for the wiki pages Cloudflare blocks. Folded into
godot-automation-hooks(record a solution as intent and replay it; bug reports with place and view),godot-game-design(puzzle playtests, a quest review),godot-game-plan,godot-architecture(a spawn economy as data, replicating the smallest state, the headless server, graybox then reskin),godot-procgen(two-stage rolls, one label vocabulary) andweekly-review. New gatesbeta.iterateandbeta.localization.Lessons from studios (
docs/studio-lessons.md): about 110 lessons, each with a checked quote and its link, from Nintendo's Iwata Asks and the Breath of the Wild talks, 15 Shmuplations interviews, an excerpt of The Untold History of Japanese Game Developers, GSC, Croteam, Techland, CD Projekt Red, Warhorse, Bohemia, Gaijin and 1C, 20 postmortems counted for what recurs, and two talk transcripts. Folded intogodot-game-design(how studios find the fun),godot-game-plan(what postmortems say goes wrong),godot-automation-hooks(what studios test),godot-architecture(data, simulation, networking) andweekly-review(outside eyes, pace).plan.jsontemplate: gatesconcept.decisions,prototype.variants,production.playthroughandlaunch.archive.doctorwarns about input actions bound only to a keyboard or only to a gamepad, about menus a gamepad cannot confirm or leave (Godot's defaultui_acceptandui_cancel), and about a project with no git repository or no remote.tests/doctor-fixture, written by Godot itself, checks it in CI.godot-mathskill, adapted from Denny Burzynski's Mathematics for Game Developers (LibreTexts, CC BY 4.0): its vectors, matrices and trigonometry mapped to Godot 4's C# API. Godot's conventions measured in 4.7.2 where they differ from the book's: y points down, so a positive 2D angle turns clockwise on screen; radians; forward is -Z;Bounce, notReflect, bounces off a surface. The book's worked answers match Godot's results; every call named compiles.Sources completed:
- Game Accessibility Guidelines: the 16 basic and intermediate menu, settings and input rules that WCAG and the XAGs miss
(game speed, settings remembered, one-press start, controls reminder from the input map, windowed mode, stationary
buttons, subtitles before any sound, and more) in
docs/wcag-ui.mdandgodot-ui-accessibility, summarised and linked, since the site states no licence for its text. - Tracery is Apache 2.0 (its repository's
LICENSE.MD).godot-procgenuses its minified build for writing grammars and in web exports; it cannot be seeded, so games read the same grammar JSON with the seeded expander. templates/genres-uw.json: the University of Washington gameplay and narrative genre vocabularies 1.3 (84 terms with scope notes), reused with the university's permission under CC BY-NC-SA 4.0; the GDD pitch uses them.- IGDB dropped. Marc LeBlanc's site has an expired certificate and stays optional.
- Game Accessibility Guidelines: the 16 basic and intermediate menu, settings and input rules that WCAG and the XAGs miss
(game speed, settings remembered, one-press start, controls reminder from the input map, windowed mode, stationary
buttons, subtitles before any sound, and more) in
Sources rechecked once the owner allowed more hosts:
- All 23 Xbox Accessibility Guidelines (v3.2) mapped to WCAG in
docs/wcag-ui.md. Where they are stricter for games,godot-ui-accessibility,templates/STYLE.mdandgodot-juicefollow them: text size as body height (26 px on console, 18 px on PC at 1080p), large text only from 36 or 52 px, flash area and red flashes, menu looping, focus kept in dialogs, touch targets in millimetres, no hold-to-confirm. - Other W3C documents for games (WCAG2ICT, IMSC subtitles, COGA, MAUR, XAUR, SSML) listed in
docs/wcag-ui.md. godot-game-designcorrected against the MDA paper (its own labels; the list is not complete), the 400 Project's master list (around 110 rules, with real rule names) and the gameplay design patterns wiki (real pattern names; the 2003 paper had three authors). New genre section.templates/genres.json: 48 genre terms from Wikidata (CC0) with their ids, in gameplay and setting facets, and the query that refreshes them. The GDD template's pitch names its genres.- Licences confirmed for Kenney (CC0), OpenGameArt (per asset), the Fast WFC add-on (MIT), WaveFunctionCollapse and MarkovJunior (MIT). Tracery's is still unconfirmed.
- All 23 Xbox Accessibility Guidelines (v3.2) mapped to WCAG in
Procedural generation:
godot-procgenskill: seeds derived per generator with a fixed mix (SplitMix64), the techniques and where each comes from (noise, cellular automata, rooms, Wave Function Collapse and MarkovJunior, both MIT C#, text grammars, weighted tables), checking the data before building the scene, and tests that sweep a thousand seeds. Its C# compiles against Godot 4.7.2.- Fixed in
godot-automation-hooks: it derived seeds withHashCode.Combine, which .NET randomises per process, so--seed=Ndid not reproduce a run (three launches gave three different values). It now points toSeeds.Derive, as doesgodot-architecture, which also suggested a plain XOR that collides (act 1 floor 2 equals act 2 floor 1).
Fixed: a Godot crash during import on Windows (a negative exit code such as -1073741819) is now retried like a crash on Linux, instead of failing the run with
import-failed.Game design:
godot-game-designskill: the MDA framework and its eight kinds of fun, the 400 Project's design rules of thumb, and Bjork and Holopainen's gameplay design patterns, summarised with links, plus a design review.- GDD features name the kinds of fun they serve on a
Fun:line.status -Jsonreturnsfeatures[].funand warns about must and should features without one, or with an unknown kind. The template, the C# example's GDD and/game(drafting, cutting, new features) use it.
Accessibility for menus and UI:
docs/wcag-ui.md: all 86 WCAG 2.2 success criteria read as rules for game menus, HUD and settings screens (31 apply as written, 49 in game terms, 6 do not apply), each with the Godot 4.7 property or API that meets it, read from the engine.godot-ui-accessibilityskill: the working rules (gamepad-only navigation, focus, WCAG contrast in C#, target size, screen readers through AccessKit, reduce motion, three flashes a second), with C# compiled against Godot 4.7.2.- Found in Godot 4.7.2's defaults:
ui_acceptandui_cancelhave no gamepad button, andColor.Luminanceis not WCAG's relative luminance unless the colour goes throughSrgbToLinear()first. templates/STYLE.md: the Danger colour failed its own 4.5:1 rule (4.2:1); now #F2555A at 4.9:1, with each colour's ratio in the palette and the WCAG numbers in the readability and motion rules.godot-juice,godot-ui-layoutandlookpoint at the new rules.
Look and feel (roadmap phase 4):
shot -Baseline <folder>compares each screenshot with the earlier one of the same name, inside Godot:compare(changedPercent,sizeChanged) and a<name>.compare.pngwith before, after and the changes in red.juicerunner, detected when the project hasjuice.json: plays the game headless at a fixed 60 fps with the bot's flags and checks the game's[juice] event/feedbacklines: every event must get each listed feedback within its window.tests/juice-fixtureandtests/Test-JuiceLog.ps1check it in CI.ci/godot/templates/STYLE.md: a style guide with aResolutions:line tools read;status -Jsonreportslook.- Skills:
look(writes the style guide with the user, critiques screens throughgodot-verifier, offers before and after as a multiple-choice question and records the choice) andgodot-juice(the feedback checklist and how to log it).
Architecture (roadmap phase 3):
architecturerunner, detected for every project: a static scan for fragile node paths, UI scripts writing game state, per-frame node lookups and allocations, autoload events never unsubscribed, and too many autoloads. Every rule is a warning by default (runnerResults[].warnings);architecture.jsonin the project sets rules toerrororoff.tests/architecture-fixturesholds one triggering project per rule and a clean one, checked in CI.godot-patternsskill: Game Programming Patterns mapped to Godot 4, with what the engine already provides.godot-architectsubagent: compares designs before code and records a decision (templates/ADR.md) indocs/decisions/for the user to accept.status -Jsonlistsdecisions[]and warns about proposed ones;/gameshows them and sends new systems through the architect first.
/game(roadmap phase 2):status -Json: GDD features with the tests taggedGDD:F<n>, the plan, the latest run of each command, git activity and an inventory (scenes, autoloads, input actions, TODOs), with warnings. Read-only.ci/godot/templates/GDD.md, a GDD format the kit can read;examples/breakouthas a GDD and tagged tests.plan -Do add -Feature F3links a task to a feature;plan -Do linkrecords a task's feature, board card and the card's list, or the plan's board;plan -Jsonreturnstasks[]and the board.- Skills:
game(judges each feature with evidence inplan/STATUS.md, drafts the GDD the first time, keeps the board in step through the connector with the user's moves winning, proposes next tasks) andweekly-review. - The
AGENTS.mdtemplate adds the scope rule (ask before building what the GDD does not contain) and the test tag.
Weekly canary (
.github/workflows/canary.yml, Fridays 18:47 UTC):ci/godot/tools/Update-Versions.ps1compares the pinned Godot, test-framework packages and GUT with the newest stable releases and rewrites every pin together;ci/godot/tools/Invoke-Canary.ps1tries the updates on both examples (all together, then one by one). Updates that pass become a pull request, failures an issue each, and a Godot minor without a GUT release is reported as blocked. First run on real releases: Microsoft.NET.Test.Sdk 18.11.0, Chickensoft.GoDotTest 2.0.48, xunit 2.9.3 and xunit.runner.visualstudio 4.0.1 pass; gdUnit4.test.adapter 3.1.1 fails (it needs the pre-release gdUnit4.api 5.1.0-rc5).Build diagnostics now include restore and project errors (
NU1605and the like, with no line or column), not only compiler errors.Agent efficiency, each item measured or sourced in docs/research.md:
-Quiet: Godot and dotnet output goes only to<Results>/hyperdot.log(named by the newlogJSON field); stderr drops from 7-16 KB to about 1 KB per test run on the examples.- Test failures now carry the specific
message,fileandline(GUT's bare "failed", Godot backtraces,at line N, C# stack traces) and a few lines ofdetails, so the log rarely needs reading. - Run history in
.godot/hyperdot-history.jsonlforbuild,test,export,benchandshot. - The kit is a Claude Code plugin (
.claude-plugin/): the skills, agodot-verifiersubagent for screenshots, benchmarks and export launches, and a Stop hook that keeps a turn from ending while Godot files changed after the last passing test run.init -Pluginenables it for a game;init -Agentsalso copies the subagent and fills in the kit path. retroandkit-reviewskills (manual): lessons with evidence become kit pull requests, gated by the validators and evals.evals/:claude plugin evalcases that compare the kit with no plugin, and a manualEvalsworkflow.- Skill validator: a skill may not set
modeloutside a forked subagent (it loses the prompt cache); theAGENTS.mdtemplate is capped at 4 KB; subagents' kit commands are checked too. The template lost its skill list and layout section.
doctorreportsGODOT_BIN: missing file, wrong version, a non-.NET build for C#, a non-console build on Windows.exportusesGODOT_BINwhen matching export templates are installed. Hints printed byinit,doctorandplanshow the kit's real path and-Project, andinitprints its "Next" line last.The kit no longer ships inside games:
.gdignorefiles at the repository root and inci/godot/keep Godot from importing and exporting the kit's.gdtools when it sits inside a project (a 4.7.2 export test found all four in the pack), and detection now skips folders with a.gdignore, as Godot does, so the kit's own examples no longer add GUT and flow runners to the game.The README now recommends cloning the kit outside the game and using
-Project.init -Agentsthen writes the kit's full (quoted, when needed) path intoAGENTS.mdinstead of a fragile../../path.init -Agentsreports skills that already exist as skipped instead of added.From the Breakout Roguelike case study (
docs/case-study-breakout-roguelike.md):bench: frame pacing of a scene (1%/0.1% lows, p50/p99/max, frames over 20/33 ms, hitch log, draw calls, custom monitors such as GC counts), a labelled CSV row per run, and a-BudgetMsgate (bench-over-budget).shot: PNG screenshots of scenes at a resolution, for agents to look at (shot-failed,no-display).-GameArgs: the game's own flags, passed after--to smoke runs,export -Run,benchandshot.doctorwarns when a preset's include filter ships.md/.pdfdocuments.- Skills:
godot-performance,godot-automation-hooks,godot-ui-layout,godot-architecture; thirteen pitfalls added. - Plan gates: automation flags and screenshots (vertical slice), bot balance runs (production), a measured performance gate (beta).
- The C# example scales with the window (
canvas_items, aspectkeep); a 1080p screenshot showed it stuck in a corner.
-Jsonon every command: one document on stdout, logs on stderr, stableerror.code, build diagnostics and test failures with file and line (docs/json.md).plancommand andci/godot/templates/plan.json: seven-phase solo plan with automatic and manual gates, timebox and WIP warnings.flowsrunner: declarative*.flow.jsonUI flows played headless in the real engine (press, input actions, waits, asserts on node properties).Editor-bridge MCP:
init -Mcp godot-mcpregisters satelliteoflove/godot-mcp in.mcp.json(adds only, backs up); docs/mcp.md compares it with godot-ai.init -McpDiagnostics: registers minimal-godot-mcp (GDScript diagnostics and the running game's console) next to the editor bridge; fixedinit -Mcpfailing when.mcp.jsondid not exist yet.plan -Do add|move|sync: tasks with a work-in-progress limit, and board sync (plan.json stays the source of truth).Skill quality:
ci/godot/tools/Test-Skills.ps1validates structure, budgets, discoverability and that quoted commands, error codes and versions are real; fixtures that must fail; newgodot-verify-before-done,godot-ui-flows,godot-editor-bridgeskills; original descriptions rewritten to triggers only.Nine agent skills in
.agents/skills,AGENTS.md/CLAUDE.mdtemplates, andinit -Agentsto install them.Godot 4.7.2 as the default and example target; GUT is reinstalled when the Godot minor changes (stamped copies only).
Docs reorganised: usage, reference, json, plan, strategies.
Added
- Changes add a fragment under
changelog.d/instead of editingCHANGELOG.md, andci/godot/tools/Update-Changelog.ps1assembles them at release;tests/Test-Changelog.ps1covers it. - Opus joins the staged programme as two more configurations,
opusandopuswith the plugin, markedmeasuredApart: they share a tier ceiling with each other only, so the standard four stay under the mid tier's $120.cost-model.jsonprices Opus tasks and milestones as estimates (2.2 times Sonnet, to be replaced by measured means). The dry run prices the mid tier at $43.20 for Opus and $61.65 for Opus with the plugin; no Opus session has run. docs/retro.mdlooks back over the 0.1.0 effort from the repository's records: what went well, what cost time (git's background maintenance, the ENet relay race, the usage limit that stopped run 44, CI growth, theunchangedrule, the judge calibration), numbers, lessons and what to change in 0.2. It names what the repository does not record.docs/label/holds the information sheets, JSON and label SVGs of the 0.1.0 tool programme for Haiku (D), Haiku with the plugin (G), Sonnet (F) and Sonnet with the plugin (F), rebuilt withbenchmark/Get-HyperdotLabel.ps1from the 216 recorded sessions, whichbenchmark/reference-runs/now keeps. They reproduce the recorded indices exactly, and the tested class is A (97.2).
Earlier
Interchangeable pipelines, gdUnit4Net/GoDotTest/GUT runners, coverage, PowerShell 7 rewrite with a Linux workflow, doctor,
init, validate runner, export -Run, PR comment and releases.