Files
SubMiner/investigation.md
2026-02-11 09:33:47 -08:00

11 KiB
Raw Blame History

Refactoring Investigation Report

Overview

This report evaluates the SubMiner refactoring effort on the refactor branch against the plan defined in plan.md and the safety checklist in docs/refactor-main-checklist.md. The refactoring aimed to eliminate unnecessary abstraction layers, consolidate related services, fix known bugs, and add test coverage.

Result: 65 commits, 104 files changed, main.ts reduced from ~5,800 to 1,398 lines, all 67 tests passing, build succeeds.


Phase 1: Delete Thin Wrappers — COMPLETE

All 9 target wrapper services and 7 associated test files have been deleted and their logic inlined into callers (mostly main.ts or the services they fed).

Target File Status
config-warning-runtime-service.ts + test Deleted, inlined
overlay-modal-restore-service.ts + test Deleted, inlined
runtime-options-manager-runtime-service.ts + test Deleted, inlined
app-logging-runtime-service.ts + test Deleted, inlined
overlay-send-service.ts (no test) Deleted, inlined
startup-resource-runtime-service.ts + test Deleted, inlined
config-generation-runtime-service.ts + test Deleted, inlined
app-shutdown-runtime-service.ts + test Deleted, inlined
shortcut-ui-deps-runtime-service.ts + test Deleted, inlined

Files removed: 16 (9 services + 7 tests) No issues found.


Phase 2: Consolidate DI Adapter Services — COMPLETE

All 4 dependency-injection adapter services have been merged into the services they fed, and their test files removed.

Adapter Merged Into Status
cli-command-deps-runtime-service.ts + test cli-command-service.ts Done
ipc-deps-runtime-service.ts + test ipc-service.ts Done
tokenizer-deps-runtime-service.ts + test tokenizer-service.ts Done
app-lifecycle-deps-runtime-service.ts + test app-lifecycle-service.ts Done

Files removed: 8 (4 services + 4 tests) No issues found.


All planned service merges have been executed.

Consolidation Source Files Result File Status
Overlay visibility overlay-visibility-runtime-service.ts overlay-visibility-service.ts Done
Overlay broadcast overlay-broadcast-runtime-service.ts + test overlay-manager-service.ts Done
Overlay shortcuts overlay-shortcut-lifecycle-service.ts, overlay-shortcut-fallback-runner.ts overlay-shortcut-service.ts + overlay-shortcut-handler.ts Done
Numeric shortcuts numeric-shortcut-runtime-service.ts + test, numeric-shortcut-session-service.ts numeric-shortcut-service.ts Done
Startup/bootstrap startup-bootstrap-runtime-service.ts + test, app-ready-runtime-service.ts + test startup-service.ts Done

Files removed: ~10 No issues found.


Phase 4: Fix Bugs and Code Quality — COMPLETE

4.1 Debug console.log statements

Status: RESOLVED — No debug console.log or console.warn calls remain in overlay-visibility-service.ts.

4.2 as never type cast

Status: RESOLVED — No as never cast remains in tokenizer-service.ts. The type mismatch was fixed properly.

4.3 fieldGroupingResolver race condition

Status: RESOLVED — Fixed in main.ts (lines 305332) with a sequence counter mechanism. Each new resolver increments fieldGroupingResolverSequence, and wrapped resolvers check if their sequence matches the current value before executing. Stale resolutions are correctly ignored.

4.4 Async callback safety

Status: RESOLVED

  • CLI commands (cli-command-service.ts): Async commands use runAsyncWithOsd helper (lines 177187) which catches errors, logs them, and displays via MPV OSD.
  • IPC handlers (ipc-service.ts): Async handlers use ipcMain.handle (not .on), which properly awaits and propagates promise results. Synchronous handlers correctly use ipcMain.on.

4.5 -runtime-service naming convention

Status: RESOLVED — No files with -runtime-service in the name exist under src/core/services/. All have been renamed to *-service.ts.


Phase 5: Add Tests for Critical Untested Services — COMPLETE

Tests added per plan:

Service Test File Tests
mpv-service.ts (761 lines) mpv-service.test.ts Socket protocol, property changes, reconnection
subsync-service.ts (427 lines) subsync-service.test.ts Config resolution, command construction, error handling
tokenizer-service.ts (305 lines) tokenizer-service.test.ts Parser init, token extraction, edge cases
cli-command-service.ts (204 lines) cli-command-service.test.ts (290 lines) Expanded: all dispatch paths, error propagation

Total: 67 tests passing across all test suites.


Phase 6: Directory Restructure — NOT STARTED (Optional)

Services remain in the flat src/core/services/ directory. This phase was explicitly marked optional and low-priority. The current flat structure with ~25 files is manageable.


Checklist Compliance (docs/refactor-main-checklist.md)

Invariants

Invariant Status
CLI flags and aliases working Verified via tests
IPC channel names backward-compatible No channel names changed
Overlay toggle behavior preserved Logic moved verbatim
MPV integration behavior preserved Logic moved verbatim, tested
Texthooker mode preserved Not altered
Mining/runtime options paths preserved Logic moved verbatim

Automated Checks

Check Status
pnpm run build Passes
pnpm run test:core 67/67 passing

Manual Smoke Checks

Status: NOT YET PERFORMED — Visual overlay rendering, card mining flow, and field-grouping interaction require a real desktop session with MPV. Automated tests validate logic correctness but cannot catch rendering regressions.


Loose Ends and Concerns

1. Unused Architectural Scaffolding (~500 lines, dead code)

The following files exist in the repository but are not imported or used anywhere:

Core abstractions:

File Lines Purpose
src/core/action-bus.ts 22 Generic action dispatcher (register/dispatch)
src/core/actions.ts 17 Union type AppAction with 16 action variants
src/core/app-context.ts 46 Module context interfaces
src/core/module-registry.ts 37 Module lifecycle manager (init/start/stop)
src/core/module.ts 7 SubminerModule<TContext> interface

Module implementations:

File Lines Purpose
src/modules/runtime-options/module.ts 62 Runtime options module
src/modules/subsync/module.ts 79 Subsync module
src/modules/jimaku/module.ts 73 Jimaku module

IPC abstraction layer:

File Lines Purpose
src/ipc/contract.ts 62 IPC channel name constants
src/ipc/main-api.ts 20 Main process IPC helpers
src/ipc/renderer-api.ts 28 Renderer process IPC helpers

These represent scaffolding for a module-based architecture that was prototyped but never wired into main.ts. The current codebase uses the service-oriented approach throughout.

Recommendation: Remove if abandoned, or document with clear intent if planned for a future phase.

2. New Consolidated Services Without Test Coverage

Seven service files created or consolidated during Phase 3 lack dedicated tests:

File Lines Risk Level Reason
overlay-shortcut-handler.ts 216 Higher Complex runtime handlers with fallback logic
mining-service.ts 179 Higher 6 public functions orchestrating mining workflows
anki-jimaku-service.ts 173 Higher Complex IPC registration with multiple handlers
startup-service.ts ~150 Medium Bootstrap and app-ready orchestration
numeric-shortcut-service.ts 133 Medium Session state management
subsync-runner-service.ts 86 Lower Thin runtime wrapper
jimaku-service.ts 81 Lower Config accessor functions

Phase 5 targeted the 4 highest-risk previously existing untested services. The Phase 3 consolidation created new files that inherited logic from multiple sources — those were not explicitly called out in the plan for testing.

3. Null Safety in Consolidated Services

All checked consolidated services handle null/undefined correctly:

  • mpv-control-service.ts: Accepts MpvRuntimeClientLike | null, uses null checks and optional chaining before all access.
  • overlay-bridge-service.ts: Returns false early if window is null or destroyed (line 17: if (!options.mainWindow || options.mainWindow.isDestroyed()) return false).
  • startup-service.ts: Uses dependency injection with all deps provided upfront, async operations awaited in sequence, config access uses optional chaining.

No null safety issues found.

4. Import Consistency

All 68 imports in main.ts from ./core/services resolve to existing exports. No references to deleted files remain. The barrel export in index.ts has 79 entries with no dead exports (one minor case: isGlobalShortcutRegisteredSafe is only used within the service layer itself, not by main.ts).


Risk Assessment

Area Risk Mitigation
Logic regression from inlining Low Code moved verbatim, 67 tests pass
Overlay rendering regression Medium Requires manual smoke test with MPV
Unused scaffolding becoming stale Low Remove or document with clear intent
Missing test coverage on new files Medium Add tests for the 3 higher-risk services
Race conditions Low fieldGroupingResolver race fixed with sequence counter
Async error swallowing Low All async paths have error boundaries

Recommendations

  1. Remove unused scaffolding (src/core/action-bus.ts, src/core/actions.ts, src/core/app-context.ts, src/core/module-registry.ts, src/core/module.ts, src/modules/, src/ipc/) — ~500 lines of dead code that contradicts the refactoring goal of reducing unnecessary abstraction.

  2. Add tests for higher-risk consolidated servicesoverlay-shortcut-handler.ts, mining-service.ts, and anki-jimaku-service.ts have the most complex logic among the untested new files.

  3. Perform desktop smoke test — Verify overlay rendering, card mining, and field-grouping interaction in a real session with MPV running.

  4. Consider removing isGlobalShortcutRegisteredSafe from barrel export — It's only used internally by the service layer, not by main.ts.