Skip to content

FE-1690: Toggle optimization from the experiment creation form - #9689

Merged
kube merged 7 commits into
mainfrom
claude/opt-proto-optimize-toggle
Sep 13, 2026
Merged

kube merged 7 commits into
mainfrom
claude/opt-proto-optimize-toggle

Conversation

@kube

@kube kube commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Important

Experimental
Behind the Parameter sweeps and In-browser optimization feature flags.

Summary

Before this PR, optimizing a sweep took two steps. The Create Experiment drawer offered a Sweep toggle on each numeric value and created an idle sweep; the optimizer started later from a purple Optimize button on the sweep's Parameters card, which asked for the metric, the direction and the step count in a popover, and a sweep could be optimized again and again into one strip.

This PR starts the study with the experiment. Where the in-browser optimizer can drive the sweep, the interval toggle reads Optimize instead of Sweep; the first toggle adds an Objective section to the drawer, metric over the experiment's metric drafts, Maximize or Minimize, and the number of steps, with a helper line that pre-checks the optimizer's step budgets. The footer reads Optimize, and submit is one gesture: create the experiment, start the study, then select it, so the results drawer opens already driving with the Parameters card purple, the headline counting steps and the cards and table mounted. A study that cannot start removes the experiment again and names the reason in the footer. The Parameters card keeps only Stop while a study drives; one experiment carries one study, and a new search is a new experiment. Without the optimizer the toggle still reads Sweep and the sweep opens idle as before.

9689.mp4

Links

Changes

Create Experiment drawer

  • The interval toggle reads Optimize where the optimizer can drive the sweep

    Parameter sweeps and In-browser optimization on with an optimizer that runs in the browser gives Optimize; Parameter sweeps alone, or a remote-only optimizer, keeps Sweep. The word never depends on how many toggles are on.
    Min and Max cells are the whole interval editor; the Step and Scale cells and the boolean two-way choice are deleted.

  • Objective section

    Appears with the first Optimize toggle, between Scenario and Constraints. Metric over the drawer's metric drafts, Maximize or Minimize, Steps with a default of 30.
    A reserved helper line reads the plan or names the budget the optimizer would refuse, mirrored from the core's step limits.
    While an ad-hoc bound fails to synthesize the section stays mounted, the footer keeps Optimize disabled and the summary line carries the error, so the drawer does not change shape mid-edit.

  • Submit creates, starts and selects in that order

    createExperiment resolves the record and no longer selects it; the drawer starts the study through createOptimization and selects afterwards, so the results drawer mounts with the study in place.
    A failed start removes the experiment, keeps every field and puts the reason in the footer.

  • Ad-hoc experiments optimize too

    The manifest is built from the record's compiled scenario; every generated parameter is an axis. Constraints stay saved-scenario only.

Results drawer

  • Stop is the only card control

    The Optimize button, its popover and the multi-study strip machinery are deleted; the strip and the cards read one study.

  • The drawer opens in the driving state for an Optimize-created experiment

    Every study slot renders at initializing, so the shape never changes afterwards; a Sweep-created experiment opens idle as before.

Public API

  • createExperiment resolves with the ExperimentRecord, which carries the scenario it compiled

    ExperimentRecord.scenario is a new required field; callers select the experiment themselves. Patch changeset for @hashintel/petrinaut.

Known issues

  • No Optimize again on an experiment

    A stopped or finished study cannot be restarted; a new search is a new experiment. Bringing it back needs the objective on the record and the multi-study strip.

  • Sweep-only exploration with both flags on

    Press Stop right after the drawer opens, or turn In-browser optimization off to get the Sweep word back.

  • The Surface pickers stay read-only while the study drives

    Unchanged behaviour, more visible now that every Optimize-created experiment opens driving.

Test coverage

  • create-experiment.test.ts, provider.test.tsx, context.test.ts:

    The record carries its compiled scenario, creation resolves the record without selecting it, no await sits before the sweep session starts.

  • ad-hoc-scenario-form.test.tsx, experiment-scenario-run.test.tsx:

    Interval selection under both words, numeric values only, Min and Max as the whole editor, gutter labels following the word.

  • sweep-objective.test.ts, objective-section.test.tsx, create-optimized-experiment.test.tsx, sweep-optimizer.test.ts:

    Metric resolution and fallback, the step budgets, create then start then select with rollback, the manifest for saved and ad-hoc records.

  • create-experiment-drawer.test.tsx, ad-hoc-interval-toggles.test.ts:

    The word per settings and source, the Objective section's gating and defaults, the footer label and budget error, submit reaching the fake optimizer, a failed start keeping the drawer open, a failing ad-hoc bound keeping the section and the word.

  • experiment-results.test.tsx, view-experiment-drawer.test.tsx, sweep-objective-history.test.ts:

    Stop only while driving, the layout signature across study states, the single-study strip.

How to test

  • Open Petrinaut preview on Vercel
  • Viewport controls > Settings > Simulation > Parameter sweeps on, In-browser optimization on
  • Menu > Load example > SIR Epidemic Model
  • Switch to Simulate
  • Experiments > Create
    • Scenario > Seasonal Flu
    • Flip Optimize on infected_ratio

      Expect an Objective section with Metric, Direction and Steps, and the Constraints section under it

    • Add a metric on Infected, choose Maximize, Steps 10

      Expect the footer to read Optimize

    • Steps 1001

      Expect the footer disabled with the budget message

    • Steps 10, then Optimize
  • Results drawer

    Expect the Parameters card purple, the headline counting steps, Stop on the card, the Objective by step strip, the cards and the steps table mounted from the first frame

  • Stop

    Expect the sliders unlocked, the outcome on the headline, no Optimize button

  • Viewport controls > Settings > Simulation > In-browser optimization off
  • Experiments > Create > flip the toggle on infected_ratio

    Expect it to read Sweep, no Objective section, footer Create sweep

@kube kube self-assigned this Sep 12, 2026
@kube
kube requested a review from drdma September 12, 2026 01:42
@vercel

vercel Bot commented Sep 12, 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 13, 2026 5:57pm UTC
petrinaut Ready Ready Preview Sep 13, 2026 5:57pm UTC
petrinaut-docs Ready Ready Preview Sep 13, 2026 5:57pm UTC
1 Skipped Deployment
Project Deployment Actions Updated
hashdotdesign-tokens Ignored Ignored Preview Sep 13, 2026 5:57pm UTC

Request Review

@cursor

cursor Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

PR Summary

Medium Risk
Changes public createExperiment contract and experiment/optimization lifecycle (create → study → select); callers must handle the new return type and selection behavior, but scope is mainly Petrinaut experiments UI and provider.

Overview
Optimization and sweeps now start from Create Experiment, not from a later Optimize control on the sweep’s Parameters card. When in-browser optimization is on, numeric interval toggles read Optimize (otherwise Sweep); the first Optimize toggle adds an Objective section (metric, direction, steps) and optional Constraints for saved scenarios. Submit creates the experiment, starts one study, and the caller selects it so the results drawer opens already optimizing—with study UI (Objective by step, Steps columns, sensitivity/constraints cards) fixed at creation for optimize runs.

createExperiment API: resolves with the full ExperimentRecord (including compiled scenario) instead of an id, and does not auto-select or navigate; the default context rejects if called outside a provider. Ad-hoc intervals are Min/Max only (Step, Scale, and boolean optimize UI removed); gutter labels follow Sweep vs Optimize.

Docs, AI help text, Storybook notes, and tests are updated for the new flow and record shape.

Reviewed by Cursor Bugbot for commit 9f859a1. Bugbot is set up for automated code reviews on this repo. Configure here.

@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 type/eng > backend Owned by the @backend team area/apps > hash.design Affects the `hash.design` design site (app) labels Sep 12, 2026
@kube
kube added this pull request to stack #9549 September 12, 2026 01:43
@kube
kube force-pushed the claude/opt-proto-optimize-toggle branch from 33bbc8d to 9bab6b3 Compare September 12, 2026 04:12
@kube
kube force-pushed the claude/opt-proto-optimize-toggle branch from 9bab6b3 to 18987af Compare September 12, 2026 06:05
@kube
kube force-pushed the claude/opt-proto-optimize-toggle branch from 18987af to 7a7f386 Compare September 12, 2026 07:18
@kube
kube force-pushed the claude/opt-proto-optimize-toggle branch from 7a7f386 to 631fa02 Compare September 12, 2026 08:18
@kube
kube added this pull request to the merge queue Sep 13, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue because a pull request earlier in the stack was removed Sep 13, 2026
@kube
kube added this pull request to the merge queue Sep 13, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue because a pull request earlier in the stack was removed Sep 13, 2026
@kube
kube removed this pull request from stack #9549 September 13, 2026 01:36
@kube
kube added this pull request to stack #9692 September 13, 2026 01:37
@kube
kube force-pushed the claude/opt-proto-optimize-toggle branch from 4428067 to 9bb809b Compare September 13, 2026 12:04
drdma
drdma previously approved these changes Sep 13, 2026
vilkinsons
vilkinsons previously approved these changes Sep 13, 2026
@hash-release hash-release Bot mentioned this pull request Sep 13, 2026

This branch was successfully deployed

3 active deployments
Preview – hash — 9f859a18 Deployed Sep 13, 2026 by vercel[bot]
Preview – petrinaut-docs — 9f859a18 Deployed Sep 13, 2026 by vercel[bot]
Preview – petrinaut — 9f859a18 Deployed Sep 13, 2026 by vercel[bot]
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 > backend Owned by the @backend team type/eng > frontend Owned by the @frontend team

Development

Successfully merging this pull request may close these issues.

3 participants