feat(advisor): capacity forecast + TTL advisor tools, recommend-only (plan 50) by duyet · Pull Request #2222 · chmonitor/chmonitor · GitHub
Skip to content

feat(advisor): capacity forecast + TTL advisor tools, recommend-only (plan 50) - #2222

Merged
duyet merged 3 commits into
mainfrom
advisor/50-capacity-forecast-ttl-advisor
Jul 3, 2026
Merged

feat(advisor): capacity forecast + TTL advisor tools, recommend-only (plan 50)#2222
duyet merged 3 commits into
mainfrom
advisor/50-capacity-forecast-ttl-advisor

Conversation

@duyet

@duyet duyet commented Jul 3, 2026

Copy link
Copy Markdown
Member

Summary

Implements plan 50 (Round-3 Wave AI). Two read-only agent tools: forecast_disk_capacity (OLS growth fit over system.part_log NewPart bytes → days-to-full + date) and suggest_ttl_adjustment (steady-state TTL solve, capped at the retention floor). Tool-count docs synced (22→24 tools; 12 modules).

Safety (recommend-only — never executes)

TTL output is a suggestion string (ALTER TABLE … MODIFY TTL …) + risk note; suggestTtl never calls writeQuery. Never suggests a TTL below the stated retention (proven by a 500-iteration fuzz test). system.part_log absent → clear "enable part_log" message, never a fabricated forecast.

Verification

bun test src/lib/ai/advisor 25 pass · bun test src/lib/ai/agent/tools 104 pass (incl. registry-safety of the dynamic-imported tools) · lint ✅. type-check/tsc-test clean for the plan's files (only pre-existing env errors remain).

Robustness fix (found in review)

Capped forecast horizon at 100 years — a near-zero-but-positive growth rate against large free space drove daysToFull into the billions and new Date().toISOString() threw RangeError; reproduced + regression-tested.

Co-Authored-By: duyetbot bot@duyet.net

duyet and others added 3 commits July 3, 2026 15:44
Add forecast_disk_capacity and suggest_ttl_adjustment agent tools that
project disk-full dates and recommend TTL/retention changes from
system.part_log NewPart write volume. Recommend-only: suggest_ttl_adjustment
returns a suggestion string (ALTER TABLE ... MODIFY TTL ...) plus a risk
note, never executes it, and never suggests a TTL below the caller's
stated retention floor — provably so, via a randomized fuzz test over the
pure TTL-solve function.

- lib/ai/advisor/capacity-forecaster.ts: pure fitLinearGrowth (OLS on the
  cumulative NewPart byte series) + growthConfidence (daily-rate
  dispersion, not the cumulative fit's R^2, which is near-1 even for
  bursty ingestion) + computeTtlSuggestion (steady-state TTL solve capped
  at the retention floor), plus ClickHouse-backed forecastDiskFull /
  identifyHotTables / suggestTtl orchestration. Gates on system.part_log
  via the existing checkTableExists helper and returns a clear
  "enable part_log" message instead of a fabricated forecast when it's
  disabled.
- storage-tools.ts: wires the two tools in, dynamic-importing
  capacity-forecaster.ts inside execute() to keep the tools/index.ts
  registry import graph side-effect-free.
- Doc/tool-count sync (CLAUDE.md x2, ai-agent.mdx, capabilities.mdx,
  tool-docs-sync.test.ts): 22 -> 24 tools (19 -> 21 default).

Co-Authored-By: duyetbot <bot@duyet.net>
…te overflow

forecastDiskFull computed daysToFull = freeBytes / dailyGrowthBytes with no
upper bound, then built Date.now() + daysToFull * MS_PER_DAY. A tiny-but-
positive growth rate against a large free space (e.g. ~100 bytes/day
against 1 TB free) pushes daysToFull into the billions, which overflows
JS's representable date range and throws a RangeError out of
toISOString() — the tool would crash instead of returning a forecast.
The same unbounded division made suggestTtl's computeTtlSuggestion capable
of emitting an absurd `INTERVAL <huge number> DAY` suggestion.

Cap both at MAX_MEANINGFUL_FORECAST_DAYS (100 years) and collapse into the
existing null/"not growing" branch beyond that — functionally equivalent
to no near-term risk, and far below any real capacity-planning horizon.
Added a regression test reproducing the exact crash scenario plus a fuzz
case in computeTtlSuggestion's randomized test.

Co-Authored-By: duyetbot <bot@duyet.net>
buildDailySeries keys days in UTC while ClickHouse's toDate(event_time)
buckets in the server's configured timezone. On a non-UTC server this can
misalign the oldest/newest bucket by a day (falls back to 0 — a minor
growth undercount, not a crash or correctness hazard over a 30-day window).
Documenting it so it isn't rediscovered as a surprise later.

Co-Authored-By: duyetbot <bot@duyet.net>
@duyet
duyet enabled auto-merge (squash) July 3, 2026 08:55
@github-actions github-actions Bot added documentation Improvements or additions to documentation app: dashboard Changes to the apps/dashboard TanStack Start app labels Jul 3, 2026
@codecov

codecov Bot commented Jul 3, 2026

Copy link
Copy Markdown

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

☁️ Cloudflare Preview Deployment

App Preview URL
Dashboard https://preview.dash.chmonitor.dev
MCP https://preview.dash.chmonitor.dev/api/mcp
Landing https://preview.chmonitor.dev
Docs https://preview.docs.chmonitor.dev
Property Value
Commit 5b7cd11
Deployed at 2026-07-03T08:58:15.905Z

Previews are automatically updated on every push to this PR.
Unchanged apps keep their previous preview (path-filtered deploys).

@duyet
duyet merged commit 0af61a8 into main Jul 3, 2026
21 checks passed
@duyet
duyet deleted the advisor/50-capacity-forecast-ttl-advisor branch July 3, 2026 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

app: dashboard Changes to the apps/dashboard TanStack Start app documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant