filter

package
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Overview

Package filter evaluates the agent-authored Starlark filter on every event. See ADR-0018.

The interface is defined here; the Starlark implementation lives behind it so we can stub it for tests and so a future filter language could replace the implementation without touching callers.

Index

Constants

View Source
const MaxPerRunEntries = 50

MaxPerRunEntries is the soft cap before everflow surfaces a warning that the per-Run list has grown beyond what's likely useful. Hard-coded for v1 (ADR-0018 §4.2).

Variables

This section is empty.

Functions

func DefaultStarlark

func DefaultStarlark() []byte

DefaultStarlark is the canonical filter content shipped with the daemon. setup() writes this to the per-Run filter file if no custom one exists, so the spike works out of the box without the user writing Starlark.

Types

type Filter

type Filter interface {
	Eval(event provider.Event, state any, phrases PhraseSet) (Outcome, error)
}

Filter evaluates a per-event decision. v1 implementations:

  • StarlarkFilter: load a .star file, evaluate filter(event, state, phrases)
  • StubFilter: hardcoded for tests and for the scaffold commit

state is the workflow's AgentState passed as `any` to avoid an import cycle (refactorsweep imports filter; filter would otherwise import refactorsweep). The Starlark adapter will marshal it into a dict; the StubFilter ignores it.

type Outcome

type Outcome int

Outcome is what the filter tells the workflow to do with the event.

const (
	OutcomeUnknown        Outcome = 0
	OutcomeSkip           Outcome = 1 // ignore the event; no LLM call, no state change
	OutcomeInvokeSubagent Outcome = 2 // run a subagent against this event
	OutcomeControlCommand Outcome = 3 // /everflow ... — route to control handler
	OutcomePause          Outcome = 4 // mark the Run paused for author intervention
)

func (Outcome) String

func (o Outcome) String() string

type PhraseEntry

type PhraseEntry struct {
	Text    string    `yaml:"text"`
	AddedBy string    `yaml:"added_by,omitempty"` // "subagent" | "human"
	AddedAt time.Time `yaml:"added_at,omitempty"`
	AfterMR int       `yaml:"after_mr,omitempty"` // MR IID this was learned from
}

type PhraseFile

type PhraseFile struct {
	Version int           `yaml:"version"`
	Phrases []PhraseEntry `yaml:"phrases"`
}

PhraseFile is the YAML shape on disk. Schema version is on file to allow future migrations without breaking older daemons.

type PhraseSet

type PhraseSet interface {
	Contains(text string) bool
	All() []string
}

PhraseSet is the per-Run skip-phrase store. Read-only from the filter's perspective; writes happen in the runner's response-handling code.

type StarlarkFilter

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

StarlarkFilter loads a .star file from disk and evaluates its filter() function on each event. Implements the Filter interface.

The filter is re-loaded from disk on every Eval() call — cheap for the file sizes we expect (<10KB), keeps "edit the .star and see the change next event" a useful workflow.

func NewStarlarkFilter

func NewStarlarkFilter(path string) *StarlarkFilter

NewStarlarkFilter constructs a StarlarkFilter pointing at the given .star file. The file isn't loaded yet — Eval will load on first call.

func (*StarlarkFilter) Eval

func (f *StarlarkFilter) Eval(event provider.Event, state any, phrases PhraseSet) (Outcome, error)

type StubFilter

type StubFilter struct{}

StubFilter is the placeholder implementation for the scaffold commit. Returns InvokeSubagent on everything that doesn't match the control-command prefix, so the scaffold compiles + behaves predictably until the real Starlark eval lands.

func (StubFilter) Eval

func (StubFilter) Eval(event provider.Event, _ any, _ PhraseSet) (Outcome, error)

type YAMLPhraseSet

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

YAMLPhraseSet is a Filter PhraseSet backed by two YAML files:

  1. Per-Run phrases at ~/.syntropy/runs/<runID>/phrases.yaml — learned via the runner's Learnings.AddPhrases, capped at MaxPerRunEntries (50 — ADR-0018 §4.2).
  2. Global phrases at ~/.syntropy/phrases.global.yaml — human-curated only; never auto-written.

Contains() checks BOTH sources case-insensitively. Add() appends to the per-Run file only (global stays curated).

func LoadYAMLPhrases

func LoadYAMLPhrases(perRunPath, globalPath string) (*YAMLPhraseSet, error)

LoadYAMLPhrases reads both files (missing files are fine — treated as empty) and returns a PhraseSet usable by the Filter.

func (*YAMLPhraseSet) Add

func (p *YAMLPhraseSet) Add(phrases []string, addedBy string, afterMR int) (added int, err error)

Add appends new phrases to the per-Run file (deduplicated against the combined view) and persists. Idempotent: phrases already known are dropped silently. Returns true if any new phrases were actually added.

Add is the only write path on YAMLPhraseSet — global stays human- curated (promote via a future `everflow phrases promote` command).

func (*YAMLPhraseSet) All

func (p *YAMLPhraseSet) All() []string

All returns the union of per-Run + global phrases. Order is arbitrary. Useful for the Starlark `phrases.all()` call and for tests.

func (*YAMLPhraseSet) Contains

func (p *YAMLPhraseSet) Contains(text string) bool

Contains reports whether the given text matches any known phrase (per-Run or global), case-insensitively and trim-tolerant.

func (*YAMLPhraseSet) OverCap

func (p *YAMLPhraseSet) OverCap() bool

OverCap reports whether the per-Run list has grown past MaxPerRunEntries. Used to surface a one-time warning in the daemon's logs / on the MR thread.

Jump to

Keyboard shortcuts

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