Skip to content

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:
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
    
  • HEREDOC: Use HEREDOC for multi-line commit messages

Release Process

  1. User confirms ready with "tag and push" or similar
  2. Check current version: git tag --sort=-v:refname | head -1
  3. Increment patch version (e.g., v0.4.38 → v0.4.39)
  4. Tag and push: git tag v0.4.39 && git push origin main --tags
  5. 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-Key header (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
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:

  1. Read hygiene docs: ./hygiene/CODE-MAINTENANCE-CYCLE.md
  2. Check previous findings: ./hygiene/FINDINGS-*.md
  3. Check open issues: ./GITHUB_ISSUES.md
  4. Create todo list with phases
  5. Execute systematically, committing after each phase
  6. Create findings doc: ./hygiene/FINDINGS-YYYY-MM-DD.md
  7. Update CLAUDE.md if technical debt status changes

Typical Phases

  1. Ruff auto-fix (ruff check --fix .)
  2. Manual lint fixes
  3. Deprecation warnings
  4. Schema cleanup (if ready)
  5. Test verification
  6. 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

  1. Before dropping person_tag: Migrate all reads to record_tag first
  2. Before dropping parent_id: Migrate all code to use category
  3. E2E tests: Only run when explicitly testing against testsite
  4. Version bumps: User will say "tag and push" when ready
  5. Maintenance docs: Always update findings after hygiene work