Uh oh!
There was an error while loading. Please reload this page.
feat(amicode): system card renders the recorded Hamiltonian, and stops inventing one - #93
Merged
Merged
Conversation
aarontrowbridgeforce-pushed
the
feat/amicode-system-card-model
branch
from
July 28, 2026 21:52
ac7078f to
4118aaaCompareaarontrowbridge added a commit
to harmoniqs/amicode
that referenced
this pull request
Jul 28, 2026
…bricating roles The System card re-derives the Hamiltonian in the renderer from (role, levels, platform) with hardcoded tables, so it is only ever right for platforms someone hardcoded — and silently wrong for the rest. It showed the transmon ladder, and asked for an anharmonicity, on an exchange-only spin qubit. Two changes here; the renderer half is harmoniqs/opencode#93. 1. `amicode_set_model` gains `hamiltonian` — the model term by term ({kind: drift|coupling|drive, latex, acts_on?, label?}) plus `hamiltonian_notes` for frame/unit/basis conventions. The agent already understands the model well enough to author the Julia solve; this is where that understanding gets written down instead of evaporating into the script. It knows what an exchange-only spin qubit is — the renderer's table never will. Full path: validation (closed kind set, non-empty latex, acts_on ids must exist, brace balance since the plugin can't parse LaTeX but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through. 2. `role` gains `other`, and `platformDefaultRole` stops inventing one. Only platforms we model get a role from the string (rydberg→atom, transmon→qubit, bosonic→mode); everything else is `other` until MODEL asks. The old blanket "unknown → qubit" was also wrong for photonic and bosonic, which are modes. AGENTS.md tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to use `other` over a near-miss. Note for the reviewer: this lands the recording side. The card only renders it once the fork release carrying #93 is pinned via `pnpm opencode:pin`, so there is no lock bump here. Verified: 782 tests pass (78 files), tsc clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The card made its component-count claim implicitly, so an unanswered 'how many
atoms?' read as 'one'. systemCountLabel now states it as its own badge ('2 atoms
x 3 levels') that a researcher can read and correct.
componentPhysicsRows renders what each role actually has, in card order:
- unanswered params read 'not set', so the list doubles as the interview's to-do
- anything else on file is still shown, so nothing recorded is dropped
- an unrecognized role expects NOTHING -- the honest floor for a platform we have
no model for
- units are never assumed (transmon params are GHz, the Rydberg templates work in
rad/us, a bare omega says which only by convention), so a unit appears only when
the recorded key spells it out
- a zero keeps the '0 means unset' reading, so an all-zeros seed does not look
like a specified device
driftTerm now keys the qubit ladder off LEVELS rather than off whether delta
happens to be filled in: a 3-level transmon with empty params is still an
anharmonic ladder, and rendering it as a bare spin misstates the model the solve
will use. A mode's Kerr stays params-driven, since a linear cavity genuinely has
none.Continues 0793fd6. Committed on the author's behalf as part of folding the worktree's in-progress work onto the branch; the content is theirs. +169 lines of tests alongside +278 of implementation; ui suite 442 -> 448 pass.
…f-template
The card re-derived the Hamiltonian in the renderer from (role, levels, platform)
using hardcoded tables, so it could only ever be right for platforms someone had
hardcoded. Two separate leaks put the transmon model on a spin qubit:
- `platformDefaultRole` maps every unfamiliar platform to "qubit", so an
exchange-only HRL spin qubit arrived indistinguishable from a transmon.
- levels >= 3 was read as "anharmonic ladder". It is not. Three levels is a
Hilbert-space DIMENSION: an exchange-only qubit at levels=3 is three dots, a
spin-1 defect is three Zeeman sublevels. Neither is an oscillator.
So the platform is now the only thing that licenses a ladder for a `qubit` role
(transmon, bosonic). levels=2 still earns the generic two-level model, which is
safe on any platform — every two-level system has an ω σ_z/2 splitting and σx/σy
control. Everything else is opaque.
Recorded beats inferred. `systemHamiltonian()` returns {latex, source}: a model
recorded on the entity (amicode_set_model's `hamiltonian`, see harmoniqs/amicode#220) renders
verbatim; otherwise the canonical form for the platform renders under an
"inferred · confirm or correct" label. When nothing is recorded AND nothing is
modelled the card says "not recorded" rather than showing `Ĥ_drift + Ĥ_c(t)`, which
is true of every control problem ever posed and would occupy the slot the real model
belongs in. Mixed systems still get a named placeholder per unmodelled component.
One `classify()` now drives both the equation and the physics rows, so the two
halves of the card cannot describe different physics again.
Also fixes a three-way drift found while doing this: the ladder drive was a single
`ε(t)(â+â†)` while the plugin's TRANSMON_LATEX (shown in chat) and Piccolo's
n_drives = 2 both say two quadratures. Two is correct; the card now matches.
Verified: 399 pass across 30 files, tsgo clean. The KaTeX sweep now crosses the
platform axis too (8k systems) and asserts BOTH directions: no output when nothing
is modelled, and never a model invented for an all-unmodelled system.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>jack-champagneforce-pushed
the
feat/amicode-system-card-model
branch
from
July 28, 2026 22:52
4118aaa to
e4e0133Compare… once The sweep enumerates ~8k systems, but they collapse onto a few hundred distinct equations, and KaTeX is the expensive part. Rendering the same string 200 times proves nothing and took 22s on CI against a 5s default timeout (it passed locally on a fast machine, and I had only been running src/amicode — CI runs all of src). Coverage is unchanged: every distinct output is still parsed, and the mapping back to a producing system is kept for the failure message. Adds an assertion that the sweep really does vary its output, so a future change that collapses everything to one equation can't quietly pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jack-champagne added a commit
that referenced
this pull request
Jul 29, 2026
…t tests (#98) The three `session.llm native recorded` scenarios are the only failures on `local/amicode`, so the fork's `test` job is red and every PR into it inherits a red check — including #93, whose own suite is 3366 pass / 3 fail with zero failures of its own. Cause is ours. AMICODE-PATCHES.md ADDENDUM 2 consolidated the prompt so `system.ts provider()` returns `[providerBase(model), PROMPT_COMMUNICATING]`, appending `communicating.txt` for every model family. The cassettes still record the pre-patch prompt, so all three break on a diff of prose. Those tests assert TRANSPORT mechanics — that a tool loop is driven to a final text answer. The prompt is incidental, so matching on it couples them to text they do not test. Patching the recorded prompt instead would work until the next prompt edit, and that patch already has three addenda. `RecorderOptions.match` is an existing seam (types.ts:85, threaded through `http()` to `recordingLayer`) that nothing used. Adds `promptAgnosticMatcher` alongside `defaultMatcher` and passes it from this one test. The prompt arrives in three shapes, all covered: instructions OpenAI Responses system[] Anthropic Messages input[].role=="system" the OpenCode proxy System-message content is replaced with a placeholder rather than deleted, so "a system message is present, with content" stays part of the match. Verified narrow, in test/matching.test.ts: it ignores prompt prose in all three shapes, and still rejects a different user message, model, tool set, URL, or a missing-vs-present system message. 49 pass in http-recorder; the three recorded scenarios go 3 fail -> 3 pass; typecheck green across 23 packages.
Uh oh!
There was an error while loading. Please reload this page.
jack-champagne pushed a commit
to harmoniqs/amicode
that referenced
this pull request
Jul 29, 2026
…bricating roles (#220) The System card re-derives the Hamiltonian in the renderer from (role, levels, platform) with hardcoded tables, so it is only ever right for platforms someone hardcoded — and silently wrong for the rest. It showed the transmon ladder, and asked for an anharmonicity, on an exchange-only spin qubit. Two changes here; the renderer half is harmoniqs/opencode#93. 1. `amicode_set_model` gains `hamiltonian` — the model term by term ({kind: drift|coupling|drive, latex, acts_on?, label?}) plus `hamiltonian_notes` for frame/unit/basis conventions. The agent already understands the model well enough to author the Julia solve; this is where that understanding gets written down instead of evaporating into the script. It knows what an exchange-only spin qubit is — the renderer's table never will. Full path: validation (closed kind set, non-empty latex, acts_on ids must exist, brace balance since the plugin can't parse LaTeX but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through. 2. `role` gains `other`, and `platformDefaultRole` stops inventing one. Only platforms we model get a role from the string (rydberg→atom, transmon→qubit, bosonic→mode); everything else is `other` until MODEL asks. The old blanket "unknown → qubit" was also wrong for photonic and bosonic, which are modes. AGENTS.md tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to use `other` over a near-miss. Note for the reviewer: this lands the recording side. The card only renders it once the fork release carrying #93 is pinned via `pnpm opencode:pin`, so there is no lock bump here. Verified: 782 tests pass (78 files), tsc clean. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The System card re-derived the Hamiltonian in the renderer from
(role, levels, platform)using hardcoded tables. So it could only ever be right for platforms someone had hardcoded, and was confidently wrong for the rest — most recently showing the transmon ladder, and asking for an anharmonicity, on an exchange-only spin qubit.Recording half of this is harmoniqs/amicode#AMICODE_PR.
Three commits
1 · per-component physics rows — the row list was a fixed transmon spec (frequency · anharmonicity · drive bound · decay) emitted for every component, while the Hamiltonian directly above it was role-aware. A Rydberg atom got asked for its anharmonicity. Rows now come from the component's model; params it doesn't have are absent, not shown as unanswered. Units are never assumed (transmon params are GHz, the Rydberg templates work in rad/µs) — a unit renders only when the recorded key spells it.
2 · Hamiltonian composed over the actual component and edge sets — the old composer deduped term strings over the set of distinct roles, so it rendered "which kinds of term appear", not the Hamiltonian of the system. It meant: a 2-atom and a 20-atom register rendered identically; an N-edge chain rendered one edge hardcoded to sites (1),(2); a qubit and a cavity both used
â; the drive-arch badge had no counterpart in the equation;+ -Δprinted literally; and\hat ^\dagger(a KaTeX error box) for any exchange/CR/mode-mediated edge with a non-bosonic endpoint. Now: components group by model and sum over their site indices, each bosonic group gets its own operator letter, like edges aggregate intoΣ_⟨ij⟩, and the drive arch decides whether a control carries a site index —Ω(t)shared,Ω_i(t)per site,Ω_z(i)(t)per zone.3 · recorded beats inferred —
systemHamiltonian()returns{latex, source}. A model recorded on the entity renders verbatim; otherwise the canonical form renders under aninferred · confirm or correctlabel. When nothing is recorded and nothing is modelled the card says "not recorded" rather than showingĤ_drift + Ĥ_c(t)— true of every control problem ever posed, and it would occupy the slot the real model belongs in.The rule that matters
Two separate leaks put the transmon model on a spin qubit, and the second is the subtle one:
platformDefaultRolemaps every unfamiliar platform to"qubit"— fixed on the plugin side.levels >= 3was read as "anharmonic ladder". It is not. Three levels is a Hilbert-space dimension: an exchange-only qubit at levels=3 is three dots; a spin-1 defect is three Zeeman sublevels. Neither is an oscillator.So the platform is now the only thing that licenses a ladder for a
qubitrole.levels=2still earns the generic two-level model — safe anywhere, since every two-level system has an ω σ_z/2 splitting and σx/σy control. Everything else is opaque.One
classify()drives both the equation and the physics rows, so the two halves of the card cannot describe different physics again.Bonus: a three-way drift
The ladder drive was a single
ε(t)(â+â†), while the plugin'sTRANSMON_LATEX(what Amico shows in chat) and Piccolo'sn_drives = 2both say two quadratures. Same device, same session, two different answers — nobody had noticed because both look plausible. Two is correct; the card now matches.What it looks like
Verification
399 pass across 30 files,
tsgoclean. The KaTeX sweep crosses role × coupling kind × drive arch × N × platform (~8k systems) and asserts both directions: every rendered system parses, no output when nothing is modelled, and never a model invented for an all-unmodelled system.Branched off
local/amicode; these three commits are extracted from a local integration branch and touch only the system-card files.🤖 Generated with Claude Code