Skip to content

Refactor passes: dead code, ThreadView split, shared Insights CSS, provider process helper #1447

Closed

Description

@currentbits

Audit of main @ 6967e43 (knip, jscpd, eslint no-unused-vars, file sizes) turned up four behaviour-preserving passes that touch disjoint files, run as parallel workers.

Findings

  • Size: ThreadView.tsx 9.4k lines (ThreadView component 4.4k, plus ~5k of sibling components), runner.js 9.3k (createRunner closure 8.6k), worktrees.js 6.8k, devCoder.ts 6.7k, services.js 5.8k.
  • Dead code (production-unused, some kept alive only by tests): crewIntegration.ts label helpers (6), uiPrefs verbose-tool-cards / run-duration / vim getters, SNOOZE_PRESETS, clearPaneLayouts, chunkForPath, browseQueryForSubmit, worktrees.js gitOutForDiff, orchServer unused import, automations PRESETS, memory-sup boundCoderMemoryUrl, session-record configureSessionRecord.
  • Duplication (~1% overall): provider adapters copy the JSON-lines child-process plumbing (cursor/muse/opencode/codex/claude/grok, about 300 lines). Insights-style views copy ~400 lines of page CSS (Activity/Insights/Fleet/Digest/Kanban/Planboard/PrList).

Passes

  • A: dead code removal
  • B: move ThreadView.tsx sibling components into src/components/thread/
  • C: shared page CSS for the Insights views
  • D: shared JSON-lines process helper for provider adapters

Not now

  • Splitting createRunner (8.6k-line closure) and the ThreadView component body: worth doing, but they need a design pass (state threading), not a mechanical move. Follow-up once A–D land.

Activity

  1. currentbits commented on Oct 4, 2026

    @currentbits
    OwnerAuthor

    All four passes are verified and open as PRs. They touch disjoint files, and each is mergeable on its own:

    Follow-ups, not started: split createRunner (8.6k-line closure) and the ThreadView component body. Both need a design pass on how state flows through them before they can be split mechanically.

  2. added and removed on Oct 4, 2026
  3. added 4 commits that reference this issue on Oct 4, 2026
  4. currentbits commented on Oct 4, 2026

    @currentbits
    OwnerAuthor

    Round 2

    Four more passes, all behaviour-preserving. None of them touch files in the open round-1 PRs (#1448–#1451).

    • E: split electron/services.js (5.8k lines, 175 flat functions) into domain modules. services.js stays as the barrel, so require("./services") callers don't change.
    • F: move ThreadCard (673 lines), SettledRow, the status helpers and the smaller components out of Sidebar.tsx into src/components/sidebar/, verbatim, the same way pass B did for ThreadView.
    • G: createRunner has 123 inner functions. Lift the ones that don't touch closure state into a module, and write a design note on how to split the rest (state map plus proposed module seams).
    • H: SettingsModal.tsx (3.2k lines): give each settings pane its own component file under src/components/settings/.
  5. currentbits commented on Oct 4, 2026

    @currentbits
    OwnerAuthor

    Round 1 merged (#1448–#1451). Round 2 is verified and open:

    Round 3: the createRunner split, per G's design

    • Safety tests first: Claude idle reap and LRU eviction, and CI-workflow sign-off failing closed. Today neither is covered before the steps that move that code.
    • Step 1: the create<Seam>(ctx) mechanism, plus the watchdogs seam. This is stacked on Lift closure-free createRunner helpers, add the runner split design (#1447 pass G) #1454.
    • Steps 2–6 (ask/btw, turn setup, subagents, session recording, Claude keep-alive) in parallel once step 1 has landed the ctx wiring.
    • Steps 7–11 one after another (verify gate, quota, notices/crew, permissions, provider runs).
  6. currentbits commented on Oct 4, 2026

    @currentbits
    OwnerAuthor

    Round 3 progress

    Merge order: #1457, #1454, #1456, #1458. #1452, #1453 and #1455 are independent.

    CI note: test (windows-latest) intermittently times out on the whole test/sidebar.test.tsx file. It has happened 3 times today, including on electron-only PRs. That's a pre-existing flake, filed as a suggested-work chip.

  7. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor

    Round 3 complete: the createRunner split

    electron/runner.js goes from 9,321 to 2,628 lines. 18 flat runner-*.js modules now hold the code that moved out; runnerHelpers.js holds pure helpers and the other 17 are create<Seam>(ctx) factories. Every step is verified: verbatim moves, eager ctx deps checked by script, construction order, the full electron suite, typecheck and the real-Electron smoke test.

    Merge order: #1457 → #1454 → #1456 → #1458 → #1459 → #1460. Round 2's #1452, #1453 and #1455 are independent.

    Still open from the original audit: the ThreadView component body (~4.4k lines) and the other large React components (Sidebar body ~3k, useCoder ~3.5k, Composer ~3k). These need hook extraction, not file moves.

  8. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor

    Round 4: hook extraction in the big React components

    Three workers in parallel, one per file. None of the open PRs touch these files.

    • I: useCoder.ts (4,510 lines, one ~3,500-line hook). Split it into domain sub-hooks that useCoder composes; the UseCoderResult shape stays identical.
    • J: ThreadView.tsx (5,042 lines, a ~4,400-line component). Extract custom hooks for closed state groups (scroll/stick-to-bottom, header, git/PR state, …).
    • K: Composer.tsx (3,531 lines, a ~3,000-line component). Extract custom hooks (speech, attachments, mentions/slash menus, vim, …).

    The rule that keeps this behaviour-preserving: React runs effects in declaration order. Only contiguous hook groups move, and each new custom hook is called exactly where its group was. Each worker also writes a short state map and seam plan for its component under docs/superpowers/specs/, and stops at whatever can't be moved safely.

    Later: the Sidebar component body (after #1453) and App.tsx.

  9. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor

    Round 4 complete: hook extraction

    Each PR was checked with a script: once the custom hooks are expanded, the component has the same effects in the same order as on main. Each is also a pure move ignoring indentation, and passes typecheck, vite build and renderer 2701/2701.

    Round 5

    • L: electron/worktrees.js (6,757 lines, 159 flat functions). Split into flat worktrees-*.js domain modules behind the same exports, like Split services.js into domain modules behind the same barrel (#1447 pass E) #1452 did for services.
    • M: src/devCoder.ts (6,696 lines, the browser demo backend). Split by domain.
    • N: src/App.tsx (~2,500-line component). Extract hooks with the same effect-order rules as round 4.
  10. 24 remaining items

  11. added a commit that references this issue on Oct 5, 2026
  12. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor

    Round 6

    Merged:

    Before merging, I combined all five on a throwaway branch: electron 4126/4126, renderer 2701/2701, typecheck, build and smoke A–E all pass. Main's tree after merging matches that branch exactly.

    Merging once CI is green:

    • Split IPC_HANDLERS into per-namespace modules (#1447 pass S) #1472 S: IPC_HANDLERS split into 11 namespace modules (ipc.js 2,476 → 176). The 262-channel set and every handler's source are identical. The modules hold exactly 262 handlers, so none is duplicated. Verified merged onto current main: electron 4126/4126, typecheck including the sync-ipc-preload check, and smoke A–E.

    Still left: ios-simulator.js (a 2,685-line factory closure, needs the runner-style ctx seams).

  13. added a commit that references this issue on Oct 5, 2026
  14. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor
  15. added a commit that references this issue on Oct 5, 2026
  16. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor

    Done: every file on the original list is split

    File Before After
    electron/runner.js 9,321 2,628
    electron/worktrees.js 6,757 206
    src/devCoder.ts 6,696 513
    electron/services.js 5,824 348
    electron/store.js 4,185 2,052
    src/useCoder.ts 4,510 2,119
    src/components/ThreadView.tsx 9,442 4,369
    src/components/Sidebar.tsx 4,752 2,124
    electron/ios-simulator.js 3,244 1,697
    src/components/Composer.tsx 3,531 2,659
    src/components/SettingsModal.tsx 3,179 801
    src/App.tsx 2,732 2,022
    electron/cli-sessions.js 2,566 ~130
    electron/workflow.js 2,557 1,106
    electron/ipc.js 2,476 176

    Also fixed along the way: the Windows sidebar.test.tsx timeout (#1468), plus new safety tests for CI sign-off fail-closed and Claude idle reap (#1457).

    Known open flake, found today: macOS workflow.test.js "stopRun mid-analyze" waitFor timeout. It predates these changes; there's a suggested-work chip on the thread.

    What's left is deliberate: the residues each spec documents (the ThreadView switch-reset effect, the useCoder core effects, the Composer model picker), which need behaviour-level changes rather than moves.

  17. added and removed on Oct 5, 2026
  18. currentbits commented on Oct 5, 2026

    @currentbits
    OwnerAuthor

    Correction to the table above: electron/cli-sessions.js on main is 187 lines (measured), not ~130.

  19. added and removed on Oct 9, 2026
  20. currentbits commented on Oct 9, 2026

    @currentbits
    OwnerAuthor

    Done: passes A–D merged (#1448–#1451). Closing in the 2026-10-09 board cleanup (#1532).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions