plandag

import "github.com/jbcom/radioactive-ralph/internal/plandag"

Package plandag owns the SQLite schema, DAG operations, and sync protocol for user-facing plans.

The schema is embedded under schema/*.sql and applied in lexical order by Migrate. The schema_version is tracked in a dedicated table so future versions can detect skew and refuse to open a DB newer than the running binary supports.

Index

Variables

ErrDuplicateSlug is returned when a plan with (repo_path, slug) already exists. Callers either pick a new slug or update.

var ErrDuplicateSlug = errors.New("plandag: plan with slug already exists in this repo")

ErrNoReadyTask indicates ClaimNextReady found nothing claimable.

var ErrNoReadyTask = errors.New("plandag: no ready task")

func Migrate

func Migrate(db *sql.DB) error

Migrate brings db up to currentSchemaVersion by applying any pending *.up.sql migrations in lexical order.

Migrations are idempotent per-version via SQLite’s user_version PRAGMA. Each migration runs inside a transaction.

type CreatePlanOpts

CreatePlanOpts configures plan creation. The caller supplies slug + title; ID is generated via Store.uuid().

type CreatePlanOpts struct {
    Slug           string
    Title          string
    RepoPath       string
    RepoRemote     string
    PrimaryVariant string
    Confidence     int
    TagsJSON       string
}

type CreateTaskOpts

CreateTaskOpts configures task creation.

type CreateTaskOpts struct {
    PlanID          string
    ID              string // stable slug (operator-chosen or fixit-emitted)
    Description     string
    Complexity      string
    Effort          string
    VariantHint     string
    ContextBoundary bool
    AcceptanceJSON  string
    ParentTaskID    string
}

type Options

Options configures Open.

type Options struct {
    // DSN is a modernc.org/sqlite DSN, e.g.
    // "file:/path/to/plans.db?_pragma=foreign_keys(1)&_pragma=journal_mode(WAL)"
    DSN string

    // Clock is swappable for tests. Nil defaults to clockwork.NewRealClock().
    Clock clockwork.Clock

    // UUID is swappable for tests. Nil defaults to uuid.NewV7().
    UUID func() string
}

type Plan

Plan is the durable row.

type Plan struct {
    ID             string
    Slug           string
    Title          string
    RepoPath       string
    RepoRemote     string
    Status         PlanStatus
    PrimaryVariant string
    Confidence     int
    CreatedAt      time.Time
    UpdatedAt      time.Time
    LastSessionAt  sql.NullTime
    TagsJSON       string // JSON array
}

type PlanStatus

PlanStatus enumerates the lifecycle states a plan can be in.

type PlanStatus string

Plan lifecycle states.

const (
    PlanStatusDraft         PlanStatus = "draft"
    PlanStatusActive        PlanStatus = "active"
    PlanStatusPaused        PlanStatus = "paused"
    PlanStatusDone          PlanStatus = "done"
    PlanStatusFailedPartial PlanStatus = "failed_partial"
    PlanStatusArchived      PlanStatus = "archived"
    PlanStatusAbandoned     PlanStatus = "abandoned"
)

type SessionMode

SessionMode identifies portable-stdio vs durable-HTTP modes.

type SessionMode string

Session execution modes.

const (
    SessionModePortable SessionMode = "portable"
    SessionModeDurable  SessionMode = "durable"
)

type SessionOpts

SessionOpts configures CreateSession.

type SessionOpts struct {
    ID           string // optional; caller may pass an existing UUID. Empty → auto.
    Mode         SessionMode
    Transport    SessionTransport
    PID          int
    PIDStartTime string
    Host         string
}

type SessionTransport

SessionTransport identifies stdio / http / sse transports.

type SessionTransport string

Session transport types.

const (
    SessionTransportStdio SessionTransport = "stdio"
    SessionTransportHTTP  SessionTransport = "http"
    SessionTransportSSE   SessionTransport = "sse"
)

type SessionVariantOpts

SessionVariantOpts configures CreateSessionVariant.

type SessionVariantOpts struct {
    SessionID           string
    VariantName         string
    SubprocessPID       int
    SubprocessStartTime string
}

type Store

Store is the plandag handle. It wraps a *sql.DB plus deterministic clock + UUID provider (test-swappable).

type Store struct {
    // contains filtered or unexported fields
}

func Open

func Open(ctx context.Context, opts Options) (*Store, error)

Open returns a migrated, ready-to-use Store.

func (*Store) AddDep

func (s *Store) AddDep(ctx context.Context, planID, taskID, dependsOn string) error

AddDep wires task → depends_on for the same plan. Rejects cycles.

func (*Store) AttachPlan

func (s *Store) AttachPlan(ctx context.Context, sessionID, planID string) error

AttachPlan records which session is watching which plan. Used by `ralph status` to enumerate active supervision.

func (*Store) ClaimNextReady

func (s *Store) ClaimNextReady(ctx context.Context, planID, variant, sessionID, sessionVariantID string) (*Task, error)

ClaimNextReady is the atomic “claim the next ready task for this variant” operation. Returns the claimed task id, or ErrNoReadyTask if none. Uses BEGIN IMMEDIATE + UPDATE … RETURNING so two parallel ralphs never claim the same task.

func (*Store) Close

func (s *Store) Close() error

Close releases DB resources.

func (*Store) CloseSession

func (s *Store) CloseSession(ctx context.Context, sessionID string) error

CloseSession removes a session row. FK cascades clear its variants and attach rows.

func (*Store) CreatePlan

func (s *Store) CreatePlan(ctx context.Context, o CreatePlanOpts) (string, error)

CreatePlan inserts a fresh plan in draft status and returns the newly generated UUID v7 id.

func (*Store) CreateSession

func (s *Store) CreateSession(ctx context.Context, o SessionOpts) (string, error)

CreateSession inserts a session row. Returns the session id. Called by the MCP server on startup; the session’s lifetime is the lifetime of one server process.

func (*Store) CreateSessionVariant

func (s *Store) CreateSessionVariant(ctx context.Context, o SessionVariantOpts) (string, error)

CreateSessionVariant registers a newly-spawned ralph subprocess against a session. Returns the variant row id.

func (*Store) CreateTask

func (s *Store) CreateTask(ctx context.Context, o CreateTaskOpts) error

CreateTask inserts a pending task. Callers wire dependencies via AddDep.

func (*Store) DB

func (s *Store) DB() *sql.DB

DB returns the underlying *sql.DB for callers that need raw access. Business-logic callers should use Store’s typed methods instead.

func (*Store) GetPlan

func (s *Store) GetPlan(ctx context.Context, id string) (*Plan, error)

GetPlan loads a plan by id.

func (*Store) GetTask

func (s *Store) GetTask(ctx context.Context, planID, id string) (*Task, error)

GetTask loads one task by (plan_id, id).

func (*Store) HeartbeatSession

func (s *Store) HeartbeatSession(ctx context.Context, sessionID string) error

HeartbeatSession refreshes last_heartbeat for a session. Called periodically by the server. Reaper uses staleness to detect dead sessions.

func (*Store) ListPlans

func (s *Store) ListPlans(ctx context.Context, statuses []PlanStatus) ([]Plan, error)

ListPlans returns plans matching filter. Empty filter → active + paused.

func (*Store) MarkDone

func (s *Store) MarkDone(ctx context.Context, planID, taskID, sessionID string, evidenceJSON string) ([]Task, error)

MarkDone transitions a running task to done, logs the event, and returns the set of newly-ready downstream tasks.

func (*Store) MarkFailed

func (s *Store) MarkFailed(ctx context.Context, planID, taskID, sessionID, reason string, maxRetries int) (retried bool, err error)

MarkFailed transitions a running task to failed or retries.

func (*Store) Ready

func (s *Store) Ready(ctx context.Context, planID string) ([]Task, error)

Ready returns tasks that are ready to run — every dependency is `done` (or `skipped`). Result is ordered by created_at for stable test output.

func (*Store) SetPlanStatus

func (s *Store) SetPlanStatus(ctx context.Context, id string, status PlanStatus) error

SetPlanStatus updates the plan’s status column.

type Task

Task is a DAG node.

type Task struct {
    ID                 string
    PlanID             string
    Description        string
    Complexity         string
    Effort             string
    VariantHint        string
    ContextBoundary    bool
    AcceptanceJSON     string
    Status             TaskStatus
    AssignedVariant    string
    ClaimedBySession   string
    ClaimedByVariantID string
    RetryCount         int
    ReclaimCount       int
    ParentTaskID       string
    CreatedAt          time.Time
    UpdatedAt          time.Time
}

type TaskStatus

TaskStatus enumerates valid task lifecycle states.

type TaskStatus string

Task lifecycle states.

const (
    TaskStatusPending              TaskStatus = "pending"
    TaskStatusReady                TaskStatus = "ready"
    TaskStatusReadyPendingApproval TaskStatus = "ready_pending_approval"
    TaskStatusRunning              TaskStatus = "running"
    TaskStatusDone                 TaskStatus = "done"
    TaskStatusFailed               TaskStatus = "failed"
    TaskStatusSkipped              TaskStatus = "skipped"
    TaskStatusDecomposed           TaskStatus = "decomposed"
)

Generated by gomarkdoc