Lands the renderer-against-stub slice of Agent I's visible engraving work (spec/PHASE2_QUICKSTART.md). Two new crates; prerequisites (G Pass 11, H spelling/decomposition) are in place. Real engraving + Minimal-tier solver follow next phase. epiphany-render-svg (the deliverable this phase): - Renders a ResolvedLayoutIR to well-formed SVG 1.1, drawing each glyph as a GENUINE Bravura SMuFL outline <path>. Outlines are extracted reproducibly from the official OFL Bravura.otf by a committed generator (tools/extract_bravura_outlines.py, OFL.txt); the font is not vendored, only the generated Rust (src/outlines_generated.rs). Staff-space/y-up coords with one global y-flip wrapper; viewBox in staff spaces, px scale on the root. - Non-overreach: every element traces to a ResolvedGlyph (data-prov) or a declared wrapper; a glyph lacking an outline is surfaced as a diagnostic and drawn as a fallback rect, never silently dropped. - Hand-rolled xml::check_well_formed (no XML dep); acceptance tests cross-check with system xmllint when present. - examples/render_fixture.rs demo (fixture name -> SVG stdout, --solver=stub|real). - Golden-locked machine acceptance snapshot + full-SVG golden for ten_measure_single_staff and valid_score_rich; deterministic output. epiphany-engrave (honest scaffold): - Engraver: a deterministic horizontal-spacing pass (first axis of the planned two-pass spring layout). Reports SolverTier::Stub — NOT Minimal — until it evaluates the declared hard constraints, guarded by a regression test. The demo's --solver=real exercises it end to end. Honesty notes (recorded as Pass-12 candidates P12-I1..I3 in spec/PASS12_BATCH.md and the crates' DECISIONS.md): the v0 to_logical/to_constrained pipeline is a structural placeholder (arbitrary glyph per object, y=0), so stub output is not yet recognizable notation and the QUICKSTART human visual gate is a next-phase gate; MUSCLOID layout-id derivation stays unwired; bundled BRAVURA_METRICS are approximations that disagree with the real outlines. Gates: cargo fmt + clippy -D warnings clean; cargo test --workspace 504 passed, 0 failed, 0 ignored (criterion 6 layout round-trip still green). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| DECISIONS.md | ||
| README.md | ||
README.md
epiphany-engrave
Agent I's engraving constraint solver (spec Chapter 9): turns a
ConstrainedLayoutIR into a ResolvedLayoutIR with real geometry. It is the
production-side replacement for epiphany-layout-ir's interface-only
StubSolver; the two live in separate crates so the spec's core/product boundary
stays sharp.
Status: honest scaffold (renderer-against-stub phase)
Per the QUICKSTART development pattern, Agent I builds the SVG renderer
(epiphany-render-svg) against the stub solver
first, then grows this crate into the real two-pass spring solver. This commit is
the first increment:
Engraverruns a deterministic horizontal spacing pass (the first axis of the planned two-pass spring layout): each spring slot is placed left-to-right by its preferred width instead of being echoed verbatim.- It honestly reports
SolverTier::Stub— it does not yet evaluate the IR's declared hard constraints or compute quality metrics, so it has not earnedMinimal. It is promoted toMinimalin the change that lands real constraint satisfaction.
The vertical spring pass, soft-constraint solve, hard-constraint evaluation, and
the quality-metric vector are the next-phase / Phase-3 work. See DECISIONS.md.
use epiphany_engrave::Engraver;
use epiphany_layout_ir::{ConstraintSolver, SolverConfig};
let report = Engraver.solve(&constrained_ir, &SolverConfig::default());
assert!(report.satisfied_hard_constraints); // for constraint-free stub-pipeline input
let resolved = report.layout; // hand to epiphany-render-svg