Files
resolutionflow/docs/LESSONS-ARCHIVE.md
chihlasm a5620f276d docs: archive lessons 1-40, condense CLAUDE.md from 40KB to 26KB
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>
2026-03-16 21:05:20 -04:00

4.9 KiB

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.