ledger

package
v0.37.0 Latest Latest
Warning

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

Go to latest
Published: Oct 20, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package ledger is f10's local record of what runs did: one append-only events table in ~/.f10/f10.db, outside every repo, so stealth is unaffected. Hooks write what they observe, `f10 state` what the model claims, and artifacts (plans, findings) what they hold.

A ledger write never fails its caller: an event that cannot reach the database goes to a spool file beside it, which the next successful open replays.

Index

Constants

View Source
const (
	BusyAsync = 3 * time.Second
	BusySync  = 200 * time.Millisecond
)

Busy timeouts: under the 5s hook timeout for async writers, so a contended write spools instead of the hook being killed; short for a synchronous hook, so a busy ledger never delays a skill's start.

View Source
const (
	Observed = "observed"
	Artifact = "artifact"
	Claimed  = "claimed"
)

Sources: what the hook saw, what an artifact holds, what the model said.

View Source
const (
	RunStarted     = "run_started"
	TaskCaptured   = "task_captured"
	StepEntered    = "step_entered"
	Committed      = "committed"
	Pushed         = "pushed"
	PROpened       = "pr_opened"
	TaskFinished   = "task_finished"
	SessionStopped = "session_stopped"

	PlanSaved         = "plan_saved"
	PlanSuperseded    = "plan_superseded"
	ReviewRoundOpened = "review_round_opened"
	FindingVerdict    = "finding_verdict"
	JudgeVerdict      = "judge_verdict"

	StateSet   = "state_set"
	StateTask  = "state_task"
	StateNote  = "state_note"
	StateAsk   = "state_ask"
	StateFinal = "state_final"
)

Kinds, by source.

View Source
const PathEnv = "F10_LEDGER"

PathEnv overrides the database's path; the spool and machine id live beside it, so a test pointing it at a temp dir touches nothing else.

Variables

This section is empty.

Functions

func MachineID

func MachineID(dir string) string

MachineID is this machine's id, generated once into <dir>/machine-id. Created exclusively, so two first runs read back the same id. Empty when the directory cannot be written.

func NewPayload

func NewPayload(p Payload) r3.JSONColumn[Payload]

NewPayload wraps a payload for an Event.

func NormalizeRemote

func NormalizeRemote(url string) string

NormalizeRemote turns a git remote url into a project id, so one repo cloned over ssh and over https is one project: scheme, user and a trailing `.git` dropped, scp-style `host:path` read as `host/path`, the host lowercased. `git@github.com:a/b.git` and `https://github.com/a/b` are both `github.com/a/b`. A local path stays a cleaned path.

func Path

func Path() string

Path is the database file: F10_LEDGER, else ~/.f10/f10.db.

func Record

func Record(ctx context.Context, busy time.Duration, events ...Event)

Record opens the ledger at Path, appends events and closes it. An open that fails spools them; nothing is returned, since no caller may act on a ledger failure.

Types

type Event

type Event struct {
	ID           string     `db:"id,pk"                   json:"id"`
	Machine      string     `db:"machine,immutable"       json:"machine"`
	At           time.Time  `db:"at,immutable"            json:"at"`
	Project      string     `db:"project,immutable"       json:"project"`
	ProjectLocal bool       `db:"project_local,immutable" json:"project_local"`
	Checkout     string     `db:"checkout,immutable"      json:"checkout"`
	Branch       string     `db:"branch,immutable"        json:"branch"`
	Session      string     `db:"session,immutable"       json:"session"`
	Task         string     `db:"task,immutable"          json:"task"`
	Kind         string     `db:"kind,immutable"          json:"kind"`
	Source       string     `db:"source,immutable"        json:"source"`
	Payload      payloadCol `db:"payload,immutable"       json:"payload"`
}

Event is one row. Every column but the id is immutable, so r3 has no update path for it and an upsert of a known id does nothing: the table only grows.

func (Event) TableName

func (Event) TableName() string

type Filter

type Filter struct {
	Project string
	Task    string
	Session string
	Kind    string
}

Filter narrows List; an empty field matches every row.

type Ledger

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

A Ledger is an open database.

func Open

func Open(ctx context.Context, path string, busy time.Duration, replay bool) (*Ledger, error)

Open opens the database at path for writing: it creates the file and runs the migrations. With replay it also replays the spool, which a synchronous hook leaves to the next async writer: a backlog has no bound.

func OpenRead

func OpenRead(ctx context.Context, path string) (*Ledger, error)

OpenRead opens an existing database read-only: no migration, no replay, so reading never writes. A missing file is fs.ErrNotExist.

func (*Ledger) Append

func (l *Ledger) Append(ctx context.Context, events ...Event)

Append writes events, ids and machine filled in where empty. An event the database refuses goes to the spool with the ones after it.

func (*Ledger) Close

func (l *Ledger) Close() error

Close closes the database.

func (*Ledger) Count

func (l *Ledger) Count(ctx context.Context, f Filter) (int64, error)

Count is how many events f matches.

func (*Ledger) List

func (l *Ledger) List(ctx context.Context, f Filter) ([]Event, error)

List returns the events f matches, oldest first.

type Observer

type Observer struct {
	StateDir string
	Busy     time.Duration
	// NoReplay leaves the spool to a later writer: a synchronous hook holds
	// the prompt while it runs.
	NoReplay bool
	// TaskID is the tracker task id a created issue's url names.
	TaskID func(ctx context.Context, cwd, url string) string
	// contains filtered or unexported fields
}

Observer records a hook's observations. It opens the ledger on the first one, so an event that yields nothing never touches the database; Close releases it.

func (*Observer) Close

func (ob *Observer) Close()

Close closes the ledger if an observation opened it.

func (*Observer) Observe

func (ob *Observer) Observe(ctx context.Context, o observe.Observation) error

type Payload

type Payload = map[string]any

Payload is an event's kind-specific detail, stored as JSON.

type Place

type Place struct {
	Project      string
	ProjectLocal bool // no remote: the main checkout's path stands in
	Checkout     string
	Branch       string
}

Place is where an event happened: the project, the checkout and its branch.

func Where

func Where(ctx context.Context, dir string) Place

Where reads the place a directory is in. Outside git, everything is empty but the project, which is the directory itself, flagged local.

Jump to

Keyboard shortcuts

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