Public: anyone can read this; the crew can change it.
Migrated from github.com/amirmushichge/pixel-plays
Add Pumpkin Patch: the playable page and its place in the catalogue, on the rules in `pumpkin-patch/plots.js` #341
Check · Review · Land · Live done — Landed and live in production.
Pumpkin Patch is now playable at `/pumpkin-patch/` and listed in the catalogue. `pumpkin-patch`, `serve` and `playtest` tests pass, 536 in all. The branch is already on top of main, so no rebase was needed.
shipped production is serving it deploy 5b5fb07
Pumpkin Patch is now playable at /pumpkin-patch/ and listed in the catalogue. pumpkin-patch, serve and playtest tests pass, 536 in all. The branch is already on top of main, so no rebase was needed.
- The page:
pumpkin-patch/index.htmldraws the walled patch on the 360×280 canvas throughengine.js. It follows the Visual rules, and the walls, flagstones, watering can, per-plot counts, HUD and aria-live announcements are all in the page. It drives the game only throughPumpkinPatchfromplots.js. The last commit widens the patch and the pumpkin spacing slightly and regeneratesog/home.pngandog/pumpkin-patch.png. - The catalogue: the
GAMESentry inshell.jsispumpkin-patch,Pumpkin Patch,Puzzle,Tap,music: false,forged: true. The matching<li>is in the rootindex.html. The README has the Games table row and an entry in the list of games without music. Its ambient-motion line says the open leaves stir and stop under reduced motion. - Tests:
rounds.mjshas a scripted round that reaches the win line.serve.test.mjsasserts that/pumpkin-patch/and/pumpkin-patch/plots.jsanswer 200. A smallpumpkin-patch/page.test.mjsis new. - Town building:
town.jsis unchanged. Welly Toss didn't touch it either, and the town looks to take its buildings fromGAMES, so I didn't confirm a Pumpkin Patch building appears. Look for it when you try the preview. - Checks I couldn't run:
scripts/gate.ts,scripts/fast.tsandscripts/design-lint.tsdon't exist in this clone.bun x tsc --noEmitprinted only the compiler help text, so it isn't set up here either. - Not done: no new dependency and no
.mp3. Sound is sound effects only, as with the other games without music.
To try it, run the app and open /pumpkin-patch/, or open the preview for this pull. Tap a plot or use the arrow keys and Enter to pour. U undoes and R restarts.
🤖 Generated with Claude Code
I merged main into this branch and pushed, so the pull should merge cleanly again. The playtest passes with 440 tests. The pumpkin-patch, fence-posts and serve tests also pass, 127 in all. I did not run the whole suite.
README.md: two paragraphs conflicted, the list of games without music and the ambient-motion list. I tookmain's text, which now includes Fence Posts, and added Pumpkin Patch to each. Againstmain, the file gains only the Pumpkin Patch table row and those two additions.og/home.png: I tookmain's version and re-ranbun scripts/og.mjs. That regeneratedhome.pngwith both Fence Posts and Pumpkin Patch in it, and thefence-posts,welly-tossandpumpkin-patchcards too.- Other files:
index.html,shell.js,rounds.mjsandserve.test.mjsmerged on their own.
My first attempt at the README.md merge overwrote the wrong lines. I caught it from leftover conflict markers, restored the conflict and redid it before committing, so none of that is in the pushed history.
Pumpkin Patch is complete against the issue and the preview serves it (200). One thing blocks approval, and one small thing goes with it.
- Keyboard and screen-reader users cannot tell where the cursor is. In the
keydownhandler inpumpkin-patch/index.html, an arrow key only changesG.cursor. Nothing is announced. The plot, its number and the can all exist only as canvas pixels, and the aria-label is static. Someone without sight, or without a mouse, cannot find the plot they are about to pour on, or learn how many waterings it needs. Fix: after each arrow move, callsay(...)withwhere(G.cursor)and the plot's state, for exampleRow 2, column 3: needs 2 more waterings,has its water,rotted, ora flagstone. The pour announcement already does this, so reuse it. Add a page test that an arrow key updates the status line.
say()goes throughsetText, which skips identical text. Two refusals in a row, such asA flagstone takes no water, are therefore not re-announced. Clear the node and then set it, or alternate the text, so a repeated refusal is spoken again.
Smaller points, not blocking:
#leveland#nameboth show the level number, because the name span sayslevel N of 6. Drop one.- The mute button's text flips between
sound onandsound offand it also carriesaria-pressed, which double-signals. Keep a fixed label (sound) witharia-pressed, or droparia-pressed.
The boxes are all met at this head, and the rest is fine. Reduced motion is honoured. The rules popup is 3 lines. The #mute button exists, with no mp3. The GAMES entry, the root <li>, the README row and the no-music list, the scripted round and the serve test are all in. The town takes its buildings from GAMES, so the Pumpkin Patch building comes from the new entry.
Both blocking points and both smaller ones from the review are fixed and pushed. The pumpkin-patch and serve tests pass, 106 in all, and so does the playtest (440). I did not run the whole suite.
- Cursor announcements: each arrow move now calls
say()with the plot's position and state, reusingwhere(). The line readsRow 2, column 3: needs 2 more waterings,has its water,rottedora flagstone. Page tests check that an arrow key updates the status line, including the flagstone case. - Repeated refusals:
say()now empties the live node before setting it, so the same line twice is spoken twice. A test sets the same line twice and checks the node ends up holding it. - Level display:
#namenow reads<name> · of 6and#levelkeeps the number. - Mute button: the label is fixed at
soundandaria-pressedcarries the state.
I did not add a test for the mute label. The playtest's DOM doesn't parse button text, so a check on it failed even though the markup is right.
I also didn't add a test that two refusals in a row both reach the node. The test I wrote checks the node's final text, not that it was emptied in between, so it doesn't pin the clear-then-set behaviour.
No security findings: no network, storage or injection surface; all text goes through textContent. Two things to fix before this lands.
- Test gap (fix first). The test "say clears the live node before setting it" passes without the clear-first behaviour: it sets the node to x and then checks it holds the same text, so it would also pass if say() only assigned once. Spy on the node, for example by defining a textContent setter on nodes.status that records each write, and assert that the writes for a repeated say() are ["", "same"]. Likewise add a test that two identical refusals (a flagstone tapped twice) each reach the node. Quill said both were left untested, and that is exactly the behaviour the review asked to pin. The mute button (aria-pressed toggles on click) is also untested; assert the attribute, not the label text, which the playtest DOM does not parse.
- Dead code in pumpkin-patch/index.html. G.drops is set in pourAt and decremented in update() but never read; G.status is written in say() and never read. Remove both fields and their writes. The G object should hold only time, cursor and canTilt. Also tidy the stray trailing comment after the closing brace of say(): move it above the function.
The issue boxes are not ticked until these land.
Pumpkin Patch is playable at /pumpkin-patch/ and listed in the catalogue. Its rules come from pumpkin-patch/plots.js. This push adds the last two tests the earlier review asked for and removes state the page no longer used.
- Live line (
say()): a new test records every write to#status. It checks thatsay()writes''before the text, which is why a repeated line is spoken again. - Repeated refusal: a second new test taps the same flagstone twice on level 2. Both taps are refused, no water is used, and the refusal line reaches the status line twice with a clear before each.
- Mute button: a test now checks that clicking it switches
aria-pressedbetweentrueandfalse. It checks the attribute, not the button text, because the test DOM doesn't read button text. - Cleanup in
pumpkin-patch/index.html: removedG.status,G.dropsandG.dropAt, which nothing read. The comment onsay()now sits above the function.
To try it, open the preview for this pull and go to /pumpkin-patch/. Tap a plot, or use the arrow keys and Enter to pour. Tap a flagstone twice and the refusal is spoken both times. U undoes and R restarts.
The pumpkin-patch and serve tests pass (108), and so does the playtest (440). I did not run the whole suite. scripts/gate.ts, scripts/fast.ts and scripts/design-lint.ts don't exist in this repository, so none of them ran.
The review that requested changes doesn't show up through the API: the reviews list for this pull comes back empty. So this push answers the two gaps listed in the last comment on the pull. If the review asked for anything else, it isn't covered here.
🤖 Generated with Claude Code
Pumpkin Patch is playable at /pumpkin-patch/ and listed in the catalogue, and the branch now merges cleanly with main. main had added Ticket Booth in the same spots this pull adds Pumpkin Patch, so every conflict keeps both games.
shell.js: Ticket Booth'sGAMESentry stays, and Pumpkin Patch's comes after it.serve.test.mjs: both serve tests stay, one after the other.README.md: the Games table has both rows. Ticket Booth and Pumpkin Patch are both in the list of games without music and the ambient-motion line. Pumpkin Patch's ambient-motion entry used to say its watering-can drops move, but the page doesn't draw drops. It now says "the tilting can is play, and still moves".og/home.png: started frommain's copy and regenerated withbun scripts/og.mjs, so the grid has both games. Running it also rewrote thewelly-toss,ticket-boothandpumpkin-patchcards.- Merged without conflicts: the root
index.htmllist androunds.mjs, along with Ticket Booth, Tide Crossing and Village Darts frommain.
The earlier push in this pull added page tests for the live status line and the mute button, and removed state the page no longer used.
To try it, open / on the preview and find both Pumpkin Patch and Ticket Booth under Puzzle, then open /pumpkin-patch/. Tap a plot, or use the arrow keys and Enter to pour. Tap a flagstone twice and the refusal is announced both times.
These tests pass after the merge: serve, shell, town, pumpkin-patch and ticket-booth (158), and the playtest (446). I did not run the whole suite. scripts/gate.ts, scripts/fast.ts and scripts/design-lint.ts don't exist in this repository, so none of them ran.
🤖 Generated with Claude Code
Earlier asks are all met: arrow moves announce the plot (with tests), say() clears before setting so repeated refusals are spoken again (with a spying test), the level/name duplication is gone, and mute has a fixed label with aria-pressed (tested). Preview /pumpkin-patch/ answers 200. Nothing new to raise; this is static client code with no write surface, output goes through textContent, and no dependency or secret is added.
I made no code change and pushed nothing new, because I couldn't find anything in the code that caused the failed deploy. Every line in the deploy log is a (pass). It stops partway through the bird-watch playtest, about six games into more than a hundred, so the run looks like it was stopped from outside rather than failing a test. The preview is now up and serving the latest commit (ef439b3): /, /pumpkin-patch/, /pumpkin-patch/plots.js and /ticket-booth/ all return 200, and the home page lists both games. A new commit would only restart the check that is already running on this commit.
---
Pumpkin Patch is now playable at /pumpkin-patch/ and listed in the catalogue. The branch also has main merged in, so Ticket Booth and Pumpkin Patch are in the catalogue together.
- The page:
pumpkin-patch/index.htmldraws the walled patch on the 360×280 canvas throughengine.jsand drives the game only throughPumpkinPatchfromplots.js. It shows the plot under the cursor, the water count on each plot, a HUD, and announcements for screen readers. It re-announces a line when the same thing happens twice, and the mute button's label and pressed state are fixed. - The catalogue: there is a
GAMESentry inshell.js(Puzzle, Tap,music: false,forged: true), an<li>in the rootindex.html, and a README row. The README also lists it with the games without music and says its leaves stop moving when reduced motion is on. - Tests:
rounds.mjshas a scripted round that reaches the win line.serve.test.mjsasserts that the page andplots.jsanswer 200, andpumpkin-patch/page.test.mjsis new. Run here, all pass:
- pumpkin-patch, ticket-booth, serve, shell and town: 158 tests.
- The playtest.test.mjs tests for both games: 12 tests, about 4 s.
- What to look at: whether the town shows a Pumpkin Patch building. It appears to take its buildings from
GAMES, but I didn't confirm it. - Not done: no new dependency and no music; the game has sound effects only.
- Checks I couldn't run:
scripts/gate.ts,scripts/fast.tsandscripts/design-lint.tsdon't exist in this clone. Earlier in this branch,bun x tsc --noEmitprinted only the compiler's help text instead of type-checking, so the type check isn't set up here either.
To try it, open /pumpkin-patch/ on the preview. Tap a plot, or use the arrow keys and Enter, to pour. U undoes and R restarts.
🤖 Generated with Claude Code
Closes #331
Pumpkin Patch is now playable at /pumpkin-patch/ and listed in the catalogue. The branch is merged with the latest main, so Ticket Booth, Carrot Pull and Pumpkin Patch are all in the catalogue together.
- The page:
pumpkin-patch/index.htmldraws the walled patch on the 360×280 canvas throughengine.js. It drives the game only throughPumpkinPatchfromplots.js. The page shows the plot under the cursor and how much water each plot still needs. Screen readers hear each announcement, including when the same line comes twice in a row. The mute button's label stays the same and its pressed state is announced. - The catalogue:
shell.jshas aGAMESentry for it (Puzzle, Tap,music: false,forged: true), and the rootindex.htmlhas the matching<li>. In the README it has a row in the Games table and a place in the list of games without music. Its ambient-motion line says the open leaves stir and stop under reduced motion. - Merge with
main:mainhad added Carrot Pull in the same places, soREADME.md,serve.test.mjsandshell.jsconflicted. Each conflict keeps both games, with Carrot Pull first and Pumpkin Patch after it.og/home.pngis regenerated withbun scripts/og.mjsso the grid shows every game, Carrot Pull and Pumpkin Patch included. - Tests:
rounds.mjshas a scripted round that reaches the win line.serve.test.mjschecks that the page andplots.jsanswer 200.pumpkin-patch/page.test.mjsis new. After the merge, these pass:
- the serve, shell, town, pumpkin-patch and carrot-pull tests: 155 pass, 0 fail
- the playtests for Pumpkin Patch and Carrot Pull, plus the test that every game has a scripted round: 13 tests, 0 fail
- Earlier failed preview deploy: its log ended partway through the
bird-watchplaytest with every test passing. That looks like the run was stopped from outside, and later deploys served the branch normally. - Look for: whether the town shows a Pumpkin Patch building. It seems to build from
GAMES, but I haven't confirmed it. - Not done: no new dependency and no music track; the game uses sound effects only.
- Checks not run: this clone has no
scripts/gate.ts,scripts/fast.tsorscripts/design-lint.ts.bun x tsc --noEmitonly prints the compiler's help text, so there is no type check set up either.
To try it, open /pumpkin-patch/ on the preview. Tap a plot, or use the arrow keys and Enter, to pour; U undoes and R restarts.
🤖 Generated with Claude Code
Closes #331
Pumpkin Patch is now playable at /pumpkin-patch/ and listed in the catalogue. The branch is merged with the latest main, so Ticket Booth, Carrot Pull, Village Darts and Pumpkin Patch are all in the catalogue together.
- The page:
pumpkin-patch/index.htmldraws the walled patch on the 360×280 canvas throughengine.js. It drives the game only throughPumpkinPatchfromplots.js. It shows the plot under the cursor and how many waterings each plot still needs. Screen readers hear every announcement, even when the same line repeats. The mute button keeps a fixed label and reports whether it is pressed. - The catalogue:
shell.jshas aGAMESentry for it (Puzzle,Tap,music: false,forged: true), and the rootindex.htmlhas the matching<li>. The README adds a row to the Games table and lists it among the games without music. Its ambient-motion line says the pumpkins' open leaves stir and stop under reduced motion. - Merge with
main:mainadded Village Darts, soREADME.mdandog/home.pngconflicted. The README keepsmain's Village Darts row, its no-music list and its ambient-motion line, with Pumpkin Patch added to both lists.og/home.pngwas regenerated withbun scripts/og.mjs, so the grid shows every game. - Tests:
rounds.mjshas a scripted round that reaches the win line, andserve.test.mjschecks that the page andplots.jsanswer 200.pumpkin-patch/page.test.mjsis new. After the merge these all pass:
- the serve, shell, town, pumpkin-patch and village-darts tests (163);
- the playtests for Pumpkin Patch and Village Darts, plus the check that every game has a scripted round (13).
- Not confirmed: whether the town shows a Pumpkin Patch building. The town appears to build from
GAMES, but I didn't check it. - Not done: no new dependency and no music track; the game uses sound effects only.
- Checks not run: this clone has no
scripts/gate.ts,scripts/fast.tsorscripts/design-lint.ts. Earlier on this branch,bun x tsc --noEmitprinted only the compiler's help text, so there is no type check to run.
To try it, open /pumpkin-patch/ on the preview. Tap a plot, or use the arrow keys and Enter, to pour. U undoes and R restarts.
🤖 Generated with Claude Code
Closes #331
Earlier asks are met: arrow moves announce the plot, say() clears before setting (a spy test pins the writes), repeated refusals both reach the live line, mute has a fixed label with aria-pressed and a test, and the dead G fields are gone. The preview serves /, /pumpkin-patch/ and plots.js with 200, and the home page lists the game. Non-blocking: (1) undo is keyboard-only (U), so a phone player has no way to take back a pour except restarting a rotted level via R, which is also a key; add small tap-able undo and restart buttons in the HUD. (2) Confirm the town shows a Pumpkin Patch building.
Left #331 open: 2 unticked items remain (pumpkin-patch/index.html draws a walled pumpkin patch: a grid of soil plots with a pumpkin in each, stone plots as flagstones, and a watering can. Each plot shows how many waterings it still needs. Tap a plot, or move a cursor with the arrow keys and press Enter, to pour. U undoes and R restarts. It drives the game only through PumpkinPatch from plots.js and adds no game rule of its own. The HUD shows the level, pours and par from the rules state. Each pour, refusal, rot and win line is announced through an aria-live region.; Follows the README Visual rules: 360x280 canvas via engine.js, fixed 30-degree camera, hard shadows screen-right, and ambient motion stopped under prefers-reduced-motion. A plot at its need differs from a dry one by shape as well as colour (the pumpkin swells, or a leaf opens), and a rotten one by a collapsed shape. The canvas aria-label says how to play. The rules popup is at most four lines. There is a #mute button and no .mp3 is committed.).
Pumpkin Patch is now playable at
/pumpkin-patch/and listed in the catalogue.pumpkin-patch,serveandplaytesttests pass, 536 in all. The branch is already on top of main, so no rebase was needed.pumpkin-patch/index.htmldraws the walled patch on the 360×280 canvas throughengine.js. It follows the Visual rules, and the walls, flagstones, watering can, per-plot counts, HUD and aria-live announcements are all in the page. It drives the game only throughPumpkinPatchfromplots.js. The last commit widens the patch and the pumpkin spacing slightly and regeneratesog/home.pngandog/pumpkin-patch.png.GAMESentry inshell.jsispumpkin-patch,Pumpkin Patch,Puzzle,Tap,music: false,forged: true. The matching<li>is in the rootindex.html. The README has the Games table row and an entry in the list of games without music. Its ambient-motion line says the open leaves stir and stop under reduced motion.rounds.mjshas a scripted round that reaches the win line.serve.test.mjsasserts that/pumpkin-patch/and/pumpkin-patch/plots.jsanswer 200. A smallpumpkin-patch/page.test.mjsis new.town.jsis unchanged. Welly Toss didn't touch it either, and the town looks to take its buildings fromGAMES, so I didn't confirm a Pumpkin Patch building appears. Look for it when you try the preview.scripts/gate.ts,scripts/fast.tsandscripts/design-lint.tsdon't exist in this clone.bun x tsc --noEmitprinted only the compiler help text, so it isn't set up here either..mp3. Sound is sound effects only, as with the other games without music.To try it, run the app and open
/pumpkin-patch/, or open the preview for this pull. Tap a plot or use the arrow keys and Enter to pour. U undoes and R restarts.🤖 Generated with Claude Code
Closes #331