Critical Review

Critical Review — snake

  • Reviewed: 2026-08-14T20:59:53.606223+00:00
  • Reviewer model: qwen/qwen3.7-max (temperature 0, independent of builder)
  • Builder model: deepseek-v4-flash
  • Objective verification: 10/10 checks passed

Process & bias controls

This review was produced by an independent frontier model in a sandbox.

Controls: blind context (no builder claims), deterministic rubric,

evidence-required scoring, independent factual verification by the

harness, and full transparency (prompt + raw output archived in review.json).

Scores

  • correctness: 7/10
  • fidelity: 8/10
  • twist: 7/10
  • ux: 5/10
  • mobile: 8/10
  • accessibility: 5/10
  • performance: 9/10
  • security: 9/10
  • docs: 3/10
  • originality: 6/10

Verdict: needs-work

### Summary

A competent Snake clone with a well-integrated combo multiplier twist, but undermined by a non-functional 'Try again' button, missing LICENSE for game code, and an experiments.json that doesn't even include the snake experiment. Core gameplay is solid; the surrounding polish and documentation are lacking.

### Issues

  • [critical] (ux) The 'Try again' retry button shown on game over has no event listener bound to it. Clicking it does nothing. — index.html:84 defines <a id='snake-retry'>, but js/game.js only binds 'snake-restart' (line 174-175). No listener for 'snake-retry' exists anywhere.
  • [major] (docs) No LICENSE file exists for the game code itself. Only a font license (Clear Sans / Apache 2.0) is present. — Glob for **/LICENSE* returns only style/fonts/LICENSE-ClearSans.txt. No top-level LICENSE or COPYING file.
  • [major] (docs) experiments.json does not include the snake experiment — it only contains the 2048 entry. The experiment ID mismatch means any tooling relying on this manifest will not find snake. — experiments.json:3 — the only entry has id '2048'. No snake entry exists.
  • [minor] (correctness) endGame() is called twice on win: once from spawnFood() when no empty cells remain, and again from step() line 113. This double-writes localStorage and sets over=true redundantly. — js/game.js:49 calls endGame() inside spawnFood(); js/game.js:113 calls endGame() again after spawnFood returns.
  • [minor] (ux) The retry button (snake-retry) has role='button' and tabindex='0' but no keyboard activation handler (Enter/Space), so even if a click handler were added, keyboard users couldn't activate it without additional code. — index.html:84 — role='button' tabindex='0' with no keydown listener in game.js.
  • [minor] (accessibility) The game canvas has no aria-label, role, or aria-live region to communicate game state to screen readers. The game is entirely inaccessible to visually impaired users. — index.html:88 — <canvas id='snake-canvas' class='snake-canvas'> with no ARIA attributes.
  • [minor] (accessibility) No reduced-motion support. The score flash animation and food color change have no prefers-reduced-motion media query override. — style/main.css — no @media (prefers-reduced-motion) query anywhere in the file.
  • [minor] (accessibility) Combo state is communicated only through food color change (from #f2b179 to #f65e3b), with no text or icon indicator on the canvas. The stats bar shows 'x1' when inactive which partially mitigates this. — js/game.js:198 — ctx.fillStyle = combo ? '#f65e3b' : '#f2b179'.
  • [minor] (docs) No attribution to the original Snake game creators. The 2048 files credit Gabriele Cirulli, but game.js has no corresponding attribution for Snake's origins. — js/game.js:1-5 — header comment mentions ByJTT Experiment but no original author credit.
  • [minor] (docs) Seven JS files (game_manager.js, grid.js, html_actuator.js, keyboard_input_manager.js, local_storage_manager.js, tile.js, application.js) are 2048 code not loaded by index.html — dead code in this artifact. — index.html:102-104 loads only game.js, lb-tab.js, x-embed.js. The other 7 files are never referenced.
  • [minor] (ux) Stray orphan </script> tag on line 106 of index.html after the x-embed.js script block. Harmless but indicates sloppy markup. — index.html:106 — bare </script> with no matching open tag.
  • [minor] (ux) index.html references /style/site.css (absolute path) which does not exist in the artifact, so shared site nav styling will be missing. — index.html:11 — <link href='/style/site.css'> but no such file in artifact.

### Strengths

  • Core snake mechanics are correctly implemented: wall collision, self-collision with proper tail handling, growing, and progressive speed increase (js/game.js:81-113).
  • Combo twist is well-designed with a 4-second chaining window, visible multiplier in the stats bar, and score flash feedback (js/game.js:99-107).
  • Mobile support is thorough: responsive canvas with devicePixelRatio scaling, touch swipe with scroll prevention, on-screen D-pad hidden on desktop via media query (js/game.js:145-171, style/main.css:41,69-71).
  • Input handling covers keyboard (arrows + WASD), touch swipe, and D-pad with 180-degree reversal prevention (js/game.js:124-171).
  • Security-conscious X/Twitter embed sanitization strips scripts, iframes, event handlers, and javascript: URIs (js/x-embed.js:15-33).

### Recommendations

  • Bind an event listener to the 'snake-retry' button so the game-over 'Try again' button actually works.
  • Add a top-level LICENSE file for the game code and include attribution for the original Snake game.
  • Add the snake experiment entry to experiments.json.
  • Add aria-label and an aria-live region to the canvas to communicate game state (score, game over) to assistive technology.
  • Remove the 7 unused 2048 JS files from the artifact, or move them to the 2048 experiment directory.
  • Add a @media (prefers-reduced-motion) query to disable the score flash animation.

### Objective verification (harness)

  • ✅ file:index.html
  • ✅ file:js/game.js
  • ✅ file:js/lb-tab.js
  • ✅ file:style/main.css
  • ✅ license:MIT n/a — original implementation, no MIT derivation
  • ✅ tests:pass 5 pass, 0 fail
  • ✅ selfcontained
  • ✅ viewport
  • ✅ x-share
  • ✅ leaderboard