Skip to content

0.1a β€” Establish the shared SchemaPackage as the single source of truth for all five config/artifact schemasΒ #15

Description

@jack-champagne

Note

πŸ”’ Decision update β€” 2026-06-27

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).

Owner: @Rchari1 Β· Reviewer: @jack-champagne

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:


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 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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions