feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles - #220

Merged
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian
Jul 29, 2026
Merged

feat(extension): record the Hamiltonian on the System entity; stop fabricating roles#220
jack-champagne merged 1 commit into
mainfrom
feat/system-recorded-hamiltonian

Conversation

@aarontrowbridge

Copy link
Copy Markdown
Member

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.

This is the recording half. 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 argument for putting it here: the agent already understands the model well enough to author the Julia solve. That understanding currently evaporates into a .jl file and never reaches the entity, so the UI re-derives it badly. Amico knows what an exchange-only spin qubit is; the renderer's lookup table never will.

Full path implemented: validation (closed kind set, non-empty latex, acts_on ids must exist, and a brace-balance check — the plugin stays dependency-free so it can't parse LaTeX, but the card renders it straight into KaTeX), TOML round-trip, wholesale patch-replace, hashing, normalizeSystem read-through.

Precedence in the card: recorded renders verbatim; otherwise the canonical form for the platform renders under an inferred · confirm or correct label; off-template it shows no Hamiltonian at all.

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 the MODEL stage asks. The old blanket "unknown → qubit" was a fabrication that every downstream consumer then read as a statement — and it was also wrong for photonic and bosonic, which are modes.

3 · AGENTS.md

Tells the interview to record the Hamiltonian — mandatory off-template, worth confirming even on template — and to prefer other over a near-miss role.

Also leaves a THIRD COPY WARNING at TRANSMON_LATEX: the same physics is written down in the plugin, the card's fallback tables, and the Julia templates, and they had drifted (the card said one drive quadrature; this constant and Piccolo's n_drives = 2 say two). Fixed in #93. Recording the model is what makes the constants a pre-MODEL fallback rather than a third source of truth.

Reviewer note

This lands recording only. The card renders it once a fork release carrying harmoniqs/opencode#93 is pinned via pnpm --filter amicode opencode:pin <tag> — so no lock bump here, and the two can merge independently.

Verification

782 tests pass (78 files), tsc --noEmit clean.

🤖 Generated with Claude Code

…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>
aarontrowbridge added a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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>
@aarontrowbridge
aarontrowbridgeforce-pushed the feat/system-recorded-hamiltonian branch from 3b45aaf to 8dda178CompareJuly 28, 2026 21:53
jack-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 28, 2026
…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-champagne pushed a commit to harmoniqs/opencode that referenced this pull request Jul 29, 2026
…s inventing one (#93)
* feat(amicode): per-component physics rows on the system card
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.
* feat(amicode): extend the system card's physics rows
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.
* feat(amicode): render the recorded Hamiltonian; stop inferring one off-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>
* test(amicode): dedupe the KaTeX sweep — render each distinct equation 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>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@jack-champagne
jack-champagne merged commit eb101be into mainJul 29, 2026
5 checks passed
@jack-champagne
jack-champagne deleted the feat/system-recorded-hamiltonian branch July 29, 2026 02:56
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@aarontrowbridge@jack-champagne