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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions