a8c29d130b
New top-level experiments/2026-05-12-cross-model-authoring/ (out of
root Cargo workspace; nested-crate standalone via empty [workspace]
table per Cargo idiom). The renderer projects one canonical
master/spec.md into two form-specific files (rendered/json.md and
rendered/ailx.md) by walking three directive forms ({form-only:
json}, {form-only: ailx}, {example: <id>}) and emitting per-example
fenced blocks sourced from 13 curated .ail.json fixtures.
Four test gates green (10/10 total):
- splitter_unit (7) — directive parser, malformed inputs panic
- spec_completeness (1) — AST-variant visitor lifted verbatim from
schema_coverage.rs; 34/34 variants covered by the curated subset
- example_roundtrip (1) — every fixture roundtrips through
ailang_surface::{print, parse} to identical canonical bytes
- token_balance (1) — form-only block totals balanced to 3.22% under
tiktoken-rs::cl100k_base (gate is ±5%)
Six of the 34 variants did not have a dedicated fixture topic in the
plan and were absorbed into the closest existing fixture per the
plan's Step 4.14 escape hatch (Let/Clone → fn_calls_prelude; LetRec
→ data_with_match; If → match_literal_pattern; ReuseAs →
data_simple; Const → floats). Surfaced as a journal note, not a
plan revision.
Two ancillary additions vs. plan, both structural Cargo necessities,
spec-compatible: render/Cargo.toml carries an empty [workspace] table
so the nested crate refuses parent-workspace discovery, and
render/.gitignore drops /target + Cargo.lock. Both surfaced inline
in the per-iter journal's Concerns section.
cma.2 (harness) and cma.3 (live IONOS run + DESIGN.md addendum +
journal + roadmap edits) remain out of scope per the spec.
80 lines
2.4 KiB
Rust
80 lines
2.4 KiB
Rust
use xmodel_render::splitter::{split, Form, Segment};
|
|
|
|
#[test]
|
|
fn plain_text_passes_through_unchanged() {
|
|
let input = "hello\nworld\n";
|
|
let segments = split(input);
|
|
assert_eq!(segments, vec![Segment::Prose("hello\nworld\n".to_string())]);
|
|
}
|
|
|
|
#[test]
|
|
fn form_only_block_is_isolated() {
|
|
let input = "before\n{form-only: json}\nschema rule\n{/form-only}\nafter\n";
|
|
let segments = split(input);
|
|
assert_eq!(
|
|
segments,
|
|
vec![
|
|
Segment::Prose("before\n".to_string()),
|
|
Segment::FormOnly { form: Form::Json, body: "schema rule\n".to_string() },
|
|
Segment::Prose("after\n".to_string()),
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn ailx_form_only_block_uses_ailx_form() {
|
|
let input = "{form-only: ailx}\ngrammar rule\n{/form-only}\n";
|
|
let segments = split(input);
|
|
assert_eq!(
|
|
segments,
|
|
vec![
|
|
Segment::FormOnly { form: Form::Ailx, body: "grammar rule\n".to_string() },
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn example_marker_is_isolated() {
|
|
let input = "before\n{example: empty_module}\nafter\n";
|
|
let segments = split(input);
|
|
assert_eq!(
|
|
segments,
|
|
vec![
|
|
Segment::Prose("before\n".to_string()),
|
|
Segment::Example("empty_module".to_string()),
|
|
Segment::Prose("after\n".to_string()),
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn multiple_directives_in_sequence() {
|
|
let input = "p1\n{example: a}\n{form-only: json}\njs\n{/form-only}\n{form-only: ailx}\nax\n{/form-only}\n{example: b}\np2\n";
|
|
let segments = split(input);
|
|
assert_eq!(
|
|
segments,
|
|
vec![
|
|
Segment::Prose("p1\n".to_string()),
|
|
Segment::Example("a".to_string()),
|
|
Segment::FormOnly { form: Form::Json, body: "js\n".to_string() },
|
|
Segment::FormOnly { form: Form::Ailx, body: "ax\n".to_string() },
|
|
Segment::Example("b".to_string()),
|
|
Segment::Prose("p2\n".to_string()),
|
|
]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn unknown_form_name_is_an_error() {
|
|
let input = "{form-only: yaml}\nx\n{/form-only}\n";
|
|
let result = std::panic::catch_unwind(|| split(input));
|
|
assert!(result.is_err(), "split should panic on unknown form name");
|
|
}
|
|
|
|
#[test]
|
|
fn unclosed_form_only_is_an_error() {
|
|
let input = "{form-only: json}\nopen\n";
|
|
let result = std::panic::catch_unwind(|| split(input));
|
|
assert!(result.is_err(), "split should panic on unclosed form-only block");
|
|
}
|