# 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//...` 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) - [x] Decide one canonical entry->bucket mutation mechanism (`context` OR `event`) - [x] Remove the non-canonical mechanism and all references - [x] Verify there is no duplicate refresh trigger path - [x] Document chosen mechanism in instructions ## Phase 1 - Instruction and Governance Updates - [x] Update `.github/copilot-instructions.md` - [x] Update `PROJECT_INSTRUCTIONS.md` - [x] Add "single mechanism per concern" rule - [x] Add file-size/complexity refactor thresholds - [x] Add dead-path cleanup rule - [x] Add architecture-consistency checklist to PR expectations ## Phase 2 - Folder Structure Scaffolding - [x] Create `apps/web/features/` - [x] Create `apps/web/shared/` - [x] Define domain folders: - [x] `features/entries` - [x] `features/buckets` - [x] `features/groups` - [x] `features/tags` - [x] `features/auth` - [x] Add minimal README/tree notes in new folders (optional but recommended) ## Phase 3 - Incremental Domain Migration ### Entries + Buckets first (highest coupling) - [x] Move entries UI/components into `features/entries/components` - [x] Move buckets UI/components into `features/buckets/components` - [x] Move domain hooks into `features//hooks` (or keep centralized with strict naming, pick one and stay consistent) - [x] Add temporary compatibility re-exports from old paths ### Remaining domains - [x] Migrate groups - [x] Migrate tags - [x] Migrate auth ## Phase 4 - Import and Boundary Cleanup - [x] Replace legacy imports with new feature paths - [x] Ensure container vs presentational separation in large panels - [x] Remove obsolete compatibility re-exports once import migration is complete - [x] Remove dead files and stale helpers ## Phase 5 - Validation and Non-Regression - [x] Run typecheck - [ ] Run lint - [x] 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//{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) - [x] Entry->bucket update mechanism currently shows architectural drift (context and event patterns both present in codebase references). - [x] `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).