Skip to content

chore: remove dead code, and two facts that were stated twice - #76

Merged
thethinkmachine merged 1 commit into
mainfrom
chore/remove-dead-code
Sep 17, 2026
Merged

thethinkmachine merged 1 commit into
mainfrom
chore/remove-dead-code

Conversation

@thethinkmachine

Copy link
Copy Markdown
Owner

An audit for unreachable code and duplication. −595 lines of app source (js/ −388, css/ −207), 1947/1947 tests pass, bundle builds.

package-lock.json has a pre-existing transitive dev-dep bump in the working tree; it is deliberately not in this branch.

What went

Each was established dead the same way: no caller in js/, tests/, index.html, or any on*= attribute string the app builds at runtime — that second group is 122 attributes, which is why a scan of index.html alone understates this seam.

lines lines
34 functions −266 3 constants −3
38 import bindings −5 4 bridge.js entries −4
16 CSS class families −137 2 CSS custom properties −70

Two worth naming:

  • simNDTMLegacy (75 lines) — a superseded NDTM search, dead since simNDTM replaced it, and it still carried the Math.max(0, nh) head clamp that js/tape.js exists to remove: the one that reports a machine scanning off the front of its input as a clean rejection.
  • --accent2 / --minimap-viewport — declared once per theme, 35 times each, read by nothing. The minimap is a 2D canvas and takes its frame colour from the Themes registry, as the note at the top of tests/themes.test.js already says. That test's guard on the dead token is repointed, not dropped, at export.viewportStroke — the value that actually paints. It holds on all 21 themes.

Several removed functions carried comments claiming a caller they no longer had ("the tests' way in", "what the tests exercise"). A comment is not a reference, and neither is an export.

Two facts that were written out many times

buildFormalDefLatex (227 → 159) was twenty branches each spelling out the four rows they agree on. Every definition is the same list — the tuple, a row per component, then δ — so that shape is stated once and a branch supplies only what is particular to it; the four tape machines share a branch for the same reason.

All 30 machines' LaTeX was snapshotted before and after: 28 byte-identical. The two that differ are 2DFA and 2NFA, which carried a trailing \\ on their δ row that no other machine has — KaTeX renders that as an empty row, so those two boxes had a blank line under δ.

zoomIn / zoomOut / setZoomFromInput (72 → 58) were three copies of "zoom about the centre of the viewport" plus four of the eased repaint. The copies had drifted: two clamped by hand where clampZoom is meant to be the single answer for every zoom path (one of them only at the maximum), and they disagreed about how to measure the box — getBoundingClientRect against clientWidth, the same number here only because .canvas-area has no border, no padding and overflow: hidden.

How the CSS was checked

Every live selector was diffed rule by rule against main, with selector lists flattened to one entry each and duplicates kept in source order: no surviving declaration changed.

That check earned its keep — it caught two earlier attempts that orphaned the live members of a list whose last selector was dead. .algo-output is the eleventh selector on one user-select: text rule, not a rule of its own. Worth knowing for any future pass: dead-class detection is mostly false positives in this codebase, because modifiers are built as is-${severity}, edge-pill-${role}, v-${cell.k}, 'k-g' + (i+1), ' g' + slot. .is-fix, .v-yes, .g1, .k-g1 and the eight edge-pill-* all scan as dead and are live; so does the overflow: hidden; overflow: clip pair, which is the deliberate fallback CLAUDE.md documents.

Deliberately untouched

  • The 16,495 comment lines in js/ (27% of the directory) — the largest block of nominally removable lines. They record which bug each rule prevents and are the only place that is written down.
  • The per-theme alphas in css/variables.css--accent-border is .22/.25/.24/.26 across themes. Collapsing the ~1,000 lines of derived tokens into color-mix() would change what is painted in most themes: a redesign, not a cleanup.

Not in this PR — worth a decision

buildFormalDefLatex still duplicates the machine registry. Each machine declares formal: { tuple(), delta() } in js/machines/*.js in Unicode ('Q × Σ → Q'), read by the Language panel; render.js states the same facts again in LaTeX. CLAUDE.md's claim that this was migrated to a per-type lookup is true of langTupleSyms/langDeltaSignature, but the LaTeX box never moved — it is the last twenty-branch machine-name chain in the app (only 13 App.machine === 'X' tests remain elsewhere). Unifying needs a call on which notation is canonical, and the LaTeX carries content the plain text does not: LBA's tape bound, ITM's index set, MTM's live arity.

Verification

  • npm test — 1947/1947
  • npm run build — clean; lightningcss accepts every stylesheet
  • node --check on all 106 js files
  • dead-function, dead-constant and unused-import sweeps re-run to a fixed point: 0 remaining
  • every changed file matches main on blank-line structure, so the diff is removals only

🤖 Generated with Claude Code

An audit for unreachable code and duplication. -595 lines of app source,
with every removal verified rather than assumed: 1947/1947 tests pass and
the bundle builds.

What went, and how each was established dead — no caller in js/, tests/,
index.html, or any `on*=` attribute string the app builds at runtime,
which is the half a scan of index.html alone understates:

  34 functions          -266   3 constants             -3
  38 import bindings      -5   4 bridge.js entries     -4
  16 CSS class families -137   2 CSS custom properties -70

Two of those are worth naming. `simNDTMLegacy` was a superseded NDTM
search, dead since `simNDTM` replaced it — and it still carried the
`Math.max(0, nh)` head clamp that js/tape.js exists to remove, the one
that reports a machine scanning off the front of its input as a clean
rejection. `--accent2` and `--minimap-viewport` were declared once per
theme, 35 times each, and read by nothing: the minimap is a 2D canvas and
takes its frame colour from the `Themes` registry, as the note at the top
of tests/themes.test.js already says. That test's guard on the dead token
is not dropped but repointed at `export.viewportStroke`, which is the
value that actually paints; it holds on all 21 themes.

Several removed functions carried comments claiming a caller they no
longer had — "the tests' way in", "what the tests exercise". A comment is
not a reference, and neither is an export.

Then two facts that were each written out many times:

`buildFormalDefLatex` (227 -> 159) was twenty branches each spelling out
the four rows they agree on. Every definition is the same list — the
tuple, a row per component, then δ — so that shape is stated once and a
branch supplies only what is particular to it. The four tape machines
shared a branch for the same reason. All 30 machines' LaTeX was snapshotted
before and after: 28 are byte-identical, and the two that differ are 2DFA
and 2NFA, which carried a trailing `\\` on their δ row that no other
machine has. KaTeX renders that as an empty row, so the box had a blank
line under δ on exactly those two.

`zoomIn`/`zoomOut`/`setZoomFromInput` (72 -> 58) were three copies of
"zoom about the centre of the viewport" plus four of the eased repaint.
The copies had drifted: two clamped by hand where `clampZoom` is meant to
be the single answer for every zoom path, one of them only at the
maximum, and they disagreed about how to measure the box —
`getBoundingClientRect` against `clientWidth`, which are the same number
here only because `.canvas-area` has no border, no padding and
`overflow: hidden`.

Every live CSS selector was diffed rule by rule against the previous
revision, with selector lists flattened to one entry each and duplicates
kept in source order: no surviving declaration changed. That check is
what caught the first two attempts at this, which orphaned the live
members of a list whose last selector was dead — `.algo-output` is the
last of eleven selectors on one rule, not a rule of its own.

Deliberately untouched: the 16,495 comment lines in js/, which record
which bug each rule prevents and are the only place that is written down;
and the per-theme alphas in css/variables.css, which are hand-tuned and
so cannot be collapsed into color-mix() without changing what is painted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 17, 2026 14:54
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

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.

@thethinkmachine
thethinkmachine merged commit 53cf9fc into main Sep 17, 2026
5 checks passed
@thethinkmachine
thethinkmachine deleted the chore/remove-dead-code branch September 17, 2026 14:55
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