loop: add rule trace/explanation engine
ExplainTick and ExplainGate produce a full TickTrace for every tick, recording per-rule: predicate result, gate result, first gate blocker, gate detail (snooze/cooldown/presence etc.), and win/loss info. IPC layer: new MethodTickTrace, DTOs (TickTrace, RuleTrace, GateDetail), dispatch, client proxy, and CoreAPI interface method. Daemon: tickLoop caches the latest trace; daemonAPI wraps storeAPI with a TickTrace override that returns the cached trace. Tests: 15 new tests for ExplainGate (all blockers, bypass conditions, ordering) and ExplainTick (nothing fires, one fires, tiebreak, winner/lost_to recording, gate-blocked recording).
This commit is contained in:
@@ -240,6 +240,42 @@ type CoreAPI interface {
|
||||
LookupTool(ctx context.Context, name string) (Tool, error)
|
||||
ListTools(ctx context.Context, status string) ([]Tool, error)
|
||||
RevertFact(ctx context.Context, key string) (int64, error)
|
||||
|
||||
// TickTrace returns the most recent tick's rule trace. The daemon caches
|
||||
// this after every tick; the store adapter returns an error (trace is not
|
||||
// persisted — it's a daemon-level cache).
|
||||
TickTrace(ctx context.Context) (TickTrace, error)
|
||||
}
|
||||
|
||||
// --- Rule trace / explanation DTOs ---
|
||||
|
||||
// RuleTrace — per-rule evaluation result for one tick.
|
||||
type RuleTrace struct {
|
||||
RuleName string `json:"rule_name"`
|
||||
Severity int `json:"severity"`
|
||||
PredicateResult bool `json:"predicate_result"`
|
||||
GateResult bool `json:"gate_result"`
|
||||
GateBlockedBy string `json:"gate_blocked_by,omitempty"`
|
||||
GateDetail GateDetail `json:"gate_detail,omitempty"`
|
||||
WasSelected bool `json:"was_selected"`
|
||||
LostTo string `json:"lost_to,omitempty"`
|
||||
}
|
||||
|
||||
// GateDetail — snapshot of the values the gate checked.
|
||||
type GateDetail struct {
|
||||
SnoozeUntil *time.Time `json:"snooze_until,omitempty"`
|
||||
CooldownUntil *time.Time `json:"cooldown_until,omitempty"`
|
||||
QuietHours bool `json:"quiet_hours"`
|
||||
CalendarBusy bool `json:"calendar_busy"`
|
||||
Presence string `json:"presence"`
|
||||
InertKeysMissing []string `json:"inert_keys_missing,omitempty"`
|
||||
}
|
||||
|
||||
// TickTrace — snapshot of one tick's rule evaluations.
|
||||
type TickTrace struct {
|
||||
Now time.Time `json:"now"`
|
||||
Winner string `json:"winner"`
|
||||
Rules []RuleTrace `json:"rules"`
|
||||
}
|
||||
|
||||
// ErrToolNotFound — no tool row with this name (re-exported store sentinel for
|
||||
|
||||
Reference in New Issue
Block a user