detectkit 0.44.1__tar.gz → 0.45.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {detectkit-0.44.1/detectkit.egg-info → detectkit-0.45.1}/PKG-INFO +1 -1
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/__init__.py +1 -1
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/CLAUDE.section.md +19 -9
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/cli.md +5 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md +11 -2
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md +20 -5
- detectkit-0.45.1/detectkit/cli/assets/claude/skills/dtk-tune/SKILL.md +184 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/init_claude.py +1 -1
- detectkit-0.45.1/detectkit/tuning/assets/tune.js +187 -0
- {detectkit-0.44.1 → detectkit-0.45.1/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit.egg-info/SOURCES.txt +1 -0
- detectkit-0.44.1/detectkit/tuning/assets/tune.js +0 -187
- {detectkit-0.44.1 → detectkit-0.45.1}/LICENSE +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/MANIFEST.in +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/README.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/branding.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_base.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_decision.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_recovery.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_replay.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/_types.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/_base.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/_types.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/autotuner.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/config_emitter.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/crossval.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/detector_select.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/distribution.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/grid_search.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/labels.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/result.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/runner.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/scoring.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/seasonality_search.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/settings.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/autotune/window_select.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/_output.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/alerting.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/autotune.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/detectors.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/metrics.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/overview.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/rules/project.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/autotune.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/clean.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/tune.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/commands/unlock.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/main.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/config/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/config/profile.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/config/project_config.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/config/validator.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/core/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/core/interval.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/core/models.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/_sql_manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_alert_states.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_autotune_runs.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_base.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_datapoints.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_detections.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_maintenance.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_metrics.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_schema.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/_tasks.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/internal_tables/manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/mysql_manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/postgres_manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/database/tables.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/base.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/seasonality.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/statistical/_windowed.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/error_dispatch.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/_base.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/_load_step.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/_types.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/orchestration/task_manager/manager.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/reporting/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/reporting/assets/report.js +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/reporting/builder.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/reporting/html_report.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/tuning/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/tuning/config_writer.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/tuning/html.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/tuning/payload.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/tuning/server.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/utils/env_interpolation.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/utils/json_utils.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit/utils/stats.py +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/pyproject.toml +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/requirements.txt +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/setup.cfg +0 -0
- {detectkit-0.44.1 → detectkit-0.45.1}/setup.py +0 -0
|
@@ -4,7 +4,7 @@ detectk - Anomaly Detection for Time-Series Metrics
|
|
|
4
4
|
A Python library for data analysts and engineers to monitor metrics with automatic anomaly detection.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "0.
|
|
7
|
+
__version__ = "0.45.1"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -48,15 +48,25 @@ version — **read the relevant one on demand** instead of guessing:
|
|
|
48
48
|
values that need your real connection details) and, optionally, a first alert
|
|
49
49
|
channel.
|
|
50
50
|
- **A new metric** — use the **`dtk-new-metric`** skill; it walks the config out
|
|
51
|
-
to a YAML file that validates and is ready to run.
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
51
|
+
to a YAML file that validates and is ready to run. A robust starter is enough —
|
|
52
|
+
it's the **sandbox** the user then refines with one of the tuning skills below.
|
|
53
|
+
- **Tune a detector (hands-on, recommended)** — use the **`dtk-tune`** skill: it
|
|
54
|
+
loads some history and opens an interactive browser **cockpit** where the user
|
|
55
|
+
turns the detector's knobs on their **real** series and watches the band,
|
|
56
|
+
anomalies and would-fire alerts recompute live, then **Apply**s the result back
|
|
57
|
+
into the metric YAML in place. It is the **umbrella** for tuning: its **Autotune**
|
|
58
|
+
mode runs the full `dtk autotune` engine **server-side** and re-seeds the knobs,
|
|
59
|
+
and its **Label / Review** modes mark or confirm incidents — so the user can
|
|
60
|
+
auto-search, hand-tune and label in one place. **Prefer this whenever the user
|
|
61
|
+
wants to be in the loop** (see, judge, adjust). This is also how you build an
|
|
62
|
+
alert from scratch and dial it in: scaffold the metric (`dtk-new-metric`), then
|
|
63
|
+
open the cockpit.
|
|
64
|
+
- **Tune a detector (fully automatic)** — use the **`dtk-autotune`** skill: a
|
|
65
|
+
cross-validated **command-line** search (seasonality → detector → params →
|
|
66
|
+
window) that writes an annotated `__tuned_<id>.yml` without touching the
|
|
67
|
+
original. Best for CI or "just pick one for me, I won't look." It runs the same
|
|
68
|
+
engine `dtk-tune`'s Autotune mode does — pick the skill by whether the user wants
|
|
69
|
+
hands-on or hands-off.
|
|
60
70
|
- **Hit a detectkit bug, or have feedback** — once you've ruled out a local
|
|
61
71
|
config fix (see the gotchas below), use the **`dtk-feedback`** skill to file a
|
|
62
72
|
redacted bug report, feature request, or comment as a GitHub issue on the
|
|
@@ -126,6 +126,11 @@ un-confirms the alert), counts toward recall + correct, and is written on Save
|
|
|
126
126
|
clean metric whose alerts are all good is validated in a few clicks **without
|
|
127
127
|
hand-drawing spans**. The list, the live metrics and Save share **one** ground-truth
|
|
128
128
|
set (hand-marked spans **plus** confirmed-valid alerts, deduped by overlap).
|
|
129
|
+
**Deleting** an incident (the chart's ✕ / Delete key **or** the list's ✕) also
|
|
130
|
+
**retracts** any confirmed-valid alert verdict it overlapped, so it's fully removed
|
|
131
|
+
instead of reappearing as a "✓ confirmed alert" row — the chart-✕ and list-✕ behave
|
|
132
|
+
identically (a `false`-alarm verdict, and a confirmed alert that doesn't overlap the
|
|
133
|
+
deleted span, are left alone).
|
|
129
134
|
As you tune, a metrics bar shows **incident catch rate (recall)** — how many
|
|
130
135
|
ground-truth incidents (marked + confirmed) your config catches (an incident is
|
|
131
136
|
caught when an alert's anomaly **streak overlaps** it, not just the fire instant) —
|
{detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md
RENAMED
|
@@ -20,6 +20,14 @@ have them, otherwise an unsupervised objective), and writes a ready-to-run
|
|
|
20
20
|
config named `<metric>__tuned_<id>` whose comment header explains every
|
|
21
21
|
decision. Each run is recorded in the `_dtk_autotune_runs` table.
|
|
22
22
|
|
|
23
|
+
**This skill is the fully-automatic, command-line path** — best for CI or when the
|
|
24
|
+
user just wants a strong config picked for them without watching. If the user wants
|
|
25
|
+
to be **in the loop** — see the series, judge the alerts, turn the knobs, mark
|
|
26
|
+
incidents by eye — prefer the **`dtk-tune`** skill: it opens an interactive browser
|
|
27
|
+
cockpit that runs this **same engine** in its **Autotune** mode (server-side,
|
|
28
|
+
re-seeding the knobs) *and* lets them hand-tune and **Apply** in one place. The two
|
|
29
|
+
share the same search; pick by whether the user wants hands-on or hands-off.
|
|
30
|
+
|
|
23
31
|
Work the steps in order. Do not invent SQL, incident times, or channel names —
|
|
24
32
|
gather them. This skill is the procedure; for field detail read the matching
|
|
25
33
|
file under `.claude/rules/detectkit/` (`autotune.md`, `detectors.md`,
|
|
@@ -79,8 +87,9 @@ generalize is rejected.
|
|
|
79
87
|
Labels turn tuning from a good unsupervised default into a config optimised
|
|
80
88
|
against *your* real incidents (it then optimises MCC and also tunes the alert
|
|
81
89
|
window `consecutive_anomalies`). **The easiest, most reliable way to produce them
|
|
82
|
-
is to mark incidents in `dtk tune` — offer this first
|
|
83
|
-
|
|
90
|
+
is to mark incidents in `dtk tune` — offer this first**: open the cockpit and
|
|
91
|
+
**guide the user through marking incidents on the chart** (see the **`dtk-tune`**
|
|
92
|
+
skill for driving it), rather than asking them to recall timestamps:
|
|
84
93
|
|
|
85
94
|
```bash
|
|
86
95
|
dtk tune --select <name>
|
{detectkit-0.44.1 → detectkit-0.45.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md
RENAMED
|
@@ -73,8 +73,12 @@ Pick with the user (see `detectors.md` for the decision table):
|
|
|
73
73
|
- **Unsure** → `mad` (robust default), `threshold: 3.0`.
|
|
74
74
|
|
|
75
75
|
If you don't yet know the right detector or parameters, scaffold a robust starter
|
|
76
|
-
(`mad`, `threshold: 3.0`)
|
|
77
|
-
|
|
76
|
+
(`mad`, `threshold: 3.0`) — treat it as a **sandbox** the user will refine on the
|
|
77
|
+
real series after this metric loads. Two complementary ways to refine it (Step 7):
|
|
78
|
+
the **`dtk-tune`** skill opens an interactive browser cockpit where they turn the
|
|
79
|
+
knobs by hand and watch the band recompute live (with autotune built in), or the
|
|
80
|
+
**`dtk-autotune`** skill searches for the best detector/params automatically. You
|
|
81
|
+
don't need the perfect detector now — a sound starter is enough to open the cockpit.
|
|
78
82
|
|
|
79
83
|
Set `window_size` to fit the data cadence (non-seasonal 100–500 points; seasonal
|
|
80
84
|
several full cycles) and `min_samples` ≈ 10–30% of it. For a metric with a
|
|
@@ -163,6 +167,17 @@ dtk run --select <name> --steps detect # confirm the detector runs
|
|
|
163
167
|
dtk test-alert <name> # confirm channels work (if alerting)
|
|
164
168
|
```
|
|
165
169
|
|
|
166
|
-
Report the created file path and the commands to run it for real.
|
|
167
|
-
|
|
168
|
-
|
|
170
|
+
Report the created file path and the commands to run it for real. Then offer to
|
|
171
|
+
**refine the starter on the real series** — the metric so far is a sandbox, and
|
|
172
|
+
this is where most of the value is. Pick the path with the user:
|
|
173
|
+
|
|
174
|
+
- **Hands-on / "let me see and turn the knobs"** → the **`dtk-tune`** skill: it
|
|
175
|
+
loads some history and opens an interactive browser cockpit where they adjust
|
|
176
|
+
the detector live and **Apply** the result back. Its **Autotune** mode runs the
|
|
177
|
+
automatic search *in place* too, so this one path covers both styles — prefer it
|
|
178
|
+
whenever the user wants to be in the loop.
|
|
179
|
+
- **Fully automatic / "just pick one for me"** → the **`dtk-autotune`** skill: a
|
|
180
|
+
cross-validated command-line search that writes an annotated tuned config
|
|
181
|
+
(optionally against incidents you label first).
|
|
182
|
+
|
|
183
|
+
If they're happy with the robust starter for now, they can just run it and tune later.
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dtk-tune
|
|
3
|
+
description: >-
|
|
4
|
+
Interactively tune a detectkit metric's detector in the browser cockpit: stand
|
|
5
|
+
up a sandbox config, open `dtk tune`, and guide the user to turn the detector's
|
|
6
|
+
knobs on their real series and watch the confidence band recompute live —
|
|
7
|
+
**with the autotune engine built in** (an Autotune mode that searches
|
|
8
|
+
server-side and re-seeds the knobs), plus Label/Review to mark or confirm
|
|
9
|
+
incidents — then write the chosen config back into the metric YAML. Use when
|
|
10
|
+
the user wants to tune a detector by hand / interactively / in the browser, see
|
|
11
|
+
and adjust the band or alerts live, set up a tuning sandbox to "turn the knobs"
|
|
12
|
+
themselves, reduce false alerts hands-on, or visually mark/confirm incidents.
|
|
13
|
+
This is the primary, hands-on entry point for dialing in a metric; it contains
|
|
14
|
+
autotune, so prefer it whenever the user wants to be in the loop.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# Tune a detectkit metric interactively (the cockpit)
|
|
18
|
+
|
|
19
|
+
`dtk tune` opens a localhost **browser cockpit** over a metric's **real**
|
|
20
|
+
persisted series. The user turns the detector's knobs and the confidence band,
|
|
21
|
+
flagged anomalies and would-fire alerts **recompute live** — no DB round-trip,
|
|
22
|
+
nothing leaves the machine — then clicks **Apply** to write the chosen config
|
|
23
|
+
**back into the metric YAML in place** (safely: validated, with the previous
|
|
24
|
+
version archived first).
|
|
25
|
+
|
|
26
|
+
It is the **hands-on umbrella** for tuning. The cockpit has four modes and one of
|
|
27
|
+
them runs the **real `dtk autotune` engine server-side** and re-seeds every knob
|
|
28
|
+
with the winner — so the user can auto-search *and* hand-tune *and* label
|
|
29
|
+
incidents without leaving the page. **Prefer this skill whenever the user wants
|
|
30
|
+
to be in the loop** (see, judge, adjust). Use the **`dtk-autotune`** skill
|
|
31
|
+
instead only for a fully hands-off, command-line search (e.g. CI, "just pick one
|
|
32
|
+
for me, I won't look").
|
|
33
|
+
|
|
34
|
+
Your job is to **set up the sandbox, open it, and guide the user through it** —
|
|
35
|
+
they drive the chart; you prepare it, explain each control in plain language, and
|
|
36
|
+
handle the follow-up (`dtk run` / `dtk clean`). This skill is the procedure; for
|
|
37
|
+
field detail read the matching file under `.claude/rules/detectkit/` (`cli.md`
|
|
38
|
+
has the full `dtk tune` reference, plus `detectors.md`, `autotune.md`,
|
|
39
|
+
`alerting.md`).
|
|
40
|
+
|
|
41
|
+
## Step 0 — A metric with loaded data (the sandbox)
|
|
42
|
+
|
|
43
|
+
The cockpit charts a metric's **already-loaded** `_dtk_datapoints`, so you need a
|
|
44
|
+
metric that exists and has some history loaded.
|
|
45
|
+
|
|
46
|
+
- **A project root** contains `detectkit_project.yml`. If `profiles.yml` is still
|
|
47
|
+
the `dtk init` placeholder, set up the DB first with **`dtk-setup-project`**.
|
|
48
|
+
- **No metric yet?** This is the "stand up a sandbox to turn the knobs" path: hand
|
|
49
|
+
off to **`dtk-new-metric`** to design the query + a robust **starter** detector
|
|
50
|
+
(e.g. `mad`, `threshold: 3.0`) — that starter is exactly the sandbox the user
|
|
51
|
+
will refine here. Keep query design in that skill; never fabricate SQL here.
|
|
52
|
+
- **Load some history** (the more, the better the picture):
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
dtk run --select <name> --steps load # incremental
|
|
56
|
+
dtk run --select <name> --steps load --from 2026-01-01 # backfill more history
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
If the chart later looks empty or too short, load more with `--from`.
|
|
60
|
+
|
|
61
|
+
## Step 1 — Open the cockpit
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
dtk tune --select <name>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The selector must resolve to a **single** metric. This starts a `127.0.0.1`
|
|
68
|
+
server and opens the browser. Useful flags:
|
|
69
|
+
|
|
70
|
+
- **Remote / headless machine** — add `--no-open` and share the printed URL (the
|
|
71
|
+
server is localhost-only; the user opens it via a tunnel/port-forward).
|
|
72
|
+
- **Focus a window** — `--from <date>` / `--to <date>` bound what's loaded.
|
|
73
|
+
- **No write-back / share a snapshot** — `--no-serve` writes a static read-only
|
|
74
|
+
HTML preview instead: the sliders still recompute, but there is **no Apply**
|
|
75
|
+
(and **no Autotune** — that needs the live server); **Save incidents**
|
|
76
|
+
downloads the labels file instead of writing it.
|
|
77
|
+
|
|
78
|
+
Tell the user plainly: *"I've opened an interactive chart of your metric — turn
|
|
79
|
+
the knobs and watch the band; tell me what you see and I'll help you decide."*
|
|
80
|
+
|
|
81
|
+
## Step 2 — Orient the user to the cockpit
|
|
82
|
+
|
|
83
|
+
One chart fills the screen (the **windshield**); the live quality metrics ride
|
|
84
|
+
**pinned over it**; every control lives in an **always-visible side rail** that is
|
|
85
|
+
**mode-aware** (it shows only the current mode's controls). A **mode switch** above
|
|
86
|
+
the chart picks the job. Navigate a dense series by **scrolling to zoom**,
|
|
87
|
+
**dragging to pan**, double-clicking to reset, and dragging the **navigator
|
|
88
|
+
strip** below the chart. The **Points shown** slider trims to the most-recent N
|
|
89
|
+
points so recompute (and the read) is faster — view-only, never written.
|
|
90
|
+
|
|
91
|
+
These controls stay visible in **every** mode (they shape the band and the
|
|
92
|
+
alerts): **Points shown**, the alert rule (**direction** + **consecutive
|
|
93
|
+
anomalies**), and the **y = 0** reference-line toggle.
|
|
94
|
+
|
|
95
|
+
## Step 3 — The four modes (autotune is one of them)
|
|
96
|
+
|
|
97
|
+
Walk the user to the mode that fits what they want to do:
|
|
98
|
+
|
|
99
|
+
- **Tune** — *turn the knobs.* The band leads. Adjust **detector type** (MAD /
|
|
100
|
+
Z-Score / IQR, or **Manual** = fixed lower/upper bounds), **threshold**,
|
|
101
|
+
**window size**, **recency weighting + half-life**, **detrend**, **smoothing**,
|
|
102
|
+
and **seasonality groups**; the band + anomalies + would-fire alerts recompute
|
|
103
|
+
on every change. The window-size / half-life readouts show the equivalent
|
|
104
|
+
wall-clock span. This is the core "turn the knobs yourself" loop.
|
|
105
|
+
|
|
106
|
+
- **Autotune** — *let the engine search, then refine.* Click **Run autotune** and
|
|
107
|
+
the **same engine `dtk autotune` uses** (seasonality → detector → grid → window,
|
|
108
|
+
cross-validated) runs **server-side over the window currently shown** (the
|
|
109
|
+
**Points shown** trim — the exact series on screen, not the full history), using
|
|
110
|
+
any marked/confirmed incidents as ground truth. It then **re-seeds every knob**
|
|
111
|
+
with the winner and shows the score + decision log. It's **advisory** — it
|
|
112
|
+
computes and re-seeds only, persists nothing (no run record, no `__tuned_<id>`
|
|
113
|
+
file, no detections), so the session stays lock-free; the user reviews the band
|
|
114
|
+
and **Applies**. Each run also streams a structured `LABELS → … → RESULT` log to
|
|
115
|
+
the terminal you launched from. (This is why `dtk tune` is the umbrella: the user
|
|
116
|
+
gets autotune **and** hand-tuning in one place.)
|
|
117
|
+
|
|
118
|
+
- **Label** — *mark the real incidents* (ground truth that sharpens both the live
|
|
119
|
+
quality metrics and a supervised Autotune). **Drag a span** over each incident;
|
|
120
|
+
or **Lasso anomalies** (loop a cloud of anomaly dots into one span per run); or
|
|
121
|
+
**Threshold capture** (grab every span past a horizontal line). **Save
|
|
122
|
+
incidents** writes a versioned `incidents/<metric>/*.yml` — the same store
|
|
123
|
+
`dtk autotune` reads.
|
|
124
|
+
|
|
125
|
+
- **Review** — *confirm the fired alerts.* When a config already looks good, click
|
|
126
|
+
each alert marker to cycle its verdict un-reviewed → **valid** (green) → **false
|
|
127
|
+
alarm** (slate). **Confirming an alert valid marks it as a ground-truth
|
|
128
|
+
incident**, and **Confirm all unreviewed valid** does the lot — so a clean
|
|
129
|
+
metric is validated in a few clicks **without hand-drawing spans**.
|
|
130
|
+
|
|
131
|
+
**Suggesting a path.** If the user *can recognise* their incidents on the chart,
|
|
132
|
+
start in **Label** (or **Review** to confirm good alerts) to give the engine
|
|
133
|
+
ground truth, then **Autotune** for a strong config, then **Tune** by eye, then
|
|
134
|
+
**Apply**. If they just want a quick strong default, go straight to **Autotune**
|
|
135
|
+
(unsupervised) and refine. If they want full manual control, stay in **Tune**.
|
|
136
|
+
|
|
137
|
+
## Step 4 — Read the live quality, then Apply
|
|
138
|
+
|
|
139
|
+
As they tune, the metrics bar shows **incident catch rate (recall)**,
|
|
140
|
+
**false-alert rate** ("≈1 in N false"), and **reviewed N/M** — recomputed against
|
|
141
|
+
the marked + confirmed incidents (only those inside the loaded window are scored).
|
|
142
|
+
An optional **false-alert budget** (`false_alert_budget`, a fraction in `(0, 1]`,
|
|
143
|
+
on the metric then project, default `0.5`) gently flags the chip when the
|
|
144
|
+
false-alert rate exceeds it (tuning-only; labeling stays optional).
|
|
145
|
+
|
|
146
|
+
When the user is happy, they click **Apply to metric**. detectkit then, in order:
|
|
147
|
+
**validates** the config (a bad/untunable config is rejected and **nothing is
|
|
148
|
+
written**), **archives** the current YAML verbatim under
|
|
149
|
+
`metrics/.history/<metric>/`, and **re-emits** the metric in place with the tuned
|
|
150
|
+
detector (and updates the first alerting block's `consecutive_anomalies` if it has
|
|
151
|
+
one). Applying ends the session; saving incidents does not.
|
|
152
|
+
|
|
153
|
+
## Step 5 — Recompute under the new config
|
|
154
|
+
|
|
155
|
+
`dtk tune` takes **no pipeline lock** and the live preview is a faithful
|
|
156
|
+
*approximation* — the **next `dtk run` is the source of truth**. Because the
|
|
157
|
+
detector params changed, the detector's identity changed, so detections recompute
|
|
158
|
+
under the new id and the old rows are orphaned:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
dtk run --select <name> # load → detect → alert under the new config
|
|
162
|
+
dtk run --select <name> --report # optional: a self-contained HTML report to confirm behavior
|
|
163
|
+
dtk clean --select <name> --execute # prune the orphaned old detector rows
|
|
164
|
+
dtk test-alert <name> # if alerting is configured
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## When to hand off instead
|
|
168
|
+
|
|
169
|
+
- **Fully automatic, no browser** (CI, "just pick one for me") → the
|
|
170
|
+
**`dtk-autotune`** skill (it runs the same engine from the command line and
|
|
171
|
+
writes an annotated `__tuned_<id>.yml` without touching the original).
|
|
172
|
+
- **No metric yet** → **`dtk-new-metric`** to scaffold the sandbox, then come back.
|
|
173
|
+
- **DB not connected** → **`dtk-setup-project`**.
|
|
174
|
+
|
|
175
|
+
## Final checklist — verify before declaring done
|
|
176
|
+
|
|
177
|
+
- [ ] Metric exists, resolves to a **single** selector, and has loaded datapoints
|
|
178
|
+
(ran `--steps load`, backfilled with `--from` if the chart was thin).
|
|
179
|
+
- [ ] You opened `dtk tune` (with `--no-open` + shared URL on a remote machine)
|
|
180
|
+
and told the user it's an interactive chart they drive.
|
|
181
|
+
- [ ] You explained the relevant mode(s) — including that **Autotune is built in**
|
|
182
|
+
and runs over the window shown — and which controls stay visible everywhere.
|
|
183
|
+
- [ ] After **Apply**, you ran `dtk run` to recompute and `dtk clean --execute`
|
|
184
|
+
to prune the orphaned old detector rows (and `dtk test-alert` if alerting).
|
|
@@ -12,7 +12,7 @@ It writes three things into the target directory:
|
|
|
12
12
|
- ``.claude/rules/detectkit/`` — the reference docs the assistant reads on
|
|
13
13
|
demand (overview, cli, project, metrics, detectors, alerting, autotune).
|
|
14
14
|
- ``.claude/skills/`` — user-facing skills (``dtk-setup-project``,
|
|
15
|
-
``dtk-new-metric``, ``dtk-autotune``, ``dtk-feedback``).
|
|
15
|
+
``dtk-new-metric``, ``dtk-tune``, ``dtk-autotune``, ``dtk-feedback``).
|
|
16
16
|
|
|
17
17
|
The source of truth for all of the above lives in ``detectkit/cli/assets/claude``
|
|
18
18
|
and ships with the package, so re-running this command after upgrading detectkit
|