Skip to content

0.1b — Add the lab.toml schema and validate it on extension load with field-precise errors #16

Description

@jack-champagne

Phase: 0-prime — Contracts/foundation · Plan task: 0.1 (SchemaPackage, lab.toml slice) · Implementing repo: amicode

Blocked by: 0.1a (SchemaPackage scaffold + shared validator + schema_version convention)

Important

Problem

A partner lab's lab.toml is the only place hardware params (frequencies, anharmonicities, couplings, drive cap) enter a solve. Today nothing validates it: β supports one lab via interview-baked constants or a raw lab.toml path with no validation layer (β.3's template reads params "from the interview or from a lab.toml path"), so a malformed or mistyped config either silently solves against the wrong hardware or fails opaquely mid-solve. A lab partner cannot fix their own config without reading source.

Approach

Add a versioned JSON Schema for lab.toml to the shared SchemaPackage (built on 0.1a's scaffold + shared validator), plus the validator entry point the extension calls when a lab.toml is loaded, emitting a field-precise error that names the offending key and its dotted path on malformed input.

Approaches Considered

  • Schema + shared-validator field-precise error path (chosen) — one source of truth, reused by CLI/CI/Julia round-trip from 0.1a.
  • Hand-rolled per-field checks in the extension — duplicates logic, drifts from the schema, no CI/Julia reuse.
  • Defer validation, parse-and-pray at solve time — the β.3 status quo; reproduces the silent-wrong-hardware failure this slice exists to kill.

Scope

In: the lab.toml JSON Schema (schema_version-bearing); the load-time validator surface the extension invokes; field-precise error reporting (offending key + dotted path); fixture-driven negative cases.
Out:

  • Value-range / sanitization / injection guards (huge N, path-traversal, shell/eval flow) — schema-valid ≠ safe; deferred hygiene (Q110/Q111), not a 0-prime gate.
  • Active-lab discovery / precedence (workspace vs user) and multi-lab generalization — Phase 2 (Q134).
  • Lab-injection-correctness (values land in the emitted SolveSpec) — that is the merge path, not this schema (Q44).
  • Editor inline diagnostics UI surfacing — the validator returns the field-precise error; wiring it into a diagnostics panel is a separate UI concern.

Assumptions

  • 0.1a has landed the shared validator harness and schema_version convention this schema plugs into.
  • The lab.toml field set (which params are required vs optional) is taken from the Schuster hardware profile the β template already consumes; this slice formalizes it, it does not negotiate it.

Acceptance Criteria

  • A schema-valid lab.toml (Schuster profile) validates clean with no error. (S17)
  • A lab.toml with a wrong-typed value yields a single error naming the offending key and its dotted path (e.g. the key and where it sits), not a bare valid===false. (S17)
  • A missing required key yields a field-precise error naming the absent key + its path. (S17)
  • An unknown / misspelled key is rejected with a field-precise error naming that key. (S17)
  • The schema carries a schema_version and validation rejects an unsupported version with a version-specific error. (S14)
  • The extension's load-time validation accepts/rejects exactly the same lab.toml inputs as the CLI/CI validator over the shared negative-fixture corpus (no input is valid in one and invalid in the other). (S14)
  • A negative matrix (missing / wrong-type / unknown-key / bad-version) over the lab.toml fields each asserts the error points at the right field. (S17)

Key Decisions

  • JSON Schema is the single source of truth; the lab.toml schema lives in the shared SchemaPackage and is consumed by extension + CLI + CI + the Julia round-trip (per 0.1a).
  • The lab-partner promise is field-precise errors: the test asserts the error names the offending field, not merely that validation failed.

Constraints & Invariants

  • schema_version is carried by the schema; an unknown newer version is a typed, recoverable rejection, never a silent pass.
  • This slice supersedes β.3's no-validation lab.toml handling — both the raw lab.toml path and the interview-baked-constants path the template reads: once landed, a loaded lab.toml is validated before it can reach a solve.
Prior Art / Patterns
  • SchemaPackage — the shared JSON-Schema source of truth + validate() surface consumed by extension, CLI, CI, and the Julia round-trip (0.1a scaffolds it; this slice adds the lab.toml member).
  • The β.3 solve-script template + AGENTS.md — already read lab params from a lab.toml path or interview-baked constants; this schema formalizes the shape they assume.
  • The negative-matrix schema-validation pattern (per-field × per-constraint) asserting the error points at the offending field.

Testing

Extend the CI fast-tier schema-validation suite (table-driven lab.toml negative matrix asserting field-precise errors), alongside the extension fast tier for the load-time validator entry point. Semi-TDD: phrase each negative case as a failing assertion on the named offending field/path; the extension/CLI parity case is a failing assertion that both reach the same accept/reject verdict over the shared fixture corpus.

Source

Phase 0-prime plan task 0.1 (SchemaPackage, lab.toml slice; DoD: "a malformed lab.toml yields a field-precise error (S17)"). Realizes S17; S29/S30 provenance (lab.toml is the config a partner drops in and the source of injected hardware params). PRD §"Schema package" + §Interfaces (SchemaPackage); PRD testing-decisions ("We do not pin internals"). Decisions: schema home / shared-package (Q86), schema_version carrier (Q54/Q87), field-precise-error test bar (Q32). Out-of-scope rationale: Q110/Q111 (sanitization), Q134 (discovery/precedence), Q44 (injection correctness). Depends on 0.1a (SchemaPackage scaffold + shared validator). Supersedes β.3's unvalidated lab.toml handling (raw path + interview-baked constants; plan §2 β.3 + S30 note "β supports one lab via a single lab.toml path or interview-baked constants").

Notes

This is the lab.toml schema β explicitly deferred from its flat one-lab starter — β.3 proved a single hardcoded/raw config works; 0-prime makes any lab's config machine-checkable so additional labs compose without hand-edits. Catalog-entry SCHEMA shape is a sibling 0.1 slice; the catalog STORE/consumer is Phase 3. Correctly sliced as a bite-sized vertical slice (schema + validator + error path); do not merge with 0.1a or further decompose.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions