open-standards/wai/quantum-studio/README.md
Transaction Science 94fabb574d wai-quantum: whether designs converge on a model's, and a while on one's own
Feature 12 of the co-design report: a convergence monitor.

- engine::converge:
  - history: for each version the person made after a model proposed,
    its structural distance from the proposals in its line of work (the
    whole proposal) and the model's share of its gates; converging when
    most of the program is the model's or the last versions come closer
    each time, with why; versions noted "organic exploration" (the
    assistant-off probes) set beside the rest;
  - cohort: the Vendi score over 1 - distance (Jacobi eigenvalues), each
    program's distance to the centroid of the gate-token bags, the medoid
    and the outlier, and with times the score in windows and a narrowing;
  - call for hosts. novelty::bag is shared.
- The command line: converge history | cohort (a file's time from its
  history, else the file's).
- MCP: converge_cohort and converge_history.
- The Studio: "Your own way" under Versions, and "Explore on my own for a
  while": the assistant only asks and offers no program, Explore and Ask
  the model wait, the person's versions are noted; End lets the model
  propose again.
- Bindings: engine_converge in the page, converge in the desktop app.
- CI: wai-web's native engine tests count 13.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 16:05:43 -04:00

159 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.
## Rewrites
"Rewrites", under the circuit, lists every rewrite the program admits that keeps its meaning: gates that cancel, rotations that merge, a gate between two Hadamards that becomes its conjugate, a gate carried past what it commutes with, two gates that trade places. The engine checks each one on the qubits it touches. Pointing at a rewrite marks its gates on the diagram; "Take" offers it as the engine's proposal, reviewed like any other, and the list follows the program as it changes. In Alternatives, a candidate that is the same circuit as the draft says how the draft becomes it, as a chain of checked rewrites.
## What is new, and Found
The engine says what is new in a program: the known construction it is, found again; a known result reached by a different route; or how far it is from the nearest program it was compared with. The known constructions are GHZ by a chain, by doubling and by fan-out, the uniform superposition and the quantum Fourier transform. The distance is structural, from 0 (built alike) to 1 (nothing shared), and it is the engine's, not a search of the literature.
- **Alternatives:** each card says what is new in it, against the known constructions and the draft. A card that reaches a known result by a different route is marked.
- **The Workbench:** each kept generator is named for what it is, and its entry shows it with the measures it beats the reference on that the cost does not weigh. A candidate that breaks only one rule of the specification (a gate, or the line) and would be verified without it is an aberration. It is never kept: the log says what it would cost, and "Try without that rule" loosens the specification, for a new archive under it.
- **Found** keeps what is worth a second look: a different route to a known result, an aberration, a verified entry far from everything it was compared with. Each can be opened in the editor, saved with a note, or dismissed. Its count says how many were flagged and how many saved. It is kept in this browser.
## Your own way
Under Versions, "Your own way" says whether your versions are converging on the model's proposals: how far your latest is built from them, and how much of the program is the model's. "Explore on my own for a while" pauses the model while you work:
- the assistant only asks questions, and does not offer its programs;
- Alternatives' Explore and the Workbench's "Ask the model" wait;
- the versions you make are noted as made on your own, and the line sets their distance from the proposals beside the rest.
"End" lets the model propose again. The mode is kept in this browser.
## Your taste
"Your taste", in the Workbench, learns what you prefer from your own choices:
- **Compare two** shows the two kept generators your profile is least sure of. The engine proves that they do the same thing, so the choice is about taste, never correctness. "This one" keeps it, and "About" says what it was for: economy, clarity, insight, precision or utility.
- **From Alternatives too:** an alternative that is the same circuit as the draft, taken whole or refused whole, is a choice between the two. One taken in part says nothing. Improve orders its candidates by your profile once it has a choice.
- **Rank by my taste** orders the kept generators. Each shows its typicality (how near the known constructions it is built), which the profile never learns and only the dial moves from typical to novel. The ranking says where a part, or the cost, puts another first, and whether its first three are built more alike than the cost's.
- **Profiles:** each name is a profile of its own, kept in this browser; nothing pools them. The summary says how many of your choices the profile predicts, each from the ones before.
## 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.
## Rules for proposals
Under the editor, "Rules for proposals" holds what no proposal may change:
- **Held lines:** "Hold the selected lines" marks them in the program with `// @lock` and `// @unlock`. They are shaded in the editor, and their gates are marked on the diagram.
- **Gates:** the gates a proposal may add, and gates to avoid.
- **Qubits:** "Hold the qubit declarations".
- **Text to avoid.**
- **A region:** "Keep the next proposal to the selected lines", let go once that proposal is decided.
The engine checks every proposal against them change by change: the assistant's program, an alternative, a fix, a generator from the Workbench. A change that breaks a rule is shown in the review with the rule and cannot be taken. The version in Versions records it as blocked. An alternative whose every change breaks a rule is left out, with the reason. The model is told the rules with every request. What you type is yours to change.
## 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, run, and say what is new in a program. Its first turn must call one of them, so every answer starts from the engine. It may call a program new only when the engine says so, and then as the engine's distance, not a search of the literature.
- **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
<div id="studio"
data-engine-pkg="/quantum-ide/pkg/wai_quantum_ide.js"
data-worker="/quantum-studio/worker.js"
data-service="/quantum-jobs"></div>
<script type="module" src="/quantum-studio/studio.js"></script>
```
`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/`.