Repository navigation
AGI IS HERE 1.2.5
Fidelity to the original interpreters on PC, Amiga and Apple IIgs, in both look and behavior: palettes, fonts, menus, dialogs, pointer, sound and timing per platform. The CHANGELOG has the player-facing list. docs/fidelity.md records each finding with build, binary hash and addresses, and its coverage table records the evidence for each aspect on each platform.
Changes from the owner's review
- Upgrades (F1–F3). Opening an older project makes one History step, "Updated for 1.2.5": room memory, unknown-word replies and the VIEW rebuild together. A conventions stamp in the project records which rules it was examined under, so History labels no longer decide. Imports and copies keep it. Word feedback gets a static hint to count words from 0.
- VIEW mirror (F4, F5). Cel orientation reverses once, at the blit.
show.objno longer inherits a shared actor's mirror, and VIEW authoring follows the selected profile's alias capabilities. - Sound state (F6). Released 2.001 booter-sound checkpoints restore through a migration at the restore boundary. Released replay fingerprints stay byte-identical outside booter playback.
- Input owner (F7, F8, gamepad focus). One owner per right-button gesture, settled at the press. A gamepad follows keyboard focus, and a fire button held across the handoff stays stale. The PAL Amiga label reads "Original proportions".
- Polish (F9, F10). The format table and the fidelity ledger are corrected, and the MAME guard compares against the repository root.
- Pre-existing debt. SetLoop/SetCel no longer mutate orientation; the guided ghost uses the game palette; the message preview follows the running game's picture row; the admission preflight has a candidate test; the gamepad follows host focus.
- Pending-edit recovery. A failed recovery opens the last saved game, and the edits stay available as "Download pending edits".
- Whole-change review fixes. A VIEW repair survives reopening with a broken room draft; no automatic write lands over pending edits; copies and exports keep the update pending.
- Terminology. One word per concept: VIEW editor, PICTURE editor, actor, ego and hero, Priority. A glossary in
src/vocabulary.tsis checked by tests and by the Terminology table in CONTRIBUTING.md.
Changes from the second review
- R1, import preview. An older busy-opening game, public or private, stamped or not, now passes the import check and plays; the preview worker receives only the resource files, words, profile and the room-memory flag. Test:
app/test/script-size-migration-session.test.ts:597(also:535),app/test/game-preview.test.ts:13,app/e2e/legacy-import.spec.ts:13. - R2, stale VIEW source. A VIEW rebuild runs only when the stored source still matches what 1.2.4 would have built; otherwise the creator's picture stays and the source waits, inactive with its notice, until the creator chooses it. Test:
app/test/script-size-migration-session.test.ts:688,app/test/view-migration-session.test.ts:43. - R3, edition identity. Importing an archive no longer merges games with different room-memory behavior, in either order; equivalent contracts still merge, and a raw reimport keeps the stored game and its progress. If the matched edition is deleted between preview and import, nothing is written and the check repeats. Test:
app/test/game-library.test.ts:1197,:1297,app/e2e/legacy-import.spec.ts:67. - R4, automatic writes. The pending-edit check now runs inside the storage write queue, just before the durable write, so an automatic update cannot land over another page's journal. Creator writes are unchanged, and the update runs once on a later open. Test:
app/test/script-size-migration-session.test.ts:1133,app/test/project-commit.test.ts:228,app/e2e/project-journal-ownership.spec.ts:229. - R5, stale gamepad fire. A fire button held across the focus handoff stays quiet on late release and on return, with a fresh press working, on Amiga, PC and IIgs. Test:
app/test/worker-joystick.test.ts:337. - R6, delayed room menu. A Create right press whose context menu arrives after Play begins is consumed without a room action, also when the player returns to Create first. Test:
app/test/play-right-button.test.ts:55,app/e2e/create-play-right-button.spec.ts:341. - CHANGELOG. It now says only the released unknown-word fallback is upgraded; customized feedback gets a reminder.
Decisions to confirm
Each of these changes an existing test's expected behavior or a product rule. The first group is new since the owner's review.
Orientation and recovery
- Mirrored orientation (
test/priority.test.ts:234,[1,2]to[2,1]).- Before: selecting shared loops 1 then 2 in one LOGIC pass reversed the row at each selection, giving
[1,2]. - After: the row reverses once, at the blit, giving
[2,1]. - Evidence: F-VIEWS-01 in
docs/fidelity.md(2.936 InsertObj calls MirrorCell; SetCel does not). - Compatibility: a recording that selects loops twice in one pass may draw a different facing.
- Test:
test/priority.test.ts:234,test/view-mirror-boundary.test.ts:124.
- Before: selecting shared loops 1 then 2 in one LOGIC pass reversed the row at each selection, giving
- Failed pending-edit recovery.
- Before: a journal that failed to replay blocked the open.
- After: the last saved game opens and the edits are offered as "Download pending edits". Only failures that repeat leave a lasting marker; temporary ones (storage errors, a failed module load after a deploy) retry on the next open.
- Evidence:
workspace-save-recoverybrowser spec checks the notice, the download bytes and one project-update entry. - Also: while unrecovered edits for a project are pending after a temporary failure, the app makes no automatic writes to that project, including the "Updated for 1.2.5" step. The check runs inside the storage write queue, just before the durable write, not in the session; a skipped update leaves the project unchanged and runs once on a later open. The creator's own edits still save, and if they conflict with the pending edits, those stay downloadable.
- Compatibility: the journal bytes are kept unchanged.
- Test:
app/e2e/workspace-save-recovery.spec.ts:758,app/test/script-size-migration-session.test.ts:1000,:1133,app/e2e/project-journal-ownership.spec.ts:229,app/test/project-save-journal.test.ts.
- Unsaved 1.2.4 edits with a mirrored JSON VIEW source.
- Before: they replayed after an upgrade.
- After: they are download-only (the owner's lean-migration decision; a release-notes line).
- Evidence: the VIEW rebuild rewrites the source those edits were made against.
- Compatibility: nothing is lost; the edits download as a ZIP.
- Test:
app/test/script-size-migration-session.test.ts,app/e2e/workspace-save-recovery.spec.ts.
app/test/project-save-journal.test.ts, "commit lands, then the callback throws".- Before: the case rejected.
- After: it replays, because the open must not block.
- Evidence: fail-first run with the six recovery cases red before the change.
- Compatibility: the committed write is never applied twice.
- Test: the same case.
- Unstamped re-exports (
app/test/archive-formats.test.ts:97,app/test/project-formats.test.ts:55).- Before: re-exporting a released Game or Project backup that carries no conventions stamp wrote no conventions, and an earlier draft expected an inferred version 1.
- After: both write the optional authoring-conventions field at the same version, as pending version 0, so the one-time "Updated for 1.2.5" step still runs after a copy, export or reimport. A file that already has a stamp keeps it.
- Evidence: the released archives in
app/test/formats/read unchanged; the tests assert every released field is preserved. A copy of an unstamped remix with a mirrored JSON VIEW reopens with one VIEW update and its original boot unchanged. - Compatibility: additive; older files parse by omission. Released bytes and fixtures are unchanged.
- Test: the two tests above,
app/test/script-size-migration-session.test.ts:1067.
- Customized boots and undeclared checkpoint capacity (
test/script-size-migration.test.ts, around line 253).- Before: the comment and string cases still inserted
script.sizeinto a partly customized LOGIC 0 boot, and a checkpoint with no declared buffer on an unmigrated boot resumed at 200. - After: only a boot that exactly matches a released template is upgraded; a customized boot is left unchanged and gets a static hint in Game updates about counting words from 0, with no automatic edit. A checkpoint with no declared buffer resumes at its saved capacity, 50, unless the host adopts a declared size. Projects marked as legacy keep their released 200 from boot.
- Evidence: the owner's decision to upgrade exact templates and show a notice for the rest. Actual released boots still upgrade despite layout or comment differences;
test/fixtures/released-templates/holds verbatim tagged blobs. - Compatibility: a player with an old project that customized its boot sees the notice and the project is not edited; that project keeps the 50-pair buffer until the creator adds the call. Saves keep the capacity they recorded.
- Test:
test/script-size-migration.test.ts,test/legacy-room-memory.test.ts,test/project-conventions.test.ts.
- Before: the comment and string cases still inserted
- Mirrored loops in VIEW preparation (
test/view-preparation.test.ts, around line 613).- Before: a mirror of a mirror, or a mirror beyond the selected profile's alias range (loop index 4 on 2.230, loop 8 on the 8-loop mask), was refused with "pixel-flipped independent copy".
- After: the preparation writes a pixel-flipped copy of the cels for the requested facing, so the loop is made instead of refused. Successive reversals are exact, and the test checks 2.001, 2.411, 2.230 and 2.936. The 15-cel limit of packed profiles still errors.
- Evidence: F-VIEWS-01 in
docs/fidelity.md: MirrorCell rewrites the stored orientation in place, so sharing one set of cels between aliases is not stable. - Compatibility: the produced VIEW is plain AGI bytecode that every profile reads; recipes that were accepted before produce the same bytes.
- Test:
test/view-preparation.test.ts,test/view-mirror-boundary.test.ts,app/e2e/view-mirror-profile.spec.ts.
Tests and terminology
@perftiming specs.- Before: they ran in WebKit too.
- After: they run only in the perf suite, alone.
- Evidence: budgets cannot hold inside the loaded suite.
- Compatibility: none.
- Test:
npm --prefix app run e2e:perf.
- Start-over spec.
- Before: it typed right after Start over.
- After: it waits for the fresh game's enabled input line.
- Evidence: ×10 beside a full WebKit suite, twice; the race was in the test.
- Compatibility: none, the product is unchanged.
- Test: the start-over-undo spec.
- Terminology.
- Before: the in-app agent's prompts used the plain register; the Views background setting was stored as
monotio_agi.spriteBackdrop; stored eval cases name the lensesartanddepth. - After: model prompts and tool descriptions use the technical register (the technical-preface expectation changed on purpose); the background setting is
monotio_agi.viewBackground, so each viewer sets it once more; the eval replay harness maps recordedart/depthtovisual/prioritywithout regenerating stored cases. The released tutorial message "try Depth" stays, the single exception, because no tutorial resource bytes change in 1.2.5. - Evidence:
src/vocabulary.tsglossary,CONTRIBUTING.mdTerminology table; stored-case replay passes. - Compatibility: released archives, fixtures and eval records are unchanged.
- Test:
app/test/vocabulary-copy.test.ts,test/docs.test.ts:86,npm run eval:replay.
- Before: the in-app agent's prompts used the plain register; the Views background setting was stored as
Earlier decisions
Script buffer and History
- Authored games use the authentic 50-pair script buffer. Projects that relied on 200 get a one-time migration recorded in History. A host option,
adoptDeclaredScriptSize, honors a declaredscript.size. - History format v3 and host image v2. Each has one migration from the released version, and its original fixture is kept.
- Walkthrough schemas v2.
- Room capacity 39→40.
Text, dialogs and status line
- The status-line spacing, the quit wording and the
version()modal follow the original interpreters. - v19.
- Window pixel assertions are rewritten to the measured originals.
- The Tandy text attribute 0x99.
- The PC font is a recreation of the Tandy typeface, credited as a recreation.
- The About title reads "Compared with originals".
Input
- Shift+F1 sends 0x5400.
- A click on the priority screen in 2.082.
- Clicks on the IIgs f15.
- Keypad 5 on 2.001.
- Fire keys on phones.
- Ctrl and Alt during key waits.
Engine and raster
- The
view.testexpectation for priority 0. - Tape changes.
delay256.
Sound (2.001)
- The period byte in test payloads.
- Completion is reported one tick later.
Studio
- An optional recipe
paletteId.
Amiga menus
- Five behavior decisions. The amiga-menus commits list each one.
Dissolve
- Test rewrites to match the original transition.
PC display
- The PAL Amiga aspect ratio changes from 4:3 to 128:75.
- EGA only on builds 2.089–2.272.
toggle.monitoron CGA keeps RGB.- Thumbnails stay EGA.
- The recreated-font expectations are rewritten.
Evals and test policy
- Genesis eval runs compare against the template hash they received, so stored metrics are unchanged.
@perftiming specs run only in the perf suite, alone. They no longer run inside the loaded WebKit suite, where their budgets cannot hold.
Gate on the release head
Local gate on 9a075d2:
npm run check, build, bundle boundaries and the production build: pass.- Performance budgets, run alone: 13 passed.
- New and changed specs ×10 beside the suites (create-play-right-button, legacy-import, project-journal-ownership, platform-input, view-mirror-profile, guided-platform-preview, workspace-save-recovery): pass.
- Chromium: 1,196 passed when run alone. Linux WebKit: 494 of 496 inside the parallel gate; the two failing specs passed 14/14 when rerun alone.
- Inside the parallel gate, beside the check, the stress run and other jobs on the machine (load average up to 40), 13 Chromium tests timed out waiting for a game or editor to appear; all 87 tests in their spec files passed when rerun alone. An earlier timed A/B against 64deae2 showed no boot regression.
Release notes
- Unsaved 1.2.4 edits in a project with a mirrored JSON VIEW can only be downloaded after the upgrade; they are not added back to the project.
Fixed during release review
start-over-undo(WebKit, CI once): the spec typed right after Start over showed room 1, before the fresh session's first frame enabled the command line, so the key reached nothing and the start-over note correctly waited on. The spec now waits for the enabled command line. The product is unchanged; the race was in the test (proof: ×10 beside a full WebKit suite, twice).- CI browser image pinned to Playwright 1.64.1 to match the dependency update.
- Opening Create from Play on a new game could show "Changed in another tab" and pause editing. The cause was that game's own first commit landing while storage was read. A publish from this tab during that read now supersedes the check, and the older record is never installed over the newer one. A unit test covers the race.
Dependencies
- Folds Dependabot #85 and #86, plus every other outdated package: vue and @vue/compiler-dom 3.5.44, @playwright/test 1.64.1, openai 7.39, @anthropic-ai/sdk 0.135, eslint 10.13, typescript-eslint 8.72, dependency-cruiser 18.7, knip 6.42.1 and @ast-grep/cli 0.51.0.
- vue-tsc stays on 3.3.11: 3.3.13 still types template reads of non-reactive
lets asnever(as 3.3.12 did), so Dependabot skips both. TypeScript 7 waits for typescript-eslint support. - The CHANGELOG entry is dated 2026-10-20. It carries the download-only line from Release notes.
Known limits
- Released booter-sound checkpoints resume under the documented conversion policy ("Released recording migration" in the fidelity ledger's PC booter sound rows entry). Exact old sound timing is not preserved. Released combined-only sync marks are not verified; strict split-digest checks are a separate path.
- Packed 2.230: restoring replay state can lose a mirrored actor's facing. This is inherited from 1.2.4 and planned for a later release.
- Unsaved 1.2.4 edits in a project with mirrored VIEWs are download-only: the download holds raw pending edits, not an importable project.
- The CHANGELOG says only the released unknown-word fallback is upgraded; customized feedback gets a reminder.
Notes
- The AGENTS.md font sentence stays as the target rule. The IIgs fallback font gap is listed in the coverage table.
- Squash message: summarize the release in plain words.
Follow-up
logic-context-menuon WebKit: under heavy load, the wait for the lazily loaded editor can exceed 5 s.
🤖 Generated with Claude Code