waggle

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package waggle is bee's self-improving procedure memory.

The forage recorder watches the agent's read-only tool stream; the miner detects repeated routes through it; the promoter crystallizes a route into a runnable exec-skill (a waggle) that later sessions follow instead of re-deriving. The name comes from the waggle dance: how a bee encodes a proven foraging route for the hive to repeat.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CompactLedger

func CompactLedger(path string, keep map[string]bool) error

CompactLedger rewrites a ledger, keeping only entries whose Name is in keep. Run it after deleting waggle files so a later re-mine of the same (content- stable) name starts with clean stats instead of inheriting a dead route's history — otherwise stale Fails would auto-demote the fresh route. A missing ledger is a no-op.

func Demote

func Demote(s *Store, stats map[string]Stat, minFails int) (int, error)

Demote disables waggles whose predictive replay repeatedly diverged without ever paying off: at least minFails recorded divergences (per the ledger) and zero successful uses. A demoted waggle keeps its file (for inspection) but is marked disabled, so LoadRoutes skips it and replay stops firing a route the tree has outgrown. Idempotent: already-disabled waggles are not re-counted. Returns the number newly demoted.

func GC

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

GC prunes a store: it removes files that fail to parse, have no script, or duplicate a script already kept. Returns the number removed. Safe to run any time — it only touches files under the waggle store, which bee owns.

func Promote

func Promote(user *Store) (int, error)

Promote copies any route present in >= 2 distinct project stores into the user store, so a route the agent rediscovers across projects becomes portable. The copy is re-tagged scope: user. Routes already in the user store are skipped. Returns the number promoted.

func PruneStale

func PruneStale(s *Store, stats map[string]Stat, maxAge time.Duration, now time.Time) (int, error)

PruneStale removes waggles a store never paid off: zero recorded uses (per the ledger stats) and a file older than maxAge. Returns the number removed. now is injected so tests are deterministic. Waggles with any use are always kept.

func ReadLedger

func ReadLedger(path string) (map[string]Stat, error)

ReadLedger aggregates a JSONL ledger by waggle name. A missing file is not an error (returns an empty map); malformed lines are skipped.

func Render

func Render(name string, c Candidate, scope Scope) (string, bool)

Render builds the waggle exec-skill markdown for a candidate. It returns ok=false when any step has no deterministic shell translation, so an un-crystallizable route is never written. Timestamps are left to the ledger.

Types

type Call

type Call struct {
	Tool      string
	Args      map[string]string
	Mutates   bool
	OutHash   string
	EstTokens int
}

Call is one recorded tool invocation in the forage log. Args holds the tool's input flattened to strings (sorted-key iteration gives a deterministic shape). Mutates marks a state-changing tool so the miner can exclude it. OutHash and EstTokens feed dedup and yield estimation.

type Candidate

type Candidate struct {
	Steps  []Call
	Count  int
	Params []Param
}

Candidate is a detected reusable route. Steps holds the representative (first) occurrence; Params lists the varying argument positions; Count is the number of non-overlapping times the route's shape recurred.

func Mine

func Mine(calls []Call, cfg MineConfig) []Candidate

Mine scans calls for repeated contiguous read-only routes, returning candidates ranked by score (length * count) descending. Windows containing a mutator are never considered. Callers typically act on the top candidate.

type CurateResult

type CurateResult struct {
	RemovedProj int
	RemovedUser int
	PrunedProj  int
	PrunedUser  int
	Demoted     int
	Promoted    int
}

CurateResult reports what a Curate pass changed, for the gc summary line.

func Curate

func Curate(proj, user *Store, staleAge time.Duration, minFails int, now time.Time) (CurateResult, error)

Curate runs the full library maintenance pass over both scopes, in the order that keeps each step's guarantee intact:

  1. GC — drop duplicate/broken files.
  2. Demote — disable chronic divergers (rewriting the file refreshes its mtime) so the prune below keeps them this run.
  3. Prune — delete never-paid-off stale files; a just-demoted file survives via its fresh mtime and only ages out on a later pass.
  4. Compact — drop ledger history for files now gone, so a re-mined identical route starts clean instead of inheriting a dead route's stats.
  5. Promote — copy routes recurring across projects (skipping disabled) into the user store.

now is injected for deterministic tests.

type Ledger

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

Ledger is an append-only reuse log for one scope, persisted as JSONL beside that scope's skills dir. Appends are serialized so concurrent replays in one session can't interleave a line.

func NewLedger

func NewLedger(path string) *Ledger

NewLedger returns a ledger writing to path. A nil ledger is a no-op sink.

func (*Ledger) Append

func (l *Ledger) Append(e LedgerEntry) error

Append records one reuse event, creating the file and parent dir on demand.

type LedgerEntry

type LedgerEntry struct {
	Name  string `json:"name"`
	Steps int    `json:"steps"`
	Yield int    `json:"yield"`
	// Fail marks a divergence: the route matched a prefix but its tail exec
	// failed or returned nothing. Recorded with zero yield; curation demotes a
	// waggle that keeps diverging without ever paying off.
	Fail bool `json:"fail,omitempty"`
}

LedgerEntry is one recorded reuse of a waggle. Yield is the estimated tokens saved by collapsing the route's remaining round-trips (chars/4), not a measured counterfactual — useful for ranking and curation, not accounting.

type Manager

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

Manager ties the recorder, miner and promoter to a store. The loop feeds it every read-only tool call via Observe; it periodically mines the forage log and writes one new crystallizable waggle per sweep. All work is read-only and best-effort: a failure never disrupts the turn.

func NewManager

func NewManager(store *Store, cfg ManagerConfig) *Manager

NewManager returns a manager writing to store. A nil store yields a no-op manager so callers need not branch.

func (*Manager) Observe

func (m *Manager) Observe(c Call)

Observe records a call and triggers a sweep every period observations.

type ManagerConfig

type ManagerConfig struct {
	Mine       MineConfig
	Scope      Scope
	MinePeriod int
}

ManagerConfig tunes the live crystallization loop. Mine bounds detection; Scope tags written waggles; MinePeriod is how many observations between sweeps (default 8) so mining never runs on the hot path of every single tool call.

type Meta

type Meta struct {
	Name        string
	Description string
	Script      string
	Path        string
}

Meta is a stored waggle's display info for `bee waggle ls`.

func List

func List(s *Store) ([]Meta, error)

List returns the waggles in a store, sorted by name. A missing store dir is not an error (returns nil); unparseable files are skipped.

type MineConfig

type MineConfig struct {
	MinLen int
	MaxLen int
	K      int
}

MineConfig bounds the search. MinLen/MaxLen cap route length; K is the minimum number of non-overlapping occurrences before a route is worth crystallizing.

type Param

type Param struct {
	Step int
	Key  string
}

Param marks an argument position whose value varies across occurrences, so it becomes a parameter of the crystallized route rather than a literal.

type Recorder

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

Recorder is a bounded per-session ring buffer of recent tool calls.

func NewRecorder

func NewRecorder(capacity int) *Recorder

NewRecorder returns a recorder holding at most capacity recent calls. A non-positive capacity defaults to 200.

func (*Recorder) Calls

func (r *Recorder) Calls() []Call

Calls returns a copy of the buffered calls, oldest first.

func (*Recorder) Record

func (r *Recorder) Record(c Call)

Record appends a call, dropping the oldest once over capacity.

type Replayer

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

Replayer follows known routes. It watches the live read-only call stream and, when the most recent calls match the start of a stored route whose remaining steps are fully determined (no unbound params), runs those remaining steps deterministically off the model's path and returns their combined output to fold into the triggering tool result. Everything is read-only, so a wrong match wastes a little read work and never causes damage.

func NewReplayer

func NewReplayer(routes []Route, minPrefix int) *Replayer

NewReplayer builds a replayer over routes. minPrefix is the smallest number of matched leading steps before a route fires (clamped to >= 2) — the conservatism knob that stops one ubiquitous call from hijacking exploration.

func (*Replayer) Follow

func (r *Replayer) Follow(ctx context.Context, exec func(context.Context, string) (string, error)) (string, bool)

Follow checks the current window for a fireable route and, if found, runs its remaining steps via exec (which must apply the host's safety + truncation). It returns the formatted block to append to the triggering tool result and true, or "" and false when nothing fires. Best-effort: an exec error or empty output yields no block. A given concrete plan fires at most once per session.

func (*Replayer) Observe

func (r *Replayer) Observe(c Call)

Observe appends a completed read-only call to the live window.

func (*Replayer) Routes

func (r *Replayer) Routes() int

Routes returns how many routes the replayer holds (0 for a nil/empty one).

func (*Replayer) SetLedger

func (r *Replayer) SetLedger(scope Scope, l *Ledger)

SetLedger registers the reuse log for a scope. Routes of that scope record an entry each time they fire. A nil ledger (or unset scope) just skips logging.

func (*Replayer) Yield

func (r *Replayer) Yield() int

Yield returns the cumulative estimated tokens saved by replays this session.

type Route

type Route struct {
	Name   string
	Steps  []Call
	Params []Param
	// Scope attributes a fired route to its store's ledger. Defaults to project.
	Scope Scope
}

Route is a stored waggle rehydrated for predictive replay: the ordered steps (literal args carry values; param args are wildcards) plus which positions are params. Steps mirror the miner's Candidate so translation is shared.

func LoadRoutes

func LoadRoutes(s *Store) ([]Route, error)

LoadRoutes reads every replayable waggle in a store. A missing dir is not an error (returns nil). Files without a structured route block are skipped (they still work as exec-skills, just aren't replayed).

type Scope

type Scope string

Scope decides where a waggle lives and how widely it applies.

const (
	ScopeProject Scope = "project" // routes that carry project paths (default)
	ScopeUser    Scope = "user"    // portable routes available across projects
)

type Stat

type Stat struct {
	Uses  int
	Yield int
	Fails int // recorded divergences (replay matched but its tail exec failed)
}

Stat is a waggle's aggregated reuse: how many times it was followed and the total estimated tokens saved.

type Store

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

Store is a directory of waggle skill files for one scope. Project stores are keyed by a hash of the project root (the same scheme as the checkpoint store) so path-bearing routes never leak between projects; the user store is shared.

func ProjectStore

func ProjectStore(projectRoot string) (*Store, error)

ProjectStore returns the per-project waggle store, rooted at <beeHome>/waggle/proj/<hash>/skills.

func UserStore

func UserStore() (*Store, error)

UserStore returns the cross-project waggle store at <beeHome>/waggle/user/skills.

func (*Store) Dir

func (s *Store) Dir() string

Dir is the absolute skills directory for this store.

func (*Store) Exists

func (s *Store) Exists(name string) bool

Exists reports whether a waggle named name is already stored.

func (*Store) IsDisabled

func (s *Store) IsDisabled(name string) bool

IsDisabled reports whether the named waggle was demoted by curation. The on-demand lookup path uses this to refuse a retired route.

func (*Store) LedgerPath

func (s *Store) LedgerPath() string

LedgerPath is the reuse-log path for this store, a sibling of the skills dir.

func (*Store) Write

func (s *Store) Write(name, md string) error

Write persists the waggle markdown as <name>.md, creating the dir on demand.

Jump to

Keyboard shortcuts

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