Repository navigation
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog,
and this project adheres to Semantic Versioning.
[0.1.0] - 2026-08-27
This is the first tagged release. It comprises 87 merge commits on origin/master
from the first commit through d80a686 (feat --semantic baseline flag, PR #189).
Every user-visible change below was verified against git show <sha> --stat for
its merge commit, not against PR titles. CI at this commit is green with
reproduced counts: 651 passed, 3 skipped (pytest, py3.10 through 3.13),
88.04% line coverage, ruff check src tests and ruff format --check src tests
clean, mypy src clean. Overhead measured on this checkout:
benchmarks/overhead_benchmark.py reports median 5.31 us/step, p99 42.22 us/step
over 200,000 synthetic steps. Detection accuracy measured on this checkout:
benchmarks/detection_accuracy.py reports macro-F1 1.000 over 76 episodes
(40 labeled, 36 healthy controls), zero healthy-control false positives.
Added
Core and configuration
- Canonical schemas
StepEvent/EpisodeMeta/FailureRiskandmake_signature
with SHA-256 normalization (PR #24 through #30, #15, #28). Monitororchestrator with fail-open guarantee, per-episode lock sharding via
StateBackend/MemoryStateBackend, andMetricsself-observability counters
(PR #44, #47).Configdataclass with 12-factor env/file layering (SNAGLINE_*env vars,
Config.resolve, optional JSON/TOML file), tunable thresholds for every
detector, and CLI wiring (snagline --config) (PR #30, #36, #37).BaselineProfilefitting and persistence (fit_baseline_from_jsonl,
save_baseline/load_baseline,BaselineStoreversioned store per
tenant/deployment) (PR #24, #45, #46).Monitor.snapshot/restorewith versioned JSON, atomic tmp+replace,
strict composition check, and per-detectordump_state/load_state
(PR #168).
Detectors
- Loop detector with sliding window and repeat threshold, plus opt-in
hardening modes: near-duplicate (volatile ID collapsing), cycle (periodic
scan), stall (consecutive identical signatures) (PR #114, ce5e449). - Error-cascade detector with windowed and consecutive modes (core), with
configcascade_count_non_tool_errors(PR #16-era, #27 baseline). - Latency-anomaly detector (Welford + CUSUM, stdlib only) with per-tool
baselines, sigma floors, warm-up, and optional baseline re-fit
(cusum_refit_every) (PR #25, #138, #167). - Goal-drift detector (opt-in, compares live run to persisted
BaselineProfileon error rate and latency z-score) (PR #25). - ML ensemble
MLOrchestrator(opt-in, noisy-OR over tier-1 detectors,
model=hook) (PR #26). - Token-runaway detector (opt-in, CUSUM over token volume plus
episode_token_budgetenvelope, triggerstoken_runaway/budget_breach)
(PR #107). - Meltdown detector (opt-in, sliding-window Shannon entropy, low/high
thresholds) (PR #107, #135). - Silent-abort detector (opt-in,
EpisodeFinalizerevaluated at
end_episode, triggersilent_abort) (PR #107). - Stagnation detector (opt-in, novelty-rate collapse) (PR #127).
- Side-effect guard (opt-in, duplicate non-idempotent action detection,
side_effectfield onStepEvent) (PR #140). - Compaction tripwire (opt-in, governance-decay across context
compactions,compaction/constraint_presentcontract) (PR #147). - Horizon-scale time axis (opt-in, PR #167):
max_episode_wall_seconds
with wall-clock budget (wall_clock_budget),idle_warn_seconds
(idle_gap), window auto-scaling (window_scale_steps,max_window),
HeartbeatSinkandsnagline watch --follow --heartbeatliveness file. - ML extra: ESN ensemble (
ml/esn_ensemble.py,snagline[ml],
one-class ESN + CUSUM + Mahalanobis baseline) (PR #135). - Drift extra: semantic goal-drift (
drift/goal_drift.py,
snagline[drift], sentence-transformers, PR #81 / 09ae888). - Auto-calibration from
BaselineProfile(calibration="auto",
CalibrationPlan,resolve_baseline_profile) (PR #138). - Scheduled baseline retrain
snagline baseline retraincontract with
--windows-dir/--jsonl/--store-dir/--max-agestaleness guard
anddocs/RETRAIN_CADENCE.md(PR #126, #102). - Enforcement policy
Monitor(policy="observe"|"callback"|"halt_webhook")
withon_riskcallback (fail-open),halt_url/halt_timeout_s
(default 250 ms) /min_severity_for_halt(default 0.8),