Move early lessons (fixes baked into codebase) to docs/LESSONS-ARCHIVE.md. Condense lessons 41-65 to one-liners. Reduces system prompt token usage by ~34% while preserving all actively relevant context. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
84 lines
4.9 KiB
Markdown
84 lines
4.9 KiB
Markdown
# Lessons Archive (1-40)
|
|
|
|
> These lessons were originally in CLAUDE.md. They've been archived because the fixes are now baked into the codebase. Consult this file if you encounter a regression in any of these areas.
|
|
|
|
**1. DateTime Handling — Always timezone-aware:** `Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))`. NEVER use `datetime.utcnow()`.
|
|
|
|
**2. SQLAlchemy Async — No lazy loading on new objects:** Use direct SQL for junction tables: `await db.execute(tree_tag_assignments.insert().values(...))`.
|
|
|
|
**3. React State — Don't store object snapshots:** Store IDs, derive objects: `const editingNode = editingNodeId ? findNode(editingNodeId, tree?.tree_structure) : null`.
|
|
|
|
**4. Modal Draft State — Exclude store-managed fields:** `const { children, ...draftWithoutChildren } = draft; updateNode(node.id, draftWithoutChildren)`.
|
|
|
|
**5. Multiple FKs to same table:** Specify `foreign_keys` on BOTH sides: `author = relationship("User", foreign_keys=[author_id], back_populates="trees")`.
|
|
|
|
**6. PostgreSQL NULL in UUID columns:** `SELECT 'tag', 'slug', NULL::uuid as team_id` — must cast NULL to uuid.
|
|
|
|
**7. API Path Gotcha:** Frontend `apiClient` baseURL is `http://localhost:8000/api/v1` — use relative paths WITHOUT `/api/v1/` prefix. Invite codes endpoint is `/invites` (NOT `/invite-codes`).
|
|
|
|
**8. CORS errors can mask 500s:** Check backend logs first. Also run `alembic upgrade head` after pulling changes.
|
|
|
|
**9. Public endpoints with optional auth:** Use manual `_get_optional_user(request, db)` helper, NOT `Optional[User]` param.
|
|
|
|
**10. React Router — Clear dirty state before navigation:** `markSaved()` before `navigate()`.
|
|
|
|
**11. CORS `expose_headers` for custom response headers:** Must be set in BOTH CORS branches in `main.py`.
|
|
|
|
**12. TreeStructure vs Tree types:** `TreeStructure` is for node structure only — it does NOT have `tree_type`, `name`, etc. Those are on `Tree`.
|
|
|
|
**13. Login redirect state format:** `navigate('/login', { state: { from: { pathname: '/path' } } })` — expects `state.from.pathname` (object), NOT a plain string.
|
|
|
|
**14. Type-aware routing:** Always use `getTreeNavigatePath(treeId, treeType)` from `@/lib/routing`. Procedural flows use `/flows/:id/navigate`.
|
|
|
|
**15. Session sharing types:** Use `tree_snapshot?.tree_type` to determine flow type from session data.
|
|
|
|
**16. tree_type has three values:** `'troubleshooting' | 'procedural' | 'maintenance'`. Use `PROCEDURAL_TREE_TYPES` set when checking for step-based flow types.
|
|
|
|
**17. Alembic autogenerate can be destructive:** Always review generated migrations. Prefer manual migrations for new tables.
|
|
|
|
**18. Pydantic partial updates — use `model_fields_set`:** Check `data.model_fields_set` to distinguish "field not sent" from "field sent as null".
|
|
|
|
**19. `gh pr merge` fails with worktrees:** Use the API: `gh api repos/ORG/REPO/pulls/N/merge --method PUT --field merge_method=squash`.
|
|
|
|
**20. `'answer'` node type in TreeStructure:** Transient stub type used only in the canvas editor. Must explicitly handle in any `node.type` switch.
|
|
|
|
**21. Test fixtures in `conftest.py`:** `client`, `test_db`, `test_user`, `auth_headers`, `test_tree`, `test_admin`, `admin_auth_headers`. NO `async_client` or `engineer_token`.
|
|
|
|
**22. Worktree venv path:** Use `backend/venv/bin/python -m pytest ...` from the worktree directory.
|
|
|
|
**23. Action nodes navigate via `next_node_id`, not `children`:** Must set `next_node_id` on action nodes for AI generation or manual editing.
|
|
|
|
**24. Anthropic model IDs:** Both alias (`claude-sonnet-4-6`) and dated forms work. Default: `claude-sonnet-4-6`.
|
|
|
|
**25. Claude API may wrap JSON responses in markdown fences:** Always strip fences before parsing. See `_strip_markdown_fences()`.
|
|
|
|
**26. `sessionsApi.list` supports `batch_id` filter.**
|
|
|
|
**27. Maintenance batch sessions are created all-at-once at launch.**
|
|
|
|
**28. AI tests in CI need `ai_enabled` mock:** Mock `settings.ai_enabled = True` via `PropertyMock`. See `tests/test_ai_chat.py`.
|
|
|
|
**29. ESLint `no-unused-vars` has no `argsIgnorePattern`:** Use `// eslint-disable-next-line` or remove the param.
|
|
|
|
**30. Alembic `env.py` must import all models.**
|
|
|
|
**31. JSONB fields — convert datetime to `.isoformat()` string.**
|
|
|
|
**32. Export pipeline order matters:** Generate → resolve variables → apply redaction. Redaction MUST run last.
|
|
|
|
**33. Railway: `DATABASE_URL_SYNC` is a property, not an env var.**
|
|
|
|
**34. Railway: run migrations in Docker CMD, not `releaseCommand`.**
|
|
|
|
**35. `bcrypt==4.0.1` pinned for passlib compatibility.**
|
|
|
|
**36. Email validator rejects `.local` TLD:** Use `example.com` for test/seed emails.
|
|
|
|
**37. First deployed user needs manual admin promotion via SQL.**
|
|
|
|
**38. Alembic migrations MUST use sequential numbered prefixes:** Always pass `--rev-id` flag.
|
|
|
|
**39. Platform settings for feature toggles:** Use `SettingsManager.get("key", db, default=True)`.
|
|
|
|
**40. Survey public routes:** Add at top level in `router.tsx` alongside `/login`.
|