design: IR repo should own cross-language golden wire fixtures (canonical contract for Rust Planner) #4

Open
opened 2026-06-11 15:37:59 +02:00 by yorunikakeru · 1 comment
Owner

IR's reason to exist is being the stable JSON contract between Haskell and the future Rust Planner. Today the only on-disk wire artifacts are in the DSL repo (test/fixtures/*.json), and IR's own tests check Haskell-internal roundtrips only.

When the Rust side lands, serde definitions become a third independent encoding of the same contract (after Haskell ToJSON and Haskell FromJSON). Without shared fixtures, drift is detected by integration failure at runtime.

Proposal:

  1. Move/copy canonical `intent.json` fixtures into IR repo (`fixtures/v2/*.json`), one per feature: profile+condition+observe, priorities, policies, and/not composition.
  2. IR CI: decode each fixture, re-encode, byte-compare (golden).
  3. Rust Planner repo consumes the same files in its serde tests.
  4. Optionally generate a JSON Schema from the fixtures for documentation.

This makes IR the single source of truth instead of "whatever the DSL currently emits".

IR's reason to exist is being the stable JSON contract between Haskell and the future Rust Planner. Today the only on-disk wire artifacts are in the **DSL** repo (test/fixtures/*.json), and IR's own tests check Haskell-internal roundtrips only. When the Rust side lands, serde definitions become a third independent encoding of the same contract (after Haskell ToJSON and Haskell FromJSON). Without shared fixtures, drift is detected by integration failure at runtime. Proposal: 1. Move/copy canonical \`intent.json\` fixtures into IR repo (\`fixtures/v2/*.json\`), one per feature: profile+condition+observe, priorities, policies, and/not composition. 2. IR CI: decode each fixture, re-encode, byte-compare (golden). 3. Rust Planner repo consumes the same files in its serde tests. 4. Optionally generate a JSON Schema from the fixtures for documentation. This makes IR the single source of truth instead of "whatever the DSL currently emits".
Author
Owner

Scope update: Planner core is Haskell (GHC native lib behind FFI, Rust actor wrapper). Rust never deserializes IR - it passes intent.json as opaque bytes to the Haskell core, which uses the existing aeson instances. So fixtures here guard Haskell encode/decode stability across IR versions, not Rust serde drift. Cross-language golden fixtures are still needed, but for SystemState and Plan - they belong in the Planner repo (see FrogOS/planner#1).

Scope update: Planner core is Haskell (GHC native lib behind FFI, Rust actor wrapper). Rust never deserializes IR - it passes intent.json as opaque bytes to the Haskell core, which uses the existing aeson instances. So fixtures here guard Haskell encode/decode stability across IR versions, not Rust serde drift. Cross-language golden fixtures are still needed, but for SystemState and Plan - they belong in the Planner repo (see FrogOS/planner#1).
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
FrogOS/IR#4
No description provided.