# Quantum Studio An editor for OpenQASM programs, with three places to run them: - **this browser**, through the quantum job service's engine compiled to WebAssembly, in a worker; - **this computer**, through the same engine built natively, in the [desktop app](../wai-quantum-desktop/); - **the job service**, over HTTP. Every place returns the same job: the request, the method and why it was chosen, the result, and its receipt. The Studio shows them the same way and checks every receipt on the machine it runs on. The same request with the same seed gives the same counts in each place. The editor: - highlights OpenQASM; - completes the standard gates and the program's own registers; - marks the engine's diagnostics on their lines; - draws the circuit and shows the plan as you type. Ctrl+Enter (⌘+Enter on macOS) runs the program, and Escape cancels a run. The program and the history of runs are kept on the device. "Copy link" puts the program in a URL fragment, which no server sees. ## Generators A program that declares integer inputs (`input uint n;`) is a generator: its `for` loops and its `if`s on integers write out one circuit for each value. The Studio shows a field for each input under the editor and reads the program at those values. The lint and the critique read the generator itself, so a problem or a smell keeps the generator's own line. The diagram, the plan, a run (here or on the service), the lens and the alternatives take the circuit it writes out. The values are kept in this browser, by name. ## The Workbench The Workbench searches a family of circuits for its cheapest members, and the engine judges every proposal. The program in the editor is the reference. The specification says: - what each member must do: prepare the same state from |0…0⟩, or be the same circuit; - the sizes to check at (`n = 3, 5, 8`); - the gates allowed, and whether a gate may join any pair or only neighbours on a line; - the cost, as weights on the critique's measures summed over the sizes; - the two measures the map plots. "Start" checks the reference at every size and seeds an archive with it. The archive keeps the cheapest verified generator in each cell of the map. Three proposers write into it, and each is named on what it found: - **the reader:** "Submit the editor's program"; - **the built-in, blind search:** "Search ×100", seeded edits of what the archive holds. It is the baseline an idea has to beat; - **the model**, when one is connected: "Ask the model ×3". It is told the specification and shown the cheapest found, with the costs the engine measured. A proposal is verified only when it reads, keeps the rules and passes the check at every size. Each kept entry is sealed with this browser's key (the desktop app's, in the app). Clicking a point shows its cost, how it was checked, its seal and where it came from; "Open in editor" puts it in the editor. The archive is kept in this browser and comes back with the page. "Download" saves the specification and its archive side by side (`NAME.json` and `NAME.archive.json`), so `wai-quantum discover verify NAME.json` checks every seal. In the desktop app a search also counts its seconds and the joules its process spent. ## Versions The Versions pane records each change to the program and who made it: - what the reader types is theirs, recorded once they pause, before a run, and before anything else changes the program; - a proposal is its proposer's: the assistant's program, an alternative (the engine's or the model's), a generator opened from the Workbench; - a fix is the engine's; - an example, a file, a link or an earlier run is where the program came from. **A proposal is taken change by change.** Its changes are listed with their lines, each with a box, and the program waits until the reader chooses. Only the changes taken reach the program. The version keeps the whole proposal and which changes were taken, so a rejected one stays readable. **Lines of work.** The versions are drawn as lines of work. "Open" puts an older version in the editor, and what is changed from it starts a line of its own. "Bring in" shows another line's head change by change against the program, and the changes taken are recorded as a merge of both. **Whose hand.** "Who wrote it" marks each line in the editor's gutter and each gate on the diagram: the reader, the assistant, an agent, the engine, where it came from, or a model's line the reader then edited, which is in both hands. The pane shows each contributor's gates and lines. **On the receipt.** A run's request carries the account of the version in the editor: its digest, and the gates and lines in each hand. The receipt binds it, and the result shows "written by" and the account recomputed here from the versions. The versions are kept in this browser, each sealed with its key (the desktop app's, in the app). "Download" saves `program.qasm` and `program.history.json`, which `wai-quantum history verify program.qasm` checks. An embedding page can offer a program as someone's proposal with `window.quantumStudio.propose(qasm, {kind, name}, note)`; it resolves once the reader has chosen. ## The assistant The Assistant pane talks to a language model on this machine: any server with the chat-completions interface and tool calls, such as the JouleClaw runtime or a llama.cpp server. The address goes under "Model…" and is `http://127.0.0.1:8080/v1` by default. Nothing leaves the machine unless the address points elsewhere. In the desktop app the app makes the call itself, so no browser origin rule stands in the way. The engine is the model's tool, not an afterthought: - **Its tools are the Studio's engine:** read the program, lint, draw, plan and run. Its first turn must call one of them, so every answer starts from the engine. - **Every program it proposes is checked before it is offered.** The engine reads it here. One that does not parse goes back to the model once, with the engine's reason, to be corrected. One that parses is run, with the settings the model used, so the counts it quoted are the counts shown. Then "Apply" puts it in the editor. - **It may state only figures the engine returned.** A figure in its prose that no tool returned is marked "Not from a run". - **Answers are plain text.** LaTeX a model writes anyway is shown as Unicode. `node test/assistant-live.mjs URL` drives the assistant against a real model server and prints what it did. It is not part of CI, which has no model. ## Hosting it Build it with `npm ci && node build.mjs`. That writes `dist/`: | File | What it is | |---|---| | `studio.js` | the interface, bundled | | `worker.js` | the engine's worker | | `studio.css` | the Studio's styles | | `tokens.css` | the site's design tokens, for when it stands alone | | `index.html` | the page that stands alone | A host mounts the Studio on an element: ```html
``` `data-embedded` tells the Studio the host page has its own heading, so the Studio's name is not a second `h1`. `data-engine-pkg` names the engine's browser package: wai-web built with the feature `quantum_engine`. `node build.mjs --pkg DIR` copies such a package into `dist/pkg/` for `index.html`. On the desktop, `window.__TAURI__` is present and the Studio uses the native engine instead. ## Testing it ```sh node build.mjs --pkg PATH/TO/PKG && node test/studio.test.mjs ``` The test runs the Studio in the installed browser: - lint, draw and plan as the program is typed; - a run in the browser, with its receipt checked there; - an error marked on its line; - a rotation run on the state vector; - the same job on the live service giving the counts run here, shot for shot; - Ctrl+Enter; - the program and the history surviving a reload; - the assistant, against a scripted model server: a tool call run on the engine, a proposal the engine cannot read sent back with its reason, the corrected one checked and run before it is offered, and Apply; - the layout at a phone's width. `STUDIO_SKIP_SERVICE=1` leaves the service step out. It saves screenshots of both colour schemes in `test/screenshots/`.