Skip to content

feat(ir): stamp ir_version into every IR projection; emitters validate before rendering (#62)#79

Merged
danielPoloWork merged 1 commit into
mainfrom
feat/ir-version-stamp
Jul 2, 2026
Merged

feat(ir): stamp ir_version into every IR projection; emitters validate before rendering (#62)#79
danielPoloWork merged 1 commit into
mainfrom
feat/ir-version-stamp

Conversation

@danielPoloWork

Copy link
Copy Markdown
Owner

Problem (#62)

Manifests carry schema_version: 1, but the emitted IR JSON carried no version or schema marker. The IR is a persisted artifact (build/*.json) that outlives tool runs and crosses the determinism boundary into five emitters — yet an emitter couldn't tell whether the JSON it received matched the contract it was written for. When a block type or field is renamed, an old cached IR (or an IR from a newer render) mis-renders silently: unknown block types already fall through to return "" in _flatten/_line.

Fix

  • render.pyIR_VERSION = 1 + GENERATOR = "eamos-render", stamped as the first two fields of all six projections (deck, infographic, data, mindmap, quiz, topology). Bump policy: ir_version increments on any breaking change to block/field shapes.

  • New _cli.require_ir_version(ir, tool, supported) — every emitter (emit_md, emit_pptx, emit_docx, emit_svg, emit_xlsx) validates right after loading the artifact, each pinning its own SUPPORTED_IR_VERSION = 1. A mismatch — or an absent field, i.e. a pre-feat(ir): stamp ir_version into every IR projection; emitters validate before rendering #62 artifact — is refused with one actionable line:

    emit_md: IR version None not supported (expected 1); re-render the manifest
    
  • os/deck-ir/_schema.md documents both fields and adds the Versioned contract invariant.

Tests

  • All six projections stamp ir_version == render.IR_VERSION and generator.
  • Reject path: emit_md on an unversioned IR exits non-zero in a subprocess with the message above, no traceback. Accept path: a fresh render → emit_md round-trips clean.
  • Determinism smoke unaffected (two renders byte-identical); 90/90 tests green.

Closes #62

🤖 Generated with Claude Code

…e before rendering (#62)

Manifests carry schema_version, but the emitted IR JSON carried no
version marker. The IR is a persisted artifact (build/*.json) that
outlives tool runs and crosses the determinism boundary into five
emitters — an emitter could not tell whether the JSON it received
matched the contract it was written for, and unknown block types
already fall through silently in _flatten/_line.

- render.py: IR_VERSION = 1 + GENERATOR = 'eamos-render', stamped as
  the first two fields of all six projections (deck, infographic,
  data, mindmap, quiz, topology). Bump policy: ir_version increments
  on any breaking change to block/field shapes.
- New _cli.require_ir_version: every emitter (md, pptx, docx, svg,
  xlsx) validates right after loading the artifact and refuses a
  mismatch — or an absent field, i.e. a pre-#62 IR — with one
  actionable line: "IR version None not supported (expected 1);
  re-render the manifest".
- os/deck-ir/_schema.md documents both fields and the bump policy as
  a new invariant.

Tests: all six projections stamped; emit_md rejects an unversioned IR
in a subprocess (exit != 0, no traceback) and accepts a fresh render.
Determinism smoke unaffected; 90/90 green.

Closes #62

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@danielPoloWork danielPoloWork added the enhancement New feature or request label Jul 2, 2026
@danielPoloWork danielPoloWork self-assigned this Jul 2, 2026
@danielPoloWork danielPoloWork added the enhancement New feature or request label Jul 2, 2026
@danielPoloWork danielPoloWork marked this pull request as ready for review July 2, 2026 20:43
@danielPoloWork danielPoloWork merged commit 866ed09 into main Jul 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ir): stamp ir_version into every IR projection; emitters validate before rendering

1 participant