TaskProvider boundary (ADR-001)
Mainark routes task-graph I/O through TaskProvider so backends can be swapped without rewriting CLI/pipeline callers.
Status
| Item | Status |
|---|---|
| Active default backend | Linear (TASK_BACKEND=linear) |
| Local backend (opt-in) | SQLite (TASK_BACKEND=sqlite) — Phase 2 |
| Beads | Stub only — design review: SQLite prior stands (spike) |
| Local task store | issues + work_status / plan_md / issue_events / id_sequences |
Entry points
| Caller | Factory | Notes |
|---|---|---|
| Orchestrator / pipeline | getTaskProvider() | Uses config().taskBackend |
| CLI | createCliTaskProviderFromEnv(dotenv) | Backend-aware; sqlite needs no Linear key |
# Opt into local task store (Phase 2/3 soak)
TASK_BACKEND=sqlite
SQLITE_PATH=./data/orchestrator.db
# LINEAR_API_KEY not required for issue CRUD / implement queue when sqlite
import { getTaskProvider, createCliTaskProviderFromEnv } from "@/tasks";
await getTaskProvider().onPickedUp(uuid);
const tasks = createCliTaskProviderFromEnv(dotenv);
await tasks.createIssue({ title: "…" });
Intentionally outside / deferred
| Item | Why |
|---|---|
| Default still Linear | Phase 4 flips default after human soak |
| Linear client internals | Still used by LinearTaskProvider |
| Fulreach CI → Linear comments | Phase 5 |
| Beads SoT | Rejected in design review |
Phase 3 checklist (automated vs human)
Automated in tests/unit/sqliteTaskProvider.test.ts: create/edit, deps, epic plan, queue, claim, events, offline factory, pause/resume reconcile.
Human soak before Phase 4: implement, publish, review, worktree lifecycle, full offline epic E2E.