Claude Code Session Context¶
This document preserves context, preferences, and learned patterns across Claude Code sessions for the cbapp project.
User Workflow Preferences¶
Command Shorthand¶
| Phrase | Meaning |
|---|---|
| "tag and push" | Create next semver tag + git push origin main --tags |
| "tech debt mode" | Maintenance cycle using ./hygiene/ docs |
| "go to tag and push" | Ready to release, create tag and push |
Commit Style¶
- Format: Conventional commits (
fix:,feat:,style:,refactor:,docs:,test:,chore:) - Footer: Always include:
- HEREDOC: Use HEREDOC for multi-line commit messages
Release Process¶
- User confirms ready with "tag and push" or similar
- Check current version:
git tag --sort=-v:refname | head -1 - Increment patch version (e.g., v0.4.38 → v0.4.39)
- Tag and push:
git tag v0.4.39 && git push origin main --tags - Report success with version number
Project State (Updated: 2025-12-20)¶
Current Version¶
- v0.4.38 (as of last session)
Technical Debt Tracking¶
Maintained in:
- CLAUDE.md → Technical Debt section
- GITHUB_ISSUES.md → Open issues
- hygiene/FINDINGS-*.md → Maintenance cycle results
Known Migration States¶
| Component | State | Action Required |
|---|---|---|
person_tag table |
Dual-write to record_tag |
Migrate reads before dropping |
tag.parent_id |
Deprecated | Use category field |
Pydantic @validator |
4 instances remaining | Migrate to @field_validator |
FastAPI on_event |
1 instance | Use lifespan handlers |
Testing Knowledge¶
Test Configuration¶
# Unit tests (default, ~273 tests, ~11s)
pytest
# E2E tests (requires live testsite.nominate.ai)
pytest tests/e2e/ -v
# E2E tests are excluded by default via pytest.ini:
# addopts = -v --ignore=tests/e2e
Test Credentials (testsite)¶
- Username:
admin - Password:
admin123 - URL:
https://testsite.nominate.ai
API Patterns¶
Response Wrapping¶
All list endpoints return wrapped objects:
# Correct API response format
{"assignments": [...]}
{"persons": [...]}
{"tags": [...]}
# Frontend access pattern
const data = await response.json();
const items = data.assignments; // NOT data directly
Authentication¶
- JWT tokens via
Authorization: Bearer <token> - API key auth via
X-API-Keyheader (service-to-service) - Tokens expire per
SESSION_INACTIVITY_TIMEOUT_MINUTES(default: 10)
File Locations¶
Key Configuration Files¶
| File | Purpose |
|---|---|
CLAUDE.md |
Project instructions for Claude Code |
docs/CLAUDE-EDITIONS.md |
This file - session context |
GITHUB_ISSUES.md |
Manual issue tracker |
hygiene/CODE-MAINTENANCE-CYCLE.md |
Maintenance process guide |
hygiene/FINDINGS-*.md |
Maintenance cycle results |
pytest.ini |
Test configuration |
pyproject.toml |
Ruff and project config |
Related Projects¶
| Project | Path | Purpose |
|---|---|---|
| testsite | /home/bisenbek/projects/nominate/testsite |
Test deployment |
| cbdistricts | /home/bisenbek/projects/nominate/cbdistricts |
District data API |
| cbtenant | (separate repo) | Tenant manager |
Maintenance Cycle Process¶
When user says "tech debt mode" or similar:
- Read hygiene docs:
./hygiene/CODE-MAINTENANCE-CYCLE.md - Check previous findings:
./hygiene/FINDINGS-*.md - Check open issues:
./GITHUB_ISSUES.md - Create todo list with phases
- Execute systematically, committing after each phase
- Create findings doc:
./hygiene/FINDINGS-YYYY-MM-DD.md - Update CLAUDE.md if technical debt status changes
Typical Phases¶
- Ruff auto-fix (
ruff check --fix .) - Manual lint fixes
- Deprecation warnings
- Schema cleanup (if ready)
- Test verification
- Documentation update
Code Style Reminders¶
Pydantic v2 (Current Standard)¶
# Models
from pydantic import BaseModel, ConfigDict
class MyModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
# Settings
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", extra="allow")
# Field validation
from pydantic import field_validator
@field_validator("field_name")
@classmethod
def validate_field(cls, v):
return v
Exception Handling¶
# Correct - specific exceptions
except (json.JSONDecodeError, TypeError):
pass
# Incorrect - bare except
except:
pass
Type Hints¶
# Correct (modern syntax)
def func(items: list[str] | None = None) -> dict[str, Any]:
pass
# Deprecated
from typing import List, Optional, Dict
def func(items: Optional[List[str]] = None) -> Dict[str, Any]:
pass
Session History Log¶
2025-12-20¶
Maintenance cycle completed (v0.4.38): - Fixed 354 ruff lint issues (330 auto + 24 manual) - Modernized Pydantic config to v2 syntax - Excluded e2e tests from default runs - Created findings doc
Bug fix (v0.4.37):
- Fixed segments page error: assignments.map is not a function
- API returns {assignments: [...]}, frontend expected array directly
Notes for Future Sessions¶
- Before dropping person_tag: Migrate all reads to record_tag first
- Before dropping parent_id: Migrate all code to use category
- E2E tests: Only run when explicitly testing against testsite
- Version bumps: User will say "tag and push" when ready
- Maintenance docs: Always update findings after hygiene work