status

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package status automates the "done prompt": after every N completed agent tasks in a project, the sweeper mints ONE status task — a headless agent that writes a full status report (docs/status/<timestamp>.md) and closes the loop by appending the next work items to the repo's TODO_LIST.md, where the next harvest tick picks them up.

Loop safety is structural (same rule as internal/review): only completions of "agent" tasks are counted — status tasks never trigger status tasks. The N-completion window is derived from queue state (completed agent tasks updated since the last status task's creation), never from sweeper memory, so restarts cannot desynchronize it. Idempotency is the store's dedup: the window's triggering completion task IDs key the minted tasks.

Index

Constants

View Source
const (
	// ConsumerKey is the sweeper's identity in the watermarks table. One
	// cursor is shared by every status sweeper over the same database:
	// completions recorded while no sweeper ran are counted on the next
	// start (the window query is queue-derived, not cursor-derived).
	ConsumerKey = "status-sweeper"
)

Variables

This section is empty.

Functions

func StatusDedupKey

func StatusDedupKey(project string, trigger task.ID) string

StatusDedupKey is the dedup identity of the report for one window: the project plus the completion that filled the window. Two windows never share a trigger completion; the same window replayed never mints twice.

Types

type SweepStats

type SweepStats struct {
	// Facts is the number of new facts consumed.
	Facts int
	// ReportsEnqueued counts fresh status tasks this sweep created.
	ReportsEnqueued int
	// ReportsKnown counts mints that hit an existing dedup key (the report
	// task already existed — replayed page or a concurrent sweeper).
	ReportsKnown int
	// Skipped counts completions that could not yield a status task
	// (foreign payload shape, vanished task record, window not yet full,
	// or a report already in flight). A refused MINT is not counted here:
	// it aborts the sweep before the checkpoint so the completion
	// redelivers.
	Skipped int
}

SweepStats summarizes one sweep pass.

type Sweeper

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

func NewSweeper

func NewSweeper(ctx context.Context, store queue.Store, cfg SweeperConfig) (*Sweeper, error)

NewSweeper returns a sweeper over store. The cursor resumes from the persisted checkpoint; a first run bootstraps at the journal head (completions that predate the sweeper are not replayed as trigger facts — but the window QUERY counts them, so the first N-th completion after start reports on the full backlogged window). Rewind deliberately with `tq watermarks set status-sweeper SEQ`.

func (*Sweeper) Sweep

func (s *Sweeper) Sweep(ctx context.Context) (SweepStats, error)

Sweep consumes new facts since the last pass and mints status tasks for full windows. Idempotent by dedup: calling it twice never duplicates work, so a replayed page (crash between consumption and checkpoint) re-hits dedup keys instead of minting duplicates.

A mint refusal — a store failure while reading a completion, listing the window, or enqueueing the report — aborts the sweep BEFORE the checkpoint: the fact redelivers on the next pass instead of silently dropping the window's report forever (dlqfix 13-15 §e pattern). Deterministic skips (foreign shapes, vanished records, done-guard dedup hits) stay checkpointed past: retrying them can never succeed.

type SweeperConfig

type SweeperConfig struct {
	// Every is the number of completed agent tasks per project that mint
	// one status report. Required, >= 1.
	Every int
	// MinInterval is the per-project floor between two status reports:
	// a mint is skipped while the project's last status task is younger
	// (2026-10-11 ceremony cut — --status-every 5 produced 213 reports in
	// one repo; the window still accumulates, so the next report after the
	// floor covers everything). 0 = no floor.
	MinInterval time.Duration
	// Model, when set, is written into every status payload.
	Model string
	// Log receives one summary line per mint. nil logs nothing.
	Log *slog.Logger
	// PageSize bounds one fact-stream page; 0 selects the default.
	PageSize int
	// AllowDirty mirrors the pool's --allow-dirty: minted status payloads
	// then tolerate an uncommitted tree (RequireClean=false). A
	// multi-agent repo is effectively always dirty; without this the
	// status preflight would requeue forever on an --allow-dirty pool.
	AllowDirty bool
	// TaskTimeout is pinned into minted payloads as TimeoutMinutes (0
	// keeps the executor's default). The executor default (15m) is tuned
	// for stub-y repos; a real done-prompt run PLUS the repo verify gate
	// needs the pool's own task budget.
	TaskTimeout time.Duration
}

SweeperConfig controls one Sweeper.

Jump to

Keyboard shortcuts

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