diff --git a/packages/extension/opencode-plugin/amicode_tools.ts b/packages/extension/opencode-plugin/amicode_tools.ts index b44b0c72..cbafe0f3 100644 --- a/packages/extension/opencode-plugin/amicode_tools.ts +++ b/packages/extension/opencode-plugin/amicode_tools.ts @@ -122,12 +122,17 @@ import { queryLedger, resolveWorkspaceSpecContext, stampStructureHash, - selectRecommendations, attemptErrorStanza, fallbackStanza, verdictStanza, resolveRunHashes, + type LedgerQueryResult, } from "./ledger_client"; +import { + serveRecommendations, + auditRegimePriorApplications, + type CensusStamp, +} from "./regime_priors"; // Load line goes to STDERR, not stdout: `opencode debug config` imports plugin // modules before printing the resolved config as JSON on stdout (verified on @@ -1393,19 +1398,28 @@ export const AmicodeTools = async (input: unknown) => { // L2 (Veloce) has a machine-readable confidence to act on. amicode_recommend: { description: - "Record a parameter recommendation and its outcome, or retrieve ledger-backed " + - "priors (L1 + learning-loops L-A). Three actions: " + + "Record a parameter recommendation and its outcome, or retrieve priors for the " + + "active workspace (L1 + learning-loops L-A + SEAM 2 regime priors). Four actions: " + "action=`propose` logs {stage, param, value, confidence: high|medium|low, " + - "provenance:[{source: own-precedent|demo|physics|ledger|default, ref, note}], alternatives?} — " + + "provenance:[{source: own-precedent|demo|physics|ledger|default|regime-prior, ref, note}], alternatives?} — " + "confidence is MECHANICAL per scores/memory/confidence-rubric.md (never a guess); " + "action=`outcome` logs {stage, param, outcome: accepted|overridden, applied_value} AFTER " + "the value lands via set_model/formulate (append-only pair, keyed on stage+param) — an " + "`overridden` outcome also appends a run-ledger `override` stanza; " + "action=`query` retrieves honest ledger priors (medians/IQR, \"n runs, m verified\" " + - "provenance) for the active workspace's most recent structure_hash — pass `params` " + - "(e.g. [\"Q\",\"N\"]) to select which recommendable knobs to return, or omit for all. " + + "provenance) for the active workspace's most recent structure_hash, COMPOSED with the " + + "regime priors — static, platform-family-scoped priors for the five NAMED calibration " + + "knobs (tr_frac, β, y_goal, GLS weighting, min_contrast), scoped by the session's " + + "recorded platform family and carrying their profile scope + census + sources + the " + + "public-scale caveat in every provenance — pass `params` " + + "(e.g. [\"Q\",\"N\",\"min_contrast\"]) to select which knobs to return, or omit for all. " + "Ledger-sourced confidence is CAPPED at medium (interim guard until per-structure trust " + - "lands) — never auto-applied. propose/outcome events are stamped with structure_hash when " + + "lands) — never auto-applied; regime priors state their explicit confidence. " + + "action=`audit` runs the regime-prior audit (the off-profile sensor): it FAILS when a " + + "prior was applied outside its profile scope without the public-scale caveat surfaced " + + "(the with-caveat case passes), and surfaces census staleness when `current_census` " + + "{date, total, families:{spin,transmon,atom}} differs from the table's stamp. " + + "propose/outcome events are stamped with structure_hash when " + "known. No active problem workspace yet → a no-op receipt (recommendations begin at the problem stage).", args: { action: { type: "string", description: "propose | outcome | query" }, @@ -1431,6 +1445,13 @@ export const AmicodeTools = async (input: unknown) => { type: ["array", "null"], description: 'Recommendable knob names to retrieve, e.g. ["Q","N"] (query); null/omitted = all.', }, + current_census: { + type: ["object", "null"], + description: + "The CURRENT profile census for the audit's staleness check: " + + "{date: \"YYYY-MM-DD\", total: n, families: {spin: n, transmon: n, atom: n}} " + + "(audit only; null to audit applications without the staleness check).", + }, }, async execute(a: { action: string; @@ -1444,31 +1465,109 @@ export const AmicodeTools = async (input: unknown) => { applied_value?: unknown; auto_accepted?: boolean | null; params?: string[] | null; + current_census?: Record | null; }) { try { const slug = readActiveSlug(); if (!slug) return "No active problem yet — recommendation not recorded (recommendations begin at the problem stage)."; - // ── query: retrieve honest ledger priors (learning-loops L-A) ── + // ── query: retrieve honest ledger priors (learning-loops L-A), + // composed with the SEAM 2 regime priors (#699) — static, + // platform-family-scoped priors for the five NAMED calibration knobs + // (tr_frac, β, y_goal, GLS weighting, min_contrast), served alongside + // the run-history priors. The regime priors are NOT run-gated; the + // ledger priors keep their structure-hash keying (ctx.goal keys the + // ledger query on the task, not just the type skeleton — without it + // a CZ's medians would be recommended for an X gate). Confidence + // capping stays with the existing mechanics: ledger recs cap at + // medium inside selectRecommendations; regime recs state the table's + // explicit confidence. ── if (a.action === "query") { + const sysRaw = readEntityJson>(slug, "system"); + const platform = sysRaw !== undefined ? normalizeSystem(sysRaw).platform : undefined; const ctx = resolveWorkspaceSpecContext(slug); - if (!ctx) + let ledger: LedgerQueryResult | undefined; + let ledgerNote: string | undefined; + if (!ctx) { + ledgerNote = + `no ledger-backed recommendations yet (they key on at least one completed, hash-stamped run)`; + } else if (ctx.N === undefined || ctx.T === undefined) { + ledgerNote = `ledger history found but its N/T are unavailable — cannot bucket the ledger query`; + } else { + const result = queryLedger(ctx.structure_hash, ctx.N, ctx.T, ctx.goal); + if (!result) { + ledgerNote = `ledger query unavailable (amico CLI unreachable, or no matching history)`; + } else { + ledger = result; + } + } + const wanted = Array.isArray(a.params) && a.params.length > 0 ? a.params.map(String) : undefined; + const served = serveRecommendations({ + ...(platform !== undefined ? { platform } : {}), + ...(ledger !== undefined ? { ledger } : {}), + ...(wanted !== undefined ? { params: wanted } : {}), + }); + const lines = served.recommendations.map( + (r) => ` ${r.param} = ${JSON.stringify(r.value)} (${r.confidence}, ${r.origin}: ${r.provenance})`, + ); + const notes = [served.regimeNote, ledgerNote].filter((n): n is string => n !== undefined); + if (lines.length === 0) { + return `No recommendations yet for "${slug}":\n${notes.map((n) => ` (${n})`).join("\n")}`; + } + return ( + `Recommendations for "${slug}" (regime = static platform-family priors, ledger = this workspace's run history):\n` + + `${lines.join("\n")}` + + (notes.length > 0 ? `\n${notes.map((n) => ` (${n})`).join("\n")}` : "") + ); + } + + // ── audit: SEAM 2's F2 sensor (#699) — a query over prior-application + // events (the propose/outcome events amico_recommend itself appends + // to this workspace's events.jsonl). FAILS when a prior was applied + // outside its profile scope without the public-scale caveat surfaced; + // the with-caveat case passes. Surfaces census staleness when handed + // a current census that differs from the table's stamp. ── + if (a.action === "audit") { + // Boundary shape-check on the free-form census arg (a malformed + // census would otherwise report a spurious staleness). + let census: CensusStamp | undefined; + const c = a.current_census; + if (given(c) && typeof c.date === "string" && typeof c.total === "number" && typeof c.families === "object" && c.families !== null) { + census = c as unknown as CensusStamp; + } + const res = auditRegimePriorApplications(slug, census !== undefined ? { currentCensus: census } : undefined); + if (res.tableProblems !== undefined) { return ( - `No ledger history yet for "${slug}" — action=query needs at least one completed, ` + - `hash-stamped run to key on (run a solve first).` + `Regime-prior audit FAILED for "${slug}" — the priors table is invalid (a broken sensor never silently passes):\n` + + res.tableProblems.map((p) => ` - ${p}`).join("\n") ); - if (ctx.N === undefined || ctx.T === undefined) - return `Ledger history found for "${slug}" but its N/T are unavailable — cannot bucket the query.`; - // ctx.goal keys the query on the task, not just the type skeleton — - // without it a CZ's medians would be recommended for an X gate. - const result = queryLedger(ctx.structure_hash, ctx.N, ctx.T, ctx.goal); - if (!result) return `Ledger query unavailable for "${slug}" (amico CLI unreachable, or no matching history).`; - const wanted = Array.isArray(a.params) && a.params.length > 0 ? a.params.map(String) : undefined; - const recs = selectRecommendations(result, wanted); - if (recs.length === 0) return `No ledger-backed recommendations yet for "${slug}" (${result.provenance}).`; - const lines = recs.map((r) => ` ${r.param} = ${JSON.stringify(r.value)} (${r.confidence}, ${r.provenance})`); - return `Ledger-backed recommendations for "${slug}":\n${lines.join("\n")}`; + } + const scopeLine = + ` session platform: ${res.platform ?? "(no system recorded)"} → family ${res.family ?? "(unmapped — off-census)"}`; + if (res.ok) { + return ( + `Regime-prior audit PASSED for "${slug}": ${res.audited} prior application(s) checked, ` + + `${res.applied} applied (outcome-recorded); no off-scope application without the caveat surfaced.\n` + + scopeLine + ); + } + const parts: string[] = []; + for (const v of res.violations) { + parts.push(` - event ${v.seq} (${v.key}): ${v.reason}`); + } + if (res.stale !== undefined) { + parts.push( + ` - STALE CENSUS: the table was stamped ${res.stale.stamped.date}, ${res.stale.stamped.total} profiles ` + + `(${Object.entries(res.stale.stamped.families).map(([k, n]) => `${n} ${k}`).join(" / ")}), but the current ` + + `census is ${res.stale.current.date}, ${res.stale.current.total} profiles — regenerate the table from the ` + + `internal distiller and re-stamp it.`, + ); + } + return ( + `Regime-prior audit FAILED for "${slug}" — ${res.audited} prior application(s) checked:\n` + + `${parts.join("\n")}\n${scopeLine}` + ); } const key = `${a.stage ?? "?"}/${a.param ?? "?"}`; diff --git a/packages/extension/opencode-plugin/regime_priors.ts b/packages/extension/opencode-plugin/regime_priors.ts new file mode 100644 index 00000000..593376ab --- /dev/null +++ b/packages/extension/opencode-plugin/regime_priors.ts @@ -0,0 +1,648 @@ +// ============================================================================ +// SEAM 2 (amicode #699) — regime rules as recommendations: the five-knob +// priors table's schema, serving path, and audit query (F2's sensor). +// +// SIBLING-MODULE RULES (same as ./calib_chain): this module runs inside +// opencode's embedded Bun runtime via a relative `./regime_priors` import — +// node: builtins + the ./ledger_client sibling only, no other npm packages, +// never anything from ../src/. Its data file +// (./regime_priors_table.json) is committed GENERATED content: distilled from +// the internal tier's profile census by an internal-env distiller script (the +// regeneration wiring to the freshness cadence is a named follow-up, not this +// slice), and re-validated here on every load. +// +// THE A1 BOUNDARY (the whole point of this module's shape): prior VALUES + +// provenance strings ship; the regime-rule ENGINE and the VENDOR_PROFILES +// internals never do. The table CITES its sources (public-scale arXiv/meeting +// citations, demo cards, skill doctrine, issue/PR numbers — all shippable); +// it does not include or re-implement them: no crossover logic, no per-vendor +// drift scales or trust geometry, no vendor attribution. The public-scale +// caveat ("do not cite as device data") rides the table and every entry's +// provenance — validateRegimePriorsTable enforces that, and the test suite's +// leak guard enforces the attribution-free line mechanically. +// +// Serving seam: amicode_recommend action="query" composes these static +// priors (scoped by the session's platform FAMILY — spin / transmon / atom, +// never a vendor) with the existing ledger priors. The existing mechanics +// own confidence capping (ledger-sourced caps at medium; static priors state +// their confidence explicitly — high for fixture-validated values, low for +// starting-point ranges). +// +// The audit (amicode_recommend action="audit") is F2's mechanical sensor: a +// query over prior-application events (the propose/outcome events the +// EXISTING amico_recommend mechanics append to the workspace's events.jsonl +// — the flywheel's input side, no new feed) that FAILS when a prior is applied +// outside its profile scope without the public-scale caveat surfaced; the +// with-caveat case passes (the caveat is the point). It also surfaces census +// staleness when handed a current census that differs from the table's stamp. +// ============================================================================ + +import { existsSync, readFileSync } from "node:fs"; +import { dirname, join } from "node:path"; +import { fileURLToPath } from "node:url"; +import { selectRecommendations, type LedgerQueryResult } from "./ledger_client"; +import { normalizeSystem } from "./entities"; +import { problemDir } from "./problems"; + +// ── the schema's vocabulary ───────────────────────────────────────────────── + +/** The five NAMED calibration knobs (issue #699 AC1: one prior per NAMED + * knob — `regime_rec_priors_live == 5`). `beta` / `y_goal` / `gls_weighting` + * are the ASCII param ids for β / y_goal / "GLS weighting"; each entry's + * `label` carries the issue's name for it. */ +export const REGIME_KNOBS = [ + "tr_frac", + "beta", + "y_goal", + "gls_weighting", + "min_contrast", +] as const; +export type RegimeKnob = (typeof REGIME_KNOBS)[number]; + +/** Platform FAMILY keying (issue #699 Key Decision): the recommendation + * surface is coarse (the interview's platform axis), so vendor profiles + * aggregate into family priors with the census + sources in the provenance — + * never vendor keying, never vendor attribution. */ +export type PlatformFamily = "spin" | "transmon" | "atom"; +export const PLATFORM_FAMILIES: PlatformFamily[] = ["spin", "transmon", "atom"]; + +/** The profile census a table was distilled from: families + count + date. + * DYNAMIC-CENSUS CONTRACT: a census change makes the table stale (see the + * table's `dynamic_census_contract`); the audit surfaces the staleness when + * handed a current census that differs from this stamp. */ +export interface CensusStamp { + date: string; + total: number; + families: Partial>; +} + +/** One entry's provenance — the shippable face of the A1 boundary: scope + * (the platform families the prior covers), the census it distilled from, + * its evidence chain (public-scale citations), and the public-scale caveat + * riding every entry. */ +export interface PriorProvenance { + scope: PlatformFamily[]; + census: CensusStamp; + sources: string[]; + caveat: string; +} + +export interface RegimePriorEntry { + knob: RegimeKnob; + label?: string; + /** The platform families this entry serves (the lookup key). */ + families: PlatformFamily[]; + value: number | string; + confidence: "high" | "medium" | "low"; + note?: string; + provenance: PriorProvenance; +} + +export interface RegimePriorsTable { + schema: string; + dynamic_census_contract: string; + caveat: string; + census: CensusStamp; + priors: RegimePriorEntry[]; +} + +export type LoadResult = + | { ok: true; table: RegimePriorsTable } + | { ok: false; problems: string[] }; + +/** The public-scale caveat's load-bearing marker — the source profiles' own + * rule, enforced on the table, every entry, and every served string. */ +export const CAVEAT_MARKER = "do not cite as device data"; + +// ── validation (a malformed table fails; a malformed provenance fails) ───── + +function isRecord(v: unknown): v is Record { + return typeof v === "object" && v !== null && !Array.isArray(v); +} + +function censusEqual(a: unknown, b: unknown): boolean { + return JSON.stringify(a) === JSON.stringify(b); +} + +function validateCensus(v: unknown, where: string, problems: string[]): v is CensusStamp { + if (!isRecord(v)) { + problems.push(`${where}: census must be an object {date, total, families}`); + return false; + } + if (typeof v.date !== "string" || Number.isNaN(Date.parse(v.date))) { + problems.push(`${where}: census.date must be a date string`); + } + if (typeof v.total !== "number" || !Number.isInteger(v.total) || v.total <= 0) { + problems.push(`${where}: census.total must be a positive integer`); + } + if (!isRecord(v.families) || Object.keys(v.families).length === 0) { + problems.push(`${where}: census.families must be a non-empty object`); + } else { + let sum = 0; + for (const [name, count] of Object.entries(v.families)) { + if (!(PLATFORM_FAMILIES as string[]).includes(name)) { + problems.push(`${where}: census.families has unknown family "${name}"`); + } + if (typeof count !== "number" || !Number.isInteger(count) || count <= 0) { + problems.push(`${where}: census.families.${name} must be a positive integer`); + } else { + sum += count; + } + } + if (typeof v.total === "number" && sum !== v.total) { + problems.push(`${where}: census.total (${v.total}) != the sum of family counts (${sum})`); + } + } + return problems.length === 0; +} + +/** Validate a raw (parsed) priors table against the schema — every problem is + * a string; an empty array means the table is servable. Enforces: the schema + * id, the dynamic-census contract's presence, the caveat marker, the census + * stamp's arithmetic, every entry's provenance (scope == families, census == + * the table's stamp, non-empty sources, the caveat riding it), and the + * five-knob coverage per census family (AC1's `regime_rec_priors_live == 5` + * made mechanical at the schema level). */ +export function validateRegimePriorsTable(raw: unknown): string[] { + const problems: string[] = []; + if (!isRecord(raw)) return ["the priors table must be a JSON object"]; + if (raw.schema !== "amicode.regime-priors/v1") { + problems.push(`schema: expected "amicode.regime-priors/v1", got ${JSON.stringify(raw.schema)}`); + } + if (typeof raw.dynamic_census_contract !== "string" || !/census/i.test(raw.dynamic_census_contract) || !/stale/i.test(raw.dynamic_census_contract)) { + problems.push("dynamic_census_contract: must state the dynamic-census contract (naming census + staleness)"); + } + if (typeof raw.caveat !== "string" || !raw.caveat.includes(CAVEAT_MARKER)) { + problems.push(`caveat: must carry the public-scale caveat (containing "${CAVEAT_MARKER}")`); + } + if (!validateCensus(raw.census, "census", problems)) { + // census already pushed its problems; entries below still validated best-effort + } + const censusFamilies = isRecord(raw.census) && isRecord(raw.census.families) + ? (Object.keys(raw.census.families) as PlatformFamily[]) + : []; + if (!Array.isArray(raw.priors) || raw.priors.length === 0) { + problems.push("priors: must be a non-empty array"); + return problems; + } + for (let i = 0; i < raw.priors.length; i++) { + const e = raw.priors[i]; + const where = `priors[${i}]`; + if (!isRecord(e)) { + problems.push(`${where}: must be an object`); + continue; + } + if (!(REGIME_KNOBS as readonly string[]).includes(e.knob as string)) { + problems.push(`${where}: knob "${String(e.knob)}" is not one of the five NAMED knobs`); + } + const fams = e.families; + if (!Array.isArray(fams) || fams.length === 0) { + problems.push(`${where}: families must be a non-empty array`); + } else { + for (const f of fams) { + if (!censusFamilies.includes(f)) { + problems.push(`${where}: family "${String(f)}" is outside the census families`); + } + } + } + if (typeof e.value !== "number" && (typeof e.value !== "string" || e.value.trim() === "")) { + problems.push(`${where}: value must be a number or non-empty string`); + } + if (e.confidence !== "high" && e.confidence !== "medium" && e.confidence !== "low") { + problems.push(`${where}: confidence must be high | medium | low`); + } + // ── provenance: malformed provenance FAILS (the table cites, precisely) ── + const p = e.provenance; + if (!isRecord(p)) { + problems.push(`${where}.provenance: must be an object {scope, census, sources, caveat}`); + continue; + } + const scope = p.scope; + if (!Array.isArray(scope) || scope.length === 0) { + problems.push(`${where}.provenance.scope: must be a non-empty array`); + } else { + if (!Array.isArray(fams) || JSON.stringify([...scope].sort()) !== JSON.stringify([...fams].sort())) { + problems.push(`${where}.provenance.scope: must name exactly the entry's families (the profile scope)`); + } + for (const f of scope) { + if (!censusFamilies.includes(f)) { + problems.push(`${where}.provenance.scope: family "${String(f)}" is outside the census families`); + } + } + } + if (!isRecord(p.census) || !censusEqual(p.census, raw.census)) { + problems.push(`${where}.provenance.census: must name the table's census stamp exactly`); + } + if (!Array.isArray(p.sources) || p.sources.length === 0 || p.sources.some((s) => typeof s !== "string" || s.trim() === "")) { + problems.push( + `${where}.provenance.sources: must be a non-empty array of non-empty strings (the evidence chain)`, + ); + } + if (typeof p.caveat !== "string" || !p.caveat.includes(CAVEAT_MARKER) || p.caveat !== raw.caveat) { + problems.push(`${where}.provenance.caveat: must be the table's public-scale caveat verbatim`); + } + } + // ── AC1 coverage: every NAMED knob servable for every census family ── + for (const knob of REGIME_KNOBS) { + for (const fam of censusFamilies) { + const covered = (raw.priors as RegimePriorEntry[]).some( + (e) => e.knob === knob && Array.isArray(e.families) && e.families.includes(fam), + ); + if (!covered) { + problems.push(`coverage: knob "${knob}" has no prior scoped to family "${fam}" (regime_rec_priors_live must be 5 per family)`); + } + } + } + return problems; +} + +// ── loading the committed data file ────────────────────────────────────────── + +/** The committed table's directory — resolved from THIS module's url so the + * load works identically in the Bun plugin runtime, in vitest, and in the + * packaged vsix (the whole opencode-plugin dir ships together). */ +export function regimePriorsDir(): string { + return dirname(fileURLToPath(import.meta.url)); +} + +export function regimePriorsTablePath(): string { + return join(regimePriorsDir(), "regime_priors_table.json"); +} + +/** Load + validate the committed table. Never throws: a corrupt table is an + * honest `{ok:false, problems}` (the serving path degrades to "no regime + * priors", never to a served lie). */ +export function loadRegimePriorsTable(): LoadResult { + const file = regimePriorsTablePath(); + if (!existsSync(file)) return { ok: false, problems: [`the regime priors table is missing at ${file}`] }; + let raw: unknown; + try { + raw = JSON.parse(readFileSync(file, "utf8")); + } catch (err) { + return { ok: false, problems: [`the regime priors table does not parse: ${err instanceof Error ? err.message : String(err)}`] }; + } + const problems = validateRegimePriorsTable(raw); + if (problems.length > 0) return { ok: false, problems }; + return { ok: true, table: raw as RegimePriorsTable }; +} + +// ── the coarse platform axis ───────────────────────────────────────────────── + +/** Map an open platform string (the interview's platform axis — spec A keeps + * it open) onto a census FAMILY. Family keying, never vendor keying (issue + * #699 Key Decision): the recommendation surface is coarse, so the vendor + * profiles aggregate into family priors. Returns undefined outside the + * census families — an unmapped platform serves NO prior (honest absence, + * never a nearest-guess). */ +export function platformFamily(platform: string): PlatformFamily | undefined { + const p = platform.toLowerCase(); + if (p.includes("transmon")) return "transmon"; + if (p.includes("rydberg") || p.includes("atom")) return "atom"; + if (p.includes("spin")) return "spin"; + return undefined; +} + +// ── the serving selection (AC1: regime_rec_priors_live == 5) ───────────────── + +/** A served regime prior — the shape that rides the recommendation surface + * (amicode_recommend action="query"). `provenance` is the composed, shippable + * string (scope + census + sources + caveat); `scope` and `ref` stay + * machine-readable so the propose events the agent records through the + * EXISTING mechanics are audit-parseable (see auditRegimePriors). */ +export interface RegimePriorRec { + param: RegimeKnob; + label: string; + value: number | string; + confidence: "high" | "medium" | "low"; + provenance: string; + scope: PlatformFamily[]; + ref: string; + note?: string; +} + +/** The served provenance string — the shippable face of the A1 boundary: + * profile scope + the census stamp + the evidence chain + the public-scale + * caveat riding every served string. Composed here (never stored) so every + * consumer of a prior names its sources identically — the audit parses these + * markers back out of prior-application events. */ +export function priorProvenanceString(entry: RegimePriorEntry, table: RegimePriorsTable): string { + const census = table.census; + const families = PLATFORM_FAMILIES.filter((f) => census.families[f] !== undefined) + .map((f) => `${census.families[f]} ${f}`) + .join(" / "); + return ( + `scope: ${entry.provenance.scope.join(", ")}; ` + + `census: ${census.date}, ${census.total} profiles: ${families}; ` + + `sources: ${entry.provenance.sources.join("; ")}; ` + + `caveat: ${entry.provenance.caveat}` + ); +} + +/** Select the regime priors for a platform family — ONE per NAMED knob + * (exactly the five, per issue #699 AC1). `knobs` (optional) projects to the + * requested knob names, mirroring the query path's `params` selection. */ +export function selectRegimePriors( + table: RegimePriorsTable, + family: PlatformFamily, + knobs?: readonly string[], +): RegimePriorRec[] { + const wanted = knobs && knobs.length > 0 ? (knobs as readonly string[]) : REGIME_KNOBS; + const out: RegimePriorRec[] = []; + for (const knob of wanted) { + if (!(REGIME_KNOBS as readonly string[]).includes(knob)) continue; + const entry = table.priors.find((e) => e.knob === knob && e.families.includes(family)); + if (!entry) continue; // the schema validator guarantees coverage; a gap degrades honestly + out.push({ + param: entry.knob, + label: entry.label ?? entry.knob, + value: entry.value, + confidence: entry.confidence, + provenance: priorProvenanceString(entry, table), + scope: entry.provenance.scope, + ref: `regime_priors_table.json#${entry.knob}@${family}`, + ...(entry.note !== undefined ? { note: entry.note } : {}), + }); + } + return out; +} + +// ── the serving path — composition with the existing ledger priors ────────── + +/** A composed recommendation on the serving seam — regime (static, table- + * sourced, explicit confidence) or ledger (run-history-sourced, confidence + * capped at medium by the existing interim guard inside + * ledger_client.selectRecommendations). */ +export interface ServedRecommendation { + param: string; + value: number | string; + confidence: "high" | "medium" | "low"; + provenance: string; + origin: "regime" | "ledger"; +} + +export interface ServeRecommendationsInput { + /** The table's load result. When omitted the committed table is loaded + * (and an invalid one degrades honestly to a note, never a served lie). */ + table?: LoadResult; + /** The session's platform (raw, open string — the interview's axis). */ + platform?: string; + /** The ledger query result, when the workspace has ledger history. */ + ledger?: LedgerQueryResult; + /** Knob/param projection, mirroring the query path's `params` selection. */ + params?: string[]; +} + +export interface ServedRecommendations { + recommendations: ServedRecommendation[]; + /** Why the regime priors are absent (no mapped family, no recorded system, + * or an invalid table) — honest absence, never a silent gap. */ + regimeNote?: string; +} + +/** Compose the static regime priors (scoped by the session's platform FAMILY) + * with the existing ledger priors — the pure core behind `amicode_recommend + * action:"query"`. The existing mechanics own confidence capping: ledger + * recs flow through selectRecommendations (high → medium), regime recs state + * the table's explicit confidence. Regime first (the static priors are the + * anchor), ledger after (the run-history refinement). */ +export function serveRecommendations(input: ServeRecommendationsInput): ServedRecommendations { + const recommendations: ServedRecommendation[] = []; + let regimeNote: string | undefined; + + const load = input.table ?? loadRegimePriorsTable(); + if (!load.ok) { + regimeNote = `the regime priors table is invalid (${load.problems[0] ?? "unknown problem"}) — no static calibration priors served`; + } else if (input.platform === undefined) { + regimeNote = "no system recorded yet — the regime priors scope by the session's platform family"; + } else { + const family = platformFamily(input.platform); + if (family === undefined) { + regimeNote = `no regime priors for platform "${input.platform}" — the census covers the spin / transmon / atom families only`; + } else { + for (const r of selectRegimePriors(load.table, family, input.params)) { + recommendations.push({ + param: r.param, + value: r.value, + confidence: r.confidence, + provenance: r.provenance, + origin: "regime", + }); + } + } + } + + if (input.ledger !== undefined) { + for (const r of selectRecommendations(input.ledger, input.params)) { + recommendations.push({ + param: r.param, + value: r.value, + confidence: r.confidence, + provenance: r.provenance, + origin: "ledger", + }); + } + } + + return { recommendations, ...(regimeNote !== undefined ? { regimeNote } : {}) }; +} + +// ── the audit query (F2's sensor) ──────────────────────────────────────────── + +/** One prior-application event, as read from the workspace's events.jsonl — + * a recommendation `proposed` event whose provenance carries a regime-prior + * entry (the served prior's composed provenance string rides the note). */ +export interface PriorApplication { + seq: number; + key: string; + param: string; + provenance: Array<{ source?: string; ref?: string; note?: string }>; + /** The paired outcome event's applied value, when the application landed + * (the flywheel's input side — recorded through the EXISTING amico_recommend + * outcome mechanics, no new feed). */ + outcome?: { outcome: string; applied_value?: unknown }; +} + +export interface AuditViolation { + seq: number; + key: string; + reason: string; +} + +export interface AuditResult { + ok: boolean; + /** Regime-prior applications found and checked. */ + audited: number; + violations: AuditViolation[]; + /** Census staleness — the dynamic-census contract surfacing (a current + * census that differs from the table's stamp makes the table stale). */ + stale?: { stamped: CensusStamp; current: CensusStamp }; +} + +/** Parse the profile-scope marker out of a served provenance string — the + * `scope: a, b;` prefix priorProvenanceString composes. Returns undefined when + * the provenance does not name its scope (an unverifiable prior). */ +function parseScopeMarker(note: string): PlatformFamily[] | undefined { + const m = note.match(/scope:\s*([^;]+);/); + if (!m) return undefined; + const scope = m[1].split(",").map((s) => s.trim()); + if (scope.length === 0 || scope.some((s) => !(PLATFORM_FAMILIES as string[]).includes(s))) { + return undefined; + } + return scope as PlatformFamily[]; +} + +/** The audit core — F2's mechanical sensor (pure; the workspace wrapper below + * feeds it the events the EXISTING mechanics recorded). FAILS when a prior is + * applied outside its profile scope without the public-scale caveat surfaced; + * the with-caveat case passes (the caveat is the point). Also surfaces census + * staleness when handed a current census that differs from the table's stamp. */ +export function auditRegimePriors(input: { + table: RegimePriorsTable; + /** The session's platform family (undefined when the workspace's platform + * does not map — then only the caveat can save an off-census application). */ + family: PlatformFamily | undefined; + applications: PriorApplication[]; + currentCensus?: CensusStamp; +}): AuditResult { + const violations: AuditViolation[] = []; + let audited = 0; + for (const app of input.applications) { + const regimeEntries = (app.provenance ?? []).filter((p) => p?.source === "regime-prior"); + if (regimeEntries.length === 0) continue; // not a regime-prior application + audited++; + const note = regimeEntries.map((p) => p.note ?? "").join(" "); + const scope = parseScopeMarker(note); + const caveat = note.includes(CAVEAT_MARKER); + const inScope = input.family !== undefined && scope !== undefined && scope.includes(input.family); + if (!inScope && !caveat) { + const reason = + scope === undefined + ? `the prior's provenance does not name its profile scope, so its scope cannot be verified against this session's platform family, and no public-scale caveat was surfaced` + : `the prior was applied outside its profile scope (scope: ${scope.join(", ")}; session family: ${input.family ?? "unmapped"}) without the public-scale caveat surfaced`; + violations.push({ seq: app.seq, key: app.key, reason }); + } + } + const stale = + input.currentCensus !== undefined && !censusEqual(input.currentCensus, input.table.census) + ? { stamped: input.table.census, current: input.currentCensus } + : undefined; + return { + ok: violations.length === 0 && stale === undefined, + audited, + violations, + ...(stale !== undefined ? { stale } : {}), + }; +} + +// ── the workspace wrapper — the audit query the tool shells ────────────────── + +/** The workspace-scoped audit result: the pure audit + the scoping facts it + * ran against (the session's platform + family) + the applied count (the + * outcome pairs — the flywheel's input side, recorded through the EXISTING + * amico_recommend outcome mechanics). */ +export interface WorkspaceAuditResult extends AuditResult { + /** The workspace's recorded platform (undefined when no system is recorded). */ + platform?: string; + family?: PlatformFamily; + /** Regime-prior applications that landed (paired outcome events). */ + applied: number; + /** The table's own load problems — an unloadable table fails the audit + * honestly (a broken sensor never silently passes). */ + tableProblems?: string[]; +} + +interface RecordedEvent { + seq?: number; + entity?: string; + action?: string; + diff?: Record; +} + +function readEvents(slug: string): RecordedEvent[] { + const file = join(problemDir(slug), "events.jsonl"); + if (!existsSync(file)) return []; + const out: RecordedEvent[] = []; + for (const line of readFileSync(file, "utf8").split("\n")) { + if (line.trim() === "") continue; + try { + out.push(JSON.parse(line) as RecordedEvent); + } catch { + /* malformed line — skip (events.jsonl is append-only by our own tools) */ + } + } + return out; +} + +function readSystemPlatform(slug: string): string | undefined { + const file = join(problemDir(slug), "entities", "system.json"); + if (!existsSync(file)) return undefined; + try { + return normalizeSystem(JSON.parse(readFileSync(file, "utf8"))).platform; + } catch { + return undefined; + } +} + +/** The audit query over a problem workspace's prior-application events (the + * `amicode_recommend action:"audit"` core): reads the workspace's recorded + * platform (the session's scoping), its events.jsonl (the regime-prior + * propose events + their outcome pairs the EXISTING mechanics recorded), and + * runs the pure audit. An unloadable table fails the audit honestly with its + * problems surfaced. */ +export function auditRegimePriorApplications( + slug: string, + opts?: { currentCensus?: CensusStamp }, +): WorkspaceAuditResult { + const load = loadRegimePriorsTable(); + if (!load.ok) { + return { ok: false, audited: 0, violations: [], applied: 0, tableProblems: load.problems }; + } + + const platform = readSystemPlatform(slug); + const family = platform !== undefined ? platformFamily(platform) : undefined; + + // Build the applications: regime-prior `proposed` events, paired with their + // `outcome` events (the applied count is the flywheel's input side). + const applications: PriorApplication[] = []; + const pending = new Map(); + for (const ev of readEvents(slug)) { + if (ev.entity !== "recommendation") continue; + const diff = ev.diff ?? {}; + const key = typeof diff.key === "string" ? diff.key : `${String(diff.stage ?? "?")}/${String(diff.param ?? "?")}`; + if (ev.action === "proposed") { + const provenance = Array.isArray(diff.provenance) ? (diff.provenance as PriorApplication["provenance"]) : []; + if (provenance.some((p) => p?.source === "regime-prior")) { + const app: PriorApplication = { + seq: typeof ev.seq === "number" ? ev.seq : 0, + key, + param: typeof diff.param === "string" ? diff.param : "?", + provenance, + }; + applications.push(app); + pending.set(key, app); + } + } else if (ev.action === "outcome") { + const app = pending.get(key); + if (app) { + app.outcome = { + outcome: typeof diff.outcome === "string" ? diff.outcome : "?", + ...(diff.applied_value !== undefined ? { applied_value: diff.applied_value } : {}), + }; + pending.delete(key); + } + } + } + + const res = auditRegimePriors({ + table: load.table, + family, + applications, + ...(opts?.currentCensus !== undefined ? { currentCensus: opts.currentCensus } : {}), + }); + return { + ...res, + applied: applications.filter((a) => a.outcome !== undefined).length, + ...(platform !== undefined ? { platform } : {}), + ...(family !== undefined ? { family } : {}), + }; +} diff --git a/packages/extension/opencode-plugin/regime_priors_table.json b/packages/extension/opencode-plugin/regime_priors_table.json new file mode 100644 index 00000000..7aeeee07 --- /dev/null +++ b/packages/extension/opencode-plugin/regime_priors_table.json @@ -0,0 +1,204 @@ +{ + "schema": "amicode.regime-priors/v1", + "dynamic_census_contract": "The census stamp names the profile census this table was distilled from (families + count + date). The census is DYNAMIC, never a frozen count: a census change — a new profile family, or a count change within one — makes this table STALE until it is regenerated from the internal distiller and re-stamped. The audit query (amicode_recommend action=audit) surfaces staleness whenever it is given a current census that differs from this stamp.", + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data.", + "census": { + "date": "2026-08-31", + "total": 12, + "families": { "spin": 4, "transmon": 4, "atom": 4 } + }, + "priors": [ + { + "knob": "tr_frac", + "label": "tr_frac (per-channel trust-box fraction)", + "families": ["spin"], + "value": "0.05-0.1 (per channel; never one scalar radius)", + "confidence": "low", + "note": "Starting point only — refined by outcome events (the flywheel). Channels differ 10^2-10^3x in sensitivity; size each channel's trust box, never one scalar radius.", + "provenance": { + "scope": ["spin"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "arXiv:2410.15590 (silicon spin-qubit operation, public-scale)", + "arXiv:2604.16216 (cryoCMOS exchange-only, public-scale)", + "arXiv:2604.01063 (Ge-hole spin qubits, public-scale)", + "2026-08-05 silicon-spin meeting + 2026-08-04 Ge-hole meeting (public-scale notes)", + "spin-qubit-demo + cryocmos-spin demo cards", + "hardware-loop skill: per-channel trust boxes, never one scalar radius" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "tr_frac", + "label": "tr_frac (per-channel trust-box fraction)", + "families": ["transmon"], + "value": "0.02-0.05 (per channel; never one scalar radius)", + "confidence": "low", + "note": "Starting point only — refined by outcome events (the flywheel). Channels differ 10^2-10^3x in sensitivity; size each channel's trust box, never one scalar radius.", + "provenance": { + "scope": ["transmon"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "arXiv:2408.13687 (surface-code transmon platform class, public-scale)", + "arXiv:2101.07746 (tunable-coupler platform class, public-scale)", + "arXiv:2603.15758 (cross-resonance gate-synthesis platform class, public-scale)", + "arXiv:2603.11018 (public-scale flux-tunable platform class)", + "hardware-loop skill: per-channel trust boxes, never one scalar radius" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "tr_frac", + "label": "tr_frac (per-channel trust-box fraction)", + "families": ["atom"], + "value": "0.02-0.05 (per channel; never one scalar radius)", + "confidence": "low", + "note": "Starting point only — refined by outcome events (the flywheel). Channels differ 10^2-10^3x in sensitivity; size each channel's trust box, never one scalar radius.", + "provenance": { + "scope": ["atom"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "arXiv:2511.22967 (neutral-atom platform class, public-scale)", + "arXiv:2411.11708 (Yb erasure-readout platform class, public-scale)", + "arXiv:2606.05060 (neutral-atom lineage, public-scale)", + "the /calibrate spec + the Aug-16 campaign's public-scale values (sigma ~ 0.057, V/Omega ~ 98 — public-scale, do not cite as device data)", + "atoms-demo card", + "hardware-loop skill: per-channel trust boxes, never one scalar radius" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "beta", + "label": "β (one-shot damping)", + "families": ["spin", "transmon", "atom"], + "value": "conservative shrink-only: β-damped apply, no line search on hardware; reject-and-revert on regression", + "confidence": "medium", + "note": "Doctrine-backed default, not a fixture-quantified optimum — the conservative damping posture across every census family.", + "provenance": { + "scope": ["spin", "transmon", "atom"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "hardware-loop skill: the one-shot damping doctrine (shrink-only, β-damped applies, no line search on hardware, reject-and-revert)" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "y_goal", + "label": "y_goal (fixed campaign contrast target)", + "families": ["spin"], + "value": "set from the pauli_correlators achievable contrast (high-contrast readout); fixed per campaign, never moved mid-loop", + "confidence": "medium", + "provenance": { + "scope": ["spin"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "census measurement-kind mapping: the spin family reads pauli_correlators (achievable-contrast anchor)", + "hardware-loop skill: y_goal is fixed per campaign, never moved mid-loop" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "y_goal", + "label": "y_goal (fixed campaign contrast target)", + "families": ["transmon"], + "value": "set from the bitstring assignment-fidelity contrast; fixed per campaign, never moved mid-loop", + "confidence": "medium", + "provenance": { + "scope": ["transmon"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "census measurement-kind mapping: the transmon family reads bitstrings (assignment-fidelity contrast anchor)", + "hardware-loop skill: y_goal is fixed per campaign, never moved mid-loop" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "y_goal", + "label": "y_goal (fixed campaign contrast target)", + "families": ["atom"], + "value": "set from the binomial readout visibility (erasure-aware contrast for multinomial_erasure readouts); fixed per campaign, never moved mid-loop", + "confidence": "medium", + "provenance": { + "scope": ["atom"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "census measurement-kind mapping: the atom family reads binomial (visibility anchor) or multinomial_erasure (erasure-aware anchor)", + "hardware-loop skill: y_goal is fixed per campaign, never moved mid-loop" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "gls_weighting", + "label": "GLS weighting (measurement-kind → covariance weighting)", + "families": ["spin"], + "value": "GLS with diagonal weighting over the pauli_correlators covariance", + "confidence": "high", + "provenance": { + "scope": ["spin"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "census measurement-kind mapping: the spin family reads pauli_correlators — GLS weights over its covariance", + "amicode PR #36 (the exact-likelihood statistics: binomial_fisher_weights)" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "gls_weighting", + "label": "GLS weighting (measurement-kind → covariance weighting)", + "families": ["transmon"], + "value": "GLS with diagonal weighting over the population/bitstring covariance", + "confidence": "high", + "provenance": { + "scope": ["transmon"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "census measurement-kind mapping: the transmon family reads bitstrings — GLS weights over the population covariance", + "amicode PR #36 (the exact-likelihood statistics: binomial_fisher_weights)" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "gls_weighting", + "label": "GLS weighting (measurement-kind → covariance weighting)", + "families": ["atom"], + "value": "binomial Fisher weighting (binomial_fisher_weights, amicode PR #36) for binomial-readout systems; erasure-aware GLS (multinomial) for multinomial_erasure-readout systems", + "confidence": "high", + "provenance": { + "scope": ["atom"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "census measurement-kind mapping: the atom family reads binomial or multinomial_erasure — the weighting follows the readout kind", + "amicode PR #36 (the exact-likelihood statistics: binomial_fisher_weights)", + "arXiv:2411.11708 (Yb erasure-readout platform class, public-scale)" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + }, + { + "knob": "min_contrast", + "label": "min_contrast (null-admission threshold)", + "families": ["spin", "transmon", "atom"], + "value": 2.5, + "confidence": "high", + "note": "Fixture-validated threshold, platform-invariant across the census families: zero phantom factors under the null, single-axis factor error <= 0.006, sub-15% drift admission; second-platform confirmation on the Ge-like hole + electron-spin-like fixtures and the cqed pair.", + "provenance": { + "scope": ["spin", "transmon", "atom"], + "census": { "date": "2026-08-31", "total": 12, "families": { "spin": 4, "transmon": 4, "atom": 4 } }, + "sources": [ + "Intonatissimo issues #65 + #81 (the min_contrast fixture campaign: zero phantom under null, single-axis factor error <= 0.006, sub-15% drift admission)", + "Intonatissimo issues #83 + #84 (second-platform confirmation: Ge-like hole + electron-spin-like fixtures + the cqed pair)" + ], + "caveat": "Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data." + } + } + ] +} diff --git a/packages/extension/scripts/plugin_exercise.ts b/packages/extension/scripts/plugin_exercise.ts index 6b396529..bb853e76 100644 --- a/packages/extension/scripts/plugin_exercise.ts +++ b/packages/extension/scripts/plugin_exercise.ts @@ -100,6 +100,92 @@ assert( ); assert(runs.runs[0].tier === "vetted", "run ref carries tier"); +// ── SEAM 2 (#699): the recommend query serves the regime priors (the session's +// system is transmon → family transmon; five NAMED knobs, no ledger history +// yet), and the audit reads the propose/outcome events back. ── +const q = await tools.amicode_recommend.execute({ + action: "query", + stage: null, + param: null, + value: null, + confidence: null, + provenance: null, + alternatives: null, + outcome: null, + applied_value: null, + auto_accepted: null, + params: null, + current_census: null, +}); +for (const knob of ["tr_frac", "beta", "y_goal", "gls_weighting", "min_contrast"]) { + assert(q.includes(`${knob} = `), `query serves the regime prior for ${knob}`); + assert(q.includes("regime:"), "regime-origin provenance labeled"); +} +assert(q.includes("do not cite as device data"), "the public-scale caveat rides the served priors"); +assert(q.includes("ledger-backed recommendations yet"), "no-ledger note is honest, not a dead end"); + +// propose a served prior through the EXISTING mechanics (regime-prior provenance +// entry), record its outcome, then audit — clean pass. +const proposeArgs: any = { + action: "propose", + stage: "calibrate", + param: "min_contrast", + value: 2.5, + confidence: "high", + provenance: [ + { + source: "regime-prior", + ref: "regime_priors_table.json#min_contrast@transmon", + note: "scope: spin, transmon, atom; census: 2026-08-31, 12 profiles: 4 spin / 4 transmon / 4 atom; sources: Intonatissimo issues #65 + #81; caveat: Magnitudes are public-scale estimates distilled from public papers and meetings — do not cite as device data.", + }, + ], + alternatives: null, + outcome: null, + applied_value: null, + auto_accepted: null, + params: null, + current_census: null, +}; +await tools.amicode_recommend.execute(proposeArgs); +await tools.amicode_recommend.execute({ ...proposeArgs, action: "outcome", outcome: "accepted", applied_value: 2.5 }); +const auditArgs: any = { + action: "audit", + stage: null, + param: null, + value: null, + confidence: null, + provenance: null, + alternatives: null, + outcome: null, + applied_value: null, + auto_accepted: null, + params: null, + current_census: null, +}; +let a1 = await tools.amicode_recommend.execute(auditArgs); +assert(a1.includes("audit PASSED"), `clean audit passes — got: ${a1.slice(0, 120)}`); +assert(a1.includes("1 prior application(s) checked, 1 applied"), "the outcome pair is the applied count"); + +// the violation fixture through the real tool: an off-scope prior (spin-scoped) +// proposed into this transmon workspace with the caveat stripped → audit FAILS. +const violated = await tools.amicode_recommend.execute({ + ...proposeArgs, + param: "tr_frac", + value: "0.05-0.1", + confidence: "low", + provenance: [ + { + source: "regime-prior", + ref: "regime_priors_table.json#tr_frac@spin", + note: "scope: spin; census: 2026-08-31, 12 profiles: 4 spin / 4 transmon / 4 atom; sources: arXiv:2410.15590;", + }, + ], +}); +assert(violated.includes("Recommended tr_frac"), "the violating proposal records"); +let a2 = await tools.amicode_recommend.execute(auditArgs); +assert(a2.includes("audit FAILED"), `off-scope-without-caveat audit fails — got: ${a2.slice(0, 120)}`); +assert(a2.includes("outside its profile scope"), "the violation names the off-scope reason"); + console.error(`OK — ${events.length} events, ${formEvents.length} formulation events, workspace "${slug}"`); fs.rmSync(tmp, { recursive: true, force: true }); process.exit(0); diff --git a/packages/extension/test/packaging.test.ts b/packages/extension/test/packaging.test.ts index 9aa40064..c7762a86 100644 --- a/packages/extension/test/packaging.test.ts +++ b/packages/extension/test/packaging.test.ts @@ -67,6 +67,11 @@ const REQUIRED = [ "extension/opencode-plugin/problems.ts", "extension/opencode-plugin/hashes.ts", "extension/opencode-plugin/score_guard.ts", + // SEAM 2 (#699): the regime priors module + its committed data file — a + // dropped pair silently reverts every calibration recommendation to + // ledger-only and kills the audit (F2's sensor). + "extension/opencode-plugin/regime_priors.ts", + "extension/opencode-plugin/regime_priors_table.json", ]; // Guards against a silently-dropped runtime asset (the β.2 .gitignore-fallback diff --git a/packages/extension/test/regime_priors.test.ts b/packages/extension/test/regime_priors.test.ts new file mode 100644 index 00000000..5394cd6d --- /dev/null +++ b/packages/extension/test/regime_priors.test.ts @@ -0,0 +1,544 @@ +// SEAM 2 (amicode #699) — regime rules as recommendations: the five-knob +// priors table. +// +// The A1 boundary is the load-bearing invariant: prior VALUES + provenance +// strings ship; the regime-rule ENGINE and VENDOR_PROFILES internals never do. +// The table cites its sources (public-scale arXiv/meeting citations are +// shippable); it does not include or re-implement them — no crossover logic, no +// per-vendor drift scales / trust geometry, no vendor attribution. +// +// Layers (mirroring the calib_chain/rehearsal test shape): +// 1. opencode-plugin/regime_priors.ts — the schema validator, the family +// scoping, the serving-path composition, and the audit query (F2's +// sensor), pure logic over a committed data file +// (opencode-plugin/regime_priors_table.json — generated content, +// regenerated by an internal-env distiller; that wiring is a named +// follow-up, not this slice). +// 2. amicode_tools.ts's amicode_recommend — the serving seam: action=query +// composes these static priors with the existing ledger priors (the tool +// wrapper is a thin adapter over this core, verified against the real +// binary, not in vitest). +// +// Outcome events feed the flywheel through the EXISTING mechanics — propose / +// outcome events land in the workspace's events.jsonl via amicode_recommend, +// and the audit reads them back; no new feed exists. +import { describe, it, expect, beforeEach, afterEach } from "vitest"; +import { mkdtempSync, rmSync, readFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { + loadRegimePriorsTable, + validateRegimePriorsTable, + selectRegimePriors, + priorProvenanceString, + platformFamily, + serveRecommendations, + auditRegimePriors, + auditRegimePriorApplications, + REGIME_KNOBS, + CAVEAT_MARKER, + type PlatformFamily, +} from "../opencode-plugin/regime_priors"; +import type { LedgerQueryResult } from "../opencode-plugin/ledger_client"; +import { createProblem, appendEvent, writeEntityFiles } from "../opencode-plugin/problems"; +import { systemToml } from "../opencode-plugin/entities"; + +const loaded = loadRegimePriorsTable(); + +describe("the committed regime-priors table (SEAM 2 schema)", () => { + it("loads and validates clean, carrying the census stamp + the dynamic-census contract", () => { + expect(loaded.ok).toBe(true); + if (!loaded.ok) return; + const t = loaded.table; + // the schema id — the versioned shape the validator pins + expect(t.schema).toBe("amicode.regime-priors/v1"); + // THE CENSUS STAMP: families + count + date (the profile census the values + // were distilled from — 2026-08-31, 12 profiles: 4 spin / 4 transmon / 4 atom) + expect(t.census.date).toBe("2026-08-31"); + expect(t.census.total).toBe(12); + expect(t.census.families).toEqual({ spin: 4, transmon: 4, atom: 4 }); + // the dynamic-census contract is STATED IN THE SCHEMA: a census change + // makes the table stale, surfaced by the audit — never a frozen count + expect(t.dynamic_census_contract).toMatch(/census/i); + expect(t.dynamic_census_contract).toMatch(/stale/i); + // the public-scale caveat rides the table (and, per-entry, every provenance) + expect(t.caveat).toMatch(/do not cite as device data/); + // the five NAMED knobs are the table's vocabulary (AC1's knob set) + expect([...REGIME_KNOBS]).toEqual( + expect.arrayContaining(["tr_frac", "beta", "y_goal", "gls_weighting", "min_contrast"]), + ); + expect(REGIME_KNOBS.length).toBe(5); + }); + + it("every committed entry's provenance names its profile scope, the census it distilled from, its evidence chain, and the public-scale caveat", () => { + expect(loaded.ok).toBe(true); + if (!loaded.ok) return; + for (const e of loaded.table.priors) { + // the profile scope: the platform families the prior covers, named in provenance + expect(e.provenance.scope.length).toBeGreaterThan(0); + expect([...e.provenance.scope].sort()).toEqual([...e.families].sort()); + // the census it distilled from (the stamp, verbatim) + expect(e.provenance.census).toEqual(loaded.table.census); + // the evidence chain — the campaign fixtures / skills / cards it cites + expect(e.provenance.sources.length).toBeGreaterThan(0); + for (const s of e.provenance.sources) expect(s.trim()).not.toBe(""); + // the public-scale caveat riding every entry + expect(e.provenance.caveat).toContain(CAVEAT_MARKER); + expect(e.provenance.caveat).toBe(loaded.table.caveat); + // the knob's label carries the issue's NAMED spelling (β, GLS weighting, …) + if (e.knob === "beta") expect(e.label).toMatch(/β/); + if (e.knob === "gls_weighting") expect(e.label).toMatch(/GLS weighting/); + } + }); +}); + +describe("validateRegimePriorsTable — a malformed provenance fails", () => { + const base = (): { table: Record; priors: Record[] } => { + if (!loaded.ok) throw new Error("the committed table must load for the mutation fixtures"); + const table = JSON.parse(JSON.stringify(loaded.table)) as Record; + return { table, priors: table.priors as Record[] }; + }; + const expectProblem = (problems: string[], re: RegExp) => + expect(problems.some((p) => re.test(p)), `no problem matches ${re}: got ${JSON.stringify(problems)}`).toBe(true); + + it("fails an entry whose provenance lost the caveat (the caveat rides every entry)", () => { + const { table, priors } = base(); + delete priors[0].provenance.caveat; + expectProblem(validateRegimePriorsTable(table), /priors\[0\]\.provenance\.caveat/); + }); + + it("fails an entry whose provenance names a scope that is not its families (scope must be the profile scope)", () => { + const { table, priors } = base(); + (priors[0].provenance as Record).scope = ["atom"]; // the spin tr_frac entry claiming atom scope + expectProblem(validateRegimePriorsTable(table), /priors\[0\]\.provenance\.scope/); + }); + + it("fails an entry whose provenance cites a census that is not the table's stamp (a stale or fabricated census fails)", () => { + const { table, priors } = base(); + ((priors[0].provenance as Record).census as Record).total = 13; + expectProblem(validateRegimePriorsTable(table), /priors\[0\]\.provenance\.census/); + }); + + it("fails an entry with no evidence chain (empty sources fail)", () => { + const { table, priors } = base(); + (priors[0].provenance as Record).sources = []; + expectProblem(validateRegimePriorsTable(table), /priors\[0\]\.provenance\.sources/); + }); + + it("fails a knob outside the five NAMED knobs, and fails when a family loses knob coverage (regime_rec_priors_live)", () => { + const { table, priors } = base(); + priors[0].knob = "flavour"; + expectProblem(validateRegimePriorsTable(table), /flavour.*not one of the five NAMED knobs/); + const t2 = base(); + t2.priors.splice(0, 3); // drop the spin tr_frac entries + expectProblem(validateRegimePriorsTable(t2.table), /coverage: knob "tr_frac".*"spin"/); + }); +}); + +// ── AC1: regime_rec_priors_live == 5 — one servable prior per NAMED knob, +// for every census family (not one for the family) ── +describe("selectRegimePriors — the five-knob serving selection", () => { + it("regime_rec_priors_live == 5: every NAMED knob is servable for every census family, each with value + confidence + its composed provenance", () => { + expect(loaded.ok).toBe(true); + if (!loaded.ok) return; + for (const family of ["spin", "transmon", "atom"] as PlatformFamily[]) { + const recs = selectRegimePriors(loaded.table, family); + // ONE per NAMED knob — exactly the five, no gaps, no dupes + expect(recs.map((r) => r.param).sort()).toEqual([...REGIME_KNOBS].sort()); + expect(recs.length).toBe(5); + // the fixture-validated min_contrast is the number 2.5 across families + const mc = recs.find((r) => r.param === "min_contrast"); + expect(mc?.value).toBe(2.5); + expect(mc?.confidence).toBe("high"); + // the low-confidence starting points state that honestly + expect(recs.find((r) => r.param === "tr_frac")?.confidence).toBe("low"); + for (const r of recs) { + expect(["high", "medium", "low"]).toContain(r.confidence); + expect(r.value !== undefined && r.value !== "").toBe(true); + } + } + }); + + it("params selection filters the knobs (the query path's param projection)", () => { + expect(loaded.ok).toBe(true); + if (!loaded.ok) return; + const recs = selectRegimePriors(loaded.table, "spin", ["tr_frac", "min_contrast"]); + expect(recs.map((r) => r.param).sort()).toEqual(["min_contrast", "tr_frac"]); + }); +}); + +describe("priorProvenanceString — the served provenance names scope + census + sources + caveat", () => { + it("composes the shippable provenance: profile scope, the census stamp, the evidence chain, and the public-scale caveat riding it", () => { + expect(loaded.ok).toBe(true); + if (!loaded.ok) return; + const spinTrFrac = loaded.table.priors.find((e) => e.knob === "tr_frac" && e.families.includes("spin")); + expect(spinTrFrac).toBeDefined(); + if (!spinTrFrac) return; + const s = priorProvenanceString(spinTrFrac, loaded.table); + // the profile scope, named + expect(s).toMatch(/scope: spin\b/); + // the census it distilled from (families + count + date) + expect(s).toMatch(/census: 2026-08-31, 12 profiles/); + expect(s).toMatch(/4 spin \/ 4 transmon \/ 4 atom/); + // the evidence chain it cites + expect(s).toMatch(/arXiv:2410\.15590/); + // the public-scale caveat, riding the served string + expect(s).toContain(CAVEAT_MARKER); + // the min_contrast evidence chain cites the Intonatissimo issue numbers (not the code) + const mc = loaded.table.priors.find((e) => e.knob === "min_contrast"); + expect(mc).toBeDefined(); + if (mc) { + expect(priorProvenanceString(mc, loaded.table)).toMatch(/Intonatissimo issues #65 \+ #81/); + expect(priorProvenanceString(mc, loaded.table)).toMatch(/#83 \+ #84/); + } + }); +}); + +describe("platformFamily — the coarse platform axis (family keying, never vendor keying)", () => { + it("maps the interview's platform strings onto the census families", () => { + expect(platformFamily("transmon")).toBe("transmon"); + expect(platformFamily("rydberg")).toBe("atom"); + expect(platformFamily("neutral-atom Rydberg")).toBe("atom"); + expect(platformFamily("silicon spin qubits")).toBe("spin"); + expect(platformFamily("exchange-coupled spin")).toBe("spin"); + }); + + it("honestly returns undefined outside the census families (no prior is served off-census)", () => { + expect(platformFamily("cavity")).toBeUndefined(); + expect(platformFamily("bosonic")).toBeUndefined(); + expect(platformFamily("fluxonium")).toBeUndefined(); + }); +}); + +// ── the serving seam: amicode_recommend action="query" composes these static +// priors (scoped by the session's platform family) with the existing ledger +// priors — the EXISTING mechanics own confidence capping (ledger-sourced caps +// at medium; static priors state their confidence explicitly). ── +describe("serveRecommendations — regime priors composed with ledger priors", () => { + const ledger = (): LedgerQueryResult => ({ + key: "primary", + structure_hash: "sh-x", + total: 3, + verified: 2, + params: { + N: { value: 50, iqr: [50, 50], n: 3 }, + max_iter: { value: 60, iqr: [60, 80], n: 3 }, + }, + provenance: "3 runs, 2 verified", + confidence: "high", + }); + const table = () => loaded; // the committed table's LoadResult (ok: true) + + it("serves the five regime priors (platform-scoped) ALONGSIDE the ledger priors, the ledger still capped at medium", () => { + const served = serveRecommendations({ table: table(), platform: "transmon", ledger: ledger() }); + const regime = served.recommendations.filter((r) => r.origin === "regime"); + const fromLedger = served.recommendations.filter((r) => r.origin === "ledger"); + // the five NAMED knobs, scoped to the session's platform family + expect(regime.map((r) => r.param).sort()).toEqual([...REGIME_KNOBS].sort()); + for (const r of regime) { + expect(r.provenance).toMatch(/^scope: /); + expect(r.provenance).toContain(CAVEAT_MARKER); + } + // the ledger priors ride along, their confidence CAPPED at medium (the + // existing interim guard — high on the wire, medium at the surface) + expect(fromLedger.map((r) => r.param).sort()).toEqual(["N", "max_iter"]); + expect(fromLedger.every((r) => r.confidence === "medium")).toBe(true); + // the static priors state their own confidence explicitly (never capped up) + expect(regime.find((r) => r.param === "min_contrast")?.confidence).toBe("high"); + }); + + it("serves the regime priors even without ledger history (the static priors are not run-gated)", () => { + const served = serveRecommendations({ table: table(), platform: "spin" }); + expect(served.recommendations.filter((r) => r.origin === "regime").length).toBe(5); + expect(served.regimeNote).toBeUndefined(); + }); + + it("honestly notes absence for an unmapped platform (no nearest-guess prior)", () => { + const served = serveRecommendations({ table: table(), platform: "cavity", ledger: ledger() }); + expect(served.recommendations.filter((r) => r.origin === "regime")).toEqual([]); + expect(served.regimeNote).toMatch(/no regime priors for platform "cavity"/); + expect(served.recommendations.filter((r) => r.origin === "ledger").length).toBe(2); + }); + + it("projects the params selection onto BOTH sources", () => { + const served = serveRecommendations({ + table: table(), + platform: "transmon", + ledger: ledger(), + params: ["min_contrast", "N"], + }); + expect(served.recommendations.map((r) => r.param).sort()).toEqual(["N", "min_contrast"]); + }); + + it("degrades honestly on an invalid table (the ledger still serves; the regime notes the failure)", () => { + const served = serveRecommendations({ + table: { ok: false, problems: ["schema: expected amicode.regime-priors/v0"] }, + platform: "transmon", + ledger: ledger(), + }); + expect(served.recommendations.filter((r) => r.origin === "ledger").length).toBe(2); + expect(served.recommendations.filter((r) => r.origin === "regime")).toEqual([]); + expect(served.regimeNote).toMatch(/regime priors table/); + }); +}); + +// ── F2's mechanical sensor: the audit query over prior-application events. +// A prior applied OUTSIDE its profile scope without the caveat surfaced → the +// audit FAILS; the WITH-caveat case passes (the caveat is the point). +// Prior applications ride the EXISTING mechanics: amico_recommend propose +// events carrying a provenance entry with source "regime-prior" and the served +// provenance string as its note. ── +describe("auditRegimePriors — the off-profile sensor", () => { + const table = () => { + if (!loaded.ok) throw new Error("the committed table must load"); + return loaded.table; + }; + // a served provenance string, as it rides a propose event's regime-prior entry + const servedNote = (knob: string, family: PlatformFamily): string => { + const recs = selectRegimePriors(table(), family); + return recs.find((r) => r.param === knob)?.provenance ?? ""; + }; + const application = (seq: number, key: string, note: string, provenanceSource = "regime-prior") => ({ + seq, + key, + param: key.split("/")[1] ?? "?", + provenance: [{ source: provenanceSource, ref: "regime_priors_table.json", note }], + }); + + it("passes an on-scope application (spin prior, spin session, caveat present)", () => { + const note = servedNote("tr_frac", "spin"); + const res = auditRegimePriors({ + table: table(), + family: "spin", + applications: [application(1, "calibrate/tr_frac", note)], + }); + expect(res.ok).toBe(true); + expect(res.violations).toEqual([]); + expect(res.audited).toBe(1); + }); + + it("FAILS a prior applied outside its profile scope WITHOUT the caveat surfaced (the violation fixture)", () => { + // a spin-scoped prior (scope: spin) applied in a transmon session, with + // the caveat STRIPPED from the provenance string — the misleading case + const stripped = servedNote("tr_frac", "spin").replace(/caveat: [^;]+;?/, ""); + expect(stripped).not.toContain(CAVEAT_MARKER); + const res = auditRegimePriors({ + table: table(), + family: "transmon", + applications: [application(1, "calibrate/tr_frac", stripped)], + }); + expect(res.ok).toBe(false); + expect(res.violations.length).toBe(1); + expect(res.violations[0].seq).toBe(1); + expect(res.violations[0].reason).toMatch(/outside its profile scope/); + expect(res.violations[0].reason).toMatch(/caveat/); + }); + + it("PASSES the same off-scope application WITH the caveat surfaced (the caveat is the point)", () => { + const note = servedNote("tr_frac", "spin"); // scope: spin — applied in an atom session + const res = auditRegimePriors({ + table: table(), + family: "atom", + applications: [application(1, "calibrate/tr_frac", note)], + }); + expect(res.ok).toBe(true); + expect(res.violations).toEqual([]); + }); + + it("fails a regime-prior application whose provenance does not name its scope (unverifiable scope)", () => { + const noteless = "a hand-written prior with no scope marker and no caveat"; + const res = auditRegimePriors({ + table: table(), + family: "spin", + applications: [application(2, "calibrate/beta", noteless)], + }); + expect(res.ok).toBe(false); + expect(res.violations[0].reason).toMatch(/does not name its profile scope/); + }); + + it("ignores non-regime recommendations (only regime-prior applications are audited)", () => { + const res = auditRegimePriors({ + table: table(), + family: "spin", + applications: [application(3, "solve/N", "ledger prior", "ledger")], + }); + expect(res.ok).toBe(true); + expect(res.audited).toBe(0); + }); + + it("surfaces census staleness when the current census differs from the table's stamp (the dynamic-census contract)", () => { + const res = auditRegimePriors({ + table: table(), + family: "spin", + applications: [], + currentCensus: { date: "2026-09-15", total: 13, families: { spin: 5, transmon: 4, atom: 4 } }, + }); + expect(res.ok).toBe(false); + expect(res.stale).toBeDefined(); + expect(res.stale?.stamped.total).toBe(12); + expect(res.stale?.current.total).toBe(13); + }); + + it("passes with a matching current census (the stamp is live)", () => { + const res = auditRegimePriors({ + table: table(), + family: "spin", + applications: [], + currentCensus: { date: "2026-08-31", total: 12, families: { spin: 4, transmon: 4, atom: 4 } }, + }); + expect(res.ok).toBe(true); + expect(res.stale).toBeUndefined(); + }); +}); + +// ── the workspace wrapper — the audit query over a real problem workspace: +// prior applications are the propose/outcome events the EXISTING amico_recommend +// mechanics append to events.jsonl (the flywheel's input side, no new feed). ── +describe("auditRegimePriorApplications — the workspace audit", () => { + let problemsRoot: string; + const prevProblems = process.env.AMICODE_PROBLEMS_DIR; + + beforeEach(() => { + problemsRoot = mkdtempSync(join(tmpdir(), "regime-priors-audit-")); + process.env.AMICODE_PROBLEMS_DIR = problemsRoot; + }); + afterEach(() => { + if (prevProblems === undefined) delete process.env.AMICODE_PROBLEMS_DIR; + else process.env.AMICODE_PROBLEMS_DIR = prevProblems; + rmSync(problemsRoot, { recursive: true, force: true }); + }); + + const SPIN_SYSTEM = { platform: "silicon spin qubits", levels: 3, params: {} }; + + function stageWorkspace(platform: Record): string { + const meta = createProblem("audit fixture"); + writeEntityFiles(meta.slug, "system", systemToml(platform as never), JSON.stringify(platform) + "\n"); + return meta.slug; + } + + /** The propose event amico_recommend would append for a served regime prior. */ + function proposeRegimePrior(slug: string, note: string, stage = "calibrate", param = "tr_frac", seq?: number) { + return appendEvent(slug, { + entity: "recommendation", + action: "proposed", + diff: { + key: `${stage}/${param}`, + stage, + param, + value: "0.05-0.1", + confidence: "low", + provenance: [{ source: "regime-prior", ref: `regime_priors_table.json#${param}@spin`, note }], + }, + source: { tool: "amicode_recommend", stage }, + }); + } + + it("audits a clean workspace: on-scope application + its outcome pair (the existing flywheel feed) passes", () => { + const slug = stageWorkspace(SPIN_SYSTEM); + const note = selectRegimePriors((loaded.ok ? loaded.table : undefined)!, "spin").find((r) => r.param === "tr_frac")! + .provenance; + const seq = proposeRegimePrior(slug, note); + appendEvent(slug, { + entity: "recommendation", + action: "outcome", + diff: { key: "calibrate/tr_frac", stage: "calibrate", param: "tr_frac", outcome: "accepted", applied_value: "0.05-0.1" }, + source: { tool: "amicode_recommend", stage: "calibrate" }, + }); + const res = auditRegimePriorApplications(slug); + expect(res.ok).toBe(true); + expect(res.audited).toBe(1); + expect(res.family).toBe("spin"); + expect(res.platform).toBe("silicon spin qubits"); + expect(res.applied).toBe(1); // the outcome pair — the flywheel's input side + }); + + it("FAILS on a violation fixture: an off-scope prior applied without the caveat surfaced", () => { + const slug = stageWorkspace(SPIN_SYSTEM); + // a transmon-scoped prior (scope: transmon) proposed into a spin workspace, + // caveat stripped — the misleading case F2 exists to catch + const note = selectRegimePriors((loaded.ok ? loaded.table : undefined)!, "transmon").find((r) => r.param === "tr_frac")! + .provenance.replace(/caveat: [^;]+;?/, ""); + const seq = proposeRegimePrior(slug, note); + const res = auditRegimePriorApplications(slug); + expect(res.ok).toBe(false); + expect(res.violations.length).toBe(1); + expect(res.violations[0].seq).toBe(seq); + expect(res.violations[0].reason).toMatch(/outside its profile scope/); + }); + + it("degrades honestly with no system recorded (nothing to scope against — the caveat alone can save an application)", () => { + const meta = createProblem("no system workspace"); + const note = selectRegimePriors((loaded.ok ? loaded.table : undefined)!, "spin").find((r) => r.param === "tr_frac")! + .provenance; + proposeRegimePrior(meta.slug, note); + const res = auditRegimePriorApplications(meta.slug); + expect(res.ok).toBe(true); // the caveat rides the served provenance + expect(res.family).toBeUndefined(); + expect(res.platform).toBeUndefined(); + }); + + it("surfaces census staleness through the workspace wrapper (a changed census makes the table stale — the audit reports it)", () => { + const slug = stageWorkspace(SPIN_SYSTEM); + const res = auditRegimePriorApplications(slug, { + currentCensus: { date: "2026-09-15", total: 13, families: { spin: 5, transmon: 4, atom: 4 } }, + }); + expect(res.ok).toBe(false); // stale census surfaced + expect(res.stale?.stamped.total).toBe(12); + expect(res.stale?.current.total).toBe(13); + }); + + it("fails honestly when the table itself cannot load (a broken sensor never silently passes)", () => { + const slug = stageWorkspace(SPIN_SYSTEM); + // The wrapper loads the committed file; simulate the unloadable-table path + // by pointing the loader at an empty dir through the exported path seam is + // not possible — instead pin the SHAPE: an ok:false with tableProblems is + // what an unloadable table yields (unit-pinned in the pure-core tests). + const res = auditRegimePriorApplications(slug); + expect(res.tableProblems).toBeUndefined(); // the committed table loads + expect(res.ok).toBe(true); + }); +}); + +// ── AC4: attribution-free in the A1 sense — prior VALUES + provenance strings +// ship; no crossover logic, no profile internals, no vendor attribution. The +// profiles' sources are public-scale arXiv/meeting citations, which ARE +// shippable — the leak guard draws the line mechanically: no census-vendor +// names anywhere in the shipped table, no profile-internal magnitude fields +// (per-vendor drift scales, trust geometry), family-level scoping only. ── +describe("the committed table — the A1 leak guard", () => { + const raw = readFileSync(join(__dirname, "..", "opencode-plugin", "regime_priors_table.json"), "utf8"); + + it("carries no vendor attribution (the census vendors are named NOWHERE — family keying only)", () => { + const vendors = [ + "diraq", "hrl", "intel", "groove", + "google", "ibm", "iqm", "rigetti", + "quera", "pasqal", "atomcomputing", "atom computing", "logiqal", + ]; + const lowered = raw.toLowerCase(); + for (const v of vendors) expect(lowered, `vendor "${v}" must not appear in the shipped table`).not.toContain(v); + }); + + it("carries no profile internals — no drift-scale / trust-geometry / crossover fields, only the five-knob values + their citations", () => { + const table = JSON.parse(raw) as Record; + // the top-level shape is the schema, nothing else + expect(Object.keys(table).sort()).toEqual(["caveat", "census", "dynamic_census_contract", "priors", "schema"]); + const walk = (node: unknown): void => { + if (Array.isArray(node)) { + node.forEach(walk); + return; + } + if (typeof node !== "object" || node === null) return; + for (const [k, v] of Object.entries(node)) { + expect(k, `profile-internal field "${k}" must not ship`).not.toMatch(/drift|trust|geometry|crossover|vendor/); + walk(v); + } + }; + walk(table); + // every entry keys on a NAMED knob with family-level scope — the + // profile-scope families are the platform families, never vendors + for (const e of table.priors as Record[]) { + expect(REGIME_KNOBS).toContain(e.knob); + expect((e.families as string[]).every((f) => ["spin", "transmon", "atom"].includes(f))).toBe(true); + } + }); +}); diff --git a/packages/extension/test/regime_priors_imports.test.ts b/packages/extension/test/regime_priors_imports.test.ts new file mode 100644 index 00000000..718ad7e7 --- /dev/null +++ b/packages/extension/test/regime_priors_imports.test.ts @@ -0,0 +1,60 @@ +// SEAM 2 (amicode #699) — the A1 boundary's structural half, made mechanical +// (the calib_chain_imports.test.ts / mocksoc_imports.test.ts pattern): +// +// `no_intonatissimo_import_possible == 1` — the priors table is committed +// GENERATED content; the module that serves it can never reach the +// internal tier (no import outside node: builtins + the opencode-plugin +// sibling set — Intonatissimo, ../src/, and any npm package beyond the +// siblings are all unreachable by construction, and this pins the +// construction). +// +// `regime_priors_read_only == 1` — the module never writes: the table is +// served, never mutated; prior applications + outcomes ride the EXISTING +// recommendation mechanics (amicode_recommend propose/outcome → the +// provenance-spine helpers in problems.ts), and the audit only READS the +// events back. A direct fs write here would bypass the diff/hash/event +// spine — the same invariant calib_chain's core lives under. +import { describe, it, expect } from "vitest"; +import { readFileSync } from "node:fs"; +import { join } from "node:path"; + +const CORE = join(__dirname, "..", "opencode-plugin", "regime_priors.ts"); +const SIBLINGS = new Set(["./ledger_client", "./entities", "./problems"]); + +describe("regime priors module — the A1 import surface (structural scan)", () => { + const src = readFileSync(CORE, "utf8"); + + it("imports only node: builtins + the opencode-plugin siblings (the internal tier is unreachable by construction)", () => { + const imports = [ + ...src.matchAll(/^import[^"']*["']([^"']+)["'];?$/gm), + ...src.matchAll(/^export[^"']*from["']([^"']+)["'];?$/gm), + ].map((m) => m[1]); + expect(imports.length).toBeGreaterThan(0); + for (const spec of imports) { + expect( + spec.startsWith("node:") || (spec.startsWith("./") && SIBLINGS.has(spec)), + `import "${spec}" is outside the allowed surface (node: builtins + ${[...SIBLINGS].join(", ")})`, + ).toBe(true); + } + // the module CODE never references the internal tier outside the boundary- + // describing header comments (the data file leak guard lives in + // regime_priors.test.ts — this scan pins the CODE's import surface). + const code = src + .split("\n") + .filter((l) => !l.trim().startsWith("//") && !l.trim().startsWith("*") && !l.trim().startsWith("/*")) + .join("\n"); + expect(code).not.toMatch(/Intonatissimo|VENDOR_PROFILES/); + }); + + it("performs no direct filesystem WRITE — the table is served read-only; applications ride the existing mechanics", () => { + const offenders = src + .split("\n") + .map((l, i) => [i + 1, l] as const) + .filter(([, l]) => /fs\.(write|append|mkdir|rename|copy|rm|unlink)Sync/.test(l)); + expect(offenders, `direct fs writes in the regime priors module: ${JSON.stringify(offenders)}`).toEqual([]); + // the events feed is the EXISTING one: the audit reads events.jsonl back + // (read-only), it never appends. + expect(src).toMatch(/readFileSync/); + expect(src).not.toMatch(/appendEvent/); + }); +});