epic(legibility): polish — remove smells surfaced by audits #411

Closed
opened 2026-05-04 16:16:33 +02:00 by marcel · 8 comments
Owner

Epic context

This is Epic 5 of 5 for the Codebase Legibility Refactor (see #387).

After Epic 4 has restructured the code, Epic 5 cleans up everything the audits found that wasn't structural: dead code (C10.1), vague or obsolete comments (C7.3), naming violations (C4.3), and repo-root hygiene (C1.5). Then CLEANUP-5 re-runs the readiness scorecard to confirm the codebase is ready for evaluation.

Scope

  • CLEANUP-1: Remove dead code identified by audits
  • CLEANUP-2: Rewrite vague comments and remove "ask Marcel" / "Claude generated" markers
  • CLEANUP-3: Fix Helper/Utils/Manager naming violations
  • CLEANUP-4: Repo hygiene — proofshot-artifacts retention, .agent/.worktrees gitignore
  • CLEANUP-5: Re-run readiness scorecard; ratify "ready for evaluation"

Acceptance criteria

  • All 5 child issues are closed
  • Final docs/LEGIBILITY-READINESS.md (refreshed by CLEANUP-5) gives 🟢 verdicts on §5 (refactor readiness) AND §6 (evaluation readiness)
  • All Critical and Major findings from Epic 1's audit reports are either closed (work done) or explicitly accepted with a written justification

Definition of Done

CLEANUP-5 closes with a 🟢🟢 verdict. The codebase is ready to send to Anja and Tobias.

Dependency

  • Blocked by: Epic 1 (audit findings define the cleanup scope) and Epic 4 (refactor must complete before cleanup runs)
  • Concludes: the entire Codebase Legibility milestone
## Epic context This is **Epic 5 of 5** for the *Codebase Legibility Refactor* (see #387). After Epic 4 has restructured the code, Epic 5 cleans up everything the audits found that wasn't structural: dead code (C10.1), vague or obsolete comments (C7.3), naming violations (C4.3), and repo-root hygiene (C1.5). Then **CLEANUP-5 re-runs the readiness scorecard** to confirm the codebase is ready for evaluation. ## Scope - **CLEANUP-1**: Remove dead code identified by audits - **CLEANUP-2**: Rewrite vague comments and remove "ask Marcel" / "Claude generated" markers - **CLEANUP-3**: Fix Helper/Utils/Manager naming violations - **CLEANUP-4**: Repo hygiene — proofshot-artifacts retention, .agent/.worktrees gitignore - **CLEANUP-5**: Re-run readiness scorecard; ratify "ready for evaluation" ## Acceptance criteria - [ ] All 5 child issues are closed - [ ] Final `docs/LEGIBILITY-READINESS.md` (refreshed by CLEANUP-5) gives 🟢 verdicts on §5 (refactor readiness) AND §6 (evaluation readiness) - [ ] All Critical and Major findings from Epic 1's audit reports are either closed (work done) or explicitly accepted with a written justification ## Definition of Done CLEANUP-5 closes with a 🟢🟢 verdict. The codebase is ready to send to Anja and Tobias. ## Dependency - **Blocked by:** Epic 1 (audit findings define the cleanup scope) and Epic 4 (refactor must complete before cleanup runs) - **Concludes:** the entire Codebase Legibility milestone
marcel added this to the Codebase Legibility milestone 2026-05-04 16:16:33 +02:00
marcel added the cleanupepiclegibility labels 2026-05-04 16:16:49 +02:00
Author
Owner

👨‍💻 Felix Brandt — Senior Fullstack Developer

Observations

  • CLEANUP-2 (vague comments) — The two confirmed TODOs I found in the current codebase are:

    • frontend/src/routes/admin/+layout.server.ts:29 — a TODO to replace a fat user-load with a dedicated stats endpoint. This is a real action item, not just a comment smell; it needs a linked issue before it's removed.
    • frontend/src/lib/components/chronik/ChronikRow.svelte:163 — a TODO noting the backend doesn't yet expose a comment body preview. This is a cross-domain note about a missing API feature; it needs a linked issue.
    • Both are well-formed TODOs, not "ask Marcel" or Claude-attribution markers. The issue title says remove "ask Marcel" markers — I found none in any source file. Either they were already cleaned up or the audit needs to confirm exactly where they are.
  • CLEANUP-3 (naming violations) — Only one confirmed violator in main source: SecurityUtils.java. It's a final class with a private constructor and one static method. This is the classic "I didn't know where else to put this" pattern. The right fix is to dissolve it: move requireUserId() logic into a @Component like AuthenticatedUserResolver or integrate it into the PermissionAspect. A static utils class breaks testability and signals a missing abstraction.

  • CLEANUP-1 (dead code) — Both files flagged in my search (DocumentController.java, ThumbnailService.java) turn out to contain legitimate comments explaining design decisions, not actual dead code. The audit reports (not yet written) will surface the real list. CLEANUP-1 should not start until AUDIT-1 and AUDIT-2 produce that list.

  • Ordering risk — The epic notes CLEANUP-5 is blocked by Epic 1 (audits) and Epic 4 (refactor). But CLEANUP-1 through CLEANUP-4 are listed here as if they can start now. They shouldn't — CLEANUP-1 specifically requires the audit findings as input. Child issues #412–#415 should carry explicit "Blocked by #388/#389" dependencies.

Recommendations

  • Add depends_on: [#388, #389] (audit-frontend, audit-backend) to child issues #412 and #413 before any implementation starts. Running cleanup blind risks removing code the audit would have explained.
  • For SecurityUtils.java: rename to AuthenticationHelper — wait, that's still a violation. The right move is CurrentUserResolver as a Spring @Component, injected where needed. This turns a static untestable util into a mockable dependency, which is a testability improvement, not just a rename.
  • The two frontend TODOs should each get a linked Gitea issue in CLEANUP-2's description so they close cleanly: one for the admin stats endpoint (#NNN), one for the comment preview API. Neither should be simply deleted — they represent real backlog items.
  • CLEANUP-5 (docs/LEGIBILITY-READINESS.md refresh) depends on all prior cleanup being done. Verify that #416 (scorecard re-run) lists all four cleanup issues as blockers, not just the refactor epic.
## 👨‍💻 Felix Brandt — Senior Fullstack Developer ### Observations - **CLEANUP-2 (vague comments)** — The two confirmed TODOs I found in the current codebase are: - `frontend/src/routes/admin/+layout.server.ts:29` — a TODO to replace a fat user-load with a dedicated stats endpoint. This is a real action item, not just a comment smell; it needs a linked issue before it's removed. - `frontend/src/lib/components/chronik/ChronikRow.svelte:163` — a TODO noting the backend doesn't yet expose a comment body preview. This is a cross-domain note about a missing API feature; it needs a linked issue. - Both are well-formed TODOs, not "ask Marcel" or Claude-attribution markers. The issue title says _remove "ask Marcel" markers_ — I found none in any source file. Either they were already cleaned up or the audit needs to confirm exactly where they are. - **CLEANUP-3 (naming violations)** — Only one confirmed violator in main source: `SecurityUtils.java`. It's a `final` class with a private constructor and one static method. This is the classic "I didn't know where else to put this" pattern. The right fix is to dissolve it: move `requireUserId()` logic into a `@Component` like `AuthenticatedUserResolver` or integrate it into the `PermissionAspect`. A static utils class breaks testability and signals a missing abstraction. - **CLEANUP-1 (dead code)** — Both files flagged in my search (`DocumentController.java`, `ThumbnailService.java`) turn out to contain legitimate comments explaining design decisions, not actual dead code. The audit reports (not yet written) will surface the real list. CLEANUP-1 should not start until AUDIT-1 and AUDIT-2 produce that list. - **Ordering risk** — The epic notes CLEANUP-5 is blocked by Epic 1 (audits) and Epic 4 (refactor). But CLEANUP-1 through CLEANUP-4 are listed here as if they can start now. They shouldn't — CLEANUP-1 specifically requires the audit findings as input. Child issues #412–#415 should carry explicit "Blocked by #388/#389" dependencies. ### Recommendations - Add `depends_on: [#388, #389]` (audit-frontend, audit-backend) to child issues #412 and #413 before any implementation starts. Running cleanup blind risks removing code the audit would have explained. - For `SecurityUtils.java`: rename to `AuthenticationHelper` — wait, that's still a violation. The right move is `CurrentUserResolver` as a Spring `@Component`, injected where needed. This turns a static untestable util into a mockable dependency, which is a testability improvement, not just a rename. - The two frontend TODOs should each get a linked Gitea issue in CLEANUP-2's description so they close cleanly: one for the admin stats endpoint (#NNN), one for the comment preview API. Neither should be simply deleted — they represent real backlog items. - CLEANUP-5 (`docs/LEGIBILITY-READINESS.md` refresh) depends on all prior cleanup being done. Verify that #416 (scorecard re-run) lists all four cleanup issues as blockers, not just the refactor epic.
Author
Owner

🏛️ Markus Keller — Application Architect

Observations

  • CLEANUP-3 is the structurally most interesting task. SecurityUtils.java is a static utility class with one method that resolves an authenticated user from Spring Security's Authentication. Static helpers that bridge framework and domain are a coupling antipattern: they cannot be mocked, they mix framework concerns into domain logic, and they suppress the real architectural question — who owns "resolve current user"? The answer is SecurityConfig and PermissionAspect own that concern. A @Component CurrentUserResolver with requireUserId(Authentication) as an instance method would be injectable, mockable, and correctly scoped.

  • CLEANUP-4 repo hygiene has a scoping ambiguity. The .gitignore already contains .worktrees/ but the git status shows .claude/worktrees/ (with the .claude/ prefix) as untracked — and .agent/ is also untracked at repo root. The issue title says "ignore .agent/.worktrees" but the current .gitignore only covers .worktrees/ (top-level), not .agent/ or .claude/worktrees/. The fix requires two lines: .agent/ and .claude/worktrees/ (or a glob). Check whether .claude/settings.json and .claude/personas/ should also be ignored or committed — that's a deliberate choice, but it needs to be stated explicitly.

  • proofshot-artifacts/ retention policy is undefined. Currently 44 files in 5 directories, 7.6MB. Without a policy, this grows unboundedly and clutters the repo root for any external developer. The clean approach: either commit a .gitignore entry for proofshot-artifacts/ entirely (they are dev-time verification artifacts, not source), or define a rolling retention (keep last N runs, delete older ones via a script). The first option is simpler and matches how .vitest-attachments is handled.

  • CLEANUP-5's Definition of Done references docs/LEGIBILITY-READINESS.md — this file doesn't exist yet; it's created by AUDIT-6 (#393). The scorecard re-run in CLEANUP-5 (#416) refreshes it after cleanup. This dependency chain is correct and should be documented as #416 blocked by #393 AND #412–#415.

  • The epic has no milestone link visible in the issue body. It is in the "Codebase Legibility" milestone (confirmed via issue list), but the acceptance criteria reference CLEANUP-5 closing with a "🟢🟢 verdict" — this verdict needs to be defined in #416's body, not just in this epic. If the scorecard criteria drift, the epic's DoD becomes unverifiable.

Recommendations

  • Resolve .agent/ vs .claude/worktrees/ ambiguity before CLEANUP-4 starts. Add both to .gitignore: .agent/ and .claude/worktrees/. Decide and document whether .claude/personas/, .claude/settings.json, and .claude/skills/ are project configuration (commit) or developer-local (ignore).
  • For proofshot-artifacts/: add to .gitignore. These are transient verification screenshots, not project history. A scripts/clean-proofshots.sh script that purges everything older than 30 days is a reasonable complement.
  • SecurityUtils.java dissolution belongs in CLEANUP-3, not CLEANUP-1. It's not dead code — it's a naming and structural violation. Make sure #414 (naming cleanup) covers it explicitly.
  • Add a comment on #416 now linking it to #412 AND #413 AND #414 AND #415 AND #393 as prerequisites. Otherwise the scorecard re-run might start before cleanup is complete.
## 🏛️ Markus Keller — Application Architect ### Observations - **CLEANUP-3 is the structurally most interesting task.** `SecurityUtils.java` is a static utility class with one method that resolves an authenticated user from Spring Security's `Authentication`. Static helpers that bridge framework and domain are a coupling antipattern: they cannot be mocked, they mix framework concerns into domain logic, and they suppress the real architectural question — who owns "resolve current user"? The answer is `SecurityConfig` and `PermissionAspect` own that concern. A `@Component CurrentUserResolver` with `requireUserId(Authentication)` as an instance method would be injectable, mockable, and correctly scoped. - **CLEANUP-4 repo hygiene has a scoping ambiguity.** The `.gitignore` already contains `.worktrees/` but the git status shows `.claude/worktrees/` (with the `.claude/` prefix) as untracked — and `.agent/` is also untracked at repo root. The issue title says "ignore .agent/.worktrees" but the current `.gitignore` only covers `.worktrees/` (top-level), not `.agent/` or `.claude/worktrees/`. The fix requires two lines: `.agent/` and `.claude/worktrees/` (or a glob). Check whether `.claude/settings.json` and `.claude/personas/` should also be ignored or committed — that's a deliberate choice, but it needs to be stated explicitly. - **proofshot-artifacts/ retention policy** is undefined. Currently 44 files in 5 directories, 7.6MB. Without a policy, this grows unboundedly and clutters the repo root for any external developer. The clean approach: either commit a `.gitignore` entry for `proofshot-artifacts/` entirely (they are dev-time verification artifacts, not source), or define a rolling retention (keep last N runs, delete older ones via a script). The first option is simpler and matches how `.vitest-attachments` is handled. - **CLEANUP-5's Definition of Done references `docs/LEGIBILITY-READINESS.md`** — this file doesn't exist yet; it's created by AUDIT-6 (#393). The scorecard re-run in CLEANUP-5 (#416) refreshes it after cleanup. This dependency chain is correct and should be documented as `#416 blocked by #393 AND #412–#415`. - **The epic has no milestone link visible in the issue body.** It is in the "Codebase Legibility" milestone (confirmed via issue list), but the acceptance criteria reference CLEANUP-5 closing with a "🟢🟢 verdict" — this verdict needs to be defined in #416's body, not just in this epic. If the scorecard criteria drift, the epic's DoD becomes unverifiable. ### Recommendations - Resolve `.agent/` vs `.claude/worktrees/` ambiguity before CLEANUP-4 starts. Add both to `.gitignore`: `.agent/` and `.claude/worktrees/`. Decide and document whether `.claude/personas/`, `.claude/settings.json`, and `.claude/skills/` are project configuration (commit) or developer-local (ignore). - For `proofshot-artifacts/`: add to `.gitignore`. These are transient verification screenshots, not project history. A `scripts/clean-proofshots.sh` script that purges everything older than 30 days is a reasonable complement. - `SecurityUtils.java` dissolution belongs in CLEANUP-3, not CLEANUP-1. It's not dead code — it's a naming and structural violation. Make sure #414 (naming cleanup) covers it explicitly. - Add a comment on #416 now linking it to `#412 AND #413 AND #414 AND #415 AND #393` as prerequisites. Otherwise the scorecard re-run might start before cleanup is complete.
Author
Owner

🔒 Nora "NullX" Steiner — Application Security Engineer

Observations

  • SecurityUtils.java is a security-adjacent class with a naming smell and a design smell. The static requireUserId() method does two things: it validates authentication state and it resolves an AppUser from the database. This dual responsibility means the authentication guard and the user lookup failure mode are tested together or not at all. If this class is missed during cleanup, it remains an untestable static dependency — which means security fixes to it cannot be covered by failing unit tests first.

  • The "remove 'ask Marcel' markers" task (CLEANUP-2) should include a sweep for any TODOs that defer security decisions. I found no // ask Marcel markers in the current source, but the two live TODOs are worth scrutinizing:

    • admin/+layout.server.ts:29 — the TODO defers creation of a stats endpoint that returns "counts only." The current code apparently loads full user/group data for a stats display. If it's loading more data than needed and exposing it to the admin template, that's a data-minimization finding worth noting in the audit before cleanup.
    • ChronikRow.svelte:163 — notes missing comment body preview. Low security relevance.
  • CLEANUP-5's scorecard should explicitly include a security readiness dimension. The current acceptance criteria check §5 (refactor readiness) and §6 (evaluation readiness) of the scorecard. If the rubric (C1–C10) includes security-related categories (C7/C10 look like candidates based on the issue text), those categories need 🟢 verdicts too before the codebase goes to Anja and Tobias. The DoD says "ready to send to Anja and Tobias" — make sure the scorecard has a security section, not just structural checks.

  • .agent/ directory at repo root — contains current-plan.md, PLAN.md, and multiple agent-* subdirectories. These directories may contain implementation plans that reference internal architecture decisions, credentials placeholders, or PII from the family archive use case. Before adding .agent/ to .gitignore, verify that none of the existing files contain information that shouldn't be in git history (they're currently untracked, so git history is clean). Adding .agent/** to .gitignore is the right call.

Recommendations

  • Before CLEANUP-1 runs, audit admin/+layout.server.ts:29's load function to confirm it isn't over-fetching sensitive user data for a stats panel. If it is, the TODO cleanup should include a note that the over-fetch is a data minimization finding — not just a code style issue.
  • The scorecard refresh in CLEANUP-5 (#416) should explicitly require 🟢 on any security-related rubric categories. Document this in #416's acceptance criteria.
  • Add .agent/ to .gitignore now (before CLEANUP-4 runs), and do a quick content scan of .agent/*.md for any credentials or sensitive paths before the directory grows further. This is a low-effort, low-risk win.
  • SecurityUtils.java dissolution in CLEANUP-3 must include a test: currentUserResolver_throws_unauthorized_when_authentication_is_null(). The test goes red, the rename/refactor goes green. No security class change without a test.
## 🔒 Nora "NullX" Steiner — Application Security Engineer ### Observations - **`SecurityUtils.java` is a security-adjacent class with a naming smell _and_ a design smell.** The static `requireUserId()` method does two things: it validates authentication state and it resolves an `AppUser` from the database. This dual responsibility means the authentication guard and the user lookup failure mode are tested together or not at all. If this class is missed during cleanup, it remains an untestable static dependency — which means security fixes to it cannot be covered by failing unit tests first. - **The "remove 'ask Marcel' markers" task (CLEANUP-2) should include a sweep for any TODOs that defer security decisions.** I found no `// ask Marcel` markers in the current source, but the two live TODOs are worth scrutinizing: - `admin/+layout.server.ts:29` — the TODO defers creation of a stats endpoint that returns "counts only." The current code apparently loads full user/group data for a stats display. If it's loading more data than needed and exposing it to the admin template, that's a data-minimization finding worth noting in the audit before cleanup. - `ChronikRow.svelte:163` — notes missing comment body preview. Low security relevance. - **CLEANUP-5's scorecard should explicitly include a security readiness dimension.** The current acceptance criteria check §5 (refactor readiness) and §6 (evaluation readiness) of the scorecard. If the rubric (C1–C10) includes security-related categories (C7/C10 look like candidates based on the issue text), those categories need 🟢 verdicts too before the codebase goes to Anja and Tobias. The DoD says "ready to send to Anja and Tobias" — make sure the scorecard has a security section, not just structural checks. - **`.agent/` directory at repo root** — contains `current-plan.md`, `PLAN.md`, and multiple `agent-*` subdirectories. These directories may contain implementation plans that reference internal architecture decisions, credentials placeholders, or PII from the family archive use case. Before adding `.agent/` to `.gitignore`, verify that none of the existing files contain information that shouldn't be in git history (they're currently untracked, so git history is clean). Adding `.agent/**` to `.gitignore` is the right call. ### Recommendations - Before CLEANUP-1 runs, audit `admin/+layout.server.ts:29`'s load function to confirm it isn't over-fetching sensitive user data for a stats panel. If it is, the TODO cleanup should include a note that the over-fetch is a data minimization finding — not just a code style issue. - The scorecard refresh in CLEANUP-5 (#416) should explicitly require 🟢 on any security-related rubric categories. Document this in #416's acceptance criteria. - Add `.agent/` to `.gitignore` now (before CLEANUP-4 runs), and do a quick content scan of `.agent/*.md` for any credentials or sensitive paths before the directory grows further. This is a low-effort, low-risk win. - `SecurityUtils.java` dissolution in CLEANUP-3 must include a test: `currentUserResolver_throws_unauthorized_when_authentication_is_null()`. The test goes red, the rename/refactor goes green. No security class change without a test.
Author
Owner

🧪 Sara Holt — QA Engineer & Test Strategist

Observations

  • CLEANUP-1 (dead code removal) has no verification mechanism defined. Removing code without a test to confirm the deleted path was never reached is a silent regression risk. The standard approach: run mutation testing (PIT) before deletion to confirm the code is truly unreachable, then run the full test suite after deletion. If the suite still passes, the deletion was safe. The epic should specify this verification step.

  • CLEANUP-5 (scorecard re-run) is the closest thing to a quality gate in this epic, but the acceptance criteria are written at the epic level rather than the child issue level. #416 needs explicit, testable criteria: which sections of the scorecard must show 🟢, and what would trigger a 🟡 that still closes the epic vs. a 🔴 that blocks closure. Without these thresholds, "ratify ready for evaluation" is a judgment call rather than a measurable gate.

  • No regression test coverage is specified for any of the five CLEANUP tasks. This is expected for documentation and gitignore tasks, but CLEANUP-1 (delete code) and CLEANUP-3 (rename class) are structural changes that can break compilation and behavior. CLEANUP-3 in particular will touch import statements across multiple files when SecurityUtils is dissolved. The test suite run after CLEANUP-3 needs to explicitly verify that SecurityUtilsTest.java (which exists per my codebase search) was updated or migrated, not just deleted.

  • The two live TODOs I found in the frontend are edge cases for CLEANUP-2's scope. They're well-formed TODOs with context, not "ask Marcel" markers. If CLEANUP-2 deletes them without creating linked issues, those backend features become invisible debt. The child issue #413 should specify: replace actionable TODOs with linked Gitea issues before deleting the comment.

  • CLEANUP-4 gitignore changes should be followed by git status verification as part of the DoD for #415. After adding .agent/ and .claude/worktrees/ to .gitignore, the untracked files count should drop to zero for those directories. This is a two-line verify step but it's easy to miss if the gitignore glob is wrong (e.g., .worktrees/ covers top-level but not .claude/worktrees/).

Recommendations

  • Add to #412 (dead code removal): "Run ./mvnw test before and after each deletion. Confirm no test failures. For critical service methods, run PIT mutation test first to verify they are genuinely unreachable."
  • Add to #413 (comment rewrite): "For each TODO that represents a real backlog item, create a Gitea issue and replace the TODO with a // See #NNN reference before committing the cleanup."
  • Add to #414 (naming violations): "After dissolving SecurityUtils.java, migrate SecurityUtilsTest.java to cover the new CurrentUserResolver component. Do not delete the test without replacement."
  • Add explicit DoD to #416: "Scorecard shows 🟢 on §5 AND §6. Any 🟡 finding must have an accepted justification comment on the issue. No 🔴 findings are acceptable for closure."
  • Add to #415 DoD: "Run git status after gitignore changes and confirm .agent/, .claude/worktrees/, and proofshot-artifacts/ no longer appear as untracked."
## 🧪 Sara Holt — QA Engineer & Test Strategist ### Observations - **CLEANUP-1 (dead code removal) has no verification mechanism defined.** Removing code without a test to confirm the deleted path was never reached is a silent regression risk. The standard approach: run mutation testing (PIT) before deletion to confirm the code is truly unreachable, then run the full test suite after deletion. If the suite still passes, the deletion was safe. The epic should specify this verification step. - **CLEANUP-5 (scorecard re-run) is the closest thing to a quality gate in this epic**, but the acceptance criteria are written at the epic level rather than the child issue level. `#416` needs explicit, testable criteria: which sections of the scorecard must show 🟢, and what would trigger a 🟡 that still closes the epic vs. a 🔴 that blocks closure. Without these thresholds, "ratify ready for evaluation" is a judgment call rather than a measurable gate. - **No regression test coverage is specified for any of the five CLEANUP tasks.** This is expected for documentation and gitignore tasks, but CLEANUP-1 (delete code) and CLEANUP-3 (rename class) are structural changes that can break compilation and behavior. CLEANUP-3 in particular will touch import statements across multiple files when `SecurityUtils` is dissolved. The test suite run after CLEANUP-3 needs to explicitly verify that `SecurityUtilsTest.java` (which exists per my codebase search) was updated or migrated, not just deleted. - **The two live TODOs I found in the frontend are edge cases for CLEANUP-2's scope.** They're well-formed TODOs with context, not "ask Marcel" markers. If CLEANUP-2 deletes them without creating linked issues, those backend features become invisible debt. The child issue #413 should specify: _replace actionable TODOs with linked Gitea issues before deleting the comment_. - **CLEANUP-4 gitignore changes should be followed by `git status` verification** as part of the DoD for #415. After adding `.agent/` and `.claude/worktrees/` to `.gitignore`, the untracked files count should drop to zero for those directories. This is a two-line verify step but it's easy to miss if the gitignore glob is wrong (e.g., `.worktrees/` covers top-level but not `.claude/worktrees/`). ### Recommendations - Add to #412 (dead code removal): "Run `./mvnw test` before and after each deletion. Confirm no test failures. For critical service methods, run PIT mutation test first to verify they are genuinely unreachable." - Add to #413 (comment rewrite): "For each TODO that represents a real backlog item, create a Gitea issue and replace the TODO with a `// See #NNN` reference before committing the cleanup." - Add to #414 (naming violations): "After dissolving `SecurityUtils.java`, migrate `SecurityUtilsTest.java` to cover the new `CurrentUserResolver` component. Do not delete the test without replacement." - Add explicit DoD to #416: "Scorecard shows 🟢 on §5 AND §6. Any 🟡 finding must have an accepted justification comment on the issue. No 🔴 findings are acceptable for closure." - Add to #415 DoD: "Run `git status` after gitignore changes and confirm `.agent/`, `.claude/worktrees/`, and `proofshot-artifacts/` no longer appear as untracked."
Author
Owner

🚀 Tobias Wendt — DevOps & Platform Engineer

Observations

  • CLEANUP-4 gitignore is more nuanced than the title suggests. The current .gitignore has .worktrees/ but the untracked directories include .agent/ (repo root) and .claude/worktrees/ (under .claude/, not root). These are different paths. .worktrees/ catches a top-level .worktrees/ directory — it does NOT catch .claude/worktrees/. This is why .claude/worktrees/ still shows as untracked. The fix needs two explicit entries:

    .agent/
    .claude/worktrees/
    

    Additionally, .claude/scheduled_tasks.lock is untracked — that's a lock file that should never be committed. Add *.lock entries or specifically .claude/*.lock.

  • proofshot-artifacts/ at repo root is 7.6MB across 44 files and growing. This is a developer tooling artifact directory with no defined retention policy. For a solo developer who will send this codebase to external reviewers (Anja and Tobias), having unexplained screenshot directories at the repo root is confusing. My recommendation: add proofshot-artifacts/ to .gitignore now, and optionally add a scripts/clean-e2e-data.sh-style companion script (scripts/clean-proofshots.sh) that deletes all but the last run. This is a one-liner: find proofshot-artifacts/ -mindepth 1 -maxdepth 1 -not -newer proofshot-artifacts/$(ls -t proofshot-artifacts/ | head -1) -exec rm -rf {} +.

  • .claude/settings.json is untracked. This may be intentional (personal Claude Code settings) or accidental. If it contains project-level tool permissions (like the fewer-permission-prompts skill would generate), it's project configuration and should be committed. If it contains local paths or personal preferences, it should be in .gitignore. This needs an explicit decision — currently it's in neither place, which is a hygiene gap.

  • node_modules/ at repo root is untracked. Check: is there a package.json at repo root? If so, this is an accidental npm init or a workspace setup. The git status also shows package.json and package-lock.json at repo root. If these are intentional (e.g., a monorepo workspace), they need documentation. If they're accidental, they need deletion plus a .gitignore entry.

  • infra/ directory is untracked at repo root. Given the stack has a docker-compose.yml at root, I'd expect infrastructure config to live there, not in a separate infra/ directory. This either belongs committed (if it contains useful deployment configs) or gitignored (if it's a generated/local artifact).

Recommendations

  • CLEANUP-4 scope should be explicitly expanded to cover: .agent/, .claude/worktrees/, .claude/scheduled_tasks.lock, proofshot-artifacts/, and the orphaned node_modules/ + package.json at root. The current issue title only mentions .agent/.worktrees — this is narrower than what the git status shows.
  • Decision needed before CLEANUP-4 starts: commit or ignore .claude/settings.json, .claude/personas/, .claude/skills/? These are project-level AI configuration — a case can be made for committing personas/ and skills/ (they define the team's workflow) while ignoring settings.json (personal tool config). Document this decision in CLEANUP-4's description.
  • Check infra/ and the root package.json/package-lock.json before they accumulate further. If they're intentional, commit with a comment in docker-compose.yml or README.md explaining them. If accidental, delete and gitignore before the external review.
## 🚀 Tobias Wendt — DevOps & Platform Engineer ### Observations - **CLEANUP-4 gitignore is more nuanced than the title suggests.** The current `.gitignore` has `.worktrees/` but the untracked directories include `.agent/` (repo root) and `.claude/worktrees/` (under `.claude/`, not root). These are different paths. `.worktrees/` catches a top-level `.worktrees/` directory — it does NOT catch `.claude/worktrees/`. This is why `.claude/worktrees/` still shows as untracked. The fix needs two explicit entries: ``` .agent/ .claude/worktrees/ ``` Additionally, `.claude/scheduled_tasks.lock` is untracked — that's a lock file that should never be committed. Add `*.lock` entries or specifically `.claude/*.lock`. - **`proofshot-artifacts/` at repo root** is 7.6MB across 44 files and growing. This is a developer tooling artifact directory with no defined retention policy. For a solo developer who will send this codebase to external reviewers (Anja and Tobias), having unexplained screenshot directories at the repo root is confusing. My recommendation: add `proofshot-artifacts/` to `.gitignore` now, and optionally add a `scripts/clean-e2e-data.sh`-style companion script (`scripts/clean-proofshots.sh`) that deletes all but the last run. This is a one-liner: `find proofshot-artifacts/ -mindepth 1 -maxdepth 1 -not -newer proofshot-artifacts/$(ls -t proofshot-artifacts/ | head -1) -exec rm -rf {} +`. - **`.claude/settings.json` is untracked.** This may be intentional (personal Claude Code settings) or accidental. If it contains project-level tool permissions (like the `fewer-permission-prompts` skill would generate), it's project configuration and should be committed. If it contains local paths or personal preferences, it should be in `.gitignore`. This needs an explicit decision — currently it's in neither place, which is a hygiene gap. - **`node_modules/` at repo root** is untracked. Check: is there a `package.json` at repo root? If so, this is an accidental npm init or a workspace setup. The git status also shows `package.json` and `package-lock.json` at repo root. If these are intentional (e.g., a monorepo workspace), they need documentation. If they're accidental, they need deletion plus a `.gitignore` entry. - **`infra/` directory** is untracked at repo root. Given the stack has a `docker-compose.yml` at root, I'd expect infrastructure config to live there, not in a separate `infra/` directory. This either belongs committed (if it contains useful deployment configs) or gitignored (if it's a generated/local artifact). ### Recommendations - CLEANUP-4 scope should be explicitly expanded to cover: `.agent/`, `.claude/worktrees/`, `.claude/scheduled_tasks.lock`, `proofshot-artifacts/`, and the orphaned `node_modules/` + `package.json` at root. The current issue title only mentions `.agent/.worktrees` — this is narrower than what the git status shows. - Decision needed before CLEANUP-4 starts: commit or ignore `.claude/settings.json`, `.claude/personas/`, `.claude/skills/`? These are project-level AI configuration — a case can be made for committing `personas/` and `skills/` (they define the team's workflow) while ignoring `settings.json` (personal tool config). Document this decision in CLEANUP-4's description. - Check `infra/` and the root `package.json`/`package-lock.json` before they accumulate further. If they're intentional, commit with a comment in `docker-compose.yml` or `README.md` explaining them. If accidental, delete and gitignore before the external review.
Author
Owner

📋 Elicit — Requirements Engineer

Observations

  • The five child issues (#412–#416) are well-structured relative to the milestone's overall shape, but they have an ordering problem embedded in the epic body that the issue descriptions don't surface: CLEANUP-1 through CLEANUP-4 need the audit outputs (Epic 1) as their input, yet they carry no explicit blocked-by links to #388–#392. A reader picking up #412 in isolation cannot tell it must wait for the audit reports.

  • CLEANUP-5 acceptance criteria mix two different concerns. "Ratify 'ready for evaluation'" is a conclusion, not a criterion. The measurable criteria should be:

    • docs/LEGIBILITY-READINESS.md exists and was last updated after CLEANUP-4 closed.
    • Scorecard §5 shows 🟢 with no unresolved 🔴 findings.
    • Scorecard §6 shows 🟢 with no unresolved 🔴 findings.
    • Every Critical/Major finding from Epic 1 audits is either linked to a closed issue or has a written accepted-justification comment on the relevant child issue.

    Without these specifics, "🟢🟢 verdict" is a subjective assessment rather than a binary gate.

  • The Definition of Done says "The codebase is ready to send to Anja and Tobias." This is the real exit criterion for the entire Codebase Legibility milestone, but it's stated only in this epic's DoD, not in any child issue. If Epic 5 closes without that final check being done, the milestone could close prematurely. Consider making this the milestone-level acceptance criterion, not just the epic's DoD.

  • CLEANUP-2's scope is ambiguous. "Rewrite vague comments and remove 'ask Marcel' / 'Claude generated' markers" covers two different activities: (a) improve comment quality and (b) remove AI attribution markers. These have different verification methods: (a) requires human judgment, (b) can be verified with a grep. The child issue #413 should split these into separate checklists so each can be mechanically verified.

  • CLEANUP-4 scope is too narrow given what git status shows. The issue covers "proofshot-artifacts retention, ignore .agent/.worktrees" but the actual hygiene surface is larger (see Tobias's comment). The issue title should be updated to reflect the full scope, or sub-tasks should be listed explicitly.

Recommendations

  • Add "Blocked by: #388, #389, #390, #391, #392" to each of #412, #413, #414, and #415 descriptions. This makes the dependency chain visible to anyone reading individual issues.
  • Rewrite #416's acceptance criteria using the four measurable bullet points above. Move "ready to send to Anja and Tobias" from the epic DoD to the milestone description as the exit criterion for the full Codebase Legibility milestone.
  • Split #413 into two checklists: (1) grep-verified removal of AI attribution markers and (2) human-reviewed comment quality improvements. This makes the issue more parallelizable and each checklist independently closeable.
  • Expand #415's scope to cover the full set of untracked hygiene items: .agent/, .claude/worktrees/, .claude/scheduled_tasks.lock, proofshot-artifacts/, and the decision on root package.json/infra/.
## 📋 Elicit — Requirements Engineer ### Observations - **The five child issues (#412–#416) are well-structured** relative to the milestone's overall shape, but they have an ordering problem embedded in the epic body that the issue descriptions don't surface: CLEANUP-1 through CLEANUP-4 need the audit outputs (Epic 1) as their input, yet they carry no explicit blocked-by links to #388–#392. A reader picking up #412 in isolation cannot tell it must wait for the audit reports. - **CLEANUP-5 acceptance criteria mix two different concerns.** "Ratify 'ready for evaluation'" is a _conclusion_, not a criterion. The measurable criteria should be: - `docs/LEGIBILITY-READINESS.md` exists and was last updated after CLEANUP-4 closed. - Scorecard §5 shows 🟢 with no unresolved 🔴 findings. - Scorecard §6 shows 🟢 with no unresolved 🔴 findings. - Every Critical/Major finding from Epic 1 audits is either linked to a closed issue or has a written accepted-justification comment on the relevant child issue. Without these specifics, "🟢🟢 verdict" is a subjective assessment rather than a binary gate. - **The Definition of Done says "The codebase is ready to send to Anja and Tobias."** This is the real exit criterion for the entire Codebase Legibility milestone, but it's stated only in this epic's DoD, not in any child issue. If Epic 5 closes without that final check being done, the milestone could close prematurely. Consider making this the milestone-level acceptance criterion, not just the epic's DoD. - **CLEANUP-2's scope is ambiguous.** "Rewrite vague comments and remove 'ask Marcel' / 'Claude generated' markers" covers two different activities: (a) improve comment quality and (b) remove AI attribution markers. These have different verification methods: (a) requires human judgment, (b) can be verified with a `grep`. The child issue #413 should split these into separate checklists so each can be mechanically verified. - **CLEANUP-4 scope is too narrow given what git status shows.** The issue covers "proofshot-artifacts retention, ignore .agent/.worktrees" but the actual hygiene surface is larger (see Tobias's comment). The issue title should be updated to reflect the full scope, or sub-tasks should be listed explicitly. ### Recommendations - Add "Blocked by: #388, #389, #390, #391, #392" to each of #412, #413, #414, and #415 descriptions. This makes the dependency chain visible to anyone reading individual issues. - Rewrite #416's acceptance criteria using the four measurable bullet points above. Move "ready to send to Anja and Tobias" from the epic DoD to the milestone description as the exit criterion for the full Codebase Legibility milestone. - Split #413 into two checklists: (1) grep-verified removal of AI attribution markers and (2) human-reviewed comment quality improvements. This makes the issue more parallelizable and each checklist independently closeable. - Expand #415's scope to cover the full set of untracked hygiene items: `.agent/`, `.claude/worktrees/`, `.claude/scheduled_tasks.lock`, `proofshot-artifacts/`, and the decision on root `package.json`/`infra/`.
Author
Owner

🎨 Leonie Voss — UX Designer & Accessibility Strategist

No direct UI/UX concerns for this epic — CLEANUP-1 through CLEANUP-4 are all backend/infra/tooling hygiene tasks with no frontend component changes.

What I checked: none of the named cleanup tasks touch Svelte components, CSS, or Tailwind tokens. SecurityUtils.java dissolution (CLEANUP-3) has no frontend surface. The gitignore changes (CLEANUP-4) and dead code removal (CLEANUP-1) don't affect the rendered UI.

One observation that's adjacent to UX: the ChronikRow.svelte TODO (flagged by Felix) notes the backend doesn't expose a comment body preview. When that TODO is cleaned up in CLEANUP-2, whoever resolves it should ensure the linked Gitea issue specifies the display requirement, not just the API requirement: a comment preview in the Chronik row needs to handle truncation gracefully (line clamp, aria-label with full text), especially for the 60+ audience reading on small screens. That's a Medium-priority UX note to carry into the future feature issue — not a blocker for CLEANUP-2.

## 🎨 Leonie Voss — UX Designer & Accessibility Strategist No direct UI/UX concerns for this epic — CLEANUP-1 through CLEANUP-4 are all backend/infra/tooling hygiene tasks with no frontend component changes. What I checked: none of the named cleanup tasks touch Svelte components, CSS, or Tailwind tokens. `SecurityUtils.java` dissolution (CLEANUP-3) has no frontend surface. The gitignore changes (CLEANUP-4) and dead code removal (CLEANUP-1) don't affect the rendered UI. One observation that's adjacent to UX: **the `ChronikRow.svelte` TODO** (flagged by Felix) notes the backend doesn't expose a comment body preview. When that TODO is cleaned up in CLEANUP-2, whoever resolves it should ensure the linked Gitea issue specifies the _display_ requirement, not just the API requirement: a comment preview in the Chronik row needs to handle truncation gracefully (line clamp, aria-label with full text), especially for the 60+ audience reading on small screens. That's a Medium-priority UX note to carry into the future feature issue — not a blocker for CLEANUP-2.
Author
Owner

🗳️ Decision Queue — Action Required

3 decisions need your input before CLEANUP-4 (#415) starts.

Repo Hygiene

  • [.claude/ directory strategy].claude/personas/, .claude/skills/, and .claude/settings.json are all untracked. Two options: (A) commit personas/ and skills/ as project configuration (they define the team's AI workflow) while adding settings.json and worktrees/ to .gitignore; (B) ignore the entire .claude/ directory as developer-local tooling. Option A is recommended — the personas and skills are meaningful project artifacts that external reviewers Anja and Tobias could read to understand how the team works. Option B treats all Claude tooling as ephemeral. (Raised by: Markus, Tobias)

  • [infra/ directory at repo root] — An infra/ directory is untracked at the repo root. Is this intentional infrastructure configuration that should be committed alongside docker-compose.yml, or was it accidentally created and should be deleted and gitignored? There's no record in CLAUDE.md or any existing docs of what infra/ contains or why it's separate from the existing docker-compose.yml. (Raised by: Tobias)

Architecture

  • [Root package.json / package-lock.json] — There is a package.json and package-lock.json at repo root (separate from frontend/package.json). This suggests either an accidental npm init or an intentional npm workspaces setup. If accidental: delete and gitignore node_modules/. If intentional: document the workspace structure in CLAUDE.md and explain the relationship to frontend/package.json. The current state — untracked, undocumented — is a hygiene gap that will confuse external reviewers. (Raised by: Tobias)
## 🗳️ Decision Queue — Action Required _3 decisions need your input before CLEANUP-4 (#415) starts._ ### Repo Hygiene - **[`.claude/` directory strategy]** — `.claude/personas/`, `.claude/skills/`, and `.claude/settings.json` are all untracked. Two options: (A) commit `personas/` and `skills/` as project configuration (they define the team's AI workflow) while adding `settings.json` and `worktrees/` to `.gitignore`; (B) ignore the entire `.claude/` directory as developer-local tooling. Option A is recommended — the personas and skills are meaningful project artifacts that external reviewers Anja and Tobias could read to understand how the team works. Option B treats all Claude tooling as ephemeral. _(Raised by: Markus, Tobias)_ - **[`infra/` directory at repo root]** — An `infra/` directory is untracked at the repo root. Is this intentional infrastructure configuration that should be committed alongside `docker-compose.yml`, or was it accidentally created and should be deleted and gitignored? There's no record in CLAUDE.md or any existing docs of what `infra/` contains or why it's separate from the existing `docker-compose.yml`. _(Raised by: Tobias)_ ### Architecture - **[Root `package.json` / `package-lock.json`]** — There is a `package.json` and `package-lock.json` at repo root (separate from `frontend/package.json`). This suggests either an accidental `npm init` or an intentional npm workspaces setup. If accidental: delete and gitignore `node_modules/`. If intentional: document the workspace structure in CLAUDE.md and explain the relationship to `frontend/package.json`. The current state — untracked, undocumented — is a hygiene gap that will confuse external reviewers. _(Raised by: Tobias)_
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: marcel/familienarchiv#411