The QuarryAPI provides the foundational CRUD operations for all Stoneforge elements. It connects the type system to the SQLite storage layer and implements filtering, pagination, hydration, and FTS search.
Overview
The QuarryAPI is implemented in packages/quarry/src/api/quarry-api.ts and provides:
CRUD operations (create, read, update, delete)
Filtering and pagination
Hydration (expanding references)
Full-text search
Dependency management
Event tracking
Import/export (JSONL)
Installation
import { QuarryAPIImpl } from '@stoneforge/quarry' ;
import { createStorageBackend } from '@stoneforge/storage' ;
const backend = await createStorageBackend ({ dbPath: '.stoneforge/stoneforge.db' });
const api = new QuarryAPIImpl ( backend );
Core CRUD Operations
get()
Retrieves a single element by ID.
Options for expanding references Include blocking elements
Expand message content documents
The element or null if not found
// Simple get
const task = await api . get < Task >( taskId );
// Get with hydration
const hydratedTask = await api . get < HydratedTask >( taskId , {
hydrate: { dependencies: true , blockers: true }
});
console . log ( hydratedTask . blockers ); // Array of blocking tasks
list()
Lists elements matching filter criteria (unpaginated).
type
ElementType | ElementType[]
Filter by element type(s)
Elements must have ALL these tags
Elements must have ANY of these tags
Include tombstoned elements (default: false)
Array of matching elements
// Get all open tasks
const openTasks = await api . list < Task >({
type: 'task' ,
status: 'open' ,
});
// Get all tasks with 'bug' tag
const bugs = await api . list < Task >({
type: 'task' ,
tags: [ 'bug' ],
});
listPaginated()
Lists elements with pagination support.
Same as list() plus pagination fields: Max items per page (default: 50, max: 1000)
Number of items to skip (default: 0)
Field to sort by (default: ‘created_at’)
Sort direction (default: ‘desc’)
const result = await api . listPaginated < Task >({
type: 'task' ,
status: [ 'open' , 'in_progress' ],
orderBy: 'priority' ,
orderDir: 'desc' ,
limit: 20 ,
offset: 0 ,
});
console . log ( `Page 1 of ${ Math . ceil ( result . total / result . limit ) } ` );
console . log ( `Showing ${ result . items . length } of ${ result . total } tasks` );
create()
Creates a new element.
input
Record<string, unknown> & { type: ElementType; createdBy: EntityId }
required
Element data (should be created using factory functions like createTask, createDocument, etc.)
import { createTask , createDocument , ContentType } from '@stoneforge/core' ;
// Create a task
const taskData = await createTask ({
title: 'Implement feature X' ,
status: 'open' ,
priority: 3 ,
createdBy: operatorId ,
tags: [ 'feature' ],
});
const task = await api . create < Task >( taskData );
// Create a document
const docData = await createDocument ({
contentType: ContentType . MARKDOWN ,
content: '# Feature X \n\n Implementation notes...' ,
createdBy: operatorId ,
});
const doc = await api . create < Document >( docData );
update()
Updates an existing element.
Fields to update (partial)
Entity performing the update (for events)
For optimistic concurrency control
// Update task status
const updated = await api . update < Task >( taskId , {
status: 'in_progress' ,
assignee: workerId ,
});
// Update with optimistic locking
const task = await api . get < Task >( taskId );
const updated = await api . update < Task >( taskId ,
{ priority: 5 },
{ expectedUpdatedAt: task . updatedAt }
);
delete() / softDelete()
Deletes an element (soft delete creates tombstone).
Entity performing deletion (for events)
Whether to permanently delete (default: false)
True if element was deleted
// Soft delete (creates tombstone)
await api . delete ( taskId );
// Hard delete (permanent)
await api . delete ( taskId , { hard: true });
// Soft delete with actor
await api . softDelete ( taskId , operatorId );
Task-Specific Methods
getTasksForPlan()
Retrieves all tasks belonging to a plan.
Array of tasks in the plan
const tasks = await api . getTasksForPlan ( planId , {
hydrate: { dependencies: true }
});
getReadyTasks()
Retrieves tasks that are ready to work on (open, not blocked).
const readyTasks = await api . getReadyTasks ();
getBlockedTasks()
Retrieves tasks that are blocked by dependencies.
Array of blocked tasks with blocker info
const blocked = await api . getBlockedTasks ();
blocked . forEach (({ task , blockers }) => {
console . log ( ` ${ task . title } is blocked by:` );
blockers . forEach ( b => console . log ( ` - ${ b . reason } ` ));
});
Dependency Management
addDependency()
Adds a dependency between elements.
Dependency type: ‘blocks’, ‘awaits’, ‘parent-child’, ‘relates-to’, ‘mentions’, ‘references’, ‘replies-to’
Entity creating the dependency
// Task B blocks Task A (A cannot start until B is done)
await api . addDependency ({
blockedId: taskAId ,
blockerId: taskBId ,
type: 'blocks' ,
createdBy: operatorId ,
});
removeDependency()
Removes a dependency.
Entity performing removal
True if dependency was removed
await api . removeDependency ( taskAId , taskBId , 'blocks' , operatorId );
getDependencies()
Gets dependencies from an element.
const blockingDeps = await api . getDependencies ( taskId , 'blocks' );
getDependents()
Gets elements that depend on an element (reverse lookup).
Array of dependent relationships
const dependents = await api . getDependents ( taskId , 'blocks' );
Full-Text Search
searchDocuments()
Searches documents using FTS5 full-text search.
Max results (default: 20)
contentType
ContentType | ContentType[]
Filter by content type
Minimum relevance score (0-1)
Use adaptive result limiting (default: true)
Whether more results exist
const results = await api . searchDocuments ( 'authentication' , {
contentType: ContentType . MARKDOWN ,
tags: [ 'docs' ],
limit: 10 ,
});
results . documents . forEach ( doc => {
console . log ( ` ${ doc . title } : ${ doc . content . substring ( 0 , 100 ) } ...` );
});
Import/Export
exportElements()
Exports elements to JSONL format.
Full export (true) or incremental (false)
Include ephemeral workflows and tasks
Elements filename (default: ‘elements.jsonl’)
Dependencies filename (default: ‘dependencies.jsonl’)
const result = await api . exportElements ({
outputDir: '.stoneforge' ,
full: true ,
includeEphemeral: false ,
});
console . log ( `Exported ${ result . elementsExported } elements` );
importElements()
Imports elements from JSONL format.
Preview changes without applying
Force overwrite local changes
Elements filename (default: ‘elements.jsonl’)
Dependencies filename (default: ‘dependencies.jsonl’)
Elements skipped (no changes)
const result = await api . importElements ({
inputDir: '.stoneforge' ,
dryRun: true ,
});
console . log ( `Would import ${ result . elementsImported } elements` );
if ( result . conflicts . length > 0 ) {
console . log ( `Found ${ result . conflicts . length } conflicts` );
}