Skip to content

[refactor] Split the four section renderers out of ReconstructedResume.tsx (1489 LOC) #861

Description

@s-annam

Problem

src/components/features/ReconstructedResume.tsx is 1489 lines — 7× the ~200 LOC guidance in CLAUDE.md, and the single largest feature component in the repo.

CLAUDE.md names it as known debt:

⚠️ Known debt — do not imitate: ReconstructedResume.tsx (1489), SectionRewrite.tsx (607), ModelSelector.tsx (556), ReconstructedRole.tsx (490) all violate this. If you are editing one, prefer extracting your change into a new sibling over growing the file further.

fallow reports three functions in this one file over the guidance:

Function LOC
ReconstructedResume 370
ExperienceSection 320
ProjectsSection 143

with AchievementsSection alongside them. Four peer section renderers are co-located in one module, and the outer component threads props to all of them.

Why now, and why not in #858

#858 grew this file from 1356 → 1489 (+133) while adding parsed-entry deletion. It did extract a sibling (src/lib/edit/entry-remove.ts), which is the right instinct — the extraction just is not where the mass is.

Splitting the sections inside #858 was explicitly declined: that diff is already 1846 insertions, and moving four section renderers would have buried the index-remap change — the part that actually needed careful review. Filed separately instead, per the review thread on #858.

This is a refactor: no behaviour change, no user-visible difference.

Reuse analysis

Capability: render one section of the reconstructed résumé.

Existing surfaces found:

Decision: extend the existing one-module-per-section convention. No new abstraction, no new design-system piece, no new panel — this moves code that already exists into the file layout its two siblings already use.

Implementation sketch

Extract each section into its own module under src/components/features/, mirroring ReconstructedRole.tsx:

  1. ExperienceSection (320 LOC) — the largest win, and the one whose extraction most clarifies the parent.
  2. ProjectsSection (143 LOC).
  3. AchievementsSection.

Each takes the props it already receives today; the parent keeps the shared state and the buildEntryGroups call. Do them as separate commits (or separate PRs) so each diff is readable as a pure move — a move plus an edit in one diff is exactly what makes this kind of refactor expensive to review.

Update the CLAUDE.md "Known debt" line with the resulting LOC when done.

Acceptance criteria

  • ExperienceSection, ProjectsSection and AchievementsSection each live in their own module.
  • ReconstructedResume.tsx is materially under its current 1489 LOC, and the ReconstructedResume function is under the ~200 LOC guidance.
  • No behaviour change — the full test suite passes without any test being modified to accommodate the move. A test that needs editing is a signal the move was not pure.
  • Round-trip invariants hold (corpus.test.ts, corpus-roundtrip.test.ts).
  • Every extracted module carries the SPDX header and a docblock naming why it exists, per the house style.
  • fallow no longer reports these three functions over the LOC guidance.
  • CLAUDE.md's "Known debt" LOC figures updated to the post-split reality.
  • npm run verify green.

Not in scope

  • SectionRewrite.tsx (607), ModelSelector.tsx (556), ReconstructedRole.tsx (490) — same debt class, separate issues.
  • Any change to what the sections render or how the edit model works.

Metadata

Metadata

Assignees

No one assigned

    Labels

    refactorCode restructuring without behavior change

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions