218 lines
14 KiB
Markdown
218 lines
14 KiB
Markdown
# Agent log
|
||
|
||
What agents have done, newest first. Add an entry for every piece of work: the date, which
|
||
note or request it was for, what changed, the files touched, the tests run, and anything left
|
||
open or not verified. Keep each entry short; the git history has the details.
|
||
|
||
## 2026-10-23: ingot molds need no F; removing a mold returns its metal (Claude Code, with Codex)
|
||
|
||
Note: "now that the ingot molds drop the ingots, what is the purpose of F…". The owner chose no F
|
||
on ingot molds.
|
||
|
||
- `src/sim/molds.js` `ejectIngot`: when nothing over or in the mold is molten, junk and mixed
|
||
metal (as scrap) and plugs over the trough or frozen in the grate are written as loose grains
|
||
into the 4 rows under the mold; what doesn't fit waits. Slag and ash are thrown away. After a
|
||
drop or a clean-out the grate above is raked. Bars and the short stub work as before.
|
||
- `collectMold` on an ingot mold only says "Ingot molds empty themselves." Bit and tank molds
|
||
keep F. `removeMold` (every kind) gives the set metal to the bag: whole bars as bars, the rest
|
||
as scrap; molten metal is left alone.
|
||
- Text: `troughState` flaws, `info.js`, `overlays.js` (no "· F" on ingots), `pieces.js`,
|
||
`progress.js`, `notebook.js`, `docs/systems/stone-and-liquids.md`, `docs/DESIGN.md`.
|
||
- Tests: `t_molds` 60 checks (F does nothing on ingots; plate, slag and rake cases now
|
||
automatic; junk out, mixed metal out as scrap, junk waits when blocked and while molten;
|
||
removal returns bars and scrap, leaves molten metal). `furnace_play.js` adapted. All 11
|
||
headless suites and `play.py` (122) pass.
|
||
- Open: undoing a mold removal brings the mold back empty (its metal stays in the bag).
|
||
|
||
## 2026-10-23: compact build card top-left (Claude Code, with Codex)
|
||
|
||
Note: "build tool has no info box like the other tools." The owner chose a compact card.
|
||
|
||
- `src/ui/selection.js`: the build tool has a card again: Q, piece name, cost (red if short), E;
|
||
variant chips, Replace · G and ghosts waiting; one how-to line; the status line. No long
|
||
description; that stays in the hover popup.
|
||
- `src/ui/build-menu.js`: the `.bb-status` row is gone (its contents are on the card); the
|
||
variant chips are shared through `buildVariantChips(P)`. `src/styles/style.css`,
|
||
`docs/DESIGN.md`, `docs/PROJECT_MAP.md`.
|
||
- `test/play.py`: the card is visible while building with name and cost and without the
|
||
description; status and Replace · G are read from the card; no `.bb-status` (122 checks pass).
|
||
All 11 headless suites pass; `t_smooth.py`'s half-resolution check is still flaky under load.
|
||
- Shots: `shots/build-card-*` (belt and wall, both looks, 1280×800 and 900×700) look right.
|
||
- Open: at 900px wide the bottom-left hover panel still sits partly under the build bar.
|
||
|
||
## 2026-10-23: Replace is held G, not Ctrl (Claude Code, with Codex)
|
||
|
||
Note: "i see the issue was ctrl+w closing the tab… it happens for the bookmark hotkey too. maybe
|
||
change the replace key?" The owner chose holding G.
|
||
|
||
- `src/ui/input.js`: `GAME.ctrl` became `GAME.replace`, set while G is held. Ctrl no longer
|
||
does anything on its own, so WASD works while replacing. Ctrl+S, Ctrl+Z, Ctrl+wheel and the
|
||
leave-page prompt are unchanged.
|
||
- Flag users and text: `previews.js`, `actions.js` ("Hold G to replace it."), `build-menu.js`
|
||
(Replace · G chip, key hints), `loop.js`, `state.js`, `notebook.js` controls, `docs/DESIGN.md`.
|
||
- `test/play.py`: the replace checks hold G; a new check flies right with D while G is held
|
||
(121 checks pass). All 11 headless suites pass. `t_smooth.py`'s half-resolution check failed
|
||
on the slow fallback again (known, flaky under load).
|
||
- Open: nothing.
|
||
|
||
## 2026-10-23: Ctrl+W no longer closes the game without asking (Claude Code)
|
||
|
||
Note: "crash: hoplding crtl and pressing W crashes the whole browser."
|
||
|
||
- Cause: Ctrl+W is the browser's close-tab shortcut (the whole window if it is the last tab);
|
||
holding Ctrl for replace while pressing W to fly hits it. Chrome and Brave reserve it, so the
|
||
page never sees the key and cannot cancel it.
|
||
- `src/ui/input.js`: a `beforeunload` handler makes the browser ask before leaving while
|
||
`GAME.running`. The `visibilitychange` autosave no longer depends on the audio context
|
||
existing (it used to return early before any sound had played).
|
||
- `test/play.py`: 2 checks (leaving asks while a world is open, not on the title screen); 120
|
||
checks pass. All 11 headless suites pass; `t_smooth.py` passed on its rerun (the known flaky
|
||
half-resolution check failed once at load ~5).
|
||
- Open: the real Ctrl+W prompt can only be seen in a headed browser; the owner checks it.
|
||
|
||
## 2026-10-23: build menu hover popup, top-left card hidden while building (Claude Code, with Codex)
|
||
|
||
Notes: "mouse hover reviels a new info popup…" and "dont need the short description in the build
|
||
menu…". The owner chose to hide the top-left card entirely while building.
|
||
|
||
- `src/ui/build-menu.js`: `#bb-pop` above the hovered tile (icon, name, cost, size, power, full
|
||
description, how to place, filter help, build keys), clamped to the window; on a gamepad it
|
||
shows for the selected tile. The `.bb-tip` row became `.bb-status`: variant (material,
|
||
direction, filter) chips, Replace · Ctrl, ghosts waiting, and status messages. The bar now
|
||
updates its parts separately so hovering doesn't rebuild the tiles.
|
||
- `src/ui/selection.js`: `#selcard` is hidden for the build tool unless copying, cutting or
|
||
pasting; the build branch moved to the bar. `src/styles/style.css`: popup and status styles;
|
||
on narrow screens the bottom-right panel moves up while building.
|
||
- `src/ui/notebook.js`, `docs/DESIGN.md`, `docs/PROJECT_MAP.md`.
|
||
- Tests: `play.py` 118 checks (popup on hover, switching tiles, hidden on leave, gamepad,
|
||
no `.bb-tip`, card hidden while building and back for tools 1 and 2, status in the bar; the
|
||
Ctrl replace check now reads the bar). All 11 headless suites pass. `t_smooth.py`'s
|
||
half-resolution check is still flaky under load (~4.8): 1 pass in 3 runs, as before.
|
||
- Screenshots in `shots/` (build-popup-*) at 1280×800 and 900×700 in both looks.
|
||
- Open: at 900px wide the bottom-left hover-info panel sits partly under the build bar.
|
||
|
||
## 2026-10-23: a backed-up heap on a belt no longer shears (Claude Code, with Codex)
|
||
|
||
Note: "belts with a big pile on top only move the grains on the top of the stack…". The owner's
|
||
setup: a belt ending in a screw tube going up; material mixed into the bottom layers never moved.
|
||
|
||
- Cause: `carryColumn` (`src/sim/conveyors.js`) skipped a blocked grain and carried on up the
|
||
column, so with the front backed up the top slid over a stuck bottom. Reproduced headlessly
|
||
first: over 4,000 ticks, 8,815 shear steps at the tube (1,415 against a wall) and only 57 of
|
||
192 bottom sand grains left the belt.
|
||
- Fix: on a belt, the walk stops at the first blocked powder grain, so the load above stands
|
||
still. On a filter the walk goes on only so chosen materials can still drop through; nothing
|
||
above a blocked grain is carried. After: no shear, 119 of 192 sand grains out through the tube.
|
||
- `test/t_conveyors.js`: 3 new checks (no shear into an up tube, none against a wall, bottom
|
||
layer leaves through the tube). `tools/scenes/belt-heap.js` sets up the owner's case for
|
||
`tools/shot.py`; shots at 30 and 900 ticks look right. `docs/DESIGN.md`, `docs/PROJECT_MAP.md`.
|
||
- Tests: all 11 headless suites and `play.py` (109) pass. `t_smooth.py` failed its
|
||
half-resolution check once at load 6.5 and passed on the rerun.
|
||
- Open: `t_smooth.py`'s half-resolution check is flaky on a busy machine (the game drops to
|
||
pixel when frames are slow). It is worth making that test immune to the slow fallback.
|
||
|
||
## 2026-10-23: ingots drop out of the bottom of the mold (Claude Code, with Codex)
|
||
|
||
Note: "copper bars go into the furnace. also they shouldnt require the player to press F…".
|
||
The owner confirmed the first part was a bug: the knock-out threw bars up into the furnace.
|
||
|
||
- `src/sim/molds.js`: `ejectIngot` runs from `checkMolds` (every 15 ticks). Bars spawn directly
|
||
under the mold, only where `entFreeAt` says there is room; the rest wait in the trough. Metal
|
||
is taken from the top so the short stub stays on the floor. `ingot_drop` and `ingot_blocked`
|
||
events (blocked is said once per spell via `mo.blockedSaid`, not saved). F on a ready ingot
|
||
never launches bars upward; F on an empty, short or spoiled mold still cleans and rakes.
|
||
- `src/ui/events.js`: first drop gets a card, later drops a toast; blocked gets a toast. Ingots
|
||
no longer emit `cast_ready`.
|
||
- Text: `pieces.js`, `progress.js`, `notebook.js`, `info.js`, `docs/DESIGN.md` (with the
|
||
decision), `docs/systems/stone-and-liquids.md`, `docs/PROJECT_MAP.md`.
|
||
- Tests: `t_molds` (38 checks: downward drops, stub kept, top-up, blocked and warned once,
|
||
partial drops, full entity pool, slag), `t_basics`, `t_stone`, `furnace_play.js` and
|
||
`play.py` section 6 changed to the new behaviour. All 11 headless suites, `play.py` (109) and
|
||
`t_smooth.py` (8) pass. A shot of a mold with a belt one block below shows the bars riding off.
|
||
- Open: a belt touching the mold's underside counts as blocked; bars need one open block. The
|
||
owner may want a belt directly under the mold to work.
|
||
|
||
## 2026-10-23: Shift+Q/E build tabs, G pick key removed (Claude Code, with Codex)
|
||
|
||
Notes: "add shift + q/e to move tabs" and "having the "g pick" there is confusing".
|
||
|
||
- `src/ui/build-menu.js`: `selectBuildCat(c)` (shared with tab clicks) and `cycleBuildCat(d)`;
|
||
the menu hint now reads Q/E cycle · Shift+Q/E tab.
|
||
- `src/ui/input.js`: Shift+Q/E switch tabs with the build tool; G is unbound.
|
||
- Text: build card (`selection.js`), notebook controls (`notebook.js`), `actions.js` comment,
|
||
`docs/DESIGN.md`, `docs/PROJECT_MAP.md` (regenerated, `--check` passes).
|
||
- `test/play.py`: checks for Shift+Q/E, wrapping, the remembered piece per tab, plain Q/E,
|
||
and that G no longer calls pick while middle mouse still does (109 checks).
|
||
- Tests: all 11 headless suites and `play.py` pass; a `tools/shot.py` shot of the Moving tab
|
||
shows the new hint. `t_smooth.py` passes, but its "half-resolution smooth still draws" check
|
||
failed on several runs with the 'slow' pixel fallback while the machine was busy (load ~14).
|
||
The previous commit fails the same way under the same load, so this change didn't cause it.
|
||
- Open: that check is timing-sensitive on a loaded machine; rerun it when the machine is idle.
|
||
|
||
## 2026-10-23: browser tests run locally (Claude Code, with Codex)
|
||
|
||
Request: get the browser tests, Playwright and Chromium working on the owner's Arch machine
|
||
(Python 3.14 refuses a system-wide pip install).
|
||
|
||
- Playwright 1.64.1 and its Chromium 156 (revision 1248) are in an in-repo `.venv/` made with uv.
|
||
|
||
- Added `tools/use_venv.py` and called it before Playwright imports in `tools/shot.py`,
|
||
`tools/perf.py`, `tools/playthrough.py`, `test/play.py` and `test/t_smooth.py`.
|
||
The `sys.prefix` guard prevents an exec loop if the venv lacks Playwright.
|
||
- Updated `requirements.txt`, `.gitignore`, `README.md`, `AGENTS.md`, `docs/TESTING.md`
|
||
and `docs/PROJECT_MAP.md` for Playwright 1.64.1 and venv setup.
|
||
- Checks: regenerated the project map and ran `tools/map.py --check`.
|
||
- Tests run with plain `python3`: `test/run_all.py --browser` all passed (11 headless suites,
|
||
`play.py` 101 checks, `t_smooth.py` 8 checks) on the newer Chromium; `tools/shot.py` shots
|
||
of the stone-uses scene look right in both looks. With `.venv` moved away, `play.py` exits
|
||
with the setup message instead of a traceback.
|
||
- Open: nothing.
|
||
|
||
## 2026-10-23: export from claude.ai to a local repository (Claude, in claude.ai)
|
||
|
||
Request: split the source into small files, deduplicate and tidy a little, test fully, and
|
||
write the notes, docs and agent instructions for local development.
|
||
|
||
- **Source split.**
|
||
- `core.js` (3,688 lines), `main.js` (2,012) and `render.js` (938) became 52 files in
|
||
`src/sim/`, `src/render/` and `src/ui/`, each with a header line. The build order lives in
|
||
`src/manifest.json`.
|
||
- Checked that the joined code was identical to before, apart from comments and blank lines.
|
||
- Every headless suite gave the same output, line for line, before and after.
|
||
- Screenshots of two scenes, in both looks, were pixel-identical before and after
|
||
(`tools/shot.py --freeze`).
|
||
- **Tidying, behaviour unchanged.**
|
||
- One scan loop in `simMove` instead of two mirrored copies.
|
||
- A `drawHazardRims` helper replaced 3 copies.
|
||
- The belt and filter shader code shares `beltLineSD`, `bandRidge` and `bandColor`.
|
||
- Removed unused `refundCost`, `wakeArea`, `brushFor`, and the `PARTS` / `PART_BY_ID` aliases.
|
||
- The suites share `suite()` (check / done) from the harness, and failures now set the exit
|
||
code.
|
||
- **Tests.**
|
||
- Six broken old scripts were deleted; they used functions removed long ago.
|
||
- Experiments and reports moved to `tools/experiments/`.
|
||
- `t_v2` / `t_v4` / `t_v9` were renamed `t_basics` / `t_world` / `t_conveyors`.
|
||
- Added `test/run_all.py`.
|
||
- **Tools.**
|
||
- `tools/shot.py`: repeatable screenshots of a scene set up in JavaScript.
|
||
- `tools/where.py`: maps built-page line numbers back to source files.
|
||
- `tools/map.py`: the project map's index.
|
||
- `tools/scenes/`: example scenes.
|
||
- The game skips cursor previews when `GAME.hidePreviews` is set, for clean screenshots.
|
||
- **World files outside claude.ai.**
|
||
- Pause → Export world file only worked inside claude.ai, through its downloads hook.
|
||
- It now falls back to an ordinary browser download (`exportWorld` in `src/ui/saves.js`).
|
||
- `test/play.py` checks that an exported file downloads and imports back on the title screen
|
||
as the same world.
|
||
- **Build.** `build.py` writes `dist/index.html` (a full page), `dist/deepgrain-foundry.html`
|
||
(the same without the document wrapper, as the claude.ai artifact used) and
|
||
`dist/bundle-lines.json`.
|
||
- **Docs.** `AGENTS.md`, `CLAUDE.md`, `README.md`, `NOTES.md`, `docs/PROJECT_MAP.md`,
|
||
`docs/DESIGN.md`, `docs/TESTING.md`, `docs/systems/*`, `docs/history/requests.md`.
|
||
- **Tests run.** All 11 headless suites pass, as do `test/play.py` (101 checks) and
|
||
`test/t_smooth.py` (8 checks).
|
||
- **Open.**
|
||
- The owner reports that big piles on belts still only move at the top (NOTES.md); not yet
|
||
reproduced.
|
||
- The game's last claude.ai artifact was version 24.
|