detectkit 0.23.2__tar.gz → 0.24.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.23.2/detectkit.egg-info → detectkit-0.24.1}/PKG-INFO +1 -1
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/__init__.py +1 -1
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/config_emitter.py +17 -5
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/html_labeler.py +9 -5
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/label_server.py +10 -5
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/autotune.md +4 -2
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/cli.md +8 -7
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md +10 -7
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/autotune.py +3 -3
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/init_claude.py +10 -7
- {detectkit-0.23.2 → detectkit-0.24.1/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.23.2 → detectkit-0.24.1}/LICENSE +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/MANIFEST.in +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/README.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/branding.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/_base.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/_decision.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/_recovery.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/_types.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/_base.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/_types.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/autotuner.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/crossval.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/detector_select.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/distribution.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/grid_search.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/labels.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/result.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/scoring.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/seasonality_search.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/settings.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/autotune/window_select.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/_output.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/CLAUDE.section.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/alerting.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/detectors.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/metrics.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/overview.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/rules/project.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/clean.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/commands/unlock.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/main.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/config/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/config/profile.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/config/project_config.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/config/validator.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/core/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/core/interval.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/core/models.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/_sql_manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_alert_states.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_autotune_runs.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_base.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_datapoints.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_detections.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_maintenance.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_metrics.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_schema.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/_tasks.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/internal_tables/manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/mysql_manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/postgres_manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/database/tables.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/base.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/seasonality.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/statistical/_windowed.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/error_dispatch.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/_base.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/_load_step.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/_types.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/orchestration/task_manager/manager.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/utils/env_interpolation.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/utils/json_utils.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit/utils/stats.py +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/pyproject.toml +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/requirements.txt +0 -0
- {detectkit-0.23.2 → detectkit-0.24.1}/setup.cfg +0 -0
- {detectkit-0.23.2 → detectkit-0.24.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.24.1"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -85,11 +85,23 @@ def _build_body(original: MetricConfig, result: AutoTuneResult, new_name: str) -
|
|
|
85
85
|
body["loading_start_time"] = original.loading_start_time
|
|
86
86
|
body["loading_batch_size"] = original.loading_batch_size
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
# The top-level `seasonality_columns` field feeds the *built-in* time-feature
|
|
89
|
+
# extractor and is validated against the built-in allowlist (hour/day_of_week/…).
|
|
90
|
+
# When the metric instead sources seasonality from the query
|
|
91
|
+
# (`query_columns.seasonality`, e.g. a custom `league_day`), the loader ignores
|
|
92
|
+
# `seasonality_columns` entirely and the chosen grouping rides in the detector's
|
|
93
|
+
# `seasonality_components`. So never copy the chosen columns here in that mode —
|
|
94
|
+
# they may be custom names the validator rejects, and they are already declared
|
|
95
|
+
# in the preserved `query_columns`.
|
|
96
|
+
if original.query_columns and original.query_columns.seasonality:
|
|
97
|
+
if original.seasonality_columns:
|
|
98
|
+
body["seasonality_columns"] = original.seasonality_columns
|
|
99
|
+
else:
|
|
100
|
+
scalar_cols = _flatten_scalar_seasonality(result.chosen_seasonality)
|
|
101
|
+
if scalar_cols:
|
|
102
|
+
body["seasonality_columns"] = scalar_cols
|
|
103
|
+
elif original.seasonality_columns:
|
|
104
|
+
body["seasonality_columns"] = original.seasonality_columns
|
|
93
105
|
|
|
94
106
|
body["detectors"] = [
|
|
95
107
|
{"type": result.chosen_detector_type, "params": result.chosen_detector_params}
|
|
@@ -7,7 +7,8 @@ file in the canonical schema, fed back via
|
|
|
7
7
|
``dtk autotune --select <metric> --incidents <file-or-dir>``.
|
|
8
8
|
|
|
9
9
|
The page is offline-only — a browser cannot write to the project, so Export
|
|
10
|
-
downloads a **versioned** file
|
|
10
|
+
downloads a **versioned** file named after the metric, with the optional set name
|
|
11
|
+
folded in as a suffix (``<metric>[-<name>]-<UTC-stamp>.yml``); drop it into
|
|
11
12
|
``incidents/<metric>/`` to keep every labeling round (``--incidents`` accepts
|
|
12
13
|
that directory and uses the newest version).
|
|
13
14
|
|
|
@@ -135,7 +136,7 @@ _TEMPLATE = """<!doctype html>
|
|
|
135
136
|
<div id="empty" class="empty">No incidents marked yet — drag across a span on the chart above.</div>
|
|
136
137
|
<ul id="list"></ul>
|
|
137
138
|
<footer>All times UTC · self-contained, nothing leaves your browser · re-label any time —
|
|
138
|
-
exports are versioned (<code>__METRIC__-<timestamp>.yml</code>), so keep every round in
|
|
139
|
+
exports are versioned (<code>__METRIC__[-<name>]-<timestamp>.yml</code>), so keep every round in
|
|
139
140
|
<code>incidents/__METRIC__/</code>. Generated by <code>dtk autotune --label</code>.</footer>
|
|
140
141
|
</div>
|
|
141
142
|
<script>
|
|
@@ -451,10 +452,13 @@ exportBtn.onclick = () => {
|
|
|
451
452
|
const d=new Date();
|
|
452
453
|
const stamp=d.getUTCFullYear()+pad2(d.getUTCMonth()+1)+pad2(d.getUTCDate())+'T'
|
|
453
454
|
+pad2(d.getUTCHours())+pad2(d.getUTCMinutes())+pad2(d.getUTCSeconds())+'Z';
|
|
454
|
-
|
|
455
|
+
// Always name the file after the metric; the optional set name is a suffix.
|
|
456
|
+
const s = name.trim() ? slug(name) : '';
|
|
457
|
+
const suffix = (s && s !== '__METRIC__') ? '-' + s : '';
|
|
458
|
+
const fname = '__METRIC__' + suffix + '-' + stamp + '.yml';
|
|
455
459
|
const blob=new Blob([y], {type:'text/yaml'}); const a=document.createElement('a');
|
|
456
|
-
a.href=URL.createObjectURL(blob); a.download=
|
|
457
|
-
setMsg('Downloaded ' +
|
|
460
|
+
a.href=URL.createObjectURL(blob); a.download=fname; a.click();
|
|
461
|
+
setMsg('Downloaded ' + fname + ' — move it into incidents/__METRIC__/ and re-run.', 'info');
|
|
458
462
|
}
|
|
459
463
|
};
|
|
460
464
|
|
|
@@ -31,9 +31,12 @@ _MAX_BODY = 5_000_000 # generous cap on the posted labels payload
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def _sanitize(name: str) -> str:
|
|
34
|
-
"""Filesystem-safe slug for a label-set name;
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
"""Filesystem-safe slug for a label-set name; ``""`` when blank.
|
|
35
|
+
|
|
36
|
+
Used as an optional *suffix* appended to the metric-named filename, so a blank
|
|
37
|
+
name simply yields no suffix (the file is named after the metric alone).
|
|
38
|
+
"""
|
|
39
|
+
return _NAME_RE.sub("-", name.strip().lower()).strip("-")
|
|
37
40
|
|
|
38
41
|
|
|
39
42
|
def _stamp() -> str:
|
|
@@ -87,14 +90,16 @@ class _Handler(BaseHTTPRequestHandler):
|
|
|
87
90
|
|
|
88
91
|
payload = json.loads(self.rfile.read(length).decode("utf-8"))
|
|
89
92
|
yaml_text = str(payload.get("yaml", ""))
|
|
90
|
-
|
|
93
|
+
suffix = _sanitize(str(payload.get("name", "")))
|
|
91
94
|
raw = _yaml.safe_load(yaml_text)
|
|
92
95
|
# validate against the canonical schema before writing anything
|
|
93
96
|
parse_incident_labels(
|
|
94
97
|
raw, interval_seconds=srv.interval_seconds, metric_name=srv.metric
|
|
95
98
|
)
|
|
96
99
|
srv.incidents_dir.mkdir(parents=True, exist_ok=True)
|
|
97
|
-
|
|
100
|
+
# Always name the file after the metric; the optional set name is a suffix.
|
|
101
|
+
stem = f"{srv.metric}-{suffix}" if suffix else srv.metric
|
|
102
|
+
out = srv.incidents_dir / f"{stem}-{_stamp()}.yml"
|
|
98
103
|
out.write_text(yaml_text, encoding="utf-8")
|
|
99
104
|
srv.saved_path = out
|
|
100
105
|
except Exception as exc:
|
|
@@ -53,7 +53,8 @@ dtk autotune --select <sel> [--incidents FILE] [--label] [--scoring METRIC] \
|
|
|
53
53
|
non-interactively) tunes **unsupervised**.
|
|
54
54
|
- `--label` — open the interactive labeler (zoom/pan, edit incident edges,
|
|
55
55
|
per-incident descriptions, named sets). **Default:** a local 127.0.0.1 server +
|
|
56
|
-
browser; **Save & tune** writes `incidents/<
|
|
56
|
+
browser; **Save & tune** writes `incidents/<metric>/<metric>[-<set>]-<UTC>.yml`
|
|
57
|
+
(named after the metric, optional set name as a suffix) and the run
|
|
57
58
|
**continues into tuning on it**. `--no-serve` writes a static
|
|
58
59
|
`metrics/<name>__labeler.html` (Export downloads the file) and exits; `--no-open`
|
|
59
60
|
prints the URL instead of launching a browser.
|
|
@@ -91,7 +92,8 @@ user to recall timestamps** — it is the easiest, most reliable path:
|
|
|
91
92
|
2. The user marks incidents on the chart (scroll to zoom, drag the navigator to
|
|
92
93
|
move, click-drag to mark, drag an incident's edges to adjust, add a
|
|
93
94
|
description, optionally name the set), then clicks **Save & tune**.
|
|
94
|
-
3. That writes `incidents/<
|
|
95
|
+
3. That writes `incidents/<metric>/<metric>[-<set>]-<UTC>.yml` automatically
|
|
96
|
+
(named after the metric, optional set name as a suffix; versioned —
|
|
95
97
|
re-labeling never overwrites) and the **same command continues into the tuning
|
|
96
98
|
run** on it. No manual file moving.
|
|
97
99
|
4. To re-tune later on saved sets, point `--incidents` at the folder
|
|
@@ -20,15 +20,16 @@ Run all commands from a project directory (the one containing
|
|
|
20
20
|
|
|
21
21
|
Used by `run`, `unlock`, and `clean` (drift mode). Three forms:
|
|
22
22
|
|
|
23
|
-
- **Metric name** — `--select cpu_usage`.
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
- **Metric name** — `--select cpu_usage`. Resolves to `metrics/cpu_usage.yml` at
|
|
24
|
+
the root, then falls back to a recursive search by the YAML `name:` field in any
|
|
25
|
+
subdirectory. Do **not** add `.yml` (it is appended). This matches the metric by
|
|
26
|
+
**name**, and every operation is keyed by that `name` inside the YAML.
|
|
26
27
|
- **Path / glob** — `--select "metrics/critical/*.yml"`, `--select "api_*"`,
|
|
27
28
|
`--select "metrics/**/*.yml"`. Searches recursively via glob; keep `.yml`.
|
|
28
29
|
- **Tag** — `--select tag:critical`. Searches recursively for metrics whose
|
|
29
30
|
`tags:` list contains that tag.
|
|
30
31
|
|
|
31
|
-
`--select "*"` selects everything. `--exclude / -e` removes matches
|
|
32
|
+
`--select "*"` selects everything. `--exclude / -e` (on `dtk run`) removes matches
|
|
32
33
|
(`--select "*" --exclude "metrics/staging/*"`). Metric names must be unique
|
|
33
34
|
across the project; duplicates raise an error listing the conflicting files.
|
|
34
35
|
|
|
@@ -39,9 +40,9 @@ dtk run --select <sel> [--steps load,detect,alert] [--from DATE] [--to DATE] \
|
|
|
39
40
|
[--full-refresh] [--force] [--profile NAME]
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
- `--steps` —
|
|
43
|
-
|
|
44
|
-
`--steps detect,alert` (skip load).
|
|
43
|
+
- `--steps` — which of `load`, `detect`, `alert` to run (default all); they always
|
|
44
|
+
execute in `load → detect → alert` order. Examples: `--steps load` (verify the
|
|
45
|
+
query), `--steps detect` (rerun detection only), `--steps detect,alert` (skip load).
|
|
45
46
|
- `--from DATE` / `--to DATE` — `YYYY-MM-DD` or `YYYY-MM-DD HH:MM:SS`, UTC.
|
|
46
47
|
Affects only the `load` step. `--from` overrides the metric's
|
|
47
48
|
`loading_start_time`; `--to` defaults to now.
|
{detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md
RENAMED
|
@@ -96,8 +96,9 @@ user through it:
|
|
|
96
96
|
with an optional **description**). Adjust one by dragging its **edges**, or its
|
|
97
97
|
**middle** to move it; optionally **name the set**; *remove* / *Clear all* fix
|
|
98
98
|
mistakes.
|
|
99
|
-
3. Click **Save & tune**. The server writes `incidents/<
|
|
100
|
-
automatically (
|
|
99
|
+
3. Click **Save & tune**. The server writes `incidents/<metric>/<metric>[-<set>]-<UTC>.yml`
|
|
100
|
+
automatically (named after the metric, with the optional set name as a suffix;
|
|
101
|
+
versioned — re-labeling never overwrites) and the **same command
|
|
101
102
|
continues into the tuning run on it**. No manual file moving.
|
|
102
103
|
|
|
103
104
|
(`--no-serve` is the offline fallback: it writes a static
|
|
@@ -157,8 +158,10 @@ dtk autotune --select <name>
|
|
|
157
158
|
none yet, load first: `dtk run --select <name> --steps load` (optionally
|
|
158
159
|
`--from <date>` to backfill history — more history tunes better). The default
|
|
159
160
|
**supervised** scoring metric is **MCC** (robust to rare anomalies). Override
|
|
160
|
-
only with reason: `--scoring
|
|
161
|
-
|
|
161
|
+
only with reason: `--scoring f_beta` (with a higher `beta:` in the `autotune:`
|
|
162
|
+
block) when a miss is worse than a false page, `--scoring f1` for a balanced
|
|
163
|
+
trade-off, etc. The valid values are `mcc`, `f1`, `f_beta`, `balanced_accuracy`,
|
|
164
|
+
`roc_auc`, `pr_auc`. Run `dtk autotune --help` to confirm the live flags. Use
|
|
162
165
|
`--dry-run` to search without writing anything.
|
|
163
166
|
|
|
164
167
|
**Unsupervised runs** (no labels) do **not** optimize MCC or any labeled metric —
|
|
@@ -190,9 +193,9 @@ The `#` comment header walks the whole decision; summarize for the user:
|
|
|
190
193
|
`Objective : unsupervised (band-fit + flag-budget) = …` (it never claims an
|
|
191
194
|
`mcc =` score it didn't compute). Read off the value + the per-fold CV spread.
|
|
192
195
|
|
|
193
|
-
Offer alternatives: a re-run with a different `--scoring` (e.g.
|
|
194
|
-
recall
|
|
195
|
-
`_dtk_autotune_runs` audit table.
|
|
196
|
+
Offer alternatives: a re-run with a different `--scoring` (e.g. `f_beta` with a
|
|
197
|
+
higher `beta` to favor recall, or `f1` for balance) or a nudged parameter. See
|
|
198
|
+
`autotune.md` for the `_dtk_autotune_runs` audit table.
|
|
196
199
|
|
|
197
200
|
## Step 5 — Show how the monitoring behaves (DB inspection query)
|
|
198
201
|
|
|
@@ -100,9 +100,9 @@ _LABELS_GLOBS = ("*.yml", "*.yaml", "*.json")
|
|
|
100
100
|
def _labels_files(directory: Path) -> list[Path]:
|
|
101
101
|
"""All labels files in *directory*, oldest→newest.
|
|
102
102
|
|
|
103
|
-
The labeler saves versioned, ISO-stamped names (``<set
|
|
104
|
-
chronologically, so name order is chronological (tie-broken by mtime).
|
|
105
|
-
lets ``incidents/<metric>/`` keep every labeling round on disk.
|
|
103
|
+
The labeler saves versioned, ISO-stamped names (``<metric>[-<set>]-<UTC>.yml``)
|
|
104
|
+
which sort chronologically, so name order is chronological (tie-broken by mtime).
|
|
105
|
+
This lets ``incidents/<metric>/`` keep every labeling round on disk.
|
|
106
106
|
"""
|
|
107
107
|
files: list[Path] = []
|
|
108
108
|
for pattern in _LABELS_GLOBS:
|
|
@@ -10,9 +10,9 @@ It writes three things into the target directory:
|
|
|
10
10
|
- ``CLAUDE.md`` — created if absent, otherwise a managed detectkit block is
|
|
11
11
|
injected/refreshed between HTML-comment markers (existing content is kept).
|
|
12
12
|
- ``.claude/rules/detectkit/`` — the reference docs the assistant reads on
|
|
13
|
-
demand (overview, cli, project, metrics, detectors, alerting).
|
|
13
|
+
demand (overview, cli, project, metrics, detectors, alerting, autotune).
|
|
14
14
|
- ``.claude/skills/`` — user-facing skills (``dtk-setup-project``,
|
|
15
|
-
``dtk-new-metric``, ``dtk-feedback``).
|
|
15
|
+
``dtk-new-metric``, ``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
|
|
@@ -38,12 +38,15 @@ if TYPE_CHECKING:
|
|
|
38
38
|
# strings, so it is never evaluated at runtime — safe on 3.10).
|
|
39
39
|
from importlib.resources.abc import Traversable
|
|
40
40
|
|
|
41
|
-
# Region in CLAUDE.md owned by this command. The BEGIN marker
|
|
42
|
-
#
|
|
43
|
-
#
|
|
41
|
+
# Region in CLAUDE.md owned by this command. The BEGIN marker is intentionally
|
|
42
|
+
# version-less: stamping the version here made the block churn on every release
|
|
43
|
+
# (a no-op upgrade still rewrote the marker), pushing users to re-run for nothing.
|
|
44
|
+
# The block now changes only when its content actually changes, so a refresh is a
|
|
45
|
+
# true no-op otherwise. The regex still matches the old *versioned* markers
|
|
46
|
+
# (`<!-- BEGIN detectkit v0.23.2 ... -->`), so refreshing an existing file
|
|
47
|
+
# replaces the whole region in place rather than appending a duplicate.
|
|
44
48
|
_BEGIN = (
|
|
45
|
-
|
|
46
|
-
"(managed by `dtk init-claude` — do not edit between these markers) -->"
|
|
49
|
+
"<!-- BEGIN detectkit (managed by `dtk init-claude` — do not edit between these markers) -->"
|
|
47
50
|
)
|
|
48
51
|
_END = "<!-- END detectkit -->"
|
|
49
52
|
_BLOCK_RE = re.compile(r"<!-- BEGIN detectkit.*?-->.*?<!-- END detectkit -->", re.DOTALL)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.23.2 → detectkit-0.24.1}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|