Skip to main content

@stoneforge/quarry

The main programmatic interface to Stoneforge. Wraps @stoneforge/storage with an event-sourced domain model, dependency management, full-text search, and Git-friendly JSONL sync.
Event-Sourced: Every mutation produces an immutable event, giving you a full audit trail and point-in-time reconstruction.

Installation

npm install @stoneforge/quarry
Includes @stoneforge/core and @stoneforge/storage as dependencies.

Quick Start

import { createStorage, initializeSchema } from '@stoneforge/storage';
import { createQuarryAPI } from '@stoneforge/quarry/api';
import type { Task } from '@stoneforge/core';

// Create storage backend
const storage = createStorage({ path: '.stoneforge/db.sqlite' });
initializeSchema(storage);

// Create API
const api = createQuarryAPI(storage);

// Create a task
const task = await api.create<Task>({
  type: 'task',
  title: 'Implement user authentication',
  priority: 2,
  createdBy: 'el-operator',
});

console.log(`Created task ${task.id}`);

QuarryAPI

Create an instance with createQuarryAPI(backend) where backend is a StorageBackend from @stoneforge/storage.

CRUD Operations

import type { Task, Entity, Document } from '@stoneforge/core';

// Create a task
const task = await api.create<Task>({
  type: 'task',
  title: 'Build API',
  priority: 3,
  taskType: 'feature',
  createdBy: operatorId,
});

// Create an entity
const entity = await api.create<Entity>({
  type: 'entity',
  name: 'alice',
  role: 'human',
  email: 'alice@example.com',
  createdBy: operatorId,
});

// Create a document
const doc = await api.create<Document>({
  type: 'document',
  title: 'API Reference',
  content: '# REST API\n\n...',
  contentType: 'text/markdown',
  createdBy: operatorId,
});

Task Queries

// Open/in-progress tasks that are not blocked
const ready = await api.ready({
  priority: { gte: 2 },
  tags: { includes: 'backend' },
});

Dependencies

// Task B blocks Task A (A depends on B)
await api.addDependency({
  blockedId: taskA.id,
  blockerId: taskB.id,
  type: 'blocks',
});

// Non-blocking relationship
await api.addDependency({
  blockedId: taskA.id,
  blockerId: taskB.id,
  type: 'relates-to',
});
// Search across all elements
const results = await api.search('authentication flow');

// Search with filter
const taskResults = await api.search('authentication', {
  type: 'task',
  status: 'open',
});

Plans

import type { Plan } from '@stoneforge/core';

const plan = await api.create<Plan>({
  type: 'plan',
  title: 'Q1 2026 Features',
  status: 'active',
  createdBy: directorId,
});

Channels & Messages

import type { Channel } from '@stoneforge/core';

const channel = await api.create<Channel>({
  type: 'channel',
  name: 'team-eng',
  channelType: 'group',
  members: [aliceId, bobId],
  visibility: 'public',
  createdBy: operatorId,
});

Workflows

import type { Workflow } from '@stoneforge/core';

const workflow = await api.create<Workflow>({
  type: 'workflow',
  title: 'Deploy to Production',
  status: 'pending',
  playbookId: playbookId,
  ephemeral: false,
  createdBy: directorId,
});

History & Events

// Get all events for an element
const events = await api.getEvents(taskId);

for (const event of events) {
  console.log(`${event.eventType} at ${event.timestamp} by ${event.actor}`);
}

Entity Management

const alice = await api.lookupEntityByName('alice');

Services

Lower-level services for specialized operations.

DependencyService

import { DependencyService } from '@stoneforge/quarry/services';

const depService = new DependencyService(storage);

const cycle = depService.detectCycle(taskA.id, taskB.id, 'blocks');
if (cycle) {
  console.error(`Cycle detected: ${cycle.join(' -> ')}`);
}

InboxService

import { createInboxService } from '@stoneforge/quarry';

const inbox = createInboxService(storage, api);

// Add inbox item
await inbox.addItem({
  entityId: recipientId,
  sourceType: 'direct_message',
  sourceElementId: messageId,
  status: 'unread',
  createdBy: senderId,
});

// Get unread items
const unread = await inbox.getUnread(entityId);
console.log(`${unread.length} unread items`);

// Mark as read
await inbox.markAsRead(itemId, entityId);

PriorityService

import { PriorityService } from '@stoneforge/quarry/services';

const priorityService = new PriorityService(api);

// Calculate effective priority (considers plan priority)
const effectivePriority = await priorityService.getEffectivePriority(taskId);

Sync System

Export to and import from Git-tracked JSONL files.
import { createSyncService } from '@stoneforge/quarry/sync';

const sync = createSyncService(storage);

// Export all elements
await sync.export({ outputDir: '.stoneforge/sync' });

// Export only dirty elements
await sync.export({
  outputDir: '.stoneforge/sync',
  incrementalOnly: true,
});

Configuration

import { loadConfig, getValue, setValue } from '@stoneforge/quarry/config';

const config = loadConfig();
const actor = getValue('actor');

CLI

The package ships the sf CLI.
sf task create --title "Build API" --priority 3
sf task list --status open
sf task ready
sf task blocked
sf task close <id> --reason "Completed"

Entry Points

import { createQuarryAPI } from '@stoneforge/quarry';
// Re-exports API, services, sync, config

API Reference

Filter Types

interface ElementFilter {
  type?: ElementType | ElementType[];
  status?: string | { in: string[] };
  priority?: number | { gte?: number; lte?: number };
  tags?: { includes: string } | { excludes: string };
  createdBy?: EntityId;
  createdAfter?: string;
  createdBefore?: string;
  limit?: number;
  offset?: number;
}

Options Types

interface GetOptions {
  includeHistory?: boolean;
}

interface UpdateOptions {
  actor?: EntityId;
}

interface DeleteOptions {
  hard?: boolean;
  actor?: EntityId;
  reason?: string;
}
Event Sourcing: All mutations are logged as immutable events. You can reconstruct any element’s state at any point in time.

Next Steps

Smithy Orchestration

Add AI agent orchestration

UI Components

Build a web dashboard

Build docs developers (and LLMs) love