fiddy/docs/03_REFACTOR_1.md

9.7 KiB

Refactor 1 - Domain-First Folder Structure

Purpose

Improve reviewability and long-term maintainability by moving from mostly flat frontend folders to a domain-first structure with clear ownership and lower coupling.

Scope

  • Frontend structure in apps/web
  • Instruction consistency updates
  • Incremental migration with compatibility shims
  • No behavior changes intended during structure migration

Source Of Truth And Alignment

Use this precedence order when guidance conflicts:

  1. PROJECT_INSTRUCTIONS.md (repo-level source of truth)
  2. .github/copilot-instructions.md (architecture and coding rules)
  3. docs/03_REFACTOR_1.md (this execution tracker and decisions for Refactor 1)

Current refactor-alignment decisions:

  • Canonical entry->bucket mutation mechanism: EntryMutationContext
  • Domain-first target layout: apps/web/features/<domain>/... and apps/web/shared/...
  • Compatibility re-exports removed on 2026-02-12; new imports must use feature-owned paths

Context Compression Guardrails

  • At the start of each new session, read this file and the two source-of-truth docs above.
  • Before implementation, re-state active decisions from "Current refactor-alignment decisions".
  • Add noteworthy changes to "Notes Log" immediately when discovered.
  • Do not introduce a second mechanism for any existing concern without logging a decision here first.

Phase 0 - Architecture Alignment (single mechanism rule)

  • Decide one canonical entry->bucket mutation mechanism (context OR event)
  • Remove the non-canonical mechanism and all references
  • Verify there is no duplicate refresh trigger path
  • Document chosen mechanism in instructions

Phase 1 - Instruction and Governance Updates

  • Update .github/copilot-instructions.md
  • Update PROJECT_INSTRUCTIONS.md
  • Add "single mechanism per concern" rule
  • Add file-size/complexity refactor thresholds
  • Add dead-path cleanup rule
  • Add architecture-consistency checklist to PR expectations

Phase 2 - Folder Structure Scaffolding

  • Create apps/web/features/
  • Create apps/web/shared/
  • Define domain folders:
    • features/entries
    • features/buckets
    • features/groups
    • features/tags
    • features/auth
  • Add minimal README/tree notes in new folders (optional but recommended)

Phase 3 - Incremental Domain Migration

Entries + Buckets first (highest coupling)

  • Move entries UI/components into features/entries/components
  • Move buckets UI/components into features/buckets/components
  • Move domain hooks into features/<domain>/hooks (or keep centralized with strict naming, pick one and stay consistent)
  • Add temporary compatibility re-exports from old paths

Remaining domains

  • Migrate groups
  • Migrate tags
  • Migrate auth

Phase 4 - Import and Boundary Cleanup

  • Replace legacy imports with new feature paths
  • Ensure container vs presentational separation in large panels
  • Remove obsolete compatibility re-exports once import migration is complete
  • Remove dead files and stale helpers

Phase 5 - Validation and Non-Regression

  • Run typecheck
  • Run lint
  • Run relevant unit tests
  • Smoke-test key UI flows:
    • Entry create/update/delete
    • Bucket usage updates
    • Edit modal discard behavior
    • Group switch behavior

Phase 6 - Consolidation

  • Publish final structure map in docs
  • Confirm all checklist items closed
  • Capture lessons learned and follow-up actions

Notes Log (append as we discover issues)

  • [YYYY-MM-DD] Observation:

    • Context:
    • Impact:
    • Decision:
    • Follow-up:
  • [YYYY-MM-DD] Alignment Snapshot:

    • Active mechanism:
    • Active folder strategy:
    • Remaining migration risk:
  • [2026-02-12] Observation:

    • Context: Entry->bucket mutation flow had architectural drift (context + custom event mechanism both present).
    • Impact: Higher cognitive load and harder debugging/review for regressions.
    • Decision: Standardized on EntryMutationContext; removed entry-mutation-events.
    • Follow-up: Keep scanning for duplicate state propagation patterns during domain migration.
  • [2026-02-12] Observation:

    • Context: During migration edits, a literal `r`n sequence was accidentally inserted in entries-panel.tsx.
    • Impact: Broke readability and could have caused compile/runtime issues.
    • Decision: Fixed immediately and added note to keep encoding/text clean during scripted edits.
    • Follow-up: Keep post-edit grep checks for suspicious escaped literals.
  • [2026-02-12] Observation:

    • Context: npx tsc --noEmit still fails on pre-existing server/test typing issues unrelated to this refactor slice.
    • Impact: Full type-green gating cannot yet be used as a migration stop condition.
    • Decision: Track failures as known baseline until addressed in separate debt fixes.
    • Follow-up: Re-run typecheck after each migration phase and confirm no net-new errors.
  • [2026-02-12] Observation:

    • Context: Alignment details were spread across multiple docs and easy to miss after context compression.
    • Impact: Higher risk of inconsistent implementation choices between sessions.
    • Decision: Added explicit source-of-truth precedence and context-compression guardrails in this file.
    • Follow-up: Keep the "Current refactor-alignment decisions" block updated whenever a major choice changes.
  • [2026-02-12] Observation:

    • Context: Hook migration started with entries and buckets domains.
    • Impact: Domain ownership is clearer; old import paths still function via compatibility re-exports.
    • Decision: Keep compatibility exports in apps/web/hooks until remaining domains are migrated.
    • Follow-up: Migrate groups/tags/auth hooks and then remove legacy re-exports.
  • [2026-02-12] Observation:

    • Context: Migrated auth/groups/tags hooks into apps/web/features/*/hooks and converted legacy apps/web/hooks/use-*.ts files to compatibility re-exports.
    • Impact: Domain ownership is now explicit while existing imports remain functional during the transition.
    • Decision: Keep compatibility shims until Phase 4 import cleanup is complete.
    • Follow-up: Remove compatibility shims in Phase 4 after all legacy component path re-exports are retired.
  • [2026-02-12] Alignment Snapshot:

    • Active mechanism: EntryMutationContext
    • Active folder strategy: domain-first features (apps/web/features/<domain>/{components,hooks})
    • Remaining migration risk: leftover compatibility imports and large mixed-responsibility panels.
  • [2026-02-12] Observation:

    • Context: Replaced the final app-level @/hooks/use-* import (apps/web/components/recurring-entries-panel.tsx) with a feature hook import.
    • Impact: Runtime code now reads hooks from feature-owned locations; apps/web/hooks/use-*.ts are compatibility shims only.
    • Decision: Keep shims temporarily for migration safety.
    • Follow-up: Delete hook shims during Phase 4 once no external references remain.
  • [2026-02-12] Observation:

    • Context: PowerShell write operations introduced BOM and mojibake artifacts in a few migrated files.
    • Impact: Increased review noise and risk of accidental text regressions.
    • Decision: Normalized touched files to UTF-8 without BOM and replaced unstable glyphs with ASCII-safe equivalents.
    • Follow-up: Prefer no-BOM file writes and run a quick mojibake scan after scripted edits.
  • [2026-02-12] Observation:

    • Context: Removed obsolete compatibility re-export files under apps/web/components and apps/web/hooks/use-*.ts.
    • Impact: Reduced duplicate paths and eliminated stale import targets.
    • Decision: Treat apps/web/features/* as the only valid home for migrated component/hook implementations.
    • Follow-up: Continue Phase 4 by splitting large panels and removing any remaining dead paths.
  • [2026-02-12] Observation:

    • Context: apps/web/components/recurring-entries-panel.tsx and apps/web/hooks/use-recurring-entries.ts had no references and were removed.
    • Impact: Fewer dead maintenance paths and clearer active surface area.
    • Decision: Keep recurring-entry behavior in server/client domain modules only until a routed UI is reintroduced.
    • Follow-up: If recurring UI returns, add it directly under features/entries/components.
  • [2026-02-12] Observation:

    • Context: Lint validation is currently blocked because npm run lint calls next lint (invalid for current Next setup) and direct eslint has no config file.
    • Impact: Lint cannot be used yet as a gating signal in this repo state.
    • Decision: Keep lint checklist unchecked and treat as tooling debt.
    • Follow-up: Add/restore ESLint config and update lint script before enforcing lint gates.
  • [2026-02-12] Observation:

    • Context: Split features/entries/components/entries-panel.tsx by extracting EntriesList, EntriesFilterModal, and EntriesDiscardModal.
    • Impact: Smaller container panel with clearer behavior vs presentation boundaries and simpler review scope.
    • Decision: Keep stateful orchestration in EntriesPanel and move UI-heavy rendering to dedicated presentational components.
    • Follow-up: Apply the same split pattern to other oversized panels (notably group settings) in a later pass.

Known Notes (seed)

  • Entry->bucket update mechanism currently shows architectural drift (context and event patterns both present in codebase references).
  • entries-panel.tsx remains large and should be split during migration for reviewability.
  • Preserve behavior while moving files; avoid functional changes in structure-only PRs.

Exit Criteria

  • Single, documented mutation propagation mechanism in use.
  • Domain-first structure in place and imports migrated.
  • No stale paths or duplicate mechanisms left.
  • Validation checks pass (or known pre-existing failures documented separately).