Documentation
¶
Overview ¶
Package rules holds celeste's stream rules (2.0 W3, #175): a regex condition on the model's streamed text or a tool call's arguments, and a reminder that joins the conversation only when the rule fires. Rules come from the built-ins, ~/.celeste/rules/*.md and the grimoire's "## Stream Rules" section. A rule costs no context until it fires.
Index ¶
- func Destructive(command string) bool
- func FieldValues(input map[string]any, field string) []string
- func IsCheck(tool string) bool
- func IsEdit(tool string) bool
- func Record(name string, acted bool)
- func ResetStats()
- func Snapshot() map[string]any
- func StripUnbackedAudioClaim(content string, ttsRan bool) string
- func StripUnbackedSpawnClaim(content string, spawnRan bool) string
- func VoiceLeak(path, content string) bool
- type Action
- type Call
- type Facts
- type Hit
- type Matcher
- type Rule
- type Scope
- type ScopeKind
- type Section
- type Set
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Destructive ¶
Destructive reports a bash command the destructive-bash rule fires on (a force push, a recursive forced rm outside build output, or any rm the bash tool refuses), read as a shell would read it.
func FieldValues ¶
FieldValues returns the values of a tool_args field. A dotted field walks into objects, and an array along the way fans out to each element, so "edits.new_string" is every patch_file edit's new_string (2.0 W4). A string met before the path ends is decoded as JSON.
func IsCheck ¶
IsCheck reports a tool whose successful run counts as checking the work (bash: a build, a test run).
func IsEdit ¶
IsEdit reports a tool that changes a file. An edit with no successful check after it leaves the work unverified (task-complete-before-verify, and the watchdog's unverified heuristic).
func Snapshot ¶
Snapshot is the celeste_status "rules" object (without "mode", which the server adds).
func StripUnbackedAudioClaim ¶
StripUnbackedAudioClaim replaces a fabricated "Audio saved:" success string in a final reply when no TTS tool ran (ttsRan false). It is the unbacked-audio-claim rule's backstop: MCP chat applies it to every reply, whether stream rules are off, in shadow, or acting and out of retries. Moved here from llm/toolargs.go (2.0 W3).
func StripUnbackedSpawnClaim ¶
StripUnbackedSpawnClaim removes a fabricated "subagent spawned (id: …)" success string the model may emit when it can't actually drive the spawn_agent tool (a non-reasoning/weak model flails then claims success — observed with a fake id "task-47"). If no spawn_agent tool ran this run (spawnRan false) and the content claims a spawned subagent with an id, the claim is replaced with an honest error. Returned unchanged when a spawn ran or no claim is present. Moved here from llm/toolargs.go, next to its audio twin.
Types ¶
type Action ¶
type Action string
Action is what a fired rule does.
const ( // Interrupt cuts the request short and re-runs the turn with the rule's // reminder; for tool_args, the turn's calls never run. Interrupt Action = "interrupt" // Append adds the reminder before the next request, after the turn's // tool results. After a final reply it waits for the next run. Append Action = "append" // Queue holds the reminder for the next run (the next user turn). Queue Action = "queue" )
type Facts ¶
type Facts struct {
TTSRan bool // generate_speech returned without an error this session
// RuntimeVerifies is set for an agent run with verification commands:
// the runtime checks the work after TASK_COMPLETE, so the
// task-complete-before-verify rule stands down.
RuntimeVerifies bool
// contains filtered or unexported fields
}
Facts are what the built-in guards know about the session, kept by the Matcher from tool results.
func (*Facts) Unverified ¶
Unverified reports a file changed after the last command that ran.
type Hit ¶
type Hit struct {
Rule *Rule
Scope Scope
Text string // what matched
Call *Call // tool_args scope: the call
Value string // tool_args scope: the whole argument value matched
}
Hit is one rule firing.
type Matcher ¶
type Matcher struct {
// contains filtered or unexported fields
}
Matcher runs a Set over one session. Not safe for concurrent use: the caller (steer.Session) serializes it.
func NewMatcher ¶
NewMatcher returns a matcher over set (nil: no rules).
func (*Matcher) Calls ¶
Calls checks a turn's complete tool calls and returns the tool_args rules they fire.
func (*Matcher) StartRequest ¶
func (m *Matcher) StartRequest()
StartRequest begins a model request: the streamed text starts empty and each rule fires at most once per request.
func (*Matcher) Text ¶
Text feeds one streamed text delta and returns the text rules it fires. Scans are batched (scanEvery, or a newline); call Flush when the stream ends so the last batch is scanned too.
func (*Matcher) ToolResult ¶
ToolResult records a call's outcome for the facts.
type Rule ¶
type Rule struct {
Name string
Condition *regexp.Regexp
Scopes []Scope
Action Action
Once bool // repeat: once (per session)
Gap int // repeat: after-gap:N, in requests
Message string
Source string // file path, grimoire path, or "builtin"
Disabled bool // enabled: false (removes a rule of the same name)
// contains filtered or unexported fields
}
Rule is one parsed rule.
func Builtins ¶
func Builtins() []*Rule
Builtins returns the shipped rules (spec §5 W3), parsed fresh each call. A user or grimoire rule of the same name replaces one; enabled: false turns it off.
func Parse ¶
Parse reads one rule: YAML-style "key: value" frontmatter between "---" lines, then the reminder text. name is the default name (the file's base name). Keys: name, condition (RE2 regex, required unless enabled: false), scope (comma-separated; default text), action (default append), repeat (once | after-gap:N; default once), enabled (default true).
type Scope ¶
Scope is one place a condition is matched: text, thinking, or tool_args:<tool>.<field>.
type Section ¶
type Section struct {
Source string // the grimoire file
Body string // "### <name>" subsections, each a rule in the file format
}
Section is one grimoire file's "## Stream Rules" body.
func Trusted ¶
Trusted returns the grimoire sections whose stream rules may load (2.0 W3, ruling 18). A repo grimoire's "## Stream Rules" can stop replies, force paid re-runs and inject reminders, so it is trusted like a repo hook: by content hash in the hooks trust store (~/.celeste/trusted.json, `celeste hooks trust`). The global grimoire (~/.celeste/grimoire.md) is the user's own file and needs no trust; neither do the built-ins and ~/.celeste/rules, which never pass through here.
approve is the interactive chat's prompt (the same one repo hooks use); a yes is recorded in the store. Non-interactive runs pass nil: only sections already trusted load, and the rest are skipped with one warning.
type Set ¶
type Set struct{ Rules []*Rule }
Set is the rules in effect, sorted by name.
func Load ¶
Load returns the built-ins, overridden by ~/.celeste/rules/*.md, then by the grimoire's "## Stream Rules" sections in order. A later rule replaces an earlier one of the same name, and enabled: false removes it. A file that does not parse is skipped with a warning; so is a rule whose only scope is thinking (thinking-scope rules are not wired to the model's reasoning yet).