Documentation
¶
Index ¶
- Constants
- Variables
- func AppendACP(path string, event ACPEvent) error
- func AppendClaim(path string, event ACPEvent) error
- func AppendDispatch(path string, event ACPEvent) error
- func CanonicalizeMission(m *MissionV1)
- func CheckClaimConflict(leases []Lease, m MissionV1, now time.Time) error
- func CheckParallelConflict(candidate MissionV1, missions []MissionV1, leases []Lease, ...) error
- func CheckpointPath(root, slug string) string
- func DispatchEnvelopeDigest(e DispatchEnvelopeV1) string
- func ExportA2A(kind string, payload any, transport A2ATransport) ([]byte, error)
- func HarnessAffectedPaths(events []ObservableEvent) []string
- func HasLiveLease(leases []Lease, now time.Time) bool
- func HasMission(events []ACPEvent, missionID string) bool
- func MissionDigest(m MissionV1) string
- func MissionID(sessionID string, step int, taskID string) string
- func MissionPayload(m MissionV1) (string, error)
- func NextAttempt(events []ACPEvent, taskID string) int
- func NormalizeTrace(events []ObservableEvent) error
- func RecordAuthorityDenial(root string, a core.AuthorityV1, tool, code string, now time.Time) error
- func SaveCheckpoint(root, path string, cp Checkpoint) error
- func SaveSessionCAS(root, path string, expectedRevision int64, next Session) error
- func TraceDigest(events []ObservableEvent) string
- func ValidateDispatchEnvelope(e DispatchEnvelopeV1) error
- func ValidateLease(l Lease) error
- func ValidateMission(m MissionV1) error
- func ValidateMissionPins(m MissionV1, p DispatchPins) error
- func ValidateWorkerReport(r WorkerReportV1, m MissionV1, l Lease, now time.Time) error
- type A2ACancelV1
- type A2AClaimV1
- type A2AEnvelope
- type A2AMessage
- type A2ATransport
- type ACPEvent
- type Action
- type Authority
- type AuthorityDenial
- type Checkpoint
- type ClaimEcho
- type CoordinationRule
- type Decision
- type DecisionLimits
- type DispatchEnvelopeV1
- type DispatchPins
- type Dispatcher
- type GateSeverity
- type HeartbeatV1
- type Lease
- type LeaseState
- type MissionLimits
- type MissionStatus
- type MissionV1
- type ObservableEvent
- type ObservationV1
- type Reclaim
- type RecoveryAction
- type RecoveryDecision
- type ResumePlan
- type RetryPolicy
- type Route
- type RouteFact
- type Session
- type SessionState
- type Snapshot
- type Telemetry
- type WorkerReportV1
- type WorkerState
- type WorkerV1
Constants ¶
const ( A2AKindMission = "mission" A2AKindClaim = "claim" A2AKindHeartbeat = "heartbeat" A2AKindCancel = "cancel" A2AKindReport = "report" )
const ( ACPKindDispatch = "dispatch" ACPKindClaim = "claim" ACPKindReport = "report" ACPKindCancel = "cancel" )
ACP event kinds. claim/report carry the worker-rigor fields (spec 10 R3); dispatch is the brain's own record.
const A2AProtocolVersion = "1"
const MaxObservationText = 256
const MissionProtocolVersion = "1"
Variables ¶
var ErrDuplicateMission = errors.New("duplicate mission id")
ErrDuplicateMission is returned when a dispatch with a mission id already in the ledger is appended again. It is the invariant that makes crash-recovery re-issue idempotent: the same deterministic mission id can appear at most once.
var ErrSessionRevisionConflict = errors.New("session revision conflict")
Functions ¶
func AppendACP ¶
AppendACP appends one event to the ledger. It is O(1): Seq is a read-time projection (ReadACP numbers events by position), so a write never re-reads the whole file — open, append, fsync. ponytail: the semantic appends (AppendClaim's attempt count, AppendDispatch's duplicate-mission guard) still scan the ledger, but that read is their actual job and the per-spec ledger is bounded by task count × attempts. Maintain an on-disk index only if a ledger ever grows past a few thousand events.
func AppendClaim ¶
AppendClaim appends a claim event, filling the attempt number from the current ledger when the caller left it zero. The read-then-append happens under the caller's spec lock so the derived attempt is race-free.
func AppendDispatch ¶
AppendDispatch appends a dispatch event, refusing a duplicate mission id (spec 07 R3). The read-then-append runs under the caller's spec lock so the duplicate check is race-free.
func CanonicalizeMission ¶ added in v0.4.0
func CanonicalizeMission(m *MissionV1)
func CheckClaimConflict ¶ added in v0.4.0
func CheckParallelConflict ¶ added in v0.4.0
func CheckpointPath ¶
CheckpointPath is the per-spec write-ahead checkpoint file.
func DispatchEnvelopeDigest ¶ added in v0.4.0
func DispatchEnvelopeDigest(e DispatchEnvelopeV1) string
func ExportA2A ¶ added in v0.4.0
func ExportA2A(kind string, payload any, transport A2ATransport) ([]byte, error)
func HarnessAffectedPaths ¶ added in v0.4.0
func HarnessAffectedPaths(events []ObservableEvent) []string
HarnessAffectedPaths is the harness-observed set of paths a worker touched. It is audit evidence, not an authoritative diff: Domain 06 owns changed-file authority (spec 04 R4.3). Paths are de-duplicated and sorted.
func HasLiveLease ¶
HasLiveLease reports whether any lease is still within its TTL at now. A live lease means another controller is actively holding work and blocks a second start/resume; only expired/orphaned leases are recoverable by resume (R5).
func HasMission ¶
HasMission reports whether the ledger already carries an event with missionID.
func MissionDigest ¶ added in v0.4.0
func MissionID ¶
MissionID is the deterministic identifier for a dispatch: session id + step + task. Determinism is the point — a dispatch re-issued after a crash on resume reuses the same mission id, so the ledger's duplicate guard makes re-issue idempotent (spec 07 R3).
func MissionPayload ¶ added in v0.4.0
func NextAttempt ¶
NextAttempt is the attempt number for a new claim on taskID: the count of prior claim events for that task plus one. It is a countable fact derived from the ledger under the spec lock, never a stored counter that can skew (spec 10 R3). It feeds spec 06's escalation counting.
func NormalizeTrace ¶ added in v0.4.0
func NormalizeTrace(events []ObservableEvent) error
NormalizeTrace validates a decoded trace: every event names its run/event id, tool, time and actor; all events share one run id; event ids are unique; and the sequence is strictly increasing (spec 04 R4.2 — duplicate/non-monotonic fail closed). It mutates nothing; a bad trace is refused, not repaired.
func RecordAuthorityDenial ¶ added in v0.4.0
func SaveCheckpoint ¶
func SaveCheckpoint(root, path string, cp Checkpoint) error
SaveCheckpoint writes the checkpoint durably (atomic write + fsync via core.AtomicWrite) under the spec lock. It must return before the caller makes the corresponding dispatch visible in the ledger (write-ahead ordering).
func SaveSessionCAS ¶
func TraceDigest ¶ added in v0.4.0
func TraceDigest(events []ObservableEvent) string
TraceDigest is the content address of a normalized trace: the SHA-256 of its canonical JSON encoding. A trajectory eval record pins this so completion can confirm the score was produced against exactly these events (spec 04 R4.2).
func ValidateDispatchEnvelope ¶ added in v0.4.0
func ValidateDispatchEnvelope(e DispatchEnvelopeV1) error
func ValidateLease ¶ added in v0.4.0
func ValidateMission ¶ added in v0.4.0
func ValidateMissionPins ¶ added in v0.4.0
func ValidateMissionPins(m MissionV1, p DispatchPins) error
func ValidateWorkerReport ¶ added in v0.4.0
Types ¶
type A2ACancelV1 ¶ added in v0.4.0
type A2AClaimV1 ¶ added in v0.4.0
type A2AEnvelope ¶ added in v0.4.0
type A2AEnvelope struct {
ProtocolVersion string `json:"protocol_version"`
Kind string `json:"kind"`
Payload json.RawMessage `json:"payload"`
Transport A2ATransport `json:"transport,omitempty"`
}
type A2AMessage ¶ added in v0.4.0
type A2AMessage struct {
Kind string
Payload any
Transport A2ATransport
}
func ImportA2A ¶ added in v0.4.0
func ImportA2A(raw []byte) (A2AMessage, error)
type A2ATransport ¶ added in v0.4.0
type A2ATransport struct {
Adapter string `json:"adapter,omitempty"`
MessageID string `json:"message_id,omitempty"`
}
A2ATransport carries non-semantic delivery facts. It is deliberately kept outside Payload so changing adapters cannot change mission or ACP identity.
type ACPEvent ¶
type ACPEvent struct {
Seq int `json:"seq"`
Time time.Time `json:"time"`
Kind string `json:"kind"`
TaskID string `json:"task_id,omitempty"`
Payload string `json:"payload,omitempty"`
// MissionID is the deterministic dispatch identifier (session/step/task, spec
// 07 R3). Optional so bare dispatch events and pre-spec-07 ledgers stay valid.
// It is the key the resume path and the duplicate guard match on.
MissionID string `json:"mission_id,omitempty"`
// Worker-rigor fields (spec 10 R3), all optional so a bare dispatch event and
// pre-telemetry ledgers stay valid. Attempt is monotonic per task (see
// NextAttempt); GitHead pins the claim/report to a commit; ChangedFiles is the
// worker-reported diff surface; VerifyRef points at the verify evidence
// backing a report; Telemetry is verbatim worker cost.
Attempt int `json:"attempt,omitempty"`
GitHead string `json:"git_head,omitempty"`
ChangedFiles []string `json:"changed_files,omitempty"`
VerifyRef string `json:"verify_ref,omitempty"`
Telemetry *core.Annotations `json:"telemetry,omitempty"`
Observation *ObservationV1 `json:"observation,omitempty"`
// TraceDigest pins the normalized observable trace (TraceDigest) backing a
// report, linking the ledger to the trajectory evidence a trajectory eval
// scores (spec 04 R4.2/R4.3). Optional so bare dispatch/claim events and
// pre-trace ledgers stay valid.
TraceDigest string `json:"trace_digest,omitempty"`
// Sanitized mission audit identity. AuditID is strictly increasing within a
// run/mission/task/policy stream; AuditKind follows constitutional stage order.
AuditID int `json:"audit_id,omitempty"`
AuditKind string `json:"audit_kind,omitempty"`
RunID string `json:"run_id,omitempty"`
PolicyDigest string `json:"policy_digest,omitempty"`
DispatchDigest string `json:"dispatch_digest,omitempty"`
}
func A2ASemanticACP ¶ added in v0.4.0
func A2ASemanticACP(message A2AMessage) (ACPEvent, error)
func MissionEvent ¶
MissionEvent returns the first event carrying missionID, or false.
type Authority ¶
type Authority struct {
Enabled bool
}
func (Authority) CanClearGate ¶
func (authority Authority) CanClearGate(severity GateSeverity) bool
func (Authority) CanDispatch ¶
type AuthorityDenial ¶ added in v0.4.0
type Checkpoint ¶
type Checkpoint struct {
SessionID string `json:"session_id"`
Step int `json:"step"`
Wave int `json:"wave"`
Decision string `json:"decision"`
MissionID string `json:"mission_id,omitempty"`
TaskID string `json:"task_id,omitempty"`
Mission *MissionV1 `json:"mission,omitempty"`
Lease *Lease `json:"lease,omitempty"`
Time time.Time `json:"time"`
}
Checkpoint is the write-ahead record the controller makes durable BEFORE a dispatch becomes visible in the ledger (spec 07 R1). If the process dies after the checkpoint but before the ACP dispatch, resume finds the checkpoint's mission id absent from the ledger and re-issues exactly that dispatch; if it dies after the ledger append, resume finds the mission id present and does not re-issue — this is what makes crash recovery converge with zero double-dispatch.
func LoadCheckpoint ¶
func LoadCheckpoint(path string) (Checkpoint, bool, error)
LoadCheckpoint reads the checkpoint. The bool is false when none exists yet.
type CoordinationRule ¶ added in v0.4.0
type Decision ¶
func Decide ¶
func Decide(snapshot Snapshot, limits DecisionLimits) Decision
func DispatchFrontier ¶
func DispatchFrontier(snapshot Snapshot, limits DecisionLimits, dispatcher Dispatcher) (Decision, error)
func EvaluateBrakes ¶
func EvaluateBrakes(snapshot Snapshot, limits DecisionLimits) Decision
EvaluateBrakes is the honest cost brake. It halts only on measured, reported telemetry: an absent measurement is unknown (never treated as zero), so an unset limit or unknown cost never fabricates a halt. A brake fired on untrusted (worker-reported) data is labelled as such (spec 07 R4.1-R4.3).
type DecisionLimits ¶
type DecisionLimits struct {
Deadline time.Time
MaxRetries int
AllowDispatch bool
MaxCostMicros int64
MaxTokens int64
RequireTelemetry bool
}
func DecisionLimitsForAuthority ¶
func DecisionLimitsForAuthority(authority Authority, limits DecisionLimits) DecisionLimits
type DispatchEnvelopeV1 ¶ added in v0.4.0
type DispatchEnvelopeV1 = core.DispatchV1
DispatchEnvelopeV1 is the orchestration name for the shared core wire contract. Keeping the type in core prevents CLI, MCP, and remote hosts from growing different pinning rules.
func NewDispatchEnvelope ¶ added in v0.4.0
func NewDispatchEnvelope(root string, m MissionV1) (DispatchEnvelopeV1, error)
func PinDispatchEnvelope ¶ added in v0.4.0
func PinDispatchEnvelope(root string, m *MissionV1) (DispatchEnvelopeV1, error)
PinDispatchEnvelope copies immutable checksum into mission. Mission remains pending; this function grants no completion authority.
type DispatchPins ¶ added in v0.4.0
type Dispatcher ¶
type Dispatcher interface {
Dispatch(task core.FrontierTask) error
}
type GateSeverity ¶
type GateSeverity string
const ( GateLow GateSeverity = "low" GateMedium GateSeverity = "medium" GateHigh GateSeverity = "high" GateCritical GateSeverity = "critical" )
type HeartbeatV1 ¶ added in v0.4.0
type Lease ¶
type Lease struct {
LeaseID string `json:"lease_id,omitempty"`
MissionID string `json:"mission_id,omitempty"`
TaskID string `json:"task_id"`
Attempt int `json:"attempt,omitempty"`
WorkerID string `json:"worker_id"`
IssuedAt time.Time `json:"issued_at,omitempty"`
ExpiresAt time.Time `json:"expires_at"`
PolicyDigest string `json:"policy_digest,omitempty"`
DispatchDigest string `json:"dispatch_digest,omitempty"`
State LeaseState `json:"state,omitempty"`
RevocationReason string `json:"revocation_reason,omitempty"`
Authority core.AuthorityV1 `json:"authority"`
Retries int `json:"retries"`
}
func CancelLease ¶ added in v0.4.0
func ClaimMission ¶ added in v0.4.0
func RenewLease ¶ added in v0.4.0
type LeaseState ¶ added in v0.4.0
type LeaseState string
const ( LeaseActive LeaseState = "active" LeaseRevoked LeaseState = "revoked" LeaseExpired LeaseState = "expired" )
type MissionLimits ¶ added in v0.4.0
type MissionStatus ¶ added in v0.4.0
type MissionStatus string
const ( MissionPending MissionStatus = "pending" MissionDelivered MissionStatus = "delivered" MissionClaimed MissionStatus = "claimed" MissionActive MissionStatus = "active" MissionReported MissionStatus = "reported" MissionExpired MissionStatus = "expired" MissionCancelled MissionStatus = "cancelled" MissionEscalated MissionStatus = "escalated" MissionTerminal MissionStatus = "terminal" )
type MissionV1 ¶ added in v0.4.0
type MissionV1 struct {
ProtocolVersion string `json:"protocol_version"`
SessionID string `json:"session_id"`
MissionID string `json:"mission_id"`
SpecSlug string `json:"spec_slug"`
TaskID string `json:"task_id"`
Attempt int `json:"attempt"`
Role string `json:"role"`
AuthorityRef string `json:"authority_ref"`
DeclaredFiles []string `json:"declared_files"`
Acceptance []string `json:"acceptance"`
Verify string `json:"verify"`
ContextRef string `json:"context_ref"`
ContextDigest string `json:"context_digest"`
ConfigDigest string `json:"config_digest"`
PaletteDigest string `json:"palette_digest"`
PolicyDigest string `json:"policy_digest"`
SubjectHead string `json:"subject_head"`
DispatchDigest string `json:"dispatch_digest,omitempty"`
DiffDigest string `json:"diff_digest,omitempty"`
RouteClass string `json:"route_class"`
RouteReason string `json:"route_reason"`
Limits MissionLimits `json:"limits"`
IssuedAt time.Time `json:"issued_at"`
ExpiresAt time.Time `json:"expires_at"`
Status MissionStatus `json:"status"`
}
type ObservableEvent ¶ added in v0.4.0
type ObservableEvent struct {
RunID string `json:"run_id"`
EventID string `json:"event_id"`
Seq int `json:"seq"`
Tool string `json:"tool"`
ArgClass string `json:"arg_class,omitempty"`
ResultClass string `json:"result_class,omitempty"`
Paths []string `json:"paths,omitempty"`
Time string `json:"time"`
Actor string `json:"actor"`
Correlation string `json:"correlation,omitempty"`
}
ObservableEvent is one run-scoped, externally observable step in a worker trajectory (spec 04 R4.1). It records what was done — tool/action identity, sanitized argument/result *class* (never raw bodies), affected paths, when, who, and a correlation id — and nothing about how the agent reasoned. There is deliberately no field for prompts, chain-of-thought, or secrets: hidden reasoning is rejected at the parse boundary, not masked (R4.1).
func ParseTrace ¶ added in v0.4.0
func ParseTrace(raw []byte) ([]ObservableEvent, error)
ParseTrace reads a JSONL trace, rejecting any line that carries a forbidden field, then normalizes the events. It returns a stable ordered error naming the first offending line/field, or the normalized events.
type ObservationV1 ¶ added in v0.4.0
type ObservationV1 struct {
Version string `json:"version"`
Known bool `json:"known"`
Source string `json:"source,omitempty"`
Unit string `json:"unit,omitempty"`
CostMicros int64 `json:"cost_micros,omitempty"`
Tokens int64 `json:"tokens,omitempty"`
DurationMs int64 `json:"duration_ms,omitempty"`
Route *RouteFact `json:"route,omitempty"`
}
ObservationV1 carries bounded audit facts. It is never evidence or proof of completion. Cost uses integer micro-units; Known distinguishes zero from absent.
func NormalizeObservation ¶ added in v0.4.0
func NormalizeObservation(in ObservationV1) (ObservationV1, error)
type RecoveryAction ¶ added in v0.4.0
type RecoveryAction string
const ( RecoveryRetry RecoveryAction = "retry" RecoveryEscalate RecoveryAction = "escalate" )
type RecoveryDecision ¶ added in v0.4.0
type RecoveryDecision struct {
Action RecoveryAction
Retry bool
Owner string
Reason string
}
func ClassifyRecovery ¶ added in v0.4.0
func ClassifyRecovery(l Lease, p RetryPolicy) RecoveryDecision
type ResumePlan ¶
type ResumePlan struct {
Reissue bool
Mission Checkpoint
Conflict string
}
ResumePlan is the reconciliation of the write-ahead checkpoint against the ACP ledger (spec 07 R3/R4). Exactly one of the outcomes holds:
- Conflict != "": the checkpoint and ledger disagree irreconcilably; resume must refuse (exit 1) rather than guess.
- Reissue == true: the checkpoint's mission never reached the ledger (crash between checkpoint and dispatch); resume re-issues exactly that dispatch.
- both zero: the checkpoint's mission is already in the ledger (or there is no outstanding mission); resume only reconstructs session state.
func PlanResume ¶
func PlanResume(cp Checkpoint, cpExists bool, events []ACPEvent) ResumePlan
PlanResume computes the resume plan from the checkpoint and the ledger. It is pure: the caller supplies the loaded checkpoint (with existence flag) and the ledger events.
type RetryPolicy ¶ added in v0.4.0
type Session ¶
type Session struct {
// ID is a stable identifier minted at `brain start`, used to derive
// deterministic mission ids (session/step/task) that survive a resume.
ID string `json:"id,omitempty"`
Revision int64 `json:"revision"`
State SessionState `json:"state,omitempty"`
// Step is the controller tick counter, incremented per dispatch. It feeds the
// mission id so a re-issued dispatch after resume reuses the same id.
Step int `json:"step,omitempty"`
Leases []Lease `json:"leases,omitempty"`
PendingMissions []MissionV1 `json:"pending_missions,omitempty"`
Missions []MissionV1 `json:"missions,omitempty"`
}
func LoadSession ¶
func ReconcileSession ¶ added in v0.4.0
func ReconcileSession(s Session, cp Checkpoint, cpExists bool, events []ACPEvent) (Session, bool, error)
ReconcileSession projects a checkpoint and append-only ledger into session state. It is pure and idempotent, allowing callers to persist with CAS.
func (Session) IsTerminal ¶
IsTerminal reports whether the session refuses further step/run/resume.
func (Session) Status ¶
func (s Session) Status() SessionState
Status returns the effective lifecycle state, treating the empty zero value as running (pre-spec-07 compatibility).
type SessionState ¶
type SessionState string
SessionState is the controller lifecycle (spec 07 R2). The persisted state machine is running → {cancelled | complete}; both terminal states refuse further step/run. An empty state decodes as running so pre-spec-07 sessions stay valid. "crashed" is never persisted — it is derived by `brain status` from a checkpoint that outran the ledger (see DeriveStatus).
const ( SessionRunning SessionState = "running" SessionCancelled SessionState = "cancelled" SessionComplete SessionState = "complete" SessionCrashed SessionState = "crashed" )
func DeriveStatus ¶
func DeriveStatus(session Session, cp Checkpoint, cpExists bool, events []ACPEvent) SessionState
DeriveStatus is the effective status reported by `brain status`. A terminal session reports its persisted state. A running session whose checkpoint names a mission missing from the ledger is reported as crashed: the process died mid-dispatch and a resume is needed to converge (spec 07 R6).
type Snapshot ¶
type Snapshot struct {
Revision int64
Phase core.Phase
Records map[string]json.RawMessage
Frontier []core.FrontierTask
Leases []Lease
Now time.Time
CostMicros int64
Tokens int64
TelemetryKnown bool
// TelemetryTrusted is true only when the known cost derives entirely from
// trusted sources; a worker-reported accounting hint leaves it false so a
// brake fired on it is labelled untrusted (spec 07 R4.1, R4.3).
TelemetryTrusted bool
}
func Sense ¶
func Sense(state core.State, frontier []core.FrontierTask, leases []Lease, telemetry Telemetry, now time.Time) Snapshot
Sense builds the immutable decision snapshot. Cost/token accounting is populated only from accepted telemetry (see AccrueTelemetry): production and tests share one honest population path, and absent telemetry stays unknown rather than being zero-filled (spec 07 R4.1).
type Telemetry ¶ added in v0.4.0
Telemetry is the cost/token total accrued from accepted report observations. Known distinguishes an unknown total (nil) from a real zero — an honest cost brake never treats an absent measurement as zero. Trusted is true only when every contributing observation came from a trusted (non worker-self-reported) source; worker telemetry is an accounting hint (spec 07 R4.1, R4.3).
func AccrueTelemetry ¶ added in v0.4.0
AccrueTelemetry folds accepted report observations into one honest total. Only observations already accepted onto the ledger reach here, so production and tests share exactly one population path (R4.1). A single unknown observation makes the whole total unknown — it is never zero-filled — so the aggregate is Known only when every report is Known.
type WorkerReportV1 ¶ added in v0.4.0
type WorkerReportV1 struct {
MissionID string `json:"mission_id"`
LeaseID string `json:"lease_id"`
WorkerID string `json:"worker_id"`
TaskID string `json:"task_id"`
Attempt int `json:"attempt"`
Role string `json:"role"`
SubjectHead string `json:"subject_head"`
DispatchDigest string `json:"dispatch_digest,omitempty"`
VerifyRef string `json:"verify_ref"`
Status string `json:"status"`
Blocker string `json:"blocker,omitempty"`
NextAction string `json:"next_action,omitempty"`
}
type WorkerState ¶ added in v0.4.0
type WorkerState string
const ( WorkerStateActive WorkerState = "active" WorkerStateExpired WorkerState = "expired" )
func LeaseWorkerState ¶ added in v0.4.0
func LeaseWorkerState(lease Lease, now time.Time) WorkerState