Skip to content

β.3+β.5: AGENTS.md + vetted template + chat→solve→inspector slice (closes #3) - #9

Merged
Rchari1 merged 9 commits into
mainfrom
rchari/beta3-agents-template
Jun 26, 2026
Merged

β.3+β.5: AGENTS.md + vetted template + chat→solve→inspector slice (closes #3)#9
Rchari1 merged 9 commits into
mainfrom
rchari/beta3-agents-template

Conversation

@Rchari1

@Rchari1 Rchari1 commented Jun 15, 2026

Copy link
Copy Markdown
Member

Closes #3. Stacked on #8 (β.2) → base retargets to main when #7/#8 merge.

Implements spec-20260615-113328-agents-template-inspector: the β.3 AGENTS.md+template merged with the β.5 single-run inspector into the full chat→solve→inspector vertical slice.

What this is (7 units)

  • AGENTS.md rewritten for D9/D10 — the LLM authors a Julia script from the bundled template, fills params in-script, runs amico-run <script>. Relocated to packages/extension/ (the repo-root copy was invisible to the bundled extension → opencode was silently getting the stub fallback; fixed).
  • templates/solve_template.jl — vetted single-transmon X-gate template: TransmonSystemEmbeddedOperatorSmoothPulseProblem, Ipopt callback emitting AMICODE_ITER + per-iter control-amplitude PNG, atomic result.toml, pulse.jld2, DONE.
  • DeliveryprepareOpencodeProject copies AGENTS.md (with the Julia project substituted in) + the template into the opencode session.
  • amico-run on PATH — esbuild stages the launcher+bundle into bin/ (VSIX-self-contained); dev resolves the workspace sibling. .vscodeignore ships it.
  • Runs-root reconciled — extension default /tmp/amicode-runs~/.amico/runs/default, matching amico-run's β.1 default, so the watcher sees what the agent's solve writes.
  • Watcher reworked to the β.1 contract — keys completion on FINISHED (previously regex-scraped result.toml and never read FINISHED), identity from manifest.toml, unbounded iter_<N>.png digits. Pure vscode-free ingestRunDir (unit-tested) + incremental live path.
  • Inspector/status-bar — CSP localResourceRoots now includes the runs-root (Q69, else blank inspector); status-bar renders failed/aborted and shows fidelity (was showing iter count mislabeled as F).

AC → evidence

Issue AC Evidence
Template unmodified → FINISHED{completed} + pulse + ≥1 iter_*.png + AMICODE_ITER slow-tier vet through real amico-run: F=0.99994, 16 iter PNGs, pulse.jld2
AGENTS.md: param-in-script (D10), run-dir contract, load_traj warm-start, no flag CLI agents_md.test.ts guard
Artifacts delivered; stub-fallback fixed relocation + opencode_config.test.ts
amico-run on PATH; project in-session; no cross-boundary env opencode_paths.test.ts + AGENTS substitution
Watcher+amico-run agree on ~/.amico/runs/default; FINISHED-keyed; manifest identity; unbounded digits watcher_contract.test.ts (completed/failed/aborted/no-promote) + opencode_paths.test.ts
Inspector renders; no CSP blank; failed/aborted render inspectorResourceRootDirs test + watcher contract test

Fast tier: 44 amico-run + 26 extension tests green from a clean install. Slow tier (AMICO_TEST_JULIA_PROJECT=… pnpm --filter amicode-v2 test:slow) passed on the dev machine.

Notes

  • API drift corrected (verified against Piccolo 1.19): load_pulseload_traj; vetted on Piccolo 1.19 (was 0.11 in dev); fidelity measured via fresh rollout over the computational subspace (unitary_fidelity(U, op.operator; subspace=op.subspace)) — full-space fidelity caps at 4/9 for an embedded gate and was the initial red herring. The amico:transmon skill + Piccolo's canonical multilevel_transmon.jl drove the fix (drive_bounds 0.2, T=10).
  • Verification boundary: every mechanical link is tested locally; the one unproven link is the chat-prompt→script LLM hop (needs opencode + creds) — user-verified at the β.6 demo.

🤖 Generated with Claude Code

@jack-champagne

Copy link
Copy Markdown
Member

Partially reviewed — holding substantive feedback until #7 and #8 are reconciled and merged.

I've gone through this in the context of the stack and it reads as coherent with the β.3/β.5 plan, but I don't want to give line-level feedback yet, for two reasons:

  1. The base is still moving — this PR retargets onto main once β.1: amico-run thin process orchestrator (closes #1) #7/β.2: vendor + pin opencode (closes #2) #8 land, so the diff I'd review against isn't settled.
  2. Two threads from the earlier reviews land squarely in this slice and should resolve first:

Once #7 and #8 are addressed, green, and merged, I'll do the full pass — correctness, the chat→solve→inspector slice, and a local run — against the settled base.

Rchari1 and others added 8 commits June 17, 2026 12:13
…ate to package root

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… plot; slow-tier AC vet (F=0.99999998 through amico-run)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…o opencode session

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ead spike_solve wiring; opencode_paths helpers

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s amico-run); add amicode.runsRoot config

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…manifest identity, unbounded iter digits)

Pure vscode-free ingestRunDir in run_dir_reader.ts (unit-tested); RunsRootWatcher
adds incremental fs.watch + run.log tailing over it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…/aborted + fidelity display

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s (no reach-through); rollout+subspace fidelity (F=0.99994, ≤1)

Re-vetted against Piccolo 1.19 (what Pkg.add installs today, per Jack's #7 note).
Kills the methods(solve!) IpoptSolverExt reach-through — Callbacks is public in 1.19.
Fidelity now = unitary_fidelity over the computational subspace from a fresh
unitary_rollout (was reading >1 from raw-propagator integrator drift).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Rchari1
Rchari1 force-pushed the rchari/beta2-vendor-opencode branch from 4bb031b to 26d9018 Compare June 17, 2026 16:14
@Rchari1
Rchari1 force-pushed the rchari/beta3-agents-template branch from 76efc8d to 259cdf6 Compare June 17, 2026 16:14
@Rchari1

Rchari1 commented Jun 17, 2026

Copy link
Copy Markdown
Member Author

Both threads you flagged as blocking the full #9 pass are resolved — ready when you are:

  1. IpoptSolverExt reach-through → gone. The template now uses the public Piccolo.Callbacks module (1.19), no methods(solve!) introspection. Re-vetted on Piccolo 1.19 end-to-end through the real amico-run: F = 0.99994 (transmon X, 7 iter PNGs, pulse.jld2, FINISHED{completed}). Two API corrections that came out of the 1.19 re-vet, both committed:
    • fidelity is now unitary_fidelity over the computational subspace from a fresh unitary_rollout — full-space fidelity against the embedded goal reads ~0.44 (the solve doesn't pin identity on the leakage level), and the raw final-propagator block read >1 from ~1e-6 integrator norm-drift. Subspace-rollout is the lab-standard metric and stays ≤1.
    • load_pulseload_traj in the AGENTS.md warm-start idiom (the former doesn't exist in 1.19).
    • Also left a comment in the template pointing at the solver-agnostic AbstractIntermediateCallback/LivePulsePlotCallback path for when the default solver moves to MadNLP/Altissimo — directly per your note.
  2. AMICO_* reconciliation → done (Task 4): chat→solve drives amico-run purely via argv; no env propagation (see my β.2: vendor + pin opencode (closes #2) #8 reply).

The base is still #8 → retargets to main once #7/#8 land. Branch force-updated from the restack (β.1 #7 fixes underneath). 45 amico-run + 26 extension tests green; slow tier green on the 1.19 project.

@jack-champagne jack-champagne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed against the issue ACs (#3, #5) and pulled the branch locally (build/typecheck green, fast tier 45+26). The slice is well-built and the run-dir-contract consumption is solid — but two issue-AC items don't hold yet, both small fixes:

  • #3 AC2 (warm-start): the documented load_traj idiom can't reload a template-produced pulse — the template saves JLD2 key trajectory but load_traj reads key traj, so the reload throws.
  • #5 AC3 (status bar): solving (iter N) is never shown — the status bar only updates at completion; live iters go only to the inspector.

A few should-fixes are inline: the live-stats regex silently drops Inf/NaN (the stagnation/blow-up case those stats exist to flag), a replay→tail seam can drop a burst of iter lines, runs lose param/lab provenance, and the cold-start promote prompt can re-fire for an old run. There's also no test covering the live status-bar / incremental inspector path, which is why the status-bar gap slips past CI — one watcher test would catch it.

Solidly right: FINISHED-keyed completion reusing amico-run's validators, runs-root agreement with amico-run's default, no env propagation, no MCP/HTTP, the CSP fix, and scope stays in lane (no scheduler / sizeClass / HDF5 / multi-run). The promote→catalog prompt is a pre-existing stub from the β.2 base, not new here.

Requesting changes scoped to the two AC items (both tiny); everything else is should-fix / nit. (Minor, not inline-able since the file isn't touched here: server_manager.ts's ServerOptions.env comment still references a removed AMICODE_EXTENSION_URL / MCP-callback env — worth deleting.)

# ensure at least one PNG even if the solve stopped before PLOT_EVERY
isfile(@sprintf("iter_%04d.png", iters[])) || save_control_plot(iters[])

JLD2.save("pulse.jld2", "trajectory", prob.trajectory)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saves JLD2 key trajectory, but the documented load_traj reads key traj, so warm-start reload throws (#3 AC2) — use JLD2.save("pulse.jld2", prob.trajectory).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a5121a9 — the template now saves JLD2.save("pulse.jld2", "traj", prob.trajectory), so the documented load_traj (which reads key traj) reloads it. Warm-start round-trips.

getInspector()?.setImageSource(fsPath, iter);
}
iter(rec: IterRecord): void {
getInspector()?.postIterationRecord(rec);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Live iters go only to the inspector here — setRun fires only at completion, so the status bar never shows solving (iter N) (#5 AC3).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a5121a9LiveRunSink.iter() now calls statusBar.setRun({status:"running", latestIter: rec.iter}) on every iter line, so the status bar shows solving (iter N) live, not just at completion (#5 AC3).

// isolation; the vscode-coupled RunsRootWatcher (file_watcher.ts) consumes it.
// ============================================================================

export const AMICODE_ITER_RE = /^AMICODE_ITER\s+iter=(\d+)\s+f=(-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?)\s+inf_pr=(-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?)\s+inf_du=(-?\d+(?:\.\d+)?(?:[eE][-+]?\d+)?)\s*$/;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This float regex rejects Inf/NaN, so stagnation/blow-up iters are silently dropped (#5 AC2) — and amico-run's own classifier keeps them, so the two disagree.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a5121a9 — the NUM group now accepts Inf|-Inf|NaN, matching amico-run's classifier, plus parseAmicoNum maps them to JS Infinity/NaN. Stagnation/blow-up iters are kept. Guard test in watcher_contract.test.ts.

Comment thread packages/extension/src/file_watcher.ts Outdated
private attach(): void {
if (this.disposed) return;
// Skip the body already replayed by ingestRunDir; tail only appended lines.
try { this.offset = fs.statSync(this.opts.path).size; } catch { this.offset = 0; }

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting offset to the current size can skip AMICODE_ITER lines appended between ingestRunDir's read and this attach.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a5121a9ingestRunDir now returns the run.log byte count it consumed, and the LogTailer attaches at that startOffset (not current EOF), so lines appended between the replay read and the tail attach aren't skipped. Covered by the 'returns the run.log byte offset' test.

anharmonicity `δ` (GHz), `levels`, the target gate, gate time `T` (ns),
timesteps `N`, `max_iter`. **Parameters live in the script — never in this
file.** If the user gives a `lab.toml` path, read it in the script.
3. Run it via the `bash` tool: `amico-run --project <JULIA_PROJECT> solve.jl`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invocation omits --lab and the template writes no params, so a run can't report which lab/params it actually solved.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two parts: params — fixed in a5121a9, the template now writes a [params] table (delta/levels/T/N/drive_max/max_iter) into result.toml, so each run is self-describing. --lab — added in e21539c (on #23, stacked above): the AGENTS.md invocation now passes --lab default so the run records its lab.


// ---------------------------------------------------------------------

private followLatest(): void {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On launch this re-reveals and can re-pop the promote prompt for a prior session's completed run, since the promote-once guard is per-run and rebuilt each switch.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a5121a9 — on launch the watcher baselines a prior finished run by setting activeRunDir without a sink (so it renders nothing and can't re-pop promote), and the promotedRuns Set is now shared across run-switches so a run promotes at most once. Only a fresh live completion prompts.

/** Local resource roots the inspector webview may load images from. Includes
* the runs-root so live iter_*.png under ~/.amico/runs/... are not CSP-blocked (Q69). */
export function inspectorResourceRootDirs(extensionRoot: string, runsRoot: string): string[] {
return [join(extensionRoot, "dist"), join(extensionRoot, "media"), runsRoot, "/tmp"];

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded /tmp is now redundant with runsRoot and needlessly broadens the webview's allowed roots.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in a5121a9inspectorResourceRootDirs no longer includes /tmp; the inspector only loads frames under runsRoot, so the webview's allowed roots are now just dist/media/runsRoot.

- warm-start (#3 AC2): template saves JLD2 key 'traj' so load_traj reloads it.
- status bar (#5 AC3): show 'running · iter N' live (sink.iter → setRun), not
  only at completion.
- live-stats (#5 AC2): AMICODE_ITER regex + parseAmicoNum accept Inf/-Inf/NaN
  so blow-up/stagnation iters aren't silently dropped (matches amico-run).
- log tailer: ingestRunDir returns the run.log bytes consumed; the tailer
  attaches at that offset (no skipped iters between replay and attach).
- promote-once: a run promotes at most once across run-switches; an
  already-finished run (launch-follows-latest / switch-back) never re-pops.
- inspector roots: drop the blanket /tmp webview root (redundant with runsRoot).
- result.toml records the scalar solve params (self-describing run).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Rchari1

Rchari1 commented Jun 21, 2026

Copy link
Copy Markdown
Member Author

Thanks Jack — all addressed in the latest push (force-pushed; #10#22 rebased on top).

Must-fix

Should-fix

  • β.5 — Minimal single-run inspector (stats row + live plot) #5 AC2 Inf/NaN: AMICODE_ITER_RE + a new parseAmicoNum accept Inf/-Inf/NaN, so blow-up/stagnation iters aren't dropped (matches amico-run). Tests added.
  • log-tailer skip: ingestRunDir now returns the run.log bytes it consumed; the tailer attaches at that offset (+ drains once) — no gap, no double-emit.
  • promote re-pop: a watcher-level promotedRuns set makes promote fire at most once per run; a run already finished when switched to (launch-follows-latest / switch-back) is pre-marked, so it never re-pops.
  • /tmp root: dropped from inspectorResourceRootDirs (redundant with runsRoot).
  • params recording: result.toml now includes a [params] table (δ, levels, T, N, drive_max, max_iter) so a run is self-describing.

Disposition: --lab on the invocation is genuinely multi-lab (Phase-2 lab.toml) — β is the single default lab, and the run now records its params in result.toml, so I left --lab for that phase. Shout if you'd rather I add it now.

Rchari1 added a commit that referenced this pull request Jun 22, 2026
…ck review nits

The real "plots never display" bug: LiveRunSink shared one counter between
image() and iter(). run.log AMICODE_ITER lines stream once per iteration and
race the counter to max BEFORE the lagging PNG frames land (solver logs iter=k,
then writes iter_k.png), so every image() hit `k <= latest` and was dropped —
blank inspector for the whole solve. Split into SinkDedup: frames dedup only
against frames; log lines advance a separate high-water mark for the status bar.

Extracted SinkDedup to the pure, vscode-free run_dir_reader layer so the live
path is finally unit-tested (Jack #9: "no test covering the live status-bar /
incremental inspector path" — the exact gap this regression slipped through).

Also folds in the remaining non-blocking review nits (kept here rather than
restacking the 7-deep chain to place one-liners on their home branches):
- #13: #runlabel was styled but never populated → setRunLabel + webview handler.
- #12: resolveJuliaProject now expands a leading ~ (parity with resolveRunsRoot).
- #9:  server_manager ServerOptions.env comment no longer cites the removed
       AMICODE_EXTENSION_URL/MCP-callback env.
- #9/#11: AGENTS.md step-2 author path now matches step-3 run path
       (/tmp/amicode-work/solve.jl) and the invocation passes --lab default
       (run provenance — amico-run supports --lab).

Plus the cold-start display polish already in flight on this branch: launch
stays idle for a prior finished run (no stale plot), and the placeholder toggles
via style.display (the [hidden] attr was overridden by .placeholder{display:flex}).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Rchari1

Rchari1 commented Jun 22, 2026

Copy link
Copy Markdown
Member Author

Thanks for the thorough pass, @jack-champagne. Both AC blockers and all should-fixes are addressed:

Blockers (a5121a9)

Should-fixes (a5121a9): Inf/NaN regex kept; replay→tail startOffset seam closed; [params] provenance in result.toml; promote no longer re-pops a prior finished run; /tmp dropped from webview roots. Stale server_manager MCP-env comment and the AGENTS.md --lab are in e21539c (on #23, stacked above).

Your top-level callout — 'no test covering the live status-bar / incremental inspector path': now covered. I extracted the live newest-wins dedup into a pure SinkDedup in run_dir_reader.ts and unit-tested it (watcher_contract.test.ts). This wasn't academic — that exact path had regressed so the run.log iters raced a shared counter past the lagging PNG frames and silently dropped every frame (blank inspector). The split (frames dedup on frames; log lines advance a separate high-water mark) + tests are in e21539c.

Re-requesting review. 47 tests green.

@Rchari1
Rchari1 requested a review from jack-champagne June 22, 2026 21:17
@Rchari1
Rchari1 changed the base branch from rchari/beta2-vendor-opencode to main June 24, 2026 15:12
@jack-champagne

Copy link
Copy Markdown
Member

Re-checked at a5121a9 — the two AC blockers from my last review are resolved:

One gap remained on #5 AC1 ("display refreshes for the whole solve"): the live plot frame never advanced during a solve. image() and iter() share one latestIter (file_watcher.ts:37,47,52); the solver prints AMICODE_ITER iter=N before writing iter_N.png, so the tailer bumps latestIter to N and image(N) then hits N <= latestIter and drops the frame. There was also no final-frame push on completion. Stats rows streamed fine — it was the plot that froze.

Fixed in #23 (SinkDedup splits frame dedup from the log high-water mark), now validated end-to-end on the live vertical. Recording the link for history; resolved in the unit. Worth a follow-up: a watcher test that appends to a run dir over time so this path is covered going forward.

@jack-champagne jack-champagne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving as a unit member — my two blockers are resolved here; the live-plot gap is fixed in #23 (validated end-to-end). Details in the comment above.

@Rchari1
Rchari1 merged commit 25651e6 into main Jun 26, 2026
3 checks passed
Sign up for free to 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.

β.3 — AGENTS.md + vetted solve-script template

2 participants