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 ¶
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 ¶
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 ¶
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.