detectkit 0.36.0__tar.gz → 0.36.2__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.36.0/detectkit.egg-info → detectkit-0.36.2}/PKG-INFO +1 -1
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/__init__.py +1 -1
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/cli.md +4 -2
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/tuning/payload.py +48 -35
- {detectkit-0.36.0 → detectkit-0.36.2/detectkit.egg-info}/PKG-INFO +1 -1
- {detectkit-0.36.0 → detectkit-0.36.2}/LICENSE +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/MANIFEST.in +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/README.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/base.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/branding.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/email.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/factory.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/mattermost.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/slack.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/telegram.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/channels/webhook.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_base.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_cooldown.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_decision.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_dispatch.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_recovery.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_replay.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/_types.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/alerting/orchestrator/orchestrator.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/_base.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/_types.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/autotuner.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/config_emitter.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/crossval.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/detector_select.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/distribution.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/grid_search.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/html_labeler.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/label_server.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/labels.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/result.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/scoring.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/seasonality_search.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/settings.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/autotune/window_select.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/_output.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/CLAUDE.section.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/alerting.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/autotune.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/detectors.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/metrics.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/overview.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/rules/project.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-setup-project/SKILL.md +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/autotune.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/clean.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/init.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/init_claude.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/run.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/test_alert.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/tune.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/commands/unlock.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/main.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/config/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/config/metric_config.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/config/profile.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/config/project_config.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/config/validator.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/core/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/core/interval.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/core/models.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/_sql_manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/clickhouse_manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_alert_states.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_autotune_runs.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_base.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_datapoints.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_detections.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_maintenance.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_metrics.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_schema.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/_tasks.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/internal_tables/manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/mysql_manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/postgres_manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/database/tables.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/base.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/factory.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/seasonality.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/statistical/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/statistical/_windowed.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/statistical/iqr.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/statistical/mad.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/statistical/manual_bounds.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/detectors/statistical/zscore.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/loaders/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/loaders/metric_loader.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/loaders/query_template.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/error_dispatch.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/_alert_step.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/_base.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/_detect_step.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/_load_step.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/_types.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/orchestration/task_manager/manager.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/reporting/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/reporting/assets/report.js +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/reporting/builder.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/reporting/html_report.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/tuning/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/tuning/assets/tune.js +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/tuning/config_writer.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/tuning/html.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/tuning/server.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/utils/__init__.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/utils/datetime_utils.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/utils/env_interpolation.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/utils/json_utils.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit/utils/stats.py +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit.egg-info/SOURCES.txt +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit.egg-info/dependency_links.txt +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit.egg-info/entry_points.txt +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit.egg-info/requires.txt +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/detectkit.egg-info/top_level.txt +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/pyproject.toml +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/requirements.txt +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/setup.cfg +0 -0
- {detectkit-0.36.0 → detectkit-0.36.2}/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.36.
|
|
7
|
+
__version__ = "0.36.2"
|
|
8
8
|
|
|
9
9
|
from detectkit.core.interval import Interval
|
|
10
10
|
from detectkit.core.models import ColumnDefinition, TableModel
|
|
@@ -101,8 +101,10 @@ fall outside any real incident ("≈1 in N false"); only incidents within the lo
|
|
|
101
101
|
window are scored. **Save incidents** writes a
|
|
102
102
|
versioned `incidents/<metric>/*.yml` — the same store `dtk autotune` reads, so the
|
|
103
103
|
same labels feed the next supervised tune (it seeds from the newest file on open,
|
|
104
|
-
**
|
|
105
|
-
|
|
104
|
+
**anchoring the budget-sized loaded window on the seeded incidents** — ending just
|
|
105
|
+
past the latest one rather than at the last datapoint — so they render/count
|
|
106
|
+
without an old outlier pulling the whole history in). Saving incidents does not end
|
|
107
|
+
the session; only **Apply** does. A
|
|
106
108
|
**y = 0 line** toggle (shared with `dtk run --report`) shows the metric relative to zero.
|
|
107
109
|
|
|
108
110
|
Safe write-back: the config is validated before anything is written, the previous
|
|
@@ -35,11 +35,6 @@ _TUNE_MAX_POINTS = 15000
|
|
|
35
35
|
# scored region (the band never reaches its real width). Floor the shown points
|
|
36
36
|
# at this many windows so the seeded window is actually exercised in the preview.
|
|
37
37
|
_TUNE_WINDOW_COVERAGE = 3
|
|
38
|
-
# Hard ceiling on the loaded point count when seeded incidents pull the window
|
|
39
|
-
# back far into history — keeps a pathological (e.g. minute-grained, multi-year)
|
|
40
|
-
# series from bloating the page. Any incident still left older than this slice
|
|
41
|
-
# stays in the list but the client metrics ignore it (it cannot be scored).
|
|
42
|
-
_TUNE_INCIDENT_MAX_POINTS = 60_000
|
|
43
38
|
|
|
44
39
|
|
|
45
40
|
def default_window_points(seed_window: int) -> int:
|
|
@@ -82,25 +77,34 @@ def _normalize_seasonality_components(
|
|
|
82
77
|
return groups or None
|
|
83
78
|
|
|
84
79
|
|
|
85
|
-
def
|
|
86
|
-
"""
|
|
80
|
+
def _incident_span(incidents: list[dict[str, str]]) -> tuple[datetime, datetime] | None:
|
|
81
|
+
"""``(earliest start, latest end)`` (naive UTC) over seeded display dicts, or ``None``.
|
|
87
82
|
|
|
88
83
|
The display dicts carry ``"YYYY-MM-DD HH:MM:SS"`` naive-UTC strings (see
|
|
89
84
|
``autotune.labels.incidents_to_display``), matching the naive datetimes the
|
|
90
85
|
builder compares against the loaded series bounds.
|
|
91
86
|
"""
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
raw = inc.get("start")
|
|
87
|
+
|
|
88
|
+
def _parse(raw: Any) -> datetime | None:
|
|
95
89
|
if not raw:
|
|
96
|
-
|
|
90
|
+
return None
|
|
97
91
|
try:
|
|
98
|
-
|
|
92
|
+
return datetime.strptime(str(raw), "%Y-%m-%d %H:%M:%S")
|
|
99
93
|
except ValueError:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
94
|
+
return None
|
|
95
|
+
|
|
96
|
+
earliest: datetime | None = None
|
|
97
|
+
latest: datetime | None = None
|
|
98
|
+
for inc in incidents:
|
|
99
|
+
start = _parse(inc.get("start"))
|
|
100
|
+
end = _parse(inc.get("end")) or start
|
|
101
|
+
if start is not None and (earliest is None or start < earliest):
|
|
102
|
+
earliest = start
|
|
103
|
+
if end is not None and (latest is None or end > latest):
|
|
104
|
+
latest = end
|
|
105
|
+
if earliest is None or latest is None:
|
|
106
|
+
return None
|
|
107
|
+
return earliest, latest
|
|
104
108
|
|
|
105
109
|
|
|
106
110
|
def _seed_detector(metric_config: MetricConfig) -> dict[str, Any]:
|
|
@@ -182,10 +186,12 @@ def build_tune_payload(
|
|
|
182
186
|
(``default_window_points``), not the whole history.
|
|
183
187
|
|
|
184
188
|
``incidents`` seeds the synced labeler with already-marked spans (display dicts
|
|
185
|
-
``{start, end, label}`` from ``incidents_to_display``). When
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
+
``{start, end, label}`` from ``incidents_to_display``). When incidents are
|
|
190
|
+
seeded the (still budget-sized) window is anchored on the incident region — it
|
|
191
|
+
ends just past the latest incident rather than at the last datapoint — so they
|
|
192
|
+
render on the chart and count toward the live recall/FDR metrics, while the
|
|
193
|
+
window stays bounded (a single old outlier incident can't pull the whole
|
|
194
|
+
history in). An explicit ``start``/``--from`` is still honored verbatim.
|
|
189
195
|
``capture_windows`` seeds the threshold-capture regime scope (display dicts
|
|
190
196
|
``{start, end}``). ``labels_save_url`` (the POST endpoint for **Save
|
|
191
197
|
incidents**) is injected by the server, like ``save_url`` — it is ``None`` here.
|
|
@@ -208,22 +214,29 @@ def build_tune_payload(
|
|
|
208
214
|
if start is None and end is not None:
|
|
209
215
|
first = internal.get_first_datapoint_timestamp(name)
|
|
210
216
|
default_points = default_window_points(int(seed["windowSize"]))
|
|
211
|
-
|
|
212
|
-
#
|
|
213
|
-
#
|
|
214
|
-
#
|
|
215
|
-
#
|
|
216
|
-
#
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
217
|
+
budget = timedelta(seconds=interval_seconds * default_points)
|
|
218
|
+
# When incidents are seeded, ANCHOR the (still budget-sized) window on the
|
|
219
|
+
# incident region instead of always ending at the last datapoint, so the
|
|
220
|
+
# incidents render and can be scored. Crucially the window stays bounded:
|
|
221
|
+
# the end is pulled back to just past the LATEST incident (a few windows of
|
|
222
|
+
# recovery context) only when that is older than the last datapoint, so a
|
|
223
|
+
# single old outlier incident can't drag the whole history in — it would
|
|
224
|
+
# blow the recompute budget (the page hangs). Incidents older than the
|
|
225
|
+
# bounded window stay in the list and are excluded from the live metrics.
|
|
226
|
+
span = _incident_span(seed_incidents)
|
|
227
|
+
if span is not None:
|
|
228
|
+
_, latest = span
|
|
229
|
+
# Align awareness to end (both represent UTC) so the comparison is valid
|
|
230
|
+
# on backends that return tz-aware timestamps.
|
|
231
|
+
if end.tzinfo is not None and latest.tzinfo is None:
|
|
232
|
+
latest = latest.replace(tzinfo=end.tzinfo)
|
|
233
|
+
elif end.tzinfo is None and latest.tzinfo is not None:
|
|
234
|
+
latest = latest.replace(tzinfo=None)
|
|
235
|
+
context = timedelta(
|
|
236
|
+
seconds=interval_seconds * max(_TUNE_WINDOW_COVERAGE * int(seed["windowSize"]), 200)
|
|
222
237
|
)
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
ceiling = end - timedelta(seconds=interval_seconds * _TUNE_INCIDENT_MAX_POINTS)
|
|
226
|
-
start = max(lookback, ceiling)
|
|
238
|
+
end = min(end, latest + context)
|
|
239
|
+
start = end - budget
|
|
227
240
|
if first is not None:
|
|
228
241
|
start = max(start, first)
|
|
229
242
|
|
|
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
|
{detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-autotune/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-feedback/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.36.0 → detectkit-0.36.2}/detectkit/cli/assets/claude/skills/dtk-new-metric/SKILL.md
RENAMED
|
File without changes
|
{detectkit-0.36.0 → detectkit-0.36.2}/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
|
|
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
|