learning

package
v0.11.0-beta.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: Apache-2.0, MIT Imports: 26 Imported by: 0

Documentation

Overview

Package learning implements a lightweight learning-from-corrections system.

When the user corrects the assistant ("no, that's wrong", "actually, ..."), the correction is detected and stored in a PostgreSQL-backed store. Future agent runs query the store and inject relevant past corrections into the system prompt to improve responses.

Package learning's evolution.go implements PicoClaw's self-improvement pipeline: hot-path recording → cold-path pattern clustering → draft generation → review (with secret scanning) → apply (with rollback).

Stolen from PicoClaw's pkg/evolution/. Wires into Overkill's existing hooks system (§6.3) and self-learning loop (§6.2).

Index

Constants

View Source
const DefaultMaxCorrections = 1000

DefaultMaxCorrections is the maximum number of corrections to store before evicting the oldest (LRU).

View Source
const MaxAppliedGuidanceBytes = 32 * 1024
View Source
const MaxAppliedGuidanceItems = 8
View Source
const MaxDraftBytes = 64 * 1024
View Source
const MaxLearningFileBytes = 4 * 1024 * 1024
View Source
const MaxLearningRecordBytes = 16 * 1024
View Source
const MaxLearningRecords = 512
View Source
const MaxStoredDrafts = 256

Variables

This section is empty.

Functions

func ExtractCorrect

func ExtractCorrect(msg string) string

ExtractCorrect extracts the substantive part of a correction message (strips the correction prefix/signal words). Returns the corrected instruction text.

func FormatPrompt

func FormatPrompt(corrections []*Correction) string

FormatPrompt formats corrections into a prompt snippet for injection.

func IsCorrection

func IsCorrection(msg string) bool

IsCorrection returns true if the user message looks like a correction.

func WorkspaceScope

func WorkspaceScope(workspace string) string

Types

type AppliedGuidance

type AppliedGuidance struct {
	ID          string `json:"id"`
	Name        string `json:"name"`
	Body        string `json:"body"`
	AppliedHash string `json:"appliedHash"`
}

AppliedGuidance is verified, explicitly installed project guidance. Drafts in any other state, stale content, or mismatched workspaces never become context.

type AttemptSnapshot

type AttemptSnapshot struct {
	Attempt int      `json:"attempt"`
	Skills  []string `json:"skills"` // active skills at this point
	Path    []string `json:"path"`   // tool names tried so far
	Error   string   `json:"error,omitempty"`
}

AttemptSnapshot captures state at each retry attempt.

type ChangeKind

type ChangeKind string
const (
	ChangeCreate  ChangeKind = "create"
	ChangeAppend  ChangeKind = "append"
	ChangeReplace ChangeKind = "replace"
	ChangeMerge   ChangeKind = "merge"
)

type ColdPathResult

type ColdPathResult struct {
	RunAt             time.Time    `json:"runAt"`
	RecordsLoaded     int          `json:"recordsLoaded"`
	JudgedTurns       int          `json:"judgedTurns"`
	SuccessfulTurns   int          `json:"successfulTurns"`
	UnverifiedTurns   int          `json:"unverifiedTurns"`
	JudgeErrors       int          `json:"judgeErrors"`
	ClustersFound     int          `json:"clustersFound"`
	ClusterReasons    []string     `json:"clusterReasons"`
	CandidateDrafts   int          `json:"candidateDrafts"`
	QuarantinedDrafts int          `json:"quarantinedDrafts"`
	AppliedDrafts     int          `json:"appliedDrafts"`
	GenerationErrors  int          `json:"generationErrors"`
	ApplyErrors       int          `json:"applyErrors"`
	Drafts            []SkillDraft `json:"drafts"`
}

type Correction

type Correction struct {
	Context   string `json:"context"`   // the user message that triggered the wrong response
	Wrong     string `json:"wrong"`     // the assistant's incorrect response
	Correct   string `json:"correct"`   // the user's correction message
	Timestamp int64  `json:"timestamp"` // Unix nano timestamp
}

Correction represents a stored correction pair: what the assistant said that was wrong, and what the user corrected it to.

func NewCorrection

func NewCorrection(context, wrong, correct string) *Correction

NewCorrection creates a Correction with the current timestamp.

func UnmarshalCorrection

func UnmarshalCorrection(data []byte) (*Correction, error)

UnmarshalCorrection deserialises a correction from JSON bytes.

func (*Correction) Key

func (c *Correction) Key() string

Key returns the hash key for this correction (sha256 of context + wrong).

func (*Correction) Marshal

func (c *Correction) Marshal() ([]byte, error)

Marshal serialises the correction to JSON bytes.

func (*Correction) MatchScore

func (c *Correction) MatchScore(queryTokens []string) float64

MatchScore returns the relevance score between a query and a correction. It scores against both the context and the wrong response.

type DraftEvidence

type DraftEvidence struct {
	SimilarRecords  []LearningRecord `json:"similarRecords"`
	PastCorrections []Correction     `json:"pastCorrections"`
	WorkspaceFiles  []string         `json:"workspaceFiles"`
}

DraftEvidence carries supporting context for draft generation.

type DraftGenerator

type DraftGenerator interface {
	GenerateDraft(ctx context.Context, rule LearningRecord, matches []SkillProfile) (SkillDraft, error)
}

DraftGenerator produces SkillDraft proposals from clustered patterns. The Evidence-aware variant receives supporting evidence (similar tasks, past corrections) for richer draft generation.

type DraftStatus

type DraftStatus string
const (
	DraftCandidate   DraftStatus = "candidate"
	DraftQuarantined DraftStatus = "quarantined"
	DraftAccepted    DraftStatus = "accepted"
	DraftRejected    DraftStatus = "rejected"
	DraftApplying    DraftStatus = "applying"
	DraftRollingBack DraftStatus = "rolling_back"
	DraftApplied     DraftStatus = "applied"
	DraftRolledBack  DraftStatus = "rolled_back"
)

type DraftType

type DraftType string
const (
	DraftWorkflow DraftType = "workflow"
	DraftShortcut DraftType = "shortcut"
)

type Engine

type Engine struct {
	// contains filtered or unexported fields
}

Engine orchestrates the hot-path recording and cold-path batch processing for self-improvement.

func NewEngine

func NewEngine(recordDir, skillDir string, clusterer PatternClusterer, generator DraftGenerator, judge SuccessJudge) *Engine

NewEngine creates an evolution engine.

func NewEngineWithOptions

func NewEngineWithOptions(recordDir, skillDir string, clusterer PatternClusterer, generator DraftGenerator, judge SuccessJudge, options EngineOptions) *Engine

func (*Engine) ApplyReviewedDraft

func (e *Engine) ApplyReviewedDraft(ctx context.Context, id string) (SkillDraft, error)

ApplyReviewedDraft durably records intent before mutation. Repeating it after a crash finalizes the same content, rather than appending a second time.

func (*Engine) ListDrafts

func (e *Engine) ListDrafts(ctx context.Context) ([]SkillDraft, error)

ListDrafts returns bounded, persisted proposals for this explicit workspace.

func (*Engine) LoadAppliedGuidance

func (e *Engine) LoadAppliedGuidance(ctx context.Context) ([]AppliedGuidance, error)

func (*Engine) RecordTurn

func (e *Engine) RecordTurn(ctx context.Context, record LearningRecord) error

RecordTurn is called synchronously at the end of every agent turn (hot path). Appends a LearningRecord to JSONL.

func (*Engine) ReviewDraft

func (e *Engine) ReviewDraft(ctx context.Context, id string, approve bool) (SkillDraft, error)

ReviewDraft is a trusted operator API, intentionally absent from model tools.

func (*Engine) RollbackDraft

func (e *Engine) RollbackDraft(ctx context.Context, id string) (SkillDraft, error)

RollbackDraft refuses to overwrite edits made after the generated skill was installed. Repeating an interrupted rollback finalizes the recorded base.

func (*Engine) RunColdPath

func (e *Engine) RunColdPath(ctx context.Context, workspace string, applyMode bool) (*ColdPathResult, error)

RunColdPath is the batch job. It:

  1. Loads all task records
  2. Runs pattern clustering
  3. Generates draft skills for each cluster
  4. Reviews drafts (secret scanning)
  5. Applies accepted drafts (with rollback capability)

type EngineOptions

type EngineOptions struct {
	// KnownSecrets are resolved configured credentials. They are never serialized.
	KnownSecrets []string
	Workspace    string
	MaxRecords   int
	Retention    time.Duration
}

type EvidenceAwareDraftGenerator

type EvidenceAwareDraftGenerator interface {
	DraftGenerator
	GenerateDraftWithEvidence(ctx context.Context, rule LearningRecord,
		matches []SkillProfile, evidence DraftEvidence) (SkillDraft, error)
}

EvidenceAwareDraftGenerator receives evidence context.

type HeuristicClusterer

type HeuristicClusterer struct{}

HeuristicClusterer groups records by task hash similarity.

func (*HeuristicClusterer) BuildPatterns

func (h *HeuristicClusterer) BuildPatterns(ctx context.Context, workspace string, tasks []LearningRecord, existing []LearningRecord) ([]LearningRecord, []string, error)

type HeuristicJudge

type HeuristicJudge struct{}

HeuristicJudge classifies success by checking for error markers.

func (*HeuristicJudge) JudgeTaskRecord

func (h *HeuristicJudge) JudgeTaskRecord(ctx context.Context, record LearningRecord) (TaskSuccessDecision, error)

type LearningRecord

type LearningRecord struct {
	WorkspaceHash   string            `json:"workspaceHash"`
	TaskHash        string            `json:"taskHash"` // SHA256 of user input
	ToolExecutions  []ToolExecution   `json:"toolExecutions"`
	AttemptTrail    []AttemptSnapshot `json:"attemptTrail"` // what was tried
	FinalOutput     string            `json:"finalOutput"`
	WinningPath     []string          `json:"winningPath"`     // tool names that succeeded
	LateAddedSkills []string          `json:"lateAddedSkills"` // skills added mid-task
	MaturityScore   float64           `json:"maturityScore"`
	SuccessRate     float64           `json:"successRate"`
	ClusterReason   string            `json:"clusterReason,omitempty"`
	EventCount      int               `json:"eventCount"`
	SessionID       string            `json:"sessionId"`
	ModelID         string            `json:"modelId"`
	RecordedAt      time.Time         `json:"recordedAt"`
}

LearningRecord captures one agent turn for later pattern clustering. Written synchronously after every turn into JSONL.

type PatternClusterer

type PatternClusterer interface {
	BuildPatterns(ctx context.Context, workspace string,
		tasks []LearningRecord, existing []LearningRecord) ([]LearningRecord, []string, error)
}

PatternClusterer groups learning records into clusters that share common failure patterns or successful strategies.

type ProviderDraftGenerator

type ProviderDraftGenerator struct {
	// contains filtered or unexported fields
}

func NewProviderDraftGenerator

func NewProviderDraftGenerator(options ProviderDraftOptions) (*ProviderDraftGenerator, error)

func (*ProviderDraftGenerator) GenerateDraft

func (g *ProviderDraftGenerator) GenerateDraft(ctx context.Context, record LearningRecord, _ []SkillProfile) (SkillDraft, error)

type ProviderDraftOptions

type ProviderDraftOptions struct {
	Provider    providers.Provider
	Model       string
	MaxTokens   int
	Timeout     time.Duration
	BudgetGate  func(context.Context) error
	RecordUsage func(context.Context, providers.Usage) error
}

ProviderDraftOptions requires explicit budget admission and usage recording. Limits bound one request; Engine.RunColdPath permits at most eight requests. BudgetGate is checked before every call. It is not an invoice reservation.

type SkillDraft

type SkillDraft struct {
	BaseHash        string      `json:"baseHash,omitempty"`
	OriginalExists  bool        `json:"originalExists"`
	ID              string      `json:"id"`
	WorkspaceHash   string      `json:"workspaceHash"`
	ReviewedAt      time.Time   `json:"reviewedAt,omitempty"`
	AppliedAt       time.Time   `json:"appliedAt,omitempty"`
	BackupID        string      `json:"backupId,omitempty"`
	AppliedHash     string      `json:"appliedHash,omitempty"`
	TargetSkillName string      `json:"targetSkillName"`
	DraftType       DraftType   `json:"draftType"`
	ChangeKind      ChangeKind  `json:"changeKind"`
	BodyOrPatch     string      `json:"bodyOrPatch"`
	Status          DraftStatus `json:"status"`
	ReviewNotes     string      `json:"reviewNotes,omitempty"`
	ScanFindings    []string    `json:"scanFindings,omitempty"`
	GeneratedAt     time.Time   `json:"generatedAt"`
}

SkillDraft is an AI-proposed skill change.

type SkillLifecycle

type SkillLifecycle string
const (
	SkillActive   SkillLifecycle = "active"
	SkillCold     SkillLifecycle = "cold"     // 90d idle + retention < 0.3
	SkillArchived SkillLifecycle = "archived" // 180d + < 0.2
	SkillDeleted  SkillLifecycle = "deleted"  // 365d + < 0.1
)

type SkillProfile

type SkillProfile struct {
	Name           string         `json:"name"`
	RetentionScore float64        `json:"retentionScore"`
	UseCount       int            `json:"useCount"`
	LastUsedAt     time.Time      `json:"lastUsedAt"`
	CreatedAt      time.Time      `json:"createdAt"`
	Status         SkillLifecycle `json:"status"`
	VersionHistory []SkillVersion `json:"versionHistory"`
}

SkillProfile tracks a skill's usage and retention across sessions.

type SkillVersion

type SkillVersion struct {
	Version    int       `json:"version"`
	Hash       string    `json:"hash"`
	UpdatedAt  time.Time `json:"updatedAt"`
	RollbackTo int       `json:"rollbackTo,omitempty"` // version to restore
}

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store persists corrections using PostgreSQL and provides retrieval via case-insensitive keyword search.

func NewStore

func NewStore(db *sql.DB, maxItems int) (*Store, error)

NewStore wraps a *sql.DB for PostgreSQL-backed correction storage. The caller owns the DB lifecycle — the store does not close it.

func (*Store) Close

func (s *Store) Close() error

Close is a no-op — the caller owns the *sql.DB lifecycle.

func (*Store) Count

func (s *Store) Count() (int, error)

Count returns the current number of stored corrections.

func (*Store) FindCorrections

func (s *Store) FindCorrections(query string, topK int) ([]*Correction, error)

FindCorrections returns up to topK corrections matching the query. Matches are found via ILIKE on the context and wrong columns against each token in the query, ordered by timestamp DESC (most recent first). Query tokens are escaped to prevent % and _ being treated as wildcards.

func (*Store) Save

func (s *Store) Save(c *Correction) error

Save stores a correction. If a correction with the same (context, wrong) already exists, it is overwritten (UPSERT via ON CONFLICT). Enforces maxItems by evicting the oldest corrections when full.

type SuccessJudge

type SuccessJudge interface {
	JudgeTaskRecord(ctx context.Context, record LearningRecord) (TaskSuccessDecision, error)
}

SuccessJudge evaluates whether a task record represents a success.

type TaskSuccessDecision

type TaskSuccessDecision struct {
	Success    bool    `json:"success"`
	Verified   bool    `json:"verified"`
	Confidence float64 `json:"confidence"`
	Reason     string  `json:"reason"`
}

type ToolExecution

type ToolExecution struct {
	ToolName string `json:"toolName"`
	Args     string `json:"args"`
	Result   string `json:"result"`
	Duration int64  `json:"durationMs"`
	Error    string `json:"error,omitempty"`
}

ToolExecution records one tool call + result.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL