Documentation
¶
Overview ¶
Package shadowconsumer is the Epic 69 S1 shadow consumer (US-69.5): the API subscribes on-demand to a pod's ABI stream with the reference client, folds it, and diffs the fold against its own API-side dialect derivation (ReferenceFold — the proxy-tracker semantics). Zero unexplained divergence across the scenario suite is the S1 exit.
Shadow only: nothing here feeds a production traffic path. The package is deliberately disposable after S1 (design 0055: "only the comparator is disposable").
Index ¶
- Constants
- type ABISource
- type Comparator
- func (c *Comparator) CompareNow() int
- func (c *Comparator) Converged() bool
- func (c *Comparator) Counts() map[string]int64
- func (c *Comparator) Debug() string
- func (c *Comparator) NoteGenerationReseed(sessionBusy map[string]bool)
- func (c *Comparator) NoteHarnessDeath()
- func (c *Comparator) ObserveABI(f *Fold)
- func (c *Comparator) ObserveReference(ref ReferenceState)
- func (c *Comparator) Report() string
- func (c *Comparator) SeqStallSeconds() float64
- func (c *Comparator) SeqStalled() bool
- func (c *Comparator) SetReferenceSource(r *ReferenceFold)
- func (c *Comparator) SetStallThreshold(d time.Duration)
- func (c *Comparator) Unexplained() int
- func (c *Comparator) WithDivergenceHook(fn func(class string)) *Comparator
- type Divergence
- type Fold
- type Recorder
- type ReferenceFold
- type ReferenceSession
- type ReferenceState
Constants ¶
const ( ClassBusyMismatch = "busy_mismatch" ClassPartMismatch = "part_mismatch" ClassSessionSet = "session_set_mismatch" ClassSeqNonMonotonic = "seq_non_monotonic" ClassSnapshotInconsist = "snapshot_inconsistency" )
Divergence classes (issue #1139): busy mismatch, part mismatch/loss, session-set mismatch, seq anomalies, snapshot inconsistency.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ABISource ¶
type ABISource struct {
// contains filtered or unexported fields
}
ABISource streams one pod's ABI surface via the reference client.
type Comparator ¶
type Comparator struct {
// contains filtered or unexported fields
}
Comparator diffs the ABI fold against the reference derivation and tracks seq-stall observability (the 0050 D1 progress signal).
func NewComparator ¶
func NewComparator(rec *Recorder) *Comparator
func (*Comparator) CompareNow ¶
func (c *Comparator) CompareNow() int
CompareNow diffs the two folds at a checkpoint (scenario boundaries, quiescent polls) and records divergences. Returns the unexplained count. A checkpoint against a still-converging pair records NOTHING: the ABI seq counts a superset of the reference's projectable events, so a seq-based lag guard cannot prove per-session quiescence — only agreement can.
func (*Comparator) Converged ¶
func (c *Comparator) Converged() bool
Converged reports whether both sides have been observed and currently agree (used by the scenario harness's eventual assertions).
func (*Comparator) Counts ¶
func (c *Comparator) Counts() map[string]int64
Counts returns divergence counts per class (the shadow_divergence_total backing data).
func (*Comparator) Debug ¶
func (c *Comparator) Debug() string
Debug renders the current both-sides state (harness failure dumps).
func (*Comparator) NoteGenerationReseed ¶
func (c *Comparator) NoteGenerationReseed(sessionBusy map[string]bool)
NoteGenerationReseed mirrors the API tracker's generation-change reconcile: the reference adopts store truth (busy per session, in-flight cleared); the ABI side reaches the same state via its own reseed.
func (*Comparator) NoteHarnessDeath ¶
func (c *Comparator) NoteHarnessDeath()
NoteHarnessDeath mirrors the API tracker's agent-death semantics: busy clears reference-side; the ABI side reaches the same state via reseed → store truth, so a transient busy mismatch inside the reseed window is EXPLAINED (not a divergence).
func (*Comparator) ObserveABI ¶
func (c *Comparator) ObserveABI(f *Fold)
ObserveABI records an ABI-side fold. Seq monotonicity is checked on every observation (cheap, ordering-valid); state diffs run only at checkpoints (CompareNow) — per-observation diffing across an async pipeline manufactures phantom divergences from propagation lag.
func (*Comparator) ObserveReference ¶
func (c *Comparator) ObserveReference(ref ReferenceState)
ObserveReference records an API-side derivation snapshot.
func (*Comparator) Report ¶
func (c *Comparator) Report() string
Report renders all divergences for failure messages and exit reports.
func (*Comparator) SeqStallSeconds ¶
func (c *Comparator) SeqStallSeconds() float64
SeqStallSeconds returns the current (or last) stall duration.
func (*Comparator) SeqStalled ¶
func (c *Comparator) SeqStalled() bool
SeqStalled reports whether no seq advance has been observed within the stall threshold while the consumer is running (M3.3: starvation must be observable, not guessed).
func (*Comparator) SetReferenceSource ¶
func (c *Comparator) SetReferenceSource(r *ReferenceFold)
SetReferenceSource lets the comparator read the current reference fold (used for harness-driven convergence checks).
func (*Comparator) SetStallThreshold ¶
func (c *Comparator) SetStallThreshold(d time.Duration)
SetStallThreshold tunes the seq-stall detector (soak scenarios).
func (*Comparator) Unexplained ¶
func (c *Comparator) Unexplained() int
Unexplained counts divergences not marked explained.
func (*Comparator) WithDivergenceHook ¶
func (c *Comparator) WithDivergenceHook(fn func(class string)) *Comparator
WithDivergenceHook installs a per-divergence callback (the API wiring uses it to increment shadow_divergence_total{class} on the process registry).
type Divergence ¶
type Divergence struct {
Time time.Time `json:"time"`
Class string `json:"class"`
Detail string `json:"detail"`
ABI string `json:"abi,omitempty"`
Ref string `json:"ref,omitempty"`
Explained bool `json:"explained"`
Note string `json:"note,omitempty"`
}
Divergence is one observed difference, recorded as an artifact.
type Fold ¶
type Fold = abiclient.SessionState
Fold is the ABI-side view handed to the comparator (an immutable abiclient snapshot).
type Recorder ¶
type Recorder struct {
// contains filtered or unexported fields
}
Recorder writes the scenario artifacts (issue #1139: "recorded streams + tracker state"): the raw dialect stream the harness fed, and every divergence observed. One directory per run.
func NewRecorder ¶
func (*Recorder) RecordDialect ¶
func (*Recorder) RecordDivergence ¶
func (r *Recorder) RecordDivergence(d Divergence)
type ReferenceFold ¶
type ReferenceFold struct {
// contains filtered or unexported fields
}
ReferenceFold is the API-side dialect fold — the same semantics the proxy tracker derives from raw opencode events (busy from session.status, in-flight parts from message.part.updated upserts), kept independent from the pod-side translation by construction (it consumes the DIALECT, not the contract).
func NewReferenceFold ¶
func NewReferenceFold(workspaceID string) *ReferenceFold
func (*ReferenceFold) ObserveDialect ¶
func (r *ReferenceFold) ObserveDialect(raw []byte)
ObserveDialect folds one raw opencode SSE payload.
func (*ReferenceFold) ObserveHarnessDeath ¶
func (r *ReferenceFold) ObserveHarnessDeath()
ObserveHarnessDeath drops every session record — the API tracker's onAgentDied semantics: after agent death the derived session set is not authoritative and is rebuilt from the store on the next reconcile (the same rule the ABI side enforces via reseed-from-store).
func (*ReferenceFold) ObserveReconcile ¶
func (r *ReferenceFold) ObserveReconcile(sessionBusy map[string]bool)
ObserveReconcile folds the API tracker's reconcile-on-generation-change: in-flight parts clear (live-turn state is not store truth) and busy follows the store. Mirrors proxy_events.go reconcileSessionState.
func (*ReferenceFold) Snapshot ¶
func (r *ReferenceFold) Snapshot() ReferenceState
type ReferenceSession ¶
ReferenceSession is one session's API-side derivation. PartIDs is the in-flight part set (distinct part IDs upserted, cleared on idle/death — comparable to the ABI fold's in-flight parts).
func (ReferenceSession) PartCount ¶
func (r ReferenceSession) PartCount() int
type ReferenceState ¶
type ReferenceState struct {
Sessions map[string]ReferenceSession
Observed int
}
ReferenceState is the API-side derivation snapshot (the tracker facts the comparator diffs against). Observed is the count of projectable events folded so far — the comparator's lag guard (the ABI fold arrives via the async stream; diffing against a stale fold would manufacture phantom divergences).