Skip to content
28 changes: 28 additions & 0 deletions packages/amico-run/src/catalog_verb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,30 @@ export function catalogIngest(argv: string[]): VerbResult {

const id = flagValue(argv, "--id") ?? nextVersionId(records, platform, gate);
const warmStart = flagValue(argv, "--warm-start") ?? incumbent?.id ?? "";
// ── SEAM 5 (amicode #681): the chain's provenance flags ─────────────────────
// The calibrate→pin→re-optimize chain stages this exact command; the
// recording path later VERIFIES the fingerprint these write. Additive —
// absent flags write no keys (pre-chain entries unchanged).
const calibrationRef = flagValue(argv, "--calibration-ref");
const pinRaw = flagValue(argv, "--pin");
const pinProblems: string[] = [];
const pinnedGlobals: Record<string, number> = {};
if (pinRaw !== undefined) {
for (const pair of pinRaw.split(",")) {
const idx = pair.indexOf("=");
const k = pair.slice(0, idx).trim();
const v = Number(pair.slice(idx + 1).trim());
if (idx === -1 || k === "" || !Number.isFinite(v)) {
pinProblems.push(`--pin entries must be name=number (got "${pair.trim()}")`);
} else {
pinnedGlobals[k] = v;
}
}
if (Object.keys(pinnedGlobals).length === 0 && pinProblems.length === 0) {
pinProblems.push("--pin was given but parsed to no globals");
}
}
if (pinProblems.length > 0) return fail(`invalid --pin: ${pinProblems.join("; ")}`);
const tagsRaw = flagValue(argv, "--tags");
const tags = tagsRaw
? tagsRaw
Expand Down Expand Up @@ -206,6 +230,10 @@ export function catalogIngest(argv: string[]): VerbResult {
meta.path = relPath;
meta.branch = flagValue(argv, "--branch") ?? "main";
meta.warm_start = warmStart;
// SEAM 5 (#681): the chain's fingerprint — additive metadata (reuse of the
// note schema; warm_start above is the seed lineage this chain relies on).
if (calibrationRef) meta.calibration_ref = calibrationRef;
if (pinRaw !== undefined) meta.pinned_globals = pinnedGlobals;
if (tags) meta.tags = tags;
meta.date = new Date().toISOString().slice(0, 10);

Expand Down
24 changes: 24 additions & 0 deletions packages/amico-run/src/repertoire.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,14 @@ export interface PulseRecord {
warm_start?: string; // lineage: the incumbent id this was warm-started from
tags?: string[];
date?: string; // ISO date "YYYY-MM-DD"
// ── SEAM 5 (amicode #681): the calibrate→pin→re-optimize chain's provenance ──
// The chain's re-bank carries its fingerprint — which calibration, which pin,
// which warm-start seed — as ADDITIVE metadata fields (`warm_start` above IS
// the seed). The recording path (extension opencode-plugin/calib_chain.ts)
// VERIFIES these before the chain's executed marker can land. Additive keys:
// old entries simply lack them.
calibration_ref?: string; // which calibration: the chain record / rehearsal artifact ref
pinned_globals?: Record<string, number>; // which pin: global → calibrated value
dir: string; // ABS path to the entry directory
}

Expand All @@ -56,6 +64,19 @@ function dateStr(v: unknown): string | undefined {
return undefined;
}

/** A `[pinned_globals]`-style inline table: every value a finite number. Returns
* undefined for anything that isn't a clean number table (SEAM 5 #681 — a
* half-parseable pin set is worse than absent). */
function pinTable(v: unknown): Record<string, number> | undefined {
if (typeof v !== "object" || v === null || Array.isArray(v)) return undefined;
const out: Record<string, number> = {};
for (const [k, val] of Object.entries(v as Record<string, unknown>)) {
if (typeof val !== "number" || !Number.isFinite(val)) return undefined;
out[k] = val;
}
return out;
}

function parseRecord(file: string, dir: string): PulseRecord | undefined {
let parsed: Record<string, unknown>;
try {
Expand Down Expand Up @@ -85,6 +106,9 @@ function parseRecord(file: string, dir: string): PulseRecord | undefined {
warm_start: str(parsed.warm_start) ?? str(parsed.warm_started_from),
tags: Array.isArray(parsed.tags) ? parsed.tags.filter((t): t is string => typeof t === "string") : undefined,
date: dateStr(parsed.date),
// SEAM 5 (#681): the chain provenance — additive, absent on pre-chain entries.
calibration_ref: str(parsed.calibration_ref),
pinned_globals: pinTable(parsed.pinned_globals),
};
}

Expand Down
67 changes: 67 additions & 0 deletions packages/amico-run/test/catalog_verb.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,71 @@ describe("amico catalog ingest (bundle) — the promotion gate", () => {
expect(r.code).toBe(64);
expect(JSON.parse(r.stdout).error).toMatch(/not found/);
});

// ── SEAM 5 (amicode #681): the chain's provenance rides the catalog note ─────
// The calibrate→pin→re-optimize chain's re-bank carries its fingerprint —
// which calibration, which pin, which warm-start seed — as ADDITIVE metadata
// fields (the note schema's open growth; the existing warm_start field IS the
// seed). The chain stages this exact command; the recording path (extension
// side, calib_chain.ts) later VERIFIES the fingerprint against these fields.
it("--calibration-ref + --pin + --warm-start write the chain's fingerprint (which calibration, which pin, which seed); loadRepertoire reads all three back", () => {
seedEntry(pulses, "transmon-X-v1", { platform: "transmon", gate: "X", fidelity: 0.98 });
const newPulse = join(pulses, "..", "chain-pulse.jld2");
writeFileSync(newPulse, "calibrated-pulse");
const r = run(
[
"catalog", "ingest",
"--platform", "transmon", "--kind", "X",
"--artifact", newPulse, "--fidelity", "0.9995",
"--agree", "true",
"--warm-start", "transmon-X-v1",
"--calibration-ref", "/problems/chain/entities/calib_chain.toml",
"--pin", "delta=0.21",
],
{ AMICO_CATALOG_DIR: pulses },
);
expect(r.code).toBe(0);
expect(JSON.parse(r.stdout).promoted).toBe(true);
const meta = readToml(join(pulses, "transmon-X-v2", "metadata.toml"));
expect(meta.warm_start).toBe("transmon-X-v1"); // which seed (the existing lineage field)
expect(meta.calibration_ref).toBe("/problems/chain/entities/calib_chain.toml"); // which calibration
expect(meta.pinned_globals).toEqual({ delta: 0.21 }); // which pin
// round-trip: the repertoire loader surfaces the fingerprint (additive fields)
const rec = queryIncumbent(loadRepertoire(pulses), "transmon", "X").incumbent;
expect(rec?.warm_start).toBe("transmon-X-v1");
expect(rec?.calibration_ref).toBe("/problems/chain/entities/calib_chain.toml");
expect(rec?.pinned_globals).toEqual({ delta: 0.21 });
});

it("--pin parses multi-global comma lists; a malformed pin value is refused honestly (exit 64, no write)", () => {
const newPulse = join(pulses, "..", "p.jld2");
writeFileSync(newPulse, "x");
const r = run(
[
"catalog", "ingest",
"--platform", "transmon", "--kind", "X",
"--artifact", newPulse, "--fidelity", "0.9999", "--agree", "true",
"--pin", "delta=0.21,omega=4.9",
],
{ AMICO_CATALOG_DIR: pulses },
);
expect(r.code).toBe(0);
expect(readToml(join(pulses, "transmon-X-v1", "metadata.toml")).pinned_globals).toEqual({ delta: 0.21, omega: 4.9 });

const bad = join(pulses, "..", "p2.jld2");
writeFileSync(bad, "x");
const r2 = run(
[
"catalog", "ingest",
"--platform", "transmon", "--kind", "X",
"--artifact", bad, "--fidelity", "0.99995", "--agree", "true",
"--id", "transmon-X-v2",
"--pin", "delta=not-a-number",
],
{ AMICO_CATALOG_DIR: pulses },
);
expect(r2.code).toBe(64);
expect(JSON.parse(r2.stdout).error).toMatch(/--pin/);
expect(existsSync(join(pulses, "transmon-X-v2"))).toBe(false);
});
});
127 changes: 127 additions & 0 deletions packages/extension/opencode-plugin/amicode_tools.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ import {
import {
guardAndRecordStage, completeStage } from "./score_guard";
import { readRehearsalRecord } from "./rehearsal";
import {
recordCalibChain,
completeCalibChain,
type ChainLeg,
} from "./calib_chain";
import {
SPAWN_MAX_COUNT,
SPAWN_MAX_DEPTH,
Expand Down Expand Up @@ -1208,6 +1213,128 @@ export const AmicodeTools = async (input: unknown) => {
);
},
},

// SEAM 5 (#681) — the calibrate→pin→re-optimize→re-bank chain: ONE recorded
// verb path composed from existing seams. The recording core (calib_chain.ts)
// owns the logic and is unit-tested; this wrapper is the agent-facing
// surface (args → core → AMICODE_DIFF receipt), never a launch, never a
// promotion (the staged re-bank runs out-of-band, human-gated).
amicode_calib_chain: {
description:
"Record the calibrate→pin→re-optimize→re-bank chain (SEAM 5, #681) — the drift-response " +
"tune-up as ONE recorded verb. TWO calls, one chain: STAGE with the calibration + pin + " +
"seed; COMPLETE with the promoted entry's metadata once the re-bank ran.\n" +
"CALIBRATE (leg=mock): the SEAM 1 MockSoc rehearsal is the calibration data source — " +
"run it first per the run-launch seam (bash, julia --startup-file=no): " +
"julia --startup-file=no --project=<ext>/templates/mocksoc-rehearsal " +
"<ext>/templates/mocksoc_rehearsal.jl <pulse.jld2> <result.toml> [out_dir], and pass the " +
"rehearsal.toml as rehearsal_ref (validated through the same reader amicode_to_hardware " +
"uses — a dishonest artifact records nothing). leg=hardware is REFUSED: real-board " +
"sessions are an enumerated human gate and this build has no real-board session surface.\n" +
"PIN: pass `pinned` (global → calibrated value, e.g. {delta: 0.21}) — it lands on the " +
"recorded formulation as the existing calibration_pin constraint (the " +
"fix_global_variable! path) + solve.pinned_globals; re-staging replaces the pin.\n" +
"RE-OPTIMIZE: pass warm_start (the bank seed — catalog entry id or pulse ref); the run " +
"stub records it. The re-solve itself launches through the EXISTING solve path (bash " +
"amico-run), warm-started via the load_traj idiom; pass its run_dir when known.\n" +
"RE-BANK: the tool STAGES the exact `amico catalog ingest` command with the chain's " +
"provenance flags (--warm-start/--calibration-ref/--pin — which calibration, which pin, " +
"which seed). Promotion is human-gated like all promotions: run it ONLY after the " +
"researcher signs off (with verification evidence). Then COMPLETE: pass the promoted " +
"entry's metadata.toml path as rebank_metadata_ref — the fingerprint is verified and the " +
"executed_on_mock event lands on the provenance spine (the countable execution record).",
args: {
leg: {
type: ["string", "null"],
description: 'mock (the only recordable leg) | hardware (refused — real-board sessions are an enumerated human gate). Null = mock.',
},
rehearsal_ref: {
type: ["string", "null"],
description: "The SEAM 1 rehearsal.toml artifact — the mock leg's calibration data source. Null to complete a staged chain.",
},
pinned: {
type: ["object", "null"],
additionalProperties: { type: "number" },
description: "The calibrated globals to pin (global → value), e.g. {delta: 0.21} from a 'delta × 1.05' rehearsal mismatch on a 0.2 nominal.",
},
warm_start: {
type: ["string", "null"],
description: "The bank seed the re-solve warm-starts from (catalog entry id or pulse ref).",
},
run_dir: {
type: ["string", "null"],
description: "The re-solve's run directory, once launched through the solve path; else null.",
},
note: {
type: ["string", "null"],
description: "Short free-text note; null for none.",
},
rebank_metadata_ref: {
type: ["string", "null"],
description: "COMPLETE the chain: the promoted catalog entry's metadata.toml path — verified (read-only) against the chain's fingerprint, then the executed_on_mock event is recorded. Null to stage.",
},
},
async execute(a: {
leg?: string | null;
rehearsal_ref?: string | null;
pinned?: Record<string, number> | null;
warm_start?: string | null;
run_dir?: string | null;
note?: string | null;
rebank_metadata_ref?: string | null;
}) {
const meta = ensureActiveProblem();

// COMPLETE — verify the promoted entry's fingerprint + the execution record.
if (given(a.rebank_metadata_ref)) {
const res = completeCalibChain({ slug: meta.slug, rebankMetadataRef: a.rebank_metadata_ref });
if (!res.ok) {
return `Cannot complete the calibrate→pin→re-optimize chain for "${meta.slug}": ${res.problem}`;
}
const sentinel = sentinelLine(meta.slug, "calib_chain", res.chainEvent.action, res.chainEvent.seq, res.chainEvent.diff);
return (
`Chain executed on mock for "${meta.slug}"${res.already ? " (re-verified; already complete)" : ""} — the re-bank ` +
`carried the chain's fingerprint (which calibration, which pin, which warm-start ` +
`seed), the rebank leg is recorded on the chain entity, and the executed_on_mock ` +
`event is on the provenance spine. The promotion itself ran out-of-band through the ` +
`human-gated ingest — this record is its receipt, not its author.\n\n${sentinel}`
);
}

// STAGE — calibrate + pin + re-optimize legs.
if (!given(a.rehearsal_ref) || !given(a.pinned) || !given(a.warm_start)) {
return (
`Cannot stage the chain for "${meta.slug}": rehearsal_ref (the SEAM 1 rehearsal ` +
`artifact), pinned (the calibrated globals), and warm_start (the bank seed) are all ` +
`required to stage — or pass rebank_metadata_ref alone to complete a staged chain. ` +
`Nothing was recorded.`
);
}
const res = recordCalibChain({
slug: meta.slug,
leg: (a.leg === "hardware" ? "hardware" : "mock") as ChainLeg,
rehearsalRef: a.rehearsal_ref,
pinned: a.pinned,
warmStart: a.warm_start,
runDir: given(a.run_dir) ? a.run_dir : undefined,
note: given(a.note) ? a.note : undefined,
});
if (!res.ok) {
return `Cannot stage the calibrate→pin→re-optimize chain for "${meta.slug}": ${res.problem}`;
}
const sentinel = sentinelLine(meta.slug, "calib_chain", res.staged.chainEvent.action, res.staged.chainEvent.seq, res.staged.chainEvent.diff);
return (
`Chain staged for "${meta.slug}" — calibrated via the MockSoc rehearsal (${res.staged.chainRef} ` +
`carries the fingerprint), the pin landed on the formulation (calibration_pin + ` +
`pinned_globals), and the re-optimize leg's warm-start seed is on the run stub.\n\n` +
`Re-bank when the re-solve finishes — the human-gated promotion, run only after the ` +
`researcher signs off:\n ${res.staged.rebankCommand}\n${res.staged.humanGate}\n\n` +
`Then complete the chain: pass the promoted entry's metadata.toml path as ` +
`rebank_metadata_ref (the fingerprint gets verified, and the executed_on_mock event ` +
`lands on the provenance spine).\n\n${sentinel}`
);
},
},
} : {}), // end quantum-control domain tools gate
// ── Onboarding (spec-20260705-002847 §3) — NOT a problem stage: UNGATED
// (no guardAndRecordStage), writes the ops-side onboarding stream, never the
Expand Down
Loading
Loading