Skip to content

Strict typing, linting, licensing and a README for newcomers - #2

Merged
russofg merged 4 commits into
mainfrom
chore/strict-and-tooling
Aug 16, 2026
Merged

Strict typing, linting, licensing and a README for newcomers#2
russofg merged 4 commits into
mainfrom
chore/strict-and-tooling

Conversation

@russofg

@russofg russofg commented Aug 16, 2026

Copy link
Copy Markdown
Collaborator

Closes the last items from the production-readiness pass: strict typing, linting,
formatting, licensing, and a README written for someone arriving cold.

Quick path for reviewing this

  1. eslint.config.js — the only file with judgement calls in it. Read the comments.
  2. README.md — rendered, not as a diff.
  3. LICENSE + ASSETS-LICENSE.md — the code/art boundary.
  4. Everything else is mechanical: Prettier's first pass and dead-code removal.

Details

Area Decision
strict On. Passes with zero errors — the code was already well typed, nothing was enforcing it since @types/react had been missing.
Dead code noUnusedLocals found 25 unused imports and variables, plus an effect returning cleanup on only one path. hooks/useAIImage.ts deleted — its last reference was a comment saying it was removed.
ESLint Pinned to 9, because eslint-plugin-jsx-a11y does not support 10 yet. Forcing the resolution would have been the other option; this seemed better than hoping.
Accessibility linting jsx-a11y runs over the whole tree, so the accessibility work is enforced instead of reviewed. It immediately caught an unlabelled range input in the settings panel.
Prettier Folded into the strict commit rather than split out — it touches nearly every file, so isolating it would produce two large diffs over the same lines.
Licensing MIT for code, CC BY-NC-ND for art. A single root LICENSE would have read as MIT covering the artwork too.

The one judgement call

Four React Compiler rules are set to warn, not error:

react-hooks/purity · refs · immutability · set-state-in-effect     (19 occurrences)

They flag real patterns in the game loop — randomness and timestamps read during
render, refs touched during render, state set from effects. Fixing them means
restructuring how the simulation ticks, which is its own piece of work and not
something to bolt onto a tooling PR.

They are left visible rather than disabled, with the reasoning written in the
config, so the count can only go down. Promote them back to errors once the loop
is reworked.

Verification

  • npm run check exits 0 — now six steps: typecheck → lint → format → test → build → budget.
  • 151 tests across 23 files, unchanged by this PR.
  • Lint: 0 errors, 45 warnings, all of them recorded debt described above.
  • Every relative link in the README and ASSETS-LICENSE.md resolves to a real path.

Out of scope

noUncheckedIndexedAccess (85 occurrences) and noUnusedParameters (35) were
measured and deliberately left off. Both are worth doing; neither belongs in the
same change as a formatting sweep.

The typecheck only became meaningful once @types/react was installed, so strict
had never actually been exercised. It passes with zero errors — the code was
already well typed, nothing was enforcing it.

noUnusedLocals surfaced 25 dead imports and variables, plus an effect in
ClientPopup that returned a cleanup on only one path. hooks/useAIImage.ts is
deleted outright: its last reference was a comment saying it had been removed.

Prettier's first pass is folded into this commit rather than split out. It
touches nearly every file, so isolating it would produce two large diffs over
the same lines instead of one.
Nothing checked for the class of mistake that typechecking cannot see. jsx-a11y
runs over the whole tree so the accessibility work is enforced rather than left
to review; it immediately caught an unlabelled range input in the settings panel.

Pinned to ESLint 9 because eslint-plugin-jsx-a11y does not support 10 yet —
preferable to forcing the resolution and hoping.

Four React Compiler rules are set to warn, with a comment on each explaining
why: they flag real patterns in the game loop — randomness read during render,
refs touched during render, state set from effects — and fixing them means
restructuring how the simulation ticks. Left visible so the count can only fall.

Lint and format now run in CI and in npm run check.
Running the game locally now comes before the design essay, the commands are a
table instead of prose, and the three things that break quietly — the Tailwind
safelist, the no-CDN rule, the asset budget — get their own section instead of
being folklore.
The repository had no license at all, which by default means nobody may reuse
any of it — the opposite of what a public showcase is for.

Code is MIT: fork it, read it, ship it. The artwork is not, because commissioned
art is the part with standing value here; it is CC BY-NC-ND, so it can be shared
with credit but not sold, rebundled or shipped inside someone else's product.

The boundary is written down rather than implied, since a single LICENSE file at
the root would have read as MIT covering everything.
Copilot AI lite review requested due to automatic review settings August 16, 2026 03:38

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@russofg
russofg merged commit 7f84271 into main Aug 16, 2026
5 checks passed
@russofg
russofg deleted the chore/strict-and-tooling branch August 16, 2026 03:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants