detectkit 0.55.2__tar.gz → 0.56.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.55.2/detectkit.egg-info → detectkit-0.56.1}/PKG-INFO +1 -1
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/__init__.py +1 -1
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/CLAUDE.section.md +2 -1
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/cli.md +16 -6
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/metrics.md +2 -1
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/skills/dtk-tune/SKILL.md +10 -3
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/clean.py +4 -11
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/factory.py +23 -0
- detectkit-0.56.1/detectkit/ui/assets/ui.js +538 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/ui/jobs.py +6 -5
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/ui/overview.py +14 -11
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/ui/server.py +111 -6
- {detectkit-0.55.2 → detectkit-0.56.1/detectkit.egg-info}/PKG-INFO +1 -1
- detectkit-0.55.2/detectkit/ui/assets/ui.js +0 -518
- {detectkit-0.55.2 → detectkit-0.56.1}/LICENSE +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/MANIFEST.in +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/README.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/branding.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_base.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_decision.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_recovery.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_replay.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/_types.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/_base.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/_types.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/autotuner.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/axis_spec.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/config_emitter.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/crossval.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/detector_select.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/distribution.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/grid_search.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/labels.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/result.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/runner.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/scoring.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/seasonality_search.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/settings.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/autotune/window_select.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/_output.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/alerting.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/autotune.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/detectors.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/overview.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/rules/project.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/autotune.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/init_claude.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/osi.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/tune.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/ui.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/commands/unlock.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/cli/main.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/config/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/config/metric_io.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/config/profile.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/config/project_config.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/config/validator.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/core/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/core/interval.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/core/models.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/_sql_manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_alert_states.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_autotune_runs.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_base.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_datapoints.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_detections.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_maintenance.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_metrics.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_schema.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/_tasks.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/internal_tables/manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/mysql_manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/postgres_manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/database/tables.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/base.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/seasonality.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/_windowed.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/autoreg.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/error_dispatch.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/_base.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/_load_step.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/_types.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/orchestration/task_manager/manager.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/reporting/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/reporting/assets/report.js +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/reporting/builder.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/reporting/html_report.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/semantic/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/semantic/errors.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/semantic/exporter.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/semantic/importer.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/semantic/osi_model.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/semantic/query_gen.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/tuning/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/tuning/assets/tune.js +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/tuning/config_writer.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/tuning/html.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/tuning/payload.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/tuning/server.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/ui/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/ui/html.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/ui/metric_files.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/utils/env_interpolation.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/utils/json_utils.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit/utils/stats.py +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/pyproject.toml +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/requirements.txt +0 -0
- {detectkit-0.55.2 → detectkit-0.56.1}/setup.cfg +0 -0
- {detectkit-0.55.2 → detectkit-0.56.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.56.1"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -84,7 +84,8 @@ version — **read the relevant one on demand** instead of guessing:
|
|
|
84
84
|
database key, not the filename. Keep filename and `name` in sync.
|
|
85
85
|
- **Changing a detector parameter changes the detector's identity** and
|
|
86
86
|
recomputes its detections from scratch; the old rows are orphaned. After
|
|
87
|
-
retuning a live metric, run `dtk clean --select <metric>` to prune them
|
|
87
|
+
retuning a live metric, run `dtk clean --select <metric>` to prune them (or,
|
|
88
|
+
from `dtk ui`, open the metric and click **Clean stale** in its detail view).
|
|
88
89
|
- **`alert_cooldown` defaults to `null`** = a persisting anomaly re-alerts on
|
|
89
90
|
*every* `dtk run`. Always set a cooldown for production metrics.
|
|
90
91
|
- The pipeline is **idempotent**: it resumes from the last saved timestamp.
|
|
@@ -12,7 +12,7 @@ Run all commands from a project directory (the one containing
|
|
|
12
12
|
| `dtk run --select <sel>` | Run the load → detect → alert pipeline |
|
|
13
13
|
| `dtk autotune --select <sel>` | Auto-configure a metric's detector (see `autotune.md`) |
|
|
14
14
|
| `dtk tune --select <sel>` | Interactively tune a detector on real data, write it back in place |
|
|
15
|
-
| `dtk ui` | Project-wide live overview + browser pipeline control panel + create/edit/delete metric YAMLs |
|
|
15
|
+
| `dtk ui` | Project-wide live overview + browser pipeline control panel + create/edit/delete metric YAMLs + per-metric Clean stale |
|
|
16
16
|
| `dtk test-alert <metric>` | Send a mock alert to the metric's channels |
|
|
17
17
|
| `dtk unlock --select <sel>` | Clear a stuck pipeline lock |
|
|
18
18
|
| `dtk clean --select <sel>` | Prune internal data that no longer matches the config |
|
|
@@ -211,13 +211,21 @@ dtk ui [-s/--select "*"] [--window 24h|7d|30d|90d|all] [--profile NAME] [--no-op
|
|
|
211
211
|
- `--no-open` — print the URL instead of opening a browser tab.
|
|
212
212
|
|
|
213
213
|
Clicking a metric's **Open** shows the existing self-contained HTML report
|
|
214
|
-
(the same one `--report` writes) in an overlay
|
|
214
|
+
(the same one `--report` writes) in an overlay, whose header also has a
|
|
215
|
+
**Clean stale** button next to **Tune**: it previews a `dtk clean --select
|
|
216
|
+
<metric>` dry-run (superseded detector generations + row counts, stale
|
|
217
|
+
alert-state ids), and — if anything is stale — an amber confirm strip offers
|
|
218
|
+
**Delete stale data**, which spawns the real `dtk clean --select <metric>
|
|
219
|
+
--execute` as a job (`clean` kind) sharing the run/autotune/unlock gate below;
|
|
220
|
+
on success the report reloads and the overview's stale chip clears. This is
|
|
221
|
+
the drift-mode `dtk clean --select` from inside the UI; `--orphaned-metrics`
|
|
222
|
+
(renamed/deleted metrics) stays CLI-only. A **pipeline panel** drives
|
|
215
223
|
the real CLI as subprocesses — `dtk run` (select/steps/from/to/force/
|
|
216
224
|
full-refresh), `dtk autotune`, `dtk unlock` — streaming their terminal
|
|
217
|
-
output live; **only one
|
|
218
|
-
the same pipeline lock anyway). **Tune** launches `dtk tune --select
|
|
225
|
+
output live; **only one `run`/`autotune`/`unlock`/`clean` job runs at a
|
|
226
|
+
time** (they'd contend for the same pipeline lock anyway). **Tune** launches `dtk tune --select
|
|
219
227
|
<metric>` for a metric and opens its cockpit in a new tab — unlike
|
|
220
|
-
run/autotune/unlock, **multiple tune jobs run concurrently**, since each is
|
|
228
|
+
run/autotune/unlock/clean, **multiple tune jobs run concurrently**, since each is
|
|
221
229
|
its own isolated, lock-free session. The `dtk ui` server itself takes **no
|
|
222
230
|
pipeline lock** and never mutates anything — every spawned command behaves
|
|
223
231
|
exactly as if typed into a terminal.
|
|
@@ -290,7 +298,9 @@ the next normal run recovers on its own.)
|
|
|
290
298
|
|
|
291
299
|
Editing metrics over time leaves stale rows in the internal tables. `dtk clean`
|
|
292
300
|
removes that drift. **Both modes dry-run by default** — pass `--execute` to
|
|
293
|
-
actually delete.
|
|
301
|
+
actually delete. Drift mode is also one click away, per metric, from `dtk
|
|
302
|
+
ui`'s detail overlay (**Clean stale**, next to Tune); `--orphaned-metrics`
|
|
303
|
+
stays CLI-only.
|
|
294
304
|
|
|
295
305
|
- **Drift mode** — `dtk clean --select <sel>`: for each still-existing metric,
|
|
296
306
|
deletes `_dtk_detections` rows for `detector_id`s the config no longer
|
|
@@ -149,7 +149,8 @@ columns and bakes the best grouping into the tuned config (see `autotune.md`).
|
|
|
149
149
|
`detector_id` and recomputes that detector's detections; the old rows are
|
|
150
150
|
orphaned in `_dtk_detections`. **Changing/removing an alerting block** orphans
|
|
151
151
|
its `_dtk_alert_states` row. Prune both with `dtk clean --select <m>`
|
|
152
|
-
(preview, then `--execute`)
|
|
152
|
+
(preview, then `--execute`) — or, from `dtk ui`, the metric's detail view's
|
|
153
|
+
**Clean stale** button.
|
|
153
154
|
- **Renaming/deleting a metric** orphans all its rows under the old name; purge
|
|
154
155
|
with `dtk clean --orphaned-metrics`.
|
|
155
156
|
- Datapoints are keyed only by `(metric, timestamp)` — a parameter edit never
|
|
@@ -33,8 +33,10 @@ for me, I won't look").
|
|
|
33
33
|
|
|
34
34
|
Your job is to **set up the sandbox, open it, and guide the user through it** —
|
|
35
35
|
they drive the chart; you prepare it, explain each control in plain language, and
|
|
36
|
-
handle the follow-up (`dtk run` / `dtk clean
|
|
37
|
-
|
|
36
|
+
handle the follow-up (`dtk run` / `dtk clean`, or point at `dtk ui`'s per-metric
|
|
37
|
+
**Clean stale** button as the interactive equivalent). This skill is the
|
|
38
|
+
procedure; for field detail read the matching file under
|
|
39
|
+
`.claude/rules/detectkit/` (`cli.md`
|
|
38
40
|
has the full `dtk tune` reference, plus `detectors.md`, `autotune.md`,
|
|
39
41
|
`alerting.md`).
|
|
40
42
|
|
|
@@ -194,6 +196,10 @@ dtk clean --select <name> --execute # prune the orphaned old detector row
|
|
|
194
196
|
dtk test-alert <name> # if alerting is configured
|
|
195
197
|
```
|
|
196
198
|
|
|
199
|
+
(`dtk ui`'s metric detail overlay has the same cleanup as a **Clean stale**
|
|
200
|
+
button, if the user is already there and would rather not switch to a
|
|
201
|
+
terminal.)
|
|
202
|
+
|
|
197
203
|
## When to hand off instead
|
|
198
204
|
|
|
199
205
|
- **Fully automatic, no browser** (CI, "just pick one for me") → the
|
|
@@ -211,4 +217,5 @@ dtk test-alert <name> # if alerting is configured
|
|
|
211
217
|
- [ ] You explained the relevant mode(s) — including that **Autotune is built in**
|
|
212
218
|
and runs over the window shown — and which controls stay visible everywhere.
|
|
213
219
|
- [ ] After **Apply**, you ran `dtk run` to recompute and `dtk clean --execute`
|
|
214
|
-
to prune the orphaned old detector
|
|
220
|
+
(or `dtk ui`'s **Clean stale** button) to prune the orphaned old detector
|
|
221
|
+
rows (and `dtk test-alert` if alerting).
|
|
@@ -264,17 +264,10 @@ def _valid_detector_ids(config: MetricConfig) -> set[str]:
|
|
|
264
264
|
injection) so the computed ``detector_id`` matches what the pipeline
|
|
265
265
|
writes — anything in the DB not in this set is stale.
|
|
266
266
|
"""
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
if seasonality_components is not None:
|
|
272
|
-
params["seasonality_components"] = seasonality_components
|
|
273
|
-
detector = DetectorFactory.create_from_config(
|
|
274
|
-
{"type": detector_config.type, "params": params}
|
|
275
|
-
)
|
|
276
|
-
ids.add(detector.get_detector_id())
|
|
277
|
-
return ids
|
|
267
|
+
return {
|
|
268
|
+
DetectorFactory.detector_id_for_config(detector_config)
|
|
269
|
+
for detector_config in config.detectors or []
|
|
270
|
+
}
|
|
278
271
|
|
|
279
272
|
|
|
280
273
|
def _valid_alert_config_ids(config: MetricConfig) -> set[str]:
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
Detector factory for creating detector instances from configuration.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
5
7
|
from detectkit.detectors.base import BaseDetector
|
|
6
8
|
from detectkit.detectors.statistical.autoreg import AutoregDetector
|
|
7
9
|
from detectkit.detectors.statistical.iqr import IQRDetector
|
|
@@ -9,6 +11,9 @@ from detectkit.detectors.statistical.mad import MADDetector
|
|
|
9
11
|
from detectkit.detectors.statistical.manual_bounds import ManualBoundsDetector
|
|
10
12
|
from detectkit.detectors.statistical.zscore import ZScoreDetector
|
|
11
13
|
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from detectkit.config.metric_config import DetectorConfig
|
|
16
|
+
|
|
12
17
|
|
|
13
18
|
class DetectorFactory:
|
|
14
19
|
"""
|
|
@@ -119,6 +124,24 @@ class DetectorFactory:
|
|
|
119
124
|
detectors.append(detector)
|
|
120
125
|
return detectors
|
|
121
126
|
|
|
127
|
+
@classmethod
|
|
128
|
+
def detector_id_for_config(cls, detector_config: "DetectorConfig") -> str:
|
|
129
|
+
"""The ``detector_id`` the detect step would run this configured detector under.
|
|
130
|
+
|
|
131
|
+
Mirrors the DETECT step's derivation exactly (``get_algorithm_params``
|
|
132
|
+
+ the same seasonality injection → :meth:`create_from_config` →
|
|
133
|
+
``get_detector_id``), so callers that only need the id — the overview's
|
|
134
|
+
current-config filter, ``dtk clean``'s drift diff, the UI's stale-data
|
|
135
|
+
preview — all agree with what the pipeline writes. Raises (like
|
|
136
|
+
:meth:`create`) on a config the factory rejects.
|
|
137
|
+
"""
|
|
138
|
+
params = detector_config.get_algorithm_params()
|
|
139
|
+
seasonality_components = detector_config.get_seasonality_components()
|
|
140
|
+
if seasonality_components is not None:
|
|
141
|
+
params["seasonality_components"] = seasonality_components
|
|
142
|
+
detector = cls.create_from_config({"type": detector_config.type, "params": params})
|
|
143
|
+
return detector.get_detector_id()
|
|
144
|
+
|
|
122
145
|
@classmethod
|
|
123
146
|
def list_available_types(cls) -> list[str]:
|
|
124
147
|
"""
|