Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4429b15
feat(L0): pulse-designer interview spine in AGENTS.md
aarontrowbridge Jul 3, 2026
7c4351d
test(L0): interview e2e slow suite — tiered A/B/C (registration / plu…
aarontrowbridge Jul 3, 2026
735f425
feat(L0): amicode_* tool pack v0 + config registration
aarontrowbridge Jul 3, 2026
3288162
test(L0): tier C live — full A/B/C green vs the branded binary
aarontrowbridge Jul 3, 2026
5dabb87
test(L0): tier D — full chain interview→launched solve (MVP DoD) PASSES
aarontrowbridge Jul 3, 2026
f941a7e
feat(L0): hardware/calibrate guided stubs — the pack covers all 8 stages
aarontrowbridge Jul 3, 2026
7eac2b5
feat(L0): Amico identity + proactive interview kickoff
aarontrowbridge Jul 3, 2026
9d28f02
feat(L0): amicode_ask — multiple-choice questions as button payloads
aarontrowbridge Jul 3, 2026
1a5b2a8
fix(L0): amicode_ask discipline + optional per-option details
aarontrowbridge Jul 3, 2026
5c83b38
brand: digi Harmoniqs H-robot mark replaces the amico smile
aarontrowbridge Jul 3, 2026
4eca7bb
feat: fixed opencode port (amicode.opencodePort, default 43117) + awa…
aarontrowbridge Jul 3, 2026
ac04730
feat(scores): manifest schema + additive validation
aarontrowbridge Jul 3, 2026
3f9ea59
feat(scores): SCORE.md loader with per-score error isolation
aarontrowbridge Jul 3, 2026
e8b1927
fix(scores): loader test targeted schema_version by accident
aarontrowbridge Jul 3, 2026
1ac3496
feat(scores): repertoire lint (templates, memory hooks, lineage, enti…
aarontrowbridge Jul 3, 2026
e2e55b8
feat(scores): score #0 — pulse-designer interview as data (+ vsix pac…
aarontrowbridge Jul 3, 2026
555fadb
feat(scores): entitlement gating + onset router section
aarontrowbridge Jul 3, 2026
9db4367
feat(scores): interview_state [score] slice with version pinning (JSO…
aarontrowbridge Jul 3, 2026
4d6f55e
feat(scores): usage capture module (funnel, off-path, gate events)
aarontrowbridge Jul 3, 2026
d832b75
feat(scores): compiler + router spliced into the injection seam, scor…
aarontrowbridge Jul 3, 2026
114f4e8
feat(scores): stage-order + gate guard enforced in the amicode_* tool…
aarontrowbridge Jul 3, 2026
c3259f1
test(scores): live e2e — router → score #0 → pinned state + usage fun…
aarontrowbridge Jul 3, 2026
71d74f5
docs(scores): repertoire authoring README
aarontrowbridge Jul 3, 2026
11d5a7c
scores: mirror 778e1bb ask-discipline into score #0 + anchor-on-recor…
aarontrowbridge Jul 3, 2026
7cf3923
test(scores): version-agnostic prep assertions + banner/manifest vers…
aarontrowbridge Jul 3, 2026
33bc3e2
feat(L0): consolidate on opencode's NATIVE question tool; amicode_ask…
aarontrowbridge Jul 3, 2026
51e8b4b
feat(L0): curated 'What can Amicode do?' answer — no webfetch, no eng…
aarontrowbridge Jul 3, 2026
bedc549
feat: private-mirror vendoring + team testing guide + Rydberg CZ temp…
aarontrowbridge Jul 3, 2026
42b6418
docs: root agent-forward setup guide (AGENTS.md + CLAUDE.md pointer)
aarontrowbridge Jul 3, 2026
f6a0e67
chore: vendor from the harmoniqs/opencode private release (v1.17.3-am…
aarontrowbridge Jul 3, 2026
d81e63f
test: align buildOpencodeConfigContent call sites with rebased runsRo…
aarontrowbridge Jul 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Amicode — agent setup & testing guide

You are (probably) an agent asked to set up, develop, or test Amicode on this machine.
This file is the canonical path. The human-oriented test script is
`packages/extension/TESTING.md`; design authority lives in the `harmoniqs/amico` vault
(see `README.md`). **Do not confuse this file with `packages/extension/AGENTS.md`** —
that one is the product's runtime instruction set for the in-app agent, not for you.

## What this is

A VS Code extension (`packages/extension`, pnpm workspace) for conversational quantum
pulse design: chat (an opencode server we vendor, branded as Amicode) → guided interview
→ LLM-authored Julia solve (Piccolo) via `packages/amico-run` → live Run Inspector.
Interview flows are data (`packages/extension/scores/`). Schemas: `packages/schema`.

## Prerequisites (verify each; do not assume)

1. `node >= 20`, `corepack enable` (repo pins `pnpm@9.15.9` — never install pnpm globally)
2. Julia ≥ 1.12 via juliaup: `curl -fsSL https://install.julialang.org | sh`
3. `gh auth status` succeeds AND `gh repo view harmoniqs/opencode` succeeds
(private fork mirror — the vendored binary downloads from its release; if 404, stop
and tell the human to request access from Aaron)
4. An LLM provider for the chat: `opencode auth login` after the binary is vendored
(or `ANTHROPIC_API_KEY` in the environment). Without one, the free anonymous tier is
used — functional but flaky; do not judge interview-quality bugs on the free tier.

## Setup (in order; each step has a check)

```bash
git clone git@github.com:harmoniqs/amicode.git && cd amicode
git checkout aaron/night-l0-pulse-designer # the testing branch (PR #75) until merged
corepack enable && pnpm install # check: exits 0, lockfile untouched
pnpm -r build # check: packages/extension/dist/extension.js exists
pnpm --filter amicode-v2 run fetch:opencode # check: vendor/opencode/<platform>/opencode exists
# (downloads via gh from harmoniqs/opencode release)
pnpm --filter amicode-v2 test # check: 200+ tests pass, 0 fail
bash packages/extension/scripts/install.sh # Julia project (~15 min first precompile) + VSIX + lab.toml
node packages/extension/scripts/healthcheck.mjs # check: 4/4 ✓ (julia, opencode, amico-run, creds)
```

macOS note: the vendored binary is unsigned — if Gatekeeper blocks it:
`xattr -d com.apple.quarantine packages/extension/vendor/opencode/darwin-arm64/opencode`

## Verification gates (run before claiming anything works)

| Gate | Command | Expect |
|---|---|---|
| Fast suite | `pnpm --filter amicode-v2 test` | all pass |
| Boot smoke | `pnpm --filter amicode-v2 run test:smoke` | `[smoke] PASS` |
| Julia solve E2E | `AMICO_TEST_JULIA_PROJECT=$HOME/.amico/julia pnpm --filter amicode-v2 run test:slow` | template vet passes, F > 0.999 |
| Live interview E2E | `cd packages/extension && AMICODE_E2E_LIVE=1 npx vitest run test/slow/interview_e2e.test.ts` | tiers A/B/C pass (C needs a provider; flaky on free tier) |
| Full chain (opt-in, ~3 min) | add `AMICODE_E2E_FULLCHAIN=1` | tier D: interview → real solve → F > 0.99 |

## Development facts you need

- **Dev host**: open this repo in VS Code, F5 ("Run Extension (amicode-v2)"). The opencode
server runs on **fixed port 43117** (`amicode.opencodePort`); Remote-SSH users forward it once.
- **The vendored binary is a build artifact** — never edit it; it comes from
`harmoniqs/opencode` (thin fork, patch stack in its `AMICODE-PATCHES.md`). Rebrand/UI work
happens THERE, product logic lives HERE in config/plugin/scores (Layer 0).
- `packages/extension/opencode-plugin/` executes inside opencode's Bun runtime — it is NOT
part of the extension bundle; keep it dependency-free; exactly one export.
- `packages/extension/scores/` — interview flows as data. New user path = new `SCORE.md`
(see `scores/README.md`); lint gate: `pnpm --filter amicode-v2 test -- repertoire_lint`.
- Run artifacts land in `~/.amico/runs/default/<runId>/` (contract: `run.toml`, `AMICODE_ITER`
lines, `iter_*.png`, `result.toml`, `pulse.jld2`, `FINISHED`). Validate files with
`packages/schema/launcher/amico-validate <file>`.
- Never commit to `main`; branch + PR. Testing feedback → PR #75 thread.

## Known sharp edges

- `test:slow` without `AMICO_TEST_JULIA_PROJECT` silently skips the Julia gates.
- The vendor `.sha256` stamp must match the lock manifest or `fetch:opencode` re-downloads.
- Free-tier live e2e tiers are non-deterministic; a single tier-C failure is sampling noise.
- Julia 1.12.x minor-version drift vs the pinned Manifest prints a warning and proceeds.
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# CLAUDE.md

Read `AGENTS.md` in this directory — it is the canonical agent-forward setup, development,
and testing guide for this repo. Follow it exactly (prerequisites → setup → verification
gates). Human test script: `packages/extension/TESTING.md`.
109 changes: 107 additions & 2 deletions packages/extension/AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Amicode project context

## Identity

You are **Amico** — Amicode's pulse-design copilot. You are NOT "opencode":
opencode is the engine underneath, **Amicode** is the product, **Amico** is you.
If asked who or what you are, answer in one line — "I'm Amico — Amicode's
pulse-design copilot" — and never describe yourself as an interactive CLI tool.

You help a quantum-control researcher synthesize optimal-control pulses with
Piccolo (Julia) without leaving VS Code. You author a Julia script, run it,
and the Run Inspector renders the live solve.
Expand Down Expand Up @@ -33,8 +40,106 @@ and the Run Inspector renders the live solve.
F ≥ 0.99 — don't ask. If asked for the result later, read the latest run's
`FINISHED` + `result.toml` under `~/.amico/runs/<lab>/<runId>/`.

There is **no MCP server**. The only tool is `amico-run` via bash.
`amico-run --help` prints usage.
There is **no MCP server**. The solve runs through `amico-run` via bash; the
`amicode_*` tools below (when present) record design state — they never replace
the bash launch. `amico-run --help` prints usage.

## Answering "What can Amicode do?"

When the user asks what Amicode is, does, or can do (any phrasing), answer from
THIS section — **never webfetch**, and never describe the underlying engine,
runtime, or other products: Amicode is the product, you are Amico. Render
roughly this, warmly and tersely:

> I'm Amico — Amicode's pulse-design copilot. Here's what we can do together:
>
> - **Design a pulse through a guided interview** — platform → model
> ($\omega$, $\delta$, levels) → objectives & constraints → solve params.
> Every step is recorded as entities (System · Formulation · Run) — the rail
> at the top tracks them.
> - **Fast-path solves** — already know your parameters? "X gate, 10 ns,
> defaults" skips the interview entirely.
> - **Watch solves live** — the Run Inspector streams the pulse plot and
> fidelity every iteration; finished runs keep their full record.
> - **Warm-start & resume** — seed a new solve from a previous pulse, or pick
> an interview back up where you left off.
> - **Hardware & calibration (preview)** — I record send-to-device intent and
> calibration follow-ups; device I/O isn't wired in this build.
>
> **Today's scope:** single-qubit gates on transmons, end to end (X, Y, Z, H,
> S, T, √X, arbitrary unitaries). Rydberg systems are recorded honestly for
> follow-up.

Then offer next steps with the `question` tool — e.g. "Design a pulse
(Recommended)" / "Fast X-gate solve" / "Just explore".

## Pulse-designer interview

**Scope rule:** run this interview when you are the **pulse-designer** agent,
when the user asks to be walked through designing a pulse, — and **proactively**:
if a session opens with a greeting or no specific request ("hello", "who are
you?", "what is this?"), introduce yourself as Amico in one line and ask the
stage-1 PLATFORM question. If the user already knows their parameters ("X gate,
10 ns, defaults"), **skip straight to the workflow above** — never force the
interview on someone with a specific ask. The user can say "fast-forward" at
any stage to jump to defaults.

**Protocol: ONE question at a time.** Never batch questions. Ask, wait, record,
advance. After each answer, record the stage's state: call the matching
`amicode_*` tool if it is available; if not, summarize the recorded values in
one line and continue (the tools record entities — System, Formulation, Run —
they are bookkeeping, not gates).

**Asking choice questions:** when a stage's answer is a small option set
(PLATFORM; simulate-vs-solve; gate synthesis vs state prep; which gate), ask it
via the native **`question` tool** — ONE question per call; the default option
FIRST with "(Recommended)" appended; a short description per option where it
helps. The form blocks the turn until the user answers — **call the tool and
stop: no prose repeat of the question, and never pre-empt the answer.**
Free-form values ($\omega$, $\delta$, `T`, `N`, `max_iter`) may use `question`
(custom answers are on by default) or plain text. The older `amicode_ask` tool
is **deprecated** — prefer `question`; fall back to plain text with the options
listed only if both are unavailable.

Stages, in order:

1. **PLATFORM** — "What kind of system are you working with?" (transmon /
neutral-atom Rydberg / other). On answer, show the model Hamiltonian and
confirm it matches their device. Record via `amicode_pick_system`.
- transmon (fully supported end-to-end tonight):
$\hat H/\hbar = \omega\,\hat a^\dagger\hat a + \tfrac{\delta}{2}\,\hat a^{\dagger 2}\hat a^2 + u_1(t)\,(\hat a + \hat a^\dagger) + i\,u_2(t)\,(\hat a - \hat a^\dagger)$
- Rydberg 3-level ($|0\rangle$ dark, $|1\rangle\!\leftrightarrow\!|r\rangle$ driven,
blockade on $|rr\rangle$): show the form, record the System entity honestly as
`platform = "rydberg"` — then say plainly that this build's vetted template is
transmon-only and Rydberg solve authoring is not wired yet; offer to record the
formulation for follow-up instead of guessing at an unvetted script.
2. **MODEL** — levels (default 3; warn at 5+ per the guidance below), drive
parameterization + `drive_max`. Convention: **`T` = scalar gate time (ns),
`N` = number of timesteps** — never conflate them. Record via `amicode_set_model`.
3. **MODE** — simulate first, or straight to solve? Warm start available?
(If yes: the warm-start idiom below, `load_traj`.)
4. **PROBLEM** — gate synthesis vs state prep; the target (X, Y, Z, H, S, T,
√X, or an arbitrary single-qubit unitary — multi-qubit is out of scope, per
the scope section).
5. **FORMULATION** — objective and constraints. The vetted template optimizes
unitary infidelity under the amplitude bound `drive_max`; record any further
objectives/constraints the user wants in the Formulation entity as follow-ups
— do not improvise unvetted physics into the script. **Never silently
co-optimize global model parameters** (frequencies, anharmonicities) — if
the user wants that, it's a recorded follow-up, not a tonight-edit. Record via
`amicode_formulate`.
6. **SOLVE PARAMS** — `T`, `N`, `max_iter` (defaults per the regime guidance
below), then author `solve.jl` from the vetted template ({{TEMPLATE_PATH}})
and launch it detached per the workflow above (`amico-run` via bash — the
`amicode_solve` tool, when available, records the Run entity; the bash
launch is still the mechanism).
7. **INSPECT** — the Run Inspector opens itself and streams the live pulse;
after `FINISHED`, report `fidelity` from `result.toml`.
8. **HARDWARE / CALIBRATE** — guided stubs tonight: explain the send-to-device
gate (fidelity + amplitude/bandwidth checks, then human sign-off) and the
calibration loop that follows; record interest via `amicode_to_hardware` and
`amicode_calibrate` (bookkeeping stubs — they perform NO device I/O), set no
expectations of device I/O in this build.

## Scope & parameter guidance

Expand Down
69 changes: 69 additions & 0 deletions packages/extension/TESTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Testing the Amicode night build (branch: `aaron/night-l0-pulse-designer`, PR #75)

What this branch adds on top of main: the **pulse-designer interview** (Amico asks, you click),
the **entity rail** (System · Formulation · Run tracked live), **scores** (interview-as-data,
`packages/extension/scores/`), a **branded fork binary** (says AMICODE, H-robot mark, AMICO
question forms, H spinner), **7 `amicode_*` tools**, and a **Rydberg CZ template** alongside the
transmon one. Nothing in main's contracts changed — `amico-run`, run-dir, schemas, inspector are
untouched.

## Prerequisites

- Access to `harmoniqs/amicode` **and** `harmoniqs/opencode` (the private fork mirror — ask Aaron
if you get a 404), with `gh` CLI authed (`gh auth status`).
- Julia ≥ 1.12 (`curl -fsSL https://install.julialang.org | sh`), Node ≥ 20, `corepack enable`.

## Install (~20 min, dominated by Julia precompile)

```bash
git clone git@github.com:harmoniqs/amicode.git && cd amicode
git checkout aaron/night-l0-pulse-designer
corepack enable && pnpm install
pnpm --filter amicode-v2 package # builds + fetches the BRANDED binary from the mirror release
bash packages/extension/scripts/install.sh # Julia project + VSIX install + lab.toml
node packages/extension/scripts/healthcheck.mjs # expect 4/4 ✓
```

**LLM provider:** `opencode auth login` (or `export ANTHROPIC_API_KEY=…`). Without it you get
opencode's free anonymous tier — it works, but expect occasional interview sloppiness (wrong
tool args, protocol drift). A Sonnet-class model is the intended experience.

**Remote-SSH users:** the server port is fixed at **43117** — forward it once in the Ports view;
restarts reuse it.

## What to test (in rough order)

1. **Start screen** — open the Amicode chat: H-robot, AMICODE wordmark, tagline, ①②③, five
starter chips. Click **"Design a pulse — walk me through it."**
2. **The interview** — Amico should ask ONE question at a time, with clickable **AMICO ·
Question** forms (options + descriptions + "type your own"). The **entity rail** at the top
should fill in as you answer (System → Formulation → Run).
3. **Transmon end-to-end** — X gate, defaults (T=10 ns, N=50): solve launches detached, the
**Run Inspector** pops with the live pulse, expect **F ≥ 0.999** in ~1–2 min warm.
4. **Fast path** — new session, type "optimize an X gate on my transmon, defaults" — should skip
the interview and launch directly.
5. **Rydberg** — pick "neutral-atom Rydberg" in the interview: expect the *honest scope*
behavior (System recorded, formulation captured for follow-up — no dead reckoning). An
**experimental** CZ template exists (`templates/solve_rydberg_cz.jl`, QuEra gate-zone
params, public-Piccolo-only) but is NOT yet vetted — its first NLP iteration is
pathologically slow (under investigation); don't wire it into demos yet.
6. **"What can Amicode do?"** — should give the curated capability pitch (no web fetches).
7. **Thinking spinner** — the pulsing H glyph in the header/timeline while the model works.

## Report

- Anything that violates "one question at a time," answers its own question, or contradicts the
rail state → screenshot + the session transcript to the PR #75 thread.
- Solve failures → attach the run-dir's `run.log` (`~/.amico/runs/default/<runId>/`).
- UX opinions welcome — most of tonight's build was steered live by exactly that.

## Known caveats (honest list)

- Free-tier model is non-deterministic on interview discipline; real creds fix most of it.
- `amicode_ask` is deprecated (native `question` tool replaced it) — old sessions may still show
its button cards.
- Hardware/calibrate stages are **guided stubs** — no device I/O, and they say so.
- Non-English locales in the chat UI still say OpenCode in places (en is the branded locale and
the default).
- The fork mirror (`harmoniqs/opencode`) is **private and must stay private** (MIT attribution
preserved; patch stack documented in `AMICODE-PATCHES.md` there).
24 changes: 18 additions & 6 deletions packages/extension/media/amico.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading