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 ¶
- func ApplyAllowed(g GateState) bool
- func DisplayStatus(s Stack, g GateState) events.Status
- func MarshalEvent(e Event) (string, []byte, error)
- func MarshalSnapshot(cs ChangeSet) ([]byte, error)
- func Requester(g GateState) string
- func Step(w World, s Signal) (ChangeSet, []Action)
- func YieldsResult(a Action) bool
- type Action
- type ApplySucceeded
- type BlockReason
- type Blocked
- type Blocker
- type ChangeSet
- type ClaimReleased
- type Classified
- type Clean
- type Collision
- type Event
- type Execution
- type ExecutionFailed
- type ExecutionStarted
- type GateBlocked
- type GatePassed
- type GateReleased
- type GateSatisfied
- type GateState
- type GateTargetRequested
- type GateTick
- type GrantCleared
- type GrantObserved
- type GrantsObserved
- type Lease
- type NotClassified
- type ObservedGrant
- type PRClosed
- type PRClosedRecorded
- type Pending
- type PhaseChanged
- type PostCommitStatus
- type PublishSSE
- type ReleaseClaim
- type RenderCheckRun
- type RequestGrant
- type RevokeGrant
- type RunnerFinalize
- type RunnerInit
- type RunnerPhase
- type RunnerUpdate
- type Satisfied
- type Signal
- type Stack
- type StackStatusChanged
- type StacksClassified
- type Target
- type TargetRevoked
- type World
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyAllowed ¶
ApplyAllowed is the fail-closed apply-gate verdict: only Clean or Satisfied permit apply; NotClassified, Pending, and Blocked deny it.
func DisplayStatus ¶
DisplayStatus is the derived per-stack status shown in the UI/check run. The runner-told status wins when terminal (failed/moving); otherwise the gating overlay (gated/safe) is derived from the ChangeSet's GateState. This is the single source of the gated/safe distinction — it is never stored separately.
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.
func Step ¶
Step is the one pure front door. Decide computes the domain facts an incoming Signal produces against the observed World; Evolve folds them into the new ChangeSet (the replay path); React projects the Actions the shell must run. Deterministic; no I/O; safe to call repeatedly.
func YieldsResult ¶
YieldsResult reports whether an action produces a GrantsObserved on the fixpoint loop (only RequestGrant does). The shell uses this to decide when the fixpoint has converged.
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 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 ChangeSet ¶
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 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 Execution ¶
type Execution struct {
ID string
Repo string
SHA string
LogURL string
Phase events.Phase
Stacks []Stack
}
Execution is the plan/apply run for the ChangeSet (edge-triggered facts).
type ExecutionFailed ¶ added in v0.17.0
type ExecutionFailed struct{}
type ExecutionStarted ¶ added in v0.17.0
type ExecutionStarted struct{ Exec Execution }
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 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 PhaseChanged ¶ added in v0.17.0
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 RunnerFinalize ¶
type RunnerFinalize struct {
Failed bool
ReportMarkdown string
Projects map[string]string // stack path → grouping/target key
Categories map[string][]events.Category // stack path → matched categories
Moving []string // stack paths adopting via cross-state move
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
}
type RunnerInit ¶
type RunnerInit struct{ Exec Execution }
type RunnerPhase ¶
type Signal ¶
type Signal interface {
// contains filtered or unexported methods
}
Signal is the union of everything that can drive a ChangeSet.
type Stack ¶
type Stack struct {
Path string
Project string
RunStatus events.Status // pending|running|planned|failed|moving (never gated/safe)
Detail string
Categories []events.Category
}
Stack is one node. RunStatus holds ONLY the runner-told statuses; the gated/safe overlay is derived from the ChangeSet's GateState (see project.go).
type StackStatusChanged ¶ added in v0.17.0
type StacksClassified ¶ added in v0.17.0
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.