implement

package
v0.13.3 Latest Latest
Warning

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

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

Documentation

Overview

Package implement is the run machinery an autonomous implementation run calls: the run's shared state in the machine-scoped store, the sessions that join it, the claim that makes a record the unit of exclusion between them, the bounds that keep a second session from becoming a hazard, and the run log the comparison of division modes is derived from (itd-2609221656373558, spc-2609221657588816).

Everything lives under one directory per repository:

~/.abcd.noindex/runs/<root-sha>/<YYYY-MM-DD>.jsonl   the run log, one event per line
~/.abcd.noindex/runs/<root-sha>/claims/<record>.json one claim per record
~/.abcd.noindex/runs/<root-sha>/sessions/<id>.json   one record per joined session

The key is the repository's root-commit SHA, the same key and the same full form the transcript, history and voyage stores use (internal/core/history's location.go says why: a checkout moves, is renamed and is cloned twice, while its root commit changes under none of that). Two sessions in two worktrees of one repository therefore share one directory and no repository file.

The package is the seed the implement loop builds on (itd-2609201916151817: `implement step` and `implement receipt`) and the pacing verb reads (itd-2609201925079472): a Run is the handle a later state file hangs off, and the log is the measurement both inherit. Core never writes to stdout; the CLI front door formats what these functions return.

Index

Constants

View Source
const (
	MinLease = time.Minute
	MaxLease = 24 * time.Hour
)

Lease bounds. A lease shorter than a minute lapses under its own gate run; a lease longer than a day outlives any window the run keeps.

View Source
const (
	SitePreflight   = "preflight"
	SiteEvalHarness = "eval-harness"
)

The sites the check runs at.

View Source
const (
	// LoadOK: nothing to warn about.
	LoadOK = "ok"
	// LoadWarning: at least one trigger fired.
	LoadWarning = "warning"
	// LoadSkipped: a CI runner, where the check does not run.
	LoadSkipped = "skipped"
	// LoadUnchecked: the machine could not be read (an unsupported platform, or
	// a read that failed) and nothing fired on what could be read.
	LoadUnchecked = "unchecked"
)

The four statuses.

View Source
const (
	LimitsDefault               = "default"
	LimitsFile                  = "file"
	LimitsDefaultAfterMalformed = "default-after-malformed"
)

Where the limits came from.

View Source
const (
	CoresOnline  = "online"
	CoresRuntime = "runtime"
)

The core-count sources.

View Source
const (
	PrivateNameMask  = "[private name]"
	WithheldNameMask = "[name withheld: private-names layer unreadable]"
)

PrivateNameMask replaces an own stray's name the private banned-names layer matches; WithheldNameMask replaces every name when that layer cannot be read.

View Source
const (
	EventSessionOpen   = "session_open"
	EventSessionClose  = "session_close"
	EventWindowMode    = "window_mode"
	EventClaim         = "claim"
	EventClaimDenied   = "claim_denied"
	EventClaimLapsed   = "claim_lapsed"
	EventClaimReleased = "claim_released"

	EventBackoff     = "backoff"
	EventLaneOpen    = "lane_open"
	EventLaneClose   = "lane_close"
	EventAgentStart  = "agent_start"
	EventAgentEnd    = "agent_end"
	EventCeilingWait = "ceiling_wait"
	EventGateRun     = "gate_run"
	EventReview      = "review"
	EventFallback    = "fallback"
	EventStop        = "stop"
	EventRefusal     = "refusal"
	EventPR          = "pr"
	EventCapture     = "capture"
	// EventContext is an orchestrator's context measurement: used_pct (the share
	// of its context window in use), role and note. The run measures it because
	// it is also an experiment in keeping a session alive for days.
	EventContext = "context"
	// EventCeilingOverrun is a session going over its agent ceiling: alive (the
	// agents alive), ceiling, lane and minutes (how long it was over). The verb
	// refuses an agent_start past the ceiling, so an overrun is what the host
	// did anyway — a fork, an agent started outside the log — and says so.
	EventCeilingOverrun = "ceiling_overrun"

	// The evidence events: what an autonomous run records so a later run can be
	// built to need no person. An intervention is a person acting on the run
	// (kind, by, what, why, autonomy_gap — what abcd or the host would need so
	// no person is needed — and optionally at and detected_after_min); a stop is
	// a stall (cause, and optionally last_productive, noticed_after_min and
	// recovery); a decision is a judgement call a person would normally make
	// (what, alternative, why, and optionally at).
	EventIntervention = "intervention"
	EventDecision     = "decision"

	// EventLoad is the load check's warning (itd-2609231434459890), written by
	// `implement load` alone and only when it warns inside a live run. The run's
	// hand-kept load samples share the name and carry no `triggers`, which is how
	// a reader tells the two apart.
	EventLoad = "load"
)

Event names. The first group is written only by this package's verbs, so the log cannot claim a join, a window or a claim that the run state does not hold.

View Source
const CoverageGapAfter = 6 * time.Hour

CoverageGapAfter is how long before the run's last line a measured event's last line may fall before the report names its coverage as stopping.

View Source
const DefaultLease = 2 * time.Hour

DefaultLease is how long a claim holds when the caller names no lease: long enough for a lane's build-and-gate cycle, short enough that a session that died mid-lane frees its record within the same working window.

View Source
const JoinGrace = time.Minute

JoinGrace is how long before a window_mode a session_open may be logged and still count in that window.

View Source
const MaxCeiling = 64

MaxCeiling bounds a stated agent ceiling.

The ceiling is a session's own limit on the agents it runs at once — for the second session, on top of the first session's (itd-2609221656373558, criterion 5). The session states it on joining, and the record and the session_open line carry it. abcd runs no agent, so what it holds the ceiling against is what the session declares: the agents its own agent_start and agent_end lines leave alive (Run.AgentsAlive). An agent_start past the ceiling is refused and the refusal logged, and every check reports the count beside the ceiling. An agent the session never logs — a fork, one the host started outside the log — is invisible, so the count is a discipline the session keeps with the verb's help, not a census of processes (iss-2609240646542516).

View Source
const UnreadableClaimGrace = time.Minute

UnreadableClaimGrace is how long a claim file nobody can parse holds its record, counted from the file's modification time. Every claim is written under the run's lock in one create, so an unparseable file is a writer killed between the create and the write; the grace is only long enough that a reader racing that writer backs off rather than taking the record.

View Source
const UnsetMode = "unset"

UnsetMode labels the events logged before any window opened.

Variables

CoverageEvents are the hand-kept events the report's figures rest on and a run writes throughout, so their stopping partway is a gap, not a lull.

View Source
var ErrContention = errors.New("contention")

ErrContention is the class of every "someone else holds it" outcome: a record another session has claimed, or the run state locked by another session's mutation. It is not a fault: the caller backs off and tries other work. The CLI maps it to exit 3.

View Source
var ErrRefused = errors.New("refused")

ErrRefused is the class of every refusal: an input the verb does not recognise, a session that has not joined, or a bound the caller's role does not permit. Nothing is written for the refused act (the refusal itself may be logged). The CLI maps it to exit 2.

View Source
var InterventionKinds = []string{
	"session_open", "account", "ruling", "restart", "close_session", "file_restore", "permission", "other",
}

InterventionKinds is the closed vocabulary of an intervention's kind.

LimitsFileDisplay is the settings file as every report names it.

Functions

func LoadSites

func LoadSites() []string

LoadSites returns the closed site vocabulary.

func LoggableEvents

func LoggableEvents() []string

LoggableEvents returns the events `implement log` accepts, for help text and shell completion.

func ParseLog

func ParseLog(name string, data []byte) ([]Event, []Unparsed)

ParseLog parses one log file's bytes. name labels Unparsed entries.

func ReadingCorpus

func ReadingCorpus(repoRoot string) ([]string, error)

ReadingCorpus is what "a lane that touches the reading corpus" means, derived from the checkout's committed preset file rather than restated here: the union of every position's object.paths, plus the preset file itself, whose recalibration serialises such lanes (iss-2609211105023379). A lane that edits one of those paths moves what a cold reading is handed, and so the measured windows the first session recalibrates. An entry names a file or a directory; a directory covers everything beneath it.

It is read through reading.LoadPresets, the loader the reading verb itself uses, so the two can never disagree about what the corpus is, and it refuses what that loader refuses: an untracked, symlinked or unparseable preset file. A corpus that cannot be derived is an error, never an empty list — the caller fails closed on it.

func RequiredFields added in v0.12.0

func RequiredFields(event string) []string

RequiredFields returns the fields `implement log` requires on event, each as its accepted names ("minutes|wall_minutes|wall_min"), for help text and the report's missing-field count.

func TouchesReadingCorpus

func TouchesReadingCorpus(corpus, paths []string) string

TouchesReadingCorpus returns the first path that falls in corpus — equal to an entry, or beneath one — or "" when none does.

Types

type Claim

type Claim struct {
	Record    string    `json:"record"`
	Session   string    `json:"session"`
	Lane      string    `json:"lane"`
	ClaimedAt time.Time `json:"claimed_at"`
	ExpiresAt time.Time `json:"expires_at"`
}

Claim is one claim file's content.

type ClaimRequest

type ClaimRequest struct {
	Session string
	Record  string
	Lane    string
	// Lease is the claim's lifetime; zero means DefaultLease.
	Lease time.Duration
	// Paths are the repository-relative files the lane expects to touch, when the
	// caller knows them. For the second session a path in the reading corpus —
	// or any path, when the corpus cannot be derived — refuses the claim (see
	// ReadingCorpus).
	Paths []string
}

ClaimRequest is what a session asks for.

type ClaimResult

type ClaimResult struct {
	Claim Claim `json:"claim"`
	// Renewed is true when the session already held the record and the lease was
	// extended instead of a second claim being taken.
	Renewed bool `json:"renewed"`
	// Lapsed is the expired claim this one replaced, when there was one.
	Lapsed *Claim `json:"lapsed,omitempty"`
}

ClaimResult is what a granted claim reports.

type ClaimState

type ClaimState struct {
	Claim
	Live bool `json:"live"`
	// Unreadable marks a claim file nobody can parse: it carries only its
	// record, and its lease is the grace after the file was written.
	Unreadable bool `json:"unreadable,omitempty"`
}

ClaimState is a claim as read at a moment: whether its lease still holds.

type CoverageGap added in v0.12.0

type CoverageGap struct {
	Event string    `json:"event"`
	Lines int       `json:"lines"`
	Last  time.Time `json:"last"`
	// RunLast is the run's last line, load samples aside.
	RunLast     time.Time `json:"run_last"`
	HoursBefore float64   `json:"hours_before"`
}

CoverageGap is a measured event whose lines stop partway through the run.

type Event

type Event struct {
	TS      time.Time                  `json:"ts"`
	Session string                     `json:"session"`
	Event   string                     `json:"event"`
	Fields  map[string]json.RawMessage `json:"-"`
}

Event is one line of the run log as it was read: the three fixed fields parsed, and every field (the fixed three included) kept as raw JSON so a reader can take what it understands and leave the rest.

func (Event) Number

func (e Event) Number(key string) (float64, bool)

Number returns a field as a number, accepting a JSON number or a string that holds one (a hand-written line may quote either), and ok=false otherwise.

func (Event) String

func (e Event) String(key string) string

String returns a field as a string: a JSON string's value, a number's or a boolean's literal text, "" when absent or null.

type Evidence added in v0.12.0

type Evidence struct {
	Interventions       int            `json:"interventions"`
	InterventionsByKind map[string]int `json:"interventions_by_kind"`
	// DetectedAfterMinutes sums the interventions' detected_after_min: how long
	// the needs went unnoticed.
	DetectedAfterMinutes float64 `json:"detected_after_minutes"`
	Stops                int     `json:"stops"`
	// StopNoticedAfterMinutes sums the stops' noticed_after_min.
	StopNoticedAfterMinutes float64 `json:"stop_noticed_after_minutes"`
	Decisions               int     `json:"decisions"`
}

Evidence is the run's evidence events counted over the whole run: what a run that needs no person would have to do without.

type FieldGap added in v0.12.0

type FieldGap struct {
	Event string `json:"event"`
	Field string `json:"field"`
	Lines int    `json:"lines"`
	Of    int    `json:"of"`
}

FieldGap is a field `implement log` requires of an event, and how many of the log's lines of that event lack it.

type HeldError

type HeldError struct {
	Holder Claim
}

HeldError is the contention a refused claim returns: the record and the session that holds it.

func (*HeldError) Error

func (e *HeldError) Error() string

func (*HeldError) Is

func (e *HeldError) Is(target error) bool

Is makes a HeldError an ErrContention.

type JoinResult

type JoinResult struct {
	Session Session `json:"session"`
	// Rejoined is true when the session's record already existed with the same
	// role: a resumed session opens again rather than being refused.
	Rejoined bool `json:"rejoined"`
}

JoinResult is what Join reports.

type LeaveResult

type LeaveResult struct {
	Session  Session `json:"session"`
	Released []Claim `json:"released"`
}

LeaveResult is what Leave reports.

type LoadAverages

type LoadAverages struct {
	One     float64 `json:"one"`
	Five    float64 `json:"five"`
	Fifteen float64 `json:"fifteen"`
}

LoadAverages are the three load averages.

type LoadLimits

type LoadLimits struct {
	StrayMinutes    int     `json:"stray_minutes"`
	ExtremeLoad     float64 `json:"extreme_load"`
	Source          string  `json:"source"`
	StrayFromFile   bool    `json:"stray_from_file"`
	ExtremeFromFile bool    `json:"extreme_from_file"`
	// Malformed says why the settings file is unusable, when it is: a line
	// number and a fault class, never a value.
	Malformed string `json:"malformed,omitempty"`
}

LoadLimits are the limits in force and where they came from.

type LoadOtherStrays

type LoadOtherStrays struct {
	Count int     `json:"count"`
	Cores float64 `json:"cores"`
}

LoadOtherStrays is every other account's strays: a count and a CPU total in cores, rounded to one decimal, and nothing else.

type LoadOwnStray

type LoadOwnStray struct {
	Name   string `json:"name"`
	PID    int    `json:"pid"`
	PGID   int    `json:"pgid"`
	AgeS   int64  `json:"age_s"`
	CPUPct int    `json:"cpu_pct"`
}

LoadOwnStray is one of the caller's own strays as it is printed and logged.

type LoadRemedy

type LoadRemedy struct {
	// Form is "group" (pgrep -g, then kill -- -PGID) or "process" (ps -p, then
	// kill PID).
	Form string `json:"form"`
	PGID int    `json:"pgid,omitempty"`
	PIDs []int  `json:"pids,omitempty"`
	PID  int    `json:"pid,omitempty"`
	// Why says why a process form is not the group form.
	Why string `json:"why,omitempty"`
}

LoadRemedy is one printed way to stop some of the caller's own strays.

type LoadRequest

type LoadRequest struct {
	// Site is where the check runs: SitePreflight or SiteEvalHarness.
	Site string
	// Getenv reads the environment; nil is os.Getenv.
	Getenv func(string) string
	// Read reads the machine; nil is machineload.Read.
	Read func() (machineload.Snapshot, error)
	// Home is the caller's home, where ~/.abcd.noindex/load-limits lives; "" resolves it.
	Home string
	// RepoRoot is the checkout the check runs in, whose private banned-names
	// layer scrubs the own strays' names; "" is outside any checkout.
	RepoRoot string
	// RootSHA keys the run state; "" derives it from RepoRoot.
	RootSHA string
	// Self is the invocation; the zero value is this process.
	Self machineload.Self
	// Now is the clock for the run-log line; nil is time.Now.
	Now func() time.Time
	// GOOS names the platform in the cannot-check reason; "" is runtime.GOOS.
	GOOS string
}

LoadRequest is one check. Every field but Site has a working zero value; the others exist so a test never depends on the real machine, environment or home.

type LoadResult

type LoadResult struct {
	Status          string          `json:"status"`
	Site            string          `json:"site"`
	Load            *LoadAverages   `json:"load"`
	Cores           int             `json:"cores"`
	CoresSource     string          `json:"cores_source,omitempty"`
	Limits          *LoadLimits     `json:"limits"`
	Triggers        []string        `json:"triggers"`
	OwnStrays       []LoadOwnStray  `json:"own_strays"`
	OwnStraysMore   int             `json:"own_strays_more"`
	OtherStrays     LoadOtherStrays `json:"other_strays"`
	Remedy          []LoadRemedy    `json:"remedy"`
	NamesWithheld   bool            `json:"names_withheld,omitempty"`
	WithinPreflight bool            `json:"within_preflight"`
	RunLog          LoadRunLog      `json:"run_log"`
	// Reason says why the check was skipped or could not read everything.
	Reason string `json:"reason,omitempty"`
}

LoadResult is the check's whole report.

func CheckLoad

func CheckLoad(req LoadRequest) LoadResult

CheckLoad runs the load check once. It never returns an error: a machine it cannot read is a status with a reason, and a run log it cannot write is reported on the result beside a warning that stands.

func LoadResultFromEvent

func LoadResultFromEvent(ev Event) (LoadResult, error)

LoadResultFromEvent reads a logged `load` event back into the warning it records, so a reader renders exactly what was printed. The run-log outcome is not part of the event.

No production code reads it yet; its readers are tests in two packages, this one and the CLI surface's (TestLoggedEventRendersToThePrintedWarning, which needs the surface's unexported renderer). It stays here, exported, because Go has no test-only export across packages and the decoding needs the unexported loadEvent, so moving it into a test file would duplicate the event's shape.

type LoadRunLog

type LoadRunLog struct {
	Logged  bool   `json:"logged"`
	Session string `json:"session,omitempty"`
	Error   string `json:"error,omitempty"`
}

LoadRunLog is what happened to the run-log event.

type Mode

type Mode string

Mode is a window's division of work between the sessions. `single` is a window with one session; the three the intent measures are `claim` (a session claims a record before opening its lane), `batch` (the run file assigns whole batches per session) and `split-roles` (the first builds; the second reviews, audits and lands).

const (
	ModeSingle     Mode = "single"
	ModeClaim      Mode = "claim"
	ModeBatch      Mode = "batch"
	ModeSplitRoles Mode = "split-roles"
)

The four modes.

func Modes

func Modes() []Mode

Modes returns the closed mode vocabulary, in the order the run tries them.

func ParseMode

func ParseMode(s string) (Mode, error)

ParseMode accepts exactly one of Modes.

type ModeTally

type ModeTally struct {
	Mode               string  `json:"mode"`
	Windows            int     `json:"windows"`
	WallMinutes        float64 `json:"wall_minutes"`
	LanesOpened        int     `json:"lanes_opened"`
	LanesLanded        int     `json:"lanes_landed"`
	SecondLanesLanded  int     `json:"second_session_lanes_landed"`
	Collisions         int     `json:"collisions"`
	Lapses             int     `json:"claims_lapsed"`
	Backoffs           int     `json:"backoffs"`
	BackoffMinutes     float64 `json:"backoff_minutes"`
	AgentMinutes       float64 `json:"agent_minutes"`
	CeilingWaitMinutes float64 `json:"ceiling_wait_minutes"`
	// CeilingOverruns are the ceiling_overrun lines, and CeilingOverrunMinutes
	// the minutes over they carry.
	CeilingOverruns       int            `json:"ceiling_overruns"`
	CeilingOverrunMinutes float64        `json:"ceiling_overrun_minutes"`
	Refusals              int            `json:"refusals"`
	LandedPerHour         float64        `json:"lanes_landed_per_hour"`
	Sessions              []SessionTally `json:"sessions"`
}

ModeTally is one division mode's figures over every window that ran it.

type Report

type Report struct {
	Events   int         `json:"events"`
	Unparsed []Unparsed  `json:"unparsed"`
	Modes    []ModeTally `json:"modes"`
	// Context is each session's context measurement, by session id.
	Context []SessionContext `json:"context"`
	// Evidence counts the run's interventions, stops and decisions.
	Evidence Evidence `json:"evidence"`
	// MissingFields names, per event and required field, the lines lacking it.
	MissingFields []FieldGap `json:"missing_fields"`
	// Coverage names each measured event whose lines stop partway.
	Coverage []CoverageGap `json:"coverage"`
	// Leader is the mode with the most lanes landed per wall-clock hour, "" when
	// no mode landed a lane or two modes tie. It is a figure, not a verdict: the
	// run's report names which mode it would keep, and says why.
	Leader      string `json:"leader"`
	LeaderBasis string `json:"leader_basis"`
}

Report is the derived comparison.

func Compare

func Compare(events []Event, unparsed []Unparsed) Report

Compare derives the comparison from a log. It never fails: a line it cannot use was already set aside by the parser, and a field it cannot read counts as absent.

type Role

type Role string

Role is a session's standing in the run. The first session is the run: it may cut a release and take any lane, and it never waits on the second. The second is optional and bounded (the intent's decision 3): at most one lane, never the release, never a lane that touches the reading corpus, and it backs off on contention.

The role lives in the session's record in the run state, written when the session joins. It is deliberately not read from the environment: a variable a shell, a task runner or a repository's configuration can set is not a statement the session made, and the bounds key on it. What the record gives is consistency, not authentication — two sessions of one account can each write anything under that account's home — so the bounds are a discipline two cooperating sessions keep, checked at every verb, not a wall against a hostile one.

const (
	RoleFirst  Role = "first"
	RoleSecond Role = "second"
)

The two roles.

func ParseRole

func ParseRole(s string) (Role, error)

ParseRole accepts exactly one of Roles.

func Roles

func Roles() []Role

Roles returns the closed role vocabulary.

type Run

type Run struct {
	// Dir is the run directory, ~/.abcd.noindex/runs/<root-sha>.
	Dir string
	// RootSHA is the repository's root-commit SHA the directory is keyed on.
	RootSHA string
	// RepoRoot is the checkout the run was opened from. The reading corpus the
	// second session's bounds check against is read from its preset file.
	RepoRoot string
	// Now is the clock. Tests set it; nil means time.Now.
	Now func() time.Time
	// contains filtered or unexported fields
}

Run is one repository's run state. The zero value is not usable; construct it with Open (which creates the directories a mutation needs) or Peek (which creates nothing, for the read-only renders).

func Open

func Open(rootSHA string) (*Run, error)

Open returns the run for rootSHA, creating its directories when absent. Every level from ~/.abcd.noindex down is created one at a time and proved a real directory, never through a symlink (fsutil.EnsureRealDirAll), so a planted redirect is refused before anything is written beneath it.

func OpenJoined

func OpenJoined(rootSHA, session string) (*Run, error)

OpenJoined returns the run for rootSHA on behalf of a session that must already have joined it: every writer but join. A run directory that does not exist holds no session, so the caller is refused before anything is created — no directory, no lock, no log line. An existing run is opened as Open opens it, and the verb itself refuses a session it does not hold.

func Peek

func Peek(rootSHA string) (*Run, error)

Peek returns the run for rootSHA without creating anything. A run directory that does not exist reads as an empty run: no sessions, no claims, no log.

func (*Run) AgentsAlive added in v0.12.0

func (r *Run) AgentsAlive(s Session) (int, error)

AgentsAlive counts the agents a session has declared alive: the agents named by its agent_start lines since it joined, each with no agent_end of the same agent after it. It counts what the session wrote and nothing else — abcd runs no agent, and a line the session never wrote (a fork, an agent the host started outside the log) is invisible here — so it is the declared count the ceiling is held against, not a census of processes. Lines naming no agent cannot be matched and are not counted.

func (*Run) Check

func (r *Run) Check(session string, stage Stage, paths []string) (Verdict, error)

Check says whether a session may take a stage, and logs the refusal when it may not. The first session may take every stage. The second is refused:

  • the release stage, always — only the first session cuts a release;
  • a lane in a split-roles window, where the second only reviews, audits and lands;
  • a lane whose paths reach the reading corpus.

Review, audit and land are open to both. A refusal is an ErrRefused-classed error and a `refusal` line in the log; an allowed stage writes nothing.

func (*Run) Claim

func (r *Run) Claim(req ClaimRequest) (ClaimResult, error)

Claim takes req.Record for req.Session. In order, under the run's lock:

  1. the session must have joined; its role decides the bounds;
  2. a second session is refused when it already holds a live claim on another record (one lane at a time), when the window's mode is split-roles (the second builds nothing), or when req.Paths reach the reading corpus;
  3. the claim file is created exclusively. If it exists and this session holds it, the lease is renewed. If another session's lease has passed, the lapse is logged, the stale file removed, and the create retried. If another session's lease holds, the denial is logged naming the holder — and for the second session a backoff is logged beside it — and a *HeldError (ErrContention) is returned.

A granted claim is logged as `claim`. When that line cannot be written the claim is removed again, so the claims directory never holds a claim the log does not.

func (*Run) Claims

func (r *Run) Claims() ([]ClaimState, error)

Claims lists every claim file, live or lapsed, by record.

func (*Run) Compare

func (r *Run) Compare() (Report, error)

Compare derives the comparison over the run's whole log.

func (*Run) CurrentMode

func (r *Run) CurrentMode() (WindowState, bool, error)

CurrentMode returns the mode the log last recorded, whoever wrote the line (a hand-written window_mode counts the same as one SetMode wrote). ok is false when no window has been opened; an unrecognised mode word is returned as it was written, and the bounds treat it as no split.

func (*Run) Join

func (r *Run) Join(id string, role Role, model, reason string, ceiling int) (JoinResult, error)

Join records a session in the run and logs its session_open. Nothing signals any other session: joining is a file the joiner writes and a log line, and the first session learns of a second only if it reads the run state. The record is taken by an exclusive create; a session that joins again with the role it holds is a resume, and one that asks for a different role is refused. ceiling is the session's own agent ceiling (see MaxCeiling), zero for none; a resume keeps the ceiling it joined with and refuses a different one.

func (*Run) Joined added in v0.12.0

func (r *Run) Joined(id string) (Session, error)

Joined returns a joined session's record, or refuses one the run does not hold, writing nothing: for a caller that acts for a session in the run state and must know it has joined before it creates anything of its own.

func (*Run) Leave

func (r *Run) Leave(id, reason string) (LeaveResult, error)

Leave closes a session: it releases every claim the session holds, logs session_close with the reason, and removes the session's record. A session that stops without leaving is covered by its claims' leases instead.

func (*Run) Log

func (r *Run) Log(session, event string, fields map[string]string) (Event, error)

Log appends one event on a joined session's word: the run's hand-kept events (lane_open, agent_end, backoff, …) through the same single-write append the verbs use. The event must be one of LoggableEvents — the verb-owned events are refused, because a hand-written claim the claims directory does not hold is a log that lies — and fields are key=value pairs under the limits above. A value that parses as an integer, a decimal or a boolean is written as a JSON number or boolean when it round-trips to the same text; anything else as a string.

func (*Run) ReadLog

func (r *Run) ReadLog() ([]Event, []Unparsed, error)

ReadLog reads every day's log in the run directory, in date order. A missing directory is an empty log. Lines that are not a JSON object carrying ts, session and event are returned as Unparsed rather than failing the read: the log is hand-written in part, and a comparison that stopped at the first odd line would report nothing.

func (*Run) Release

func (r *Run) Release(session, record string) (Claim, error)

Release gives up a session's claim on a record and logs claim_released. Only the holder releases: a session cannot free another's claim, which lapses on its own lease instead.

func (*Run) Sessions

func (r *Run) Sessions() ([]Session, error)

Sessions lists the joined sessions, by join time.

func (*Run) SetMode

func (r *Run) SetMode(session string, m Mode, window int) (WindowState, error)

SetMode opens a window: it logs window_mode with the mode and, when given, the window's number. Only the first session sets it — the second tells the first nothing, and the window's mode is how the first divides its own run.

type Session

type Session struct {
	Session  string    `json:"session"`
	Role     Role      `json:"role"`
	JoinedAt time.Time `json:"joined_at"`
	Model    string    `json:"model,omitempty"`
	// Ceiling is the session's own agent ceiling as it stated it on joining,
	// zero when it stated none.
	Ceiling int `json:"ceiling,omitempty"`
}

Session is a joined session's record.

type SessionContext

type SessionContext struct {
	Session     string    `json:"session"`
	Role        string    `json:"role"`
	Events      int       `json:"events"`
	LastUsedPct float64   `json:"last_used_pct"`
	LastAt      time.Time `json:"last_at"`
}

SessionContext is one session's context measurement across the whole run: how many context lines it logged and the last used_pct among them. It is per session rather than per mode because an orchestrator's context is carried across windows, not reset by them.

type SessionTally

type SessionTally struct {
	Session            string  `json:"session"`
	Role               string  `json:"role"`
	LanesOpened        int     `json:"lanes_opened"`
	LanesLanded        int     `json:"lanes_landed"`
	AgentMinutes       float64 `json:"agent_minutes"`
	BackoffMinutes     float64 `json:"backoff_minutes"`
	CeilingWaitMinutes float64 `json:"ceiling_wait_minutes"`
	CeilingOverruns    int     `json:"ceiling_overruns"`
	Collisions         int     `json:"collisions"`
}

SessionTally is one session's share of a mode.

type Stage added in v0.12.0

type Stage string

Stage is a point in a run where the second session's bounds are checked before the session acts, called a stage like the loop's lane stages (rulings BU1 and CM1: a spec's piece is a step, and nothing else is). A lane is opened by a claim (Claim applies the lane bounds itself); Check is for the stages that are not claims, and for a lane whose files are only known once it has been built.

const (
	StageLane    Stage = "lane"
	StageRelease Stage = "release"
	StageReview  Stage = "review"
	StageAudit   Stage = "audit"
	StageLand    Stage = "land"
)

The stages.

func ParseStage added in v0.12.0

func ParseStage(s string) (Stage, error)

ParseStage accepts exactly one of Stages.

func Stages added in v0.12.0

func Stages() []Stage

Stages returns the closed stage vocabulary.

type Unparsed

type Unparsed struct {
	File   string `json:"file"`
	Line   int    `json:"line"`
	Reason string `json:"reason"`
}

Unparsed is one log line the reader could not use, with why.

type UnreadableClaimError

type UnreadableClaimError struct {
	Record   string
	Path     string
	LapsesAt time.Time
}

UnreadableClaimError is a claim file nobody can parse — a session killed between the exclusive create and the write leaves an empty one. It names the file's full path and when it lapses, never a guess at who holds it.

func (*UnreadableClaimError) Error

func (e *UnreadableClaimError) Error() string

type Verdict

type Verdict struct {
	Session string `json:"session"`
	Role    Role   `json:"role"`
	Stage   Stage  `json:"stage"`
	Mode    Mode   `json:"mode,omitempty"`
	Allowed bool   `json:"allowed"`
	// Ceiling is the session's own agent ceiling as it joined with it, zero when
	// it stated none: reported with every verdict, beside AgentsAlive, so the
	// session about to act sees the limit it keeps (see MaxCeiling).
	Ceiling int `json:"ceiling,omitempty"`
	// AgentsAlive is the count of the session's agents its own log lines declare
	// alive (see Run.AgentsAlive): what an agent_start is held against when the
	// session stated a ceiling.
	AgentsAlive int `json:"agents_alive"`
}

Verdict is Check's answer.

type WindowState

type WindowState struct {
	Mode   Mode      `json:"mode"`
	Window int       `json:"window,omitempty"`
	Since  time.Time `json:"since"`
	SetBy  string    `json:"set_by"`
}

WindowState is the division mode in force, as the log last recorded it.

Directories

Path Synopsis
Package loop is the implement loop's engine (itd-2609201916151817, spc-2609202134338445): the state file a run lives in, the checks that decide whether a run may start, and the step interface a driving host calls.
Package loop is the implement loop's engine (itd-2609201916151817, spc-2609202134338445): the state file a run lives in, the checks that decide whether a run may start, and the step interface a driving host calls.

Jump to

Keyboard shortcuts

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