Skip to content

Daily dead-code sweep 2026-09-29: directions.matrix, TERM_NAMES - #148

Open
EnesYilmazcode wants to merge 3 commits into
mainfrom
deadcode/2026-09-29
Open

EnesYilmazcode wants to merge 3 commits into
mainfrom
deadcode/2026-09-29

Conversation

@EnesYilmazcode

Copy link
Copy Markdown
Owner

Automated daily dead-code sweep. Baseline node --test on main (a1ede09): 932 tests, 928 pass, 4 skipped, 0 fail — green, so I fixed nothing and proceeded.

Checked against open sweep PRs first (per the routine's rule against re-finding the same code): read the full diffs of #147 (deadcode/2026-09-27, the #chips shim), #146 (deadcode/2026-09-24, inBounds), #144 (deadcode/2026-09-23, bestGap/pickGap export), and #143 (deadcode/2026-09-22, allWeekCodes). Neither finding below overlaps any of those four diffs.

Findings, most certain first

1. directions.matrix() and MATRIX_MAX — js/directions.js (was lines 24, 144-179)

What it is: createDirections() returns an object with steps(), invalidate(), a generation getter, and a matrix() method that batches walking times to many buildings via Google's DistanceMatrixService, gated by MATRIX_MAX = 25.

How I proved it dead: this isn't a coverage question, it's a call-graph one. js/app.js is the only production caller of the object createDirections() returns (constructed once, at js/app.js:3590), and I grepped every use of state.directions in it: .invalidate() (line 2077), a truthiness check for the "Step by step" button (lines 2442, 2456), and .steps() (line 2507). .matrix never appears. I then grepped matrix( and MATRIX_MAX across js/ scripts/ index.html dev/ spikes/ docs/: the only other hits are scripts/test/directions.test.mjs, which calls d.matrix(...) directly against the module, not through anything the app does. So no user interaction, dev scene, or refusal state can ever reach it — there's no path to it at all, driven or undriven. Since .matrix() is an object method rather than a top-level export, scripts/check-dead-code.mjs (which only walks top-level declarations) can't see it; that's why it reported clean.

What would make me wrong: a caller I missed reaching state.directions.matrix through a property access built from a string (e.g. state.directions['ma' + 'trix']) or reflection. I grepped for directions\[ and found nothing, and this codebase's style (plain property access throughout) makes that unlikely.

Removed: the matrix() method, MATRIX_MAX, and the two comment blocks that exist only to explain matrix() (the "ranking half is opt-in" paragraph in the file header, and the doc comment directly above the method). The paragraph pointed at docs/research/walking-routes-115.md for the underlying design record, which I left untouched — only the code-comment pointer to it, describing the now-removed method, came out. In scripts/test/directions.test.mjs: removed the MATRIX_MAX import, the DistanceMatrixService fake and its calls.matrix counter (nothing constructs one anymore), the four matrix-only tests, and the .matrix(...) assertions embedded in two shared tests (without consent, a rejected request) — the .steps() half of each of those already covers the same shared ready()/consent/timeout logic, so no behavior loses coverage.

2. TERM_NAMES — js/state.js:104

What it is: export const TERM_NAMES = { 2: 'Spring', 4: 'Summer', 8: 'Autumn' };, sitting next to ROOM_FLOOR (which floorFor() does use).

How I proved it dead: grepped TERM_NAMES across the whole repo. Zero hits anywhere except its own declaration — not in js/app.js, not in any test file, not in scripts/, not in index.html or dev/. scripts/build-index.mjs has its own unrelated, unexported const TERM_NAMES (a build-time lookup with the same shape, coincidentally the same name) — that's a separate binding in a separate file, not a use of this export. This is a stronger case than the object-method finding above: it isn't even test-exercised, so there's no ambiguity about a code path reaching it under some state I didn't drive. The app gets its term name from current.termName directly (see resolveState's current?.termName ?? 'This term'), so this table looks like a leftover from before that.

What would make me wrong: nothing I can think of — a zero-reference exported binding either gets used somewhere I didn't grep, or it doesn't exist as a live code path at all.

Runtime coverage attempted, for context

I built a throwaway coverage harness on top of scripts/lib/browser.mjs / pinned-clock.mjs (never committed) to look for dead CSS selectors and unreachable UI branches, the kind of finding neither grep nor check-dead-code.mjs can prove alone. Before running it broad, I did a full static pass first: every class/id selector in index.html's stylesheet, every sprite <symbol>, and every CSS custom property all resolve to at least one real reference in js/*.js or dev/*.html (icons in particular are built as template strings in js/app.js, e.g. WALK_ICON/CHEV, not literal markup, so a naive index.html-only grep undercounts them — I checked js/*.js too). That came back clean, so I did not find a CSS or markup candidate worth driving the full coverage harness to confirm.

I also worked out real dates in the shipped data/rooms-1268.json/data/current.json for each refusal, to know what's actually reachable this term:

  • Thanksgiving: 2026-11-25 is no-classes (ranks, with a note); 2026-11-26 is offices-closed → CAMPUS_CLOSED.
  • Finals week: 2026-12-11 → EXAM_REFUSAL.
  • Campus closed: 2026-09-07 (Labor Day) → CAMPUS_CLOSED.
  • Saturday 3am: outside roomSearchOn's 7am-11pm weekend window → the unscheduled gate/buildings screen, not one of the six refusal kinds.
  • "Between terms": reachable only as the "has not started yet" flavor of BETWEEN_TERMS (2026-07-31, before the 08-25 instruction start). The other flavor — "campus is between terms, next term begins X" — needs current.next, which the shipped data/current.json doesn't carry yet (no next-term harvest exists), so it's not reachable with real data right now. Left alone, not claimed as dead.
  • Schedule-dark (SCHEDULE_DARK): I scanned scheduleCoverage() over every date in and around the term. Coverage never drops below the 10% SILENT_SHARE floor anywhere inside the actual instruction window (2026-08-25 to 2026-12-09) — every date low enough to trip it is also caught by the out-of-term check first, which runs earlier in refusalFor. So this is a defensive branch with no real-data path to it right now, not a live one I failed to drive. Per the rules, not touched.

I did not get as far as actually driving the coverage harness through boot/refusal/menu/dev-panel states end to end before concluding the CSS and markup side had nothing to show for it, so I'm not claiming exhaustive runtime proof beyond the two call-graph findings above — those two don't need it (nothing anywhere calls them, driven or not).

Not removed, not proven

Nothing else. I looked at js/route.js's metresToPoint/offGraphMetres (same "app has no use for it" shape as the two findings above) but both are genuinely used — the former by docs/research/walking-graph-sample.mjs, the latter by scripts/test/walk-graph.test.mjs — so I left them alone.

Verification

  • node --test: 928 tests, 924 pass, 4 skipped, 0 fail (4 fewer than baseline — exactly the four matrix()-only tests removed).
  • node scripts/check-dead-code.mjs: clean.
  • Re-measured the sw.js shell gzip figure after the deletions (both removed files are in SHELL_ASSETS) and ran node scripts/stamp-sw.mjs: shell 164,286 → 163,573 bytes, header re-dated 2026-09-29, SHELL_CACHE restamped.
  • node scripts/shoot.mjs --check: passed (one earlier run hit the documented boot() navigation race and threw; reproduced the same flake against unmodified main too, so it's unrelated to this change — a clean re-run confirmed no visual regression).

Neither change touches anything reachable from the shipped UI, so no screenshots moved.

🤖 Generated with Claude Code

https://claude.ai/code/session_01GCaTB3nB6X3MkbBCyge5aD


Generated by Claude Code

Both had no caller outside their own declaration and tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GCaTB3nB6X3MkbBCyge5aD

Copy link
Copy Markdown
Owner Author

Merged main into this branch to resolve a real conflict in sw.js (main had advanced 15 commits, including its own shell-cache restamp). Both conflicting pieces were generated/measured values, not logic, so I resolved them with the repo's own tooling rather than by hand:

  • The gzip-figure header comment: re-measured shell/data bytes against the merged file set per the comment's own recipe (git show HEAD:<file> | gzip -9 -c | wc -c), same methodology scripts/test/sw.test.mjs checks — shell 168,101 bytes, data 116,033 bytes, dated 2026-10-04.
  • SHELL_CACHE: resolved to a placeholder, then regenerated with node scripts/stamp-sw.mjs → vacant-shell-898b152.

Verified after merging: node --test (930 pass, 4 skipped, 0 fail) and node scripts/check-dead-code.mjs (clean) on the merged tree.

node scripts/shoot.mjs --check fails on this branch with three real (non-flake) failures on the room/list screens — "the map is on screen with nothing on it", "the sheet rests at 324px, not over the map", "the sheet did not drop (324 → 324)". I checked these against origin/main directly (no dead-code changes, nothing from this PR): identical three failures reproduce there too. So this isn't something this merge introduced — it's a pre-existing regression on main, most likely from the recent desktop-panel/map-pan work (#166-168). Not fixing it from this PR since it's out of this sweep's scope; flagging it here since it'll show the same way on any PR based on current main.

Pushed the merge commit (fbc1218) to this branch; waiting on CI now.


Generated by Claude Code

This branch has not been deployed

No deployments
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