diff --git a/packages/extension/AGENTS.md b/packages/extension/AGENTS.md index aa8eff9..1d55203 100644 --- a/packages/extension/AGENTS.md +++ b/packages/extension/AGENTS.md @@ -38,14 +38,14 @@ Sound like it — not a generic assistant. ## Workflow (this is the whole job) The script is authored at an explicit TRUST TIER and launched through the gate -`amico-run --spec`. All paths below use the active Problem workspace +`{{AMICO_RUN}} --spec`. All paths below use the active Problem workspace `~/.amico/problems//` (open/create/rename with `amicode_problem`; the workspace owns `solve.jl` — never author in `/tmp`). 1. **Resolve the tier** once the System + Formulation are recorded. From the Formulation, run: ```bash - amico-run resolve --platform --kind --size + {{AMICO_RUN}} resolve --platform --kind --size ``` It prints JSON: `{tier, source?, template_path?|exemplar_path?, packages, blocked_higher?}`. 2. **Author `solve.jl` per the tier** into `~/.amico/problems//solve.jl`: @@ -66,7 +66,7 @@ workspace owns `solve.jl` — never author in `/tmp`). 4. **free tier only — generate the env** (vetted/composed use the provisioned env unless `resolve` said otherwise): ```bash - amico-run sandbox ~/.amico/problems/ --packages + {{AMICO_RUN}} sandbox ~/.amico/problems/ --packages # then run the printed JULIA_PKG_USE_CLI_GIT=true julia --project=… Pkg.instantiate() line ``` 5. **Estimate, confirm routing, then assemble `~/.amico/problems//solvespec.json`.** @@ -79,7 +79,7 @@ workspace owns `solve.jl` — never author in `/tmp`). it specifies and do **not** ask where the solve should run. When the section is **absent**, this solve is LOCAL: run local and do NOT offer remote. - **Estimate (informs, never decides).** Run - `amico-run estimate ~/.amico/problems//solve.jl` — it prints ONE JSON line + `{{AMICO_RUN}} estimate ~/.amico/problems//solve.jl` — it prints ONE JSON line `{sizeClass, estimatedBytes, localRamBytes, offloadSuggested, reason, …}`. Surface it at the decision point: tell the researcher the `sizeClass`, the `estimatedBytes` vs local RAM, and the `reason`. The estimate only **suggests**, and only where a choice @@ -96,7 +96,7 @@ workspace owns `solve.jl` — never author in `/tmp`). env: `{{JULIA_PROJECT}}` (the provisioned env) for vetted/composed, or the sandbox env from step 4 for free (it must equal the spec's `env.project`). ```bash - ( nohup amico-run --spec ~/.amico/problems//solvespec.json \ + ( nohup {{AMICO_RUN}} --spec ~/.amico/problems//solvespec.json \ --project {{JULIA_PROJECT}} --lab default \ ~/.amico/problems//solve.jl \ > ~/.amico/problems//solve.log 2>&1 < /dev/null & ) @@ -116,9 +116,9 @@ workspace owns `solve.jl` — never author in `/tmp`). agree/disagree honestly — a `free` run is UNTRUSTED and cannot be promoted until verification agrees. -There is **no MCP server**. The solve runs through `amico-run` via bash; the +There is **no MCP server**. The solve runs through `{{AMICO_RUN}}` via bash; the `amicode_*` tools below (when present) record design state under the Problem -workspace — they never replace the bash launch. `amico-run --help` prints usage. +workspace — they never replace the bash launch. `{{AMICO_RUN}} --help` prints usage. ### Bookkeeping verbs (`amico` — same bash surface) @@ -322,7 +322,7 @@ Stages, in order: below); pass them to `amicode_solve` (it records them on the Formulation and writes the Run entity, stamped with the resolved `tier`), then author `solve.jl` and launch it through the tiered gate — **follow the Workflow - steps 1–7 above** (`amico-run resolve` → author per tier → `amico-run --spec` + steps 1–7 above** (`{{AMICO_RUN}} resolve` → author per tier → `{{AMICO_RUN}} --spec` via bash). For a stock single-qubit transmon gate this resolves to the **vetted** tier and is exactly the fill-in-the-block flow. 7. **INSPECT** — the Run Inspector opens itself and streams the live pulse; @@ -411,7 +411,7 @@ lists it — honestly caveated (see the PLATFORM stage). ## The run-dir contract your script MUST emit -`amico-run` writes `run.toml` (first) and `FINISHED` (last) itself. Your +`{{AMICO_RUN}}` writes `run.toml` (first) and `FINISHED` (last) itself. Your script, running with cwd = the run dir, must emit: - `AMICODE_ITER iter= f= inf_pr=<…> inf_du=<…>` to stdout, flushed, @@ -493,6 +493,18 @@ correct loader in this Piccolo. **{{JULIA_PROJECT}}**. Always pass it. +## Tool use + +- **The tools you need are at absolute paths already. Never hunt for them.** Use + `{{AMICO_RUN}}` and `{{JULIA_PROJECT}}` verbatim. Do **not** run + `which amico-run`, and never fall back to `find ~ -name …`, `find /usr -name …`, + or `pip list` to locate it — searching the filesystem for a path you were handed + is always wrong here. If a command genuinely fails, report the error and stop; + do not go looking for the binary. + +- Batch independent tool calls into one turn where it's natural; each turn is a + full round-trip. Serialize only when a later call needs an earlier result. + ## Style & formatting The user is a quantum-control researcher — skip the basics, keep the physics diff --git a/packages/extension/src/extension.ts b/packages/extension/src/extension.ts index fbc3920..36d9238 100644 --- a/packages/extension/src/extension.ts +++ b/packages/extension/src/extension.ts @@ -423,7 +423,11 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { const parsed = parseLibraryRootSpecs(raw); return parsed.length ? parsed : undefined; }; + // Absolute launcher path for AGENTS.md's {{AMICO_RUN}} — so the agent never + // needs `which`, and never falls back to scanning $HOME (417s measured waste). + const amicoRunPath = amicoRunBinDir ? path.join(amicoRunBinDir, "amico-run") : undefined; const opencodeProject = prepareOpencodeProject({ + amicoRunPath, agentsSrc: path.resolve(ctx.extensionPath, "AGENTS.md"), // MODE-SELECTED vetted template: HP sessions get the Piccolissimo variant // (same run-dir contract, spline solver layer). An AGENTS.md instruction @@ -573,6 +577,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { opencodeChannel.appendLine(`[solver] switching → ${mode}`); applyEntitlementForMode(mode, path.join(os.homedir(), ".amico", "amicode")); const project2 = prepareOpencodeProject({ + amicoRunPath, agentsSrc: path.resolve(ctx.extensionPath, "AGENTS.md"), // Same mode-selection as boot; `mode` is the requested target of THIS // switch (the state file still reads status:"switching" here). @@ -707,6 +712,7 @@ export async function activate(ctx: vscode.ExtensionContext): Promise { } const port = vscode.workspace.getConfiguration("amicode").get("opencodePort", 0); const project2 = prepareOpencodeProject({ + amicoRunPath, agentsSrc: path.resolve(ctx.extensionPath, "AGENTS.md"), templateSrc: path.resolve( ctx.extensionPath, diff --git a/packages/extension/src/opencode_config.ts b/packages/extension/src/opencode_config.ts index b543d3f..6d3d561 100644 --- a/packages/extension/src/opencode_config.ts +++ b/packages/extension/src/opencode_config.ts @@ -464,6 +464,14 @@ export interface OpencodeConfigOptions { /** Julia project (--project) the agent should use; already resolved (see * resolveJuliaProject). Substituted into AGENTS.md as {{JULIA_PROJECT}}. */ juliaProject: string | undefined; + /** Absolute path to the `amico-run` launcher, substituted into AGENTS.md as + * {{AMICO_RUN}}. PATH augmentation already happens at spawn time, but when it + * fails the agent fell back to `which amico-run || find ~ -name amico-run`, + * and an unbounded scan of $HOME costs ~2 minutes EACH: 128 such calls totalling + * 417s were measured in one session's history (2026-08-03). Handing over the + * absolute path removes the reason to search at all. Undefined leaves the + * placeholder resolving to the bare command (previous behaviour). */ + amicoRunPath?: string; /** Scores repertoire root (SCORE.md manifests). Default: the bundled scores/. */ scoresRoot?: string; /** Dir holding the user's entitlements.toml (access-code stub). Default: ~/.amico/amicode. */ @@ -524,7 +532,11 @@ export function prepareOpencodeProject(opts: OpencodeConfigOptions): OpencodePro : "# Amicode\nRead the template at {{TEMPLATE_PATH}}, fill params, run `amico-run