feat(mcp): add clickstack_emerging_signals tool (+7% on service-health-check)#2701
feat(mcp): add clickstack_emerging_signals tool (+7% on service-health-check)#2701brandon-pereira wants to merge 7 commits into
Conversation
Add a two-window Drain pattern novelty detector that set-differences mined log/event patterns between an earlier baseline window and a current window to surface what is newly emerging or has disappeared. The existing event_patterns tool mines one window and event_deltas compares attribute-value distributions within a shared population; neither can answer 'what is present now that was not before?' A brand-new log template has no baseline distribution to shift, so it is invisible to event_deltas. emerging_signals fills that gap. Extract mineWindowPatterns() from runEventPatterns so the single-window tool and the two-window tool share an identical sample-and-mine pipeline, and add normalizeTemplate() to key Drain templates across windows (placeholder glyph unified, whitespace collapsed, case-folded) since Drain assigns fresh cluster ids each run.
🦋 Changeset detectedLatest commit: 1362bb5 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🔴 Tier 4 — CriticalTouches auth, data models, config, tasks, OTel pipeline, ClickHouse, or CI/CD. Why this tier:
Additional context: agent branch ( Review process: Deep review from a domain expert. Synchronous walkthrough may be required. Stats
|
Greptile SummaryThis PR adds a new MCP tool for comparing event patterns across two time windows. The main changes are:
Confidence Score: 5/5This looks safe to merge.
Important Files Changed
Reviews (7): Last reviewed commit: "fix(mcp): require directional change in ..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 243 passed • 1 skipped • 1058s
Tests ran across 4 shards in parallel. |
Deep Review✅ No critical issues found. The new 🟡 P2 -- recommended
🔵 P3 nitpicks (4)
Reviewers (3): correctness, adversarial, testing. Testing gaps: |
Covers schema serialization (tools/list), both validation paths (overlapping windows + inverted current window), and the core algorithm against ClickHouse: a brand-new log template absent from baseline surfaces as an emerging "new" signal, a template common to both windows does not, and two same-pattern windows report nothing novel.
… P1) The emerging/disappeared ratio checks added an epsilon to the divisor (curShare / (baseShare + EPS) >= ratio), which always nudged the ratio below the threshold and could suppress a genuine >=ratio× shift. Extract the qualification into a pure classifyShift() and compare via cross-multiplication (curShare >= ratio * baseShare) — no epsilon, no division, no divide-by-zero guard needed. Add a unit test covering the brand-new floor, emerging/disappeared thresholds, and the previously suppressed clean-shift case.
The integration test cast JSON.parse output via `as Array<{...}>`, tripping
@typescript-eslint/no-unsafe-type-assertion 3× and pushing the api package
one warning over its --max-warnings cap. Assign to a typed const instead,
which reads off the any-typed parse result without an assertion.
…tile) Cross-multiplication alone still dropped a mathematically-exact ratio× shift at some sample sizes: at a 10k sample, 3*(1/10000) rounds just above 3/10000, so a genuine 1->3 row shift fell under the threshold. Add a tiny relative tolerance (1e-9) biased toward qualifying so the exact boundary is admitted while anything meaningfully below (2.9x) is still rejected. Unit tests cover the exact-3x emerging and disappeared cases at a 10k sample plus a just-under-threshold negative case.
At minShareRatio=1 (schema-allowed), the relative tolerance made a stable equal-share pattern satisfy curShare >= ratio*baseShare*tol and get reported as emerging, flooding the novelty report with steady-state templates. Require a real increase (curShare > baseShare) for emerging and a real decrease (baseShare > curShare) for disappeared, in addition to the ratio threshold. Add unit tests for the ratio=1 stable and ratio=1 genuine-increase cases.
What
Adds a ClickStack MCP tool,
clickstack_emerging_signals— a two-window Drain pattern novelty detector. It mines log/event patterns in a baseline window and a current window and set-differences them:"new") or>= minShareRatio×more frequent (default 3×)"gone"/"shifted")It answers "what is new or gone?" — which the existing tools structurally can't.
Why
clickstack_event_patternsclickstack_event_deltasclickstack_emerging_signals(new)event_deltascompares value distributions within a shared population, so it can't surface a brand-new log template (a feature-flag line that started an hour ago has no baseline distribution to shift — it just appears). The two are complementary: "what's different about these rows" vs "what's new since then".How
Runs the
event_patternssample-and-mine pipeline twice (once per window) and set-differences the result:<*>unified, whitespace collapsed, lower-cased), since Drain assigns fresh cluster ids each run.Calibration:
minShareRatio(default 3×) ignores routine volume wobble; an emptyemerginglist is a valid "nothing novel" answer, and the tool is told not to fabricate findings.Eval results
Dual-slot A/B vs
main, identical seeded data (seed 42, same anchor), Opus judge (averaged over n=3 and n=5 runs).Win —
service-health-check, the scenario that exercises novelty detection:Driven by
notes_new_log_pattern: 67% branch vs 0% main (main missed the planted new log template every run). Matches an earlier controlled measure: agent surfaced the signal in 0/10 runs without the tool, 8/10 with it.No effect elsewhere. The other scenarios don't exercise novelty detection, and their deltas average to noise — no regressions:
(These scenarios swing 20–40 pts per run, so small deltas are variance, not signal.)
Testing
tsc/eslint/knipclean on the feature files. Changeset included (@hyperdx/apiminor).