66
apps/web/docs/ARCHITECTURE.md
Executable file
66
apps/web/docs/ARCHITECTURE.md
Executable file
@@ -0,0 +1,66 @@
|
||||
# AdventureOS Architecture
|
||||
|
||||
AdventureOS is a Next.js 16 full-stack monolith with npm workspaces.
|
||||
|
||||
## Layers
|
||||
|
||||
```
|
||||
Browser (React + TanStack Query + Zustand)
|
||||
↓ fetch /api/*
|
||||
Next.js Route Handlers (app/api/**)
|
||||
↓ validation (lib/validation) + handleApi (lib/api)
|
||||
Domain Services (lib/services/**)
|
||||
↓
|
||||
Repositories (lib/repositories/**) — Drizzle queries
|
||||
Packages: @adventureos/db, @adventureos/shared
|
||||
```
|
||||
|
||||
## Frontend boundaries
|
||||
|
||||
| Path | Responsibility |
|
||||
|------|----------------|
|
||||
| `app/*/page.tsx` | Route pages, data fetching via React Query |
|
||||
| `components/features/` | Domain UI components |
|
||||
| `components/ui/` | Reusable retro UI primitives |
|
||||
| `features/*/api.ts` | Typed client fetch wrappers |
|
||||
| `hooks/` | Shared React hooks (mutations, toasts) |
|
||||
| `stores/ui.ts` | Ephemeral UI state (toasts, modals) |
|
||||
| `themes/` | CSS token registry and runtime theme switching |
|
||||
|
||||
## Backend boundaries
|
||||
|
||||
| Path | Responsibility |
|
||||
|------|----------------|
|
||||
| `app/api/**/route.ts` | HTTP entry; parse/validate; call services |
|
||||
| `lib/services/adventure/` | Daily adventures, materialization, scoring, templates |
|
||||
| `lib/services/reading/` | Shared reading log + action recording |
|
||||
| `lib/services/ai*.ts` | AI generation, config, memory, chat, context |
|
||||
| `lib/services/ai-memory.ts` | User-controlled personal AI memories |
|
||||
| `lib/services/ai-context.ts` | Layered context builder for local models |
|
||||
| `lib/services/ai-chat.ts` | Mentor chat sessions and messages |
|
||||
| `lib/services/day-boundary.ts` | Configurable day rollover (after-midnight logging) |
|
||||
| `lib/repositories/` | Drizzle data access only |
|
||||
| `lib/config/` | Environment variables and domain constants |
|
||||
| `lib/errors/` | Typed errors and response mapping |
|
||||
| `lib/validation/` | Zod request schemas |
|
||||
|
||||
## Data stores
|
||||
|
||||
- **PostgreSQL** — primary app data via Drizzle (`packages/db`)
|
||||
- **Calibre metadata.db** — read-only SQLite via `better-sqlite3` when configured
|
||||
|
||||
## Service boundaries (rules)
|
||||
|
||||
1. Route handlers must not import Drizzle directly (use services/repositories).
|
||||
2. Repositories contain no business rules.
|
||||
3. Services orchestrate repositories, shared math, XP, and action events.
|
||||
4. Client components use `features/*/api.ts`, not raw fetch scattered in UI.
|
||||
5. `@adventureos/shared` holds pure domain types and formulas — no I/O.
|
||||
|
||||
## Known gaps
|
||||
|
||||
See [KNOWN-ISSUES.md](./KNOWN-ISSUES.md).
|
||||
|
||||
## Refactor history
|
||||
|
||||
See [REFACTOR-LOG.md](./REFACTOR-LOG.md).
|
||||
41
apps/web/docs/KNOWN-ISSUES.md
Executable file
41
apps/web/docs/KNOWN-ISSUES.md
Executable file
@@ -0,0 +1,41 @@
|
||||
# Known Issues
|
||||
|
||||
Issues discovered during refactor audit. Not fixed unless explicitly approved (behaviour preservation).
|
||||
|
||||
## Calibre reading undo is broken
|
||||
|
||||
Both manual (`reading.ts`) and Calibre (`calibre-reading.ts`) use `actionType: "reading.log_pages"`.
|
||||
|
||||
- Manual: `beforeState: { book: { currentPage, status, finishedAt } }`, `entityType: "book"`
|
||||
- Calibre: `beforeState: { currentPage, status }`, `entityType: "reading_progress"`
|
||||
|
||||
`undo.ts` case `"reading.log_pages"` only restores the manual `books` table. Undoing Calibre page logs will fail or corrupt state.
|
||||
|
||||
## Cron middleware requires session
|
||||
|
||||
`middleware.ts` does not exempt `/api/cron`. External cron with only `x-cron-secret` (per README) receives 401 before the route handler runs.
|
||||
|
||||
## Partial undo coverage
|
||||
|
||||
- `applyTemplateToDate` records no action event
|
||||
- Template item create/update not recorded (only delete)
|
||||
|
||||
**Fixed:** Reflection saves now record `reflection.save` action events for undo.
|
||||
|
||||
## HTTP status codes
|
||||
|
||||
`handleApi` maps thrown `"Item not found"` to 500, not 404. Normalising would change API contract.
|
||||
|
||||
## Dashboard may ignore Calibre progress
|
||||
|
||||
Stats and dashboard reading metrics query manual `books` / `reading_logs`; Calibre `reading_progress` may not feed scores.
|
||||
|
||||
## Dead / unused code
|
||||
|
||||
- `packages/shared/src/titles.ts` — exported, never imported
|
||||
- `action_events.inversePatch` — written, never read in undo
|
||||
- `getCalibreBook()` in calibre.ts — no-op implementation
|
||||
|
||||
## Undo UX inconsistency
|
||||
|
||||
Toast undo (`overlays.tsx`) reloads the page; settings undo invalidates React Query cache.
|
||||
74
apps/web/docs/REFACTOR-LOG.md
Executable file
74
apps/web/docs/REFACTOR-LOG.md
Executable file
@@ -0,0 +1,74 @@
|
||||
# Refactor Log
|
||||
|
||||
Internal refactor of AdventureOS. Behaviour, API contracts, and schema preserved unless explicitly noted.
|
||||
|
||||
## Phase 1: Safety baseline
|
||||
|
||||
- Removed debug telemetry from `apps/web/src/app/api/library/books/route.ts`
|
||||
- Extracted pure adventure helpers: `derive-state.ts`, `template-matching.ts`, `checklist-value.ts`
|
||||
- Added unit tests for `@adventureos/shared` (xp, levels, scores, chapters)
|
||||
- Added characterization tests for deriveState, template matching, undo Calibre mismatch
|
||||
- Replaced misnamed `feature-repair.test.ts` with real tests
|
||||
|
||||
### Manual smoke checklist
|
||||
|
||||
- [ ] Login / logout
|
||||
- [ ] Command Centre: adventure items, todos, rest day, customize
|
||||
- [ ] Settings: theme, AI config, templates, action history undo
|
||||
- [ ] Library: manual books and Calibre (if configured)
|
||||
- [ ] Cartographer: generate, activate, complete, dismiss
|
||||
- [ ] Teacher: generate, complete, deep links
|
||||
- [ ] Undo toast and settings undo
|
||||
|
||||
### Commands run each phase
|
||||
|
||||
```bash
|
||||
npm run test
|
||||
npm run lint
|
||||
npm run build
|
||||
npm run db:migrate # when DB available
|
||||
```
|
||||
|
||||
## Phase 2: Configuration and constants
|
||||
|
||||
- Centralised env reads in `lib/config/`
|
||||
- Typed constants for settings keys, action types, theme IDs
|
||||
|
||||
## Phase 3: API and data access
|
||||
|
||||
- Zod input validation on teacher, templates, settings routes
|
||||
- Repository layer for settings, teacher, adventure templates
|
||||
- Typed errors in `lib/errors/`; `handleApi` uses `mapErrorToResponse`
|
||||
- Teacher route uses `createTeacherLesson` service
|
||||
|
||||
## Phase 4: Domain/service cleanup
|
||||
|
||||
- Split `adventure.ts` into `lib/services/adventure/{materialization,daily,scoring,templates}.ts`
|
||||
- Unified Calibre reading log via `lib/services/reading/log-pages.ts`
|
||||
|
||||
## Phase 5: Frontend cleanup
|
||||
|
||||
- Client API: `features/adventure/api.ts`, `features/undo/api.ts`, `lib/api-client.ts`
|
||||
- Hooks: `useAdventureMutations`, `useUndoMutation`, `useActionToastHandlers`
|
||||
- Split `todays-adventure.tsx`; extracted `adventure-item-row`, `checklist-item`
|
||||
- Consolidated AI prompt editors into `AiPromptEditor`
|
||||
- Shared UI: `RetroWindow`, `TabToggle`, `LoadingState`, `ErrorState`
|
||||
- Undo toast uses query invalidation (no full page reload)
|
||||
|
||||
## Phase 6: Type safety
|
||||
|
||||
- JSONB interfaces in `lib/types/jsonb.ts`
|
||||
- Teacher types in `@adventureos/shared`
|
||||
- Removed unused `@radix-ui/*` dependencies
|
||||
|
||||
## Phase 7: Tests and CI
|
||||
|
||||
- Validation/error unit tests
|
||||
- `@adventureos/shared` test script and vitest config
|
||||
- Root `npm run test` runs web + shared
|
||||
- GitHub Actions CI workflow
|
||||
|
||||
## Phase 8: Documentation
|
||||
|
||||
- [ARCHITECTURE.md](./ARCHITECTURE.md) — layers and service boundaries
|
||||
- [KNOWN-ISSUES.md](./KNOWN-ISSUES.md) — documented gaps
|
||||
Reference in New Issue
Block a user