You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Critical-path root of Phase 0β². Land to main fast β this blocks #16, #17, #18, which branch from main once it merges (do not rebuild a deep stack like the Ξ² rollout).
Locked (already reflected below): five schemas incl. SolveSpec (owned here, assembled in amico-run); manifest.toml/result.toml reverse-engineered from Ξ²'s actual emissions β formalize, don't fork.
Added β execution-environment contract (from the #24 Piccolissimo binary recheck). The schemas must make the runtime contract machine-checkable, not only the config/artifact shapes. On the shipped Piccolissimo binary, #24's template is non-functional β using Piccolo/Piccolissimo/CairoMakie all fail and JLD2.save crashes the run β yet it "passed" against a source Pkg.develop env, because nothing declares what the lab runtime provides vs what the solve requires. So v0 of the frozen contract must carry that dimension:
SolveSpec declares what the solve requires β packages/symbols, load mechanism, julia patch.
lab.toml declares what the lab runtime provides β image/depot ref, julia version, loadable packages, license presence.
The run-dir contract and every config artifact (lab.toml, SolveSpec, manifest.toml, result.toml, catalog-entry) is the universal interface every surface reads, but its shape lives only as prose plus Ξ².1's emitter code. Ξ² has no validation layer at all (plan Β§2), so the contract is unenforced: the extension, the CLI, CI, and the Julia emitter can each interpret it differently and drift independently. There is no machine-checkable definition and no single schema_version carrier, so a contract bump silently breaks old runs.
Approach
Stand up the shared workspace SchemaPackage as the single source of truth: JSON Schemas for all five artifacts β lab.toml, SolveSpec, manifest.toml, result.toml, catalog-entry β each carrying schema_version, behind one validate() consumed by the extension, the amico-run CLI, and CI, plus a Julia round-trip that validates emitted artifacts against the same schemas. This formalizes the run-dir contract Ξ².1 currently emits as prose + emitter-code into a versioned, machine-checkable schema set. The FINISHED terminal sentinel ({status, exitCode}) is captured as a sub-shape of the run-dir contract, not as a sixth peer schema with its own schema_version.
Approaches Considered
Shared workspace package, JSON Schema as source of truth, one validate() for TS + a Julia round-trip check (chosen β kills cross-language drift at one seam)
No shared layer, keep the contract as prose + Ξ².1 emitter code β rejected: that is the Ξ² status quo with no machine check and no version gate
TS-types-only with zod/io-ts β rejected: not consumable by the Julia emitter, so the cross-language drift risk (the whole point) survives
Scope
In: JSON Schemas for lab.toml, SolveSpec, manifest.toml, result.toml, catalog-entry; schema_version on each; validate(artifact, kind); the FINISHED{status, exitCode} sub-shape of the run-dir contract; package wired as a workspace dep for extension + CLI; CI fast-tier validation of committed fixtures + a Julia round-trip check of emitted manifest.toml/result.toml.
Out:
The lab.toml on-load field-precise-error UX (S17) β sibling slice 0.1b owns that distinct on-load behavior; the lab.toml schema itself is defined here.
CatalogStore / any catalog-entry consumer β Phase 3 (3.1); the entry SCHEMA is defined here, the STORE is not.
HDF5 export schema/shape beyond what the catalog-entry references β Phase 3 (3.2) owns the export API.
Schema-version migration transforms / upgrade maps β only the schema_version field lands now; maps land when the first bump happens.
Assumptions / Open Qs
Ξ².1's emitted manifest.toml/FINISHED/result.toml are the authoritative shapes to encode (this slice formalizes the contract Ξ².1 emits; it does not redesign it).
SolveSpec's schema is owned by SchemaPackage as the single source of truth; amico-run assembles a SolveSpec and calls validate() on it β it does not own the schema.
JSON Schema (not a TS-only validator) so the same files drive the Julia round-trip β resolves Q86's cross-language home.
Acceptance Criteria
A well-formed lab.toml, SolveSpec, manifest.toml, result.toml, and catalog-entry each validate against their schema via the package's single validate() entrypoint.
A malformed artifact (missing required key, wrong type, out-of-range value, unknown key) fails validation with an error that names the offending key and its path.
Every schema carries a schema_version; an artifact whose schema_version is absent or unrecognized is rejected (not silently accepted as current).
A manifest.toml whose FINISHED field carries a {status, exitCode} outside the allowed terminal-status set fails validation against the run-dir-contract shape.
The CI fast tier validates committed fixtures for all five artifacts against the package and fails the PR on any nonconformance.
A Julia-emitted result.toml and manifest.toml round-trip: emitted by the solver path, then validated against the SAME schema files in CI (no second, transcribed copy).
SolveSpec's requires (packages + symbols, load mechanism, julia patch) and lab.toml's provides (image/depot, julia version, loadable packages, license) are schema-validated; validate() rejects a SolveSpec whose requires are not satisfied by the target lab's provides β e.g. the DRAFT feat(template): verified Piccolissimo solve template (beta target) + integration contractΒ #24 case (requires using-loadable Piccolissimo + CairoMakie; lab provides an image-only depot without CairoMakie) fails before any run.
The Julia round-trip is exercised against a real binary-backed runtime (the shipped pkgimage), not only a source Pkg.develop env, so an artifact that validates only under source is caught.
The extension and amico-run both obtain validation only from this package's validate(); a consumer that reintroduces its own schema definition is a regression.
The catalog-entry schema validates a representative promote-shaped record even though no store consumes it yet.
Key Decisions
JSON Schema is the single source of truth; one validate() shared across CLI, extension, CI, and a Julia round-trip (PRD Schema-package decision; resolves Q86).
All five schemas (lab.toml, SolveSpec, manifest.toml, result.toml, catalog-entry) live in SchemaPackage; SolveSpec is validated here even though it is assembled in amico-run.
schema_version lives on every artifact; manifest.toml is the per-run version + provenance carrier.
FINISHED is the run-dir's terminal sentinel ({status, exitCode}), modeled as a sub-shape of the run-dir contract, not a peer schema with its own schema_version.
This package formalizes Ξ².1's prose + emitter-code run-dir contract into versioned machine-checkable schemas; it supersedes the informal contract, not any pre-existing validators (Ξ² has none).
catalog-entry schema is in-scope here; its store/consumer is Phase 3.
Constraints & Invariants
The schemas must encode Ξ².1's emitted run-dir contract exactly β formalize, do not fork it.
One validator path only: a consumer adding its own schema definition is a regression.
The Julia round-trip must use the same schema files as the TS consumers, not a transcription.
Prior Art / Patterns
SchemaPackage (the deep module rooted at the top of the dependency order). The run-dir contract artifacts: manifest.toml, result.toml, the FINISHED terminal sentinel; plus the lab.toml, SolveSpec, and catalog-entry config schemas. The amico-run SolveSpec builder (assembles a SolveSpec, then calls the shared validate()). The RunsManager / RunInspector / CatalogStore as downstream consumers of these shapes. The Julia round-trip validator pattern (emit-then-validate against the shared schemas in CI).
Source
Phase 0-prime task 0.1 (SchemaPackage, 6 pd), sliced to 0.1a (the full five-schema SET + shared validate() + CI fast-tier conformance + Julia round-trip); plan-20260603 Β§3 Phase 0'. Realizes S14 (versioned schema per config/artifact), S15 (machine-checkable validate()), S16 (CI conformance + Julia round-trip of emitted artifacts). Resolves Q86 (schema home / cross-language sharing). Partially resolves Q87 (per-artifact schema_version on all five artifacts; migration maps deferred to the first bump). Related: #1 (Ξ².1 emits the contract this formalizes), sibling 0.1b (the S17 lab.toml on-load field-precise error UX), 3.1 CatalogStore (the catalog-entry consumer, Phase 3).
Notes
This slice is the dependency-graph root for Phase 0-prime β its consumers (lab.toml on-load UX 0.1b, CatalogStore 3.1) gate on it. The plan treats 0.1 SchemaPackage as one 6-pd task; this split keeps the full schema SET (all five, incl. SolveSpec) + shared validate() + CI conformance + Julia round-trip together in 0.1a as one coherent vertical slice, and carves out ONLY the distinct S17 lab.toml on-load field-precise-error behavior as 0.1b. Do not merge them and do not pull the catalog STORE or HDF5 export forward.
Testing
TDD applies (RED->GREEN): write failing validation cases first. Extend the CI fast tier's schema-validation suite (committed-fixture conformance across all five artifacts + the Julia round-trip emit-then-validate); add the per-field/per-constraint negative matrix asserting the error names the offending field. No prescribed test names β the tdd loop decides structure.
Note
π Decision update β 2026-06-27
Critical-path root of Phase 0β². Land to
mainfast β this blocks #16, #17, #18, which branch frommainonce it merges (do not rebuild a deep stack like the Ξ² rollout).Owner: @Rchari1 Β· Reviewer: @jack-champagne
Locked (already reflected below): five schemas incl. SolveSpec (owned here, assembled in amico-run);
manifest.toml/result.tomlreverse-engineered from Ξ²'s actual emissions β formalize, don't fork.Added β execution-environment contract (from the #24 Piccolissimo binary recheck). The schemas must make the runtime contract machine-checkable, not only the config/artifact shapes. On the shipped Piccolissimo binary, #24's template is non-functional β
using Piccolo/Piccolissimo/CairoMakieall fail andJLD2.savecrashes the run β yet it "passed" against a sourcePkg.developenv, because nothing declares what the lab runtime provides vs what the solve requires. So v0 of the frozen contract must carry that dimension:validate()cross-checksrequires β provides, so a DRAFT feat(template): verified Piccolissimo solve template (beta target) + integration contractΒ #24-class mismatch fails at validate-time, before any run.Important
Problem
The run-dir contract and every config artifact (
lab.toml, SolveSpec,manifest.toml,result.toml, catalog-entry) is the universal interface every surface reads, but its shape lives only as prose plus Ξ².1's emitter code. Ξ² has no validation layer at all (plan Β§2), so the contract is unenforced: the extension, the CLI, CI, and the Julia emitter can each interpret it differently and drift independently. There is no machine-checkable definition and no singleschema_versioncarrier, so a contract bump silently breaks old runs.Approach
Stand up the shared workspace SchemaPackage as the single source of truth: JSON Schemas for all five artifacts β
lab.toml, SolveSpec,manifest.toml,result.toml, catalog-entry β each carryingschema_version, behind onevalidate()consumed by the extension, the amico-run CLI, and CI, plus a Julia round-trip that validates emitted artifacts against the same schemas. This formalizes the run-dir contract Ξ².1 currently emits as prose + emitter-code into a versioned, machine-checkable schema set. TheFINISHEDterminal sentinel ({status, exitCode}) is captured as a sub-shape of the run-dir contract, not as a sixth peer schema with its ownschema_version.Approaches Considered
validate()for TS + a Julia round-trip check (chosen β kills cross-language drift at one seam)zod/io-tsβ rejected: not consumable by the Julia emitter, so the cross-language drift risk (the whole point) survivesScope
In: JSON Schemas for
lab.toml, SolveSpec,manifest.toml,result.toml, catalog-entry;schema_versionon each;validate(artifact, kind); theFINISHED{status, exitCode}sub-shape of the run-dir contract; package wired as a workspace dep for extension + CLI; CI fast-tier validation of committed fixtures + a Julia round-trip check of emittedmanifest.toml/result.toml.Out:
lab.tomlon-load field-precise-error UX (S17) β sibling slice 0.1b owns that distinct on-load behavior; thelab.tomlschema itself is defined here.schema_versionfield lands now; maps land when the first bump happens.Assumptions / Open Qs
manifest.toml/FINISHED/result.tomlare the authoritative shapes to encode (this slice formalizes the contract Ξ².1 emits; it does not redesign it).validate()on it β it does not own the schema.Acceptance Criteria
lab.toml, SolveSpec,manifest.toml,result.toml, and catalog-entry each validate against their schema via the package's singlevalidate()entrypoint.schema_version; an artifact whoseschema_versionis absent or unrecognized is rejected (not silently accepted as current).manifest.tomlwhoseFINISHEDfield carries a{status, exitCode}outside the allowed terminal-status set fails validation against the run-dir-contract shape.result.tomlandmanifest.tomlround-trip: emitted by the solver path, then validated against the SAME schema files in CI (no second, transcribed copy).requires(packages + symbols, load mechanism, julia patch) and lab.toml'sprovides(image/depot, julia version, loadable packages, license) are schema-validated;validate()rejects a SolveSpec whoserequiresare not satisfied by the target lab'sprovidesβ e.g. the DRAFT feat(template): verified Piccolissimo solve template (beta target) + integration contractΒ #24 case (requiresusing-loadable Piccolissimo + CairoMakie; lab provides an image-only depot without CairoMakie) fails before any run.Pkg.developenv, so an artifact that validates only under source is caught.validate(); a consumer that reintroduces its own schema definition is a regression.Key Decisions
validate()shared across CLI, extension, CI, and a Julia round-trip (PRD Schema-package decision; resolves Q86).lab.toml, SolveSpec,manifest.toml,result.toml, catalog-entry) live in SchemaPackage; SolveSpec is validated here even though it is assembled in amico-run.schema_versionlives on every artifact;manifest.tomlis the per-run version + provenance carrier.FINISHEDis the run-dir's terminal sentinel ({status, exitCode}), modeled as a sub-shape of the run-dir contract, not a peer schema with its ownschema_version.Constraints & Invariants
Prior Art / Patterns
SchemaPackage (the deep module rooted at the top of the dependency order). The run-dir contract artifacts: manifest.toml, result.toml, the FINISHED terminal sentinel; plus the lab.toml, SolveSpec, and catalog-entry config schemas. The amico-run SolveSpec builder (assembles a SolveSpec, then calls the shared validate()). The RunsManager / RunInspector / CatalogStore as downstream consumers of these shapes. The Julia round-trip validator pattern (emit-then-validate against the shared schemas in CI).Source
Phase 0-prime task 0.1 (SchemaPackage, 6 pd), sliced to 0.1a (the full five-schema SET + shared
validate()+ CI fast-tier conformance + Julia round-trip); plan-20260603 Β§3 Phase 0'. Realizes S14 (versioned schema per config/artifact), S15 (machine-checkablevalidate()), S16 (CI conformance + Julia round-trip of emitted artifacts). Resolves Q86 (schema home / cross-language sharing). Partially resolves Q87 (per-artifactschema_versionon all five artifacts; migration maps deferred to the first bump). Related: #1 (Ξ².1 emits the contract this formalizes), sibling 0.1b (the S17lab.tomlon-load field-precise error UX), 3.1 CatalogStore (the catalog-entry consumer, Phase 3).Notes
This slice is the dependency-graph root for Phase 0-prime β its consumers (lab.toml on-load UX 0.1b, CatalogStore 3.1) gate on it. The plan treats 0.1 SchemaPackage as one 6-pd task; this split keeps the full schema SET (all five, incl. SolveSpec) + shared
validate()+ CI conformance + Julia round-trip together in 0.1a as one coherent vertical slice, and carves out ONLY the distinct S17lab.tomlon-load field-precise-error behavior as 0.1b. Do not merge them and do not pull the catalog STORE or HDF5 export forward.Testing
TDD applies (RED->GREEN): write failing validation cases first. Extend the CI fast tier's schema-validation suite (committed-fixture conformance across all five artifacts + the Julia round-trip emit-then-validate); add the per-field/per-constraint negative matrix asserting the error names the offending field. No prescribed test names β the tdd loop decides structure.