Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 41 additions & 2 deletions packages/extension/scores/overture/SCORE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@ stages:
prompt: "I can scan your existing AI-tool configs to bootstrap your workspace — want me to?"
choices: ["Yes, scan my configs", "No thanks, skip"]
default: "Yes, scan my configs"
- id: demo
optional: true
questions:
- id: demo_offer
prompt: "Want me to show you the full workflow end-to-end? (requires Julia)"
choices: ["Yes, show me", "Skip the demo"]
default: "Yes, show me"
---

You are running the **overture** — Amico's onboarding interview (session zero).
Expand Down Expand Up @@ -125,7 +132,39 @@ Per-stage guidance and the `amicode_profile` mapping:
- If no scannable files are found, say so honestly: "I didn't find any
AI-tool configs to import — no worries, we'll build your context as we go."

After seeding (or declining), advance to the next stage. **Stages 4–8 are
defined in subsequent slices** — for now, after Stage 3 completes, record
After seeding (or declining), advance to Stage 4 (demo).

4. **demo** _(optional)_ — check Julia readiness by calling
`amicode_demo_check`. This returns `{ready: true|false, reason?}`.

**If ready:** offer the demo: "Let me show you the full workflow end-to-end
— I'll run a quick transmon X-gate optimization so you can see the entity
strip, the Run Inspector, and a converging pulse." Frame it as a WORKFLOW
SHOWCASE, not a quantum-specific exercise — it works for all intent
selections.

On accept, call `amicode_demo_launch`. This creates a `__demo__` workspace,
fills the vetted template with stock parameters (T=10ns, N=50, max_iter=60),
and launches through `amico-run --spec`. The Run Inspector streams
iterations live. After FINISHED, report the result: "Solved — F=0.9998 in
47 iterations" (or whatever the actual numbers are). Then call
`amicode_demo_archive` to clean up the ephemeral workspace.

**If not ready:** explain honestly: "Julia environment isn't set up yet —
{reason}. No worries, we'll skip the demo. You can always run one later
from the command palette." Advance without blocking.

**If the user DECLINES the demo:** say "No problem" and advance.

**If the demo FAILS** (Julia error, convergence failure): report honestly
and continue. A failed demo never blocks onboarding.

**Constraints:**
- The demo MUST use the vetted template — never free-tier.
- The demo MUST NOT create vault artifacts (no problem card, no pulse bank entry).
- If `isDemoCompleted()` is true (archive marker exists), skip — don't re-offer.

After the demo (or skipping), advance to the next stage. **Stages 5–8 are
defined in subsequent slices** — for now, after Stage 4 completes, record
the completion marker: `amicode_profile {entity:"onboarding_completed"}`
and hand off to a normal session.
183 changes: 183 additions & 0 deletions packages/extension/src/demo_showcase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Demo workflow showcase — Stage 4: Julia gate + __demo__ workspace (#437)
//
// Readiness gate (Julia on PATH + Manifest.toml exists), demo workspace
// creation/archival, and the score-stage logic for running the transmon X-gate
// demo as a workflow showcase.

import * as fs from "node:fs";
import * as path from "node:path";
import * as os from "node:os";
import { execFileSync } from "node:child_process";

// ─── Readiness gate ──────────────────────────────────────────────────────────

export interface ReadinessResult {
ready: boolean;
juliaOnPath: boolean;
manifestExists: boolean;
reason?: string;
}

/** Check if the Julia environment is ready for the demo.
* Both conditions must pass: julia binary on PATH AND ~/.amico/julia/Manifest.toml exists. */
export function checkJuliaReadiness(
manifestPath: string = path.join(os.homedir(), ".amico", "julia", "Manifest.toml"),
): ReadinessResult {
const juliaOnPath = isJuliaOnPath();
const manifestExists = fs.existsSync(manifestPath);

if (juliaOnPath && manifestExists) {
return { ready: true, juliaOnPath, manifestExists };
}

const reasons: string[] = [];
if (!juliaOnPath) reasons.push("Julia binary not found on PATH");
if (!manifestExists) reasons.push("Julia environment not precompiled (~/.amico/julia/Manifest.toml missing)");

return {
ready: false,
juliaOnPath,
manifestExists,
reason: reasons.join("; "),
};
}

/** Check if `julia` is available on PATH. */
function isJuliaOnPath(): boolean {
try {
execFileSync("which", ["julia"], { encoding: "utf8", timeout: 5000 });
return true;
} catch {
return false;
}
}

/** Testable version that accepts a checker function. */
export function checkJuliaReadinessWithChecker(
juliaOnPath: boolean,
manifestPath: string = path.join(os.homedir(), ".amico", "julia", "Manifest.toml"),
): ReadinessResult {
const manifestExists = fs.existsSync(manifestPath);

if (juliaOnPath && manifestExists) {
return { ready: true, juliaOnPath, manifestExists };
}

const reasons: string[] = [];
if (!juliaOnPath) reasons.push("Julia binary not found on PATH");
if (!manifestExists) reasons.push("Julia environment not precompiled (~/.amico/julia/Manifest.toml missing)");

return { ready: false, juliaOnPath, manifestExists, reason: reasons.join("; ") };
}

// ─── Demo workspace management ───────────────────────────────────────────────

export const DEMO_WORKSPACE_NAME = "__demo__";

/** Resolve the demo workspace path. */
export function demoWorkspacePath(
problemsRoot: string = path.join(os.homedir(), ".amico", "problems"),
): string {
return path.join(problemsRoot, DEMO_WORKSPACE_NAME);
}

/** Check if a demo has already been completed (archive marker exists). */
export function isDemoCompleted(
problemsRoot: string = path.join(os.homedir(), ".amico", "problems"),
): boolean {
const archivePath = path.join(problemsRoot, `${DEMO_WORKSPACE_NAME}.archived`);
const workspacePath = demoWorkspacePath(problemsRoot);
// Archived marker OR a FINISHED file in the workspace
if (fs.existsSync(archivePath)) return true;
if (fs.existsSync(path.join(workspacePath, "FINISHED"))) return true;
return false;
}

/** Create the __demo__ workspace with the vetted solve.jl for transmon X gate. */
export function createDemoWorkspace(
problemsRoot: string = path.join(os.homedir(), ".amico", "problems"),
templateContent: string = DEFAULT_DEMO_SOLVE,
): string {
const wsPath = demoWorkspacePath(problemsRoot);
fs.mkdirSync(wsPath, { recursive: true });
fs.writeFileSync(path.join(wsPath, "solve.jl"), templateContent);
return wsPath;
}

/** Archive the demo workspace after completion.
* Creates a `.archived` marker and optionally removes the workspace. */
export function archiveDemoWorkspace(
problemsRoot: string = path.join(os.homedir(), ".amico", "problems"),
): void {
const wsPath = demoWorkspacePath(problemsRoot);
const archivePath = path.join(problemsRoot, `${DEMO_WORKSPACE_NAME}.archived`);

// Write archive marker with timestamp
fs.writeFileSync(archivePath, JSON.stringify({
archived_at: new Date().toISOString(),
reason: "demo_completed",
}) + "\n");

// Remove the workspace directory (it's ephemeral)
try {
fs.rmSync(wsPath, { recursive: true, force: true });
} catch {
// Non-critical — marker is what matters
}
}

/** Check if a given problem name is the demo workspace (for exclusion from listings). */
export function isDemoWorkspace(name: string): boolean {
return name === DEMO_WORKSPACE_NAME || name === `${DEMO_WORKSPACE_NAME}.archived`;
}

// ─── Demo solve parameters (stock, vetted) ───────────────────────────────────

export const DEMO_PARAMS = {
platform: "transmon",
gate: "X",
T: 10, // ns
N: 50, // timesteps
max_iter: 60,
levels: 3,
drive_max: 0.2, // GHz
} as const;

/** The solve.jl content for the demo. In production this would be filled from
* the vetted template; here we define the stock parameters that go into it. */
export const DEFAULT_DEMO_SOLVE = `# Amicode Demo — Transmon X Gate (vetted template, stock params)
# This file is auto-generated for the onboarding demo workflow showcase.
# Parameters: T=${DEMO_PARAMS.T}ns, N=${DEMO_PARAMS.N}, max_iter=${DEMO_PARAMS.max_iter}
#
# The actual solve.jl is authored from the vetted template at launch time
# via amico-run resolve + the fill-in-the-block flow.
`;

// ─── Demo solvespec ──────────────────────────────────────────────────────────

export interface DemoSolveSpec {
schema_version: "2";
script_path: string;
lab_id: string;
executor: "local";
tier: "vetted";
env: { kind: "provisioned"; project: string };
source: { template: string };
}

/** Build the solvespec for the demo run. */
export function buildDemoSolveSpec(
scriptPath: string,
juliaProject: string = path.join(os.homedir(), ".amico", "julia"),
templatePath: string = "",
): DemoSolveSpec {
return {
schema_version: "2",
script_path: scriptPath,
lab_id: "default",
executor: "local",
tier: "vetted",
env: { kind: "provisioned", project: juliaProject },
source: { template: templatePath },
};
}
Loading
Loading