Documentation
¶
Overview ¶
Package crs provides the Code Reasoning State (CRS) - the central mutable state container for the Aleutian Hybrid MCTS system.
Architecture Overview ¶
CRS sits between the application layer (activities) and the algorithm layer, providing immutable snapshots for reading and delta-based mutations for writing.
┌─────────────────────────────────────────────────────────────────────────┐
│ APPLICATION LAYER │
│ (Activities: Search, Constraint, etc.) │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ 1. Snapshot() - get immutable view
│ 2. Apply(delta) - atomic mutation
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ CRS (Code Reasoning State) │
│ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ Snapshot (Immutable) │ │
│ │ ┌─────────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ │
│ │ │ Proof │ │ Constraint │ │ Similarity │ │ Dependency │ │ │
│ │ │ Index │ │ Index │ │ Index │ │ Index │ │ │
│ │ └─────────┘ └────────────┘ └────────────┘ └────────────┘ │ │
│ │ ┌─────────┐ ┌────────────┐ │ │
│ │ │ History │ │ Streaming │ │ │
│ │ │ Index │ │ Index │ │ │
│ │ └─────────┘ └────────────┘ │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ Key Operations: │
│ • Snapshot() → CRSSnapshot (copy-on-write, immutable) │
│ • Apply(delta) → validates, updates indexes, increments generation │
│ • Query() → cross-index query API │
│ • Generation() → current state version │
└────────────────────────────────┬────────────────────────────────────────┘
│
│ Algorithms produce deltas
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ ALGORITHM LAYER │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ PN-MCTS │ │ CDCL │ │ TMS │ │ HTN │ │ MinHash │ ... │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
│ Pure Functions: Process(ctx, snapshot, input) → (output, delta, error) │
└─────────────────────────────────────────────────────────────────────────┘
Core Concepts ¶
## Snapshot
A snapshot is an immutable view of CRS at a point in time. Algorithms read from snapshots, never from CRS directly. This ensures:
- Thread safety: multiple algorithms can read the same snapshot concurrently
- Consistency: all reads within an algorithm see the same state
- Performance: copy-on-write semantics make snapshots cheap to create
## Delta
A delta represents a change to CRS state. Algorithms produce deltas as output, which activities then merge and apply to CRS. Deltas support:
- Validation: deltas are validated before application
- Merging: multiple deltas can be combined
- Conflict detection: overlapping changes are detected
- Atomicity: either all changes apply or none do
## Generation
Every Apply() increments the generation counter. This enables:
- Cache invalidation: detect when cached data is stale
- Ordering: determine which state is newer
- Debugging: trace state evolution
Thread Safety ¶
CRS uses a single RWMutex for thread safety:
- Snapshot() acquires read lock briefly, returns immutable snapshot
- Apply() acquires write lock, validates and applies delta
- Multiple readers can hold snapshots concurrently
- Writer blocks until all readers release
All CRS methods accept context.Context and respect cancellation.
Observability ¶
CRS implements the eval.Evaluable interface, exposing:
- Properties: snapshot_immutability, delta_idempotence, generation_monotonic
- Metrics: crs_snapshot_duration, crs_apply_duration, crs_generation
- Health checks: index connectivity, memory bounds
Hard/Soft Signal Boundary ¶
CRS enforces the hard/soft signal boundary from CB-28C:
- Hard signals (compiler errors, test results): can mark nodes DISPROVEN
- Soft signals (LLM feedback): cannot mark nodes DISPROVEN
Delta validation rejects any delta that violates this boundary.
Usage Example ¶
// Create CRS
crs := crs.New(crs.DefaultConfig())
// Get snapshot for algorithm
snapshot := crs.Snapshot()
// Algorithm processes snapshot
output, delta, err := algorithm.Process(ctx, snapshot, input)
if err != nil {
return err
}
// Apply delta to CRS
metrics, err := crs.Apply(ctx, delta)
if err != nil {
return fmt.Errorf("apply delta: %w", err)
}
// Check new generation
fmt.Printf("New generation: %d\n", crs.Generation())
Index ¶
- Constants
- Variables
- func ComputeProjectHash(projectPath string) string
- func FindFilesModifiedSince(ctx context.Context, projectPath string, since time.Time, ...) ([]string, error)
- func GetStateKey(step StepRecord) string
- func GetToolStateKey(step StepRecord) string
- func RegisterDeltaTypesForSSE()
- func ValidateProjectHash(hash string) error
- type Actor
- type AnalyticsDelta
- func (d *AnalyticsDelta) ConflictsWith(_ Delta) bool
- func (d *AnalyticsDelta) IndexesAffected() []string
- func (d *AnalyticsDelta) Merge(other Delta) (Delta, error)
- func (d *AnalyticsDelta) Source() SignalSource
- func (d *AnalyticsDelta) Timestamp() int64
- func (d *AnalyticsDelta) Type() DeltaType
- func (d *AnalyticsDelta) Validate(_ Snapshot) error
- type AnalyticsHistory
- type AnalyticsQueryParams
- type AnalyticsQueryType
- type AnalyticsRecord
- func (r *AnalyticsRecord) GetProofDoneKey() string
- func (r *AnalyticsRecord) GetProofFoundKey() string
- func (r *AnalyticsRecord) HasResults() bool
- func (r *AnalyticsRecord) TruncateResults() *AnalyticsRecord
- func (r *AnalyticsRecord) WithCycles(cycles [][]string) *AnalyticsRecord
- func (r *AnalyticsRecord) WithGraphGeneration(gen int64) *AnalyticsRecord
- func (r *AnalyticsRecord) WithParams(params map[string]any) *AnalyticsRecord
- func (r *AnalyticsRecord) WithPath(path []string) *AnalyticsRecord
- func (r *AnalyticsRecord) WithResults(results []string) *AnalyticsRecord
- func (r *AnalyticsRecord) WithTypedParams(params AnalyticsQueryParams) *AnalyticsRecord
- type ApplyMetrics
- type BackupMetadata
- type BackupOptions
- type BadgerJournal
- func (j *BadgerJournal) Append(ctx context.Context, delta Delta) error
- func (j *BadgerJournal) AppendBatch(ctx context.Context, deltas []Delta) error
- func (j *BadgerJournal) Backup(ctx context.Context, w io.Writer) error
- func (j *BadgerJournal) Checkpoint(ctx context.Context) error
- func (j *BadgerJournal) Close() error
- func (j *BadgerJournal) DB() *badger.DB
- func (j *BadgerJournal) IsAvailable() bool
- func (j *BadgerJournal) IsDegraded() bool
- func (j *BadgerJournal) Replay(ctx context.Context) ([]Delta, error)
- func (j *BadgerJournal) ReplayStream(ctx context.Context) (<-chan DeltaOrError, error)
- func (j *BadgerJournal) Restore(ctx context.Context, r io.Reader) error
- func (j *BadgerJournal) Stats() JournalStats
- func (j *BadgerJournal) Sync() error
- type CRS
- type CRSExport
- type Checkpoint
- type CircuitBreakerResult
- type Clause
- type ClauseCheckResult
- type ClausePersistence
- type ClauseScope
- type CompositeDelta
- func (d *CompositeDelta) ConflictsWith(other Delta) bool
- func (d *CompositeDelta) IndexesAffected() []string
- func (d *CompositeDelta) Merge(other Delta) (Delta, error)
- func (d *CompositeDelta) Source() SignalSource
- func (d *CompositeDelta) Timestamp() int64
- func (d *CompositeDelta) Type() DeltaType
- func (d *CompositeDelta) Validate(snapshot Snapshot) error
- type Config
- type Constraint
- type ConstraintDelta
- func (d *ConstraintDelta) ConflictsWith(other Delta) bool
- func (d *ConstraintDelta) IndexesAffected() []string
- func (d *ConstraintDelta) Merge(other Delta) (Delta, error)
- func (d *ConstraintDelta) Source() SignalSource
- func (d *ConstraintDelta) Timestamp() int64
- func (d *ConstraintDelta) Type() DeltaType
- func (d *ConstraintDelta) Validate(snapshot Snapshot) error
- type ConstraintEntry
- type ConstraintIndexExport
- type ConstraintIndexView
- type ConstraintType
- type ConstraintUpdate
- type CycleAnalysis
- type CycleDetectionResult
- type CycleDetector
- type CycleDetectorConfig
- type CycleDetectorStats
- type Decision
- type DecisionGraph
- type Delta
- type DeltaHistoryView
- type DeltaHistoryWorker
- func (w *DeltaHistoryWorker) All(ctx context.Context) ([]DeltaRecord, error)
- func (w *DeltaHistoryWorker) Close()
- func (w *DeltaHistoryWorker) Explain(ctx context.Context, nodeID string) ([]DeltaRecord, error)
- func (w *DeltaHistoryWorker) GetByGeneration(ctx context.Context, gen int64) (DeltaRecord, bool, error)
- func (w *DeltaHistoryWorker) GetByNode(ctx context.Context, nodeID string) ([]DeltaRecord, error)
- func (w *DeltaHistoryWorker) GetRange(ctx context.Context, fromGen, toGen int64) ([]DeltaRecord, error)
- func (w *DeltaHistoryWorker) Record(delta Delta, gen int64, source, sessionID string, metadata map[string]string)
- func (w *DeltaHistoryWorker) Size(ctx context.Context) (int, error)
- type DeltaOrError
- type DeltaRecord
- type DeltaType
- type DependencyDelta
- func (d *DependencyDelta) ConflictsWith(other Delta) bool
- func (d *DependencyDelta) IndexesAffected() []string
- func (d *DependencyDelta) Merge(other Delta) (Delta, error)
- func (d *DependencyDelta) Source() SignalSource
- func (d *DependencyDelta) Timestamp() int64
- func (d *DependencyDelta) Type() DeltaType
- func (d *DependencyDelta) Validate(snapshot Snapshot) error
- type DependencyEdge
- type DependencyEdgeExport
- type DependencyIndexExport
- type DependencyIndexView
- type ErrorCategory
- type ExportOptions
- type ExportResult
- type FailureEvent
- type FailureType
- type GraphAnalyticsQuery
- type GraphBackedDependencyIndex
- func (d *GraphBackedDependencyIndex) AllEdges() map[string][]string
- func (d *GraphBackedDependencyIndex) DependedBy(nodeID string) []string
- func (d *GraphBackedDependencyIndex) DependsOn(nodeID string) []string
- func (d *GraphBackedDependencyIndex) Generation() int64
- func (d *GraphBackedDependencyIndex) HasCycle(nodeID string) bool
- func (d *GraphBackedDependencyIndex) InvalidateCache()
- func (d *GraphBackedDependencyIndex) IsGraphBacked() bool
- func (d *GraphBackedDependencyIndex) Size() int
- type GraphCommunity
- type GraphHotSpot
- type GraphQuery
- type GraphQueryConfig
- type GraphRefreshCoordinator
- type HistoryDelta
- func (d *HistoryDelta) ConflictsWith(_ Delta) bool
- func (d *HistoryDelta) IndexesAffected() []string
- func (d *HistoryDelta) Merge(other Delta) (Delta, error)
- func (d *HistoryDelta) Source() SignalSource
- func (d *HistoryDelta) Timestamp() int64
- func (d *HistoryDelta) Type() DeltaType
- func (d *HistoryDelta) Validate(_ Snapshot) error
- type HistoryEntry
- type HistoryEntryExport
- type HistoryIndexExport
- type HistoryIndexView
- type ImportOptions
- type ImportedState
- type IndexMask
- type IndexesExport
- type Journal
- type JournalConfig
- type JournalStats
- type KeyValue
- type Literal
- type NATSJournal
- func (j *NATSJournal) Append(ctx context.Context, delta Delta) error
- func (j *NATSJournal) AppendBatch(ctx context.Context, deltas []Delta) error
- func (j *NATSJournal) Backup(ctx context.Context, w io.Writer) error
- func (j *NATSJournal) Checkpoint(ctx context.Context) error
- func (j *NATSJournal) Close() error
- func (j *NATSJournal) IsAvailable() bool
- func (j *NATSJournal) IsDegraded() bool
- func (j *NATSJournal) Replay(ctx context.Context) ([]Delta, error)
- func (j *NATSJournal) ReplayStream(ctx context.Context) (<-chan DeltaOrError, error)
- func (j *NATSJournal) Restore(ctx context.Context, r io.Reader) error
- func (j *NATSJournal) Stats() JournalStats
- func (j *NATSJournal) Sync() error
- type NATSJournalConfig
- type NodeFrequency
- type NodeStats
- type Outcome
- type PersistenceConfig
- type PersistenceManager
- func (pm *PersistenceManager) BackupPath(projectHash string) string
- func (pm *PersistenceManager) Close() error
- func (pm *PersistenceManager) ExportPath(projectHash string) string
- func (pm *PersistenceManager) GetBackupMetadata(projectHash string) (*BackupMetadata, error)
- func (pm *PersistenceManager) HasBackup(projectHash string) bool
- func (pm *PersistenceManager) LoadBackup(ctx context.Context, projectHash string, journal Journal) (*BackupMetadata, error)
- func (pm *PersistenceManager) LockPath(projectHash string) string
- func (pm *PersistenceManager) MetadataPath(projectHash string) string
- func (pm *PersistenceManager) PrevBackupPath(projectHash string) string
- func (pm *PersistenceManager) PrevMetadataPath(projectHash string) string
- func (pm *PersistenceManager) ProjectDir(projectHash string) string
- func (pm *PersistenceManager) SaveBackup(ctx context.Context, projectHash string, journal Journal, opts *BackupOptions) (*BackupMetadata, error)
- func (pm *PersistenceManager) SetRefreshCoordinator(coordinator GraphRefreshCoordinator)
- type ProofDelta
- func (d *ProofDelta) ConflictsWith(other Delta) bool
- func (d *ProofDelta) IndexesAffected() []string
- func (d *ProofDelta) Merge(other Delta) (Delta, error)
- func (d *ProofDelta) Source() SignalSource
- func (d *ProofDelta) Timestamp() int64
- func (d *ProofDelta) Type() DeltaType
- func (d *ProofDelta) Validate(snapshot Snapshot) error
- type ProofEntry
- type ProofIndexExport
- type ProofIndexView
- type ProofNumber
- type ProofStatus
- type ProofUpdate
- type ProofUpdateType
- type QueryAPI
- type ReasoningSummary
- type ReasoningTrace
- type RestoreResult
- type Sanitizer
- type SecretSanitizer
- type Serializer
- func (s *Serializer) ComputeSummary(snapshot Snapshot) ReasoningSummary
- func (s *Serializer) Export(snapshot Snapshot, sessionID string) *CRSExport
- func (s *Serializer) ExportFull(ctx context.Context, snapshot Snapshot, sessionID string, opts *ExportOptions) (*ExportResult, error)
- func (s *Serializer) ExportSummaryOnly(snapshot Snapshot) ReasoningSummary
- func (s *Serializer) Import(ctx context.Context, export *CRSExport, opts *ImportOptions) (*ImportedState, error)
- type SessionIdentifier
- type SessionRestoreFailedEvent
- type SessionRestoredEvent
- type SessionRestorer
- type SessionRestorerConfig
- type SignalSource
- type SimilarityDelta
- func (d *SimilarityDelta) ConflictsWith(other Delta) bool
- func (d *SimilarityDelta) IndexesAffected() []string
- func (d *SimilarityDelta) Merge(other Delta) (Delta, error)
- func (d *SimilarityDelta) Source() SignalSource
- func (d *SimilarityDelta) Timestamp() int64
- func (d *SimilarityDelta) Type() DeltaType
- func (d *SimilarityDelta) Validate(_ Snapshot) error
- type SimilarityIndexExport
- type SimilarityIndexView
- type SimilarityMatch
- type SimilarityPairData
- type SimilarityPairExport
- type Snapshot
- type StepRecord
- type StreamDelta
- type StreamingDelta
- func (d *StreamingDelta) ConflictsWith(_ Delta) bool
- func (d *StreamingDelta) IndexesAffected() []string
- func (d *StreamingDelta) Merge(other Delta) (Delta, error)
- func (d *StreamingDelta) Source() SignalSource
- func (d *StreamingDelta) Timestamp() int64
- func (d *StreamingDelta) Type() DeltaType
- func (d *StreamingDelta) Validate(_ Snapshot) error
- type StreamingIndexExport
- type StreamingIndexView
- type ToolParams
- type TraceConfig
- type TraceRecorder
- type TraceStep
- type TraceStepBuilder
- func (b *TraceStepBuilder) Build() TraceStep
- func (b *TraceStepBuilder) WithAction(action string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithConstraint(id, constraintType string, nodes []string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithDependency(from, to string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithDuration(d time.Duration) *TraceStepBuilder
- func (b *TraceStepBuilder) WithError(err string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithMetadata(key, value string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithProofUpdate(nodeID, status, reason, source string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithProofUpdateTyped(nodeID string, updateType ProofUpdateType, delta uint64, reason string, ...) *TraceStepBuilder
- func (b *TraceStepBuilder) WithSymbolsFound(symbols []string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithTarget(target string) *TraceStepBuilder
- func (b *TraceStepBuilder) WithTool(tool string) *TraceStepBuilder
Constants ¶
const ( // ProofKeyAnalyticsHotspotsDone indicates hotspots analysis was run. ProofKeyAnalyticsHotspotsDone = "analytics:hotspots:done" // ProofKeyAnalyticsHotspotsFound indicates hotspots were found. ProofKeyAnalyticsHotspotsFound = "analytics:hotspots:found" // ProofKeyAnalyticsDeadCodeDone indicates dead code analysis was run. ProofKeyAnalyticsDeadCodeDone = "analytics:dead_code:done" // ProofKeyAnalyticsDeadCodeFound indicates dead code was found. ProofKeyAnalyticsDeadCodeFound = "analytics:dead_code:found" // ProofKeyAnalyticsCyclesDone indicates cycle detection was run. ProofKeyAnalyticsCyclesDone = "analytics:cycles:done" // ProofKeyAnalyticsCyclesFound indicates cycles were found. ProofKeyAnalyticsCyclesFound = "analytics:cycles:found" // ProofKeyAnalyticsPathDone indicates path analysis was run. ProofKeyAnalyticsPathDone = "analytics:path:done" // ProofKeyAnalyticsPathFound indicates a path was found. ProofKeyAnalyticsPathFound = "analytics:path:found" // ProofKeyAnalyticsCouplingDone indicates coupling analysis was run. ProofKeyAnalyticsCouplingDone = "analytics:coupling:done" // ProofKeyAnalyticsCouplingFound indicates coupling issues were found. ProofKeyAnalyticsCouplingFound = "analytics:coupling:found" // ProofKeyAnalyticsReferencesDone indicates references analysis was run. ProofKeyAnalyticsReferencesDone = "analytics:references:done" // ProofKeyAnalyticsReferencesFound indicates references were found. ProofKeyAnalyticsReferencesFound = "analytics:references:found" )
ProofKeyAnalytics* are typed constants for analytics proof keys. Using constants prevents typos and enables IDE autocomplete.
const ( // DefaultCheckpointMaxAge is the maximum age of a checkpoint before invalidation. // GR-36 Code Review Fix: S2 - No magic numbers. DefaultCheckpointMaxAge = 7 * 24 * time.Hour // DefaultMaxFilesToRefresh is the maximum files to mark dirty after restore. // Beyond this threshold, a full rebuild is more efficient. DefaultMaxFilesToRefresh = 1000 // CheckpointKeyHashBytes is the number of bytes used for checkpoint key hash. // GR-36 Code Review Fix: R1 - Use 16 bytes (128 bits) to match ProjectHashLength. CheckpointKeyHashBytes = 16 // DefaultSessionRestoreRetries is the number of retry attempts on transient failures. // GR-36 Code Review Fix: R4 - Add retry logic. DefaultSessionRestoreRetries = 3 )
const BadgerDBVersion = "v4.9.1"
BadgerDBVersion is the version of BadgerDB used for backup compatibility.
IMPORTANT: This MUST match the version in go.mod. When upgrading BadgerDB:
- Update go.mod: go get github.com/dgraph-io/badger/v4@vX.Y.Z
- Update this constant to match
- Test backup/restore with existing backups
Reference: go.mod -> github.com/dgraph-io/badger/v4 Build verification: go generate ./... should fail if mismatch (TODO: add check)
const CurrentSchemaVersion = "1.0"
CurrentSchemaVersion is the backup schema version.
const DefaultCircuitBreakerThreshold = 2
DefaultCircuitBreakerThreshold is the fallback threshold for tool execution count when no proof data exists. If a tool has been executed this many times, the circuit breaker fires. This is used for backwards compatibility with code that hasn't yet integrated proof numbers.
NOTE: This value should match maxRepeatedToolCalls in execute.go. Feb 13, 2026: Lowered from 5 to 2 based on integration test evidence. Threshold=5 allowed too much wasteful exploration (Test 95: 5 identical calls). Threshold=2 prevents tool loops while still allowing legitimate multi-call patterns. CRS-16: Per-tool overrides are configured via Config.CircuitBreakerThresholds.
const DefaultDeltaQueryChannelSize = 10
DefaultDeltaQueryChannelSize is the buffer size for the query channel.
const DefaultDeltaRecordChannelSize = 100
DefaultDeltaRecordChannelSize is the buffer size for the record channel.
const DefaultInitialProofNumber uint64 = 10
DefaultInitialProofNumber is the starting proof number for new nodes. Represents moderate cost to prove - not too easy, not too hard.
const DefaultMaxDeltaRecords = 1000
DefaultMaxDeltaRecords is the default maximum number of delta records to keep.
const DefaultMaxDependencyEdges = 100_000
DefaultMaxDependencyEdges is the default limit for dependency edges export.
const DefaultMaxSimilarityPairs = 100_000
DefaultMaxSimilarityPairs is the default limit for similarity pairs export.
const MaxAnalyticsHistoryRecords = 100
MaxAnalyticsHistoryRecords is the maximum number of analytics records to keep.
const MaxPropagationDepth = 100
MaxPropagationDepth prevents runaway propagation in cyclic graphs. 100 levels is sufficient for any reasonable decision tree.
const MaxResultsPerRecord = 50
MaxResultsPerRecord limits stored result IDs to prevent memory bloat.
const ProjectHashLength = 16 // 64 bits = 16 hex chars
ProjectHashLength is the expected length of a project hash (SHA256 truncated).
const ProofNumberInfinite uint64 = ^uint64(0)
ProofNumberInfinite represents a disproven path (infinite cost to prove). Using max uint64 value.
Variables ¶
var ( // ErrGraphQueryClosed is returned when operations are attempted on a closed adapter. ErrGraphQueryClosed = errors.New("graph query adapter is closed") // ErrGraphNotAvailable is returned when graph is not available. ErrGraphNotAvailable = errors.New("graph is not available") )
var ( // ErrJournalClosed is returned when operations are called on a closed journal. ErrJournalClosed = errors.New("journal is closed") // ErrJournalCorrupted is returned when journal data fails integrity check. ErrJournalCorrupted = errors.New("journal entry corrupted (CRC mismatch)") // ErrJournalFull is returned when journal exceeds MaxJournalBytes. ErrJournalFull = errors.New("journal size limit exceeded") // ErrJournalDegraded is returned when journal is operating in degraded mode. ErrJournalDegraded = errors.New("journal operating in degraded mode") // ErrJournalSequenceGap is returned when replay detects sequence number gaps. ErrJournalSequenceGap = errors.New("journal sequence number gap detected") // ErrNilDeltaJournal is returned when attempting to append nil delta. ErrNilDeltaJournal = errors.New("delta must not be nil") )
var ( // ErrBackupCorrupted indicates backup data failed integrity check. ErrBackupCorrupted = errors.New("backup corrupted: content hash mismatch") // ErrBackupVersionMismatch indicates BadgerDB version incompatibility. ErrBackupVersionMismatch = errors.New("backup BadgerDB version mismatch") // ErrBackupNotFound indicates no backup exists for the project. ErrBackupNotFound = errors.New("backup not found") // ErrBackupLockFailed indicates file lock acquisition failed. ErrBackupLockFailed = errors.New("failed to acquire backup lock") // ErrPersistenceManagerClosed indicates the manager has been closed. ErrPersistenceManagerClosed = errors.New("persistence manager is closed") // ErrRestoreInProgress indicates a restore is already in progress. ErrRestoreInProgress = errors.New("restore already in progress") )
var ( // ErrSessionIdentifierNil is returned when session identifier is nil. ErrSessionIdentifierNil = errors.New("session identifier must not be nil") // ErrProjectPathEmpty is returned when project path is empty. ErrProjectPathEmpty = errors.New("project path must not be empty") // ErrCheckpointTooOld is returned when checkpoint exceeds max age. ErrCheckpointTooOld = errors.New("checkpoint too old") // ErrProjectHashMismatch is returned when project hash doesn't match checkpoint. ErrProjectHashMismatch = errors.New("project hash mismatch") // ErrSchemaVersionMismatch is returned when schema versions don't match. ErrSchemaVersionMismatch = errors.New("schema version mismatch") // ErrTooManyModifiedFiles is returned when modified file count exceeds threshold. ErrTooManyModifiedFiles = errors.New("too many modified files, full rebuild recommended") )
var ( // ErrNilContext is returned when context is nil. ErrNilContext = errors.New("context must not be nil") // ErrNilDelta is returned when delta is nil. ErrNilDelta = errors.New("delta must not be nil") // ErrDeltaValidation is returned when delta validation fails. ErrDeltaValidation = errors.New("delta validation failed") // ErrDeltaConflict is returned when deltas conflict. ErrDeltaConflict = errors.New("delta conflict detected") // ErrSnapshotStale is returned when snapshot is too old. ErrSnapshotStale = errors.New("snapshot is stale") // ErrIndexNotFound is returned when an index doesn't exist. ErrIndexNotFound = errors.New("index not found") // ErrHardSoftBoundaryViolation is returned when soft signal attempts hard action. ErrHardSoftBoundaryViolation = errors.New("soft signal cannot perform hard action") // ErrApplyRollback is returned when apply partially failed and rolled back. ErrApplyRollback = errors.New("apply failed, changes rolled back") )
var DefaultClauseConfig = ClausePersistence{ Scope: ClauseScopeProject, TTL: 7 * 24 * time.Hour, MaxClauses: 1000, }
DefaultClauseConfig is the default clause persistence configuration.
var ErrDeltaHistoryClosed = errors.New("delta history worker is closed")
ErrDeltaHistoryClosed is returned when querying a closed delta history worker.
var ErrMetadataCorrupted = errors.New("metadata corrupted: hash mismatch")
ErrMetadataCorrupted indicates the metadata file failed integrity check.
var ErrUnknownQueryType = errors.New("unknown analytics query type")
ErrUnknownQueryType is returned when an unknown query type is used.
Functions ¶
func ComputeProjectHash ¶
ComputeProjectHash generates a project hash from a path.
Description:
Computes a SHA256 hash of the project path and returns the first 16 hex characters. This provides consistent project identification across sessions.
Inputs:
- projectPath: Absolute path to the project root.
Outputs:
- string: 16-character hex hash.
Thread Safety: Safe for concurrent use (stateless).
func FindFilesModifiedSince ¶
func FindFilesModifiedSince( ctx context.Context, projectPath string, since time.Time, config *SessionRestorerConfig, ) ([]string, error)
FindFilesModifiedSince finds files changed since a timestamp.
Description:
Uses git status for git repositories (much faster) and falls back to mtime scan for non-git directories. Returns an error if more files than MaxFilesToRefresh are found.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- projectPath: Path to the project root.
- since: Find files modified after this time.
- config: Configuration with UseGitStatus and MaxFilesToRefresh.
Outputs:
- []string: Paths of modified files relative to project root.
- error: Non-nil on failure or if too many files modified.
Thread Safety: Safe for concurrent use.
func GetStateKey ¶
func GetStateKey(step StepRecord) string
GetStateKey generates a normalized state key for cycle detection.
Description:
Creates a canonical state representation that ignores step numbers but captures the semantically relevant state: - Tool name (what tool was used/selected) - Outcome (success/failure/forced) - Actor (who made the decision) This enables detecting semantic cycles like: "router selects list_packages -> executes -> router selects list_packages" regardless of step numbers or timestamps.
Inputs:
step - The step record to generate a key for.
Outputs:
string - Normalized state key (e.g., "tool:list_packages:success:router").
func GetToolStateKey ¶
func GetToolStateKey(step StepRecord) string
GetToolStateKey generates a tool-focused state key for cycle detection.
Description:
Creates a simpler state key focused only on tool usage. Use this for detecting tool repetition cycles specifically.
Inputs:
step - The step record to generate a key for.
Outputs:
string - Tool-focused state key (e.g., "list_packages:success").
func RegisterDeltaTypesForSSE ¶
func RegisterDeltaTypesForSSE()
RegisterDeltaTypesForSSE exposes gob type registration for SSE decoding. CRS-27: Called by the SSE handler to ensure delta types are registered before decoding NATS messages.
Thread Safety: Safe for concurrent use (uses sync.Once internally).
func ValidateProjectHash ¶
ValidateProjectHash checks if a hash is valid.
Description:
Validates that the project hash is a hex string of 8-64 characters. Used by GR-33, GR-34, and GR-36 for consistent validation.
Inputs:
- hash: The project hash to validate.
Outputs:
- error: Non-nil if validation fails.
Thread Safety: Safe for concurrent use (stateless).
Types ¶
type Actor ¶
type Actor string
Actor identifies who made a decision in the agent reasoning process.
type AnalyticsDelta ¶
type AnalyticsDelta struct {
// Record is the analytics record to add.
Record *AnalyticsRecord
// contains filtered or unexported fields
}
AnalyticsDelta represents an analytics query to record in CRS.
Description:
When applied, records the analytics query in CRS history, sets relevant proof numbers, and emits events for coordination.
Thread Safety: NOT safe for concurrent modification.
func CreateAnalyticsDelta ¶
func CreateAnalyticsDelta( queryType AnalyticsQueryType, resultCount int, executionMs int64, ) *AnalyticsDelta
createAnalyticsDeltaFromParams is a helper to create an analytics delta.
Description:
Convenience function for tools to create analytics deltas.
Inputs:
- queryType: The type of analytics query.
- resultCount: Number of results.
- executionMs: Execution time in milliseconds.
Outputs:
*AnalyticsDelta: The new delta.
func NewAnalyticsDelta ¶
func NewAnalyticsDelta(source SignalSource, record *AnalyticsRecord) *AnalyticsDelta
NewAnalyticsDelta creates a new analytics delta.
Inputs:
- source: The signal source (should be SignalSourceHard for analytics).
- record: The analytics record to add. Must not be nil.
Outputs:
*AnalyticsDelta: The new delta.
func (*AnalyticsDelta) ConflictsWith ¶
func (d *AnalyticsDelta) ConflictsWith(_ Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*AnalyticsDelta) IndexesAffected ¶
func (d *AnalyticsDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Description:
Analytics deltas affect both the analytics history and proof index (for completion markers).
Thread Safety: Returns a shared slice. Callers must not modify.
func (*AnalyticsDelta) Merge ¶
func (d *AnalyticsDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*AnalyticsDelta) Source ¶
func (d *AnalyticsDelta) Source() SignalSource
func (*AnalyticsDelta) Type ¶
func (d *AnalyticsDelta) Type() DeltaType
Type returns the delta type.
func (*AnalyticsDelta) Validate ¶
func (d *AnalyticsDelta) Validate(_ Snapshot) error
Validate checks if this delta can be applied.
Description:
Validates the analytics record structure. Ensures required fields are present and results match the query type.
Inputs:
snapshot: Current CRS state (unused for analytics).
Outputs:
error: Non-nil if validation fails.
Thread Safety: Safe for concurrent use (read-only operation).
type AnalyticsHistory ¶
type AnalyticsHistory struct {
// contains filtered or unexported fields
}
AnalyticsHistory stores recent analytics records.
Description:
Thread-safe ring buffer for analytics history with O(1) insertions. Uses channel-based concurrency pattern per project standards.
Thread Safety: Safe for concurrent use.
func NewAnalyticsHistory ¶
func NewAnalyticsHistory(maxSize int) *AnalyticsHistory
NewAnalyticsHistory creates a new analytics history.
Inputs:
maxSize: Maximum number of records to keep.
Outputs:
*AnalyticsHistory: The new history instance.
func (*AnalyticsHistory) Add ¶
func (h *AnalyticsHistory) Add(record *AnalyticsRecord)
Add records an analytics query.
Inputs:
record: The record to add. Must not be nil.
func (*AnalyticsHistory) All ¶
func (h *AnalyticsHistory) All() []*AnalyticsRecord
All returns a copy of all records in chronological order.
Outputs:
[]*AnalyticsRecord: Copy of all records.
func (*AnalyticsHistory) GetLast ¶
func (h *AnalyticsHistory) GetLast(queryType AnalyticsQueryType) *AnalyticsRecord
GetLast returns the most recent record of a given type.
Inputs:
queryType: The type of query to find.
Outputs:
*AnalyticsRecord: The most recent matching record, or nil if not found.
func (*AnalyticsHistory) HasRun ¶
func (h *AnalyticsHistory) HasRun(queryType AnalyticsQueryType) bool
HasRun returns true if a query type has been run.
Inputs:
queryType: The type of query to check.
Outputs:
bool: True if the query type has been run.
func (*AnalyticsHistory) Size ¶
func (h *AnalyticsHistory) Size() int
Size returns the number of records stored.
type AnalyticsQueryParams ¶
type AnalyticsQueryParams struct {
// Limit is the maximum results for hotspots queries.
Limit int `json:"limit,omitempty"`
// FromSymbol is the starting symbol for path queries.
FromSymbol string `json:"from_symbol,omitempty"`
// ToSymbol is the target symbol for path queries.
ToSymbol string `json:"to_symbol,omitempty"`
// TargetSymbol is the symbol for references queries.
TargetSymbol string `json:"target_symbol,omitempty"`
// PackageName is the package for coupling queries.
PackageName string `json:"package_name,omitempty"`
}
AnalyticsQueryParams contains typed parameters for analytics queries.
Description:
Replaces map[string]any to comply with CLAUDE.md §4.5. Each field is optional - only populate what's relevant for the query type.
Thread Safety: NOT safe for concurrent modification.
type AnalyticsQueryType ¶
type AnalyticsQueryType string
AnalyticsQueryType identifies the type of analytics query.
const ( // AnalyticsQueryHotspots finds the most connected symbols. AnalyticsQueryHotspots AnalyticsQueryType = "hotspots" // AnalyticsQueryDeadCode finds unreachable code. AnalyticsQueryDeadCode AnalyticsQueryType = "dead_code" // AnalyticsQueryCycles detects cyclic dependencies. AnalyticsQueryCycles AnalyticsQueryType = "cycles" // AnalyticsQueryPath finds the shortest path between symbols. AnalyticsQueryPath AnalyticsQueryType = "path" // AnalyticsQueryReferences finds all references to a symbol. AnalyticsQueryReferences AnalyticsQueryType = "references" // AnalyticsQueryCoupling computes package coupling metrics. AnalyticsQueryCoupling AnalyticsQueryType = "coupling" )
func (AnalyticsQueryType) IsValid ¶
func (t AnalyticsQueryType) IsValid() bool
IsValid returns true if this is a known analytics query type.
type AnalyticsRecord ¶
type AnalyticsRecord struct {
// ID is a unique identifier for this record.
ID string `json:"id"`
// QueryType identifies the type of analytics query.
QueryType AnalyticsQueryType `json:"query_type"`
// QueryTime is when the query was executed (Unix milliseconds UTC).
QueryTime int64 `json:"query_time"`
// GraphGeneration is the graph version when this analytics was run.
// Used to correlate analytics with graph state.
GraphGeneration int64 `json:"graph_generation,omitempty"`
// Params contains typed query parameters.
// Replaces QueryParams map[string]any per CLAUDE.md §4.5.
Params AnalyticsQueryParams `json:"params,omitempty"`
// QueryParams is DEPRECATED. Use Params instead.
// Retained for backwards compatibility with existing records.
QueryParams map[string]any `json:"query_params,omitempty"`
// ResultCount is the number of results returned.
ResultCount int `json:"result_count"`
// Results contains symbol IDs found (for hotspots, dead_code).
// Limited to MaxResultsPerRecord entries.
Results []string `json:"results,omitempty"`
// Cycles contains detected cycles (for cycle detection).
// Each inner slice is a cycle path.
Cycles [][]string `json:"cycles,omitempty"`
// Path contains the path between symbols (for path queries).
Path []string `json:"path,omitempty"`
// ExecutionMs is how long the query took in milliseconds.
// Must be non-negative.
ExecutionMs int64 `json:"execution_ms"`
}
AnalyticsRecord represents a single analytics query and its results.
Description:
Stores metadata and results from an analytics query for CRS tracking. Used for learning and activity coordination.
Thread Safety: NOT safe for concurrent modification.
func NewAnalyticsRecord ¶
func NewAnalyticsRecord( queryType AnalyticsQueryType, queryTime int64, resultCount int, executionMs int64, ) *AnalyticsRecord
NewAnalyticsRecord creates a new analytics record with the given parameters.
Description:
Creates a new AnalyticsRecord with a unique ID. The ID includes a monotonic counter to ensure uniqueness even at millisecond precision.
Inputs:
- queryType: The type of analytics query.
- queryTime: When the query was executed (Unix milliseconds UTC).
- resultCount: Number of results returned.
- executionMs: How long the query took in milliseconds.
Outputs:
*AnalyticsRecord: The new record.
Thread Safety: Safe for concurrent use.
func (*AnalyticsRecord) GetProofDoneKey ¶
func (r *AnalyticsRecord) GetProofDoneKey() string
GetProofDoneKey returns the proof key for "done" status.
Description:
Returns the typed constant for known query types. For unknown types, generates a key dynamically and logs a warning.
Thread Safety: Safe for concurrent use.
func (*AnalyticsRecord) GetProofFoundKey ¶
func (r *AnalyticsRecord) GetProofFoundKey() string
GetProofFoundKey returns the proof key for "found" status.
Description:
Returns the typed constant for known query types. For unknown types, generates a key dynamically and logs a warning.
Thread Safety: Safe for concurrent use.
func (*AnalyticsRecord) HasResults ¶
func (r *AnalyticsRecord) HasResults() bool
HasResults returns true if the record has results.
func (*AnalyticsRecord) TruncateResults ¶
func (r *AnalyticsRecord) TruncateResults() *AnalyticsRecord
TruncateResults limits Results to MaxResultsPerRecord.
Description:
Called before storing to prevent memory bloat from large result sets. Logs if truncation occurs.
Thread Safety: NOT safe for concurrent use.
func (*AnalyticsRecord) WithCycles ¶
func (r *AnalyticsRecord) WithCycles(cycles [][]string) *AnalyticsRecord
WithCycles adds cycle data to the record.
func (*AnalyticsRecord) WithGraphGeneration ¶
func (r *AnalyticsRecord) WithGraphGeneration(gen int64) *AnalyticsRecord
WithGraphGeneration sets the graph generation for correlation.
Description:
Records the graph version when this analytics was run. Enables correlation of analytics results with graph state.
Thread Safety: NOT safe for concurrent use.
func (*AnalyticsRecord) WithParams ¶
func (r *AnalyticsRecord) WithParams(params map[string]any) *AnalyticsRecord
WithParams adds query parameters to the record.
DEPRECATED: Use WithTypedParams instead per CLAUDE.md §4.5.
func (*AnalyticsRecord) WithPath ¶
func (r *AnalyticsRecord) WithPath(path []string) *AnalyticsRecord
WithPath adds path data to the record.
func (*AnalyticsRecord) WithResults ¶
func (r *AnalyticsRecord) WithResults(results []string) *AnalyticsRecord
WithResults adds symbol IDs to the record.
func (*AnalyticsRecord) WithTypedParams ¶
func (r *AnalyticsRecord) WithTypedParams(params AnalyticsQueryParams) *AnalyticsRecord
WithTypedParams sets typed query parameters.
Description:
Sets the Params field with typed parameters. Preferred over WithParams which uses map[string]any.
Thread Safety: NOT safe for concurrent use.
type ApplyMetrics ¶
type ApplyMetrics struct {
// DeltaType is the type of delta applied.
DeltaType DeltaType
// ApplyDuration is how long the apply took.
ApplyDuration time.Duration
// ValidationDuration is how long validation took.
ValidationDuration time.Duration
// IndexesUpdated identifies which indexes were updated (bitmask).
// Use IndexesUpdated.Has(IndexProof) to check, .Names() for string slice.
IndexesUpdated IndexMask
// EntriesModified is the number of entries modified.
EntriesModified int
// OldGeneration is the generation before apply.
OldGeneration int64
// NewGeneration is the generation after apply.
NewGeneration int64
}
ApplyMetrics contains metrics about an Apply operation.
type BackupMetadata ¶
type BackupMetadata struct {
// ProjectHash identifies the project this backup belongs to.
ProjectHash string `json:"project_hash"`
// CreatedAt is when this backup was created (Unix milliseconds UTC).
CreatedAt int64 `json:"created_at"`
// BadgerVersion is the BadgerDB version used to create the backup.
BadgerVersion string `json:"badger_version"`
// ContentHash is the SHA256 hash of the compressed backup file.
ContentHash string `json:"content_hash"`
// UncompressedSize is the original size before compression.
UncompressedSize int64 `json:"uncompressed_size"`
// CompressedSize is the size of the compressed backup file.
CompressedSize int64 `json:"compressed_size"`
// Generation is the CRS generation at backup time.
Generation int64 `json:"generation"`
// SessionID is the session that created this backup.
SessionID string `json:"session_id,omitempty"`
// DeltaCount is the number of deltas in the journal.
DeltaCount int64 `json:"delta_count"`
// SchemaVersion is the backup format version for future compatibility.
SchemaVersion string `json:"schema_version"`
// ExportPath is the path to the companion JSON export (if created).
ExportPath string `json:"export_path,omitempty"`
// MetadataHash is the SHA256 hash of this metadata (excluding this field).
// Used to detect metadata file corruption (P2 fix: I2).
MetadataHash string `json:"metadata_hash,omitempty"`
}
BackupMetadata contains information about a backup for verification.
Description:
Stored alongside the backup file to enable integrity verification and version compatibility checking. Uses int64 timestamps per CLAUDE.md standards.
Thread Safety: Immutable after creation.
func (*BackupMetadata) Age ¶
func (m *BackupMetadata) Age() time.Duration
Age returns the age of the backup.
func (*BackupMetadata) CompressionRatio ¶
func (m *BackupMetadata) CompressionRatio() float64
CompressionRatio returns the compression ratio.
type BackupOptions ¶
type BackupOptions struct {
// CreateJSONExport also creates a portable JSON export.
CreateJSONExport bool
// SessionID to record in metadata.
SessionID string
}
BackupOptions configures backup behavior.
type BadgerJournal ¶
type BadgerJournal struct {
// contains filtered or unexported fields
}
BadgerJournal implements Journal using BadgerDB.
Description:
Provides persistent WAL storage using BadgerDB. Each delta is stored with a CRC32 checksum for integrity verification.
Key format: "delta:{session_id}:{seq_num:016d}" Value format: [4-byte CRC32][gob-encoded delta]
Thread Safety: Safe for concurrent use.
func NewBadgerJournal ¶
func NewBadgerJournal(config JournalConfig) (*BadgerJournal, error)
NewBadgerJournal creates a journal at the specified path.
Inputs:
config - Journal configuration. Must pass Validate().
Outputs:
*BadgerJournal - Ready-to-use journal. error - Non-nil if BadgerDB initialization fails and AllowDegraded is false.
Thread Safety: Safe for concurrent use.
func (*BadgerJournal) Append ¶
func (j *BadgerJournal) Append(ctx context.Context, delta Delta) error
Append writes a delta with CRC checksum.
func (*BadgerJournal) AppendBatch ¶
func (j *BadgerJournal) AppendBatch(ctx context.Context, deltas []Delta) error
AppendBatch writes multiple deltas atomically.
func (*BadgerJournal) Backup ¶
Backup creates a portable backup of the journal.
Description:
Uses BadgerDB's built-in streaming backup to export all KV pairs. The writer receives a binary stream suitable for later restore. Caller is responsible for compression and storage.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- w: Writer to receive backup stream. Must not be nil.
Outputs:
- error: Non-nil if backup fails.
Thread Safety: Safe for concurrent use.
func (*BadgerJournal) Checkpoint ¶
func (j *BadgerJournal) Checkpoint(ctx context.Context) error
Checkpoint marks current position and truncates old entries.
func (*BadgerJournal) Close ¶
func (j *BadgerJournal) Close() error
Close syncs and releases resources.
func (*BadgerJournal) DB ¶
func (j *BadgerJournal) DB() *badger.DB
DB returns the underlying BadgerDB wrapper.
Description:
Provides access to the underlying database for backup operations. Used by PersistenceManager.SaveBackup and LoadBackup.
INTERNAL USE ONLY: This method is intended for use by the persistence package only. External callers should use the Journal interface methods (Append, Replay, Checkpoint) rather than accessing the database directly. Direct database access bypasses journal safety mechanisms including:
- CRC checksums on entries
- Sequence number tracking
- Degraded mode handling
Outputs:
- *badger.DB: The database wrapper. May be nil in degraded mode.
Thread Safety: Safe for concurrent use.
func (*BadgerJournal) IsAvailable ¶
func (j *BadgerJournal) IsAvailable() bool
IsAvailable returns false if journal is in degraded mode or closed.
func (*BadgerJournal) IsDegraded ¶
func (j *BadgerJournal) IsDegraded() bool
IsDegraded returns true if operating with reduced durability.
func (*BadgerJournal) Replay ¶
func (j *BadgerJournal) Replay(ctx context.Context) ([]Delta, error)
Replay returns all deltas since last checkpoint with validation.
func (*BadgerJournal) ReplayStream ¶
func (j *BadgerJournal) ReplayStream(ctx context.Context) (<-chan DeltaOrError, error)
ReplayStream returns a channel for streaming replay.
func (*BadgerJournal) Restore ¶
Restore loads state from a backup.
Description:
Uses BadgerDB's built-in Load function to restore from a backup stream. After restore, re-initializes internal state (sequence numbers, counters).
Inputs:
- ctx: Context for cancellation. Must not be nil.
- r: Reader with backup stream. Must not be nil.
Outputs:
- error: Non-nil if restore fails.
Limitations:
- Restore is all-or-nothing: failure leaves journal in undefined state.
- Caller should discard journal and create new one on restore failure.
Thread Safety: NOT safe for concurrent use with Append/Replay. Caller must ensure exclusive access during restore.
func (*BadgerJournal) Stats ¶
func (j *BadgerJournal) Stats() JournalStats
Stats returns journal statistics.
type CRS ¶
type CRS interface {
eval.Evaluable
// Snapshot returns an immutable view of the current state.
//
// Description:
//
// Creates a copy-on-write snapshot that algorithms can read from safely.
// The snapshot is immutable and will not change even if Apply() is called.
//
// Outputs:
// - Snapshot: The immutable snapshot. Never nil.
//
// Thread Safety: Safe for concurrent use.
Snapshot() Snapshot
// Apply atomically applies a delta to the state.
//
// Description:
//
// Validates the delta, then applies all changes atomically. If any
// index update fails, all changes are rolled back.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - delta: The delta to apply. Must not be nil.
//
// Outputs:
// - ApplyMetrics: Metrics about the apply operation.
// - error: Non-nil if apply failed.
//
// Thread Safety: Safe for concurrent use. Acquires write lock.
Apply(ctx context.Context, delta Delta) (ApplyMetrics, error)
// Generation returns the current state version.
//
// Description:
//
// Generation increments with each successful Apply(). Use for cache
// invalidation and ordering.
//
// Outputs:
// - int64: The current generation. Always >= 0.
//
// Thread Safety: Safe for concurrent use.
Generation() int64
// Checkpoint creates a restorable checkpoint for chaos testing.
//
// Description:
//
// Creates a checkpoint that can be restored later. Used for chaos
// testing and debugging.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - Checkpoint: The checkpoint. Never nil on success.
// - error: Non-nil if checkpoint creation failed.
//
// Thread Safety: Safe for concurrent use.
Checkpoint(ctx context.Context) (Checkpoint, error)
// Restore returns to a previous checkpoint.
//
// Description:
//
// Restores CRS to the state at the checkpoint. All changes since
// the checkpoint are discarded.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - cp: The checkpoint to restore. Must not be nil.
//
// Outputs:
// - error: Non-nil if restore failed.
//
// Thread Safety: Safe for concurrent use. Acquires write lock.
Restore(ctx context.Context, cp Checkpoint) error
// RecordStep adds a step to the CRS step history.
//
// Description:
//
// Validates the step, then atomically appends to the session's history.
// Recording is non-blocking - steps are added directly to the index.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - step: The step to record. Must pass Validate().
//
// Outputs:
// - error: Non-nil if validation fails or context cancelled.
//
// Thread Safety: Safe for concurrent use.
RecordStep(ctx context.Context, step StepRecord) error
// GetStepHistory returns all steps for a session, ordered by step number.
//
// Inputs:
// - sessionID: The session to query. Must not be empty.
//
// Outputs:
// - []StepRecord: Steps in order. Empty slice if session not found.
//
// Thread Safety: Safe for concurrent use.
GetStepHistory(sessionID string) []StepRecord
// GetLastStep returns the most recent step for a session.
//
// Inputs:
// - sessionID: The session to query. Must not be empty.
//
// Outputs:
// - *StepRecord: The last step, or nil if session not found/empty.
//
// Thread Safety: Safe for concurrent use.
GetLastStep(sessionID string) *StepRecord
// CountToolExecutions returns how many times a tool was EXECUTED in a session.
//
// Description:
//
// Counts steps where Decision == DecisionExecuteTool, not DecisionSelectTool.
// For circuit breaker, we care about actual executions, not selection attempts.
//
// Inputs:
// - sessionID: The session to query. Must not be empty.
// - tool: The tool name to count. Must not be empty.
//
// Outputs:
// - int: Number of executions. 0 if session not found or tool not used.
//
// Thread Safety: Safe for concurrent use.
CountToolExecutions(sessionID string, tool string) int
// GetStepsByActor returns steps filtered by actor.
//
// Inputs:
// - sessionID: The session to query. Must not be empty.
// - actor: The actor to filter by.
//
// Outputs:
// - []StepRecord: Matching steps in order. Empty slice if none found.
//
// Thread Safety: Safe for concurrent use.
GetStepsByActor(sessionID string, actor Actor) []StepRecord
// GetStepsByOutcome returns steps filtered by outcome.
//
// Inputs:
// - sessionID: The session to query. Must not be empty.
// - outcome: The outcome to filter by.
//
// Outputs:
// - []StepRecord: Matching steps in order. Empty slice if none found.
//
// Thread Safety: Safe for concurrent use.
GetStepsByOutcome(sessionID string, outcome Outcome) []StepRecord
// ClearStepHistory removes all steps for a session.
//
// Description:
//
// Use when starting a new query or when session is complete.
//
// Inputs:
// - sessionID: The session to clear. Must not be empty.
//
// Thread Safety: Safe for concurrent use.
ClearStepHistory(sessionID string)
// UpdateProofNumber applies a proof update to a node.
//
// Description:
//
// Updates the proof number for a node based on the update type:
// - Increment: Increases proof number (failure = path harder to prove)
// - Decrement: Decreases proof number (success = path easier to prove)
// - Disproven: Marks path as disproven (infinite cost)
// - Proven: Marks path as proven (solution found)
//
// IMPORTANT: Proof number represents COST TO PROVE. Lower = better.
// This is counterintuitive but matches PN-MCTS semantics.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - update: The proof update to apply. Must pass Validate().
//
// Outputs:
// - error: Non-nil if validation fails or context cancelled.
//
// Thread Safety: Safe for concurrent use.
UpdateProofNumber(ctx context.Context, update ProofUpdate) error
// GetProofStatus returns the current proof status for a node.
//
// Description:
//
// Returns the full ProofNumber struct for a node, including proof number,
// disproof number, status, and last update time.
//
// Inputs:
// - nodeID: The node to query. Must not be empty.
//
// Outputs:
// - ProofNumber: The current proof status. Zero value if node not found.
// - bool: True if node was found, false otherwise.
//
// Thread Safety: Safe for concurrent use.
GetProofStatus(nodeID string) (ProofNumber, bool)
// CheckCircuitBreaker checks if the circuit breaker should fire for a tool.
//
// Description:
//
// Checks if a tool path is disproven or has exhausted proof number.
// This replaces ad-hoc counting in execute.go with proof-based logic.
//
// Circuit breaker fires when:
// - Node status is ProofStatusDisproven
// - Proof number >= ProofNumberInfinite (exhausted)
//
// Inputs:
// - sessionID: The session to check. Must not be empty.
// - tool: The tool name to check. Must not be empty.
//
// Outputs:
// - CircuitBreakerResult: Contains ShouldFire bool and Reason.
//
// Thread Safety: Safe for concurrent use.
CheckCircuitBreaker(sessionID string, tool string) CircuitBreakerResult
// PropagateDisproof propagates disproof to parent decisions.
//
// Description:
//
// When a node is disproven, parent decisions that depended on it have
// their proof numbers increased (harder to prove). Uses BFS with depth
// limit to prevent stack overflow.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - nodeID: The disproven node. Must not be empty.
//
// Outputs:
// - int: Number of nodes affected by propagation.
//
// Thread Safety: Safe for concurrent use.
PropagateDisproof(ctx context.Context, nodeID string) int
// AddClause adds a learned clause to the constraint index.
//
// Description:
//
// Adds a clause learned from CDCL analysis. Checks for semantic
// duplicates and handles LRU eviction when MaxClauses is reached.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - clause: The clause to add. Must pass Validate().
//
// Outputs:
// - error: Non-nil if validation fails or context cancelled.
//
// Thread Safety: Safe for concurrent use.
AddClause(ctx context.Context, clause *Clause) error
// CheckDecisionAllowed checks if a proposed decision violates learned clauses.
//
// Description:
//
// Builds an assignment from the step history and the proposed decision,
// then checks against all learned clauses using watched literals.
//
// Inputs:
// - sessionID: The session to check. Must not be empty.
// - tool: The proposed tool selection.
//
// Outputs:
// - bool: True if the decision is allowed.
// - string: Reason if the decision is blocked.
//
// Thread Safety: Safe for concurrent use.
CheckDecisionAllowed(sessionID string, tool string) (bool, string)
// GarbageCollectClauses removes expired clauses based on TTL.
//
// Description:
//
// Removes clauses older than their TTL. Call periodically or after
// session ends to clean up stale clauses.
//
// Outputs:
// - int: Number of clauses removed.
//
// Thread Safety: Safe for concurrent use.
GarbageCollectClauses() int
// RecordSimilarity records a similarity pair between two queries.
//
// Description:
//
// Records that two queries (identified by tool+query keys) are
// semantically similar with the given distance score. This data
// persists across sessions via the journal and is used for
// cross-session semantic dedup.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - key1: First query key (e.g., "tool:query_hash"). Must not be empty.
// - key2: Second query key. Must not be empty or equal to key1.
// - distance: Similarity distance (0 = identical, higher = less similar).
// Must be non-negative.
//
// Outputs:
// - error: Non-nil if validation fails or context cancelled.
//
// Thread Safety: Safe for concurrent use.
RecordSimilarity(ctx context.Context, key1, key2 string, distance float64) error
// GetSimilarity returns the recorded similarity distance between two keys.
//
// Inputs:
// - key1: First query key. Must not be empty.
// - key2: Second query key. Must not be empty.
//
// Outputs:
// - float64: The distance, or -1 if no similarity recorded.
// - bool: True if a similarity record exists.
//
// Thread Safety: Safe for concurrent use.
GetSimilarity(key1, key2 string) (float64, bool)
// SetSessionID sets the current session ID for delta history tracking.
//
// Description:
//
// Deltas recorded via Apply() will be associated with this session ID.
// Call this at the start of each agent session.
//
// Inputs:
// - sessionID: The session identifier. Can be empty to clear.
//
// Thread Safety: Safe for concurrent use.
SetSessionID(sessionID string)
// ApplyWithSource applies a delta with explicit source and metadata tracking.
//
// Description:
//
// Like Apply(), but allows specifying a custom source string and metadata
// for delta history recording. Use this when you want to track which
// activity or component caused the delta.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - delta: The delta to apply. Must not be nil.
// - source: Human-readable source identifier (e.g., "AwarenessActivity").
// - metadata: Optional additional context for the delta.
//
// Outputs:
// - ApplyMetrics: Metrics about the apply operation.
// - error: Non-nil on validation failure or apply error.
//
// Thread Safety: Safe for concurrent use.
ApplyWithSource(ctx context.Context, delta Delta, source string, metadata map[string]string) (ApplyMetrics, error)
// DeltaHistory returns the delta history for querying.
//
// Description:
//
// Returns the delta history worker which provides methods to query
// what deltas were applied, when, and by whom. Use this to understand
// causality and build reasoning traces.
//
// Outputs:
// - DeltaHistoryView: Read-only view of delta history. May be nil if not initialized.
//
// Thread Safety: Safe for concurrent use.
DeltaHistory() DeltaHistoryView
// Close releases resources held by the CRS.
//
// Description:
//
// Stops background workers (like delta history). Should be called when
// the CRS is no longer needed to prevent goroutine leaks.
//
// Thread Safety: Safe for concurrent use. Idempotent.
Close()
// SetGraphProvider sets the graph query provider.
//
// Description:
//
// Registers a GraphQuery implementation that will be included in all
// future snapshots. Activities can then call snapshot.GraphQuery() to
// access the actual code graph.
//
// Call this after the graph is initialized and after graph refreshes
// to update the adapter with the new graph state.
//
// Inputs:
// - provider: The graph query implementation. May be nil to clear.
//
// Thread Safety: Safe for concurrent use.
SetGraphProvider(provider GraphQuery)
// InvalidateGraphCache invalidates graph-backed dependency index caches.
//
// Description:
//
// Called after the graph is refreshed (GR-29) to ensure subsequent queries
// see fresh data. Invalidates the Size() cache in GraphBackedDependencyIndex,
// which in turn invalidates the CRSGraphAdapter analytics cache (PageRank,
// communities, edge count).
//
// This is a no-op if graph-backed index is not in use (legacy mode).
//
// Thread Safety: Safe for concurrent use.
InvalidateGraphCache()
// GetAnalyticsHistory returns all analytics records.
//
// Description:
//
// Returns a copy of all analytics records in chronological order.
//
// Outputs:
// - []*AnalyticsRecord: Copy of all records.
//
// Thread Safety: Safe for concurrent use.
GetAnalyticsHistory() []*AnalyticsRecord
// GetLastAnalytics returns the most recent analytics of a given type.
//
// Description:
//
// Searches analytics history for the most recent record of the
// specified query type.
//
// Inputs:
// - queryType: The type of analytics query to find.
//
// Outputs:
// - *AnalyticsRecord: The most recent matching record, or nil if not found.
//
// Thread Safety: Safe for concurrent use.
GetLastAnalytics(queryType AnalyticsQueryType) *AnalyticsRecord
// HasRunAnalytics checks if a specific analytics type has been run.
//
// Description:
//
// Returns true if an analytics query of the given type has been
// recorded in history.
//
// Inputs:
// - queryType: The type of analytics query to check.
//
// Outputs:
// - bool: True if the query type has been run.
//
// Thread Safety: Safe for concurrent use.
HasRunAnalytics(queryType AnalyticsQueryType) bool
}
CRS is the central mutable state container for the Aleutian Hybrid MCTS system.
Description:
CRS manages 6 indexes that algorithms read from and write to. It provides immutable snapshots for reading and delta-based mutations for writing.
Thread Safety: Safe for concurrent use. Uses RWMutex internally.
type CRSExport ¶
type CRSExport struct {
// SessionID identifies the session this export belongs to.
SessionID string `json:"session_id"`
// Generation is the CRS generation at export time.
Generation int64 `json:"generation"`
// Timestamp is when this export was created (Unix milliseconds UTC).
Timestamp int64 `json:"timestamp"`
// Indexes contains all six CRS indexes in exportable form.
Indexes IndexesExport `json:"indexes"`
// Summary provides high-level metrics about the reasoning state.
Summary ReasoningSummary `json:"summary"`
}
CRSExport is the JSON-serializable representation of CRS state.
Description:
Contains a complete snapshot of CRS state suitable for JSON export. Includes all six indexes and computed summary metrics.
type Checkpoint ¶
type Checkpoint struct {
// ID is the unique checkpoint identifier.
ID string
// Generation is the generation at checkpoint time.
Generation int64
// CreatedAt is when the checkpoint was created (Unix milliseconds UTC).
CreatedAt int64
// contains filtered or unexported fields
}
Checkpoint represents a restorable state checkpoint.
type CircuitBreakerResult ¶
type CircuitBreakerResult struct {
// ShouldFire is true if the circuit breaker should intervene.
ShouldFire bool `json:"should_fire"`
// Reason explains why the circuit breaker fired (or didn't).
Reason string `json:"reason,omitempty"`
// ProofNumber is the current proof number for the checked path.
ProofNumber uint64 `json:"proof_number,omitempty"`
// Status is the current proof status.
Status ProofStatus `json:"status,omitempty"`
}
CircuitBreakerResult contains the result of a circuit breaker check.
Description:
Returned by CheckCircuitBreaker to indicate whether the circuit breaker should fire and why.
type Clause ¶
type Clause struct {
// ID is the unique clause identifier.
ID string `json:"id"`
// Literals are the disjuncts (OR'd together).
Literals []Literal `json:"literals"`
// Source indicates where this clause was learned.
// Must be HARD for CDCL-learned clauses.
Source SignalSource `json:"source"`
// LearnedAt is when this clause was created (Unix milliseconds UTC).
LearnedAt int64 `json:"learned_at"`
// FailureType categorizes what kind of failure created this clause.
FailureType FailureType `json:"failure_type"`
// SessionID is the session where this was learned (for debugging).
SessionID string `json:"session_id,omitempty"`
// UseCount tracks how often this clause blocks decisions (for GC).
UseCount int64 `json:"use_count"`
// LastUsed is when this clause last blocked a decision (Unix milliseconds UTC).
LastUsed int64 `json:"last_used,omitempty"`
}
Clause represents a learned constraint in CNF (Conjunctive Normal Form).
Description:
A clause is a disjunction (OR) of literals that must be satisfied. Learned clauses prevent the agent from repeating the same mistakes. Example: (¬tool:list_packages ∨ ¬outcome:success ∨ ¬tool:list_packages) Meaning: "Don't select list_packages after it already succeeded"
Thread Safety: Clause is safe for concurrent read access.
func (*Clause) IsSatisfied ¶
IsSatisfied checks if the clause is satisfied by the given assignment.
Description:
A clause is satisfied if ANY literal is true (disjunction). For a literal to be true: - If positive: the variable must be true in the assignment - If negated: the variable must be false in the assignment
Inputs:
assignment - Map of variable names to their boolean values.
Outputs:
bool - True if the clause is satisfied.
func (*Clause) IsViolated ¶
IsViolated checks if the clause is violated by the given assignment.
Description:
A clause is violated when ALL literals are false under the assignment. This is the opposite of IsSatisfied, but with explicit handling: if a variable is unassigned, the clause is not yet violated.
Inputs:
assignment - Map of variable names to their boolean values.
Outputs:
bool - True if the clause is violated (all literals are false).
type ClauseCheckResult ¶
type ClauseCheckResult struct {
// Conflict is true if a clause is violated by the assignment.
Conflict bool `json:"conflict"`
// ViolatedClause is the clause that was violated, if any.
ViolatedClause *Clause `json:"violated_clause,omitempty"`
// Reason explains why the conflict occurred.
Reason string `json:"reason,omitempty"`
}
ClauseCheckResult contains the result of checking an assignment against clauses.
type ClausePersistence ¶
type ClausePersistence struct {
// Scope determines clause visibility.
Scope ClauseScope
// TTL is how long clauses remain valid.
TTL time.Duration
// MaxClauses is the maximum clauses per scope (LRU eviction).
MaxClauses int
}
ClausePersistence configures clause storage and garbage collection.
type ClauseScope ¶
type ClauseScope string
ClauseScope determines clause visibility and persistence.
const ( // ClauseScopeSession: Clauses only valid for current session. // TTL: session duration. GC: session end. ClauseScopeSession ClauseScope = "session" // ClauseScopeProject: Clauses valid across sessions for same project. // TTL: 7 days. GC: LRU eviction when MaxClauses reached. ClauseScopeProject ClauseScope = "project" // ClauseScopeGlobal: Clauses valid across all projects (rare). // TTL: 30 days. GC: Manual review required. // Use sparingly - only for universal patterns like "don't infinite loop". ClauseScopeGlobal ClauseScope = "global" )
type CompositeDelta ¶
type CompositeDelta struct {
// Deltas are the contained deltas.
Deltas []Delta
// contains filtered or unexported fields
}
CompositeDelta contains multiple deltas for atomic application.
func NewCompositeDelta ¶
func NewCompositeDelta(deltas ...Delta) *CompositeDelta
NewCompositeDelta creates a composite delta from multiple deltas.
func (*CompositeDelta) ConflictsWith ¶
func (d *CompositeDelta) ConflictsWith(other Delta) bool
ConflictsWith returns true if any contained delta conflicts.
func (*CompositeDelta) IndexesAffected ¶
func (d *CompositeDelta) IndexesAffected() []string
IndexesAffected returns all indexes affected by contained deltas.
func (*CompositeDelta) Merge ¶
func (d *CompositeDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*CompositeDelta) Source ¶
func (d *CompositeDelta) Source() SignalSource
func (*CompositeDelta) Type ¶
func (d *CompositeDelta) Type() DeltaType
Type returns the delta type.
func (*CompositeDelta) Validate ¶
func (d *CompositeDelta) Validate(snapshot Snapshot) error
Validate checks if all contained deltas can be applied.
type Config ¶
type Config struct {
// MaxGeneration is the maximum generation before wrapping.
// Default: 0 (no maximum, wraps at int64 max).
MaxGeneration int64
// SnapshotEpochLimit is how many generations a snapshot is valid.
// Default: 1000 (snapshots older than 1000 generations are stale).
SnapshotEpochLimit int64
// EnableMetrics enables metrics collection.
// Default: true.
EnableMetrics bool
// EnableTracing enables OpenTelemetry tracing.
// Default: true.
EnableTracing bool
// CircuitBreakerThresholds maps tool names to their per-tool circuit
// breaker thresholds. When a tool has been executed this many times in
// a session (and no proof data exists), the circuit breaker fires.
// Tools not in this map fall back to DefaultCircuitBreakerThreshold.
//
// CRS-16: Per-tool circuit breaker thresholds.
CircuitBreakerThresholds map[string]int
}
Config configures a CRS instance.
type Constraint ¶
type Constraint struct {
// ID is the unique constraint identifier.
ID string
// Type is the constraint type.
Type ConstraintType
// Nodes are the nodes this constraint affects.
Nodes []string
// Expression is the constraint expression.
Expression string
// Active indicates if the constraint is currently active.
Active bool
// Source indicates where this constraint came from.
Source SignalSource
// CreatedAt is when this constraint was created (Unix milliseconds UTC).
CreatedAt int64
}
Constraint represents a constraint on the search space.
type ConstraintDelta ¶
type ConstraintDelta struct {
// Add contains constraints to add.
Add []Constraint
// Remove contains constraint IDs to remove.
Remove []string
// Update contains constraints to update (by ID).
Update map[string]Constraint
// contains filtered or unexported fields
}
ConstraintDelta represents changes to constraints.
func NewConstraintDelta ¶
func NewConstraintDelta(source SignalSource) *ConstraintDelta
NewConstraintDelta creates a new constraint delta.
func (*ConstraintDelta) ConflictsWith ¶
func (d *ConstraintDelta) ConflictsWith(other Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*ConstraintDelta) IndexesAffected ¶
func (d *ConstraintDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Thread Safety: Returns a shared slice. Callers must not modify.
func (*ConstraintDelta) Merge ¶
func (d *ConstraintDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*ConstraintDelta) Source ¶
func (d *ConstraintDelta) Source() SignalSource
func (*ConstraintDelta) Type ¶
func (d *ConstraintDelta) Type() DeltaType
Type returns the delta type.
func (*ConstraintDelta) Validate ¶
func (d *ConstraintDelta) Validate(snapshot Snapshot) error
Validate checks if this delta can be applied.
type ConstraintEntry ¶
type ConstraintEntry struct {
// ID is the unique constraint identifier.
ID string `json:"id"`
// Type is the constraint type: "mutual_exclusion", "implication", "ordering", "resource".
Type string `json:"type"`
// Nodes are the node IDs affected by this constraint.
Nodes []string `json:"nodes"`
// Expression is the constraint expression if any.
Expression string `json:"expression,omitempty"`
// Active indicates if the constraint is currently enforced.
Active bool `json:"active"`
// Source indicates signal source: "unknown", "hard", "soft".
Source string `json:"source"`
// CreatedAt is when this constraint was created.
CreatedAt time.Time `json:"created_at"`
}
ConstraintEntry represents a single constraint.
type ConstraintIndexExport ¶
type ConstraintIndexExport struct {
// Constraints contains all active constraints.
Constraints []ConstraintEntry `json:"constraints"`
}
ConstraintIndexExport is the serializable form of the Constraint Index.
type ConstraintIndexView ¶
type ConstraintIndexView interface {
// Get returns a constraint by ID.
Get(constraintID string) (Constraint, bool)
// FindByType returns all constraints of a type.
FindByType(constraintType ConstraintType) []Constraint
// FindByNode returns all constraints affecting a node.
FindByNode(nodeID string) []Constraint
// All returns all constraints.
All() map[string]Constraint
// Size returns the number of constraints.
Size() int
// GetClause returns a learned clause by ID.
GetClause(clauseID string) (*Clause, bool)
// AllClauses returns all learned clauses.
AllClauses() map[string]*Clause
// ClauseCount returns the number of learned clauses.
ClauseCount() int
// CheckAssignment checks if an assignment violates any learned clauses.
//
// Description:
//
// Uses watched literals for efficient checking. Returns the first
// violated clause if any.
//
// Inputs:
//
// assignment - Map of variable names to their boolean values.
//
// Outputs:
//
// ClauseCheckResult - Result of the check.
CheckAssignment(assignment map[string]bool) ClauseCheckResult
}
ConstraintIndexView provides read-only access to constraints.
Thread Safety: Safe for concurrent use (immutable).
type ConstraintType ¶
type ConstraintType int
ConstraintType represents the type of constraint.
const ( // ConstraintTypeUnknown is an unknown constraint type. ConstraintTypeUnknown ConstraintType = iota // ConstraintTypeMutualExclusion means nodes cannot be selected together. ConstraintTypeMutualExclusion // ConstraintTypeImplication means selecting one node implies another. ConstraintTypeImplication // ConstraintTypeOrdering means nodes must be selected in order. ConstraintTypeOrdering // ConstraintTypeResource means nodes share a resource limit. ConstraintTypeResource )
func (ConstraintType) String ¶
func (t ConstraintType) String() string
String returns the string representation of ConstraintType.
type ConstraintUpdate ¶
type ConstraintUpdate struct {
// ID is the constraint ID.
ID string `json:"id"`
// Type is the constraint type (typed enum).
Type ConstraintType `json:"type"`
// Nodes are the affected nodes.
Nodes []string `json:"nodes"`
// Source indicates where this constraint came from.
Source SignalSource `json:"source"`
}
ConstraintUpdate represents a constraint being added.
Thread Safety: ConstraintUpdate is immutable after creation.
type CycleAnalysis ¶
type CycleAnalysis struct {
// SessionID is the session that was analyzed.
SessionID string `json:"session_id"`
// TotalSCCs is the total number of strongly connected components.
TotalSCCs int `json:"total_sccs"`
// CyclicSCCs contains SCCs with more than one node (actual cycles).
CyclicSCCs [][]string `json:"cyclic_sccs"`
// LargestSCCSize is the size of the largest cyclic SCC.
LargestSCCSize int `json:"largest_scc_size"`
// AnalysisTime is when the analysis was performed.
AnalysisTime time.Time `json:"analysis_time"`
// AnalysisDuration is how long the analysis took.
AnalysisDuration time.Duration `json:"analysis_duration_ns"`
}
CycleAnalysis contains post-session cycle analysis results.
func AnalyzeSessionCycles ¶
func AnalyzeSessionCycles(ctx context.Context, crsInstance CRS, sessionID string) (*CycleAnalysis, error)
AnalyzeSessionCycles performs comprehensive cycle analysis using Tarjan SCC.
Description:
Called at session end or on-demand for debugging. Uses Tarjan's algorithm to find ALL strongly connected components in the decision graph. Unlike Brent's algorithm (which detects single cycles as they form), Tarjan finds ALL cycles including: - Multi-step cycles that Brent's might miss - Complex SCCs with multiple entry/exit points - Cycles that span multiple decision branches This is more expensive than Brent's (O(V+E) vs O(1) per step) but provides complete analysis for debugging and learning.
When to call:
- Session end (for learning)
- On-demand debugging
- NOT in the hot path (too expensive)
Inputs:
ctx - Context for cancellation. crsInstance - The CRS instance to get step history from. sessionID - The session to analyze.
Outputs:
*CycleAnalysis - Analysis results. Never nil. error - Non-nil on failure.
type CycleDetectionResult ¶
type CycleDetectionResult struct {
// Detected is true if a cycle was found.
Detected bool
// Cycle contains the states in the detected cycle.
// Empty if no cycle detected.
Cycle []string
// CycleLength is the length of the detected cycle.
CycleLength int
// TailLength is the number of states before the cycle starts.
TailLength int
// StateKey is the state key that triggered detection.
StateKey string
// Errors contains any non-fatal errors during detection.
// A-02: Added to report partial failures.
Errors []error
}
CycleDetectionResult contains the result of a cycle detection check.
func CheckCycleOnStep ¶
func CheckCycleOnStep( ctx context.Context, crsInstance CRS, step StepRecord, detector *CycleDetector, ) CycleDetectionResult
CheckCycleOnStep checks for cycles after a step is recorded.
Description:
Called after each step to detect cycles in real-time using Brent's algorithm. If a cycle is detected, marks all cycle states as disproven in the proof index and records a circuit breaker step. This is the main integration point between cycle detection and CRS.
Inputs:
ctx - Context for cancellation and tracing. crsInstance - The CRS instance for recording and proof updates. step - The step that was just recorded. detector - The cycle detector for this session.
Outputs:
CycleDetectionResult - The detection result.
Thread Safety: Safe for concurrent use.
type CycleDetector ¶
type CycleDetector struct {
// contains filtered or unexported fields
}
CycleDetector uses Brent's algorithm for online cycle detection.
Description:
Maintains state between calls to detect cycles incrementally. Each AddStep() call is O(1) amortized, enabling real-time detection. Brent's algorithm uses the "teleporting tortoise" approach: - Hare moves one step at a time - Tortoise teleports to hare's position when power of 2 is reached - Cycle detected when hare == tortoise This is preferred over Floyd's tortoise-hare because: - Fewer comparisons on average (24-36% fewer iterations) - Same O(λ + μ) time complexity where λ=cycle length, μ=tail length - O(1) space (vs O(V) for Tarjan SCC)
Thread Safety: Safe for concurrent use.
func NewCycleDetector ¶
func NewCycleDetector(config *CycleDetectorConfig) *CycleDetector
NewCycleDetector creates a new cycle detector.
Description:
Creates a CycleDetector configured for real-time cycle detection. The detector maintains state between AddStep() calls to enable online cycle detection with O(1) amortized time per step.
Inputs:
config - Configuration options. Uses defaults if nil.
Outputs:
*CycleDetector - The configured detector. Never nil.
func (*CycleDetector) AddStep ¶
func (d *CycleDetector) AddStep(state string) CycleDetectionResult
AddStep processes a new state and returns cycle detection result.
Description:
Uses Brent's cycle detection algorithm incrementally. State is a normalized representation of the current decision. Time Complexity: O(1) amortized per call. Space Complexity: O(maxHistory) total.
Inputs:
state - Normalized state string (e.g., "tool:list_packages:success:router").
Outputs:
CycleDetectionResult - Contains detection status and cycle if found.
Thread Safety: Safe for concurrent use.
func (*CycleDetector) Reset ¶
func (d *CycleDetector) Reset()
Reset clears all detector state.
Description:
Use when starting a new session or when cycle has been handled.
Thread Safety: Safe for concurrent use.
func (*CycleDetector) Stats ¶
func (d *CycleDetector) Stats() CycleDetectorStats
Stats returns the detector statistics.
Thread Safety: Safe for concurrent use.
type CycleDetectorConfig ¶
type CycleDetectorConfig struct {
// MaxHistory is the maximum number of states to track for cycle extraction.
// Larger values enable detecting longer cycles but use more memory.
// Default: 1000
MaxHistory int
}
CycleDetectorConfig configures the cycle detector.
func DefaultCycleDetectorConfig ¶
func DefaultCycleDetectorConfig() *CycleDetectorConfig
DefaultCycleDetectorConfig returns the default cycle detector configuration.
type CycleDetectorStats ¶
type CycleDetectorStats struct {
StepsProcessed int
CyclesDetected int
LastCycleTime time.Time
HistorySize int
MaxHistory int
}
CycleDetectorStats contains detector statistics.
type Decision ¶
type Decision string
Decision identifies what type of decision was made.
const ( // DecisionSelectTool means the router selected a tool. DecisionSelectTool Decision = "select_tool" // DecisionExecuteTool means a tool was executed. DecisionExecuteTool Decision = "execute_tool" // DecisionSynthesize means generating a final answer. DecisionSynthesize Decision = "synthesize" // DecisionCircuitBreaker means the circuit breaker intervened. DecisionCircuitBreaker Decision = "circuit_breaker" // DecisionRetry means a retry was triggered. DecisionRetry Decision = "retry" // DecisionComplete means the session completed. DecisionComplete Decision = "complete" // DecisionError means an error occurred. DecisionError Decision = "error" )
type DecisionGraph ¶
type DecisionGraph struct {
// Nodes are the node IDs (state keys).
Nodes []string
// Edges maps each node to its successors.
Edges map[string][]string
}
DecisionGraph represents a graph of decisions for cycle analysis.
func BuildDecisionGraph ¶
func BuildDecisionGraph(steps []StepRecord) *DecisionGraph
BuildDecisionGraph constructs a decision graph from step records.
Description:
Builds a directed graph where: - Nodes are state keys (from GetStateKey) - Edges connect consecutive states This graph can then be analyzed with Tarjan SCC for comprehensive cycle detection.
Inputs:
steps - The step records to build the graph from.
Outputs:
*DecisionGraph - The decision graph. Never nil.
type Delta ¶
type Delta interface {
// Type returns the delta type.
Type() DeltaType
// Validate checks if this delta can be applied to the snapshot.
//
// Inputs:
// - snapshot: The snapshot to validate against.
//
// Outputs:
// - error: Non-nil if validation fails.
Validate(snapshot Snapshot) error
// Merge combines this delta with another delta.
//
// Inputs:
// - other: The delta to merge with.
//
// Outputs:
// - Delta: The merged delta.
// - error: Non-nil if deltas cannot be merged.
Merge(other Delta) (Delta, error)
// ConflictsWith returns true if this delta conflicts with another.
//
// Inputs:
// - other: The delta to check for conflicts.
//
// Outputs:
// - bool: True if deltas conflict.
ConflictsWith(other Delta) bool
// Source returns the signal source for this delta.
Source() SignalSource
// Timestamp returns when this delta was created (Unix milliseconds UTC).
Timestamp() int64
// IndexesAffected returns which indexes this delta will modify.
IndexesAffected() []string
}
Delta represents an atomic change to CRS state.
Description:
Algorithms produce deltas that describe state changes. Deltas are validated before application and can be merged with other deltas.
Thread Safety: Implementations must be safe for concurrent use.
type DeltaHistoryView ¶
type DeltaHistoryView interface {
// GetRange returns deltas between two generations (exclusive start, inclusive end).
GetRange(ctx context.Context, fromGen, toGen int64) ([]DeltaRecord, error)
// GetByNode returns all deltas that affected a specific node.
GetByNode(ctx context.Context, nodeID string) ([]DeltaRecord, error)
// GetByGeneration returns the delta applied at a specific generation.
GetByGeneration(ctx context.Context, gen int64) (DeltaRecord, bool, error)
// Explain returns the causality chain for a node's current state.
Explain(ctx context.Context, nodeID string) ([]DeltaRecord, error)
// Size returns the current number of records in history.
Size(ctx context.Context) (int, error)
}
DeltaHistoryView provides read-only access to delta history from snapshots.
Thread Safety: All methods are safe for concurrent use.
type DeltaHistoryWorker ¶
type DeltaHistoryWorker struct {
// contains filtered or unexported fields
}
DeltaHistoryWorker manages delta history using a channel-based architecture.
Description:
Uses buffered channels for parallel delta recording and queries. A single goroutine owns all history state, eliminating mutex contention. This design follows the "share memory by communicating" principle.
Thread Safety: Safe for concurrent use. All operations go through channels.
func NewDeltaHistoryWorker ¶
func NewDeltaHistoryWorker(maxRecords int, logger *slog.Logger) *DeltaHistoryWorker
NewDeltaHistoryWorker creates a new delta history worker.
Description:
Starts a background goroutine that owns all history state. The worker accepts record and query requests via buffered channels.
Inputs:
- maxRecords: Maximum records to keep (uses DefaultMaxDeltaRecords if <= 0).
- logger: Logger instance. If nil, uses slog.Default().
Outputs:
- *DeltaHistoryWorker: The new worker. Never nil.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) All ¶
func (w *DeltaHistoryWorker) All(ctx context.Context) ([]DeltaRecord, error)
All returns all records in chronological order.
Inputs:
- ctx: Context for cancellation. Must not be nil.
Outputs:
- []DeltaRecord: All records in chronological order.
- error: Non-nil on context cancellation.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) Close ¶
func (w *DeltaHistoryWorker) Close()
Close stops the worker goroutine.
Description:
Signals the worker to stop and waits for it to finish. Safe to call multiple times.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) Explain ¶
func (w *DeltaHistoryWorker) Explain(ctx context.Context, nodeID string) ([]DeltaRecord, error)
Explain returns the causality chain for a node's current state.
Description:
Returns all deltas that affected the node, in chronological order. This provides a "reasoning trace" showing how the node reached its current state.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- nodeID: The node to explain.
Outputs:
- []DeltaRecord: All deltas affecting this node, ordered chronologically.
- error: Non-nil on context cancellation.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) GetByGeneration ¶
func (w *DeltaHistoryWorker) GetByGeneration(ctx context.Context, gen int64) (DeltaRecord, bool, error)
GetByGeneration returns the delta applied at a specific generation.
Description:
Returns the single delta that was applied to reach the specified generation.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- gen: The generation to look up.
Outputs:
- DeltaRecord: The matching record (zero value if not found).
- bool: True if a record was found.
- error: Non-nil on context cancellation.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) GetByNode ¶
func (w *DeltaHistoryWorker) GetByNode(ctx context.Context, nodeID string) ([]DeltaRecord, error)
GetByNode returns all deltas that affected a specific node.
Description:
Returns all deltas where the node appears in AffectedNodes, ordered chronologically.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- nodeID: The node to look up.
Outputs:
- []DeltaRecord: Matching records, ordered by generation. Empty if none found.
- error: Non-nil on context cancellation.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) GetRange ¶
func (w *DeltaHistoryWorker) GetRange(ctx context.Context, fromGen, toGen int64) ([]DeltaRecord, error)
GetRange returns deltas between two generations (exclusive start, inclusive end).
Description:
Returns all deltas where fromGen < generation <= toGen, ordered by generation.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- fromGen: Exclusive lower bound (deltas after this generation).
- toGen: Inclusive upper bound (deltas up to and including this generation).
Outputs:
- []DeltaRecord: Matching records, ordered by generation. Empty if none found.
- error: Non-nil on context cancellation.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) Record ¶
func (w *DeltaHistoryWorker) Record(delta Delta, gen int64, source, sessionID string, metadata map[string]string)
Record adds a delta to history.
Description:
Non-blocking operation using a buffered channel. If the channel is full, the record is dropped and a warning is logged.
Inputs:
- delta: The delta that was applied. Must not be nil.
- gen: The CRS generation after applying the delta.
- source: What caused this delta (activity name, tool name, etc.).
- sessionID: The session that applied this delta.
- metadata: Optional additional context.
Thread Safety: Safe for concurrent use.
func (*DeltaHistoryWorker) Size ¶
func (w *DeltaHistoryWorker) Size(ctx context.Context) (int, error)
Size returns the current number of records in history.
Inputs:
- ctx: Context for cancellation. Must not be nil.
Outputs:
- int: Number of records.
- error: Non-nil on context cancellation.
Thread Safety: Safe for concurrent use.
type DeltaOrError ¶
type DeltaOrError struct {
// Delta is the decoded delta (nil if error).
Delta Delta
// SeqNum is the sequence number of this entry.
SeqNum uint64
// Err is set if decoding failed.
Err error
// Skipped is true if the delta was corrupted and skipped.
Skipped bool
}
DeltaOrError is used for streaming replay.
Description:
Yields either a successfully decoded delta or an error. Skipped indicates the delta was corrupted but skipped per config.
type DeltaRecord ¶
type DeltaRecord struct {
// ID is a stable identifier for this record (not slice index).
ID string `json:"id"`
// Generation is the CRS generation after this delta was applied.
Generation int64 `json:"generation"`
// Timestamp is when this delta was applied (Unix milliseconds UTC).
Timestamp int64 `json:"timestamp"`
// DeltaType identifies the type of delta (proof, constraint, etc.).
DeltaType DeltaType `json:"delta_type"`
// DeltaBytes contains the JSON-serialized delta.
// Storing as bytes avoids interface serialization issues.
DeltaBytes []byte `json:"delta_bytes"`
// Source identifies what caused this delta (activity name, tool, etc.).
Source string `json:"source"`
// SessionID identifies the session that applied this delta.
SessionID string `json:"session_id"`
// Metadata contains additional context about the delta.
Metadata map[string]string `json:"metadata,omitempty"`
// AffectedNodes lists node IDs affected by this delta.
AffectedNodes []string `json:"affected_nodes"`
}
DeltaRecord captures a single delta application with full context.
Description:
Stores metadata about when and why a delta was applied, along with the serialized delta itself. Uses stable string IDs for indexing to avoid invalidation issues with slice-based indexing.
Thread Safety: Immutable after creation.
type DeltaType ¶
type DeltaType int
DeltaType identifies the type of delta.
const ( // DeltaTypeUnknown is an unknown delta type. DeltaTypeUnknown DeltaType = iota // DeltaTypeProof updates proof numbers. DeltaTypeProof // DeltaTypeConstraint updates constraints. DeltaTypeConstraint // DeltaTypeSimilarity updates similarity scores. DeltaTypeSimilarity // DeltaTypeDependency updates dependencies. DeltaTypeDependency // DeltaTypeHistory adds history entries. DeltaTypeHistory // DeltaTypeStreaming updates streaming statistics. DeltaTypeStreaming // DeltaTypeComposite contains multiple deltas. DeltaTypeComposite // DeltaTypeAnalytics records analytics queries. // GR-31: Added for analytics CRS routing. DeltaTypeAnalytics )
type DependencyDelta ¶
type DependencyDelta struct {
// AddEdges contains edges to add (from -> to).
AddEdges [][2]string
// RemoveEdges contains edges to remove (from -> to).
RemoveEdges [][2]string
// contains filtered or unexported fields
}
DependencyDelta represents changes to dependencies.
func NewDependencyDelta ¶
func NewDependencyDelta(source SignalSource) *DependencyDelta
NewDependencyDelta creates a new dependency delta.
func (*DependencyDelta) ConflictsWith ¶
func (d *DependencyDelta) ConflictsWith(other Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*DependencyDelta) IndexesAffected ¶
func (d *DependencyDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Thread Safety: Returns a shared slice. Callers must not modify.
func (*DependencyDelta) Merge ¶
func (d *DependencyDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*DependencyDelta) Source ¶
func (d *DependencyDelta) Source() SignalSource
func (*DependencyDelta) Type ¶
func (d *DependencyDelta) Type() DeltaType
Type returns the delta type.
func (*DependencyDelta) Validate ¶
func (d *DependencyDelta) Validate(snapshot Snapshot) error
Validate checks if this delta can be applied.
type DependencyEdge ¶
type DependencyEdge struct {
// From is the dependent node.
From string `json:"from"`
// To is the dependency target.
To string `json:"to"`
// Source indicates where this dependency was discovered.
Source SignalSource `json:"source"`
}
DependencyEdge represents a dependency relationship.
Thread Safety: DependencyEdge is immutable after creation.
type DependencyEdgeExport ¶
type DependencyEdgeExport struct {
// FromID is the source node (the caller/dependent).
FromID string `json:"from_id"`
// ToID is the target node (the callee/dependency).
ToID string `json:"to_id"`
}
DependencyEdgeExport represents a single dependency edge.
type DependencyIndexExport ¶
type DependencyIndexExport struct {
// EdgeCount is the number of dependency edges.
EdgeCount int `json:"edge_count"`
// Edges contains all dependency edges for full export.
// Empty for graph-backed indexes (use graph persistence instead).
Edges []DependencyEdgeExport `json:"edges,omitempty"`
// Source indicates the index implementation type.
// Values: "legacy" (edges exported) or "graph_backed" (edges not exported).
Source string `json:"source,omitempty"`
// Truncated indicates if Edges was truncated due to limits.
Truncated bool `json:"truncated,omitempty"`
}
DependencyIndexExport is the serializable form of the Dependency Index.
Export behavior depends on the index implementation:
- Legacy dependencyGraph: Full edges are exported.
- GraphBackedDependencyIndex (GR-32): Only EdgeCount is exported; edges live in the graph which has its own persistence.
type DependencyIndexView ¶
type DependencyIndexView interface {
// DependsOn returns all nodes that nodeID depends on.
DependsOn(nodeID string) []string
// DependedBy returns all nodes that depend on nodeID.
DependedBy(nodeID string) []string
// HasCycle returns true if there's a cycle involving nodeID.
HasCycle(nodeID string) bool
// Size returns the number of dependency edges.
Size() int
// AllEdges returns all dependency edges for export.
//
// Description:
//
// Returns a deep copy of all dependency edges for serialization.
// Format: map[fromID][]toIDs.
//
// For GraphBackedDependencyIndex (GR-32), returns nil since edges
// live in the graph which has its own persistence mechanism.
//
// Outputs:
// - map[string][]string: Copy of forward edges, or nil for graph-backed.
//
// Thread Safety: Returns deep copy; caller can modify without affecting source.
AllEdges() map[string][]string
// IsGraphBacked returns true if this index delegates to the graph.
//
// Description:
//
// When true, AllEdges() returns nil and edge export should be skipped.
// The graph has its own persistence; use graph backup instead.
//
// Outputs:
// - bool: True if graph-backed (GR-32), false for legacy implementation.
IsGraphBacked() bool
}
DependencyIndexView provides read-only access to dependencies.
Thread Safety: Safe for concurrent use (immutable).
type ErrorCategory ¶
type ErrorCategory string
ErrorCategory categorizes errors for retry and learning logic. Using typed enums instead of raw strings enables compile-time checking and better analytics.
const ( // ErrorCategoryNone means no error occurred. ErrorCategoryNone ErrorCategory = "" // ErrorCategoryToolNotFound means the tool doesn't exist. ErrorCategoryToolNotFound ErrorCategory = "tool_not_found" // ErrorCategoryInvalidParams means the tool parameters were invalid. ErrorCategoryInvalidParams ErrorCategory = "invalid_params" // ErrorCategoryTimeout means the operation timed out. ErrorCategoryTimeout ErrorCategory = "timeout" // ErrorCategoryRateLimited means the operation was rate limited. ErrorCategoryRateLimited ErrorCategory = "rate_limited" // ErrorCategoryPermission means permission was denied. ErrorCategoryPermission ErrorCategory = "permission" // ErrorCategoryNetwork means a network error occurred. ErrorCategoryNetwork ErrorCategory = "network" // ErrorCategoryInternal means an internal error occurred. ErrorCategoryInternal ErrorCategory = "internal" // ErrorCategorySafety means the safety gate blocked the operation. ErrorCategorySafety ErrorCategory = "safety" )
func (ErrorCategory) IsRetryable ¶
func (e ErrorCategory) IsRetryable() bool
IsRetryable returns true if this error category is potentially retryable.
func (ErrorCategory) String ¶
func (e ErrorCategory) String() string
String returns the string representation of ErrorCategory.
type ExportOptions ¶
type ExportOptions struct {
// MaxSimilarityPairs limits how many similarity pairs to export.
// 0 = use default (100K), -1 = unlimited.
MaxSimilarityPairs int
// MaxDependencyEdges limits how many dependency edges to export.
// 0 = use default (100K), -1 = unlimited.
MaxDependencyEdges int
}
ExportOptions configures export behavior.
type ExportResult ¶
type ExportResult struct {
// Export is the CRS export data.
Export *CRSExport
// Truncated indicates if any index was truncated.
Truncated bool
// Warnings contains messages about truncation or other issues.
Warnings []string
}
ExportResult contains the export data and metadata.
type FailureEvent ¶
type FailureEvent struct {
// SessionID is the session where the failure occurred.
SessionID string `json:"session_id"`
// FailureType classifies the type of failure.
FailureType FailureType `json:"failure_type"`
// DecisionPath is the sequence of decisions leading to failure.
// This is analyzed by CDCL to find the conflict cut.
DecisionPath []StepRecord `json:"decision_path"`
// FailedStep is the step that failed.
FailedStep StepRecord `json:"failed_step"`
// ErrorMessage is the error message if applicable.
ErrorMessage string `json:"error_message,omitempty"`
// ErrorCategory categorizes the error for learning.
ErrorCategory ErrorCategory `json:"error_category,omitempty"`
// Tool is the tool that was involved in the failure.
Tool string `json:"tool,omitempty"`
// Source indicates signal source (should be hard for learning).
Source SignalSource `json:"source"`
}
FailureEvent represents something the agent should learn from.
Description:
When a failure occurs (tool error, cycle, circuit breaker), a FailureEvent is created and passed to the Learning Activity for CDCL analysis. The Learning Activity extracts a conflict clause that prevents the same failure.
Thread Safety: FailureEvent is immutable after creation.
func (*FailureEvent) Validate ¶
func (e *FailureEvent) Validate() error
Validate checks that the FailureEvent has required fields.
type FailureType ¶
type FailureType string
FailureType identifies the type of failure that triggered learning.
const ( // FailureTypeToolError means a tool execution failed. FailureTypeToolError FailureType = "tool_error" // FailureTypeCycleDetected means a reasoning cycle was detected. FailureTypeCycleDetected FailureType = "cycle_detected" // FailureTypeCircuitBreaker means the circuit breaker intervened. FailureTypeCircuitBreaker FailureType = "circuit_breaker" // FailureTypeTimeout means the operation timed out. FailureTypeTimeout FailureType = "timeout" // FailureTypeInvalidOutput means the output was invalid. FailureTypeInvalidOutput FailureType = "invalid_output" // FailureTypeSafety means the safety gate blocked the operation. FailureTypeSafety FailureType = "safety" // FailureTypeSemanticRepetition means a semantically similar tool call was detected. // CB-30c: Added to prevent repeated similar queries (e.g., Grep("parseConfig") then Grep("parse_config")). FailureTypeSemanticRepetition FailureType = "semantic_repetition" // FailureTypeBatchFiltered means the router filtered out this tool call as redundant. // GR-39a: Added for batch filter learning to inform CDCL clause generation. FailureTypeBatchFiltered FailureType = "batch_filtered" // FailureTypeResolutionDemotion means the post-LLM validator overrode the LLM's // conceptual symbol pick because a better tier0 candidate existed. // D3: Added for CRS-governed conceptual resolution prune/annotate/validate pipeline. FailureTypeResolutionDemotion FailureType = "resolution_demotion" )
func (FailureType) IsValid ¶
func (f FailureType) IsValid() bool
IsValid returns true if the failure type is a known value.
func (FailureType) String ¶
func (f FailureType) String() string
String returns the string representation of FailureType.
type GraphAnalyticsQuery ¶
type GraphAnalyticsQuery interface {
// HotSpots returns the top N most-connected symbols.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - k: Number of hotspots to return.
//
// Outputs:
// - []GraphHotSpot: Top k hotspots sorted by score descending.
// - error: Non-nil on failure.
//
// Thread Safety: Safe for concurrent use.
HotSpots(ctx context.Context, k int) ([]GraphHotSpot, error)
// DeadCode returns symbols that are never called/referenced.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - []string: Symbol IDs of dead code.
// - error: Non-nil on failure.
//
// Thread Safety: Safe for concurrent use.
DeadCode(ctx context.Context) ([]string, error)
// CyclicDependencies returns groups of symbols with cyclic dependencies.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - [][]string: Groups of symbol IDs forming cycles.
// - error: Non-nil on failure.
//
// Thread Safety: Safe for concurrent use.
CyclicDependencies(ctx context.Context) ([][]string, error)
// PageRank returns PageRank scores for all symbols.
//
// Description:
//
// Results are cached and recomputed only when cache is invalidated.
// May take significant time on first call for large graphs.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - map[string]float64: Symbol ID to PageRank score.
// - error: Non-nil on failure or timeout.
//
// Thread Safety: Safe for concurrent use.
PageRank(ctx context.Context) (map[string]float64, error)
// Communities returns groups of related symbols.
//
// Description:
//
// Results are cached and recomputed only when cache is invalidated.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - []GraphCommunity: Community groups.
// - error: Non-nil on failure.
//
// Thread Safety: Safe for concurrent use.
Communities(ctx context.Context) ([]GraphCommunity, error)
}
GraphAnalyticsQuery provides read-only access to graph analytics results.
Description:
Analytics results may be cached for performance. The cache is invalidated when InvalidateCache() is called on the adapter.
Thread Safety: All methods are safe for concurrent use.
type GraphBackedDependencyIndex ¶
type GraphBackedDependencyIndex struct {
// contains filtered or unexported fields
}
GraphBackedDependencyIndex provides dependency queries backed by the actual graph.
Description:
This replaces the standalone dependencyGraph that stored duplicate edge data. Instead of maintaining its own forward/reverse maps, it delegates all queries to the GraphQuery interface (typically CRSGraphAdapter from GR-28), which wraps the actual HierarchicalGraph. The index implements DependencyIndexView interface for use in CRS snapshots.
Architecture:
┌──────────────────────────────┐ │ GraphBackedDependencyIndex │ │ └── adapter GraphQuery ─────┼──► CRSGraphAdapter ──► HierarchicalGraph └──────────────────────────────┘
Limitations:
- Does NOT provide point-in-time snapshot semantics. Queries see live graph state.
- Interface methods cannot accept context.Context (existing interface constraint).
- Uses internal timeout (5 seconds) to prevent unbounded queries.
Thread Safety: Safe for concurrent read access.
func NewGraphBackedDependencyIndex ¶
func NewGraphBackedDependencyIndex(adapter GraphQuery) (*GraphBackedDependencyIndex, error)
NewGraphBackedDependencyIndex creates a dependency index backed by the graph.
Description:
Creates an index that delegates dependency queries to the GraphQuery interface (typically CRSGraphAdapter from GR-28). This eliminates data duplication between CRS and the code graph.
Inputs:
- adapter: The GraphQuery implementation. Must not be nil.
Outputs:
- *GraphBackedDependencyIndex: The new index.
- error: Non-nil if adapter is nil.
Example:
adapter, _ := graph.NewCRSGraphAdapter(g, idx, gen, refresh, nil)
depIndex, err := crs.NewGraphBackedDependencyIndex(adapter)
if err != nil {
return fmt.Errorf("create dependency index: %w", err)
}
Thread Safety: The returned index is safe for concurrent read access. The caller must ensure the adapter outlives this index.
func (*GraphBackedDependencyIndex) AllEdges ¶
func (d *GraphBackedDependencyIndex) AllEdges() map[string][]string
AllEdges returns nil for graph-backed indexes.
Description:
For GraphBackedDependencyIndex, edges live in the actual code graph which has its own persistence mechanism. Exporting edges from here would be expensive (requires querying all nodes) and redundant. Use the graph's own backup/restore mechanism for edge persistence.
Outputs:
- nil: Always returns nil. Use graph persistence instead.
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) DependedBy ¶
func (d *GraphBackedDependencyIndex) DependedBy(nodeID string) []string
DependedBy returns all nodes that depend on nodeID (callers).
Description:
Returns the IDs of all symbols that call the given node. Delegates to GraphQuery.FindCallers() and extracts symbol IDs.
Inputs:
- nodeID: The symbol ID to find dependents for.
Outputs:
- []string: Symbol IDs of callers. Empty slice if none or on error.
Limitations:
- Cannot accept context.Context due to interface constraint.
- Uses internal 5-second timeout.
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) DependsOn ¶
func (d *GraphBackedDependencyIndex) DependsOn(nodeID string) []string
DependsOn returns all nodes that nodeID depends on (callees).
Description:
Returns the IDs of all symbols that the given node calls. Delegates to GraphQuery.FindCallees() and extracts symbol IDs.
Inputs:
- nodeID: The symbol ID to find dependencies for.
Outputs:
- []string: Symbol IDs of callees. Empty slice if none or on error.
Limitations:
- Cannot accept context.Context due to interface constraint.
- Uses internal 5-second timeout.
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) Generation ¶
func (d *GraphBackedDependencyIndex) Generation() int64
Generation returns the adapter's generation for staleness detection.
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) HasCycle ¶
func (d *GraphBackedDependencyIndex) HasCycle(nodeID string) bool
HasCycle returns true if there's a cycle involving nodeID.
Description:
Checks if following call edges from nodeID eventually leads back to itself. Delegates to CRSGraphAdapter.HasCycleFrom() if supported.
Inputs:
- nodeID: The symbol ID to check for cycles from.
Outputs:
- bool: True if cycle exists, false otherwise or on error.
Limitations:
- Cannot accept context.Context due to interface constraint.
- Uses internal 5-second timeout.
- Returns false on error (safe default).
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) InvalidateCache ¶
func (d *GraphBackedDependencyIndex) InvalidateCache()
InvalidateCache marks the cache as stale.
Description:
Called when the underlying graph is refreshed. This forces Size() to recompute on next call. Also invalidates the adapter's cache if supported.
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) IsGraphBacked ¶
func (d *GraphBackedDependencyIndex) IsGraphBacked() bool
IsGraphBacked returns true for GraphBackedDependencyIndex.
Description:
Indicates that this index delegates to the graph for dependency data. When true, AllEdges() returns nil and edge export should be skipped.
Outputs:
- true: Always returns true.
Thread Safety: Safe for concurrent use.
func (*GraphBackedDependencyIndex) Size ¶
func (d *GraphBackedDependencyIndex) Size() int
Size returns the number of dependency edges (call edges).
Description:
Returns the total number of CALLS edges in the graph. Uses invalidation-based caching with singleflight to prevent thundering herd.
Outputs:
- int: Number of call edges. Returns 0 on error.
Thread Safety: Safe for concurrent use.
type GraphCommunity ¶
type GraphCommunity struct {
// ID is the community identifier.
ID string `json:"id"`
// SymbolIDs are the symbols in this community.
SymbolIDs []string `json:"symbol_ids"`
// Modularity is the community's modularity score.
Modularity float64 `json:"modularity"`
}
GraphCommunity represents a group of related symbols.
type GraphHotSpot ¶
type GraphHotSpot struct {
// SymbolID is the unique symbol identifier.
SymbolID string `json:"symbol_id"`
// Name is the symbol name.
Name string `json:"name"`
// Score is the connectivity score (higher = more connected).
Score int `json:"score"`
// InDegree is the number of incoming edges.
InDegree int `json:"in_degree"`
// OutDegree is the number of outgoing edges.
OutDegree int `json:"out_degree"`
}
GraphHotSpot represents a highly-connected symbol in the graph.
type GraphQuery ¶
type GraphQuery interface {
// FindSymbolByID returns a symbol by its unique ID.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - id: The unique symbol ID.
//
// Outputs:
// - *ast.Symbol: The symbol, or nil if not found.
// - bool: True if symbol was found.
// - error: Non-nil on context cancellation or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindSymbolByID(ctx context.Context, id string) (*ast.Symbol, bool, error)
// FindSymbolsByName returns all symbols with the given name.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - name: The symbol name to search for.
//
// Outputs:
// - []*ast.Symbol: Matching symbols. Empty slice if none found.
// - error: Non-nil on context cancellation or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindSymbolsByName(ctx context.Context, name string) ([]*ast.Symbol, error)
// FindSymbolsByKind returns all symbols of the given kind.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - kind: The symbol kind to filter by.
//
// Outputs:
// - []*ast.Symbol: Matching symbols. Empty slice if none found.
// - error: Non-nil on context cancellation or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindSymbolsByKind(ctx context.Context, kind ast.SymbolKind) ([]*ast.Symbol, error)
// FindSymbolsInFile returns all symbols in the given file.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - filePath: The file path to search in.
//
// Outputs:
// - []*ast.Symbol: Symbols in the file. Empty slice if none found.
// - error: Non-nil on context cancellation or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindSymbolsInFile(ctx context.Context, filePath string) ([]*ast.Symbol, error)
// FindCallers returns symbols that call the given symbol.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - symbolID: The symbol to find callers for.
//
// Outputs:
// - []*ast.Symbol: Caller symbols. Empty slice if none found.
// - error: Non-nil on graph query failure or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindCallers(ctx context.Context, symbolID string) ([]*ast.Symbol, error)
// FindCallees returns symbols that the given symbol calls.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - symbolID: The symbol to find callees for.
//
// Outputs:
// - []*ast.Symbol: Callee symbols. Empty slice if none found.
// - error: Non-nil on graph query failure or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindCallees(ctx context.Context, symbolID string) ([]*ast.Symbol, error)
// FindImplementations returns types that implement the given interface.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - interfaceName: The interface name to find implementations for.
//
// Outputs:
// - []*ast.Symbol: Implementing types. Empty slice if none found.
// - error: Non-nil on graph query failure or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindImplementations(ctx context.Context, interfaceName string) ([]*ast.Symbol, error)
// FindReferences returns symbols that reference the given symbol.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - symbolID: The symbol to find references for.
//
// Outputs:
// - []*ast.Symbol: Referencing symbols. Empty slice if none found.
// - error: Non-nil on graph query failure or adapter closed.
//
// Thread Safety: Safe for concurrent use.
FindReferences(ctx context.Context, symbolID string) ([]*ast.Symbol, error)
// GetCallChain returns the call chain from source to target.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - fromID: The source symbol ID.
// - toID: The target symbol ID.
// - maxDepth: Maximum traversal depth.
//
// Outputs:
// - []string: Symbol IDs in the call chain. Empty if no path found.
// - error: Non-nil on graph query failure or adapter closed.
//
// Thread Safety: Safe for concurrent use.
GetCallChain(ctx context.Context, fromID, toID string, maxDepth int) ([]string, error)
// ShortestPath returns the shortest path between two symbols.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - fromID: The source symbol ID.
// - toID: The target symbol ID.
//
// Outputs:
// - []string: Symbol IDs in the path. Empty if no path found.
// - error: Non-nil on graph query failure or adapter closed.
//
// Thread Safety: Safe for concurrent use.
ShortestPath(ctx context.Context, fromID, toID string) ([]string, error)
// Analytics returns the analytics query interface.
//
// Outputs:
// - GraphAnalyticsQuery: The analytics interface. Never nil.
//
// Thread Safety: Safe for concurrent use.
Analytics() GraphAnalyticsQuery
// NodeCount returns the number of nodes in the graph.
//
// Thread Safety: Safe for concurrent use.
NodeCount() int
// EdgeCount returns the number of edges in the graph.
//
// Thread Safety: Safe for concurrent use.
EdgeCount() int
// Generation returns the graph generation this adapter was created with.
//
// Description:
//
// Use for staleness detection. If the current graph generation is higher
// than this value, the adapter may return stale data.
//
// Thread Safety: Safe for concurrent use.
Generation() int64
// LastRefreshTime returns when the graph was last refreshed (Unix milliseconds UTC).
//
// Thread Safety: Safe for concurrent use.
LastRefreshTime() int64
// Close releases resources held by the adapter.
//
// Description:
//
// Must be called when the adapter is no longer needed to prevent
// resource leaks. After Close, all methods return ErrGraphQueryClosed.
//
// Thread Safety: Safe for concurrent use. Idempotent.
Close() error
}
GraphQuery provides read-only access to the code graph from CRS activities.
Description:
GraphQuery is the interface that allows CRS activities to query the actual code graph for structural information. This enables activities to use graph algorithms (PageRank, community detection, etc.) rather than relying solely on CRS's internal DependencyIndex. The interface is read-only from the CRS perspective - the graph is owned by the graph package and mutations happen via graph refresh, not CRS deltas.
Thread Safety: All methods are safe for concurrent use.
type GraphQueryConfig ¶
type GraphQueryConfig struct {
// CacheTTLMs is how long cached analytics results are valid (milliseconds).
// Default: 300000 (5 minutes)
CacheTTLMs int64
// PageRankTimeoutMs is the maximum time for PageRank computation (milliseconds).
// Default: 30000 (30 seconds)
PageRankTimeoutMs int64
}
GraphQueryConfig configures the GraphQuery adapter.
func DefaultGraphQueryConfig ¶
func DefaultGraphQueryConfig() *GraphQueryConfig
DefaultGraphQueryConfig returns the default configuration.
type GraphRefreshCoordinator ¶
type GraphRefreshCoordinator interface {
// Pause stops graph refresh operations.
Pause(ctx context.Context) error
// Resume allows graph refresh operations to continue.
Resume(ctx context.Context) error
// IsPaused returns true if currently paused.
IsPaused() bool
}
GraphRefreshCoordinator is implemented by components that need to pause during CRS restore operations.
Description:
During restore, the graph must not be refreshed as this could introduce inconsistent state. Components implementing this interface will be paused during restore and resumed after.
type HistoryDelta ¶
type HistoryDelta struct {
// Entries contains history entries to add.
Entries []HistoryEntry
// contains filtered or unexported fields
}
HistoryDelta represents additions to history.
func NewHistoryDelta ¶
func NewHistoryDelta(source SignalSource, entries []HistoryEntry) *HistoryDelta
NewHistoryDelta creates a new history delta.
func (*HistoryDelta) ConflictsWith ¶
func (d *HistoryDelta) ConflictsWith(_ Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*HistoryDelta) IndexesAffected ¶
func (d *HistoryDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Thread Safety: Returns a shared slice. Callers must not modify.
func (*HistoryDelta) Merge ¶
func (d *HistoryDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*HistoryDelta) Source ¶
func (d *HistoryDelta) Source() SignalSource
func (*HistoryDelta) Validate ¶
func (d *HistoryDelta) Validate(_ Snapshot) error
Validate checks if this delta can be applied.
type HistoryEntry ¶
type HistoryEntry struct {
// ID is the unique entry identifier.
ID string
// NodeID is the node this decision was about.
NodeID string
// Action is the action taken.
Action string
// Result is the outcome of the action.
Result string
// Source indicates where this decision came from.
Source SignalSource
// Timestamp is when this decision was made (Unix milliseconds UTC).
Timestamp int64
// Metadata contains additional context.
Metadata map[string]string
}
HistoryEntry represents a single decision in the history.
type HistoryEntryExport ¶
type HistoryEntryExport struct {
// ID is the unique entry identifier.
ID string `json:"id"`
// NodeID is the node this decision was about.
NodeID string `json:"node_id"`
// Action is the action taken.
Action string `json:"action"`
// Result is the outcome of the action.
Result string `json:"result"`
// Source indicates signal source.
Source string `json:"source"`
// Timestamp is when this decision was made (Unix milliseconds UTC).
Timestamp int64 `json:"timestamp"`
// Metadata contains additional context.
Metadata map[string]string `json:"metadata,omitempty"`
}
HistoryEntryExport represents a single history entry.
type HistoryIndexExport ¶
type HistoryIndexExport struct {
// EntryCount is the total number of history entries.
EntryCount int `json:"entry_count"`
// RecentEntries contains the most recent history entries.
RecentEntries []HistoryEntryExport `json:"recent_entries,omitempty"`
}
HistoryIndexExport is the serializable form of the History Index.
type HistoryIndexView ¶
type HistoryIndexView interface {
// Trace returns the decision trace for a node.
Trace(nodeID string) []HistoryEntry
// Recent returns the N most recent history entries.
Recent(n int) []HistoryEntry
// Size returns the number of history entries.
Size() int
}
HistoryIndexView provides read-only access to decision history.
Thread Safety: Safe for concurrent use (immutable).
type ImportOptions ¶
type ImportOptions struct {
// StrictValidation returns error on count mismatches.
// Default: true.
StrictValidation bool
}
ImportOptions configures import behavior.
func DefaultImportOptions ¶
func DefaultImportOptions() *ImportOptions
DefaultImportOptions returns the default import options.
type ImportedState ¶
type ImportedState struct {
// Generation is the CRS generation from the export.
Generation int64
// SessionID is the session identifier from the export.
SessionID string
// ProofData contains proof numbers keyed by node ID.
ProofData map[string]ProofNumber
// ConstraintData contains constraints keyed by constraint ID.
ConstraintData map[string]Constraint
// SimilarityData contains similarity scores (bidirectional).
// Format: map[fromID]map[toID]similarity
SimilarityData map[string]map[string]float64
// DependencyForward contains forward edges: node -> nodes it depends on.
DependencyForward map[string]map[string]struct{}
// DependencyReverse contains reverse edges: node -> nodes that depend on it.
DependencyReverse map[string]map[string]struct{}
// HistoryData contains history entries in order.
HistoryData []HistoryEntry
}
ImportedState contains the data reconstructed from a CRS export.
Description:
This struct holds all the data needed to restore CRS state. It uses the internal data structures that CRS expects, allowing direct restoration without additional transformation.
type IndexMask ¶
type IndexMask uint8
IndexMask identifies which CRS indexes were modified using a bitmask.
Description:
Uses bitmask for O(1) operations and zero allocation. There are exactly 6 CRS indexes, so a uint8 is sufficient.
Thread Safety: IndexMask is immutable; safe for concurrent use.
const ( // IndexProof indicates the proof index was modified. IndexProof IndexMask = 1 << iota // IndexConstraint indicates the constraint index was modified. IndexConstraint // IndexSimilarity indicates the similarity index was modified. IndexSimilarity // IndexDependency indicates the dependency index was modified. IndexDependency // IndexHistory indicates the history index was modified. IndexHistory // IndexStreaming indicates the streaming index was modified. IndexStreaming )
func IndexMaskFromDelta ¶
IndexMaskFromDelta converts a delta's IndexesAffected to IndexMask.
func IndexMaskFromStrings ¶
IndexMaskFromStrings converts string names to IndexMask.
func (IndexMask) MarshalJSON ¶
MarshalJSON implements json.Marshaler for backwards-compatible JSON output.
Outputs a JSON array of index names: ["proof", "constraint"]
func (IndexMask) Names ¶
Names returns the names of all indexes in the mask.
Thread Safety: Allocates a new slice on each call.
func (*IndexMask) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
Accepts either a JSON array of strings or a number (bitmask).
type IndexesExport ¶
type IndexesExport struct {
// Proof contains proof/disproof numbers for nodes.
Proof ProofIndexExport `json:"proof"`
// Constraint contains active constraints.
Constraint ConstraintIndexExport `json:"constraint"`
// Similarity contains node similarity data.
Similarity SimilarityIndexExport `json:"similarity"`
// Dependency contains dependency graph data.
Dependency DependencyIndexExport `json:"dependency"`
// History contains decision history.
History HistoryIndexExport `json:"history"`
// Streaming contains streaming statistics.
Streaming StreamingIndexExport `json:"streaming"`
}
IndexesExport contains all six indexes in JSON-serializable form.
type Journal ¶
type Journal interface {
// Append writes a delta with CRC checksum.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - delta: The CRS delta to persist. Must not be nil.
//
// Outputs:
// - error: Non-nil if write fails or context cancelled.
//
// Performance: ~100-200µs per append (BadgerDB sync write + CRC).
Append(ctx context.Context, delta Delta) error
// AppendBatch writes multiple deltas atomically in a single transaction.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - deltas: Deltas to persist. Must not be nil or empty.
//
// Outputs:
// - error: Non-nil if write fails or context cancelled.
//
// Performance: More efficient than individual Append calls.
AppendBatch(ctx context.Context, deltas []Delta) error
// Replay returns all deltas since last checkpoint with validation.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - []Delta: Deltas in order. Empty if no journal exists.
// - error: Non-nil if read fails or validation errors (unless SkipCorrupted).
//
// Usage: Called once at session start to recover state.
Replay(ctx context.Context) ([]Delta, error)
// ReplayStream returns a channel for streaming replay (low memory).
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - <-chan DeltaOrError: Channel yielding deltas or errors.
// - error: Non-nil if replay cannot start.
//
// Usage: For large journals where loading all into memory is prohibitive.
ReplayStream(ctx context.Context) (<-chan DeltaOrError, error)
// Checkpoint marks current position, enabling journal truncation.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
//
// Outputs:
// - error: Non-nil if checkpoint fails.
//
// Usage: Called after successful state persistence to Weaviate.
Checkpoint(ctx context.Context) error
// IsAvailable returns false if journal is in degraded mode.
IsAvailable() bool
// IsDegraded returns true if journal is operating with reduced durability.
IsDegraded() bool
// Sync flushes pending writes to disk.
//
// Outputs:
// - error: Non-nil if sync fails.
Sync() error
// Close syncs and releases resources.
//
// Outputs:
// - error: Non-nil if close fails.
Close() error
// Stats returns journal statistics.
Stats() JournalStats
// Backup creates a portable backup of the journal.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - w: Writer to receive backup data. Must not be nil.
//
// Outputs:
// - error: Non-nil if backup fails.
//
// Thread Safety: Safe for concurrent use.
Backup(ctx context.Context, w io.Writer) error
// Restore loads state from a backup.
//
// Inputs:
// - ctx: Context for cancellation. Must not be nil.
// - r: Reader containing backup data. Must not be nil.
//
// Outputs:
// - error: Non-nil if restore fails.
//
// Limitations:
// - Restore is all-or-nothing: failure leaves journal in undefined state.
//
// Thread Safety: NOT safe for concurrent use. Caller must ensure exclusivity.
Restore(ctx context.Context, r io.Reader) error
}
Journal provides crash recovery for CRS via Write-Ahead Logging.
Description:
Appends deltas synchronously to BadgerDB with CRC checksums. On restart, replays all deltas since last checkpoint to reconstruct state.
Thread Safety: Safe for concurrent use from multiple goroutines.
type JournalConfig ¶
type JournalConfig struct {
// Path is the directory for BadgerDB files.
// Required for persistent mode.
Path string
// SessionID scopes this journal to a specific session.
// Required. Used as key prefix for isolation.
SessionID string
// SyncWrites enables synchronous writes for durability.
// MUST be true for WAL correctness. Default: true.
SyncWrites bool
// MaxJournalBytes triggers checkpoint when exceeded.
// Default: 1GB. Set to 0 to disable limit.
MaxJournalBytes int64
// AllowDegraded allows startup even if BadgerDB unavailable.
// When true, journal operates in memory-only mode with reduced durability.
// Default: false (strict mode).
AllowDegraded bool
// SkipCorruptedDeltas continues replay past corrupted entries.
// Corrupted entries are logged and skipped.
// Default: false (fail fast).
SkipCorruptedDeltas bool
// InMemory uses in-memory BadgerDB (for testing).
// Default: false.
InMemory bool
// Logger for journal operations.
// Default: slog.Default().
Logger *slog.Logger
}
JournalConfig configures journal behavior.
Description:
Contains all settings for journal operation including durability, size limits, and degradation behavior.
func DefaultJournalConfig ¶
func DefaultJournalConfig() JournalConfig
DefaultJournalConfig returns sensible defaults for production use.
Outputs:
JournalConfig - Ready-to-use production configuration.
func (*JournalConfig) Validate ¶
func (c *JournalConfig) Validate() error
Validate checks if the configuration is valid.
type JournalStats ¶
type JournalStats struct {
// TotalDeltas is the count of deltas in the journal.
TotalDeltas int64
// TotalBytes is approximate size of journal data.
TotalBytes int64
// LastSeqNum is the most recent sequence number.
LastSeqNum uint64
// LastCheckpoint is when the last checkpoint occurred.
LastCheckpoint time.Time
// CorruptedCount is the number of corrupted entries encountered.
CorruptedCount int64
// Degraded indicates if running in degraded mode.
Degraded bool
}
JournalStats contains journal metrics.
type KeyValue ¶
KeyValue is a typed key-value pair for extra parameters. This provides a bounded, auditable alternative to map[string]any.
type Literal ¶
type Literal struct {
// Variable is the decision variable name.
// Format: "<type>:<value>" e.g., "tool:list_packages", "outcome:success"
Variable string `json:"variable"`
// Negated indicates if this literal is negated (NOT).
Negated bool `json:"negated"`
}
Literal represents a single variable assignment in a clause.
Description:
A literal is either a variable (positive) or its negation (negative). Variables use the format "<type>:<value>" e.g., "tool:list_packages", "outcome:success", "error:file_not_found".
Thread Safety: Literal is immutable after creation.
type NATSJournal ¶
type NATSJournal struct {
// contains filtered or unexported fields
}
NATSJournal implements the Journal interface using NATS JetStream.
Description:
Replaces BadgerJournal with NATS JetStream for CRS delta persistence. Each delta is published to a subject scoped by session ID, encoded as [4-byte CRC32][gob-encoded Delta]. NATS message sequence numbers replace manual seqNum counters. Checkpoints are stored as separate messages containing the sequence number up to which deltas can be purged.
Thread Safety: Safe for concurrent use from multiple goroutines.
func NewNATSJournal ¶
func NewNATSJournal(config NATSJournalConfig) (*NATSJournal, error)
NewNATSJournal creates a new NATS JetStream journal.
Description:
Initializes a journal backed by NATS JetStream. The stream must already exist (created by storage/nats.Client.EnsureStream). The journal initializes its sequence number from the latest message in the stream.
Inputs:
- config: Journal configuration. SessionID and JS are required.
Outputs:
- *NATSJournal: Configured journal ready for use.
- error: Non-nil if configuration is invalid or stream is inaccessible.
Thread Safety: Safe for concurrent use after creation.
func (*NATSJournal) Append ¶
func (j *NATSJournal) Append(ctx context.Context, delta Delta) error
Append writes a delta to NATS JetStream with CRC checksum.
Description:
Publishes a CRC32+gob encoded delta to the session's delta subject. NATS assigns a monotonically increasing sequence number automatically.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- delta: The CRS delta to persist. Must not be nil.
Outputs:
- error: Non-nil if publish fails or context is cancelled.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) AppendBatch ¶
func (j *NATSJournal) AppendBatch(ctx context.Context, deltas []Delta) error
AppendBatch writes multiple deltas sequentially to NATS JetStream.
Description:
Publishes deltas one at a time under a mutex for ordering guarantees. NATS JetStream does not support atomic multi-message transactions, but deltas are idempotent on replay so partial batches are acceptable.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- deltas: Deltas to persist. Must not be nil or empty.
Outputs:
- error: Non-nil if any publish fails.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) Backup ¶
Backup creates a portable backup of the journal.
Description:
Iterates all delta messages on this session's subject via an ordered consumer and writes them as length-prefixed frames to the writer. Frame format: [4-byte big-endian length][message data].
Inputs:
- ctx: Context for cancellation. Must not be nil.
- w: Writer to receive backup data. Must not be nil.
Outputs:
- error: Non-nil if backup fails.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) Checkpoint ¶
func (j *NATSJournal) Checkpoint(ctx context.Context) error
Checkpoint marks the current position for journal truncation.
Description:
Publishes the current sequence number to the checkpoint subject and purges delta messages up to that sequence number.
Inputs:
- ctx: Context for cancellation. Must not be nil.
Outputs:
- error: Non-nil if checkpoint fails.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) Close ¶
func (j *NATSJournal) Close() error
Close marks the journal as closed.
Description:
Marks the journal as closed so future operations return ErrJournalClosed. Does not close the underlying NATS connection (that's managed by the Client).
Outputs:
- error: Always nil.
Thread Safety: Safe for concurrent use. Idempotent.
func (*NATSJournal) IsAvailable ¶
func (j *NATSJournal) IsAvailable() bool
IsAvailable returns true if the journal is operational.
Description:
Returns false if the journal is in degraded mode (NATS unavailable).
Outputs:
- bool: True if journal can accept writes.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) IsDegraded ¶
func (j *NATSJournal) IsDegraded() bool
IsDegraded returns true if the journal is in degraded mode.
Description:
Degraded mode occurs when NATS becomes unavailable after initial connection. In degraded mode, writes return ErrJournalDegraded and replays return empty results.
Outputs:
- bool: True if operating with reduced durability.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) Replay ¶
func (j *NATSJournal) Replay(ctx context.Context) ([]Delta, error)
Replay returns all deltas since last checkpoint with validation.
Description:
Creates an ordered consumer to fetch all deltas from the checkpoint sequence + 1 to the latest message. Validates CRC on each delta.
Inputs:
- ctx: Context for cancellation. Must not be nil.
Outputs:
- []Delta: Ordered deltas since last checkpoint. Empty if no journal.
- error: Non-nil if read fails or CRC validation errors.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) ReplayStream ¶
func (j *NATSJournal) ReplayStream(ctx context.Context) (<-chan DeltaOrError, error)
ReplayStream returns a channel for streaming replay.
Description:
Same as Replay but yields deltas through a channel for low-memory consumption on large journals.
Inputs:
- ctx: Context for cancellation. Must not be nil.
Outputs:
- <-chan DeltaOrError: Channel yielding deltas or errors.
- error: Non-nil if replay cannot start.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) Restore ¶
Restore loads state from a backup.
Description:
Reads length-prefixed frames from the reader and publishes each as a delta message to NATS JetStream. This rebuilds the journal state from a portable backup.
Inputs:
- ctx: Context for cancellation. Must not be nil.
- r: Reader containing backup data. Must not be nil.
Outputs:
- error: Non-nil if restore fails.
Limitations:
- Restore is all-or-nothing: partial restores leave partial data.
Thread Safety: NOT safe for concurrent use. Caller must ensure exclusivity.
func (*NATSJournal) Stats ¶
func (j *NATSJournal) Stats() JournalStats
Stats returns journal statistics.
Description:
Returns current journal metrics including delta count, byte size, sequence number, and degraded status. For NATS journals, attempts to query JetStream stream info for accurate counts.
Outputs:
- JournalStats: Current journal statistics.
Thread Safety: Safe for concurrent use.
func (*NATSJournal) Sync ¶
func (j *NATSJournal) Sync() error
Sync is a no-op for NATS JetStream (file storage is durable).
Description:
JetStream with file storage is already durable on publish acknowledgment. This method exists only to satisfy the Journal interface.
Outputs:
- error: Always nil.
Thread Safety: Safe for concurrent use.
type NATSJournalConfig ¶
type NATSJournalConfig struct {
// SessionID scopes this journal to a specific session.
// Required. Used in NATS subject names for isolation.
SessionID string
// JS is the JetStream context for publishing and subscribing.
// Required. Must not be nil.
JS nats.JetStreamContext
// StreamName is the JetStream stream name.
// Required. Must match the stream created by EnsureStream.
StreamName string
// MaxJournalBytes limits total journal size. 0 means no limit.
MaxJournalBytes int64
// AllowDegraded allows journal to continue in degraded mode
// if NATS becomes unavailable after initial connection.
AllowDegraded bool
// SkipCorruptedDeltas skips corrupted deltas during replay
// instead of returning an error.
SkipCorruptedDeltas bool
// Logger is the structured logger.
// If nil, slog.Default() is used.
Logger *slog.Logger
}
NATSJournalConfig configures the NATS JetStream journal.
Description:
Contains settings for NATS-backed CRS delta journaling. Uses JetStream for durable, observable storage with built-in sequence numbering.
Inputs:
SessionID - Unique session identifier for subject scoping. JS - JetStream context obtained from a NATS client. StreamName - Name of the JetStream stream (e.g., "CRS_DELTAS").
Limitations:
- Requires an active NATS connection with JetStream enabled.
Assumptions:
- The stream has already been created (via storage/nats.Client.EnsureStream).
type NodeFrequency ¶
NodeFrequency pairs a node ID with its access frequency.
type NodeStats ¶
type NodeStats struct {
// NodeID is the node identifier.
NodeID string
// Proof information (if exists).
HasProof bool
ProofNumber ProofNumber
// Constraint information.
ConstraintCount int
Constraints []string // Constraint IDs
// Similarity information.
SimilarNodeCount int
NearestNeighbor string
NearestDistance float64
// Dependency information.
DependsOnCount int
DependedByCount int
HasCycle bool
// History information.
HistoryEntryCount int
LastAction string
LastActionTime string
// Streaming information.
AccessFrequency uint64
}
NodeStats contains comprehensive statistics about a node.
type Outcome ¶
type Outcome string
Outcome identifies the result of a step.
const ( // OutcomeSuccess means the step completed successfully. OutcomeSuccess Outcome = "success" // OutcomeFailure means the step failed. OutcomeFailure Outcome = "failure" // OutcomeSkipped means the step was skipped (e.g., low confidence). OutcomeSkipped Outcome = "skipped" // OutcomeForced means the outcome was forced (e.g., circuit breaker). OutcomeForced Outcome = "forced" )
type PersistenceConfig ¶
type PersistenceConfig struct {
// BaseDir is the root directory for all CRS persistence data.
// Default: ~/.aleutian/crs/
BaseDir string
// CompressionLevel is the gzip compression level (1-9).
// Higher = smaller files, slower. Default: 6.
CompressionLevel int
// LockTimeoutSec is how long to wait for file lock.
// Default: 30 seconds.
LockTimeoutSec int
// MaxBackupRetries is the number of retry attempts on transient failures.
// Default: 3.
MaxBackupRetries int
// ValidateOnRestore enables integrity checks during restore.
// Default: true.
ValidateOnRestore bool
// Logger for persistence operations.
Logger *slog.Logger
}
PersistenceConfig configures the PersistenceManager.
func DefaultPersistenceConfig ¶
func DefaultPersistenceConfig() PersistenceConfig
DefaultPersistenceConfig returns production defaults.
func (*PersistenceConfig) Validate ¶
func (c *PersistenceConfig) Validate() error
Validate checks if the configuration is valid.
type PersistenceManager ¶
type PersistenceManager struct {
// contains filtered or unexported fields
}
PersistenceManager handles CRS state persistence across sessions.
Description:
Provides backup and restore functionality for CRS state using BadgerDB's native backup mechanism. Features include: - Gzip compression for space efficiency - SHA256 content hashing for integrity verification - flock-based file locking for concurrent access safety - Atomic file operations to prevent corruption - BadgerDB version compatibility checking - Optional JSON export for portability
Thread Safety: Safe for concurrent use.
func NewPersistenceManager ¶
func NewPersistenceManager(config *PersistenceConfig) (*PersistenceManager, error)
NewPersistenceManager creates a new persistence manager.
Description:
Creates a manager rooted at the configured base directory. Creates the directory structure if it doesn't exist.
Inputs:
- config: Configuration. If nil, uses DefaultPersistenceConfig().
Outputs:
- *PersistenceManager: The new manager.
- error: Non-nil if configuration is invalid or directory creation fails.
Example:
cfg := DefaultPersistenceConfig()
pm, err := NewPersistenceManager(&cfg)
if err != nil {
return fmt.Errorf("create persistence manager: %w", err)
}
defer pm.Close()
Thread Safety: Safe for concurrent use.
func (*PersistenceManager) BackupPath ¶
func (pm *PersistenceManager) BackupPath(projectHash string) string
BackupPath returns the path to the backup file.
func (*PersistenceManager) Close ¶
func (pm *PersistenceManager) Close() error
Close releases resources.
func (*PersistenceManager) ExportPath ¶
func (pm *PersistenceManager) ExportPath(projectHash string) string
ExportPath returns the path to the JSON export file.
func (*PersistenceManager) GetBackupMetadata ¶
func (pm *PersistenceManager) GetBackupMetadata(projectHash string) (*BackupMetadata, error)
GetBackupMetadata returns metadata for an existing backup.
Outputs:
- *BackupMetadata: Metadata, or nil if no backup exists.
- error: Non-nil on read error (not on missing backup).
Thread Safety: Safe for concurrent use.
func (*PersistenceManager) HasBackup ¶
func (pm *PersistenceManager) HasBackup(projectHash string) bool
HasBackup checks if a backup exists for a project.
Thread Safety: Safe for concurrent use.
func (*PersistenceManager) LoadBackup ¶
func (pm *PersistenceManager) LoadBackup(ctx context.Context, projectHash string, journal Journal) (*BackupMetadata, error)
LoadBackup restores journal state from a backup.
Description:
Restores the journal from a compressed backup file. Performs integrity verification (SHA256 hash check) and version compatibility check before restoring. Coordinates with the graph refresh coordinator if set.
Inputs:
- ctx: Context for cancellation and tracing. Must not be nil.
- projectHash: Project identifier. Must not be empty.
- journal: The BadgerJournal to restore into. Must not be nil.
Outputs:
- *BackupMetadata: Metadata about the restored backup.
- error: Non-nil if restore fails. ErrBackupNotFound if no backup exists.
Example:
meta, err := pm.LoadBackup(ctx, "abc123def456", journal)
if errors.Is(err, ErrBackupNotFound) {
// First run, no backup exists
return nil
}
if err != nil {
return fmt.Errorf("restore: %w", err)
}
Thread Safety: Safe for concurrent use. Uses file locking.
func (*PersistenceManager) LockPath ¶
func (pm *PersistenceManager) LockPath(projectHash string) string
LockPath returns the path to the lock file.
func (*PersistenceManager) MetadataPath ¶
func (pm *PersistenceManager) MetadataPath(projectHash string) string
MetadataPath returns the path to the metadata file.
func (*PersistenceManager) PrevBackupPath ¶
func (pm *PersistenceManager) PrevBackupPath(projectHash string) string
PrevBackupPath returns the path to the previous generation backup. CRS-21: Two-generation checkpoint rotation for crash safety.
func (*PersistenceManager) PrevMetadataPath ¶
func (pm *PersistenceManager) PrevMetadataPath(projectHash string) string
PrevMetadataPath returns the path to the previous generation metadata. CRS-21: Two-generation checkpoint rotation for crash safety.
func (*PersistenceManager) ProjectDir ¶
func (pm *PersistenceManager) ProjectDir(projectHash string) string
ProjectDir returns the directory for a specific project.
func (*PersistenceManager) SaveBackup ¶
func (pm *PersistenceManager) SaveBackup(ctx context.Context, projectHash string, journal Journal, opts *BackupOptions) (*BackupMetadata, error)
SaveBackup creates a backup of the journal state.
Description:
Creates a compressed, integrity-verified backup of the BadgerDB journal. Uses atomic file operations to ensure backup is either completely written or not at all. Optionally creates a JSON export for portability. Implements retry logic for transient failures.
Inputs:
- ctx: Context for cancellation and tracing. Must not be nil.
- projectHash: Project identifier (8-64 hex chars). Must not be empty.
- journal: The BadgerJournal to backup. Must not be nil.
- opts: Optional backup options (nil for defaults).
Outputs:
- *BackupMetadata: Metadata about the created backup.
- error: Non-nil if backup fails after all retries.
Example:
meta, err := pm.SaveBackup(ctx, "abc123def456", journal, nil)
if err != nil {
return fmt.Errorf("backup: %w", err)
}
log.Info("backup created", "size", meta.CompressedSize)
Thread Safety: Safe for concurrent use. Uses file locking for safety.
func (*PersistenceManager) SetRefreshCoordinator ¶
func (pm *PersistenceManager) SetRefreshCoordinator(coordinator GraphRefreshCoordinator)
SetRefreshCoordinator registers the graph refresh coordinator.
Description:
The coordinator will be paused during restore operations to prevent graph refresh from interfering with state restoration.
Inputs:
- coordinator: The coordinator to pause/resume. May be nil.
Thread Safety: Safe for concurrent use.
type ProofDelta ¶
type ProofDelta struct {
// Updates maps node ID to new proof number.
Updates map[string]ProofNumber
// contains filtered or unexported fields
}
ProofDelta represents changes to proof numbers.
func NewProofDelta ¶
func NewProofDelta(source SignalSource, updates map[string]ProofNumber) *ProofDelta
NewProofDelta creates a new proof delta.
Inputs:
- source: The signal source (hard or soft).
- updates: Map of node ID to proof number updates.
Outputs:
- *ProofDelta: The new delta.
func (*ProofDelta) ConflictsWith ¶
func (d *ProofDelta) ConflictsWith(other Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*ProofDelta) IndexesAffected ¶
func (d *ProofDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Thread Safety: Returns a shared slice. Callers must not modify.
func (*ProofDelta) Merge ¶
func (d *ProofDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*ProofDelta) Source ¶
func (d *ProofDelta) Source() SignalSource
func (*ProofDelta) Validate ¶
func (d *ProofDelta) Validate(snapshot Snapshot) error
Validate checks if this delta can be applied.
Description:
Validates the hard/soft signal boundary. Soft signals cannot mark nodes as DISPROVEN.
type ProofEntry ¶
type ProofEntry struct {
// NodeID is the unique node identifier.
NodeID string `json:"node_id"`
// Proof is the proof number (cost to prove).
Proof uint64 `json:"proof"`
// Disproof is the disproof number (cost to disprove).
Disproof uint64 `json:"disproof"`
// Status is the current proof status: "unknown", "proven", "disproven", "expanded".
Status string `json:"status"`
// Source indicates signal source: "unknown", "hard", "soft".
Source string `json:"source"`
// UpdatedAt is when this entry was last updated (RFC3339 format).
UpdatedAt time.Time `json:"updated_at"`
}
ProofEntry represents a single proof number entry.
type ProofIndexExport ¶
type ProofIndexExport struct {
// Entries contains all proof number entries.
Entries []ProofEntry `json:"entries"`
}
ProofIndexExport is the serializable form of the Proof Index.
type ProofIndexView ¶
type ProofIndexView interface {
// Get returns the proof number for a node.
Get(nodeID string) (ProofNumber, bool)
// All returns all proof numbers.
All() map[string]ProofNumber
// Size returns the number of entries.
Size() int
}
ProofIndexView provides read-only access to proof numbers.
Thread Safety: Safe for concurrent use (immutable).
type ProofNumber ¶
type ProofNumber struct {
// Proof is the proof number (cost to prove this node).
Proof uint64
// Disproof is the disproof number (cost to disprove this node).
Disproof uint64
// Status is the current proof status.
Status ProofStatus
// Source indicates where this proof came from.
Source SignalSource
// UpdatedAt is when this proof was last updated (Unix milliseconds UTC).
UpdatedAt int64
}
ProofNumber represents proof and disproof numbers for a node.
type ProofStatus ¶
type ProofStatus int
ProofStatus represents the proof status of a node.
const ( // ProofStatusUnknown means the node's proof status is not determined. ProofStatusUnknown ProofStatus = iota // ProofStatusProven means the node is proven (leads to solution). ProofStatusProven // ProofStatusDisproven means the node is disproven (does not lead to solution). ProofStatusDisproven // ProofStatusExpanded means the node has been expanded but not proven/disproven. ProofStatusExpanded )
func (ProofStatus) String ¶
func (s ProofStatus) String() string
String returns the string representation of ProofStatus.
type ProofUpdate ¶
type ProofUpdate struct {
// NodeID is the node whose proof status changed.
NodeID string `json:"node_id"`
// Type is the type of update to apply.
Type ProofUpdateType `json:"type"`
// Delta is the amount to increment/decrement (ignored for Disproven/Proven).
Delta uint64 `json:"delta,omitempty"`
// Reason explains why this update is being made.
Reason string `json:"reason,omitempty"`
// Source indicates where this signal came from (hard, soft, safety).
Source SignalSource `json:"source"`
// Status is the new status (used for JSON serialization compatibility).
// Deprecated: Use Type instead. This field exists for backwards compatibility
// with trace_recorder.go format.
Status string `json:"status,omitempty"`
}
ProofUpdate represents a proof number update operation.
Description:
Used by RecordStep and UpdateProofNumber to track changes to proof numbers. The update type determines how the proof number is modified: - Increment: Add Delta to proof number (failure) - Decrement: Subtract Delta from proof number (success) - Disproven: Set status to disproven regardless of current number - Proven: Set status to proven regardless of current number
Thread Safety: ProofUpdate is immutable after creation.
func (*ProofUpdate) Validate ¶
func (u *ProofUpdate) Validate() error
Validate checks that the ProofUpdate has required fields.
type ProofUpdateType ¶
type ProofUpdateType int
ProofUpdateType identifies the type of proof number update.
Description:
In PN-MCTS, proof number represents the COST TO PROVE a node (lower = easier). This is the OPPOSITE of a "success count": - Success DECREASES proof number (path is viable, easier to prove) - Failure INCREASES proof number (path is problematic, harder to prove) - Disproven means infinite cost (path cannot lead to solution)
const ( // ProofUpdateTypeUnknown is an unknown update type. ProofUpdateTypeUnknown ProofUpdateType = iota // ProofUpdateTypeIncrement increases proof number (failure = harder to prove). ProofUpdateTypeIncrement // ProofUpdateTypeDecrement decreases proof number (success = easier to prove). ProofUpdateTypeDecrement // ProofUpdateTypeDisproven marks node as disproven (infinite cost). ProofUpdateTypeDisproven // ProofUpdateTypeProven marks node as proven (solution found via this path). ProofUpdateTypeProven // ProofUpdateTypeReset resets proof number to initial value. ProofUpdateTypeReset )
func (ProofUpdateType) IsValid ¶
func (t ProofUpdateType) IsValid() bool
IsValid returns true if the update type is a known value.
func (ProofUpdateType) String ¶
func (t ProofUpdateType) String() string
String returns the string representation of ProofUpdateType.
type QueryAPI ¶
type QueryAPI interface {
// FindProvenNodes returns all nodes with PROVEN status.
//
// Outputs:
// - []string: Node IDs that are proven. Empty if none.
FindProvenNodes() []string
// FindDisprovenNodes returns all nodes with DISPROVEN status.
//
// Outputs:
// - []string: Node IDs that are disproven. Empty if none.
FindDisprovenNodes() []string
// FindUnexploredNodes returns nodes that haven't been fully explored.
//
// Description:
// A node is unexplored if it has proof status UNKNOWN or EXPANDED
// but not PROVEN or DISPROVEN.
//
// Outputs:
// - []string: Node IDs that are unexplored. Empty if none.
FindUnexploredNodes() []string
// FindByProofRange returns nodes with proof numbers in the given range.
//
// Inputs:
// - minProof: Minimum proof number (inclusive).
// - maxProof: Maximum proof number (inclusive).
//
// Outputs:
// - []string: Node IDs in range, sorted by proof number ascending.
FindByProofRange(minProof, maxProof uint64) []string
// FindConstrainedNodes returns nodes that have constraints on them.
//
// Inputs:
// - constraintType: Type of constraint to filter by. Use ConstraintTypeUnknown for all.
//
// Outputs:
// - []string: Node IDs with constraints. Empty if none.
FindConstrainedNodes(constraintType ConstraintType) []string
// FindViolatedConstraints returns constraints where at least one node is DISPROVEN.
//
// Outputs:
// - []Constraint: Constraints with disproven nodes. Empty if none.
FindViolatedConstraints() []Constraint
// FindSimilarWithProofStatus returns nodes similar to nodeID with the given status.
//
// Inputs:
// - nodeID: The node to find similar nodes for.
// - status: The proof status to filter by.
// - k: Maximum number of similar nodes to return.
//
// Outputs:
// - []SimilarityMatch: Similar nodes with matching status, sorted by distance.
FindSimilarWithProofStatus(nodeID string, status ProofStatus, k int) []SimilarityMatch
// FindDependencyChain returns the dependency chain from start to end.
//
// Description:
// Uses BFS to find the shortest path from start to end through dependencies.
//
// Inputs:
// - startNodeID: The starting node.
// - endNodeID: The target node.
//
// Outputs:
// - []string: Path from start to end (inclusive). Empty if no path exists.
FindDependencyChain(startNodeID, endNodeID string) []string
// FindAffectedByNode returns all nodes that would be affected if nodeID changed.
//
// Description:
// Computes the transitive closure of nodes that depend on nodeID.
//
// Inputs:
// - nodeID: The node to check impact for.
//
// Outputs:
// - []string: All nodes affected (transitively). Empty if none.
FindAffectedByNode(nodeID string) []string
// FindHotNodes returns the most frequently accessed nodes.
//
// Inputs:
// - n: Number of hot nodes to return.
//
// Outputs:
// - []NodeFrequency: Top N nodes by frequency.
FindHotNodes(n int) []NodeFrequency
// FindRecentDecisions returns recent history entries with optional filtering.
//
// Inputs:
// - n: Maximum number of entries.
// - source: Filter by source. Use SignalSourceUnknown for all.
//
// Outputs:
// - []HistoryEntry: Recent entries matching filter.
FindRecentDecisions(n int, source SignalSource) []HistoryEntry
// NodeStats returns comprehensive statistics about a node across all indexes.
//
// Inputs:
// - nodeID: The node to get stats for.
//
// Outputs:
// - *NodeStats: Statistics about the node. Nil if node not found anywhere.
NodeStats(nodeID string) *NodeStats
}
QueryAPI provides cross-index query capabilities.
Description:
QueryAPI enables queries that span multiple indexes, such as finding proven nodes that satisfy certain constraints or nodes with high similarity that are dependencies of each other.
Thread Safety: Safe for concurrent use (operates on immutable snapshot).
type ReasoningSummary ¶
type ReasoningSummary struct {
// NodesExplored is the total number of nodes in the proof index.
NodesExplored int `json:"nodes_explored"`
// NodesProven is the count of nodes with PROVEN status.
NodesProven int `json:"nodes_proven"`
// NodesDisproven is the count of nodes with DISPROVEN status.
NodesDisproven int `json:"nodes_disproven"`
// NodesUnknown is the count of nodes with UNKNOWN or EXPANDED status.
NodesUnknown int `json:"nodes_unknown"`
// ConstraintsApplied is the number of active constraints.
ConstraintsApplied int `json:"constraints_applied"`
// ExplorationDepth is the number of history entries (proxy for depth).
ExplorationDepth int `json:"exploration_depth"`
// ConfidenceScore is the ratio of proven nodes to explored nodes.
// Value is between 0.0 and 1.0. Use with caution - this is a coverage
// metric, not a statistical confidence interval.
ConfidenceScore float64 `json:"confidence_score"`
}
ReasoningSummary provides high-level metrics about reasoning progress.
Description:
Computed from CRS state to give a quick overview of reasoning progress without requiring full index inspection.
type ReasoningTrace ¶
type ReasoningTrace struct {
// SessionID identifies the session this trace belongs to.
SessionID string `json:"session_id"`
// TotalSteps is the number of steps recorded.
TotalSteps int `json:"total_steps"`
// Duration is the total time from first to last step.
Duration string `json:"total_duration"`
// StartTime is when the first step occurred (Unix milliseconds UTC).
StartTime int64 `json:"start_time,omitempty"`
// EndTime is when the last step occurred (Unix milliseconds UTC).
EndTime int64 `json:"end_time,omitempty"`
// Trace contains all recorded steps.
Trace []TraceStep `json:"trace"`
}
ReasoningTrace is the exportable trace format.
type RestoreResult ¶
type RestoreResult struct {
// Restored is true if a checkpoint was successfully restored.
Restored bool `json:"restored"`
// CheckpointID is the ID of the restored checkpoint (empty if not restored).
CheckpointID string `json:"checkpoint_id,omitempty"`
// Generation is the CRS generation of the restored state.
Generation int64 `json:"generation,omitempty"`
// CheckpointTime is when the checkpoint was created (Unix milliseconds UTC).
// GR-36 Code Review Fix: S3 - Use int64 instead of time.Time.
CheckpointTime int64 `json:"checkpoint_time,omitempty"`
// CheckpointAge is how old the checkpoint was at restore time.
CheckpointAge time.Duration `json:"checkpoint_age,omitempty"`
// Reason explains why restore succeeded or failed.
Reason string `json:"reason"`
// ModifiedFiles is the list of files modified since checkpoint.
ModifiedFiles []string `json:"modified_files,omitempty"`
// ModifiedFileCount is the total count (may exceed len(ModifiedFiles) if truncated).
ModifiedFileCount int `json:"modified_file_count"`
// DurationMs is how long the restore took in milliseconds.
DurationMs int64 `json:"duration_ms"`
}
RestoreResult describes what happened during session restore.
Description:
Contains the outcome of a restore attempt including whether it succeeded, checkpoint details, and any modified files detected.
Thread Safety: Immutable after creation; safe for concurrent use.
type Sanitizer ¶
type Sanitizer interface {
// Sanitize redacts sensitive data from a string.
//
// Inputs:
// s - The string to sanitize.
//
// Outputs:
// string - The sanitized string with secrets replaced by [REDACTED].
Sanitize(s string) string
}
Sanitizer sanitizes sensitive data before recording.
Description:
Implementations should redact secrets, PII, and other sensitive data to prevent leakage into audit trails.
Thread Safety:
Implementations must be safe for concurrent use.
type SecretSanitizer ¶
type SecretSanitizer struct {
// contains filtered or unexported fields
}
SecretSanitizer detects and redacts secrets from strings.
Description:
SecretSanitizer uses regex patterns to detect common secret formats including API keys, tokens, passwords, and private keys. Detected secrets are replaced with [REDACTED].
Thread Safety:
SecretSanitizer is safe for concurrent use after initialization.
func NewSecretSanitizer ¶
func NewSecretSanitizer() *SecretSanitizer
NewSecretSanitizer creates a new secret sanitizer with default patterns.
Description:
Creates a sanitizer that detects common secret patterns including: - AWS keys (AKIA*, ASIA*, etc.) - Google Cloud API keys (AIza*) - GitHub tokens (ghp_*, gho_*, etc.) - Slack tokens (xox*) - Private keys (-----BEGIN * PRIVATE KEY-----) - Generic API keys and passwords - Database connection strings with credentials - JWT secrets
Outputs:
*SecretSanitizer - The configured sanitizer.
func (*SecretSanitizer) Sanitize ¶
func (ss *SecretSanitizer) Sanitize(s string) string
Sanitize replaces detected secrets with [REDACTED].
Description:
Scans the input string for known secret patterns and replaces any matches with [REDACTED]. Multiple secrets in the same string are all replaced.
Inputs:
s - The string to sanitize.
Outputs:
string - The sanitized string with secrets replaced.
Thread Safety:
This method is safe for concurrent use.
func (*SecretSanitizer) SanitizeMap ¶
func (ss *SecretSanitizer) SanitizeMap(m map[string]string) map[string]string
SanitizeMap sanitizes all values in a string map.
Description:
Creates a new map with all values sanitized. Keys are preserved.
Inputs:
m - The map to sanitize.
Outputs:
map[string]string - New map with sanitized values.
Thread Safety:
This method is safe for concurrent use.
type Serializer ¶
type Serializer struct {
// contains filtered or unexported fields
}
Serializer converts CRS snapshots to exportable JSON formats.
Thread Safety: Safe for concurrent use (stateless).
func NewSerializer ¶
func NewSerializer(logger *slog.Logger) *Serializer
NewSerializer creates a new CRS serializer.
Inputs:
logger - Logger for serialization events. Uses default if nil.
Outputs:
*Serializer - The configured serializer.
func (*Serializer) ComputeSummary ¶
func (s *Serializer) ComputeSummary(snapshot Snapshot) ReasoningSummary
ComputeSummary computes summary metrics from a snapshot.
Thread Safety: Safe for concurrent use.
func (*Serializer) Export ¶
func (s *Serializer) Export(snapshot Snapshot, sessionID string) *CRSExport
Export converts a CRS snapshot to exportable JSON format.
Description:
Takes an immutable CRS snapshot and converts all indexes to JSON-serializable structures. Computes summary metrics.
Inputs:
snapshot - Immutable CRS snapshot. If nil, returns empty export. sessionID - Session identifier for the export.
Outputs:
*CRSExport - Serializable CRS state. Never nil.
Thread Safety: Safe for concurrent use.
func (*Serializer) ExportFull ¶
func (s *Serializer) ExportFull(ctx context.Context, snapshot Snapshot, sessionID string, opts *ExportOptions) (*ExportResult, error)
ExportFull creates a full export of CRS state with options.
Description:
Creates a JSON-serializable export of all CRS indexes, including the previously incomplete SimilarityIndex and DependencyIndex. Operates on an immutable snapshot for thread safety.
Inputs:
- ctx: Context for cancellation and tracing. Must not be nil.
- snapshot: Immutable CRS snapshot to export. Must not be nil.
- sessionID: Session identifier for the export.
- opts: Export options. If nil, uses defaults (100K pair limit).
Outputs:
- *ExportResult: Export data and metadata. Never nil on success.
- error: Non-nil if context is nil, snapshot is nil, or export fails.
Example:
result, err := serializer.ExportFull(ctx, snap, "session-123", nil)
if err != nil {
return fmt.Errorf("export: %w", err)
}
if result.Truncated {
log.Warn("export truncated", "warnings", result.Warnings)
}
Thread Safety: Safe for concurrent use (reads immutable snapshot).
func (*Serializer) ExportSummaryOnly ¶
func (s *Serializer) ExportSummaryOnly(snapshot Snapshot) ReasoningSummary
ExportSummaryOnly returns just the summary without full indexes.
Description:
Lightweight export for including in API responses. Computes metrics without serializing full indexes.
Inputs:
snapshot - Immutable CRS snapshot. If nil, returns empty summary.
Outputs:
ReasoningSummary - High-level metrics.
Thread Safety: Safe for concurrent use.
func (*Serializer) Import ¶
func (s *Serializer) Import(ctx context.Context, export *CRSExport, opts *ImportOptions) (*ImportedState, error)
Import reconstructs CRS state from an export.
Description:
Parses a CRSExport and constructs internal data structures that can be used to restore CRS state. Uses transactional semantics: all data is validated and built before constructing the result. For similarity pairs, both directions are reconstructed since only one direction is exported. For dependency edges, duplicates are deduplicated.
Inputs:
- ctx: Context for cancellation and tracing. Must not be nil.
- export: The CRS export to import. Must not be nil.
- opts: Import options. If nil, uses defaults (strict validation).
Outputs:
- *ImportedState: The imported state data. Never nil on success.
- error: Non-nil if validation fails or import errors occur.
Example:
state, err := serializer.Import(ctx, export, nil)
if err != nil {
return fmt.Errorf("import: %w", err)
}
// Use state to restore CRS...
Thread Safety: Safe for concurrent use.
type SessionIdentifier ¶
type SessionIdentifier struct {
// ProjectPath is the canonical absolute path to the project root.
ProjectPath string `json:"project_path"`
// ProjectHash is the SHA256 hash of lock files (go.mod, go.sum, etc.).
// Used to detect dependency changes between sessions.
ProjectHash string `json:"project_hash"`
// GitCommitHash is the git commit hash if available.
// Provides additional change detection beyond lock files.
GitCommitHash string `json:"git_commit_hash,omitempty"`
// ComputedAt is when this identifier was computed (Unix milliseconds UTC).
ComputedAt int64 `json:"computed_at"`
}
SessionIdentifier uniquely identifies a project/workspace for checkpoint lookup.
Description:
Combines the canonical project path with a content hash of lock files to detect when dependencies change. The checkpoint key is a hash of the project path for filesystem-safe storage.
Thread Safety: Immutable after creation; safe for concurrent use.
func NewSessionIdentifier ¶
func NewSessionIdentifier(ctx context.Context, projectPath string) (*SessionIdentifier, error)
NewSessionIdentifier creates a session identifier for a project.
Description:
Computes a stable project identifier from the project path and its dependency lock files. The identifier includes a hash of go.mod, go.sum, package.json, etc. to detect when the project changes.
Inputs:
- ctx: Context for cancellation and tracing. Must not be nil.
- projectPath: Path to the project root. Must not be empty.
Outputs:
- *SessionIdentifier: The computed identifier. Never nil on success.
- error: Non-nil if path resolution fails or context is nil.
Example:
sid, err := crs.NewSessionIdentifier(ctx, "/path/to/project")
if err != nil {
return fmt.Errorf("compute session ID: %w", err)
}
key := sid.CheckpointKey()
Thread Safety: Safe for concurrent use.
func (*SessionIdentifier) Age ¶
func (s *SessionIdentifier) Age() time.Duration
Age returns the age of this session identifier.
Thread Safety: Safe for concurrent use.
func (*SessionIdentifier) CheckpointKey ¶
func (s *SessionIdentifier) CheckpointKey() string
CheckpointKey returns a filesystem-safe key for checkpoint storage.
Description:
Computes a SHA256 hash of the project path and returns the first 16 bytes (128 bits) as a hex string. This provides a stable key for checkpoint storage that avoids filesystem issues with long paths.
Outputs:
- string: 32-character hex string (16 bytes = 128 bits).
Thread Safety: Safe for concurrent use.
type SessionRestoreFailedEvent ¶
type SessionRestoreFailedEvent struct {
// ProjectPath is the project that failed to restore.
ProjectPath string
// Reason explains why restore failed.
Reason string
// Error is the underlying error if any.
Error error
}
SessionRestoreFailedEvent is emitted when session restore fails.
type SessionRestoredEvent ¶
type SessionRestoredEvent struct {
// ProjectPath is the project that was restored.
ProjectPath string
// ProjectHash is the hash used to identify the project.
ProjectHash string
// Generation is the CRS generation after restore.
Generation int64
// CheckpointAge is how old the restored checkpoint was.
CheckpointAge time.Duration
// ModifiedFileCount is the number of files modified since checkpoint.
ModifiedFileCount int
// RestoreDuration is how long the restore took.
RestoreDuration time.Duration
}
SessionRestoredEvent is emitted when a session is successfully restored.
type SessionRestorer ¶
type SessionRestorer struct {
// contains filtered or unexported fields
}
SessionRestorer handles checkpoint loading at session start.
Description:
Integrates with GR-33's PersistenceManager to load checkpoints and restore CRS state. Validates checkpoint compatibility using project hash and age checks.
Thread Safety: Safe for concurrent use.
func NewSessionRestorer ¶
func NewSessionRestorer(pm *PersistenceManager, config *SessionRestorerConfig) (*SessionRestorer, error)
NewSessionRestorer creates a new session restorer.
Description:
Creates a restorer that uses the provided PersistenceManager for checkpoint storage. Reuses GR-33 infrastructure instead of creating a separate CheckpointStorage interface.
Inputs:
- pm: Persistence manager from GR-33. Must not be nil.
- config: Configuration. If nil, uses DefaultSessionRestorerConfig().
Outputs:
- *SessionRestorer: The new restorer. Never nil on success.
- error: Non-nil if pm is nil or config is invalid.
Thread Safety: Safe for concurrent use.
func (*SessionRestorer) TryRestore ¶
func (r *SessionRestorer) TryRestore( ctx context.Context, crsi CRS, journal Journal, sessionID *SessionIdentifier, ) (*RestoreResult, error)
TryRestore attempts to restore CRS state from a previous session.
Description:
Loads a checkpoint from disk and restores it into the CRS instance if it passes validation. Validation includes project hash matching and age checks. Returns a RestoreResult describing the outcome. This method uses GR-33's LoadBackup infrastructure rather than creating a parallel path.
Inputs:
- ctx: Context for cancellation and tracing. Must not be nil.
- crsi: The CRS instance to restore into. Must not be nil.
- journal: The Journal for replay. Must not be nil.
- sessionID: Session identifier for checkpoint lookup. Must not be nil.
Outputs:
- *RestoreResult: Describes what happened during restore. Never nil on success.
- error: Non-nil only for fatal errors (restore failures return in result).
Example:
result, err := restorer.TryRestore(ctx, crs, journal, sessionID)
if err != nil {
return fmt.Errorf("restore: %w", err)
}
if result.Restored {
log.Info("restored checkpoint", "generation", result.Generation)
}
Thread Safety: Safe for concurrent use.
type SessionRestorerConfig ¶
type SessionRestorerConfig struct {
// CheckpointMaxAge is how old a checkpoint can be before it's invalid.
// Default: 7 days.
CheckpointMaxAge time.Duration
// MaxFilesToRefresh is the maximum files to mark dirty after restore.
// If more files changed, skip restore and trigger full rebuild.
// Default: 1000.
MaxFilesToRefresh int
// UseGitStatus uses `git status` to find modified files instead of mtime scan.
// Much faster for git repositories.
// Default: true.
UseGitStatus bool
// MaxRetries is the number of retry attempts on transient failures.
// Default: 3.
MaxRetries int
// Logger for session restore operations.
// If nil, uses slog.Default().
Logger *slog.Logger
}
SessionRestorerConfig configures session restore behavior.
Description:
Provides configuration options for session restore including checkpoint age limits, file refresh thresholds, and git integration.
Thread Safety: Immutable after creation; safe for concurrent use.
func DefaultSessionRestorerConfig ¶
func DefaultSessionRestorerConfig() SessionRestorerConfig
DefaultSessionRestorerConfig returns production defaults.
func (*SessionRestorerConfig) Validate ¶
func (c *SessionRestorerConfig) Validate() error
Validate checks if the configuration is valid.
GR-36 Code Review Fix: S6 - Add config validation.
type SignalSource ¶
type SignalSource int
SignalSource indicates where a signal came from (hard vs soft).
const ( // SignalSourceUnknown means the source is not known. SignalSourceUnknown SignalSource = iota // SignalSourceHard means the signal came from a hard source (compiler, tests). SignalSourceHard // SignalSourceSoft means the signal came from a soft source (LLM). SignalSourceSoft // SignalSourceSafety means the signal came from the safety gate. // // Safety violations are treated as HARD signals for learning purposes. // When the safety gate blocks an action, CDCL should learn to avoid // the pattern that caused the violation. // // This addresses the "Safety Blocking Learning Signal" problem: // without this, safety-blocked actions would be soft errors that // MCTS/CDCL ignores, potentially retrying the same blocked pattern. SignalSourceSafety )
func (SignalSource) IsHard ¶
func (s SignalSource) IsHard() bool
IsHard returns true if this is a hard signal source.
Safety violations are treated as hard signals because: 1. They represent definitive failures (the action WILL be blocked) 2. CDCL should learn to avoid patterns that trigger safety blocks 3. Unlike soft signals, safety rules are deterministic
func (SignalSource) IsSafety ¶
func (s SignalSource) IsSafety() bool
IsSafety returns true if this signal came from the safety gate.
func (SignalSource) IsValid ¶
func (s SignalSource) IsValid() bool
IsValid returns true if the signal source is a known value (not Unknown).
Description:
Used for validation to ensure proof updates have explicit signal sources. SignalSourceUnknown is not considered valid as it indicates missing attribution.
func (SignalSource) String ¶
func (s SignalSource) String() string
String returns the string representation of SignalSource.
type SimilarityDelta ¶
type SimilarityDelta struct {
// Updates maps (node1, node2) to distance.
Updates map[[2]string]float64
// contains filtered or unexported fields
}
SimilarityDelta represents changes to similarity scores.
func NewSimilarityDelta ¶
func NewSimilarityDelta(source SignalSource) *SimilarityDelta
NewSimilarityDelta creates a new similarity delta.
func (*SimilarityDelta) ConflictsWith ¶
func (d *SimilarityDelta) ConflictsWith(other Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*SimilarityDelta) IndexesAffected ¶
func (d *SimilarityDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Thread Safety: Returns a shared slice. Callers must not modify.
func (*SimilarityDelta) Merge ¶
func (d *SimilarityDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*SimilarityDelta) Source ¶
func (d *SimilarityDelta) Source() SignalSource
func (*SimilarityDelta) Type ¶
func (d *SimilarityDelta) Type() DeltaType
Type returns the delta type.
func (*SimilarityDelta) Validate ¶
func (d *SimilarityDelta) Validate(_ Snapshot) error
Validate checks if this delta can be applied.
type SimilarityIndexExport ¶
type SimilarityIndexExport struct {
// PairCount is the number of similarity pairs stored.
PairCount int `json:"pair_count"`
// Pairs contains all similarity pairs for full export.
// Only one direction is exported (FromID < ToID) to avoid duplicates.
Pairs []SimilarityPairExport `json:"pairs,omitempty"`
// Truncated indicates if Pairs was truncated due to limits.
Truncated bool `json:"truncated,omitempty"`
}
SimilarityIndexExport is the serializable form of the Similarity Index.
type SimilarityIndexView ¶
type SimilarityIndexView interface {
// Distance returns the similarity distance between two nodes.
Distance(node1, node2 string) (float64, bool)
// NearestNeighbors returns the k nearest neighbors of a node.
NearestNeighbors(nodeID string, k int) []SimilarityMatch
// Size returns the number of entries.
Size() int
// AllPairs returns all similarity pairs for export.
//
// Description:
//
// Returns a deep copy of the similarity matrix for serialization.
// Format: map[fromID]map[toID]similarity.
//
// Outputs:
// - map[string]map[string]float64: Copy of all pairs. Never nil.
//
// Thread Safety: Returns deep copy; caller can modify without affecting source.
AllPairs() map[string]map[string]float64
// AllPairsFiltered returns similarity pairs in one direction only for efficient export.
//
// Description:
//
// Returns pairs where fromID < toID to avoid duplicates. This is more
// memory-efficient than AllPairs() for export since similarity is symmetric.
// Respects maxPairs limit and returns truncated flag.
//
// Inputs:
// - maxPairs: Maximum pairs to return. -1 for unlimited.
//
// Outputs:
// - []SimilarityPairData: Pairs in one direction. Never nil.
// - bool: True if truncated due to limit.
//
// Thread Safety: Safe for concurrent use.
AllPairsFiltered(maxPairs int) ([]SimilarityPairData, bool)
}
SimilarityIndexView provides read-only access to similarity scores.
Thread Safety: Safe for concurrent use (immutable).
type SimilarityMatch ¶
type SimilarityMatch struct {
// NodeID is the matching node.
NodeID string
// Distance is the similarity distance (lower = more similar).
Distance float64
}
SimilarityMatch represents a similarity search result.
type SimilarityPairData ¶
SimilarityPairData holds a similarity pair for export.
type SimilarityPairExport ¶
type SimilarityPairExport struct {
// FromID is the first node ID (lexicographically smaller).
FromID string `json:"from_id"`
// ToID is the second node ID (lexicographically larger).
ToID string `json:"to_id"`
// Similarity is the similarity score between the nodes (0.0 to 1.0).
Similarity float64 `json:"similarity"`
}
SimilarityPairExport represents a single similarity pair.
NOTE: Only one direction is exported (FromID < ToID) since similarity is symmetric. Import reconstructs both directions.
type Snapshot ¶
type Snapshot interface {
// Generation returns the generation when this snapshot was created.
Generation() int64
// CreatedAt returns when this snapshot was created (Unix milliseconds UTC).
CreatedAt() int64
// ProofIndex returns the proof numbers index view.
ProofIndex() ProofIndexView
// ConstraintIndex returns the constraint index view.
ConstraintIndex() ConstraintIndexView
// SimilarityIndex returns the similarity index view.
SimilarityIndex() SimilarityIndexView
// DependencyIndex returns the dependency index view.
DependencyIndex() DependencyIndexView
// HistoryIndex returns the history index view.
HistoryIndex() HistoryIndexView
// StreamingIndex returns the streaming statistics index view.
StreamingIndex() StreamingIndexView
// Query returns the cross-index query API.
//
// Description:
//
// Query provides methods that span multiple indexes, such as finding
// proven nodes that satisfy constraints or computing dependency chains.
//
// Outputs:
// - QueryAPI: The query API. Never nil.
Query() QueryAPI
// GraphQuery returns read-only access to the code graph (GR-28).
//
// Description:
//
// Returns the graph query interface for activities to query the actual
// code graph structure. This enables activities to use graph algorithms
// (PageRank, community detection, etc.) rather than relying solely on
// CRS's internal DependencyIndex.
//
// Outputs:
// - GraphQuery: The graph query interface, or nil if unavailable.
//
// Thread Safety: Safe for concurrent use (snapshot is immutable).
GraphQuery() GraphQuery
// AnalyticsHistory returns recent analytics records (GR-31).
//
// Description:
//
// Returns a copy of analytics records in chronological order.
// Activities can use this to check what analytics have been run.
//
// Outputs:
// - []*AnalyticsRecord: Copy of analytics records.
//
// Thread Safety: Safe for concurrent use (snapshot is immutable).
AnalyticsHistory() []*AnalyticsRecord
// LastAnalytics returns the most recent analytics of a given type (GR-31).
//
// Description:
//
// Searches analytics history for the most recent record of the
// specified query type.
//
// Inputs:
// - queryType: The type of analytics query to find.
//
// Outputs:
// - *AnalyticsRecord: The most recent matching record, or nil if not found.
//
// Thread Safety: Safe for concurrent use (snapshot is immutable).
LastAnalytics(queryType AnalyticsQueryType) *AnalyticsRecord
// HasRunAnalytics checks if a specific analytics type has been run (GR-31).
//
// Description:
//
// Returns true if an analytics query of the given type has been
// recorded in history.
//
// Inputs:
// - queryType: The type of analytics query to check.
//
// Outputs:
// - bool: True if the query type has been run.
//
// Thread Safety: Safe for concurrent use (snapshot is immutable).
HasRunAnalytics(queryType AnalyticsQueryType) bool
}
Snapshot is an immutable view of CRS at a point in time.
Description:
Snapshots are created by CRS.Snapshot() and provide read-only access to all indexes. Snapshots are thread-safe and can be shared across goroutines.
Thread Safety: Safe for concurrent use (immutable).
type StepRecord ¶
type StepRecord struct {
// StepNumber is the 1-indexed step number.
StepNumber int `json:"step_number"`
// Timestamp is when this step started (Unix milliseconds UTC).
Timestamp int64 `json:"timestamp"`
// SessionID links this step to its session. Must not be empty.
SessionID string `json:"session_id"`
// Actor identifies who made this decision.
Actor Actor `json:"actor"`
// Model is the specific model used (e.g., "granite4:micro-h", "glm-4.7-flash").
Model string `json:"model,omitempty"`
// Decision is the type of decision made.
Decision Decision `json:"decision"`
// Tool is the tool name if applicable.
Tool string `json:"tool,omitempty"`
// ToolParams are the parameters passed to the tool (typed struct, not map[string]any).
ToolParams *ToolParams `json:"tool_params,omitempty"`
// Confidence is the router confidence if applicable (0.0-1.0).
Confidence float64 `json:"confidence,omitempty"`
// Reasoning explains why this decision was made.
Reasoning string `json:"reasoning,omitempty"`
// Outcome is the result of this step.
Outcome Outcome `json:"outcome"`
// ErrorMessage contains the error message if outcome is failure.
ErrorMessage string `json:"error_message,omitempty"`
// ErrorCategory categorizes the error for retry logic (typed enum, not string).
ErrorCategory ErrorCategory `json:"error_category,omitempty"`
// DurationMs is how long this step took in milliseconds.
// NOTE: Using int64 with explicit _ms suffix for JSON clarity.
// time.Duration encodes as nanoseconds in JSON which is confusing.
DurationMs int64 `json:"duration_ms"`
// ResultSummary is a brief summary of what was found/produced.
ResultSummary string `json:"result_summary,omitempty"`
// TokensUsed is the number of tokens consumed.
TokensUsed int `json:"tokens_used,omitempty"`
// Propagate indicates if this step's outcome should influence the next step.
Propagate bool `json:"propagate"`
// Terminal indicates if this is a final answer (no more steps needed).
Terminal bool `json:"terminal"`
// NextHint provides guidance for the next step.
NextHint string `json:"next_hint,omitempty"`
// ProofUpdates for MCTS proof number changes.
ProofUpdates []ProofUpdate `json:"proof_updates,omitempty"`
// ConstraintsAdded for MCTS constraint additions.
ConstraintsAdded []ConstraintUpdate `json:"constraints_added,omitempty"`
// DependenciesFound for MCTS dependency edges.
DependenciesFound []DependencyEdge `json:"dependencies_found,omitempty"`
}
StepRecord captures one step in the agent reasoning process.
Description:
This is the primary unit of CRS recording. Each step represents a discrete decision point with explicit attribution, outcome, and context for the next step. StepRecord replaces the old TraceStep with typed fields instead of untyped strings.
Thread Safety: StepRecord is immutable after creation.
func TraceStepToStepRecord ¶
func TraceStepToStepRecord(step TraceStep, sessionID string) StepRecord
TraceStepToStepRecord converts a lightweight TraceStep into a full StepRecord.
Description:
Bridge function connecting the execute phase's TraceStep recording with the CRS StepRecord system. Maps available TraceStep fields to StepRecord fields and provides sensible defaults for fields not present in TraceStep. This enables CRS.CountToolExecutions() to return accurate counts, which the circuit breaker uses as a fallback when no proof data exists.
Inputs:
- step: The TraceStep to convert. Should have non-empty Tool field for the conversion to be meaningful for execution counting.
- sessionID: The session ID to attach. Must not be empty.
Outputs:
- StepRecord: The converted record ready for CRS.RecordStep().
Limitations:
- TraceStep does not carry Actor or Decision context; defaults to ActorSystem / DecisionExecuteTool.
- ToolParams are not available in TraceStep; left nil in StepRecord.
- Confidence is not available; defaults to 0.
func (*StepRecord) IsCircuitBreakerIntervention ¶
func (s *StepRecord) IsCircuitBreakerIntervention() bool
IsCircuitBreakerIntervention returns true if this step was a circuit breaker action.
func (*StepRecord) IsTerminal ¶
func (s *StepRecord) IsTerminal() bool
IsTerminal returns true if this step marks the end of reasoning.
func (*StepRecord) IsToolExecution ¶
func (s *StepRecord) IsToolExecution() bool
IsToolExecution returns true if this step represents an actual tool execution. Used by CountToolExecutions to count real executions, not selections.
func (*StepRecord) Validate ¶
func (s *StepRecord) Validate() error
Validate checks that the StepRecord has required fields and valid values.
Description:
Call this before recording to catch errors early. Validation is strict: all required fields must be present and values must be in valid ranges.
Outputs:
error - Non-nil if validation fails with a description of the problem.
Thread Safety: Safe for concurrent use (read-only).
type StreamDelta ¶
type StreamDelta struct {
// Type is the delta type name (e.g., "proof", "constraint", "similarity").
Type string `json:"type"`
// SeqNum is the NATS JetStream message sequence number.
SeqNum uint64 `json:"seq"`
// Timestamp is when the delta was created (Unix milliseconds UTC).
Timestamp int64 `json:"timestamp"`
// Summary is a human-readable description of the delta.
Summary string `json:"summary"`
}
StreamDelta represents a delta event for SSE streaming.
Description:
Provides a JSON-serializable summary of a CRS delta for Server-Sent Events. Contains the delta type, sequence number, timestamp, and a human-readable summary suitable for real-time observability dashboards.
Thread Safety: Immutable after creation.
func DeltaToStreamDelta ¶
func DeltaToStreamDelta(delta Delta, seqNum uint64, timestampMs int64) StreamDelta
DeltaToStreamDelta converts a Delta to a StreamDelta for SSE.
Description:
Extracts the type and generates a human-readable summary from a Delta. Used by the SSE endpoint to stream live CRS decisions.
Inputs:
- delta: The CRS delta to summarize. Must not be nil.
- seqNum: The NATS message sequence number.
- timestampMs: The delta timestamp (Unix milliseconds UTC).
Outputs:
- StreamDelta: SSE-ready summary of the delta.
Thread Safety: Safe for concurrent use (read-only on delta).
type StreamingDelta ¶
type StreamingDelta struct {
// Increments maps item to frequency increment.
Increments map[string]uint64
// CardinalityItems are items to count for cardinality.
CardinalityItems []string
// contains filtered or unexported fields
}
StreamingDelta represents updates to streaming statistics.
func NewStreamingDelta ¶
func NewStreamingDelta(source SignalSource) *StreamingDelta
NewStreamingDelta creates a new streaming delta.
func (*StreamingDelta) ConflictsWith ¶
func (d *StreamingDelta) ConflictsWith(_ Delta) bool
ConflictsWith returns true if this delta conflicts with another.
func (*StreamingDelta) IndexesAffected ¶
func (d *StreamingDelta) IndexesAffected() []string
IndexesAffected returns which indexes this delta will modify.
Thread Safety: Returns a shared slice. Callers must not modify.
func (*StreamingDelta) Merge ¶
func (d *StreamingDelta) Merge(other Delta) (Delta, error)
Merge combines this delta with another delta.
func (*StreamingDelta) Source ¶
func (d *StreamingDelta) Source() SignalSource
func (*StreamingDelta) Type ¶
func (d *StreamingDelta) Type() DeltaType
Type returns the delta type.
func (*StreamingDelta) Validate ¶
func (d *StreamingDelta) Validate(_ Snapshot) error
Validate checks if this delta can be applied.
type StreamingIndexExport ¶
type StreamingIndexExport struct {
// Cardinality is the estimated unique item count.
Cardinality uint64 `json:"cardinality"`
// ApproximateBytes is the approximate memory usage.
ApproximateBytes int `json:"approximate_bytes"`
}
StreamingIndexExport is the serializable form of the Streaming Index.
type StreamingIndexView ¶
type StreamingIndexView interface {
// Estimate returns the frequency estimate for an item.
Estimate(item string) uint64
// Cardinality returns the estimated unique item count.
Cardinality() uint64
// Size returns the approximate memory usage in bytes.
Size() int
}
StreamingIndexView provides read-only access to streaming statistics.
Thread Safety: Safe for concurrent use (immutable).
type ToolParams ¶
type ToolParams struct {
// Target is the primary target (file path, symbol name, etc.).
Target string `json:"target,omitempty"`
// Query is the search query or pattern.
Query string `json:"query,omitempty"`
// Depth limits recursion or traversal depth.
Depth int `json:"depth,omitempty"`
// Limit caps the number of results.
Limit int `json:"limit,omitempty"`
// Flags are boolean options.
Flags []string `json:"flags,omitempty"`
// Extra holds additional string key-value pairs for tool-specific params.
// This is bounded and auditable unlike map[string]any.
Extra []KeyValue `json:"extra,omitempty"`
}
ToolParams captures tool invocation parameters with typed fields.
Description:
Per CLAUDE.md Section 4.5, we use typed structs instead of map[string]any. This ensures type safety at compile time and proper serialization.
Thread Safety: ToolParams is immutable after creation.
type TraceConfig ¶
type TraceConfig struct {
// MaxSteps limits trace size to prevent unbounded growth.
// When exceeded, oldest steps are evicted.
// Default: 1000.
MaxSteps int
// RecordSymbols enables recording of discovered symbols.
// Default: true.
RecordSymbols bool
// RecordMetadata enables recording of step metadata.
// Default: true.
RecordMetadata bool
// Sanitizer sanitizes trace data before recording.
// If nil, no sanitization is performed.
// SECURITY: Should be set to prevent secrets from leaking into traces.
Sanitizer Sanitizer
}
TraceConfig configures trace recording behavior.
func DefaultTraceConfig ¶
func DefaultTraceConfig() TraceConfig
DefaultTraceConfig returns sensible defaults.
func SecureTraceConfig ¶
func SecureTraceConfig() TraceConfig
SecureTraceConfig returns config with secret sanitization enabled.
Description:
Returns a TraceConfig with the default SecretSanitizer configured. Use this configuration to prevent secrets from leaking into audit trails.
Outputs:
TraceConfig - Configuration with sanitization enabled.
type TraceRecorder ¶
type TraceRecorder struct {
// contains filtered or unexported fields
}
TraceRecorder captures reasoning steps for audit and debugging.
Description:
Records each reasoning action and its effects on CRS state. Steps are stored in order and can be exported as a complete trace.
Thread Safety: Safe for concurrent use.
func NewTraceRecorder ¶
func NewTraceRecorder(config TraceConfig) *TraceRecorder
NewTraceRecorder creates a new trace recorder.
Inputs:
config - Configuration for the recorder. Uses defaults if zero-valued.
Outputs:
*TraceRecorder - The configured recorder.
func (*TraceRecorder) Clear ¶
func (r *TraceRecorder) Clear()
Clear removes all recorded steps.
Thread Safety: Safe for concurrent use.
func (*TraceRecorder) Export ¶
func (r *TraceRecorder) Export(sessionID string) ReasoningTrace
Export returns the trace in exportable format.
Description:
Creates a ReasoningTrace containing all recorded steps, suitable for JSON serialization.
Inputs:
sessionID - Session identifier for the export.
Outputs:
ReasoningTrace - The exportable trace.
Thread Safety: Safe for concurrent use.
func (*TraceRecorder) GetSteps ¶
func (r *TraceRecorder) GetSteps() []TraceStep
GetSteps returns a copy of all recorded steps.
Outputs:
[]TraceStep - Copy of recorded steps in order.
Thread Safety: Safe for concurrent use.
func (*TraceRecorder) LastStep ¶
func (r *TraceRecorder) LastStep() *TraceStep
LastStep returns the most recently recorded step, or nil if empty.
Thread Safety: Safe for concurrent use.
func (*TraceRecorder) RecordStep ¶
func (r *TraceRecorder) RecordStep(step TraceStep)
RecordStep adds a step to the trace.
Description:
Called after each reasoning action to capture what was done, what was found, and how CRS was updated. Automatically assigns step numbers and timestamps. SECURITY: If a Sanitizer is configured, all string fields are sanitized before storage to prevent secrets from leaking into audit trails. This is critical because safety scanners may block actions that contain secrets, but the attempted action (including the secret) would otherwise be recorded in the trace.
Inputs:
step - The trace step to record. Step number and timestamp
will be overwritten by the recorder.
Thread Safety: Safe for concurrent use.
func (*TraceRecorder) StepCount ¶
func (r *TraceRecorder) StepCount() int
StepCount returns the number of recorded steps.
Thread Safety: Safe for concurrent use.
type TraceStep ¶
type TraceStep struct {
// Step is the 1-indexed step number (assigned by recorder).
Step int `json:"step"`
// Timestamp is when this step occurred (Unix milliseconds UTC).
Timestamp int64 `json:"timestamp"`
// Action describes what was done (e.g., "explore", "analyze", "trace_flow").
Action string `json:"action"`
// Target is the file or symbol being operated on.
Target string `json:"target"`
// Tool is the tool that triggered this action (optional).
Tool string `json:"tool,omitempty"`
// Duration is how long this step took.
Duration time.Duration `json:"duration_ms"`
// SymbolsFound lists symbols discovered in this step.
SymbolsFound []string `json:"symbols_found,omitempty"`
// ProofUpdates lists proof status changes.
ProofUpdates []ProofUpdate `json:"proof_updates,omitempty"`
// ConstraintsAdded lists new constraints added.
ConstraintsAdded []ConstraintUpdate `json:"constraints_added,omitempty"`
// DependenciesFound lists new dependency edges found.
DependenciesFound []DependencyEdge `json:"dependencies_found,omitempty"`
// Error contains any error that occurred.
Error string `json:"error,omitempty"`
// Metadata contains additional step context.
Metadata map[string]string `json:"metadata,omitempty"`
}
TraceStep represents one step in the reasoning process.
Description:
Captures what action was taken, what was found, and how CRS was updated. Steps are recorded in order and can be exported for audit/debugging.
type TraceStepBuilder ¶
type TraceStepBuilder struct {
// contains filtered or unexported fields
}
TraceStepBuilder helps construct TraceStep instances.
func NewTraceStepBuilder ¶
func NewTraceStepBuilder() *TraceStepBuilder
NewTraceStepBuilder creates a new builder.
func (*TraceStepBuilder) Build ¶
func (b *TraceStepBuilder) Build() TraceStep
Build returns the constructed TraceStep.
func (*TraceStepBuilder) WithAction ¶
func (b *TraceStepBuilder) WithAction(action string) *TraceStepBuilder
WithAction sets the action.
func (*TraceStepBuilder) WithConstraint ¶
func (b *TraceStepBuilder) WithConstraint(id, constraintType string, nodes []string) *TraceStepBuilder
WithConstraint adds a constraint update.
func (*TraceStepBuilder) WithDependency ¶
func (b *TraceStepBuilder) WithDependency(from, to string) *TraceStepBuilder
WithDependency adds a dependency edge.
func (*TraceStepBuilder) WithDuration ¶
func (b *TraceStepBuilder) WithDuration(d time.Duration) *TraceStepBuilder
WithDuration sets the duration.
func (*TraceStepBuilder) WithError ¶
func (b *TraceStepBuilder) WithError(err string) *TraceStepBuilder
WithError sets the error.
func (*TraceStepBuilder) WithMetadata ¶
func (b *TraceStepBuilder) WithMetadata(key, value string) *TraceStepBuilder
WithMetadata adds a metadata key-value pair.
func (*TraceStepBuilder) WithProofUpdate ¶
func (b *TraceStepBuilder) WithProofUpdate(nodeID, status, reason, source string) *TraceStepBuilder
WithProofUpdate adds a proof update.
Parameters accept string values for backwards compatibility:
- status: "proven", "disproven", "expanded", "unknown", "increment", "decrement"
- source: "hard", "soft", "safety"
func (*TraceStepBuilder) WithProofUpdateTyped ¶
func (b *TraceStepBuilder) WithProofUpdateTyped(nodeID string, updateType ProofUpdateType, delta uint64, reason string, source SignalSource) *TraceStepBuilder
WithProofUpdateTyped adds a proof update with typed parameters. Prefer this over WithProofUpdate for new code.
func (*TraceStepBuilder) WithSymbolsFound ¶
func (b *TraceStepBuilder) WithSymbolsFound(symbols []string) *TraceStepBuilder
WithSymbolsFound sets the symbols found.
func (*TraceStepBuilder) WithTarget ¶
func (b *TraceStepBuilder) WithTarget(target string) *TraceStepBuilder
WithTarget sets the target.
func (*TraceStepBuilder) WithTool ¶
func (b *TraceStepBuilder) WithTool(tool string) *TraceStepBuilder
WithTool sets the tool.