Skip to content

Bring the AMICODE_* stdout grammar under the shared-fixture roundtrip discipline #83

Description

@jack-champagne

Problem

The run-dir contract has three producer↔consumer boundaries. Two are guarded; the stdout grammar is the one that escaped the discipline.

Boundary Producer Consumer Guard
orchestrator ↔ schema (TOML) amico-run schema producer_roundtrip.sh + SchemaPackage
host ↔ webview (inspector msgs/DOM) RunsManager RunInspector ⏳ frozen; gated by #62
solver ↔ host (AMICODE_* stdout) solve_template.jl (@printf) run_dir_reader.ts (regex) unguarded

The AMICODE_PULSE_META / AMICODE_ITER / AMICODE_PULSE grammar (#66, self-labeled prototype-grade at solve_template.jl:45) is encoded three independent times:

  1. @printf in packages/extension/templates/solve_template.jl
  2. regexes in packages/extension/src/run_dir_reader.ts
  3. hand-copied string templates in packages/extension/test/corpus/fake-julia (1.4a: smoke corpus — seconds-scale end-to-end fixtures (Scheduler → executor → RunsManager → Inspector) #78)

The #78 smoke corpus proves fake ↔ parser agreement (wiring). It does not guard template ↔ parser: if solve_template.jl changes its emit format and the parser isn't updated, fake-julia doesn't change either, so the suite stays green while real solves silently break.

Why the existing roundtrip does not already cover this

packages/schema/julia/emit_fixture.jl is a 14-line, TOML-stdlib-only stub. Its lone AMICODE line is a hardcoded literal

println("AMICODE_ITER iter=1 f=1.000000e-03 inf_pr=1.0e-9 inf_du=1.0e-6"); flush(stdout)

— that exists only so amico-run's tail has something to drain while producer_roundtrip.sh validates result.toml against the schema. It is not the template's emit code, and it is never fed to the TS parser. So producer_roundtrip.sh guards TOML↔schema only; there is no consumer-side (parser) step in it today. This is new coverage modeled on the schema fixture pattern — not an extension of that script.

Proposed fix (right-sized to 3 line types)

  1. Extract the template's emit into shared Julia helpersemit_pulse_meta / emit_iter / emit_pulse — so solve_template.jl has one emit site instead of scattered @printf (mirrors the emit_formulation helper from feat(contract): pre-solve formulation.toml (additive; scoped counterpart to #64) #81).
  2. One canonical fixture (one sample line per type) checked in once, that both sides reference — same mechanism as the schema test fixtures.
  3. Two small tests + AC6 perturbation:
    • Julia: the emit helpers reproduce exactly the fixture lines.
    • TS: run_dir_reader parses the fixture lines into the expected records.
    • Perturb the fixture → both must fail. That's what makes template↔parser format drift impossible to land green on the shared emit path.
  4. Point fake-julia at the same fixtures (generate from / diff against) so the fake can't drift from the template either — all three encodings trace to one source.

Explicit non-goals / limits (so a future reader doesn't over-trust it)

  • Format drift only, not semantic drift. A row-major↔column-major flip in a=, or a dt unit change, still parses — green — but means something different. A format roundtrip cannot catch that.
  • "Impossible to land green" holds only for emit that goes through the shared helper. A new inline @printf in the template bypasses the guard (same residual as hand-writing TOML instead of using the schema writer).
  • Optional slow-tier canary (one real tiny Julia solve, nightly/on-demand) is the only thing that exercises genuine end-to-end emit — but it earns its Julia cost only if it asserts parsed pulse values, not liveness. A canary that checks "ran + FINISHED" catches nothing the format roundtrip doesn't. Specify golden-value assertions or skip it.

Sequencing & placement

Relationship

Same species as #81 (formulation.toml additive contract) and the readTerminal/ingestRunDir duplication caught in #70 review: parallel copies of one truth drift. The repo already knows the cure (SchemaPackage + fixture roundtrip); this applies it to the last uncovered piece of the run-dir contract.

Surfaced by the #78 smoke-corpus review (finding #1).

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