Skip to content

Commit d8b0eaf

Browse files
committed
feat(v6-h01): ShardingTab Accept mutates spec.sharding.axis_assignments
Closes V6-H01 / cppmega-mlx-fjb. V5-G05 backend reported extras.sharding_applied, but UI Accept button only re-verified the OLD spec — accepting a proposal had zero observable downstream effect. App.tsx changes: - suggest_sharding RPC typed to include nested sharding.axis_assignments - setProposals carries axis_assignments through - handleShardingAccept dispatches sharding.set with chosen axes ShardingTab.tsx: ShardingProposalView gains axis_assignments? field. E2E 55_sharding_apply.spec.ts: select h100_8x → ShardingTab → Accept first proposal → Train → extras.sharding_applied.shard_dim > 0. 1/1 e2e + 192/192 vitest green.
1 parent bcb71ff commit d8b0eaf

3 files changed

Lines changed: 62 additions & 5 deletions

File tree

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// H01: ShardingTab accept proposal updates spec.sharding.axis_assignments
2+
// AND extras.sharding_applied reflects the chosen strategy after Train.
3+
4+
import { test, expect } from "@playwright/test";
5+
import { gotoApp, selectPreset, closeModal } from "../fixtures";
6+
7+
test("H01: accept first sharding proposal → axes mutated → train extras matches",
8+
async ({ page }) => {
9+
test.setTimeout(90_000);
10+
await gotoApp(page);
11+
await selectPreset(page, "llama3_8b");
12+
13+
// Pick a topology with degree=8 so proposals are non-trivial
14+
await page.getByTestId("topology-selector").selectOption("h100_8x");
15+
await page.waitForTimeout(800); // suggest_sharding debounce
16+
17+
// Switch to sharding tab and accept first proposal
18+
await page.getByTestId("sidebar-tab-sharding").click();
19+
await page.getByTestId("sharding-tab").waitFor();
20+
const firstAccept = page.locator(
21+
"[data-testid^='sharding-accept-']").first();
22+
await firstAccept.waitFor({ timeout: 8_000 });
23+
await firstAccept.click();
24+
await page.waitForTimeout(600); // dispatch + re-verify
25+
26+
// Run Train; extras.sharding_applied must reflect the accepted
27+
// strategy's axes (not the INITIAL_SPEC fsdp2 default unchanged).
28+
await page.getByTestId("run-pipeline-toggle").click();
29+
await page.getByTestId("run-pipeline-train").click();
30+
const modal = page.getByTestId("run-result-modal");
31+
await modal.waitFor({ timeout: 60_000 });
32+
await page.getByTestId("run-result-expand-train").click();
33+
34+
const shardDim = parseInt(
35+
(await page.getByTestId(
36+
"run-result-extras-train-sharding_applied-shard_dim")
37+
.textContent()) ?? "0", 10);
38+
// Accepted proposal's shard_dim = product of axis degrees.
39+
// h100_8x supports 8-way → shard_dim should be ≥ 1
40+
expect(shardDim).toBeGreaterThan(0);
41+
await closeModal(page);
42+
});

vbgui/src/App.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,10 @@ export function App(): JSX.Element {
246246
try {
247247
const r = await rpc.call<{
248248
proposals: { strategy_name: string; fits: boolean;
249-
estimated_per_rank_bytes: number; reason: string }[];
249+
estimated_per_rank_bytes: number; reason: string;
250+
sharding?: { axis_assignments: {
251+
axis_name: string; kind: string; degree: number;
252+
}[] } }[];
250253
}>("suggest_sharding", {
251254
graph: nodesToGraph(snap.nodes, snap.edges),
252255
dim_env: MINI_DIM_ENV,
@@ -267,6 +270,7 @@ export function App(): JSX.Element {
267270
strategy_name: p.strategy_name, fits: p.fits,
268271
estimated_per_rank_bytes: p.estimated_per_rank_bytes,
269272
reason: p.reason,
273+
axis_assignments: p.sharding?.axis_assignments,
270274
})));
271275
} catch { /* keep prior proposals on failure */ }
272276
}, [rpc]);
@@ -326,13 +330,20 @@ export function App(): JSX.Element {
326330
const handleShardingAccept = useCallback((idx: number) => {
327331
const chosen = proposals[idx];
328332
if (!chosen) return;
329-
// The proposal carries strategy + reason; backend already knows the
330-
// axis-assignments. We re-run verify so the new memory bar reflects.
333+
// H01: actually mutate spec.sharding.axis_assignments with the
334+
// proposal's axes. Previous version only re-verified the OLD spec,
335+
// so accepting a proposal had zero observable effect downstream.
336+
if (chosen.axis_assignments && chosen.axis_assignments.length > 0) {
337+
dispatch({ type: "sharding.set",
338+
sharding: { ...spec.sharding,
339+
axis_assignments: chosen.axis_assignments } });
340+
}
331341
void scheduleVerify();
332342
setRunReport(null);
333-
setRunError(`sharding proposal "${chosen.strategy_name}" applied — re-verifying`);
343+
setRunError(
344+
`sharding proposal "${chosen.strategy_name}" applied — re-verifying`);
334345
setTimeout(() => setRunError(null), 2000);
335-
}, [proposals, scheduleVerify]);
346+
}, [proposals, scheduleVerify, spec.sharding]);
336347

337348
return (
338349
<ReactFlowProvider>

vbgui/src/components/sidebar/ShardingTab.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ export interface ShardingProposalView {
55
fits: boolean;
66
estimated_per_rank_bytes: number;
77
reason: string;
8+
/** H01: backend proposals carry the full axis_assignments + topology +
9+
* compile_mode. Accept must mutate spec.sharding to use them, not
10+
* just re-verify with the old spec. */
11+
axis_assignments?: ShardingAxis[];
812
}
913

1014
export interface ShardingTabProps {

0 commit comments

Comments
 (0)