Skip to content

Commit f45c8ea

Browse files
cquil11claude
andcommitted
Merge branch 'master' into feat/agentx
Brings in the unofficial-run agentic artifact fallback (#537) and latest master. 中文:合并 master 分支,引入非官方 run 的 agentic 产物回退(#537)及 master 最新改动。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2 parents 4749b70 + a1bedeb commit f45c8ea

15 files changed

Lines changed: 570 additions & 137 deletions

File tree

.github/workflows/tests-e2e.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ jobs:
5858
fail-fast: false
5959
matrix:
6060
browser: [chrome, firefox]
61-
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
61+
# Cap at four shards per browser. Every shard repeats checkout, dependency
62+
# installation, Cypress setup, and a full app build; beyond four, that
63+
# duplicated fixed cost dominates and yields sharply diminishing returns.
64+
shard: [1, 2, 3, 4]
6265
steps:
6366
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
6467
- uses: pnpm/action-setup@0ebf47130e4866e96fce0953f49152a61190b271 # v6.0.9
@@ -117,11 +120,11 @@ jobs:
117120
CI: true
118121
E2E_FIXTURES: '1'
119122
# cypress-split picks the subset of specs for this shard.
120-
# SPLIT_INDEX1 is 1-based to match matrix.shard values [1..16].
123+
# SPLIT_INDEX1 is 1-based to match matrix.shard values [1..4].
121124
# SPLIT_FILE seeds the balance from observed timings;
122125
# SPLIT_OUTPUT_FILE redirects on-disk updates to a throwaway path
123126
# so CI never tries to mutate the committed timings.json.
124-
SPLIT: 16
127+
SPLIT: 4
125128
SPLIT_INDEX1: ${{ matrix.shard }}
126129
SPLIT_FILE: timings.json
127130
SPLIT_OUTPUT_FILE: /tmp/cypress-split-out.json

docs/d3-charts.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,11 @@ These exist because multiple chart types (scatter, GPU, bar) all need the same t
109109
## Dynamic Left Margin Measurement
110110

111111
D3 bar charts measure actual Y-axis label widths using a temporary SVG `<text>` element before rendering. Hardcoded margins truncate labels when GPU names get long (e.g., "GB200 NVL72 (Dynamo TRT, MTP) (FP4)"). The formula `max(80, ceil(measuredWidth * 0.6) + 12)` ensures labels always fit while maintaining a minimum margin for short labels.
112+
113+
## One Animation System per Property
114+
115+
Opacity animates via inline CSS `transition: opacity 150ms ease` (set on dots, rooflines, and labels in the render path); d3 `.transition()` is reserved for attributes CSS can't animate — the `data-update` entrance transitions on dot `transform` and roofline `d`. Never point both systems at the same property: a d3 transition re-writes the style every animation frame, and each write restarts the CSS transition, emitting `transitionrun`/`transitioncancel` per node per frame (a legend hover across a full chart used to produce tens of thousands of events per session, all of it also observed by PostHog's session-replay MutationObserver). Handlers like legend hover therefore write opacity **once** and let CSS do the animation.
116+
117+
## Batched Label Measurement
118+
119+
Label loops that size a background rect to its text (`.ll-bg`/`.pl-bg`, point-label collision avoidance) must not interleave `getBBox()` with DOM writes — each read after a write forces a synchronous layout, turning N labels into N reflows. The pattern is two passes over the selection: write every label's text first, then measure every bbox (one forced layout for the whole batch), then write the rects. Same rule for `measureLegendRightInset`: it reads `getBoundingClientRect`, so it's skipped entirely when there are no known-issue annotations to place — it would otherwise run on every zoom frame.

packages/app/cypress/e2e/dropdown-switching.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ describe('Dropdown one-click switching', () => {
4949

5050
cy.contains('Maintenance Mode').scrollIntoView().should('be.visible');
5151
cy.contains('[role="option"]', 'DeepSeek R1 0528 671B').scrollIntoView().should('be.visible');
52-
cy.contains('[role="option"]', 'gpt-oss 120B').scrollIntoView().should('be.visible');
5352
cy.contains('Deprecated').scrollIntoView().should('be.visible');
53+
cy.contains('[role="option"]', 'gpt-oss 120B').scrollIntoView().should('be.visible');
5454
cy.contains('[role="option"]', 'Llama 3.3 70B Instruct').scrollIntoView().should('be.visible');
5555
});
5656

packages/app/next.config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const nextConfig: NextConfig = {
1414
serverExternalPackages: ['shiki'],
1515
experimental: {
1616
optimizePackageImports: ['lucide-react', 'd3', '@tanstack/react-query'],
17+
// NOTE: experimental.inlineCss was evaluated (2026-07) for the PageSpeed
18+
// "Render-blocking requests" insight and rejected: it embeds the full CSS
19+
// text in every route's RSC payload (~46 KiB gz, duplicated 2×), so every
20+
// client-side tab navigation re-downloads CSS that is otherwise a
21+
// one-time immutable fetch. Net regression for this SPA-heavy dashboard.
1722
// Persist Turbopack's compiler cache under .next/cache in GitHub Actions
1823
// so the workflow cache step makes warm builds fast. Gated on
1924
// GITHUB_ACTIONS (not CI, which Vercel also sets) to keep the
2.85 KB
Loading
Lines changed: 20 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)