Stoneforge is built as a multi-agent orchestration platform with two main architectural layers: Quarry (the data platform) and Smithy (the orchestrator).
Architectural Layers
┌─────────────────────────────────────────────────────────┐
│ @stoneforge/smithy │
│ Agent orchestration, spawning, sessions, prompts │
└────────────────────────────┬────────────────────────────┘
│
depends on
│
▼
┌─────────────────────────────────────────────────────────┐
│ @stoneforge/quarry │
│ QuarryAPI, services, sync, CLI, identity │
└────────────────────────────┬────────────────────────────┘
│
┌───────────────────┼────────────────────┐
│ │ │
┌────────▼────────┐ ┌───────▼───────┐ ┌────────▼────────┐
│ @stoneforge/ │ │ @stoneforge/ │ │ SQLite │
│ core │ │ storage │ │ (.stoneforge/) │
└─────────────────┘ └───────────────┘ └─────────────────┘
Smithy: The Orchestrator
Smithi manages the lifecycle and coordination of AI coding agents:
Agent Registry : Tracks registered agents (Directors, Workers, Stewards)
Session Manager : Manages agent process spawning and lifecycle
Dispatch Daemon : Assigns tasks and routes messages
Spawner Service : Handles provider-agnostic process spawning
Git Worktree Manager : Isolates agent work in separate git worktrees
Quarry provides event-sourced task and data management:
QuarryAPI : CRUD operations for all element types
Dependency Service : Manages blocking and associative relationships
Inbox Service : Message routing and triage
Sync Service : JSONL import/export with merge conflict resolution
Priority Service : Calculates effective task priorities
Package Dependency Graph
Stoneforge is organized as a monorepo with strict dependency boundaries:
Core Package
Storage Package
Quarry Package
Smithy Package
@stoneforge/core - Foundation types with no dependencies
Element types (Task, Document, Entity, etc.)
Dependency types and blocking semantics
Validation functions and type guards
ID generation utilities
Error codes and error classes
Import rule: Cannot import from any other package@stoneforge/storage - SQLite abstraction layer
Cross-runtime SQLite backends (Bun, Node, Browser)
Schema management and migrations
Transaction support
Dirty tracking for incremental sync
Import rule: Can only import from @stoneforge/core@stoneforge/quarry - Business logic and API
QuarryAPI for element CRUD
Service layer (dependency, inbox, priority, etc.)
Sync engine (JSONL import/export)
CLI commands
Identity and signing
Import rule: Can import from @stoneforge/core and @stoneforge/storage@stoneforge/smithy - Agent orchestration
Agent registry and lifecycle
Dispatch daemon with polling loops
Session spawning and management
Git worktree isolation
Role-based prompt system
Import rule: Can import from all lower layers
Dual Storage Model
Stoneforge uses a sophisticated dual-storage architecture that balances performance with git-friendliness:
┌─────────────────────────────────────────────────────────┐
│ SQLite │
│ • Fast queries with indexes │
│ • Full-text search (FTS5) │
│ • Materialized views (blocked cache) │
│ • Ephemeral - can be rebuilt from JSONL │
└────────────────────────────┬────────────────────────────┘
│ sync
┌────────────────────────────▼────────────────────────────┐
│ JSONL │
│ • Git-tracked, append-only │
│ • Source of truth for all durable data │
│ • Human-readable, diff-friendly │
│ • Mergeable across branches │
└─────────────────────────────────────────────────────────┘
Key Principle: SQLite is the cache , JSONL is the source of truth .
Write Path
When you create or update an element:
Write to SQLite - Changes are immediately available for queries
Mark as dirty - Element is flagged for export
Export to JSONL - Dirty elements are appended to .stoneforge/sync/elements.jsonl
This approach provides both fast local queries and durable, git-tracked storage.
Read Path
All queries go directly to SQLite:
// Fast indexed queries
const readyTasks = await api . ready ();
const blockedTasks = await api . blocked ();
const task = await api . get ( taskId );
SQLite provides:
Indexed lookups by ID, status, assignee
Full-text search via FTS5
Materialized blocked status cache
Complex JOIN queries for relationships
Sync and Merge
When branches diverge and merge:
// Import JSONL from another branch
await syncService . importFromJsonl ( '.stoneforge/sync/elements.jsonl' );
// Merge conflicts are resolved automatically:
// - Newer timestamp wins (last-write-wins)
// - closed/tombstone status always wins
// - Content hash detects conflicting edits
This enables multiple agents to work in parallel branches and merge cleanly.
Monorepo Structure
packages/
├── core/ # Foundation types, no dependencies
├── storage/ # SQLite backends (Bun, Node, Browser)
├── quarry/ # API, services, sync, CLI
├── smithy/ # Agent orchestration
├── ui/ # React components and hooks
└── shared-routes/ # HTTP route factories
apps/
├── quarry-server/ # Platform HTTP + WebSocket (port 3456)
├── quarry-web/ # Platform React SPA (port 5173)
├── smithy-server/ # Orchestrator API (port 3457)
└── smithy-web/ # Orchestrator dashboard (port 5174)
.stoneforge/
├── stoneforge.db # SQLite cache
├── sync/
│ ├── elements.jsonl # Element source of truth
│ └── dependencies.jsonl # Dependency relationships
├── config.yaml # Project configuration
└── prompts/ # Custom agent prompts
├── director.md
├── worker.md
└── steward-merge.md
Data Flow Patterns
Task Creation and Assignment
Dependency Blocking
Configuration Precedence
Stoneforge uses a layered configuration system:
CLI Flags
Highest priority: --actor, --db, --provider sf agent start worker-1 --provider opencode
Environment Variables
Second priority: STONEFORGE_* variables export STONEFORGE_PROVIDER = opencode
sf agent start worker-1
Config File
Third priority: .stoneforge/config.yaml provider : opencode
identity :
mode : cryptographic
Built-in Defaults
Lowest priority: hardcoded defaults
Provider: claude-code
Identity mode: soft
Merge strategy: squash
Cross-Runtime Support
Stoneforge runs on multiple JavaScript runtimes:
Bun Native SQLite support via bun:sqlite Fastest performance
Node.js better-sqlite3 backendProduction ready
Browser WASM-based sql.js Client-side capable
Edge Runtimes WebAssembly fallback Deploy anywhere
Next Steps
Agent Roles Learn about Director, Worker, and Steward roles
Task Management Understand task lifecycle and status transitions
Storage Model Deep dive into SQLite + JSONL dual storage
Orchestration Loop See how the dispatch daemon coordinates agents