Skip to content

feat(inference): distinguish certified vs legacy measured power with quick filter | 推理图表:区分已认证与旧版实测功耗并新增快捷筛选 - #907

Closed
edwingao28 wants to merge 5 commits into
masterfrom
klaud/powerx-02-certified-view
Closed

feat(inference): distinguish certified vs legacy measured power with quick filter | 推理图表:区分已认证与旧版实测功耗并新增快捷筛选#907
edwingao28 wants to merge 5 commits into
masterfrom
klaud/powerx-02-certified-view

Conversation

@edwingao28

@edwingao28 edwingao28 commented Aug 27, 2026

Copy link
Copy Markdown
Collaborator

Problem (Gap G2)

The nine "Measured Energy" y-axes plot two telemetry populations as one. The transform deliberately admits legacy rows with no producer verdict (power_valid absent) alongside rows aggregate_power.py explicitly validated (power_valid=1), with no visual or filterable distinction. In production the legacy population dominates ~10:1 (~1192 no-verdict rows vs ~130 validated), so the flagship measured-power story silently mixes unvalidated historical measurements with certified ones.

Tier rule

A per-entry power_tier is computed once in rowToAggDataEntry (single source of truth: resolvePowerTier in src/lib/power-tier.ts) and flows to every rendered point — official, overlay, and GPU-comparison — via the existing entry spread:

  • certifiedpower_valid === 1 and whole-deployment energy semantics hold (!disagg || power_metric_schema_version === 2). Non-disagg rows never had a semantics change on the unprefixed joules fields, so a producer verdict alone certifies them; disagg rows additionally need schema v2 — mirroring the field gating the transform already trusts.
  • legacy — measured telemetry renders but predates the validation contract: no verdict at all, or a disagg power_valid=1 row without schema v2.
  • absent — no measured telemetry survives gating (power_valid=0 rows included; the explicit invalid verdict stays authoritative).

Zero change to which values render — G2 is distinguish, not exclude. Rows lacking power_valid (and the future PLAN-06/07 fields power_invalid_reasons / power_audit) transform and render unchanged.

Surfaces

  1. Quick filter — new "Measured Power" category (EN/ZH) with Certified/Legacy pills; URL param i_power; identical semantics to the existing categories (empty = no constraint, values OR'd, categories AND'd); pills auto-disable when no matching data exists; wired into every count/clear path (dialog clear, plus the legend "Reset filter" on both the main chart and GPU-comparison graphs).
  2. Dotted ring on power_tier === 'legacy' points only while a Measured Energy axis is selected (official + overlay render paths), modeled on the KV-offload halo but nested outside it (POINT_SIZE + 7, 1 3 dasharray) so both can render on one point; localized footer legend key appears only when ringed points are on screen.
  3. Tooltip tier line — "Power Data: Certified (validated measurement)" / "Legacy (no validation verdict)" (EN/ZH) in all three tooltip generators, gated on measured axes.
  4. Axis explanations — the nine Measured Energy footer entries now state the tier distinction in both locales.

Default: filter OFF

Legacy rows outnumber certified ~10:1 today; defaulting to certified-only would empty most measured charts and vanish historical data. i_power defaults to '' (no constraint) in PARAM_DEFAULTS.

Follow-up (post PLAN-06 producer rollout): once single-node strict-v2 rows land at scale, flip the default by pre-seeding i_power=certified — this must land as a coordinated default change because PARAM_DEFAULTS strips values equal to their default from share links (see the DEFAULT_Y_AXIS_METRIC caveat in url-state.ts).

Note: the public API's powerValid=certified filter (PLAN-04) deliberately keeps the strict all-rows-v2 rule; the UI-vs-API divergence is documented on both sides and intentional.

Tests

  • bun run test:unit fully green (251 files / 4480 tests), including new coverage: table-driven resolvePowerTier, tier derivation through rowToAggDataEntry / transformBenchmarkRows, quick-filter matching/availability/parsing, MEASURED_ENERGY_METRIC_CONFIG_KEYS lockstep with the registry, per-axis ring rendering in the ScatterGraph harness, EN/ZH tooltip tier lines, and the i_power URL default. tsc --noEmit + oxlint + oxfmt green (lefthook pre-commit on every commit).
  • New e2e spec cypress/e2e/certified-power-filter.cy.ts uses deterministic intercepted fixtures (one certified config, one legacy) to assert the ring, legend key, pills, filtering, clear-filters reset, and i_power=certified share-link restore; registered in timings.json. Verified in CI: E2E chrome shard ran the spec 2/2 passing on this branch (run 33103582116); firefox shards green.
  • Cypress cannot run on the implementing machine (no Node.js runtime or repo-root .env), so the spec's legacy-power-rings / certified-only-filter screenshots are not embedded here — reproduce with cd packages/app && ./node_modules/.bin/cypress run --spec cypress/e2e/certified-power-filter.cy.ts on a node-equipped machine.

Review

Two independent review passes over the implementation:

  • Lens 1: approve, no findings.
  • Lens 2: approve-with-fixes, two findings:
    1. Major (fixed, aa2cbe9): the main chart legend's quick-filter badge count and "Reset filter" handler in ScatterGraph.tsx — a third copy of the pattern alongside QuickFiltersDialog and GPUGraph — omitted the new power category, so a Certified/Legacy selection was invisible in the legend badge and survived the legend reset. Fixed by mirroring the GPUGraph edit (quickFilters.power.length in the count, setQuickFilterPower([]) in the reset); full unit suite re-run green.
    2. Minor (dispositioned, not fixable locally): plan step 18 asked for cypress screenshots in this PR body. The implementing machine has no Node.js runtime and no repo-root .env, the e2e workflow uploads no screenshot artifacts, and GitHub's PR-body image upload has no public API — so the visual evidence cannot be attached from this environment. The spec's assertions (per-point .legacy-power-ring, legend-key visibility, pill filtering, i_power restore) are machine-verified green in CI; a maintainer with a node-equipped machine can run the spec above and drag the two screenshots into this body.

Rollback

Revert this PR. No migrations, no artifact-schema changes; i_power in old links degrades to an ignored param.

🤖 Generated with Claude Code

Wenyao Gao and others added 4 commits August 27, 2026 11:11
…filter | 推理图表:派生实测功耗认证层级并新增快捷筛选

Compute a per-entry power_tier ('certified' | 'legacy') in
rowToAggDataEntry from the producer verdict and whole-deployment energy
semantics, without changing which values render. Add a 'Measured Power'
quick-filter category (Certified/Legacy pills, i_power URL param) wired
through QuickFilters, InferenceContext, the dialog, and GPUGraph.

在 rowToAggDataEntry 中根据生产端验证结论与整体部署能耗语义派生
power_tier(certified/legacy),不改变任何渲染值。新增“实测功耗”
快捷筛选(已认证/旧版,URL 参数 i_power)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… axes | 推理图表:在实测能耗坐标轴上标记旧版功耗数据点

On the nine Measured Energy y-axes, draw a dotted ring around points
whose telemetry lacks a producer validation verdict (official and
overlay render paths), show a localized footer legend key when such
points are on screen, state the tier in all three tooltip generators
(EN/ZH), and append a tier note to the measured axis explanations.

在九个实测能耗 Y 轴上,为缺少生产端验证结论的数据点绘制虚线圆环
(官方与叠加渲染路径),当此类点可见时在图表底部显示本地化图例,
在三种工具提示中标注认证层级(中英文),并在实测指标说明中补充
层级说明。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…and tooltips | 测试:覆盖实测功耗层级派生、筛选、圆环与工具提示

Table-driven resolvePowerTier cases, tier derivation through
rowToAggDataEntry/transformBenchmarkRows, quick-filter matching and
availability, measured-energy key classification, decoration rendering
per axis, tier tooltip lines (EN/ZH), and the i_power URL default.

覆盖 resolvePowerTier 表驱动用例、转换层层级派生、快捷筛选匹配与
可用性、实测能耗指标判定、按坐标轴的圆环渲染、中英文工具提示层级
行以及 i_power URL 默认值。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…与旧版实测功耗筛选

Deterministic intercepted fixtures (one certified, one legacy config)
drive the measured-axis ring, footer legend key, Certified/Legacy quick
filter pills, clear-filters reset, and i_power share-link restore.

使用确定性的拦截数据(一个已认证、一个旧版配置)验证实测坐标轴
圆环、底部图例、已认证/旧版快捷筛选、清除筛选以及 i_power 分享
链接恢复。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@edwingao28
edwingao28 requested a review from adibarra as a code owner August 27, 2026 18:27
@vercel

vercel Bot commented Aug 27, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
inferencemax-app Ready Ready Preview Aug 27, 2026 6:52pm

Request Review

@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Claude finished @edwingao28's task in 5m 24s —— View job


Review: certified vs legacy measured power (PR #907)

  • Read core logic (power-tier, transform, quickFilters)
  • Read UI surfaces (ScatterGraph ring, legend, tooltips, context)
  • Check CI status (Unit ✅ / Lint ✅ / E2E in progress at review time)
  • Runtime verification via Playwright
  • Post findings

🟢 LGTM — no blocking issues found.

Static review. The tier is derived once in resolvePowerTier and threaded through the existing entry spread, so official / overlay / GPU-comparison paths all get power_tier for free. Logic checks out on the edge cases:

  • hasMeasuredTelemetry is computed from the 7 gated power/joules fields, which are exactly the sources behind all nine Measured Energy axes (Wh/queryJ/query, %TDPavg_power_w), so a rendered measured point can never end up tier-less.
  • power_valid === 0measuredPowerValid=false → fields scrubbed → tier undefined (no ring, unfilterable). Disagg power_valid=1 without schema-v2 → legacy. Non-disagg power_valid=1certified. All match the spec.
  • The ring is rendered on both the official (.dot-group.each) and overlay (overlayPoints.each) passes, uses the run-derived overlay stroke, .raise()d after precision swaps, and re-runs when isMeasuredEnergyAxis flips (added to the effect dep array). MEASURED_ENERGY_METRIC_CONFIG_KEYS is satisfies-checked and drives the control group, so the two can't drift.
  • Filter wiring (i_power param, parsePowerTiers, both clear paths, quickFiltersActive, availability) mirrors the existing categories; default stays ''.

Runtime (localhost, real DB — DeepSeek V4 Pro, Measured Avg Power axis):

  • Y-axis switch to a Measured Energy metric renders real data, 0 console errors.
  • Quick Filters shows the new Measured Power category with Certified / Legacy pills. On this date the data is certified-only, and the Legacy pill correctly auto-disables (disabled=true) while Certified stays enabled — verified .legacy-power-ring count = 0 and 25 .offload-halo (the dashed ring I first spotted on H200 was the KV-offload halo, not a legacy ring — the two decorations are correctly independent).
  • Clicking Certified narrows the visible point set as expected.
  • Legacy-ring / legend-key / share-restore behavior with actual legacy data is exercised by the new fixture-based e2e spec (certified-power-filter.cy.ts), since the current real DB slice for this model has no legacy rows to render.

Tests: comprehensive new coverage — power-tier.test.ts, transform tier derivation, quick-filter matching/availability/parsing, tooltip tier lines (EN/ZH), ScatterGraph decoration harness, i_power URL default, and the e2e spec.

Chinese copy: the new strings (功耗数据 / 已认证(通过验证的测量) / 旧版(无验证结论), 实测功耗, the axis-explanation note, dialog descriptions, legend key) are accurate and read naturally — no fidelity or register issues.
· branch klaud/powerx-02-certified-view

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3aba294. Configure here.

Comment thread packages/app/src/components/inference/ui/ScatterGraph.tsx
setQuickFilterFrameworks,
setQuickFilterDeployment,
setQuickFilterSpec,
setQuickFilterPower,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GPU chart missing power rings

Medium Severity

GPU comparison never draws the dotted legacy-power ring. ChartDisplay still shows LegacyPowerLegendKey whenever a Measured Energy axis has power_tier === 'legacy' points, including GPU comparison, so the footer advertises a ring that is not on the chart. Official and overlay scatter paths call renderLegacyPowerRing; GPUGraph only calls renderOffloadHalo.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3aba294. Configure here.

…ick-filter reset | 推理图表:图例快捷筛选计数与重置纳入实测功耗层级

ScatterGraph keeps its own copy of the quick-filter badge count and the
legend "Reset filter" handler; both omitted the new power category, so a
Certified/Legacy selection was invisible in the legend badge and
survived the reset click. Mirror the GPUGraph edit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Claude finished @edwingao28's task in 2m 50s —— View job


Re-review: certified vs legacy measured power (PR #907)

Re-review since the prior LGTM. I focused on the two Cursor Bugbot findings (which were against the older commit 3aba2942) plus the latest commit aa2cbe9b.

Bugbot #1 — ScatterGraph reset omits power filter → ✅ already fixed. Commit aa2cbe9b added quickFilters.power.length to quickFilterCount (ScatterGraph.tsx:1077) and setQuickFilterPower([]) to clearQuickFilters (ScatterGraph.tsx:1084). Both the count badge and the legend Reset path now cover the power tier. No action needed.

Bugbot #2 — GPU chart missing power rings → 🟡 confirmed real (still open). ChartDisplay.tsx:886-888 computes hasLegacyPowerPoints with no GPU-comparison carve-out, so LegacyPowerLegendKey renders in comparison mode, but GPUGraph.tsx's .dot-group.each pass only calls renderOffloadHalo — never renderLegacyPowerRing. Since measured-energy y-axes aren't filtered out of the selector in comparison mode and legacy points dominate ~10:1, the footer can advertise a dotted ring that appears on no point. Left an inline comment with a concrete fix (draw the ring in GPUGraph, mirroring the offload halo already rendered there). Not a crash — a visual/legend inconsistency — hence 🟡, not blocking.

CI: Lint ✅, Unit ✅, Code Quality ✅; E2E in progress at review time.

Chinese copy: no new/changed user-visible Chinese strings since the prior review that covered them; nothing further to flag.

The rest of the PR (tier derivation in resolvePowerTier, the entry-spread threading, filter wiring, tooltips, axis explanations) looked correct in the prior review and is unchanged. Recommend addressing #2 for GPU-comparison parity before merge.
· branch klaud/powerx-02-certified-view

hasOffloadHalo || hasLegacyPowerPoints || isAgenticSequence || hasAtomSeries ? (
<>
{hasOffloadHalo && <OffloadHaloLegendKey />}
{hasLegacyPowerPoints && <LegacyPowerLegendKey />}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 WARNING: GPU comparison advertises a legacy-power ring it never draws.

Why it matters: hasLegacyPowerPoints (886-888) is isMeasuredEnergyConfigKey(selectedYAxisMetric) && footerPoints.some(p => p.power_tier === 'legacy') with no GPU-comparison carve-out, so this LegacyPowerLegendKey renders in comparison mode too. But GPUGraph.tsx's .dot-group.each onRender pass (around lines 907-911) only calls renderOffloadHalo — it never calls renderLegacyPowerRing like the official/overlay scatter paths (ScatterGraph.tsx:2624,3015). Measured-energy y-axes aren't filtered out of the selector in comparison mode, and legacy points dominate ~10:1 per the PR description, so a user comparing GPUs on a Measured Energy axis sees this footer key ("dotted ring = legacy") with no ring on any point. The offload halo doesn't have this problem because GPUGraph does render it in that same pass.

Fix: render the ring in GPUGraph.tsx alongside the halo, gated on the measured-energy axis (mirroring the scatter path) — add to the .dot-group.each callback:

renderLegacyPowerRing(
  d3.select(this),
  point,
  isMeasuredEnergyConfigKey(selectedYAxisMetric),
  'var(--foreground)',
);

plus the renderLegacyPowerRing / isMeasuredEnergyConfigKey imports. Marking the points matches the intent and the offload halo already drawn there; alternatively gate this key out of GPU comparison. Fix this →

@edwingao28

Copy link
Copy Markdown
Collaborator Author

Superseded by #934 (branch renamed to feat/measured-power-tiering); identical diff.

@edwingao28 edwingao28 closed this Aug 28, 2026
@edwingao28
edwingao28 deleted the klaud/powerx-02-certified-view branch August 28, 2026 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant