Debloat the repository: comments cut to the reasons, docs to their decisions #229

Merged
Grandiras merged 19 commits from debloat into main 2026-09-23 15:16:28 +00:00
Owner

The repository was about 40% comments by volume, and docs/ was long-form essays. This PR cuts both down to the reasons, removes dead code and duplication, and changes nothing a member can see.

Tracked text: 2.87 MB → 1.91 MB (−34%), 58.8k → 45.9k lines. That excludes migrations, binaries, vendored sortable.min.js and lockfiles, none of which were touched.

Area Before After
docs/ 371 KB 152 KB (40%)
src/ 1.54 MB 1.07 MB (69%)
tests/ 654 KB 477 KB (72%)
deploy/ 143 KB 85 KB (59%)
.claude/, tools/, .forgejo/ 57 KB 38 KB
CLAUDE.md 14.1 KB 8.4 KB

Comment share: C# 39% → 21%, Razor 33% → 12%, JS 40% → 21%, CSS 41% → 17%.

What stays, what goes

Comments that stay: a non-obvious why, an invariant, a trap (in one clause), a security reason, a measurement behind an odd shape, and upstream issue numbers. Comments that go: anything restating the code, history, repetition, <remarks> essays and banners.

Docs: every page keeps its Covers: line and every decision, trap and command. One page owns each topic and the others link to it. CLAUDE.md keeps its routing table, commands and every convention, each compressed to one line.

Code, beyond comments

Behaviour is preserved throughout.

  • Merged duplicates:
    • Cards and columns share one midpoint-placement routine (CardService.PlaceAt).
    • Soft delete and restore of boards share one body.
    • The three entrance gates in auth-enter.js are one factory. The old and new versions were diffed under a fake DOM across 13 scenarios.
    • The four board-settings pages share a base class (SettingsPage) and a frame component (SettingsFrame). The rendered markup is identical.
    • Also merged: the calendar interop imports, the .ics 404 handling, the rate-limit policies, the sign-in claim builders, and the encryptor's error messages.
  • Dead code removed:
    • AccessRequestService.CountPendingAsync, AllowlistOptions.Members (and its unused config key), BoardPalette.Count, and the isPhoneViewport JS export.
    • 8 unused translation keys, in both locales.
    • Template leftovers in app.css: Blazor form-validation and error-boundary classes, --info and --success-bg, and a @keyframes that a later one with the same name always overrode.
    • Assorted private helpers.
  • Unchanged: the EF model (the entity and context code is identical once comments are stripped), routes, config keys, CSS classes, ids, data-* attributes, interop names, test titles, and the behaviour of every deploy script. The deploy scripts are line-identical once comments are removed.

Tests

  • Unit: 560 → 558. The two removed tests asserted exactly the same input and outcome as another case. Shared fixtures moved into Fixtures.cs. DocumentationTests keeps every check and threshold.
  • E2E: the same 154 tests with the same titles. Sign-in, board, card and menu helpers moved into tests/e2e/helpers/, replacing about 20 private copies.

Verification

  • dotnet build Ponente.sln -c Release: 0 warnings, 0 errors.
  • dotnet test: 558/558.
  • Full Playwright suite: 154/154. It ran against an isolated copy of the test stack on ports 18090–18092, so the shared ponente stack was never touched. The first run failed one test (a local variable shadowing a new helper in calendar.spec.js); that is fixed in acd2c13.

Not in this PR

These are pre-existing issues found along the way and filed as separate tasks:

  • restore.sh exits silently with no .env beside it. backups.md documents a touch .env workaround for now.
  • release.sh prints a wrong next step.
  • The GetColumnsAsync comment says "one query", but the app-wide default is SplitQuery.
  • Three calendar specs lean on cards made by earlier tests.

No changelog entry: members see no change.

🤖 Generated with Claude Code

The repository was about 40% comments by volume, and `docs/` was long-form essays. This PR cuts both down to the reasons, removes dead code and duplication, and changes nothing a member can see. **Tracked text: 2.87 MB → 1.91 MB (−34%), 58.8k → 45.9k lines.** That excludes migrations, binaries, vendored `sortable.min.js` and lockfiles, none of which were touched. | Area | Before | After | |---|---|---| | `docs/` | 371 KB | 152 KB (40%) | | `src/` | 1.54 MB | 1.07 MB (69%) | | `tests/` | 654 KB | 477 KB (72%) | | `deploy/` | 143 KB | 85 KB (59%) | | `.claude/`, `tools/`, `.forgejo/` | 57 KB | 38 KB | | `CLAUDE.md` | 14.1 KB | 8.4 KB | Comment share: C# 39% → 21%, Razor 33% → 12%, JS 40% → 21%, CSS 41% → 17%. ## What stays, what goes **Comments that stay:** a non-obvious why, an invariant, a trap (in one clause), a security reason, a measurement behind an odd shape, and upstream issue numbers. **Comments that go:** anything restating the code, history, repetition, `<remarks>` essays and banners. **Docs:** every page keeps its `Covers:` line and every decision, trap and command. One page owns each topic and the others link to it. `CLAUDE.md` keeps its routing table, commands and every convention, each compressed to one line. ## Code, beyond comments **Behaviour is preserved throughout.** - **Merged duplicates:** - Cards and columns share one midpoint-placement routine (`CardService.PlaceAt`). - Soft delete and restore of boards share one body. - The three entrance gates in `auth-enter.js` are one factory. The old and new versions were diffed under a fake DOM across 13 scenarios. - The four board-settings pages share a base class (`SettingsPage`) and a frame component (`SettingsFrame`). The rendered markup is identical. - Also merged: the calendar interop imports, the `.ics` 404 handling, the rate-limit policies, the sign-in claim builders, and the encryptor's error messages. - **Dead code removed:** - `AccessRequestService.CountPendingAsync`, `AllowlistOptions.Members` (and its unused config key), `BoardPalette.Count`, and the `isPhoneViewport` JS export. - 8 unused translation keys, in both locales. - Template leftovers in `app.css`: Blazor form-validation and error-boundary classes, `--info` and `--success-bg`, and a `@keyframes` that a later one with the same name always overrode. - Assorted private helpers. - **Unchanged:** the EF model (the entity and context code is identical once comments are stripped), routes, config keys, CSS classes, ids, `data-*` attributes, interop names, test titles, and the behaviour of every deploy script. The deploy scripts are line-identical once comments are removed. ## Tests - **Unit:** 560 → 558. The two removed tests asserted exactly the same input and outcome as another case. Shared fixtures moved into `Fixtures.cs`. `DocumentationTests` keeps every check and threshold. - **E2E:** the same 154 tests with the same titles. Sign-in, board, card and menu helpers moved into `tests/e2e/helpers/`, replacing about 20 private copies. ## Verification - `dotnet build Ponente.sln -c Release`: 0 warnings, 0 errors. - `dotnet test`: 558/558. - **Full Playwright suite: 154/154.** It ran against an isolated copy of the test stack on ports 18090–18092, so the shared `ponente` stack was never touched. The first run failed one test (a local variable shadowing a new helper in `calendar.spec.js`); that is fixed in acd2c13. ## Not in this PR These are pre-existing issues found along the way and filed as separate tasks: - `restore.sh` exits silently with no `.env` beside it. `backups.md` documents a `touch .env` workaround for now. - `release.sh` prints a wrong next step. - The `GetColumnsAsync` comment says "one query", but the app-wide default is `SplitQuery`. - Three calendar specs lean on cards made by earlier tests. No changelog entry: members see no change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Comments in Auth/, Encryption/ and the profile, PDS, access-request, mail and
feedback services trimmed to one-line whys: the allowlist, invite gating, the
enc:v1: envelope and its measurements, address validation, the dev-login token trap.
Removed the unused AccessRequestService.CountPendingAsync and AllowlistOptions.Members,
sealed HandleResolver (no test substitutes it), and deduplicated the encryptor's errors.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in the fifteen search, calendar, share-link, markdown and resume
services are cut to the why, the traps and the security rules, one line each.
Duplicated logic merged: CardSearch's phrase and term scoring share one loop,
Normalize builds on Fold, and CalendarFeedService mints tokens in one place.
CardPreview's hand-rolled line enumerator gives way to span Split, and a few
one-call helpers are inlined. No behaviour, signature or route changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes eight translation keys nothing renders, in both locales: nav.admin,
login.title, login.subtitle, login.signup.hint, login.signup.link,
admin.invites.create, admin.invites.existing and cal.overdue.
Trims the doc comments in LocaleService and Changelog to the reasons, and folds
the private IsSupported/Normalize helpers into IsSupportedLocale.
Release entries and the Unreleased/Releases shapes promote-changelog.py matches are untouched.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in wwwroot/js, service-worker.js and offline.html now keep only the
traps and reasons (the preload header trap, the press-to-drag rule, dragScroll).
auth-enter.js's three copies of the board/calendar/home gate are one per-page
factory with one history hook; behaviour checked identical in a fake-DOM diff.
Unused isPhoneViewport export and column-sort init's unused parameters removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in Calendar.razor, BoardPage.razor and Home.razor are cut to the
non-obvious why, the traps and the attribution; the markup is unchanged.
Duplicated code is folded: one calendar interop import helper, one link query
for the download and the feed, one JS module teardown helper, one DID read in Home.
Dead code goes: Calendar's _swipeWired and SetScale, and the OnBoardsChangedExternally wrappers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in the eighteen board, card, member and permission services are cut
to the reasons a later edit could break, with the long rationale left to docs/.
Card and column moves share one midpoint helper (CardService.PlaceAt), placing
a card at a column's bottom is one query helper, and the soft delete and
restore paths share one body each. BoardPalette.Count, which nothing read, is gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Program.cs, KanbanDbContext, DatabaseInitializer, EncryptionMigrator and the
entities keep one line per non-obvious why, trap or invariant; the essays go.
Program.cs dedupes its three per-IP rate limit policies, three claim-building
blocks and the two .ics result branches into local helpers. The configured
super-admin list is computed once at startup. The EF model is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in the auth, request, profile, admin and settings pages are cut to the
non-obvious why, and redundant usings and a redundant @implements are gone.
The four board settings pages share one base class (SettingsPage: board
resolution, the reload guard, the viewer) and one frame component
(SettingsFrame: header, phone bar, title, refusal states, tabs); the markup
they render is unchanged. Dead BoardId properties and duplicate helpers removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Razor, XML-doc and inline-script comments across Components/ (root, Board,
Layout, Settings) trimmed to the why, the traps and the constraints.
Duplicated bits merged: DeletedBoardState's viewer lookup, AssigneePicker's
menu shut-down, CardModal's two close handlers, NavHeader's switcher tick
SVG, ReconnectModal.razor.js's deferral. Redundant @usings dropped.
The generated render trees were diffed against main: identical DOM.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in the calendar, mobile, search, share, requests, changelog, prefs,
reconnect, install, auth-entrance, i18n, profile, feedback, icons and pds specs
are down to one-line reasons; banners and history are gone. Local helpers now
carry repeated setup (pageScrolls and chip in calendar, touchPhone in mobile,
openAdminMembers in requests), and prefs deletes its board with deleteBoard.
Every test title and assertion is unchanged; profile's real-account guards stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shell scripts, systemd units, compose file and env templates keep every
line of code, key and value; only comments changed (checked line by line
against the originals, and the compose file parses identically). The help
text deploy.sh and restore.sh print from their headers is untouched.
README.md, backups.md and postgres-upgrade.md keep every step and command
at about half the length, and backups.md now notes the empty .env a bare-machine restore needs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
calendar, auth, search, testing, data, live-updates, access-requests,
deployment, lexicons, brand and i18n cut from 178 KB to 72 KB: history and
narrative dropped, each decision and trap kept as a bullet with its reason.
Caddy's on-demand TLS ask endpoint moved from auth.md to deployment.md, and
cross-page repeats (@bind, dev sign-in, ?handle=) now live on one page each.
i18n.md now names TranslationTests for the parity and plural checks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLAUDE.md, orientation.md and the boards, UI and front-end pages keep every
decision, invariant and trap with a one-line reason and drop the history and
narrative. Topics explained twice now live on one page and are linked from the
other. AGENTS.md is a pointer, and README.md covers what the app is, how to run
and deploy it, and where the docs are.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments shrink from ~107 KB to ~32 KB: essays and history become one-line
reasons, and banners become short section names. Removes the unused Blazor
form/error-boundary scaffolding, .field-label, .login-card form .hint, the
unused --info and --success-bg tokens, and a phone-only @keyframes flyoutIn
that the top-level one always overrode. Also drops two overridden
declarations and merges two adjacent same-selector rules.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
release/SKILL.md goes from 22 KB to 13 KB with every step and gate kept (approval
before the tag, the dev digest check, the env check, rollback, diagnostics).
Script, workflow and compose comments are cut to the why; parsed YAML and shell
code are unchanged apart from verify.sh's help range, now 2,11p.
design/trace: capture.mjs scenarios share sign-in helpers, extract.js has one
shape-to-path function, build.py one place() step; dead code and imports removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments in the board, home, filter, entrance, access, permissions and
moderation specs, the helpers and the global setup/teardown are cut to one-line
reasons. Sign-in, didOf, card and comment creation, the composer opener and the
fill-until-enabled retry now live once in helpers/ (new exports only), and the
card deletions that only existed to empty a board before deleting it are gone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The fourteen specs that still carried their own copy of devLogin, ADMIN_DID or
the nav-menu opener import them from helpers/ instead. The docs stop naming a
method, a JS export and line numbers that are gone, the ignored column-sort
dispose argument goes, and so does the Allowlist:Members key nothing binds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comments and class summaries trimmed to the non-obvious why, traps and security reasons.
New Fixtures.cs holds what several classes duplicated: the repo-root lookup, the HTTP stub,
the calendar card/tag/filter builders and the test DIDs. Two true duplicate tests removed
(BoardPermissions super-admin case, LastPage "/" case); their reasons now sit on the kept case.
DocumentationTests keeps every check, threshold and allow-list; only prose and messages shrank.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
calendar.spec.js: a chip's local no longer shadows the chip() helper
All checks were successful
CI / build (pull_request) Successful in 44s
acd2c134a4
The debloat folded the chip locators into a chip(page, title) helper; one test
still declared its own const chip = chip(...), a temporal-dead-zone error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collaborator

🤖 Reviewing this PR — the review will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the review runs.

🤖 Reviewing this PR — the review will link the full session transcript. <!-- opencode-run:review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-229/run-2026-09-23T14-42-15-979Z.md) — updating every ~5 minutes while the review runs.
opencode-reviewer left a comment

💬 Verdict: comment — the reviewer did not submit a structured review; the raw output follows.

(empty)


⏱ 30m 3s · 142 steps · $0.9926 · tokens: 1648.3k in / 40.9k out (+24129.3k cache-read) · Go: 5h 0% · wk 83% · mo 74%
📜 Full session transcript

💬 **Verdict: comment** — the reviewer did not submit a structured review; the raw output follows. (empty) --- ⏱ 30m 3s · 142 steps · $0.9926 · tokens: 1648.3k in / 40.9k out (+24129.3k cache-read) · Go: 5h 0% · wk 83% · mo 74% 📜 [Full session transcript](https://git.grandiras.net/Grandiras/opencode-bot/src/branch/opencode-logs/transcripts/Grandiras/Ponente/pr-229/run-2026-09-23T14-42-15-979Z.md)
Collaborator

🔧 Let opencode-bot fix this — tick the box and opencode-bot picks up the review above, on this PR branch. Nothing runs until you do.

  • @opencode-bot Address the findings of the latest review on this pull request.
🔧 **Let opencode-bot fix this** — tick the box and opencode-bot picks up the review above, on this PR branch. Nothing runs until you do. - [ ] @opencode-bot Address the findings of the latest review on this pull request. <!-- opencode-fix-button:229 -->
Author
Owner
@claude-reviewer
Collaborator

🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.

📜 Live transcript — updating every ~5 minutes while the task runs.

🤖 Reviewing this PR — follow along in [the action run](https://git.grandiras.net/Grandiras/claude-bot/actions/runs/573); the reply will link the full session transcript. <!-- claude-run:pr_review --> 📜 [Live transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-229/run-573.md) — updating every ~5 minutes while the task runs.
claude-reviewer left a comment

✅ Verdict: approve — no blocking issues found.

This is a large, mechanical debloat pass (comments, docs, dead code, duplication) spanning ~256 files. Given the size, I sampled the highest-risk merges rather than reading every hunk line-by-line:

  • CardService.PlaceAt / ColumnService's use of it: the extracted midpoint-placement routine is byte-for-byte equivalent to the two inlined copies it replaces (clamp, midpoint switch, precision-exhaustion renormalize guard all preserved).
  • BoardService soft-delete/restore consolidation (MarkDeletedAsync/UndeleteAsync): the moderation-delete guard on restore (DeletedAsModeration && !asSuperAdmin) is preserved correctly for both the owner-admin and super-admin paths.
  • AesGcmDataEncryptor/IDataEncryptor: purely comment/doc trimming plus a trivial two-line factoring of the exception messages (TooShort()/WrongKey()); crypto logic untouched.

All three held up — the PR's "behaviour is preserved" claim checks out where I looked. The doc/comment trims read reasonably (reasons kept, restated-code and history dropped), matching the stated policy in CLAUDE.md. I did not fully re-verify the auth-enter.js entrance-gate factory or the SettingsPage/SettingsFrame markup-identity claim beyond skimming — those are plausible given the PR's own claimed diff-under-fake-DOM verification and the passing full Playwright run, but are lower-confidence in my own review.

No correctness issues found in the portions reviewed. Given the scale (256 files, 13k net line delta) and that this is inherently hard to fully audit by hand, approving on the strength of the sampled checks plus the reported build/test/e2e results.


⏱ 1m 7s · 18 turns · tokens: 109.9k in / 5.7k out (+1873.5k cache-read)
📜 Full session transcript

✅ **Verdict: approve** — no blocking issues found. This is a large, mechanical debloat pass (comments, docs, dead code, duplication) spanning ~256 files. Given the size, I sampled the highest-risk merges rather than reading every hunk line-by-line: - `CardService.PlaceAt` / `ColumnService`'s use of it: the extracted midpoint-placement routine is byte-for-byte equivalent to the two inlined copies it replaces (clamp, midpoint switch, precision-exhaustion renormalize guard all preserved). - `BoardService` soft-delete/restore consolidation (`MarkDeletedAsync`/`UndeleteAsync`): the moderation-delete guard on restore (`DeletedAsModeration && !asSuperAdmin`) is preserved correctly for both the owner-admin and super-admin paths. - `AesGcmDataEncryptor`/`IDataEncryptor`: purely comment/doc trimming plus a trivial two-line factoring of the exception messages (`TooShort()`/`WrongKey()`); crypto logic untouched. All three held up — the PR's "behaviour is preserved" claim checks out where I looked. The doc/comment trims read reasonably (reasons kept, restated-code and history dropped), matching the stated policy in CLAUDE.md. I did not fully re-verify the `auth-enter.js` entrance-gate factory or the `SettingsPage`/`SettingsFrame` markup-identity claim beyond skimming — those are plausible given the PR's own claimed diff-under-fake-DOM verification and the passing full Playwright run, but are lower-confidence in my own review. No correctness issues found in the portions reviewed. Given the scale (256 files, 13k net line delta) and that this is inherently hard to fully audit by hand, approving on the strength of the sampled checks plus the reported build/test/e2e results. --- ⏱ 1m 7s · 18 turns · tokens: 109.9k in / 5.7k out (+1873.5k cache-read) 📜 [Full session transcript](https://git.grandiras.net/Grandiras/claude-bot/src/branch/claude-logs/transcripts/Grandiras/Ponente/pr-229/run-573.md) <!-- claude-verdict:approve --> <!-- claude-reviewed-head:acd2c134a46e2a4d3a37ed65f6bed4bf4c4c703c -->
Grandiras deleted branch debloat 2026-09-23 15:16:28 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
5 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/Ponente!229
No description provided.