Documentation
¶
Overview ¶
Event append API: validates a payload, coerces invalid UTF-8 to U+FFFD, mints a UUIDv7 record id, stamps the canonical timestamp, and appends the event record to the active session store.
EmitInteractionMode appends and immediately flushes the interaction_mode event recording the active mode at session start, on /clear, and on a /mode switch
EmitLaunchBegan appends and immediately flushes the launch_began boundary event for a launch or in-process session switch (7b1).
Package events defines the event payload schemas, their per-kind cross-field validators, and the append API that mints a record id, stamps the canonical timestamp, coerces invalid UTF-8 to U+FFFD, and appends an event to the active session store. It stays independent of internal/sessions's load path so load orchestration can compose spine validation with the payload validation here without an import cycle.
Permission-event emitter helpers: thin wrappers that build the permission event payloads and append them to the active session store. The payload validators in payloads.go own the cross-field rules; these helpers only construct the typed payload and call Append.
EmitProviderRequestFailed appends and immediately flushes the provider_request_failed event for a transport-level failure, in the same append-then-flush style as EmitLaunchBegan.
EmitProviderRequestRetry appends and immediately flushes the provider_request_retry event for one scheduled auto-retry of a transient provider-round failure, in the same append-then-flush style as EmitProviderRequestFailed.
EmitProviderRequestRetrySkipped appends and immediately flushes the provider_request_retry_skipped event for a classified retryable provider-round failure that is not scheduled for another attempt, in the same append-then-flush style as EmitProviderRequestRetry.
Child-agent lifecycle payloads and their emitters: one start/end pair per delegate call, linked by a stable invocation id, recorded in the parent's own session so a reader can see what was delegated, what it changed, and how it ended.
Tool-exec event emitter helpers plus the shared stdout/stderr truncation used for both event persistence and the model-input feed.
Index ¶
- Constants
- func Append(store *sessions.Store, payload EventPayload) (sessions.Record, error)
- func Build(payload EventPayload) (sessions.Record, error)
- func BuildModelInputBytes(stdout, stderr []byte, cap int) (modelStdout, modelStderr []byte)
- func BuildToolExecEndBounded(exec BoundedToolExec, cap int) (sessions.Record, error)
- func ChildInstructionDigest(instruction string) string
- func EmitChildAgentEnd(store *sessions.Store, projectRoot string, payload ChildAgentEnd) error
- func EmitChildAgentStart(store *sessions.Store, projectRoot string, payload ChildAgentStart) error
- func EmitDecision(store *sessions.Store, ...) error
- func EmitDecisionAttributed(store *sessions.Store, ...) error
- func EmitDecisionGrant(store *sessions.Store, ...) error
- func EmitDecisionGrantAttributed(store *sessions.Store, ...) error
- func EmitInteractionMode(ctx context.Context, store *sessions.Store, mode, source, trigger string, ...) error
- func EmitLaunchBegan(ctx context.Context, store *sessions.Store, source string, ...) error
- func EmitMatchedIdentity(store *sessions.Store, ...) error
- func EmitMatchedIdentityAttributed(store *sessions.Store, ...) error
- func EmitPermissionRevokeRequested(store *sessions.Store, ...) error
- func EmitPersistFailed(store *sessions.Store, ...) error
- func EmitPromptShown(store *sessions.Store, subjectKind, subject, pathScope string, ...) error
- func EmitPromptShownAttributed(store *sessions.Store, subjectKind, subject, pathScope string, ...) error
- func EmitProviderRequestFailed(ctx context.Context, store *sessions.Store, ...) error
- func EmitProviderRequestRetry(ctx context.Context, store *sessions.Store, ...) error
- func EmitProviderRequestRetrySkipped(ctx context.Context, store *sessions.Store, ...) error
- func EmitProviderStreamIdle(ctx context.Context, store *sessions.Store, providerName, modelID string, ...) error
- func EmitSecurityStateHalt(ctx context.Context, store *sessions.Store, records []SecurityStateHalted, ...) error
- func EmitStructuredReadEnd(store *sessions.Store, invocationID, toolName, outcome string, ...) error
- func EmitStructuredReadRefused(store *sessions.Store, toolName, reason string, batchSize int64, ...) error
- func EmitStructuredReadStart(store *sessions.Store, invocationID, toolName, pathScope string, ...) error
- func EmitToolExecEnd(store *sessions.Store, invocationID string, subjectKind, subject string, ...) error
- func EmitToolExecStart(store *sessions.Store, ...) error
- func EmitTurnTerminal(ctx context.Context, store *sessions.Store, payload TurnTerminal, ...) error
- func SafeFailedTool(name string) bool
- func ValidatePayload(kind string, raw json.RawMessage) error
- type AgentInstructionsLoaded
- type BoundedToolExec
- type ChildAgentEnd
- type ChildAgentStart
- type ChildMovePair
- type EventPayload
- type ExecutionCapability
- type ExecutionCapabilityLeg
- type InteractionMode
- type LaunchBegan
- type ModelCatalogRefreshed
- type ModelChanged
- type ModelEffortUnsupported
- type ModelGlobalMirrorFailed
- type ModelPersistFailed
- type ModelRecoveryFailed
- type ModelResponse
- type ModelTurn
- type OriginalBytes
- type PermissionDecision
- type PermissionMatched
- type PermissionPersistFailed
- type PermissionPromptShown
- type PermissionRevokeRequested
- type ProviderRequestFailed
- type ProviderRequestRetry
- type ProviderRequestRetrySkipped
- type ProviderRoundTrip
- type ProviderStreamIdle
- type PruneFailure
- type QueuedPromptDiscarded
- type SecurityStateHalted
- type SessionForked
- type SessionPruneSummary
- type SessionWriteFailed
- type SlashCommand
- type StreamInterrupted
- type StructuredReadEnd
- type StructuredReadRefused
- type StructuredReadStart
- type SuggestFollowupDebug
- type ToolExecEnd
- type ToolExecStart
- type TurnLatency
- type TurnTerminal
- type WriteFailureHandler
Constants ¶
const ( KindLaunchBegan = "launch_began" KindSessionForked = "session_forked" KindPermissionPromptShown = "permission_prompt_shown" KindPermissionDecision = "permission_decision" KindPermissionMatched = "permission_matched" KindToolExecStart = "tool_exec_start" KindToolExecEnd = "tool_exec_end" KindAgentInstructionsLoaded = "agent_instructions_loaded" KindSessionPruneSummary = "session_prune_summary" KindSessionWriteFailed = "session_write_failed" KindPermissionPersistFailed = "permission_persist_failed" KindModelTurn = "model_turn" KindModelResponse = "model_response" KindModelChanged = "model_changed" KindModelEffortUnsupported = "model_effort_unsupported" KindModelRecoveryFailed = "model_recovery_failed" KindModelPersistFailed = "model_persist_failed" KindModelGlobalMirrorFailed = "model_global_mirror_failed" KindModelCatalogRefreshed = "model_catalog_refreshed" KindSlashCommand = "slash_command" KindStreamInterrupted = "stream_interrupted" KindProviderRequestFailed = "provider_request_failed" KindInteractionMode = "interaction_mode" // turn_latency and provider_round_trip are additive timing events: they // record how long a user-visible turn and a single provider // round took so a session reviewer can see where the time went. Like // interaction_mode they are non-breaking additions — older sessions that lack // them load unchanged with no schema_version bump. KindTurnLatency = "turn_latency" KindProviderRoundTrip = "provider_round_trip" // provider_request_retry records one scheduled auto-retry of a transient // provider-round failure, appended and flushed before each // backoff wait. Like the timing events it is a non-breaking addition that older // sessions load unchanged with no schema_version bump; the terminal // provider_request_failed schema is deliberately left untouched, so the attempt // count is reconstructed from these events rather than added to that one. KindProviderRequestRetry = "provider_request_retry" // provider_request_retry_skipped records that a classified retryable // provider-round failure was NOT scheduled for another attempt, carrying the // closed skip reason (retry_disabled / max_attempts_reached / budget_exhausted). // It mirrors provider_request_retry's (phase, reason) taxonomy and, like it, is a // non-breaking addition that older sessions load unchanged with no schema_version // bump. This slice only defines and validates the event; the retry loop // that emits it is wired separately. KindProviderRequestRetrySkipped = "provider_request_retry_skipped" // suggest_followup_debug is the development-only trace of the // suggest_followup path. It is written only when the // dev-debug gate is on (CODEMELD_DEV_DEBUG / `run --dev-debug`); a normal // session never carries it. Like the timing events it is a non-breaking // addition that older sessions load unchanged with no schema_version bump, and // it deliberately persists only lengths/booleans/reasons — never suggestion // label or prompt text — so it cannot reintroduce the ephemeral UI text the // follow-up suggestion channel keeps out of the record. KindSuggestFollowupDebug = "suggest_followup_debug" KindQueuedPromptDiscarded = "queued_prompt_discarded" KindProviderStreamIdle = "provider_stream_idle" KindStructuredReadStart = "structured_read_start" KindStructuredReadEnd = "structured_read_end" KindStructuredReadRefused = "structured_read_refused" KindTurnTerminal = "turn_terminal" KindPermissionRevokeRequested = "permission_revoke_requested" KindSecurityStateHalted = "security_state_halted" // child_agent_start and child_agent_end are the delegate lifecycle pair, linked by one // invocation id the child's own tool and permission events also carry. Like the timing // events they are a non-breaking addition: a parent's own events omit the attribution // field, so older sessions load unchanged with no schema_version bump. KindChildAgentStart = "child_agent_start" KindChildAgentEnd = "child_agent_end" KindExecutionCapability = "execution_capability" )
Event-kind constants. Each EventPayload reports its kind via Kind(); these are also the kind strings written to the record.
const ( SuggestFollowupStageRequestBuilt = "request_built" SuggestFollowupStageNoCall = "provider_round_no_call" SuggestFollowupStageToolCallSeen = "tool_call_seen" SuggestFollowupStageIntercepted = "intercepted" SuggestFollowupStageSurfaceCalled = "surface_called" SuggestFollowupStageGhostSet = "ghost_set" SuggestFollowupStageGhostAccepted = "ghost_accepted" SuggestFollowupStageGhostCleared = "ghost_cleared" )
suggest_followup_debug stage labels. Each marks one observable point on the suggest_followup path so a developer reproducing a missing suggestion can see exactly how far it got: whether the tool was advertised, whether the model called it, where it was intercepted, and what the TUI surface did with it. turn-side stages (request_built…intercepted) come from the turn loop; the ghost stages come from the TUI event loop.
const ( RetryPhaseToolHandoff = "tool_handoff" RetryReasonAssemblyFailed = "assembly_failed" RetryReasonInvalidPlan = "invalid_plan" )
const ( SecurityDetectionBeforeMutatingCall = "before_mutating_call" SecurityDetectionBeforeFinalSuccess = "before_final_success" SecurityDetectionStartup = "startup" )
const ( ChildAgentReasonCompleted = "completed" ChildAgentReasonCancelled = "cancelled" ChildAgentReasonStepCap = "step_cap" ChildAgentReasonFailed = "failed" )
Terminal reasons for a child agent, mirroring internal/subagent's Reason values.
const ( ChildRollbackNotNeeded = "not_needed" ChildRollbackRolledBack = "rolled_back" ChildRollbackUnrecovered = "unrecovered" )
const ( TurnOutcomeCompleted = "completed" TurnOutcomeCancelled = "cancelled" TurnOutcomeProviderFailed = "provider_failed" TurnOutcomeInvalidResponse = "invalid_response" TurnOutcomeToolAssemblyFailed = "tool_assembly_failed" TurnOutcomeToolPlanInvalid = "tool_plan_invalid" TurnOutcomeDispatchFailed = "dispatch_failed" TurnOutcomeContinuationFailed = "continuation_failed" // TurnOutcomeSecurityHalted always names a real started round: a startup checkpoint // has none, so it records only security_state_halted and no terminal at all. TurnOutcomeSecurityHalted = "security_halted" )
const ( DispatchReasonToolDispatchFailed = "tool_dispatch_failed" DispatchReasonPostPlanFailed = "post_plan_failed" )
const RevokeSourcePermissionsUI = "permissions_ui"
RevokeSourcePermissionsUI is the only source permission_revoke_requested is ever written with: the dedicated /permissions revoke control. A revoke recorded from anywhere else would make the event's provenance unreadable, so the vocabulary stays closed to this one value.
Variables ¶
This section is empty.
Functions ¶
func Append ¶
Append validates payload, mints a fresh UUIDv7 record id, stamps the canonical timestamp, and appends the event record to store. The payload's string fields are coerced to valid UTF-8 (invalid byte sequences replaced with U+FFFD) before marshalling, and always-present list fields render as “ rather than null. It returns the appended record. Append does not flush; callers trigger durability at the points via the store. An invalid payload is rejected before anything is appended.
func BuildModelInputBytes ¶
BuildModelInputBytes truncates stdout and stderr exactly as EmitToolExecEnd persists them, so the next model turn is fed the same bytes that were recorded in tool_exec_end. Because both paths go through truncateStream, the returned bytes are byte-for-byte identical to the persisted tool_exec_end stdout/stderr (after Append's UTF-8 canonicalization, which truncateStream already applies).
func BuildToolExecEndBounded ¶
func BuildToolExecEndBounded(exec BoundedToolExec, cap int) (sessions.Record, error)
BuildToolExecEndBounded exists beside EmitToolExecEnd because that emitter derives truncated and original_bytes from the full streams it is handed, which would record a stage already cut short at capture time as complete. The retained bytes still go through truncateStream at the same cap: the capture bound is raw, so a retained prefix can end mid-rune or grow past the cap once invalid bytes become U+FFFD.
func ChildInstructionDigest ¶
ChildInstructionDigest lives beside the validator that pins the digest format so a caller hands the instruction to nothing but this function.
func EmitChildAgentEnd ¶
func EmitChildAgentEnd(store *sessions.Store, projectRoot string, payload ChildAgentEnd) error
A terminal record that cannot be appended leaves its child_agent_start unclosed, so the one bound a well-behaved child can still exceed — a declared directory holding more distinct files than the record carries — is applied here rather than refused, exactly as EmitToolExecEnd bounds a stream it is handed. A path outside the project root is refused instead: the child ceiling should have made it impossible, so it is a confinement breach, not a size.
func EmitChildAgentStart ¶
func EmitChildAgentStart(store *sessions.Store, projectRoot string, payload ChildAgentStart) error
EmitChildAgentStart appends child_agent_start. It refuses a declared path outside projectRoot, so a start-append failure — which keeps the child from beginning its first provider round — is also what stops a path from outside the project reaching the record.
func EmitDecision ¶
func EmitDecision(store *sessions.Store, subjectKind, subject, pathScope, outcome, grantKind, grantPathScope, directCommandSubject, directRequestSubject string) error
EmitDecision appends a permission_decision event recording the user's response to a prompt. On a denied outcome the caller passes empty grantKind/ grantPathScope so omitempty drops them. This event is emitted before any degradation rewrite, so grantKind/grantPathScope record the user's chosen values rather than the rewritten ones. It appends only.
func EmitDecisionAttributed ¶
func EmitDecisionAttributed(store *sessions.Store, subjectKind, subject, pathScope, outcome, grantKind, grantPathScope, directCommandSubject, directRequestSubject, childInvocationID string) error
EmitDecisionAttributed is EmitDecision with the child-agent attribution.
func EmitDecisionGrant ¶
func EmitDecisionGrantAttributed ¶
func EmitDecisionGrantAttributed(store *sessions.Store, subjectKind, subject, pathScope, grantKind, grantScope, grantSubject, directCommandSubject, directRequestSubject, childInvocationID string) error
EmitDecisionGrantAttributed is EmitDecisionGrant with the child-agent attribution.
func EmitInteractionMode ¶
func EmitInteractionMode(ctx context.Context, store *sessions.Store, mode, source, trigger string, onWriteFailure WriteFailureHandler) error
EmitInteractionMode appends an interaction_mode event with the given mode, source, and trigger and then immediately flushes the active session, giving the session-start (launch/resume), /clear, and /mode emissions the same durability as the adjacent launch_began boundary (point (e)). mode, source, and trigger are validated by the payload's per-kind rules during Append; an invalid value is rejected before anything is appended or flushed. On an atomic-write failure (Flush returns a real WriteReason) it invokes onWriteFailure with Flush's category, reason, and error so the caller can run the write-failure protocol; cancellation and other non-write flush errors (sessions.ReasonNone) bypass the handler. In all failure cases it returns the flush (or append) error; onWriteFailure may be nil. It mirrors EmitLaunchBegan so launch/resume/clear share one persistence policy rather than each rolling its own.
func EmitLaunchBegan ¶
func EmitLaunchBegan(ctx context.Context, store *sessions.Store, source string, onWriteFailure WriteFailureHandler) error
EmitLaunchBegan appends a launch_began event with the given source and then immediately flushes the active session, satisfying point (e)'s flush-after-this-event rule. source must be one of fresh, resume, or fork an invalid source is rejected before anything is appended or flushed. On an atomic-write failure (Flush returns a real WriteReason) it invokes onWriteFailure with Flush's category, reason, and error so the caller can run the write-failure protocol; cancellation and other non-write flush errors (sessions.ReasonNone) bypass the handler. In all failure cases it returns the flush error; onWriteFailure may be nil. It is called from five sites:
- bootstrap step 7b1 on fresh launch -> source "fresh"
- resume sub-sequence on cold-start --resume -> source "resume"
- /clear in-process switch -> source "fresh"
- in-TUI /resume switch -> source "resume"
- fork action -> source "fork"
func EmitMatchedIdentity ¶
func EmitMatchedIdentityAttributed ¶
func EmitMatchedIdentityAttributed(store *sessions.Store, subjectKind, subject, pathScope, grantKind, grantPathScope, outcome, outcomeSource, argumentHash, directRequestSubject, childInvocationID string) error
EmitMatchedIdentityAttributed is EmitMatchedIdentity with the child-agent attribution.
func EmitPersistFailed ¶
func EmitPersistFailed(store *sessions.Store, targetPath, grantKind, subjectKind, subject, reason, errorCategory, errorDetail, degradedToPathScope string) error
EmitPersistFailed appends a permission_persist_failed event for a failed permission-grant persist. degradedToPathScope is the rewritten in-memory path scope, populated only when grantKind is "global" and empty for a folder grant. For a lock_timeout reason the caller must pass the canonical error_detail the validator pins ("lock acquisition timed out"); error_category is omitted (empty) for the reasons that do not originate in a file syscall. It appends only.
func EmitPromptShown ¶
func EmitPromptShown(store *sessions.Store, subjectKind, subject, pathScope string, directTokens []string, directCommandSubject, directRequestSubject string) error
EmitPromptShown appends a permission_prompt_shown event. directTokens is the request's canonical direct-command token sequence (permissions.MatchRequest.SubjectTokens), recorded verbatim so a later audit replays direct matching from the tokens rather than re-tokenizing the flattened subject. It is nil for every non-direct subject kind and for a direct request that carries no canonical tokens; Append deep-copies it, so no caller alias survives in the record.
func EmitPromptShownAttributed ¶
func EmitPromptShownAttributed(store *sessions.Store, subjectKind, subject, pathScope string, directTokens []string, directCommandSubject, directRequestSubject, childInvocationID string) error
EmitPromptShownAttributed is EmitPromptShown for a caller that knows which child agent's call this was; childInvocationID is empty for the run's own calls.
func EmitProviderRequestFailed ¶
func EmitProviderRequestFailed(ctx context.Context, store *sessions.Store, providerName, modelID, phase, reason, errorDetail string, httpStatus *int64, partialResponseChars int64, onWriteFailure WriteFailureHandler) error
EmitProviderRequestFailed builds a ProviderRequestFailed event from the already-classified (phase, reason) tuple — produced by provider.Classify* — appends it via Append (which validates and rejects an invalid payload before the store is touched), then flushes the active session so the failure is durable at the point. httpStatus is nil except for the http phase, and partialResponseChars is non-zero only for stream_drop; the payload validator enforces both. On a real atomic-write failure (Flush returns a non-ReasonNone WriteReason) it invokes onWriteFailure with Flush's category, reason, and error so the caller can run the write-failure protocol; a cancelled context or other ReasonNone flush failure surfaces to the caller without invoking the handler, since the session_write_failed contract cannot encode ReasonNone. onWriteFailure may be nil. It returns the append or flush error, or nil on success.
func EmitProviderRequestRetry ¶
func EmitProviderRequestRetry(ctx context.Context, store *sessions.Store, providerName, modelID, phase, reason string, attempt, delayMs, partialCharsDiscarded int64, onWriteFailure WriteFailureHandler) error
EmitProviderRequestRetry builds a ProviderRequestRetry event from the already classified (phase, reason) tuple, the 1-based failed-attempt number, the scheduled backoff delay, and the partial-content runes being discarded, appends it via Append (which validates and rejects an invalid payload before the store is touched), then flushes the active session so the retry is durable before the turn waits out the backoff — a failed attempt survives a process exit during the wait. partialCharsDiscarded is non-zero only for a stream_drop; the payload validator enforces that. On a real atomic-write failure (Flush returns a non-ReasonNone WriteReason) it invokes onWriteFailure with Flush's category, reason, and error so the caller can run the write-failure protocol; a cancelled context or other ReasonNone flush failure surfaces to the caller without invoking the handler. onWriteFailure may be nil. It returns the append or flush error, or nil on success.
func EmitProviderRequestRetrySkipped ¶
func EmitProviderRequestRetrySkipped(ctx context.Context, store *sessions.Store, providerName, modelID, phase, reason, skipReason string, attempt, partialCharsDiscarded int64, onWriteFailure WriteFailureHandler) error
EmitProviderRequestRetrySkipped builds a ProviderRequestRetrySkipped event from the already classified (phase, reason) tuple, the 1-based failed-attempt number, the closed skip reason, and the partial-content runes discarded, appends it via Append (which validates and rejects an invalid payload before the store is touched), then flushes the active session so the skip is durable before the turn proceeds to terminal failure. partialCharsDiscarded is non-zero only for a stream_drop; the payload validator enforces that. On a real atomic-write failure (Flush returns a non-ReasonNone WriteReason) it invokes onWriteFailure with Flush's category, reason, and error so the caller can run the write-failure protocol; a cancelled context or other ReasonNone flush failure surfaces to the caller without invoking the handler. onWriteFailure may be nil. It returns the append or flush error, or nil on success.
func EmitProviderStreamIdle ¶
func EmitSecurityStateHalt ¶
func EmitSecurityStateHalt(ctx context.Context, store *sessions.Store, records []SecurityStateHalted, terminal *TurnTerminal, onWriteFailure WriteFailureHandler) error
EmitSecurityStateHalt makes one checkpoint's halt durable in a single store commit; a startup checkpoint has no started round to close and passes a nil terminal. A returned error means the halt was not recorded, and the caller must still stop the turn rather than treat the records as durable or present a recorded halt.
func EmitStructuredReadEnd ¶
func EmitStructuredReadStart ¶
func EmitStructuredReadStart(store *sessions.Store, invocationID, toolName, pathScope string, configuredConcurrency int64, childInvocationID string) error
childInvocationID attributes the record to the child agent whose call produced it; the parent's own reads pass "" and the field is omitted from the persisted payload.
func EmitToolExecEnd ¶
func EmitToolExecEnd(store *sessions.Store, invocationID string, subjectKind, subject string, exitCode int, durationMs int64, stdout, stderr []byte, cap int, childInvocationID string) error
EmitToolExecEnd appends a tool_exec_end event for a completed invocation, paired to its start event by invocationID. Each of stdout/stderr is truncated independently to cap bytes at a UTF-8 rune boundary (see truncateStream); truncated and original_bytes are set only when at least one stream was actually shortened, and original_bytes then carries the pre-truncation raw byte size of both streams. A kept-empty stream is stored as the empty string so omitempty drops it from the persisted payload. It appends only; the caller owns the flush.
func EmitToolExecStart ¶
func EmitToolExecStart(store *sessions.Store, invocationID, subjectKind, subject, pathScope, childInvocationID string) error
EmitToolExecStart appends a tool_exec_start event recording the start of a tool invocation. invocationID is the runner-minted UUIDv7 for this invocation and is reused on the matching tool_exec_end so the pair shares one id; subjectKind/subject describe the dispatched command and pathScope is its resolved working directory (a cleaned absolute path). It validates the payload through Append, so a non-UUIDv7 invocationID, an unrecognized subjectKind, an empty subject, or a non-absolute pathScope is rejected and nothing is appended. It appends only; the caller owns the flush.
func EmitTurnTerminal ¶
func EmitTurnTerminal(ctx context.Context, store *sessions.Store, payload TurnTerminal, onWriteFailure WriteFailureHandler) error
func SafeFailedTool ¶
func ValidatePayload ¶
func ValidatePayload(kind string, raw json.RawMessage) error
ValidatePayload is the exported load-time validator: it unmarshals raw into the struct for kind and runs that kind's cross-field validation. Load orchestration combines this with the session spine validation without internal/sessions importing this package. An unknown kind is an error so a codemeld-written record stream is held to the closed set.
Types ¶
type AgentInstructionsLoaded ¶
type AgentInstructionsLoaded struct {
Path string `json:"path"`
Layer string `json:"layer"`
LoadOrder int64 `json:"load_order"`
SkipReason string `json:"skip_reason,omitempty"`
ErrorCategory string `json:"error_category,omitempty"`
ErrorDetail string `json:"error_detail,omitempty"`
}
AgentInstructionsLoaded records one AGENTS.md file loaded or skipped.
func (AgentInstructionsLoaded) Kind ¶
func (AgentInstructionsLoaded) Kind() string
type BoundedToolExec ¶
type BoundedToolExec struct {
InvocationID string
ChildInvocationID string
SubjectKind string
Subject string
ExitCode int
DurationMs int64
Stdout []byte
Stderr []byte
StdoutTotal int64
StderrTotal int64
}
BoundedToolExec is one completed invocation whose stdout/stderr were already bounded before they reached the event layer. Stdout/Stderr are the bytes that were retained; StdoutTotal/StderrTotal are how many bytes were read from each stream in full, which is what original_bytes must report.
type ChildAgentEnd ¶
type ChildAgentEnd struct {
InvocationID string `json:"invocation_id"`
Reason string `json:"reason"`
Steps int64 `json:"steps"`
WrittenPaths []string `json:"written_paths"`
RollbackOutcome string `json:"rollback_outcome"`
DurationMs int64 `json:"duration_ms"`
ReplyTruncated bool `json:"reply_truncated"`
// WrittenPathsTotal is the child's true distinct-write count, present only when the list
// above was bounded to fit the record.
WrittenPathsTotal int64 `json:"written_paths_total,omitempty"`
DeletedPaths []string `json:"deleted_paths,omitempty"`
DeletedPathsTotal int64 `json:"deleted_paths_total,omitempty"`
// MovedPairs needs no total: a child moves only pairs it declared, so the distinct list never
// outgrows the declaration's own limit.
MovedPairs []ChildMovePair `json:"moved_pairs,omitempty"`
}
ChildAgentEnd records how a child agent ended. RollbackOutcome is a third outcome alongside a clean finish and a clean undo: "unrecovered" says the child's writes are still on disk after a failed restore, so it must never be reported as "rolled_back".
func (ChildAgentEnd) Kind ¶
func (ChildAgentEnd) Kind() string
type ChildAgentStart ¶
type ChildAgentStart struct {
InvocationID string `json:"invocation_id"`
ProviderID string `json:"provider_id"`
ModelID string `json:"model_id"`
DeclaredPaths []string `json:"declared_paths"`
StepCap int64 `json:"step_cap"`
InstructionBytes int64 `json:"instruction_bytes"`
InstructionDigest string `json:"instruction_digest"`
DeclaredDeletePaths []string `json:"declared_delete_paths,omitempty"`
DeclaredMovePairs []ChildMovePair `json:"declared_move_pairs,omitempty"`
}
ChildAgentStart records a child agent about to run. The instruction is reduced to its length and digest so the record stays bounded and carries no delegated text.
func (ChildAgentStart) Kind ¶
func (ChildAgentStart) Kind() string
type ChildMovePair ¶
type EventPayload ¶
type EventPayload interface {
// Kind returns the kind string for this payload.
Kind() string
// contains filtered or unexported methods
}
EventPayload is the closed set of event payloads. The unexported validate keeps the set closed to this package (mirroring sessions.Record) and is exercised externally only through Append and ValidatePayload.
type ExecutionCapability ¶
type ExecutionCapability struct {
Capability string `json:"capability"`
Reason string `json:"reason,omitempty"`
Legs []ExecutionCapabilityLeg `json:"legs,omitempty"`
}
func (ExecutionCapability) Kind ¶
func (ExecutionCapability) Kind() string
type ExecutionCapabilityLeg ¶
type InteractionMode ¶
type InteractionMode struct {
Mode string `json:"mode"`
Source string `json:"source"`
Trigger string `json:"trigger"`
}
InteractionMode records the active interaction mode at session start and on every mode switch, mirroring model_turn. It is an additive event kind — non-breaking schema-version semantics.
func (InteractionMode) Kind ¶
func (InteractionMode) Kind() string
type LaunchBegan ¶
type LaunchBegan struct {
Source string `json:"source"` // fresh | resume | fork
}
LaunchBegan marks the boundary of a launch or in-process session switch.
func (LaunchBegan) Kind ¶
func (LaunchBegan) Kind() string
type ModelCatalogRefreshed ¶
type ModelCatalogRefreshed struct {
Provider string `json:"provider"`
Outcome string `json:"outcome"`
}
func (ModelCatalogRefreshed) Kind ¶
func (ModelCatalogRefreshed) Kind() string
type ModelChanged ¶
type ModelChanged struct {
NewProvider string `json:"new_provider"`
NewModelID string `json:"new_model_id"`
NewEffort string `json:"new_effort"`
PriorProvider string `json:"prior_provider,omitempty"`
PriorModelID string `json:"prior_model_id,omitempty"`
PriorEffort string `json:"prior_effort,omitempty"`
}
ModelChanged records a TUI model-picker selection.
func (ModelChanged) Kind ¶
func (ModelChanged) Kind() string
type ModelEffortUnsupported ¶
type ModelEffortUnsupported struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
ConfiguredEffort string `json:"configured_effort"`
}
ModelEffortUnsupported records that the configured effort was dropped.
func (ModelEffortUnsupported) Kind ¶
func (ModelEffortUnsupported) Kind() string
type ModelGlobalMirrorFailed ¶
type ModelGlobalMirrorFailed struct {
TargetPath string `json:"target_path"`
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Effort string `json:"effort"`
Reason string `json:"reason"`
ErrorCategory string `json:"error_category,omitempty"`
ErrorDetail string `json:"error_detail"`
}
ModelGlobalMirrorFailed records a failed global mirror write (step 2).
func (ModelGlobalMirrorFailed) Kind ¶
func (ModelGlobalMirrorFailed) Kind() string
type ModelPersistFailed ¶
type ModelPersistFailed struct {
TargetPath string `json:"target_path"`
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Effort string `json:"effort"`
Reason string `json:"reason"`
ErrorCategory string `json:"error_category,omitempty"`
ErrorDetail string `json:"error_detail"`
}
ModelPersistFailed records a failed per-project model write (step 1).
func (ModelPersistFailed) Kind ¶
func (ModelPersistFailed) Kind() string
type ModelRecoveryFailed ¶
type ModelRecoveryFailed struct {
Reason string `json:"reason"`
ErrorDetail string `json:"error_detail"`
}
ModelRecoveryFailed records a failed model recovery on resume (step 1).
func (ModelRecoveryFailed) Kind ¶
func (ModelRecoveryFailed) Kind() string
type ModelResponse ¶
type ModelResponse struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
// nil is not reported; a non-nil 0 is a reported zero. Without omitempty,
// requireShape would reject every record written before this field existed.
CachedInputTokens *int64 `json:"cached_input_tokens,omitempty"`
// Written only as true, marking the present CachedInputTokens a known lower bound.
CachedInputTokensPartial bool `json:"cached_input_tokens_partial,omitempty"`
Anomaly []string `json:"anomaly"`
UpstreamProvider string `json:"upstream_provider,omitempty"`
}
ModelResponse records an assistant turn's token usage.
func (ModelResponse) Kind ¶
func (ModelResponse) Kind() string
type ModelTurn ¶
type ModelTurn struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Effort string `json:"effort"`
Source string `json:"source"`
}
ModelTurn records the active model/effort at the start of an assistant turn. Effort validation is intentionally independent of provider catalog support.
type OriginalBytes ¶
OriginalBytes carries the pre-truncation byte sizes of a captured stream pair.
func TruncateToolOutput ¶
func TruncateToolOutput(stdout, stderr []byte, cap int) (keptOut, keptErr []byte, truncated bool, original *OriginalBytes)
TruncateToolOutput caps a stdout/stderr pair for a tool_exec_end payload: each stream is independently truncated to max(cap, 0) bytes at a UTF-8 rune boundary (see truncateStream). truncated is true iff at least one stream was actually shortened, and original is non-nil exactly when truncated is true, carrying the pre-truncation raw byte size of both streams (so a non-truncated pair leaves ToolExecEnd.OriginalBytes nil, matching the absence rule). Production emitters — EmitToolExecEnd and the VCS invocation path — share this helper so their persisted bytes stay byte-for-byte identical to what BuildModelInputBytes feeds the model.
type PermissionDecision ¶
type PermissionDecision struct {
SubjectKind string `json:"subject_kind"`
Subject string `json:"subject"`
PathScope string `json:"path_scope,omitempty"`
Outcome string `json:"outcome"`
GrantKind string `json:"grant_kind,omitempty"`
GrantPathScope string `json:"grant_path_scope,omitempty"`
HostScope string `json:"host_scope,omitempty"`
GrantHostScope string `json:"grant_host_scope,omitempty"`
// An absent GrantSubject is a legacy record, not an equal subject.
GrantSubject string `json:"grant_subject,omitempty"`
// Stored verbatim; see PermissionPromptShown for the ownership rule.
DirectCommandSubject string `json:"direct_command_subject,omitempty"`
DirectRequestSubject string `json:"direct_request_subject,omitempty"`
// See ToolExecStart.ChildInvocationID.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
PermissionDecision records the user's response to a permission prompt.
func (PermissionDecision) Kind ¶
func (PermissionDecision) Kind() string
type PermissionMatched ¶
type PermissionMatched struct {
SubjectKind string `json:"subject_kind"`
Subject string `json:"subject"`
PathScope string `json:"path_scope,omitempty"`
GrantKind string `json:"grant_kind,omitempty"`
GrantPathScope string `json:"grant_path_scope,omitempty"`
Outcome string `json:"outcome"`
OutcomeSource string `json:"outcome_source"`
ArgumentHash string `json:"argument_hash,omitempty"`
HostScope string `json:"host_scope,omitempty"`
GrantHostScope string `json:"grant_host_scope,omitempty"`
// Stored verbatim; see PermissionPromptShown for the ownership rule.
DirectRequestSubject string `json:"direct_request_subject,omitempty"`
// See ToolExecStart.ChildInvocationID.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
BlockedEntry string `json:"blocked_entry,omitempty"`
BlockedEntrySource string `json:"blocked_entry_source,omitempty"`
}
PermissionMatched records an existing grant or in-turn cache hit that authorized a command without prompting.
func (PermissionMatched) Kind ¶
func (PermissionMatched) Kind() string
type PermissionPersistFailed ¶
type PermissionPersistFailed struct {
TargetPath string `json:"target_path"`
GrantKind string `json:"grant_kind"`
SubjectKind string `json:"subject_kind"`
Subject string `json:"subject"`
Reason string `json:"reason"`
ErrorCategory string `json:"error_category,omitempty"`
ErrorDetail string `json:"error_detail"`
DegradedToPathScope string `json:"degraded_to_path_scope,omitempty"`
HostScope string `json:"host_scope,omitempty"`
}
PermissionPersistFailed records a failed permission-grant persist.
func (PermissionPersistFailed) Kind ¶
func (PermissionPersistFailed) Kind() string
type PermissionPromptShown ¶
type PermissionPromptShown struct {
SubjectKind string `json:"subject_kind"`
Subject string `json:"subject"`
PathScope string `json:"path_scope,omitempty"`
HostScope string `json:"host_scope,omitempty"`
// DirectTokens is the canonical direct-command token sequence the matcher
// was given (permissions.MatchRequest.SubjectTokens). It is a pointer so a
// legacy record's absence (unknown tokens) stays distinct from a present
// empty array, which canonicalize would otherwise manufacture from a nil
// slice. Absence must never be reconstructed by re-tokenizing Subject.
DirectTokens *[]string `json:"direct_tokens,omitempty"`
// DirectCommandSubject and DirectRequestSubject are the permission checker's
// boundary-preserving direct identities, stored verbatim. This package never
// decodes or cross-validates them against Subject or DirectTokens; only
// internal/permissions parses them.
DirectCommandSubject string `json:"direct_command_subject,omitempty"`
DirectRequestSubject string `json:"direct_request_subject,omitempty"`
// See ToolExecStart.ChildInvocationID.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
PermissionPromptShown records that a permission prompt was displayed.
func (PermissionPromptShown) Kind ¶
func (PermissionPromptShown) Kind() string
type PermissionRevokeRequested ¶
type PermissionRevokeRequested struct {
EntryKind string `json:"kind"`
Subject string `json:"subject"`
PathScope string `json:"path_scope,omitempty"`
HostScope string `json:"host_scope,omitempty"`
GrantKind string `json:"grant_kind"`
ArgumentHash string `json:"argument_hash,omitempty"`
Source string `json:"source"`
}
PermissionRevokeRequested records that the /permissions revoke control asked for one stored grant to be removed. Its fields are the removed grant's own identity — permissions.DedupKey (EntryKind/Subject/PathScope/HostScope/GrantKind) plus the literal ArgumentHash — never the subject of the request that once triggered the grant, so a reader can match the record to the exact stored entry.
The record is not proof that this process removed a settings entry: the writable target is inspected before the delete takes its lock, so a persisted revoke means /permissions observed the grant and requested an idempotent delete that reported success.
func (PermissionRevokeRequested) Kind ¶
func (PermissionRevokeRequested) Kind() string
type ProviderRequestFailed ¶
type ProviderRequestFailed struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Phase string `json:"phase"`
HTTPStatus *int64 `json:"http_status,omitempty"`
PartialResponseChars int64 `json:"partial_response_chars"`
Reason string `json:"reason"`
ErrorDetail string `json:"error_detail"`
}
ProviderRequestFailed records a provider request failure before a usable response.
func (ProviderRequestFailed) Kind ¶
func (ProviderRequestFailed) Kind() string
type ProviderRequestRetry ¶
type ProviderRequestRetry struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Attempt int64 `json:"attempt"`
Phase string `json:"phase"`
Reason string `json:"reason"`
DelayMs int64 `json:"delay_ms"`
PartialCharsDiscarded int64 `json:"partial_chars_discarded"`
}
ProviderRequestRetry records one scheduled auto-retry of a transient provider-round failure. It is appended and flushed before the backoff wait, so a failed attempt is durable even if the process exits during the wait. attempt is the 1-based number of the attempt that just failed and is being retried; phase/reason carry the classified failure; delay_ms is the backoff (or honored Retry-After) wait in milliseconds; partial_chars_discarded is the assistant-content runes rolled back before re-issue and is meaningful only for a stream_drop (0 otherwise). The terminal provider_request_failed is unchanged, so the attempt count is reconstructed from these events.
func (ProviderRequestRetry) Kind ¶
func (ProviderRequestRetry) Kind() string
type ProviderRequestRetrySkipped ¶
type ProviderRequestRetrySkipped struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Attempt int64 `json:"attempt"`
Phase string `json:"phase"`
Reason string `json:"reason"`
SkipReason string `json:"skip_reason"`
PartialCharsDiscarded int64 `json:"partial_chars_discarded"`
}
ProviderRequestRetrySkipped records that a classified retryable provider-round failure was not scheduled for another attempt. attempt is the 1-based number of the attempt that just failed; phase/reason reuse the provider_request_failed taxonomy so a skip only ever records a (phase, reason) the classifier can produce; skip_reason is the closed set explaining why no retry followed; partial_chars_discarded is the assistant-content runes rolled back and is meaningful only for a stream_drop (0 otherwise). HTTP retryability stays emitter-enforced (via provider.Retryable in the retry loop), so there is no http_status field — mirroring provider_request_retry.
func (ProviderRequestRetrySkipped) Kind ¶
func (ProviderRequestRetrySkipped) Kind() string
type ProviderRoundTrip ¶
type ProviderRoundTrip struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
DurationMs int64 `json:"duration_ms"`
TurnID string `json:"turn_id,omitempty"`
RoundID string `json:"round_id,omitempty"`
UpstreamProvider string `json:"upstream_provider,omitempty"`
}
ProviderRoundTrip records the wall-clock latency of one provider round: the time around a single model call, from just before the request to the round's terminal outcome — a final answer, a tool-call handoff, an empty-response classification, a stream drop, or a pre-stream failure. An agentic turn records one per provider round. It is recorded even when the round fails, so a slow failure is visible alongside the paired provider_request_failed event. duration_ms is int64 milliseconds, matching the existing duration convention.
func (ProviderRoundTrip) Kind ¶
func (ProviderRoundTrip) Kind() string
type ProviderStreamIdle ¶
type ProviderStreamIdle struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
RoundElapsedMs int64 `json:"round_elapsed_ms"`
IdleMs int64 `json:"idle_ms"`
PartialChars int64 `json:"partial_chars"`
}
func (ProviderStreamIdle) Kind ¶
func (ProviderStreamIdle) Kind() string
type PruneFailure ¶
type PruneFailure struct {
Path string `json:"path"`
Reason string `json:"reason"`
Kind string `json:"kind"` // file_delete | dir_enumerate
}
PruneFailure is one entry of session_prune_summary.failures.
type QueuedPromptDiscarded ¶
type QueuedPromptDiscarded struct {
Text string `json:"text"`
ImageCount int64 `json:"image_count"`
Reason string `json:"reason"`
}
func (QueuedPromptDiscarded) Kind ¶
func (QueuedPromptDiscarded) Kind() string
type SecurityStateHalted ¶
type SecurityStateHalted struct {
Path string `json:"path"`
DetectionPoint string `json:"detection_point"`
Sections []string `json:"sections,omitempty"`
Labels []string `json:"labels,omitempty"`
}
SecurityStateHalted records one protected settings layer whose checkpoint stopped the launch or the turn.
func (SecurityStateHalted) Kind ¶
func (SecurityStateHalted) Kind() string
type SessionForked ¶
type SessionForked struct {
ToSessionID string `json:"to_session_id"`
}
SessionForked is appended to the original session as its final event on fork.
func (SessionForked) Kind ¶
func (SessionForked) Kind() string
type SessionPruneSummary ¶
type SessionPruneSummary struct {
FilesScanned int64 `json:"files_scanned"`
FilesDeleted int64 `json:"files_deleted"`
FilesFailed int64 `json:"files_failed"`
Failures []PruneFailure `json:"failures"`
ElapsedMs int64 `json:"elapsed_ms"`
}
SessionPruneSummary records the outcome of a retention prune pass.
func (SessionPruneSummary) Kind ¶
func (SessionPruneSummary) Kind() string
type SessionWriteFailed ¶
type SessionWriteFailed struct {
TargetPath string `json:"target_path"`
Reason string `json:"reason"`
ErrorCategory string `json:"error_category"`
ErrorDetail string `json:"error_detail"`
}
SessionWriteFailed records a failed atomic session-file write.
func (SessionWriteFailed) Kind ¶
func (SessionWriteFailed) Kind() string
type SlashCommand ¶
type SlashCommand struct {
Name string `json:"name"`
Args []string `json:"args"`
Outcome string `json:"outcome"`
ErrorDetail string `json:"error_detail,omitempty"`
}
SlashCommand records execution of a recognized slash command.
func (SlashCommand) Kind ¶
func (SlashCommand) Kind() string
type StreamInterrupted ¶
type StreamInterrupted struct {
Source string `json:"source"`
ContentChars int64 `json:"content_chars"`
}
StreamInterrupted records a user-initiated interruption of a model response.
func (StreamInterrupted) Kind ¶
func (StreamInterrupted) Kind() string
type StructuredReadEnd ¶
type StructuredReadEnd struct {
ToolName string `json:"tool_name"`
InvocationID string `json:"invocation_id"`
Outcome string `json:"outcome"`
DurationMs int64 `json:"duration_ms"`
// See StructuredReadStart.ChildInvocationID.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
func (StructuredReadEnd) Kind ¶
func (StructuredReadEnd) Kind() string
type StructuredReadRefused ¶
type StructuredReadRefused struct {
ToolName string `json:"tool_name"`
Reason string `json:"reason"`
BatchSize int64 `json:"batch_size"`
// See StructuredReadStart.ChildInvocationID. A refusal is child activity too: without it a
// child's rejected read is indistinguishable from the parent's.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
func (StructuredReadRefused) Kind ¶
func (StructuredReadRefused) Kind() string
type StructuredReadStart ¶
type StructuredReadStart struct {
ToolName string `json:"tool_name"`
PathScope string `json:"path_scope"`
InvocationID string `json:"invocation_id"`
ConfiguredConcurrency int64 `json:"configured_concurrency"`
// See ToolExecStart.ChildInvocationID. A child agent's read tools run through the
// structured-read path rather than tool_exec_*, so this is where their attribution lives.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
func (StructuredReadStart) Kind ¶
func (StructuredReadStart) Kind() string
type SuggestFollowupDebug ¶
type SuggestFollowupDebug struct {
Stage string `json:"stage"`
Provider string `json:"provider"`
ModelID string `json:"model_id"`
Mode string `json:"mode"`
Advertised *bool `json:"advertised,omitempty"`
LabelLen int64 `json:"label_len,omitempty"`
PromptLen int64 `json:"prompt_len,omitempty"`
Reason string `json:"reason,omitempty"`
}
SuggestFollowupDebug records one ordered stage of the development-only suggest_followup trace. provider/model_id/mode identify the turn that produced it. The remaining fields are stage-specific and deliberately privacy-safe: advertised is set only on request_built (was the tool in the advertised set), label_len/prompt_len carry rune lengths — never the suggestion text — on the stages that handle a concrete suggestion, and reason explains a discard on ghost_cleared. Persisting lengths and booleans rather than the label/prompt keeps the follow-up suggestion's ephemeral UI text out of the record.
func (SuggestFollowupDebug) Kind ¶
func (SuggestFollowupDebug) Kind() string
type ToolExecEnd ¶
type ToolExecEnd struct {
SubjectKind string `json:"subject_kind"`
Subject string `json:"subject"`
ExitCode int64 `json:"exit_code"`
DurationMs int64 `json:"duration_ms"`
Stdout string `json:"stdout,omitempty"`
Stderr string `json:"stderr,omitempty"`
Truncated bool `json:"truncated"`
OriginalBytes *OriginalBytes `json:"original_bytes,omitempty"`
InvocationID string `json:"invocation_id"`
// See ToolExecStart.ChildInvocationID.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
ToolExecEnd records the completion of a tool invocation.
func ToolExecEndFromBounded ¶
func ToolExecEndFromBounded(exec BoundedToolExec, cap int) ToolExecEnd
func (ToolExecEnd) Kind ¶
func (ToolExecEnd) Kind() string
type ToolExecStart ¶
type ToolExecStart struct {
SubjectKind string `json:"subject_kind"`
Subject string `json:"subject"`
PathScope string `json:"path_scope"`
InvocationID string `json:"invocation_id"`
// ChildInvocationID names the child_agent_start this call belongs to; a parent's own
// call omits it. Attribution must be read from here rather than inferred from a child's
// start/end interval, because disjoint children may run concurrently.
ChildInvocationID string `json:"child_invocation_id,omitempty"`
}
ToolExecStart records the start of a tool invocation.
func (ToolExecStart) Kind ¶
func (ToolExecStart) Kind() string
type TurnLatency ¶
type TurnLatency struct {
Provider string `json:"provider"`
ModelID string `json:"model_id"`
DurationMs int64 `json:"duration_ms"`
}
TurnLatency records the end-to-end wall-clock latency of one completed, user-visible turn: the elapsed time from the point the user's input was accepted to the point the final answer was committed. One is recorded per completed agentic turn, on the final no-tool answer — failed or interrupted turns record none. duration_ms is int64 milliseconds, matching the tool_exec_end.duration_ms / session_prune_summary.elapsed_ms convention.
func (TurnLatency) Kind ¶
func (TurnLatency) Kind() string
type TurnTerminal ¶
type TurnTerminal struct {
TurnID string `json:"turn_id"`
RoundID string `json:"round_id"`
Outcome string `json:"outcome"`
FailurePhase string `json:"failure_phase,omitempty"`
FailedTool string `json:"failed_tool,omitempty"`
FailureReason string `json:"failure_reason,omitempty"`
DispatchStarted bool `json:"dispatch_started"`
}
func (TurnTerminal) Kind ¶
func (TurnTerminal) Kind() string
type WriteFailureHandler ¶
type WriteFailureHandler func(cat fserrors.Category, reason sessions.WriteReason, err error)
WriteFailureHandler receives the outcome of the post-append flush when it fails (point e). It carries exactly the values sessions.Store.Flush returns, so a caller can drive the session write-failure protocol (sessionfailures.HandleWriteFailure) without internal/events importing that failure code and coupling the event package to session failure policy. Keeping the callback minimal — only Flush's return tuple — lets the final write-failure API change without touching this helper.