First remote CI run went red twice, neither from the change that triggered it. The declared MSRV was false. Cargo.toml claimed 1.77 and all ten crates inherited it, but the committed lockfile carries blake3 1.8.5, which ships edition 2024 and cannot be parsed by any Cargo before 1.85. The job died in fifteen seconds, before compiling a line. The claim had simply never been tested -- there was no remote to test it. Raised to 1.85, which is measured rather than picked: over the Linux-target dependency closure minus the GUI crate, the highest declared rust-version is constant_time_eq at 1.85.0, pulled in by blake3 itself. The comment on the field says so, and says not to raise it again to make a build pass. Raising it woke six clippy lints that MSRV-gating had suppressed: map_or(true, f) is is_none_or(f) as of 1.82. Rewritten. Five of the six sites are covered -- verified by flipping each to is_some_and and confirming a named test dies. The sixth, invariants.rs:1335, survives the flip: nothing constructs a Constant tempo segment with end_tempo None, so that branch has no test that can see it. The rewrite is safe by the standard library's own equivalence, but the gap is real and is not created by this commit. The blocking jobs no longer float on stable. CI ran 1.97.1; this machine has 1.95.0 with no rustup, so the second failure -- float_literal_f32_fallback on a 2.0 literal in the GUI crate -- was invisible and unreproducible here. With -D warnings and a floating toolchain, a Rust release turns the gate red with no repo change, and a gate that fails for reasons the developer cannot reproduce stops being a gate. All four blocking jobs now pin PINNED_STABLE; the nightly soak keeps floating, so drift surfaces on a schedule instead of in an unrelated push. The GUI literal is suffixed anyway, so the eventual deliberate bump is clean. 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: Minimal tier, with casting-off
Engraverruns a deterministic horizontal spacing pass (the first axis of the two-pass spring layout): each spring slot is placed left-to-right by a collision-aware advance derived from real glyph bearings.- A casting-off pass (Phase 3's layout track) then breaks the spaced line
into systems at measure boundaries (greedy first-fit against a
PageGeometry— default A4 portrait at an 8 mm staff), stacks systems vertically at the vertical-band model's inter-system gap, assigns pages by content height, and populates the realResolvedPage/ResolvedSystemtree. Every position is baked into a single y-up world frame (pages stacked vertically), so the SVG renderer and hit-testing consume the flat glyph/stroke lists unchanged. - The IR's declared constraints are evaluated — geometric families against
the pre-casting spaced frame, break constraints against the final break
structure (hard breaks are always honoured; a pathological soft break is
skipped and recorded as an
IrOverridedecision). Chosen breaks are recorded asEngravingDecisions withSynthesisKind::EngravedBreaktargets, attributed to the user override that requested them when one did. - It reports
SolverTier::Minimal: hard constraints (break family included) satisfied, no optimality claim — the quality-metric vector stays the honest all-worst placeholder until the Quality Metric Catalog lands.
Deferred: the vertical soft-spring solve, per-system justification/stretch,
optimal break search, widow/orphan control, and casting-off caching. See
DECISIONS.md.
use epiphany_engrave::Engraver;
use epiphany_layout_ir::{ConstraintSolver, SolverConfig};
let report = Engraver::default().solve(&constrained_ir, &SolverConfig::default());
assert!(report.satisfied_hard_constraints);
let resolved = report.layout; // real pages/systems; hand to epiphany-render-svg