Documentation
¶
Overview ¶
Package contextmgr owns context preparation policy and provider-message conversion. Durable state remains in the dependency-neutral contextstate package.
Index ¶
- Constants
- Variables
- func BuildCommitRequest(_ context.Context, preparation Preparation, result TurnResult, ...) (contextstate.CommitRequest, error)
- func ClassifySummaryFailure(err error) string
- func CommitPreparation(ctx context.Context, request PublicationRequest) error
- func OmittedEvidence(input, retained []provider.Message) []string
- func PercentFloor(value, numerator, denominator int) int
- func ProjectSource(ctx context.Context, principal contextstate.Principal, ...) ([]contextstate.SourceEvent, []contextstate.PayloadRecord, error)
- func RetryableSummaryFailure(err error) bool
- type Calibration
- type CheckpointCandidate
- type CheckpointPublisher
- type CommitToken
- type ContextManager
- type ElisionStats
- type LLMSummaryProvider
- type PlanInput
- type PlanResult
- type PlannerInput
- type PlannerResult
- type Preparation
- type PreparationCommitter
- type PreparationManager
- type PrepareInput
- type PublicationRequest
- type SourceExcerpt
- type StructuralPreparationManager
- type Summarizer
- type Summary
- type SummaryBuildInput
- type SummaryEnvelope
- type SummaryProvider
- type SummaryRequest
- type SummaryRequestBuilder
- type TurnResult
- type TurnState
- func (t *TurnState) AddChangedSurface(surface string) error
- func (t *TurnState) AddDecision(decision string) error
- func (t *TurnState) AddEvidence(evidence string) error
- func (t *TurnState) AddOpenWork(work string) error
- func (t *TurnState) AddRisk(risk string) error
- func (t *TurnState) SetState(state string) error
- func (t *TurnState) Snapshot() (TurnStateSnapshot, error)
- type TurnStateSnapshot
- type UntrustedSummary
Constants ¶
const ( OutcomeComplete = "complete" OutcomeCancelled = "cancelled" OutcomeTruncated = "truncated" OutcomeUpstreamErr = "upstream-error" )
const ( // MaxSummaryFieldBytes bounds every individual summary envelope field, // including each list item. Host trackers and injection paths share it so // the loop and the validators cannot drift apart. MaxSummaryFieldBytes = 2 * 1024 // MaxSummaryItems bounds every summary envelope list. The turn-state // tracker and OmittedEvidence share it with the validators. MaxSummaryItems = 32 )
const ( SummaryReasonTimeout = "the summary call timed out" SummaryReasonTransport = "the summary call could not reach the provider" SummaryReasonCancelled = "the turn was cancelled before the summary returned" SummaryReasonReplyMalformed = "the summary reply was not valid summary JSON" SummaryReasonEchoMismatch = "the summary reply did not echo the request identity" SummaryReasonOutputTooLarge = "the summary reply exceeded its output bound" SummaryReasonRedactionRefused = "the summary was refused by the redaction policy" SummaryReasonPolicyRefused = "the summary policy is not enabled for this session" SummaryReasonBindingChanged = "the summary binding or policy changed mid-turn" SummaryReasonRequestInvalid = "the host could not build a valid summary request" SummaryReasonHostState = "the host turn state was unreadable" SummaryReasonMetadataTooLarge = "the summary metadata exceeded its persistence bound" SummaryReasonOverBudget = "the summary did not fit the remaining context budget" SummaryReasonUnclassified = "the summary call failed for an unclassified reason" )
Closed, content-free vocabulary of summary failure reasons. These constants are rendered verbatim in compaction event details and durable ledger records.
const MaxSummaryExcerptTotalBytes = 16 * 1024
MaxSummaryExcerptTotalBytes caps the whole source-excerpt section of one summary request (about 4k tokens): large enough to carry a real dropped segment, small enough that the summarize call stays cheap on every model.
const SummarySchemaVersion uint32 = 1
SummarySchemaVersion is the sealed summary envelope schema version minted by BuildSummaryRequest. ValidateSummary requires provider output to echo it.
Variables ¶
var ( ErrSummaryReplyMalformed = fmt.Errorf("%w: summary reply is not usable", contextstate.ErrInvalidDTO) ErrSummaryEchoMismatch = fmt.Errorf("%w: summary reply does not echo the request", contextstate.ErrInvalidDTO) ErrSummaryOutputTooLarge = fmt.Errorf("%w: summary output exceeds its bound", contextstate.ErrInvalidDTO) ErrSummaryRedactionRefused = fmt.Errorf("%w: summary rejected by redaction policy", contextstate.ErrInvalidDTO) )
Summary failure sentinels. Each wraps contextstate.ErrInvalidDTO so existing errors.Is(err, contextstate.ErrInvalidDTO) assertions continue to hold while allowing exact classification of the failure mode.
Functions ¶
func BuildCommitRequest ¶
func BuildCommitRequest(_ context.Context, preparation Preparation, result TurnResult, principal contextstate.Principal, expected contextstate.Revision, binding contextstate.BindingRevision) (contextstate.CommitRequest, error)
BuildCommitRequest is the only conversion from provider-facing turn state into the durable context contract. It validates all captured fences before constructing bytes that storage may publish.
func ClassifySummaryFailure ¶
ClassifySummaryFailure maps a summary error to one of the closed SummaryReason* constants. It never includes raw error text or model output in the returned reason.
func CommitPreparation ¶
func CommitPreparation(ctx context.Context, request PublicationRequest) error
CommitPreparation validates and summarizes before calling Store.Commit. Summary/provider failures therefore occur before any durable CAS attempt, and a persistence failure leaves the caller's preparation untouched.
func OmittedEvidence ¶
OmittedEvidence derives content-free summary evidence from the difference between the pre-compaction history and the retained preparation. Each item records only the role, the tool name (for tool results), and the size bucket of one omitted message - never Content, Arguments, digests, or identifiers, mirroring elisionNotice. The result is capped at MaxSummaryItems items and byte-deterministic for identical inputs.
Items are DISTINCT, in first-seen order. An item is content-free, so two dropped messages of the same role in the same size bucket render the same string - the ordinary case once a compaction drops several similar messages, not an edge case. The summary envelope validator refuses duplicate evidence, and every caller degrades silently on a build error, so emitting duplicates here meant automatic compaction produced no summary at all while still reporting success. The cap therefore bounds distinct items: applying it before dedup let one repeated item consume the whole budget and report a single fact.
func PercentFloor ¶
PercentFloor returns floor(value * numerator / denominator) without overflowing on large token budgets. Shared by Plan's trigger/target math and any other caller that needs the same hysteresis shape (trigger at numerator/denominator of a budget, prune down to a lower target).
func ProjectSource ¶
func ProjectSource(ctx context.Context, principal contextstate.Principal, messages []provider.Message, firstSequence uint64, policy contextstate.RedactionPolicy) ([]contextstate.SourceEvent, []contextstate.PayloadRecord, error)
ProjectSource is the allowlisted source boundary for a completed turn. It records message metadata and, when the workspace explicitly configures a redaction classifier, bounded sanitized payloads. System prompts, tool-call arguments, and hidden provider fields never cross this boundary.
func RetryableSummaryFailure ¶
RetryableSummaryFailure reports whether a summary error represents a transient failure that should be retried. Permanent failures (reply shape errors, redaction refusal, stale bindings, policy refusal, cancellation) return false immediately.
Types ¶
type Calibration ¶
type Calibration struct {
// Alpha is the smoothing factor (0 < alpha <= 1). Higher values
// react faster to changes. Defaults to 0.2.
Alpha float64
// Ratio is the current correction factor: reported/estimated.
// Bounded to [calibrationMinRatio, calibrationMaxRatio] once samples
// exist. The zero value is 0.0, which means no correction (treated as
// 1.0 everywhere it is applied).
Ratio float64
// Samples is the number of updates applied.
Samples int
}
Calibration maintains a per-binding (provider+model) rolling correction ratio between estimated and provider-reported token usage. It uses EWMA (exponentially weighted moving average) to smooth noise from individual requests while tracking systematic drift in the len(s)/4 heuristic.
The zero value is valid and means unity (no correction): Ratio is 0.0, which applyCalibration and the loop's emission path treat as 1.0.
func (Calibration) Apply ¶
func (c Calibration) Apply(estimated int) int
Apply scales an estimated token count by this calibration's correction ratio, exactly as the planner does when it scores a history against the compaction trigger.
Every surface that reports "how full is the context" must go through this method. The planner compares a CALIBRATED cost against the trigger (planner.go's Plan), so a gauge that divides an UNCALIBRATED estimate by the same budget is measuring the same history with a different ruler: with a ratio below 1.0 the displayed percentage runs ahead of the trigger and can sit far above 100% while the planner correctly sees a history below the threshold and never compacts. That disagreement is what this method exists to make impossible.
A calibration with no samples applies no correction, matching PlanInput.CalibrationRatio, which callers leave unset until the first estimate-vs-actual observation lands.
func (*Calibration) Update ¶
func (c *Calibration) Update(estimated, reported int)
Update incorporates a new (estimated, reported) observation into the EWMA. If estimated is zero, the update is skipped to avoid division by zero.
type CheckpointCandidate ¶
type CheckpointCandidate struct {
ActiveContext []byte
SummaryMetadata []byte
SourceEvents []contextstate.SourceEvent
Payloads []contextstate.PayloadRecord
SourceRange contextstate.SourceRange
}
func (CheckpointCandidate) CandidateAlgorithm ¶
func (c CheckpointCandidate) CandidateAlgorithm() string
type CheckpointPublisher ¶
type CheckpointPublisher interface {
Commit(context.Context, Preparation, TurnResult) error
}
type CommitToken ¶
type CommitToken struct {
Principal contextstate.Principal
Revision contextstate.Revision
Binding contextstate.BindingRevision
WorktreeInstance contextstate.WorktreeInstance
Range contextstate.SourceRange
IdempotencyKey string
}
type ContextManager ¶
type ContextManager struct {
PreparationManager PreparationManager
CheckpointPublisher CheckpointPublisher
// Summarizer is the optional LLM summarizer wiring point. Nil keeps every
// path structural-only (today's production state: no SummaryProvider
// exists). It is copied into chat turn configurations so both the agent
// loop and plain chat can inject a validated summary at the request
// boundary; the checkpoint committer reaches it through the
// PreparationCommitter fields.
Summarizer *Summarizer
Enabled bool
// fixed, classified, content-free string set once at session setup (see
// internal/cli's summaryDisabledReason). Every compaction path in the
// session's lifetime reads it to report a real cause instead of a bare
// "not summarized" boolean. Empty when Summarizer is configured.
SummaryUnavailableReason string
// UsageWriter is the optional durable usage-measurement sink. Nil keeps
// usage events ephemeral (bus-only, today's production state everywhere
// this isn't wired). Constructed once per session, alongside Summarizer,
// and copied into agent.Options per turn the same way.
UsageWriter usage.UsageWriter
}
func (ContextManager) Commit ¶
func (m ContextManager) Commit(ctx context.Context, preparation Preparation, result TurnResult) error
func (ContextManager) Prepare ¶
func (m ContextManager) Prepare(ctx context.Context, input PrepareInput) (Preparation, error)
type ElisionStats ¶
ElisionStats is a content-free aggregate of tool-result replacements made during one compaction plan. Bytes is the sum of original Content lengths.
type LLMSummaryProvider ¶
type LLMSummaryProvider struct {
// contains filtered or unexported fields
}
LLMSummaryProvider adapts one provider.Completer to the SummaryProvider contract. It renders a host-authored prompt from the sealed envelope, calls the completer once, and decodes one strict JSON reply. It never logs and never retries (retry policy lives in Summarizer.Summarize). Any error lets the caller degrade to structural-only compaction.
func NewLLMSummaryProvider ¶
func NewLLMSummaryProvider(completer provider.Completer, sessionID string) (LLMSummaryProvider, error)
NewLLMSummaryProvider binds one completer to one session. A nil completer is refused the same way NewSummarizer refuses a nil provider. sessionID may be empty for callers with no session concept.
func (LLMSummaryProvider) Summarize ¶
func (p LLMSummaryProvider) Summarize(ctx context.Context, request SummaryRequest) (Summary, error)
Summarize runs one non-stream completion and decodes the reply. It checks the two mandated echoes before it returns. ValidateSummary in Summarizer.Summarize owns the full field, redaction, and size validation. The adapter does not read request.RedactionPolicy: the host blanks it before the call, because classifier configuration is host policy.
type PlanInput ¶
type PlanInput struct {
Messages []provider.Message
Budget int
Tools []provider.ToolSpec
// OutputReserve is validated (must not be negative) and folded into the
// idempotency-key fingerprint (planIdempotencyKey) - it is NOT subtracted
// from Budget anywhere in the trigger/target math below. Budget already
// excludes the reserved completion allowance (callers derive it from
// config.EffectivePromptTokens, which does the subtraction once, upstream
// of the planner). Using OutputReserve again here would double-subtract
// the same reserve. If a future caller needs the planner itself to
// account for an output reserve, pass a Budget that has NOT already
// excluded it and remove this comment along with the double-subtraction
// it warns against - do not add a second, silent subtraction beside this
// one.
OutputReserve int
Force bool
CurrentObjective string
SourceRange contextstate.SourceRange
SourceEvents []contextstate.SourceEvent
IdempotencyKey string
RecentTail int
// Revision is the session revision the compaction starts FROM. It is
// part of the derived idempotency key: two compactions of the same
// retained set off the same source range (a resumed process compacting
// an already-compacted session again) are different operations that
// commit different work, so sharing a key made the store reject the
// second as a conflicting retry. Retries of the SAME compaction carry
// the same revision and stay idempotent.
Revision contextstate.Revision
// PreserveNames lists provider.Message.Name values that structural
// retention keeps whole alongside the mandatory set. The chat layer uses
// it for the session-owned core-memory context frame so compaction never
// drops it.
PreserveNames []string
// CalibrationRatio scales token estimates to correct for heuristic drift.
// 0 means use 1.0 (no correction). Should come from a Calibration.Ratio.
CalibrationRatio float64
// ContextAccounting carries the bound provider's declared context-billing
// profile (provider.ContextAccountingProfile) opaquely: the planner never
// interprets its fields itself, only passes it to the provider estimators
// it already calls. The zero value is the conservative "bill everything"
// default, so a caller that leaves this unset behaves exactly as before
// the field existed.
ContextAccounting provider.ContextAccountingProfile
// Spool: nil = elision mints no refs (plain notices), keeping the planner free of storage side effects.
Spool *remainder.Spool
// Principal: the session principal that receives the remainder grant when Spool is set.
Principal contextstate.Principal
}
PlanInput contains only immutable inputs to the structural planner. The planner stays pure except for an explicit caller-provided Spool seam: when Spool is nil there are no side effects and output is byte-identical to before; when set, elision spools bytes through that seam only.
type PlanResult ¶
type PlanResult struct {
Messages []provider.Message
Candidate CheckpointCandidate
BeforeTokens int
AfterTokens int
TriggerTokens int
TargetTokens int
Compacted bool
// ElidedMessages and ElidedBytes are content-free aggregates of prior-turn
// tool-result replacements applied on the compaction path. Both are zero
// when the request is below the trigger or no body was eligible.
ElidedMessages int
ElidedBytes int
// ElidedReasoningMessages and ElidedReasoningBytes are content-free
// aggregates of stale assistant reasoning replaced with
// reasoningElisionMarker on the compaction path. Both are zero when the
// request is below the trigger or no reasoning was eligible.
ElidedReasoningMessages int
ElidedReasoningBytes int
SourceRange contextstate.SourceRange
IdempotencyKey string
}
PlanResult is the deterministic structural result. Summary generation and durable publication happen in later seams; this value is safe to discard.
func Plan ¶
func Plan(input PlanInput) (PlanResult, error)
Plan applies threshold/target math and strict structural retention. A request exactly at the trigger is compacted; a request exactly at the hard budget is accepted, while one token over is rejected.
type PlannerInput ¶
type PlannerInput = PlanInput
PlannerInput is a descriptive alias for callers that use the planner as a standalone preparation boundary.
type PlannerResult ¶
type PlannerResult = PlanResult
PlannerResult is a descriptive alias for PlanResult.
type Preparation ¶
type Preparation struct {
Messages []provider.Message
Candidate CheckpointCandidate
Token CommitToken
Compacted bool
BeforeTokens int
AfterTokens int
TriggerTokens int
TargetTokens int
// ElidedMessages and ElidedBytes are content-free aggregates of prior-turn
// tool-result replacements from the planner (or turn-level accumulation on
// the agent loop). Both are zero when nothing was elided.
ElidedMessages int
ElidedBytes int
// ElidedReasoningMessages and ElidedReasoningBytes are content-free
// aggregates of stale assistant reasoning replaced with a constant marker
// on the planner compaction path. Both are zero when nothing was elided.
ElidedReasoningMessages int
ElidedReasoningBytes int
}
func CapturePreparation ¶
func CapturePreparation(input PrepareInput, candidate CheckpointCandidate, messages []provider.Message, compacted bool, idempotencyKey string) (Preparation, error)
CapturePreparation creates an immutable preparation token from one policy snapshot. It is intentionally independent of storage and provider I/O.
func (Preparation) ValidateToken ¶
func (p Preparation) ValidateToken(revision contextstate.Revision, binding contextstate.BindingRevision) error
ValidateToken checks that an asynchronous preparation still belongs to the captured durable revision and provider/model generation before publication.
type PreparationCommitter ¶
type PreparationCommitter struct {
Store contextstate.Store
Summarizer *Summarizer
SummaryRequest SummaryRequest
SummaryBuilder SummaryRequestBuilder
}
PreparationCommitter adapts the publication function to the narrow CheckpointPublisher interface used by chat. The summary request is captured by the host together with the preparation's provider/model policy snapshot, or derived per preparation through SummaryBuilder when the host has live turn state to draw on.
func (PreparationCommitter) Commit ¶
func (c PreparationCommitter) Commit(ctx context.Context, preparation Preparation, result TurnResult) error
type PreparationManager ¶
type PreparationManager interface {
Prepare(context.Context, PrepareInput) (Preparation, error)
Discard(Preparation)
}
type PrepareInput ¶
type PrepareInput struct {
// Spool, when non-nil, lets compaction elision store the full body of an
// elided tool result and name the remainder ref in the notice, so the model
// can fetch the original bytes with read_output. Nil keeps plain
// (non-recoverable) notices.
Spool *remainder.Spool
Messages []provider.Message
Budget int
Tools []provider.ToolSpec
OutputReserve int
Force bool
CurrentObjective string
RecentTail int
// PreserveNames lists provider.Message.Name values that structural
// retention keeps whole alongside the mandatory set. The chat layer uses
// it for the session-owned core-memory context frame so compaction never
// drops it.
PreserveNames []string
// CalibrationRatio scales token estimates in the planner for
// heuristic drift correction. 0 means no correction.
CalibrationRatio float64
// ContextAccounting carries the bound provider's declared context-billing
// profile through to Plan(), opaquely - see PlanInput.ContextAccounting.
ContextAccounting provider.ContextAccountingProfile
SourceRange contextstate.SourceRange
Principal contextstate.Principal
Revision contextstate.Revision
Binding contextstate.BindingRevision
WorktreeInstance contextstate.WorktreeInstance
Policy contextstate.PolicySnapshot
}
type PublicationRequest ¶
type PublicationRequest struct {
Store contextstate.Store
Summarizer *Summarizer
SummaryRequest SummaryRequest
SummaryBuilder SummaryRequestBuilder
Preparation Preparation
Result TurnResult
}
PublicationRequest keeps summary generation, request mapping, and durable publication in one explicit call boundary. No memory publication happens in this package; the caller adopts the preparation only after success.
type SourceExcerpt ¶
SourceExcerpt is one bounded, content-bearing quote of a message the compaction dropped. It rides the summary REQUEST only - never the sealed envelope, the durable metadata, or the injected message - so the persisted summary contract stays unchanged while the model reads real content.
func SourceExcerpts ¶
func SourceExcerpts(input, retained []provider.Message) []SourceExcerpt
SourceExcerpts derives bounded excerpts of the dropped messages, newest first, so the summarizer reads the real conversation content instead of size labels. The FIRST dropped user message keeps a guaranteed opening slot: it frames the task of the summarized segment. Tool-call arguments and assistant reasoning never ride the request; tool results do. Item, per-field, and total-byte bounds cap the section.
type StructuralPreparationManager ¶
type StructuralPreparationManager struct {
Tools []map[string]any
OutputReserve int
RecentTail int
}
StructuralPreparationManager adapts the pure planner to the preparation capability. It owns no storage and never publishes a checkpoint.
func (StructuralPreparationManager) Discard ¶
func (StructuralPreparationManager) Discard(Preparation)
func (StructuralPreparationManager) Prepare ¶
func (m StructuralPreparationManager) Prepare(ctx context.Context, input PrepareInput) (Preparation, error)
type Summarizer ¶
type Summarizer struct {
Provider SummaryProvider
Binding contextstate.BindingRevision
Policy contextstate.PolicySnapshot
Timeout time.Duration
}
Summarizer binds one captured provider/model/policy snapshot to a summary request. It has no provider discovery or network fallback path.
func NewSummarizer ¶
func NewSummarizer(provider SummaryProvider, binding contextstate.BindingRevision, policy contextstate.PolicySnapshot) (Summarizer, error)
func (Summarizer) Summarize ¶
func (s Summarizer) Summarize(ctx context.Context, request SummaryRequest) (UntrustedSummary, error)
Summarize executes a bounded provider call (with one retry on transient failure) and validates its result before returning it. The caller's context remains the outer cancellation authority.
type Summary ¶
type Summary struct {
Version uint32 `json:"version"`
Objective string `json:"objective"`
State string `json:"state"`
Decisions []string `json:"decisions,omitempty"`
Evidence []string `json:"evidence,omitempty"`
ChangedSurfaces []string `json:"changed_surfaces,omitempty"`
OpenWork []string `json:"open_work,omitempty"`
Risks []string `json:"risks,omitempty"`
SourceRange contextstate.SourceRange `json:"source_range"`
}
type SummaryBuildInput ¶
type SummaryBuildInput struct {
Version uint32
Objective string
State string
Decisions []string
Evidence []string
ChangedSurfaces []string
OpenWork []string
Risks []string
SourceRange contextstate.SourceRange
PolicyDigest string
Provider string
Model string
EndpointAllowlist []string
RedactionPolicy contextstate.RedactionPolicy
Budget int
OutputLimit int
// SourceExcerpts carries bounded quotes of the dropped messages for the
// summarize REQUEST. BuildSummaryRequest sanitizes them and drops every
// item the redaction policy flags; the envelope never sees them.
SourceExcerpts []SourceExcerpt
// Focus is an optional caller-supplied bias string telling the
// summarizer what to prioritize (e.g. `/compact <focus instructions>`).
// Empty is the default, unbiased behavior. See SummaryRequest.Focus.
Focus string
}
SummaryBuildInput is the host-side accumulation BuildSummaryRequest converts into a validated SummaryRequest. Envelope lists are already bounded by the turn-state tracker or OmittedEvidence; the constructor re-validates every field through the same validators Summarizer.Summarize will apply.
type SummaryEnvelope ¶
type SummaryEnvelope struct {
Version uint32
Objective string
State string
Decisions []string
Evidence []string
ChangedSurfaces []string
OpenWork []string
Risks []string
SourceRange contextstate.SourceRange
PolicyDigest string
// contains filtered or unexported fields
}
SummaryEnvelope is the only input accepted by a summary provider. The unexported seal prevents callers from manufacturing provider input with a struct literal; the host must construct and validate it through the bounded constructor below.
func NewSummaryEnvelope ¶
func NewSummaryEnvelope(version uint32, objective, state string, decisions, evidence, surfaces, openWork, risks []string, sourceRange contextstate.SourceRange, policyDigest string) (SummaryEnvelope, error)
func (SummaryEnvelope) Validate ¶
func (e SummaryEnvelope) Validate() error
type SummaryProvider ¶
type SummaryProvider interface {
Summarize(context.Context, SummaryRequest) (Summary, error)
}
type SummaryRequest ¶
type SummaryRequest struct {
Input SummaryEnvelope
Budget int
OutputLimit int
SourceRange contextstate.SourceRange
Provider string
Model string
EndpointAllowlist []string
// SourceExcerpts are bounded quotes of the dropped messages, for the
// summarize request only. The sealed envelope never carries them, so no
// durable record or injected message contains excerpt content.
SourceExcerpts []SourceExcerpt `json:"-"`
// Focus is an optional caller-supplied bias string (e.g. `/compact <focus
// instructions>`) telling the summarizer what to prioritize. It rides the
// request only - never the sealed envelope the model echoes back or the
// durable metadata - since it is host-side guidance, not conversation
// content the model needs to round-trip.
Focus string `json:"-"`
RedactionPolicy contextstate.RedactionPolicy `json:"-"`
}
func BuildSummaryRequest ¶
func BuildSummaryRequest(input SummaryBuildInput) (SummaryRequest, error)
BuildSummaryRequest is the production constructor for a summary request: it seals the bounded envelope, fills the transport fields, and validates the whole request exactly as Summarizer.Summarize will re-validate it.
func (SummaryRequest) Validate ¶
func (r SummaryRequest) Validate() error
type SummaryRequestBuilder ¶
type SummaryRequestBuilder func(Preparation) (SummaryRequest, error)
SummaryRequestBuilder derives the summary request for one preparation from real host state (objective, source range, policy digest, turn state). It is consulted only for a compacted preparation with a non-nil Summarizer; a nil builder falls back to the fixed SummaryRequest field, keeping existing callers byte-identical.
type TurnResult ¶
type TurnState ¶
type TurnState struct {
// contains filtered or unexported fields
}
TurnState is a bounded per-turn accumulator of host-observable facts that a summary request may carry. Every list is capped at MaxSummaryItems items and every field at MaxSummaryFieldBytes, matching the summary validators in summary.go, so a validated Snapshot is always envelope-valid.
The zero value and a nil *TurnState are valid empty trackers: callers that must never fail the turn (the agent loop, the chat turn path) treat a rejected fact as a drop, never as an error.
func (*TurnState) AddChangedSurface ¶
AddChangedSurface appends one bounded changed file surface. A rejected item is never stored.
func (*TurnState) AddDecision ¶
AddDecision appends one bounded decision. A rejected item (list full, oversized, duplicate, control characters, invalid UTF-8) is never stored.
func (*TurnState) AddEvidence ¶
AddEvidence appends one bounded evidence item (tool names, omitted-segment markers). A rejected item is never stored.
func (*TurnState) AddOpenWork ¶
AddOpenWork appends one bounded open-work item. A rejected item is never stored.
func (*TurnState) SetState ¶
SetState replaces the accumulated state text (host-observed latest completed assistant content). An empty state is valid: nothing was observed yet.
func (*TurnState) Snapshot ¶
func (t *TurnState) Snapshot() (TurnStateSnapshot, error)
Snapshot validates the accumulator against the summary validators and returns a defensive copy. Mutating the returned slices never changes the tracker. A nil tracker snapshots to an empty valid snapshot.
type TurnStateSnapshot ¶
type TurnStateSnapshot struct {
State string
Decisions []string
Evidence []string
ChangedSurfaces []string
OpenWork []string
Risks []string
}
TurnStateSnapshot is a validated defensive copy of a TurnState.
type UntrustedSummary ¶
type UntrustedSummary struct {
// contains filtered or unexported fields
}
UntrustedSummary is a validated data-only result from a summarizer. The private seal and private payload prevent callers from manufacturing an authority-bearing summary with a struct literal.
func ValidateSummary ¶
func ValidateSummary(summary Summary, request SummaryRequest) (UntrustedSummary, error)
ValidateSummary validates provider output against the exact request that produced it and seals it as untrusted state data.
func (UntrustedSummary) Metadata ¶
func (s UntrustedSummary) Metadata(redactionConfigured bool) ([]byte, error)
Metadata returns bounded persistence bytes. Without an explicitly configured redaction policy, only structural metadata and a digest survive; summary content remains ephemeral.
func (UntrustedSummary) Validate ¶
func (s UntrustedSummary) Validate() error
func (UntrustedSummary) Value ¶
func (s UntrustedSummary) Value() Summary
Value returns a defensive copy for host framing. The returned Summary is data only; it has no tool, policy, credential, or dispatcher fields.