2026-02-23 21:17:00 -06:00

63 lines
4.3 KiB
Markdown

# Backend Refactoring Summary
## Problem
`Entry.cs` was a 550-line god class that contained command dispatching, business logic, HTML sanitization, logging infrastructure, and 13 private payload record types. The two Python sidecar services (`PythonSidecarAiService` and `PythonSidecarSpeechService`) duplicated ~80 lines of identical process/JSON plumbing. Payload DTOs were hidden as private records inside `Entry.cs` instead of being in the `Dtos/` folder.
## What Changed
### 1. Slimmed `Entry.cs` to a thin dispatcher (~330 lines)
Removed all business logic, HTML processing, logging implementation, and private record types. `Entry` now only parses the incoming JSON command, routes to the correct service, and returns the `{ok, data}` / `{ok: false, error}` envelope.
### 2. Extracted `HtmlSanitizer` (new file)
`StripRichHtml` and `LooksLikeRichHtml` moved from `Entry.cs` to `Services/HtmlSanitizer.cs` as a static utility class.
### 3. Extracted `CommandLogger` (new file)
`LogStart`, `LogSuccess`, `LogFailure`, `EmitLog`, `ShouldLog`, and `LogLevelRank` moved from `Entry.cs` to `Services/CommandLogger.cs`. Entry now receives this as a dependency.
### 4. Extracted `IEntryFileService` + `EntryFileService` (new files)
`SaveEntry`, `LoadEntry`, `ListEntries`, and `ResolveTargetPath` moved out of `Entry.cs` into a proper service with an interface. This follows the same pattern as `IFragmentService` / `FragmentService`.
### 5. Added `IEntryFileRepository` + `DiskEntryFileRepository` (new files)
`EntryFileService` now delegates all filesystem I/O (read, write, append, list, exists) to an `IEntryFileRepository`, keeping only business logic (HTML sanitization, parsing, merging) in the service. This mirrors the Fragment module's repository pattern (`IFragmentRepository``FragmentService`). An in-memory implementation can be swapped in for testing.
### 6. Extracted `PythonSidecarClient` (new file)
The duplicated `SendAsync`, `LastJsonLine`, and `TryKill` methods were extracted from both `PythonSidecarAiService` and `PythonSidecarSpeechService` into a shared `Services/PythonSidecarClient.cs`. Both services now delegate to it.
### 7. Moved payload records to `Dtos/CommandDtos.cs` (new file)
The 16 private payload/result records that were inside `Entry.cs` are now in `Dtos/CommandDtos.cs`. Records used through public interfaces (`EntrySavePayload`, `EntryListItem`, `EntryLoadResult`, `EntrySaveResult`) are public; the rest remain internal.
### 8. Moved database result records to `Dtos/DatabaseDtos.cs` (new file)
`JournalDatabaseStatus` and `JournalDatabaseHydrationResult` moved from `IJournalDatabaseService.cs` to `Dtos/DatabaseDtos.cs` for consistency with the other DTO files.
## Files Created
- `Journal.Core/Services/HtmlSanitizer.cs`
- `Journal.Core/Services/CommandLogger.cs`
- `Journal.Core/Services/IEntryFileService.cs`
- `Journal.Core/Services/EntryFileService.cs`
- `Journal.Core/Services/PythonSidecarClient.cs`
- `Journal.Core/Repositories/IEntryFileRepository.cs`
- `Journal.Core/Repositories/DiskEntryFileRepository.cs`
- `Journal.Core/Dtos/CommandDtos.cs`
- `Journal.Core/Dtos/DatabaseDtos.cs`
## Files Modified
- `Journal.Core/Entry.cs` — slimmed to thin dispatcher
- `Journal.Core/Services/PythonSidecarAiService.cs` — delegates to PythonSidecarClient
- `Journal.Core/Services/PythonSidecarSpeechService.cs` — delegates to PythonSidecarClient
- `Journal.Core/Services/IJournalDatabaseService.cs` — result records moved to Dtos
- `Journal.Core/Services/JournalDatabaseService.cs` — added Dtos using
- `Journal.Core/ServiceCollectionExtensions.cs` — registers new services and repository
- `Journal.SmokeTests/Program.cs` — updated NewEntry() with new dependencies
## What Was NOT Changed
- **Fragment module** — already clean, untouched
- **Config module** — singleton reader, no changes needed
- **Vault module** — already well-separated (crypto/storage), untouched
- **AI/Speech interfaces and disabled variants** — untouched (only the sidecar implementations were refactored)
- **Search module** — stateless query service, no repository needed
- **All test logic** — no assertions or test behavior changed
## Verification
- All 4 projects build successfully
- 70/70 smoke tests pass (5 Python sidecar tests fail only when Python is not installed on the machine, which is pre-existing)