open-notebook/open_notebook/domain/CLAUDE.md
LUIS NOVO 71b8d13b24 docs: generate comprehensive CLAUDE.md reference documentation across codebase
Create a hierarchical CLAUDE.md documentation system for the entire Open Notebook
codebase with focus on concise, pattern-driven reference cards rather than
comprehensive tutorials.

## Changes

### Core Documentation System
- Updated `.claude/commands/build-claude-md.md` to distinguish between leaf and
  parent modules, with special handling for prompt/template modules
- Established clear patterns:
  * Leaf modules (40-70 lines): Components, hooks, API clients
  * Parent modules (50-150 lines): Architecture, cross-layer patterns, data flows
  * Template modules: Pattern focus, not catalog listings

### Generated Documentation
Created 15 CLAUDE.md reference files across the project:

**Frontend (React/Next.js)**
- frontend/src/CLAUDE.md: Architecture overview, data flow, three-tier design
- frontend/src/lib/hooks/CLAUDE.md: React Query patterns, state management
- frontend/src/lib/api/CLAUDE.md: Axios client, FormData handling, interceptors
- frontend/src/lib/stores/CLAUDE.md: Zustand state persistence, auth patterns
- frontend/src/components/ui/CLAUDE.md: Radix UI primitives, CVA styling

**Backend (Python/FastAPI)**
- open_notebook/CLAUDE.md: System architecture, layer interactions
- open_notebook/ai/CLAUDE.md: Model provisioning, Esperanto integration
- open_notebook/domain/CLAUDE.md: Data models, ObjectModel/RecordModel patterns
- open_notebook/database/CLAUDE.md: Repository pattern, async migrations
- open_notebook/graphs/CLAUDE.md: LangGraph workflows, async orchestration
- open_notebook/utils/CLAUDE.md: Cross-cutting utilities, context building
- open_notebook/podcasts/CLAUDE.md: Episode/speaker profiles, job tracking

**API & Other**
- api/CLAUDE.md: REST layer, service architecture
- commands/CLAUDE.md: Async command handlers, job queue patterns
- prompts/CLAUDE.md: Jinja2 templates, prompt engineering patterns (refactored)

**Project Root**
- CLAUDE.md: Project overview, three-tier architecture, tech stack, getting started

### Key Features
- Zero duplication: Parent modules reference child CLAUDE.md files, don't repeat them
- Pattern-focused: Emphasizes how components work together, not component catalogs
- Scannable: Short bullets, code examples only when necessary (1-2 per file)
- Practical: "How to extend" guides, quirks/gotchas for each module
- Navigation: Root CLAUDE.md acts as hub pointing to specialized documentation

### Cleanup
- Removed unused `batch_fix_services.py`
- Removed deprecated `open_notebook/plugins/podcasts.py`
- Updated .gitignore for documentation consistency

## Impact
New contributors can now:
1. Read root CLAUDE.md for system architecture (5 min)
2. Jump to specific layer documentation (frontend, api, open_notebook)
3. Dive into module-specific patterns in child CLAUDE.md files (1 min per module)
All documentation is lean, reference-focused, and avoids duplication.
2026-01-03 16:27:52 -03:00

4.1 KiB

Domain Module

Core data models for notebooks, sources, notes, and settings with async SurrealDB persistence, auto-embedding, and relationship management.

Purpose

Two base classes support different persistence patterns: ObjectModel (mutable records with auto-increment IDs) and RecordModel (singleton configuration with fixed IDs).

Key Components

base.py

  • ObjectModel: Base for notebooks, sources, notes

    • save(): Create/update with auto-embedding for searchable content
    • delete(): Remove by ID
    • relate(relationship, target_id): Create graph relationships (reference, artifact, refers_to)
    • get(id): Polymorphic fetch; resolves subclass from ID prefix
    • get_all(order_by): Fetch all records from table
    • Integrates with ModelManager for automatic embedding
  • RecordModel: Singleton configuration (ContentSettings, DefaultPrompts)

    • Fixed record_id per subclass
    • update(): Upsert to database
    • Lazy DB loading via _load_from_db()

notebook.py

  • Notebook: Research project container

    • get_sources(), get_notes(), get_chat_sessions(): Navigate relationships
  • Source: Content item (file/URL)

    • vectorize(): Submit async embedding job (returns command_id, fire-and-forget)
    • get_status(), get_processing_progress(): Track job via surreal_commands
    • get_context(): Returns summary for LLM context
    • add_insight(): Generate and store insights with embeddings
  • Note: Standalone or linked notes

    • needs_embedding(): Always True (searchable)
    • add_to_notebook(): Link to notebook
  • SourceInsight, SourceEmbedding: Derived content models

  • ChatSession: Conversation container with optional model_override

  • Asset: File/URL reference helper

  • Search functions:

    • text_search(): Full-text keyword search
    • vector_search(): Semantic search via embeddings (default minimum_score=0.2)

content_settings.py

  • ContentSettings: Singleton for processing engines, embedding strategy, file deletion, YouTube languages

transformation.py

  • Transformation: Reusable prompts for content transformation
  • DefaultPrompts: Singleton with transformation instructions

Important Patterns

  • Async/await: All DB operations async; always use await
  • Polymorphic get(): ObjectModel.get(id) determines subclass from ID prefix (table:id format)
  • Auto-embedding: save() generates embeddings if needs_embedding() returns True
  • Nullable fields: Declare via nullable_fields ClassVar to allow None in database
  • Timestamps: created and updated auto-managed as ISO strings
  • Fire-and-forget jobs: source.vectorize() returns command_id without waiting

Key Dependencies

  • surrealdb: RecordID type for relationships
  • pydantic: Validation and field_validator decorators
  • open_notebook.database.repository: CRUD and relationship functions
  • open_notebook.ai.models: ModelManager for embeddings
  • surreal_commands: Async job submission (vectorization, insights)
  • loguru: Logging

Quirks & Gotchas

  • Polymorphic resolution: ObjectModel.get() fails if subclass not imported (search subclasses list)
  • RecordModel singleton: new returns existing instance; call clear_instance() in tests
  • Source.command field: Stored as RecordID; auto-parsed from strings via field_validator
  • Text truncation: Note.get_context(short) hardcodes 100-char limit
  • Embedding async: Only Note and SourceInsight embed on save; Source too large (uses async job)
  • Relationship strings: Must match SurrealDB schema (reference, artifact, refers_to)

How to Add New Model

  1. Inherit from ObjectModel with table_name ClassVar
  2. Define Pydantic fields with validators
  3. Override needs_embedding() if searchable
  4. Add custom methods for domain logic (get_X, add_to_Y)
  5. Implement _prepare_save_data() if custom serialization needed

Usage

notebook = Notebook(name="Research", description="My project")
await notebook.save()

obj = await ObjectModel.get("notebook:123")  # Polymorphic fetch

# Search
await text_search("quantum", results=5)
await vector_search("quantum computing", results=10, minimum_score=0.3)