-
Notifications
You must be signed in to change notification settings - Fork 1
β.6: demo dry-run + failure fallback (closes #6) #11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
c5c2163
feat(extension): AGENTS.md launches amico-run detached (portable nohu…
Rchari1 b06e129
feat(extension): bundle pre-baked known-good run-dir for the demo fal…
Rchari1 b3f413f
feat(extension): stageDemoRun — stage bundled demo run into runs root…
Rchari1 6992701
feat(extension): amicode.replayDemo command — on-site fallback render…
Rchari1 ddec597
docs(extension): β run-dir contract freeze (DoD) + demo acceptance ch…
Rchari1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,3 +11,4 @@ tsconfig.json | |
| **/*.map | ||
| !bin/** | ||
| !julia/** | ||
| !demo/** | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| # Amicode run-dir contract — β freeze (wk-3, Phase-β DoD) | ||
|
|
||
| This is the **frozen** contract every Amicode solve emits and the Run Inspector | ||
| consumes. It is the seam between the orchestrator (`@amicode/amico-run`, β.1), | ||
| the bundled agent (`AGENTS.md` + `solve_template.jl`, β.3), and the extension's | ||
| watcher/inspector. **Frozen for the β phase** — changes after wk-3 go through | ||
| Phase 0' (the SchemaPackage supersedes the provisional validators below). | ||
|
|
||
| ## Layout | ||
|
|
||
| A run lives at `~/.amico/runs/<lab-id>/<runId>/`, where `runId` is | ||
| `r<UTC-timestamp>Z-<hex>` (e.g. `r20260617-161814Z-e8cb`). `amico-run` writes | ||
| `manifest.toml` **first** and `FINISHED` **last**; the script (cwd = the run dir) | ||
| emits the rest. | ||
|
|
||
| | Artifact | Writer | Contents | | ||
| |---|---|---| | ||
| | `manifest.toml` | amico-run (first) | `schema_version = "1"`, snake_case keys: `run_id`, `lab`, `lab_id`, `script_path`, `created_at`, `orchestrator_version`, and a `[julia]` table (`binary`, optional `project`/`sysimage`). | | ||
| | `run.log` | amico-run (stdout tee) | One `AMICODE_ITER iter=<n> f=<obj> inf_pr=<…> inf_du=<…>` line per Ipopt iteration (drives the live stats row), plus a final `DONE fidelity=<…>` line and any Julia traceback. | | ||
| | `iter_<N>.png` | script | Per-iteration pulse/fidelity plot. `N` is the iteration with **unbounded digits** (`iter_0`, `iter_10`, … `iter_0060`). The inspector globs `iter_*.png`. | | ||
| | `result.toml` | script (atomic) | Written `result.toml.tmp` then renamed. At least `fidelity` (float) and `iterations` (int); `wall_seconds` optional. | | ||
| | `FINISHED` | amico-run (last, terminal) | `status = "completed" | "failed" | "aborted"` and `exit_code` (int). Its presence is the **only** completion signal — the inspector fires `onFinished` solely on a valid `FINISHED`, so a killed solve shows "running", never a false success. | | ||
|
|
||
| Two convenience files live at the **lab runs root** (`~/.amico/runs/<lab-id>/`): | ||
|
|
||
| | File | Writer | Contents | | ||
| |---|---|---| | ||
| | `index` | amico-run (`appendIndex`) | Append-only, tab-separated `<runId>\t<createdAt>\t<scriptPath>` per run. | | ||
| | `latest` | amico-run (`updateLatest`) | Symlink → the most recent `<runId>`; written via temp-then-rename so the watcher sees an atomic swing. The inspector follows `latest`. | | ||
|
|
||
| ## Frozen schemas | ||
|
|
||
| The provisional validators in `@amicode/amico-run` are the β source of truth: | ||
|
|
||
| - `validateManifest` — `schema_version === "1"`; the six string keys non-empty; a `[julia]` table with a string `binary`. | ||
| - `validateFinished` — `status` ∈ {completed, failed, aborted}; integer `exit_code`. | ||
| - `validateResult` — numeric `fidelity`; integer `iterations`. | ||
|
|
||
| These are **frozen for β**. The Phase 0' SchemaPackage replaces them; any contract | ||
| change before then is a breaking change to the watcher and must be coordinated. | ||
|
|
||
| ## Exit codes (amico-run) | ||
|
|
||
| - `0` — `FINISHED.status == "completed"`. | ||
| - `130` — `aborted` (SIGINT/SIGTERM, e.g. the inspector's stop control). | ||
| - `64` — usage/config error, orchestrator fault (any unexpected throw), or a | ||
| missing `FINISHED` (write fault). | ||
| - otherwise — the Julia process's return code (a `failed` run; `1` if it failed | ||
| with a zero return code). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # Amicode demo acceptance checklist (β.6) | ||
|
|
||
| Sign off **before** the live demo. The presenter runs this on the target machine | ||
| after the [RUNBOOK](./RUNBOOK.md) install. Pre-flight (rows 1–3) is the safety | ||
| net; rows 4–6 are the live run. | ||
|
|
||
| ## Pre-flight (arm the fallback first) | ||
|
|
||
| - [ ] **Install clean** — followed `RUNBOOK.md` end-to-end on the target machine; total time recorded below (target ≤ 60 min). | ||
| - [ ] **Healthcheck green** — `node packages/extension/scripts/healthcheck.mjs` exits `0` (julia + pinned Piccolo project · opencode `/event` · `amico-run` · Bedrock creds). | ||
| - [ ] **Fallback armed** — Command Palette → **"Amicode: Replay demo run"** stages the bundled solve and the Run Inspector renders it (iter frames + final fidelity + promote prompt), with **no Julia, no opencode, no creds**. Confirm this works *before* relying on the live path. | ||
|
|
||
| ## Live run | ||
|
|
||
| - [ ] **Chat → script** — a chat prompt makes the agent read the template, author `solve.jl`, and launch `amico-run` **detached** (`( nohup … & )`); the chat returns immediately with "Solve launched — watch the Run Inspector" and is **not** blocked by the solve. | ||
| - [ ] **Inspector streams** — the Run Inspector shows `AMICODE_ITER` rows advancing + `iter_*.png` frames updating while the solve runs in the background. | ||
| - [ ] **Fidelity shown** — on completion the inspector reports the final fidelity (F ≥ 0.99 → promote prompt fires automatically). | ||
|
|
||
| ## Definition-of-Done (Phase β) | ||
|
|
||
| - [ ] **Contract frozen** — the run-dir contract + provisional schemas are frozen and documented in [`CONTRACT.md`](./CONTRACT.md). | ||
| - [ ] **Timings recorded** — clean-machine install + first-solve timings written into `RUNBOOK.md` (cold first run pays Julia precompile/JIT on top of the warm ~100 s solve). | ||
|
|
||
| --- | ||
|
|
||
| **Recorded timings (fill in at the dry-run):** | ||
|
|
||
| | Step | Time | | ||
| |---|---| | ||
| | Julia install | | | ||
| | `install.sh` (instantiate + precompile + VSIX) | | | ||
| | Healthcheck | | | ||
| | First live solve (cold) | | | ||
| | Replay fallback | instant | | ||
| | **Total** | | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| status = "completed" | ||
| exit_code = 0 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| schema_version = "1" | ||
| run_id = "r20260617-161814Z-e8cb" | ||
| script_path = "/Users/raghavchari/amicode/packages/extension/templates/solve_template.jl" | ||
| lab = "default" | ||
| lab_id = "default" | ||
| created_at = "2026-06-17T16:18:14.159Z" | ||
| orchestrator_version = "0.1.0" | ||
|
|
||
| [julia] | ||
| binary = "julia" | ||
| project = "/Users/raghavchari/.amico/julia" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| iterations = 60 | ||
| fidelity = 0.9999788203047787 | ||
| wall_seconds = 101.5023238658905 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { copyFileSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from "node:fs"; | ||
| import { join } from "node:path"; | ||
| import { generateRunId, appendIndex, updateLatest } from "@amicode/amico-run"; | ||
|
|
||
| /** | ||
| * Copy a bundled demo run-dir into the runs root under a fresh β.1 runId, | ||
| * rewrite manifest.toml's `run_id` to match the new directory, append the | ||
| * index, and swing `latest` to it. Reuses the β.1 run-dir primitives so the | ||
| * staged run is byte-for-byte contract-identical and the existing | ||
| * RunsRootWatcher renders it exactly like a live solve. | ||
| * | ||
| * Filesystem side effects only (pure w.r.t. its inputs). Returns the staged | ||
| * run directory. | ||
| */ | ||
| export function stageDemoRun(demoDir: string, runsRoot: string): string { | ||
| mkdirSync(runsRoot, { recursive: true }); | ||
| const runId = generateRunId(runsRoot); | ||
| const runDir = join(runsRoot, runId); | ||
| mkdirSync(runDir); | ||
| for (const f of readdirSync(demoDir)) { | ||
| if (f === "manifest.toml") { | ||
| const m = readFileSync(join(demoDir, f), "utf8").replace( | ||
| /run_id\s*=\s*"[^"]*"/, | ||
| `run_id = ${JSON.stringify(runId)}`, | ||
| ); | ||
| writeFileSync(join(runDir, f), m); | ||
| } else { | ||
| copyFileSync(join(demoDir, f), join(runDir, f)); | ||
| } | ||
| } | ||
| appendIndex(runsRoot, runId, new Date().toISOString(), "demo-replay"); | ||
| updateLatest(runsRoot, runId); | ||
| return runDir; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { describe, it, expect } from 'vitest' | ||
| import { mkdtempSync, writeFileSync, readFileSync, readlinkSync, existsSync } from 'node:fs' | ||
| import { tmpdir } from 'node:os' | ||
| import { join } from 'node:path' | ||
| import { parse } from 'smol-toml' | ||
| import { validateManifest, validateFinished } from '@amicode/amico-run' | ||
| import { stageDemoRun } from '../src/demo_replay' | ||
|
|
||
| function fakeDemo(): string { | ||
| const d = mkdtempSync(join(tmpdir(), 'demo-')) | ||
| writeFileSync(join(d, 'manifest.toml'), | ||
| `schema_version = "1"\nrun_id = "rDEMO"\nscript_path = "/demo.jl"\nlab = "default"\nlab_id = "default"\ncreated_at = "2026-06-17T00:00:00Z"\norchestrator_version = "0.1.0"\n[julia]\nbinary = "julia"\n`) | ||
| writeFileSync(join(d, 'run.log'), 'AMICODE_ITER iter=10 f=0.1 inf_pr=1e-8 inf_du=1e-6\n') | ||
| writeFileSync(join(d, 'iter_0010.png'), 'PNG') | ||
| writeFileSync(join(d, 'result.toml'), 'fidelity = 0.9999\niterations = 10\n') | ||
| writeFileSync(join(d, 'FINISHED'), 'status = "completed"\nexit_code = 0\n') | ||
| return d | ||
| } | ||
|
|
||
| describe('stageDemoRun', () => { | ||
| it('stages the demo into a fresh runId, rewrites manifest run_id, swings latest', () => { | ||
| const demo = fakeDemo() | ||
| const runsRoot = mkdtempSync(join(tmpdir(), 'runs-')) | ||
| const runDir = stageDemoRun(demo, runsRoot) | ||
| const runId = runDir.split('/').pop()! | ||
| expect(runId).toMatch(/^r\d{8}-\d{6}Z-[0-9a-f]{4}$/) // β.1 runId format | ||
| expect(existsSync(join(runDir, 'iter_0010.png'))).toBe(true) | ||
| const m = parse(readFileSync(join(runDir, 'manifest.toml'), 'utf8')) as Record<string, unknown> | ||
| expect(validateManifest(m).ok).toBe(true) | ||
| expect(m.run_id).toBe(runId) // rewritten to match the dir | ||
| expect(validateFinished(parse(readFileSync(join(runDir, 'FINISHED'), 'utf8'))).ok).toBe(true) | ||
| expect(readlinkSync(join(runsRoot, 'latest'))).toBe(runId) // the watcher will follow this | ||
| expect(readFileSync(join(runsRoot, 'index'), 'utf8')).toContain(runId) // appended to the index | ||
| }) | ||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Step 2 copies to
solve.jlbut you run/tmp/amicode-work/solve.jlhere — have step 2 write to that path so they match.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in e21539c (on #23, stacked above) — step 2 now writes
/tmp/amicode-work/solve.jl, the exact path step 3 runs (mkdir -p /tmp/amicode-work && cp {{TEMPLATE_PATH}} /tmp/amicode-work/solve.jl).