Skip to content

FE-1583: Run the connected optimizer's trials through the experiments backend - #9516

Draft
kube wants to merge 7 commits into
claude/web-optimizer-core-runtimefrom
claude/web-optimizer-react-channel
Draft

FE-1583: Run the connected optimizer's trials through the experiments backend#9516
kube wants to merge 7 commits into
claude/web-optimizer-core-runtimefrom
claude/web-optimizer-react-channel

Conversation

@kube

@kube kube commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Important

Experimental
Behind the In-browser optimization feature flag.

Summary

Before this PR, PetrinautOptimizationContext accepted a self-contained remote capability, and a study's trials were numbers in a table. Study drawer's Surface could sample the objective locally, but it knew nothing of where the optimizer was looking, and the optimizer could not use the browser's compute at all.

This PR lets the context carry a connected optimization source and runs its trials through the experiments layer. A new runDetachedObjective action runs a frozen study's objective at one parameter point on the chosen backend with pinned seeds and streams its frames. Optimizations provider evaluates each trial through it, follows the trial in the navigator, streams its metrics live, and after the study settles refines the best point, or whichever point the user picks. Study drawer shows the optimizer's own steps as dots on the Surface with the field filling in as steps report, a Stop that keeps the study and a Continue that adds steps to it, up to four steps in flight with an activity list, and one metric line always in view. Form gains Runs per step, Parallel steps and the experiments' Backend switch. A remote capability such as the HASH host's NodeAPI bridge is unaffected, and the connected source only takes effect with the experimental setting on.

9516.mp4

Links

Changes

Feature flag

  • New experimental setting In-browser optimization under Settings > Simulation

    Row shows only when the host supplies a connected optimizer.

  • useOptimizationSource is the one place that reads the context and the setting

    A remote capability passes through as is.
    A connected source passes through only with the setting on, else the tab stays hidden and nothing connects; turning it off cancels connected runs and disposes.

Experiments layer

  • runDetachedObjective runs a study's objective at one point and streams it

    Compiles once per study, chooses the backend once per study and backend with the experiments' registrations at a third of the CPU pool, pins per-run seeds on the CPU pool only, streams frames and progress.
    Settles with per-run results or a reason: compile diagnostics, backend refusals, failed runs, cancellation.

  • Runs queue per queueKey while sharing one compiled snapshot per cacheKey

    Parallel steps of one study overlap on the backend; refinement rungs of one point stay in order.

  • A cancelled run settles instead of hanging its queue

    Instantiation gets its own abort controller, mirrored from the run signal only until the backend handle exists.
    A later cancel goes through the handle, whose cancelled event releases the queue to the next run.

  • Sweep throttle moves to experiments/shared for reuse

Optimization channel and provider

  • Channel evaluates a trial as one detached objective run with the trial's seeds and the study's backend

    Objective is the mean of the per-run finals when the backend reports them, else the last frames' value; a failure prunes the trial with its reason; the channel never throws.

  • Records carry computeBackend, its fallback reason, the study's axes, parallelism, resumable, a navigation, a selection stream, inFlight steps and an activity list

    Navigation follows the most recently started step; a user move stops following.
    Selection stream carries the followed step's frames, then the refined point's.

  • Study settles on its best point when it completes or stops

    Navigation moves to the best step while it still follows, and refinement starts there.

  • Point refinement climbs the run ladder to 100 runs for the navigated point

    Starts when the study settles or the user moves, cancels and restarts on a navigation change, caches per point, stops with the reason on failure.
    Between rungs it compares the point's estimate with the best: a point that cannot beat the best by 2.5 standard errors stops after its first rung with the note "8 runs · cannot beat the best"; the best point refines fully.

  • extendOptimization(id, steps) continues a finished or stopped connected study

    Provider calls extendOptimizationRun, re-attaches from the record's cursor, turns following back on; the steps continue Optuna's numbering.
    Stop keeps the attachment so the segment's terminal event lands and marks the record resumable.

  • Removing a connected record releases its study in the worker
  • Connected runs are not written to session storage since they cannot outlive the page

Form and drawer

  • Create form gains Runs per step, Parallel steps, Seed and the Backend switch

    Runs per step lands in execution.seedsPerTrial; the total-steps rule multiplies by it.
    Parallel steps is 1 to 4 and shows for a connected source only.
    Seed starts at a fresh random value each time the form opens and seeds both the proposals and the runs; every study used to share one fixed seed, so two studies drew the same random steps.
    Backend cell is the experiments' shared toggle, shown for a connected source with WebGPU on; it stays disabled with the reason because the GPU backend cannot compute an expression objective.

  • Connected study drawer lays everything out to fit one screen

    A summary strip carries status, finished over requested steps, best value, the backend badge, the steps bar and the "N computing" chip.
    Parameters band holds a slider per axis, Follow steps and the refinement status.
    Surface sits beside the objective chart, the Steps table fills the rest, and the footer holds Stop, or Remove and Continue with a step count.

  • Surface shows the optimizer's steps only

    Each step with an objective is one sample of the field at its projected position and a dot, the best emphasized, pruned steps hollow.
    A step in flight enters the field with its running value, and so does the refined point after settle, so the plot fills in as the study streams.
    While a running study is followed the plot and the sliders are display-only; once the study is terminal, or Follow steps is off, a click or drag commits the navigation.

  • Remote study drawer keeps its locally sampled Surface and its Cancel
  • Shared pieces move to SimulateView/shared: useGpuAvailability, ComputeBackendToggle, ComputeBackendBadge, MetricTiles, ComputeActivity, SummaryStrip
  • Slider in @hashintel/ds-components accepts disabled

Stories and example

  • Storybook Simulate / Browser optimizer (real) runs the real Pyodide optimizer against the real experiments backends

    SirCpu, SirGpuRequested, SupplyChain, VaccinationCampaign start a study on load; Manual opens the create form.
    Shared harness simulate-view-story-harness.tsx with AutoStudy; the synthetic-optimizer story is renamed RunSupplyChainOptimizationSyntheticOptimizer.

  • New core example Vaccination Campaign built for optimization demos

    SIR with pre-wave vaccination coverage and contact reduction, a Total cost objective whose minimum lies inside the domain, GPU-eligible; listed under Load example.

Known issues

  • GPU studies are unreachable from the form until the WebGPU backend computes expression metrics

    Record, channel and registrations already carry the choice.

Test coverage

  • provider/detached-objective.test.ts:

    Streaming, pinned seeds on the CPU and none on the GPU, fallback re-pinning, failure reasons for refusal, errored runs and compile errors, one walk per study and backend, per-key queueing, a cancelled batch settling and releasing the queue, distinct queue keys side by side, cancel and dispose.

  • optimizations/provider.test.tsx, provider/connected-study.test.ts, provider/point-refinement.test.ts, provider/point-refinement/objective-estimate.test.ts, provider/activity-registry.test.ts, channel/create-optimization-channel.test.ts:

    Setting gate on, off and toggled, remote unaffected, trials through runDetachedObjective with seeds and backend, following and user moves, settle on the best, the ladder and its early stop, restart on navigation change, stop then continue from the cursor, refused continuation, removal releasing the study, activity throttling.

  • create-optimization-drawer.test.tsx, view-optimization-drawer.test.tsx, study-summary-strip.test.ts, steps-table.test.ts, optimization-navigator.test.tsx, optimization-surface/surface-plot.test.tsx, simulate-view.test.tsx, viewport-settings-dialog.test.tsx:

    Runs per step, parallel steps, the typed seed and its limit, the backend option, Stop, Stopped and Continue, progress bars and the computing chip, the note on a refused point, trials-only field and provisional samples, display-only while following, tab gating, default off.

  • examples/vaccination-campaign.test.ts, webgpu/compilation-report.test.ts:

    GPU eligibility and readiness of the example, its default marking, and a seeded check that the cost at the valley is below the domain's boundary points.

  • Storybook DOM probes and screenshots:

    SirCpu streaming, Stop at step 2 then Continue +4 to Complete 6 / 6, a hopeless pick stopping after 8 runs, the best point climbing to 100 runs.

How to test

  • yarn workspace @hashintel/petrinaut dev
  • Simulate > Browser optimizer (real) > SirCpu

    Expect the runtime to download once, then steps as dots on the Surface, the field filling in, the metric line streaming

  • Stop

    Expect Stopped, the navigation on the best step, refinement to 100 runs

  • Continue

    Expect steps resuming with continued numbering, then Complete

  • Click a corner of the Surface

    Expect "0 of 8 runs — refining" then "8 runs · cannot beat the best"

  • Click next to the best dot

    Expect refinement climbing to 100 runs and the metric line restreaming

  • Simulate > Browser optimizer (real) > VaccinationCampaign

    Expect a valley on the Surface with the best dot on its floor

  • Simulate > ViewOptimizationDrawer stories

    Expect the running, complete, stopped, fallback and remote variants to render

@vercel

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated
hash Ready Ready Preview Sep 4, 2026 12:39pm UTC
petrinaut Ready Ready Preview Sep 4, 2026 12:39pm UTC
petrinaut-docs Ready Ready Preview Sep 4, 2026 12:39pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
hashdotdesign-tokens Ignored Ignored Preview Sep 4, 2026 12:39pm UTC

Request Review

@github-actions github-actions Bot added area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team area/apps > hash.design Affects the `hash.design` design site (app) labels Sep 3, 2026
@kube kube self-assigned this Sep 3, 2026
@kube
kube force-pushed the claude/web-optimizer-react-channel branch from 06f4f63 to 9dfc3eb Compare September 3, 2026 00:33
@kube
kube force-pushed the claude/web-optimizer-react-channel branch 2 times, most recently from fe9bfc0 to 2f1fd14 Compare September 3, 2026 05:40
@kube
kube force-pushed the claude/web-optimizer-react-channel branch from 2f1fd14 to dc659ba Compare September 3, 2026 22:00
@kube
kube force-pushed the claude/web-optimizer-react-channel branch from dc659ba to fc5cf7b Compare September 3, 2026 22:23
* reproducible through the field while making studies differ by default.
*/
export const randomOptimizationSeed = (): number =>
Math.floor(Math.random() * (PETRINAUT_OPTIMIZATION_MAX_SEED + 1));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/apps > hash.design Affects the `hash.design` design site (app) area/infra Relates to version control, CI, CD or IaC (area) area/libs Relates to first-party libraries/crates/packages (area) type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

2 participants