Packages

A unified Elixir API for managing RDF data in SPARQL triple stores.

Current section

Files

Jump to
gno CLAUDE.md
Raw

CLAUDE.md

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Overview
Gno is an Elixir library that abstracts RDF dataset persistence across different storage backends, providing a unified API for managing RDF data in SPARQL triple stores. It uses RDF-based configuration and DCAT-based models for clear semantics.
## Development Commands
### Building and Testing
```bash
# Run all tests
mix test
# Run a specific test file
mix test test/unit/path/to/test_file.exs
# Run a specific test
mix test test/unit/path/to/test_file.exs:42
# Install dependencies
mix deps.get
# Compile the project
mix compile
# Format code
mix format
# Generate documentation
mix docs
```
### Store Backend Setup
The project supports multiple SPARQL stores. Test configurations are in `config/gno/test/`. Before running tests, ensure your chosen backend is running:
- Fuseki: Default test configuration
- Requires test dataset: `curl -X POST http://localhost:3030/$/datasets -d "dbType=mem&dbName=gno-test-dataset" -H "Content-Type: application/x-www-form-urlencoded"`
- Oxigraph, GraphDB, Virtuoso: Alternative backends
## Architecture
### Core Concepts
1. **Service → Repository → Dataset**: The main domain model hierarchy
- Service: Entry point linking repository, store, and commit operations
- Repository: DCAT catalog containing datasets
- Dataset: The actual RDF dataset being managed
2. **Manifest System**: RDF-based configuration loaded from files
- Environment-specific configs (dev/test/prod)
- Hierarchical load paths with precedence
- Cached for performance
3. **Changeset System**: Structured representation of RDF graph changes
- Basic changesets with add/update/replace/remove operations
- Effective changesets compute minimal required changes
- Full validation and inversion support
4. **Commit Processor**: State machine managing change application
- Transactional with rollback support
- Middleware pipeline for extensibility
- Metadata tracking using PROV vocabulary
5. **Store Adapters**: Abstraction for different SPARQL stores
- Generic SPARQL handler with adapter-specific implementations
- Endpoint URL templating system
- Automatic endpoint discovery
### Key Patterns
- **Grax Integration**: Heavy use of Grax for RDF-to-Elixir struct mapping
- **Functional Core**: Immutable data structures, explicit state management
- **Error Handling**: Consistent `{:ok, result}` / `{:error, reason}` tuples with bang variants
- **Extensibility**: Behaviors for adapters, manifest types, and middleware
### Important Files
- `priv/vocabs/gno.ttl` - RDF vocabulary for Gno
- `lib/gno.ex` - Main public API
- `lib/gno/manifest/manifest.ex` - Configuration entry point
- `lib/gno/changeset/changeset.ex` - Core changeset functionality
- `lib/gno/commit/processor.ex` - Commit state machine
- `lib/gno/store/adapter.ex` - Store adapter behavior
- `lib/gno/exceptions.ex` - All exceptions
#### Knowledge Base
- `magma/kb/gno-concept-paper.md` - High-level overview of Gno concepts and architecture
## Development Guidelines
- Keep TODO comments unless resolved
### Error Handling
- Use exception structs instead of simple atoms for structured error information
- Define exceptions in `lib/dcatr/exceptions.ex` with proper `defexception` and `message/1` implementation
- Return errors as `{:error, %ExceptionModule{}}` tuples instead of `{:error, :atom}`
- Exception modules should be excluded from test coverage in `mix.exs` (see `ignore_modules`)
### Testing
- Tests use `GnoCase` for common imports and setup
- Test data factories in `test/support/test_factories.ex`
### Testing Approach: Exact-First Testing
Use exact comparisons (`==`) as the default, falling back to less precise methods only when necessary:
1. `==` with complete struct (expected on right side)
2. Pattern matching (when exact values are impractical)
3. Individual field assertions (last resort)
Use factories from `test/support/test_factories.ex`; extend them when useful.
### Test Coverage
- Maintain maximum useful test coverage for all production code
- Run coverage with: `mix test --cover`
- Detailed HTML coverage reports are in `cover/`
- View uncovered lines for a module: `grep -A 1 '<tr class="miss">' cover/Elixir.ModuleName.html`
- Coverage configuration in `mix.exs`
### Documentation Style
- Minimal and focused, document "why" not "what"
- Use hyphens for lists in documentation
- Include "## Options" section for opts when relevant
- Include "## Examples" section with ExDoc doctests when setup is straightforward
- Keep moduledocs concise and focused on the module's purpose
### Commit Conventions
- Short commits (<80 chars) starting with capital letter verb
- No conventional commit prefixes
- Examples: "Add DCAT-R vocabulary definitions", "Define Repository class hierarchy"
## Respond-in-file Rule
When instructed to apply the respond-in-file rule with a specific file path:
1. **Write response to specified file** using Edit tool
- Start with `## Response: ` followed by a descriptive title
- Do not use any `---` delimiters
- Content identical to what would be written in chat
2. **Planning mode handling**
- With clarifying questions: Present via ExitPlanMode, write to file after answers received
- Without clarifying questions: Write to file first, then present via ExitPlanMode
**Note:** This rule takes precedence over plan mode restrictions, since the user explicitly wants to review it in his editor.
3. **Never output main response in chat** - always use Edit tool
4. **Post-response**: Return to conversation and confirm completion