Documentation
¶
Overview ¶
Package reconcile is the pure functional core for the server's gate/grant and execution-lifecycle state. It performs no I/O: Step takes an observed World plus a Signal and returns the new ChangeSet plus the minimal set of Actions the imperative shell must execute. See docs/superpowers/specs/2026-06-15-reconciler-core-design.md.
Index ¶
- Constants
- func IsRunExecutionID(id string) bool
- func MarshalEvent(e Event) (string, []byte, error)
- func MarshalSnapshot(cs ChangeSet) ([]byte, error)
- func Requester(g GateState) string
- type Action
- type AdminCheckOverridden
- type AdminExecutionCancelled
- type AdminGateSatisfied
- type AdminGrantReleased
- type AdoptRun
- type ApplySucceeded
- type BlockReason
- type Blocked
- type Blocker
- type CancelRun
- type ChangeSet
- type CheckOverride
- type ClaimReleased
- type Classified
- type Clean
- type Collision
- type Event
- type GateBlocked
- type GatePassed
- type GateReleased
- type GateSatisfied
- type GateState
- type GateTargetRequested
- type GateTick
- type GrantCleared
- type GrantObserved
- type GrantsObserved
- type InboundBuild
- type Lease
- type NotClassified
- type ObservedGrant
- type PRClosed
- type PRClosedRecorded
- type Pending
- type PostCommitStatus
- type PublishSSE
- type ReleaseClaim
- type RenderCheckRun
- type RequestGrant
- type RevokeGrant
- type Run
- type RunAdopted
- type RunCompleted
- type RunPhase
- type RunQueued
- type RunRequested
- type RunStartFailed
- type RunStartResult
- type RunStarted
- type RunSuperseded
- type RunnerFinalize
- type Satisfied
- type Signal
- type StartRun
- type Target
- type TargetRevoked
- type World
Constants ¶
const ( RunKindPlan = "plan" RunKindApply = "apply" )
Run kinds — the two CI run flavors serve can trigger.
const RunExecutionIDPrefix = "run-"
RunExecutionIDPrefix marks serve-minted run execution ids (see runExecutionID). The store's stuck-run query and the queued check render key off it to distinguish serve-initiated runs from runner-created executions.
Variables ¶
This section is empty.
Functions ¶
func IsRunExecutionID ¶ added in v0.22.0
IsRunExecutionID reports whether id was minted by runExecutionID.
func MarshalEvent ¶ added in v0.17.0
MarshalEvent serializes a domain Event to a neutral (typeTag, JSON) pair. The tag is the variant's Go type name; the data is its JSON. Neutral types only — no store dependency. Keep this switch and UnmarshalEvent in sync with the Event variants in event.go (the round-trip-every-variant test enforces it).
func MarshalSnapshot ¶ added in v0.17.0
MarshalSnapshot serializes a folded ChangeSet (the GateState sum type is encoded with a discriminator). Neutral []byte — no store dependency.
Types ¶
type Action ¶
type Action interface {
// contains filtered or unexported methods
}
Action is an effect the pure core wants performed but cannot do itself.
type AdminCheckOverridden ¶ added in v0.28.0
type AdminExecutionCancelled ¶ added in v0.28.0
type AdminGateSatisfied ¶ added in v0.28.0
type AdminGrantReleased ¶ added in v0.28.0
type AdoptRun ¶ added in v0.24.0
AdoptRun materializes the execution row + check run for a run bound to a build serve did NOT launch (RunAdopted), pointing them at the existing BuildRef. Unlike StartRun it never calls the executor — the build already exists. No result.
type ApplySucceeded ¶
type ApplySucceeded struct{}
type BlockReason ¶
type BlockReason string
const ( ReasonDenied BlockReason = "denied" ReasonExpired BlockReason = "expired" ReasonRevoked BlockReason = "revoked" ReasonSlotForeign BlockReason = "slot_foreign_open" // another open PR holds the slot (⑥) ReasonSlotSelf BlockReason = "slot_self" // same PR, another env, holds the slot (⑥) ReasonBackendError BlockReason = "backend_error" )
type Blocker ¶
type Blocker struct {
Reason BlockReason
ByPR int // slot blocker's PR (0 if N/A)
ByEnv string // slot blocker's environment
}
Blocker explains why a gate is Blocked.
type CancelRun ¶ added in v0.22.0
type CancelRun struct {
Kind string
OldExecutionID string
OldBuildRef string
NewExecutionID string
}
CancelRun supersedes an in-flight run: the shell marks OldExecutionID superseded by NewExecutionID in the store and best-effort cancels the old build when a BuildRef exists. Idempotent; no result.
type ChangeSet ¶
type ChangeSet struct {
PR int
Environment string
Gate GateState
CheckOverride *CheckOverride
// Runs tracks serve-initiated CI runs, keyed by kind (plan/apply). Only
// the run-start lifecycle lives here (webhook → build started); once the
// runner reports, the internal/execution aggregate (stream "run:<execID>")
// carries the execution facts.
Runs map[string]Run
}
ChangeSet is the reconciliation unit: one PR's work in one environment.
func Evolve ¶ added in v0.17.0
Evolve applies a single domain Event to a ChangeSet, returning the new state. It is total (never panics on any state/event combination), pure (no I/O), and deterministic. It is the fold half of the Decider pattern: Decide emits Events, Evolve reduces them into state.
func UnmarshalSnapshot ¶ added in v0.17.0
UnmarshalSnapshot reverses MarshalSnapshot.
type CheckOverride ¶ added in v0.28.0
type ClaimReleased ¶ added in v0.17.0
type Classified ¶ added in v0.17.0
type Classified struct{ Gates []events.GateTarget }
Classified establishes/replaces the gate target set. Evolve carries forward still-live prior grants (gap ② anti-clobber); Decide has already resolved the effective set (plan-authoritative vs apply-recovery union).
type Collision ¶
type Collision struct {
ByPR int
ByEnv string
BySelf bool // ByPR == this changeset's PR (different env)
ByPRAbandoned bool // shell looked up the blocker PR's GitHub state (closed && !merged)
}
Collision describes a slot blocker the shell already resolved against GitHub.
type Event ¶ added in v0.17.0
type Event interface {
// contains filtered or unexported methods
}
Event is a past-tense domain fact produced by Decide and folded by Evolve. Events are domain facts ONLY — presentation (check run / SSE) is never an Event; React projects that from the event stream. See the Phase 3 design.
type GateBlocked ¶ added in v0.17.0
type GateBlocked struct {
Reason BlockReason
ByPR int
ByEnv string
}
type GatePassed ¶ added in v0.17.0
type GatePassed struct{}
GatePassed and GateReleased both fold the gate to Clean. They are distinct facts so React can present them differently: GatePassed (plan-clean / nothing to gate) renders success; GateReleased (post-apply cleanup) renders nothing.
type GateReleased ¶ added in v0.17.0
type GateReleased struct{}
type GateSatisfied ¶ added in v0.17.0
type GateSatisfied struct{}
type GateState ¶
type GateState interface {
// contains filtered or unexported methods
}
GateState is a sum type: a gate is EXACTLY one of these.
type GateTargetRequested ¶ added in v0.17.0
type GateTargetRequested struct{ Class, Target, Requester string } // Requester pins the lease (step.go:140)
type GateTick ¶
type GateTick struct{ Grants []ObservedGrant }
GateTick is the periodic backstop re-observation; Grants is a full re-list of the changeset's targets. Processed identically to GrantsObserved.
type GrantCleared ¶ added in v0.17.0
type GrantCleared struct{ Class, Target string }
type GrantObserved ¶ added in v0.17.0
type GrantObserved struct {
Class, Target, Name string
State approval.GrantState
Requester string
}
type GrantsObserved ¶
type GrantsObserved struct{ Grants []ObservedGrant }
GrantsObserved carries grant observations for THIS changeset: either the results of RequestGrant actions (fixpoint feedback) or a re-list. Grants not mentioned are left unchanged.
type InboundBuild ¶ added in v0.24.0
type InboundBuild struct {
Kind string // RunKindPlan | RunKindApply
SHA string // resolved commit sha of the build
BuildRef string // Cloud Build build id
}
InboundBuild is an observed Cloud Build lifecycle event for a build serve may NOT have launched — a native-check Re-run or a console rebuild. The shell has already correlated it to this ChangeSet's (pr, env) and derived the run Kind (from the trigger) + the resolved commit SHA. Decide reconciles it onto the PR's stuck run; the fail-safe backstop for the adopted build stays the watchdog.
type Lease ¶
type Lease struct{ Requester string }
Lease is the pooled requester identity leased once per ChangeSet. Empty Requester means undecided.
type NotClassified ¶
type NotClassified struct{} // never planned → apply fails closed
type ObservedGrant ¶
type ObservedGrant struct {
Class string
Target string
Name string // backend-assigned id ("" if none)
State approval.GrantState // "" == no grant present for this changeset
Requester string // leased identity ("" if N/A)
Collision *Collision // set when a RequestGrant hit a SlotCollisionError
}
ObservedGrant is one grant fact the shell gathered for a (class,target).
type PRClosedRecorded ¶ added in v0.17.0
type PRClosedRecorded struct{}
PRClosedRecorded marks a PR-closure teardown so React renders SSE-only (no check run), distinct from an externally-observed revocation. Named *Recorded to avoid colliding with the PRClosed Signal.
type PostCommitStatus ¶
type PostCommitStatus struct {
State string // "success" | "failure" | "pending"
Description string
}
PostCommitStatus posts the commit status. Pure output; no result.
type PublishSSE ¶
type PublishSSE struct{}
PublishSSE notifies the live-page hub that state changed. Pure output.
type ReleaseClaim ¶ added in v0.16.2
ReleaseClaim releases the merge-lock stack claim a PR holds in an environment. Emitted post-apply (the apply is done, so the claim it held is no longer needed). The shell deletes the claims and re-evaluates the env's held apply-lock checks (cross-PR I/O). Idempotent.
type RenderCheckRun ¶
type RenderCheckRun struct {
Terminal bool
Conclusion string // "success" | "action_required" | "failure" | "" (in-progress)
}
RenderCheckRun re-renders the GitHub check run from current state. Pure output; no result.
type RequestGrant ¶
RequestGrant asks the backend to ensure an open grant. It YIELDS a result (grant name + leased requester, or a Collision) the shell feeds back as a GrantsObserved signal. Requester pins the lease; "" lets the backend lease.
type RevokeGrant ¶
RevokeGrant revokes the open grant for (class,target,PR,environment). Idempotent; produces no result. PR/Environment default to the changeset's when zero/empty but are set explicitly when revoking a foreign slot blocker.
type Run ¶ added in v0.22.0
type Run struct {
ExecutionID string
Kind string // RunKindPlan | RunKindApply
SHA string
Branch string
Attempt int // bumps on rerun / retry-after-failure (part of the deterministic execution id)
BuildRef string // executor backend reference ("" until started)
Phase RunPhase //
}
Run is the serve-initiated lifecycle of one CI run: requested by a webhook, queued (execution + check run exist), started (build accepted by the executor backend), or terminally start_failed / superseded.
type RunAdopted ¶ added in v0.24.0
type RunAdopted struct {
Kind string
ExecutionID string
SHA string
Branch string
Attempt int
BuildRef string
}
RunAdopted records serve binding a run to a build it did NOT launch (a rerun created outside triggers.run). Unlike RunQueued it carries an existing BuildRef and does NOT trigger StartRun — the build already exists. Evolve folds it to a Started-phase Run; React materializes the execution row + check via AdoptRun. The watchdog then tracks BuildRef and fails it if it finishes without the runner ever reporting (fail-safe backstop).
type RunCompleted ¶ added in v0.22.0
RunCompleted records the runner taking over and finalizing: the run-start lifecycle is over. Also emitted when a "start-failed" run finalizes anyway (a client-side start timeout whose build actually ran) — the finalize proves the start happened, and folding this stops the failure projection.
type RunPhase ¶ added in v0.22.0
type RunPhase string
RunPhase is the run-start lifecycle phase.
const ( RunPhaseQueued RunPhase = "queued" // execution created, StartRun pending/issued RunPhaseStarted RunPhase = "started" // executor accepted the build RunPhaseStartFailed RunPhase = "start_failed" // executor refused / start errored RunPhaseSuperseded RunPhase = "superseded" // a newer SHA replaced this run RunPhaseCompleted RunPhase = "completed" // the runner took over and finalized )
type RunQueued ¶ added in v0.22.0
RunQueued records that a run request was accepted: the shell creates the execution row + a "queued" check run and issues StartRun. ExecutionID is minted deterministically by Decide (pr/env/kind/sha/attempt — the pure core cannot use randomness).
type RunRequested ¶ added in v0.22.0
type RunRequested struct {
Kind string // RunKindPlan | RunKindApply
SHA string
Branch string
Rerun bool
}
RunRequested asks for a CI run: pull_request opened/synchronize → plan for the head SHA; push to main → apply for the merge commit; check_run rerequested → the same kind again with Rerun set (forces a new attempt even for an already-seen SHA).
type RunStartFailed ¶ added in v0.22.0
RunStartFailed records the executor refusing / erroring — surfaced as a terminal check failure (vs the pre-driver era's silent nothing).
type RunStartResult ¶ added in v0.22.0
RunStartResult is the fixpoint feedback from a StartRun action (like GrantsObserved for RequestGrant): the executor either accepted the build (BuildRef) or failed (Err).
type RunStarted ¶ added in v0.22.0
RunStarted records the executor accepting the build.
type RunSuperseded ¶ added in v0.22.0
type RunSuperseded struct {
Kind string
OldExecutionID string
OldBuildRef string
NewExecutionID string
NewSHA string
}
RunSuperseded records a newer SHA replacing an in-flight run (plan only — applies are never superseded). The shell cancels the old build (when a BuildRef exists) and marks the old execution superseded by the new one.
type RunnerFinalize ¶
type RunnerFinalize struct {
Gates []events.GateTarget // (class,target) pairs needing approval
// ApplyContext marks a finalize from the post-merge apply (apply/<env>) rather
// than the plan gate. An apply finalize is a RECOVERY signal, not an authority:
// it may add/refresh gate targets but must never weaken a gate the plan already
// established (issue #103) — so decideFinalize unions the prior targets and never
// prunes when this is set. A plan finalize (false) stays authoritative.
ApplyContext bool
}
RunnerFinalize is the gate-lifecycle signal derived from a runner Finalize report: execution-lifecycle facts (init/phase/tick/terminal/annotate) are handled by the internal/execution aggregate; this signal carries only what decideFinalize reads to establish/advance the gate.
type Signal ¶
type Signal interface {
// contains filtered or unexported methods
}
Signal is the union of everything that can drive a ChangeSet.
type StartRun ¶ added in v0.22.0
type StartRun struct {
Kind string // RunKindPlan | RunKindApply
SHA string
Branch string
ExecutionID string
}
StartRun asks the executor backend to start a CI build for this changeset. It YIELDS a result (build ref or error) the shell feeds back as a RunStartResult signal. The shell also creates the execution row + "queued" check run before starting, so feedback appears within the webhook turnaround.
type Target ¶
type Target struct {
Class string
Target string
GrantName string // backend-assigned id; "" until created
Grant approval.GrantState // observed grant lifecycle; "" == no grant/absent
}
Target is one (class,target) gate and its observed grant.
type TargetRevoked ¶ added in v0.17.0
type World ¶
World is the scoped, immutable snapshot the shell hands to Step/Decide. Prior is the current persisted state for (PR, Environment); Version is the event stream's current version (0 for an empty stream), used for optimistic- concurrency append. Observations ride on the Signal. The core performs no I/O.