store

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 21, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

ABOUTME: Append-only JSONL event log for durable event storage. ABOUTME: Provides crash-safe append, sequential replay, and repair for truncated files.

ABOUTME: High-level storage manager for the mammoth-specd daemon's filesystem layout. ABOUTME: Handles directory creation, spec discovery, recovery orchestration, and export writing.

ABOUTME: Crash recovery and self-healing for spec state reconstruction. ABOUTME: Combines snapshots, JSONL repair, event replay, and SQLite integrity checks.

ABOUTME: Atomic snapshot save and load for SpecState persistence. ABOUTME: Writes snapshots with atomic rename for crash safety and loads the latest by event ID.

ABOUTME: SQLite-backed index for fast spec and card queries without replaying events. ABOUTME: Provides upsert, delete, list, and rebuild operations synchronized with the event log.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RecoverSpec

func RecoverSpec(specDir string) (*core.SpecState, uint64, error)

RecoverSpec recovers a spec's state from its storage directory.

Recovery sequence:

  1. Try to load the latest snapshot
  2. Repair the JSONL event log (truncate partial last line)
  3. Replay all events from the JSONL
  4. Apply events that are newer than the snapshot
  5. Open SQLite index and check integrity (compare last_event_id)
  6. If mismatch or empty: rebuild SQLite from all events
  7. Return recovered state and last_event_id

func RepairJsonl

func RepairJsonl(path string) (int, error)

RepairJsonl repairs a potentially corrupted JSONL file by keeping only complete, parseable lines and truncating any partial trailing data. Uses atomic temp-file + fsync + rename to prevent data loss on crash. Returns the count of valid events retained.

func ReplayJsonl

func ReplayJsonl(path string) ([]core.Event, error)

ReplayJsonl reads all events from a JSONL file, returning them in order. Empty lines are skipped. Returns an empty slice for empty files.

func SaveSnapshot

func SaveSnapshot(dir string, data *SnapshotData) error

SaveSnapshot saves a snapshot to disk using atomic write (write to .tmp, fsync, rename). Creates the target directory if it does not exist.

func WriteExports

func WriteExports(specDir string, state *core.SpecState) error

WriteExports writes export files to the exports/ subdirectory. This is a placeholder that creates the exports directory and writes a basic markdown export. Full export support (YAML, DOT) will be added when the export module is ported.

Types

type CardRow

type CardRow struct {
	CardID    string
	SpecID    string
	CardType  string
	Title     string
	Body      *string
	Lane      string
	SortOrder float64
	CreatedBy string
	UpdatedAt string
}

CardRow is a row from the cards table for list query results.

type JsonlLog

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

JsonlLog is an append-only JSONL event log backed by a file. Each line is a single JSON-serialized Event followed by a newline.

func OpenJsonl

func OpenJsonl(path string) (*JsonlLog, error)

OpenJsonl opens (or creates) a JSONL log file at the given path. Creates parent directories if they do not exist. The file is opened in append mode.

func (*JsonlLog) Append

func (l *JsonlLog) Append(event *core.Event) error

Append serializes a single event as one JSON line, writes it with a trailing newline, and fsyncs to disk.

func (*JsonlLog) Close

func (l *JsonlLog) Close() error

Close closes the underlying file.

func (*JsonlLog) Path

func (l *JsonlLog) Path() string

Path returns the path to the underlying JSONL file.

type RecoveredSpec

type RecoveredSpec struct {
	SpecID ulid.ULID
	State  *core.SpecState
}

RecoveredSpec pairs a recovered spec state with its ULID.

type SnapshotData

type SnapshotData struct {
	State         *core.SpecState            `json:"-"` // Custom marshal/unmarshal
	LastEventID   uint64                     `json:"last_event_id"`
	AgentContexts map[string]json.RawMessage `json:"agent_contexts"`
	SavedAt       time.Time                  `json:"saved_at"`
}

SnapshotData is a full snapshot of spec state at a given event, including optional agent context for restoring agent-specific working memory.

func LoadLatestSnapshot

func LoadLatestSnapshot(dir string) (*SnapshotData, error)

LoadLatestSnapshot loads the snapshot with the highest event ID from the given directory. Returns nil if the directory is empty or does not exist.

func (SnapshotData) MarshalJSON

func (sd SnapshotData) MarshalJSON() ([]byte, error)

MarshalJSON serializes the SnapshotData with proper handling of SpecState internals.

func (*SnapshotData) UnmarshalJSON

func (sd *SnapshotData) UnmarshalJSON(data []byte) error

UnmarshalJSON deserializes the SnapshotData with proper handling of SpecState internals.

type SpecDir

type SpecDir struct {
	SpecID ulid.ULID
	Path   string
}

SpecDir pairs a spec's ULID with its filesystem path.

type SpecSummary

type SpecSummary struct {
	SpecID    string
	Title     string
	OneLiner  string
	Goal      string
	UpdatedAt string
}

SpecSummary is a summary of a spec for list queries, matching the API's shape.

type SqliteIndex

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

SqliteIndex is a SQLite-backed index that mirrors spec and card data for fast reads. This index is always rebuildable from the event log and serves as a queryable cache, not the source of truth.

func OpenSqlite

func OpenSqlite(path string) (*SqliteIndex, error)

OpenSqlite opens or creates a SQLite index database at the given path. Runs migrations to ensure the schema is up to date.

func (*SqliteIndex) ApplyEvent

func (idx *SqliteIndex) ApplyEvent(event *core.Event) error

ApplyEvent incrementally applies a single event to update the index.

func (*SqliteIndex) Close

func (idx *SqliteIndex) Close() error

Close closes the SQLite database connection.

func (*SqliteIndex) DeleteCard

func (idx *SqliteIndex) DeleteCard(cardID ulid.ULID) error

DeleteCard removes a card row by card_id.

func (*SqliteIndex) GetLastEventID

func (idx *SqliteIndex) GetLastEventID() (uint64, bool, error)

GetLastEventID returns the last event ID that was indexed, from the meta table. Returns 0, false if no last event ID has been set.

func (*SqliteIndex) ListCards

func (idx *SqliteIndex) ListCards(specID ulid.ULID) ([]CardRow, error)

ListCards returns all cards for a given spec, ordered by sort_order ascending.

func (*SqliteIndex) ListSpecs

func (idx *SqliteIndex) ListSpecs() ([]SpecSummary, error)

ListSpecs returns all specs as summaries, ordered by updated_at descending.

func (*SqliteIndex) RebuildFromEvents

func (idx *SqliteIndex) RebuildFromEvents(events []core.Event) error

RebuildFromEvents clears all data and rebuilds from a list of events.

func (*SqliteIndex) SetLastEventID

func (idx *SqliteIndex) SetLastEventID(eventID uint64) error

SetLastEventID stores the last event ID in the meta table.

func (*SqliteIndex) UpdateCard

func (idx *SqliteIndex) UpdateCard(specID ulid.ULID, card *core.Card) error

UpdateCard upserts a card row.

func (*SqliteIndex) UpdateSpec

func (idx *SqliteIndex) UpdateSpec(spec *core.SpecCore) error

UpdateSpec upserts a spec row from a SpecCore.

type StorageManager

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

StorageManager manages the mammoth-specd home directory layout and provides high-level operations for spec storage, recovery, and export generation.

Dir layout:

home/specs/{ulid}/events.jsonl
home/specs/{ulid}/index.db
home/specs/{ulid}/snapshots/
home/specs/{ulid}/exports/

func NewStorageManager

func NewStorageManager(home string) (*StorageManager, error)

NewStorageManager creates a new StorageManager rooted at the given home directory. Creates the home and specs subdirectories if they do not exist.

func (*StorageManager) CreateSpecDir

func (m *StorageManager) CreateSpecDir(specID ulid.ULID) (string, error)

CreateSpecDir creates a spec directory with the required subdirectories.

func (*StorageManager) GetSpecDir

func (m *StorageManager) GetSpecDir(specID ulid.ULID) string

GetSpecDir returns the path to a spec's directory (does not create it).

func (*StorageManager) Home

func (m *StorageManager) Home() string

Home returns the home directory path.

func (*StorageManager) ListSpecDirs

func (m *StorageManager) ListSpecDirs() ([]SpecDir, error)

ListSpecDirs scans the specs directory and returns all spec directories with their ULIDs.

func (*StorageManager) RecoverAllSpecs

func (m *StorageManager) RecoverAllSpecs() ([]RecoveredSpec, error)

RecoverAllSpecs recovers all specs from their storage directories. Returns a list of (spec_id, recovered_state) pairs. Logs and skips specs that fail to recover.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL