mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-28 06:22:45 -08:00
9.3 KiB
9.3 KiB
SubMiner Composability and Extensibility Plan
Goals
- Reduce coupling concentrated in
src/main.ts. - Make new features additive (new files/modules) instead of invasive (edits across many files).
- Standardize extension points for trackers, subtitle processing, IPC actions, and integrations.
- Preserve existing behavior while incrementally migrating architecture.
Current Constraints (From Existing Code)
src/main.tsis the effective integration bus (~5k LOC) and mixes lifecycle, IPC, shortcuts, mpv integration, overlay control, and feature flows.- Input surfaces are fragmented (CLI args, global shortcuts, renderer IPC) and often route through separate logic paths.
- Some extension points already exist (
src/window-trackers/*, centralized config definitions insrc/config/definitions.ts) but still use hardcoded selection/wiring. - Type contracts are duplicated between main/preload/renderer in places, which increases drift risk.
Target Architecture
1. Composition Root + Services
- Keep
src/main.tsas bootstrap only. - Move behavior into focused services:
src/core/app-orchestrator.tssrc/core/services/overlay-service.tssrc/core/services/mpv-service.tssrc/core/services/shortcut-service.tssrc/core/services/ipc-service.tssrc/core/services/subtitle-service.ts
2. Module System
- Introduce module contract:
src/core/module.tssrc/core/module-registry.ts
- Built-in features become modules:
- anki module
- jimaku module
- runtime options module
- texthooker/websocket module
- subsync module
3. Action Bus
- Add typed action dispatch (single command path for CLI/shortcut/IPC):
src/core/actions.ts(action type map)src/core/action-bus.ts(register/dispatch)
- All triggers emit actions; business logic subscribes once.
4. Provider Registries (Strategy Pattern)
- Replace hardcoded switch/if wiring with registries:
- tracker providers
- tokenizer providers
- translation providers
- subsync backend providers
5. Shared IPC Contract
- Single source of truth for IPC channels and payloads:
src/ipc/contract.tssrc/ipc/main-api.tssrc/ipc/renderer-api.ts
preload.tsand renderer consume typed wrappers instead of ad hoc channel strings.
6. Subtitle Pipeline
- Middleware/stage pipeline:
- ingest -> normalize -> tokenize -> merge -> enrich -> emit
- Files:
src/subtitle/pipeline.tssrc/subtitle/stages/*.ts
7. Module-Owned Config Extensions
- Keep
src/config/definitions.tsas the central resolved output. - Add registration path so modules can contribute config/runtime option metadata and defaults before final resolution.
Phased Delivery Plan
Phase 0: Baseline and Safety Net
Scope
- Add architecture docs and migration guardrails.
- Increase tests around currently stable behavior before structural changes.
Changes
- Add architecture decision notes:
docs/development.md(new section: architecture/migration)docs/architecture.md(new)
- Add basic smoke tests for command routing, overlay visibility toggles, and config load behavior.
Exit Criteria
- Existing behavior documented with acceptance checklist.
- CI/build + config tests green.
Phase 1: Extract I/O Surfaces
Scope
- Isolate IPC and global shortcut registration from
src/main.tswithout changing semantics.
Changes
- Create:
src/core/services/ipc-service.tssrc/core/services/shortcut-service.ts
- Move
ipcMain.handle/onregistration blocks fromsrc/main.tsintoIpcService.register(...). - Move global shortcut registration into
ShortcutService.registerGlobal(...). - Keep old entrypoints in
main.tsdelegating to new service methods.
Exit Criteria
- No user-visible behavior changes.
src/main.tsshrinks materially.- Manual verification:
- overlay toggles
- copy/mine shortcuts
- runtime options open/cycle
Phase 2: Introduce Action Bus
Scope
- Canonicalize command execution path.
Changes
- Add typed action bus (
src/core/action-bus.ts,src/core/actions.ts). - Convert these triggers to dispatch actions instead of direct calls:
- CLI handling (
handleCliCommandpath) - shortcut handlers
- IPC command handlers
- CLI handling (
- Keep existing business functions as subscribers initially.
Exit Criteria
- One action path per command (no duplicated behavior branches).
- Unit tests for command mapping (CLI -> action, shortcut -> action, IPC -> action).
Phase 3: Module Runtime Skeleton
Scope
- Add module contract and migrate one low-risk feature first.
Changes
- Introduce:
src/core/module.tssrc/core/module-registry.tssrc/core/app-context.ts
- First migration target: runtime options
- create
src/modules/runtime-options/module.ts - wire existing
RuntimeOptionsManagerthrough module lifecycle.
- create
Exit Criteria
- Runtime options fully owned by module.
- Core app can start with module list and deterministic module init order.
Phase 4: Provider Registries
Scope
- Remove hardcoded provider selection.
Changes
- Window tracker:
- Replace switch in
src/window-trackers/index.tswith registry API. - Add provider objects for hyprland/sway/x11/macos.
- Replace switch in
- Tokenizer/translator/subsync:
- Add analogous registries in new provider directories.
Exit Criteria
- Adding a provider requires adding one file + registration line.
- No edits required in composition root for new provider variants.
Phase 5: Shared IPC Contract
Scope
- Eliminate channel/payload drift between main/preload/renderer.
Changes
- Add typed IPC contract files under
src/ipc/. - Refactor
src/preload.tsto generate API from shared contract wrappers. - Refactor renderer calls to consume typed API interface from shared module.
Exit Criteria
- Channel names declared once.
- Compile-time checking across main/preload/renderer for payload mismatch.
Phase 6: Subtitle Pipeline
Scope
- Extract subtitle transformations into composable stages.
Changes
- Create pipeline framework and migrate existing tokenization/merge flow:
- stage: normalize subtitle
- stage: tokenize (
MecabTokenizeradapter) - stage: merge tokens (
mergeTokensadapter) - stage: post-processing/enrichment hooks
- Integrate pipeline execution into subtitle update loop.
Exit Criteria
- Current output parity for tokenization/merged token behavior.
- Stage-level tests for deterministic input/output.
Phase 7: Moduleized Integrations
Scope
- Convert major features to modules in descending complexity.
Migration Order
- Jimaku
- Texthooker/WebSocket bridge
- Subsync
- Anki integration
Exit Criteria
- Each feature has independent init/start/stop lifecycle.
- App startup composes modules instead of hardcoded inline setup.
Recommended File Layout (Target)
src/
core/
app-orchestrator.ts
app-context.ts
actions.ts
action-bus.ts
module.ts
module-registry.ts
services/
ipc-service.ts
shortcut-service.ts
overlay-service.ts
mpv-service.ts
subtitle-service.ts
modules/
runtime-options/module.ts
jimaku/module.ts
texthooker/module.ts
subsync/module.ts
anki/module.ts
ipc/
contract.ts
main-api.ts
renderer-api.ts
subtitle/
pipeline.ts
stages/
normalize.ts
tokenize-mecab.ts
merge-default.ts
enrich.ts
PR Breakdown (Suggested)
- PR1: Phase 1 (
IpcService,ShortcutService, no behavior changes) - PR2: Phase 2 (action bus + trigger mapping)
- PR3: Phase 3 (module skeleton + runtime options module)
- PR4: Phase 4 (window tracker registry + provider pattern)
- PR5: Phase 5 (shared IPC contract)
- PR6: Phase 6 (subtitle pipeline)
- PR7+: Phase 7 (feature-by-feature module migrations)
Validation Matrix
- Build/typecheck:
pnpm run build
- Config correctness:
pnpm run test:config
- Manual checks per PR:
- app start/stop/toggle CLI
- visible/invisible overlay control
- global shortcuts
- subtitle render and token display
- runtime options open + cycle
- anki mine flow + update-from-clipboard
Backward Compatibility Rules
- Preserve existing CLI flags and IPC channel behavior during migration.
- Maintain config shape compatibility; only additive changes unless versioned migration is added.
- Keep default behavior equivalent for all supported compositor backends.
Key Risks and Mitigations
- Risk: behavior regressions during extraction.
- Mitigation: move code verbatim first, refactor second; keep thin delegates in
main.tsuntil stable.
- Mitigation: move code verbatim first, refactor second; keep thin delegates in
- Risk: module lifecycle race conditions.
- Mitigation: explicit init order, idempotent
start/stop, and startup dependency checks.
- Mitigation: explicit init order, idempotent
- Risk: IPC contract churn breaks renderer.
- Mitigation: contract wrappers and compile-time types; temporary compatibility adapters.
- Risk: feature coupling around anki/mine flows.
- Mitigation: defer high-coupling module migrations until action bus and shared app context are stable.
Definition of Done (Program-Level)
src/main.tsreduced to bootstrap/composition responsibilities.- New feature prototype can be added as an isolated module with:
- module file
- optional provider registration
- optional config schema registration
- no invasive edits across unrelated subsystems
- IPC and command routing are single-path and typed.
- Existing user workflows remain intact.