T4 round 1: the precommitted fill oracle, and nothing has rendered against it

Pin 13 makes this sequencing a hard rule -- "points that must be ink" chosen
after seeing candidate output is not a test -- so this crate draws nothing and
depends on no rendering, tessellation or windowing crate. It derives the oracle
from the typed glyph outlines and writes it out as data. Candidates render
against it in a later packet.

Twenty-seven sample points across five glyphs, all derived programmatically by
even-odd point-in-path over the flattened PathCommand outline, never chosen by
eye, each at least eight device pixels clear of any outline edge so
antialiasing cannot explain a result. Every background point is proven to lie
inside a BOUNDED HOLE -- enclosed by the outer silhouette yet unfilled -- since
a point merely outside the glyph is passed trivially by a renderer that fills
holes solid. fClef instead carries one ink point inside each of its three
filled subpaths, tagged by subpath index so the oracle proves every component
is covered rather than three points that could all land in the bowl.

The status model distinguishes a satisfied disjoint-component result from a
failed hole result: a requirement enum, per-requirement required/satisfied
pairs, and one authoritative satisfied flag.

Mutations, each with kill evidence in the test module. A perturbed ink point is
rejected outside the glyph. Shrinking the clearance floor admits strictly more
points, so the filter is not a no-op. Every hole point sits inside a naive
outer-contour-only fill but outside the real whole-outline fill -- the positive
proof that inner-subpath handling is load-bearing, which stands in for a
fill-rule flip that CANNOT reclassify anything on correctly wound contours.
And filling only fClef's largest subpath misses both dot points, which is the
disjoint-component analogue and the reason that class exists.

Two proofs about fClef's topology, because one was not enough. Vertex-level
non-nesting cannot see two subpaths whose edges cross with no vertex of either
inside the other, so it is paired with pairwise bounding-box disjointness,
which rules out crossing, touching and containment together. The grid-based
corroboration is named for what it actually checks -- one finer 0.005 grid --
rather than claiming any resolution.

The oracle's adaptive flattening is authoritative for the recorded signed
areas; an earlier coarser fixed-step measurement is marked superseded where it
appears. The first four-glyph pass is kept in DECISIONS.md under an explicit
SUPERSEDED -- NEVER COMMITTED banner, because its two findings are what caused
the contract amendment, and deleting the discovery would erase the reason.

Verified: 12/12 tests; fmt clean; cargo doc clean; regeneration byte-identical
by SHA-256 from the crate directory. All 27 coordinates were additionally
cross-validated by an independent point-in-path implementation with zero
mismatches, and the new bounding-box assertion was mutation-killed against a
nested glyph to prove it is not vacuous.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RSX4zSLgKvtiXaPjnMqLGz
This commit is contained in:
Levi Neuwirth 2026-07-28 21:25:07 -04:00
parent b724e94faf
commit 0a35697d8e
8 changed files with 3040 additions and 0 deletions

View File

@ -549,6 +549,20 @@ version = "2.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da"
[[package]]
name = "blake3"
version = "1.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce"
dependencies = [
"arrayref",
"arrayvec",
"cc",
"cfg-if",
"constant_time_eq",
"cpufeatures",
]
[[package]]
name = "block"
version = "0.1.6"
@ -797,6 +811,12 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "constant_time_eq"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b"
[[package]]
name = "core-foundation"
version = "0.9.4"
@ -891,6 +911,15 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "cpufeatures"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.5.0"
@ -1198,6 +1227,52 @@ version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13ee4e1f553a3584c301f3a56ff1a775f1384781396cea301c8d952e9b93f560"
[[package]]
name = "epiphany-core"
version = "0.0.0"
dependencies = [
"blake3",
"epiphany-determinism",
"getrandom 0.2.17",
"num-bigint",
"num-rational",
"num-traits",
"slotmap",
"unicode-normalization",
]
[[package]]
name = "epiphany-determinism"
version = "0.0.0"
dependencies = [
"blake3",
]
[[package]]
name = "epiphany-glyphs"
version = "0.0.0"
dependencies = [
"epiphany-layout-ir",
]
[[package]]
name = "epiphany-layout-ir"
version = "0.0.0"
dependencies = [
"epiphany-core",
"epiphany-determinism",
"epiphany-ops",
]
[[package]]
name = "epiphany-ops"
version = "0.0.0"
dependencies = [
"epiphany-core",
"epiphany-determinism",
"unicode-normalization",
]
[[package]]
name = "equivalent"
version = "1.0.2"
@ -1528,6 +1603,17 @@ dependencies = [
"windows-link",
]
[[package]]
name = "getrandom"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "getrandom"
version = "0.3.4"
@ -2163,6 +2249,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "jni"
version = "0.22.4"
@ -2608,6 +2700,36 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451"
[[package]]
name = "num-bigint"
version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
@ -3483,6 +3605,16 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
[[package]]
name = "round1-oracle"
version = "0.1.0"
dependencies = [
"epiphany-glyphs",
"epiphany-layout-ir",
"serde",
"serde_json",
]
[[package]]
name = "roxmltree"
version = "0.20.0"
@ -3618,6 +3750,19 @@ dependencies = [
"syn 3.0.3",
]
[[package]]
name = "serde_json"
version = "1.0.151"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14"
dependencies = [
"itoa",
"memchr",
"serde",
"serde_core",
"zmij",
]
[[package]]
name = "serde_repr"
version = "0.1.21"
@ -4176,6 +4321,15 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-normalization"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-script"
version = "0.5.8"
@ -4312,6 +4466,12 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.4+wasi-0.2.12"
@ -5600,6 +5760,12 @@ dependencies = [
"syn 2.0.119",
]
[[package]]
name = "zmij"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
[[package]]
name = "zune-core"
version = "0.5.1"

View File

@ -4,6 +4,7 @@ members = [
"probe-egui",
"probe-vello",
"probe-iced",
"round1-oracle",
]
# a11y-verifier is a standalone Python script (a11y-verifier/verify.py), not

View File

@ -137,3 +137,151 @@ behavior — that is round 1's job):
All three document both rules explicitly. No candidate is eliminated on
this desk-survey item; round 1 is where it is actually tested.
## Round 1 — the precommitted oracle: SUPERSEDED FIRST PASS
> **SUPERSEDED DISCOVERY — NEVER COMMITTED.** This section records the
> four-glyph oracle built against the pre-Revision-6 contract, kept because its
> two findings are what *caused* the amendment. It was never committed and is
> not the oracle any candidate renders against; **the authoritative account is
> the Revision 6 amendment section below** (five glyphs, two check classes,
> explicit status model). In particular, `fClef`'s `background_satisfied =
> false` below is the superseded encoding — under Revision 6 `fClef` is a
> *satisfied* disjoint-component result — and every "committed" in this section
> describes an intent that this pass never reached.
**This is the oracle only — no candidate has rendered against it yet.**
`round1-oracle/` (new spike-workspace member) derives, for `gClef`, `fClef`,
`timeSig8`, `accidentalFlat` from `BravuraGlyphCatalog::render_data`: a
pinned staff-space -> device-pixel transform, Bezier-flattened outlines
(recursive de Casteljau, 0.0005 staff-space flatness tolerance), an even-odd
/ nonzero point-in-path classifier, and a grid search (0.01 staff-space
step) that derives >=3 ink and >=3 bounded-hole background sample points per
glyph, each with >=8 device-px clearance from any outline edge, entirely
programmatically — no coordinate here was chosen by eye. Output:
`round1-oracle/oracle.json` (committed, machine-readable) and
`round1-oracle/ORACLE_SUMMARY.md` (human-readable). **No rendering,
tessellation, or windowing crate is a dependency of this crate** — see its
Cargo.toml and module doc comment.
**Transform (pinned):** `device = (staff.x * scale + tx, ty - staff.y *
scale)`, `scale = 100` device px per staff space, `tx`/`ty` center each
glyph's own flattened bounding box in the pin-4 1920x1080 target — one
uniform rule applied identically to all four glyphs, not a per-glyph fudge.
**Subpath counts.** All four match the contract's recorded starting point
exactly: `gClef` 4, `fClef` 3, `timeSig8` 3, `accidentalFlat` 2 (asserted in
`subpath_counts_match_the_recorded_starting_point`).
**Finding — `fClef` has no bounded hole at all.** Its three subpaths (the
solid clef bowl, area 2.534, plus two disjoint dot subpaths, areas 0.153 and
0.148) are not nested — the search finds **zero** grid hits inside the outer
contour and outside the even-odd fill, at both the main search's resolution
and an independent finer corroboration (0.005 staff-space step, no
clearance floor at all;
`finding_corroboration::fclef_has_no_bounded_hole_at_any_resolution_or_clearance`).
Per Round 1's hole-check clause ("asserted by the derivation, not assumed"), no fallback/relaxed point was substituted:
`fClef`'s oracle carries 3 ink points and **zero** background points, and
`background_satisfied = false` is recorded in `oracle.json` alongside the
diagnostic. The other three glyphs each got 3 ink + 3 background points with
no relaxation needed (thousands of qualifying grid candidates for each).
**Finding — even-odd and nonzero agree on every hole point found.** Mutation
(b) (flip even-odd to nonzero on the selected hole points) was run for
`gClef`, `timeSig8`, `accidentalFlat`'s hole points and **none reclassify**:
Bravura's outer contour and its hole wind in *opposite* directions (the
well-formed-font convention), so nonzero winding cancels to 0 at exactly the
points where the even-odd crossing count is 2 — both rules correctly exclude
the hole. This is real information about the font data (recorded, not
smoothed over), and it means the literal "flip the rule" mutation does not,
for this data, demonstrate that fill-*rule* choice is load-bearing. A
supplementary mutation
(`mutation_b_supplement_hole_points_reclassify_under_naive_outer_only_fill`)
demonstrates the property the check actually needed — that respecting inner
subpaths at all is load-bearing — by showing every selected hole point *is*
inside a naive outer-contour-only fill (what a renderer ignoring holes
entirely would wrongly paint as ink) while being outside the real
whole-outline fill.
Full mutation evidence (a/b/b-supplement/c) is in
`round1-oracle/src/lib.rs`'s `tests` and `finding_corroboration` modules, run
via `cargo test -p round1-oracle -- --nocapture`.
## Round 1 — Revision 6 amendment (five glyphs, two check classes, status model)
**Both findings above changed the contract, not just this oracle.**
`fClef` having no bounded hole and criterion 1's fill-*rule* framing being
moot on Bravura's correctly (oppositely) wound contours were reported as
findings against the pre-Revision-6 contract; the coordinator's response was
to amend `spec/CONTRACT_EDITOR_T4_SPIKE.md` to Revision 6 rather than treat
`fClef` as a shortfall. Round 1 is now **five glyphs in two check classes**,
and this oracle is amended to match (uncommitted diff on top of the original
oracle; the mechanics below are unchanged — same flattening, same
point-in-path classifier, same transform, same clearance floor — only the
requirement model and the glyph set changed):
- **Bounded-hole check** (unchanged mechanics): `gClef`, `timeSig8`,
`accidentalFlat`, and now **`noteheadHalf`** (new: two subpaths, measured
`ring_signed_areas = [0.903, -0.368]` — the authoritative figure, now also
what the contract records; an earlier `[0.902, -0.367]` came from a coarser
fixed-step flattening). Still >=3 ink + >=3 background points per glyph, every
background point inside a bounded hole.
- **Disjoint-component check** (new): `fClef` alone, no longer folded into
the bounded-hole class it never actually belonged to. It carries **no
background requirement** — that is its design (bowl plus two solid,
disjoint dots) — and instead requires >=1 ink point inside **each** of its
three filled subpaths, each point tagged with `subpath_index` so the
oracle proves coverage of every component rather than three ink points
that could all land in the bowl. Verified two ways: a finer (0.005
staff-space step) grid corroboration (renamed
`fclef_has_zero_bounded_hole_grid_hits_at_a_finer_0_005_grid`, since the
old name overclaimed "any resolution" for what was actually one grid) and
a genuinely resolution-independent topological check,
`subpaths_are_mutually_non_nested` /
`fclef_subpaths_are_topologically_non_nested`, which asserts no subpath's
vertices lie inside another subpath — a property of the flattened polygon
itself, not of any sampling step, and what actually justifies the
stronger claim.
**Status model.** `GlyphOracle` now carries an explicit `Requirement` enum
(`BoundedHole` / `DisjointComponents`), per-requirement booleans
(`background_required`/`background_satisfied`,
`subpath_coverage_required`/`subpath_coverage_satisfied`), and one overall
`satisfied: bool` — the field to read. `fClef` is `satisfied = true` with
`background_required = false` and zero background points; a bounded-hole
glyph that failed to find enough background points would be
`satisfied = false`. The two are no longer distinguishable only by an absent
field, which was the defect the amendment closes.
**Fill-rule equivalence, now asserted, not merely reported.** The original
oracle's `mutation_b_...` test printed `reclassifies_under_nonzero=false` for
every hole point without asserting on it. `derive_bounded_hole_oracle` now
asserts `!ev.nonzero_filled` for every selected background point at
derivation time (fails loudly if the opposite-winding assumption is ever
false for a glyph's real data), and
`mutation_b_nonzero_rule_equivalence_on_hole_points_is_asserted` asserts the
same independently at the test level. `ring_signed_areas` — the measured
signed area of every subpath, in ring order — is now recorded on every
glyph's oracle output (`oracle.json` and `ORACLE_SUMMARY.md`), not just
observed in this log: `gClef [8.702, -0.691, -1.803, -0.509]`, `timeSig8
[2.674, -0.435, -0.515]`, `accidentalFlat [1.040, -0.257]`, `noteheadHalf
[0.903, -0.368]`, `fClef [2.534, 0.153, 0.148]` — all within measurement
tolerance of the contract's recorded values.
**New kill test.** `mutation_d_largest_contour_only_fill_misses_the_dot_points`
is the disjoint-component analogue of the outer-contour-only mutation kept
from the original oracle: it asserts that filling only `fClef`'s largest
subpath (the bowl) fails to contain either dot's ink point — the literal
"tessellator keeps only the largest contour" scenario Round 1 names as the
reason this check exists. The original outer-contour-only mutation
(`mutation_b_supplement_...`) is unchanged and still runs, now over all four
bounded-hole glyphs including `noteheadHalf`.
**Citations.** Every `pin 13 item N` citation in `round1-oracle/src/lib.rs`,
`src/main.rs`, `ORACLE_SUMMARY.md`, and this file has been replaced with a
direct citation to the Round 1 clause's own wording — pin 13 has no numbered
items in Revision 6 (or any prior revision), so those citations pointed at
nothing.
`oracle.json` and `ORACLE_SUMMARY.md` are regenerated from the amended code
(`cargo run -p round1-oracle` from `spikes/editor-toolkit/round1-oracle/`).

View File

@ -0,0 +1,26 @@
[package]
name = "round1-oracle"
version = "0.1.0"
edition.workspace = true
publish.workspace = true
# CONTRACT_EDITOR_T4_SPIKE.md, Round 1 (criterion 1, fill correctness).
# Builds the precommitted oracle ONLY: sample points, their expected
# ink/background class, and the render transform they are pinned against.
#
# This crate draws NOTHING. It depends on no rendering, tessellation, or
# windowing crate of any kind (no egui, no lyon, no vello, no wgpu, no
# winit). Round 1's own wording requires the oracle file, the render transform,
# and the expected class per point to be "committed before any candidate
# renders", so candidate runs happen in a later packet, only after the user
# has reviewed and committed this. This crate's only job is deriving the oracle programmatically
# from the typed glyph outlines and writing it out as data.
#
# The two epiphany dependencies below are the only epiphany dependencies, by
# path, exactly as the packet's brief requires.
[dependencies]
epiphany-glyphs = { path = "../../../crates/epiphany-glyphs" }
epiphany-layout-ir = { path = "../../../crates/epiphany-layout-ir" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View File

@ -0,0 +1,147 @@
# Round 1 precommitted oracle — compound-path fill correctness
Generated by `round1-oracle` (`spikes/editor-toolkit/round1-oracle`). Governed by `spec/CONTRACT_EDITOR_T4_SPIKE.md` Revision 6, Round 1 ("criterion 1, compound-path fill correctness"). No rendering crate was used to produce this file — every point below is derived from the typed `PathCommand` outline alone.
Two check classes, testing two different properties: **bounded-hole** (`gClef`, `timeSig8`, `accidentalFlat`, `noteheadHalf`) requires ≥3 ink and ≥3 must-be-background points inside a bounded hole; **disjoint-component** (`fClef`) has no bounded hole by design and instead requires ≥1 ink point inside each of its three filled subpaths, tagged with `subpath_index`.
## Render transform (pinned)
`device = (staff.x * scale + tx, ty - staff.y * scale); scale = 100 device px per staff space; tx/ty center the glyph's own flattened bounding box in a 1920x1080 target (pin 4); staff-space is y-up, device space is y-down`
- Flatten tolerance: `0.0005` staff-space units (Bezier chord deviation).
- Clearance floor: `8` device px.
## Overall status
| glyph | requirement | satisfied | ring_signed_areas |
|---|---|---|---|
| `gClef` | BoundedHole | **true** | [8.702, -0.691, -1.803, -0.509] |
| `timeSig8` | BoundedHole | **true** | [2.674, -0.435, -0.515] |
| `accidentalFlat` | BoundedHole | **true** | [1.040, -0.257] |
| `noteheadHalf` | BoundedHole | **true** | [0.903, -0.368] |
| `fClef` | DisjointComponents | **true** | [2.534, 0.153, 0.148] |
`fClef` is `satisfied = true` with zero background points — that is the correct, designed-for outcome for its `DisjointComponents` requirement class, not a shortfall. The `satisfied` column above is the field to read; `background_satisfied` alone would make that correct outcome indistinguishable from a bounded-hole glyph's genuine failure.
## `gClef`
- Requirement class: BoundedHole (≥3 ink, ≥3 background inside a bounded hole)
- Overall status: **satisfied = true**
- Subpaths: 4 (matches recorded 4)
- Ring signed areas (staff-space², shoelace, ring order): `[8.702, -0.691, -1.803, -0.509]`
- Bounding box (staff space): `[0.0, -2.631999969482422, 2.684000015258789, 4.392000198364258]`
- Outer contour ring index: 0
- Transform: scale=100, tx=825.800, ty=628.000, target=1920x1080
- background_required=true, background_satisfied=true
- subpath_coverage_required=false, subpath_coverage_satisfied=true
- Ink candidates found (>= 8px clearance): 27069
- Background/hole candidates found (>= 8px clearance): 18066
- Ink point spacing relaxed: false
- Background point spacing relaxed: false
| class | subpath_index | staff (x, y) | device (x, y) | clearance (device px) | hole evidence |
|---|---|---|---|---|---|
| Ink | - | (0.9400, -1.9220) | (919.80, 820.20) | 39.879 | - |
| Ink | - | (0.8500, -2.0520) | (910.80, 833.20) | 31.153 | - |
| Ink | - | (1.2700, 1.8880) | (952.80, 439.20) | 29.458 | - |
| Background | - | (1.7600, 3.2580) | (1001.80, 302.20) | 32.236 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (1.7000, 3.1180) | (995.80, 316.20) | 31.015 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (1.8200, 3.4080) | (1007.80, 287.20) | 29.839 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
## `timeSig8`
- Requirement class: BoundedHole (≥3 ink, ≥3 background inside a bounded hole)
- Overall status: **satisfied = true**
- Subpaths: 3 (matches recorded 3)
- Ring signed areas (staff-space², shoelace, ring order): `[2.674, -0.435, -0.515]`
- Bounding box (staff space): `[0.07999999821186066, -1.0360000133514404, 1.6640000343322754, 1.0360000133514404]`
- Outer contour ring index: 0
- Transform: scale=100, tx=872.800, ty=540.000, target=1920x1080
- background_required=true, background_satisfied=true
- subpath_coverage_required=false, subpath_coverage_satisfied=true
- Ink candidates found (>= 8px clearance): 8030
- Background/hole candidates found (>= 8px clearance): 5882
- Ink point spacing relaxed: false
- Background point spacing relaxed: false
| class | subpath_index | staff (x, y) | device (x, y) | clearance (device px) | hole evidence |
|---|---|---|---|---|---|
| Ink | - | (1.3300, -0.1960) | (1005.80, 559.60) | 28.647 | - |
| Ink | - | (1.1200, -0.0460) | (984.80, 544.60) | 28.211 | - |
| Ink | - | (0.9600, 0.0140) | (968.80, 538.60) | 26.413 | - |
| Background | - | (0.6900, -0.5360) | (941.80, 593.60) | 34.514 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (0.8400, -0.5860) | (956.80, 598.60) | 31.745 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (1.0000, 0.5940) | (972.80, 480.60) | 29.916 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
## `accidentalFlat`
- Requirement class: BoundedHole (≥3 ink, ≥3 background inside a bounded hole)
- Overall status: **satisfied = true**
- Subpaths: 2 (matches recorded 2)
- Ring signed areas (staff-space², shoelace, ring order): `[1.040, -0.257]`
- Bounding box (staff space): `[0.0, -0.699999988079071, 0.9039999842643738, 1.75600004196167]`
- Outer contour ring index: 0
- Transform: scale=100, tx=914.800, ty=592.800, target=1920x1080
- background_required=true, background_satisfied=true
- subpath_coverage_required=false, subpath_coverage_satisfied=true
- Ink candidates found (>= 8px clearance): 1381
- Background/hole candidates found (>= 8px clearance): 1175
- Ink point spacing relaxed: false
- Background point spacing relaxed: false
| class | subpath_index | staff (x, y) | device (x, y) | clearance (device px) | hole evidence |
|---|---|---|---|---|---|
| Ink | - | (0.7500, 0.3100) | (989.80, 561.80) | 14.124 | - |
| Ink | - | (0.7600, 0.1500) | (990.80, 577.80) | 13.243 | - |
| Ink | - | (0.1500, 0.3800) | (929.80, 554.80) | 12.985 | - |
| Background | - | (0.4000, 0.1200) | (954.80, 580.80) | 22.160 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (0.3700, -0.0300) | (951.80, 595.80) | 18.269 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (0.4600, 0.2600) | (960.80, 566.80) | 13.874 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
## `noteheadHalf`
- Requirement class: BoundedHole (≥3 ink, ≥3 background inside a bounded hole)
- Overall status: **satisfied = true**
- Subpaths: 2 (matches recorded 2)
- Ring signed areas (staff-space², shoelace, ring order): `[0.903, -0.368]`
- Bounding box (staff space): `[0.0, -0.5, 1.1799999475479126, 0.5]`
- Outer contour ring index: 0
- Transform: scale=100, tx=901.000, ty=540.000, target=1920x1080
- background_required=true, background_satisfied=true
- subpath_coverage_required=false, subpath_coverage_satisfied=true
- Ink candidates found (>= 8px clearance): 949
- Background/hole candidates found (>= 8px clearance): 1919
- Ink point spacing relaxed: false
- Background point spacing relaxed: false
| class | subpath_index | staff (x, y) | device (x, y) | clearance (device px) | hole evidence |
|---|---|---|---|---|---|
| Ink | - | (0.4000, 0.2800) | (941.00, 512.00) | 12.348 | - |
| Ink | - | (0.7600, -0.2900) | (977.00, 569.00) | 12.308 | - |
| Ink | - | (0.8900, -0.2000) | (990.00, 560.00) | 11.678 | - |
| Background | - | (0.5900, 0.0000) | (960.00, 540.00) | 21.286 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (0.4600, -0.0800) | (947.00, 548.00) | 20.683 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
| Background | - | (0.7200, 0.0800) | (973.00, 532.00) | 20.108 | inside_outer_contour=true, even_odd_filled=false, nonzero_filled=false (outer ring 0) |
## `fClef`
- Requirement class: DisjointComponents (no background requirement; ≥1 ink point per filled subpath)
- Overall status: **satisfied = true**
- Subpaths: 3 (matches recorded 3)
- Ring signed areas (staff-space², shoelace, ring order): `[2.534, 0.153, 0.148]`
- Bounding box (staff space): `[-0.019999999552965164, -2.5399999618530273, 2.7360000610351563, 1.0479999780654907]`
- Outer contour ring index: 0
- Transform: scale=100, tx=824.200, ty=465.400, target=1920x1080
- background_required=false, background_satisfied=true
- subpath_coverage_required=true, subpath_coverage_satisfied=true
- Ink candidates found (>= 8px clearance): 3
- Background/hole candidates found (>= 8px clearance): 0
- Ink point spacing relaxed: false
- Background point spacing relaxed: false
| class | subpath_index | staff (x, y) | device (x, y) | clearance (device px) | hole evidence |
|---|---|---|---|---|---|
| Ink | 0 | (0.5000, -0.0200) | (874.20, 467.40) | 41.560 | - |
| Ink | 1 | (2.5160, 0.5000) | (1075.80, 415.40) | 21.974 | - |
| Ink | 2 | (2.5240, -0.4960) | (1076.60, 515.00) | 21.149 | - |

View File

@ -0,0 +1,651 @@
{
"contract": "spec/CONTRACT_EDITOR_T4_SPIKE.md Round 1 (criterion 1, compound-path fill correctness)",
"round": "round1",
"render_transform_rule": "device = (staff.x * scale + tx, ty - staff.y * scale); scale = 100 device px per staff space; tx/ty center the glyph's own flattened bounding box in a 1920x1080 target (pin 4); staff-space is y-up, device space is y-down",
"flatten_tolerance_staff_space": 0.0005,
"clearance_floor_device_px": 8.0,
"glyphs": [
{
"name": "gClef",
"requirement": "BoundedHole",
"subpath_count": 4,
"expected_subpath_count": 4,
"transform": {
"scale": 100.0,
"tx": 825.7999992370605,
"ty": 628.0000114440918,
"target_width": 1920.0,
"target_height": 1080.0
},
"bbox_staff": [
0.0,
-2.631999969482422,
2.684000015258789,
4.392000198364258
],
"outer_contour_ring_index": 0,
"ring_signed_areas": [
8.70199089321805,
-0.6913140433690712,
-1.8034304355375201,
-0.5093689639942818
],
"points": [
{
"staff": [
0.9400000000000006,
-1.9219999694824352
],
"device": [
919.7999992370605,
820.2000083923353
],
"class": "Ink",
"clearance_device_px": 39.879224940156384,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.8500000000000005,
-2.0519999694824342
],
"device": [
910.7999992370605,
833.2000083923352
],
"class": "Ink",
"clearance_device_px": 31.152574135700984,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
1.270000000000001,
1.8880000305175677
],
"device": [
952.7999992370607,
439.200008392335
],
"class": "Ink",
"clearance_device_px": 29.458331559341232,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
1.7600000000000013,
3.258000030517541
],
"device": [
1001.7999992370607,
302.2000083923377
],
"class": "Background",
"clearance_device_px": 32.23617311771167,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
1.7000000000000013,
3.118000030517544
],
"device": [
995.7999992370607,
316.2000083923374
],
"class": "Background",
"clearance_device_px": 31.015291567040098,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
1.8200000000000014,
3.4080000305175377
],
"device": [
1007.7999992370607,
287.200008392338
],
"class": "Background",
"clearance_device_px": 29.838877367007576,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
}
],
"ink_candidates_found": 27069,
"background_candidates_found": 18066,
"ink_spacing_relaxed": false,
"background_spacing_relaxed": false,
"ink_satisfied": true,
"background_required": true,
"background_satisfied": true,
"subpath_coverage_required": false,
"subpath_coverage_satisfied": true,
"satisfied": true,
"hole_diagnostic": {
"raw_hole_grid_hits": 30028,
"best_hole_clearance_device_px": 32.23617311771167
}
},
{
"name": "timeSig8",
"requirement": "BoundedHole",
"subpath_count": 3,
"expected_subpath_count": 3,
"transform": {
"scale": 100.0,
"tx": 872.7999983727932,
"ty": 540.0,
"target_width": 1920.0,
"target_height": 1080.0
},
"bbox_staff": [
0.07999999821186066,
-1.0360000133514404,
1.6640000343322754,
1.0360000133514404
],
"outer_contour_ring_index": 0,
"ring_signed_areas": [
2.6743829783025608,
-0.43524448349075884,
-0.5148498430682749
],
"points": [
{
"staff": [
1.3299999982118615,
-0.19600001335143968
],
"device": [
1005.7999981939794,
559.6000013351439
],
"class": "Ink",
"clearance_device_px": 28.64675883470137,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
1.1199999982118614,
-0.04600001335143965
],
"device": [
984.7999981939794,
544.6000013351439
],
"class": "Ink",
"clearance_device_px": 28.21134677772842,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.9599999982118613,
0.013999986648560359
],
"device": [
968.7999981939794,
538.6000013351439
],
"class": "Ink",
"clearance_device_px": 26.412730159918755,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.6899999982118611,
-0.53600001335144
],
"device": [
941.7999981939793,
593.600001335144
],
"class": "Background",
"clearance_device_px": 34.51401272338884,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
0.8399999982118612,
-0.58600001335144
],
"device": [
956.7999981939793,
598.600001335144
],
"class": "Background",
"clearance_device_px": 31.74536201663279,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
0.9999999982118614,
0.5939999866485607
],
"device": [
972.7999981939794,
480.60000133514393
],
"class": "Background",
"clearance_device_px": 29.916370370369677,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
}
],
"ink_candidates_found": 8030,
"background_candidates_found": 5882,
"ink_spacing_relaxed": false,
"background_spacing_relaxed": false,
"ink_satisfied": true,
"background_required": true,
"background_satisfied": true,
"subpath_coverage_required": false,
"subpath_coverage_satisfied": true,
"satisfied": true,
"hole_diagnostic": {
"raw_hole_grid_hits": 9504,
"best_hole_clearance_device_px": 34.51401272338884
}
},
{
"name": "accidentalFlat",
"requirement": "BoundedHole",
"subpath_count": 2,
"expected_subpath_count": 2,
"transform": {
"scale": 100.0,
"tx": 914.8000007867813,
"ty": 592.80000269413,
"target_width": 1920.0,
"target_height": 1080.0
},
"bbox_staff": [
0.0,
-0.699999988079071,
0.9039999842643738,
1.75600004196167
],
"outer_contour_ring_index": 0,
"ring_signed_areas": [
1.0400791647491505,
-0.2566232782507076
],
"points": [
{
"staff": [
0.7500000000000004,
0.3100000119209296
],
"device": [
989.8000007867813,
561.8000015020369
],
"class": "Ink",
"clearance_device_px": 14.123904362928288,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.7600000000000005,
0.15000001192092943
],
"device": [
990.8000007867813,
577.800001502037
],
"class": "Ink",
"clearance_device_px": 13.242801200968785,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.15,
0.38000001192092964
],
"device": [
929.8000007867813,
554.8000015020369
],
"class": "Ink",
"clearance_device_px": 12.984644164814336,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.4000000000000002,
0.12000001192092942
],
"device": [
954.8000007867813,
580.800001502037
],
"class": "Background",
"clearance_device_px": 22.16023587801027,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
0.37000000000000016,
-0.02999998807907056
],
"device": [
951.8000007867813,
595.800001502037
],
"class": "Background",
"clearance_device_px": 18.26919422193897,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
0.46000000000000024,
0.26000001192092953
],
"device": [
960.8000007867813,
566.800001502037
],
"class": "Background",
"clearance_device_px": 13.87396974116893,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
}
],
"ink_candidates_found": 1381,
"background_candidates_found": 1175,
"ink_spacing_relaxed": false,
"background_spacing_relaxed": false,
"ink_satisfied": true,
"background_required": true,
"background_satisfied": true,
"subpath_coverage_required": false,
"subpath_coverage_satisfied": true,
"satisfied": true,
"hole_diagnostic": {
"raw_hole_grid_hits": 2571,
"best_hole_clearance_device_px": 22.16023587801027
}
},
{
"name": "noteheadHalf",
"requirement": "BoundedHole",
"subpath_count": 2,
"expected_subpath_count": 2,
"transform": {
"scale": 100.0,
"tx": 901.0000026226044,
"ty": 540.0,
"target_width": 1920.0,
"target_height": 1080.0
},
"bbox_staff": [
0.0,
-0.5,
1.1799999475479126,
0.5
],
"outer_contour_ring_index": 0,
"ring_signed_areas": [
0.9031883633805334,
-0.36761223428111944
],
"points": [
{
"staff": [
0.4000000000000002,
0.2800000000000004
],
"device": [
941.0000026226044,
511.99999999999994
],
"class": "Ink",
"clearance_device_px": 12.347781160235112,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.7600000000000005,
-0.2899999999999998
],
"device": [
977.0000026226044,
569.0
],
"class": "Ink",
"clearance_device_px": 12.307512116945116,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.8900000000000006,
-0.19999999999999973
],
"device": [
990.0000026226044,
560.0
],
"class": "Ink",
"clearance_device_px": 11.678047475017337,
"hole_evidence": null,
"subpath_index": null
},
{
"staff": [
0.5900000000000003,
3.0878077872387166e-16
],
"device": [
960.0000026226044,
540.0
],
"class": "Background",
"clearance_device_px": 21.285841339339235,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
0.46000000000000024,
-0.0799999999999997
],
"device": [
947.0000026226044,
548.0
],
"class": "Background",
"clearance_device_px": 20.68272256548643,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
},
{
"staff": [
0.7200000000000004,
0.08000000000000031
],
"device": [
973.0000026226044,
532.0
],
"class": "Background",
"clearance_device_px": 20.1077663347467,
"hole_evidence": {
"inside_outer_contour": true,
"even_odd_filled": false,
"nonzero_filled": false,
"outer_contour_ring_index": 0
},
"subpath_index": null
}
],
"ink_candidates_found": 949,
"background_candidates_found": 1919,
"ink_spacing_relaxed": false,
"background_spacing_relaxed": false,
"ink_satisfied": true,
"background_required": true,
"background_satisfied": true,
"subpath_coverage_required": false,
"subpath_coverage_satisfied": true,
"satisfied": true,
"hole_diagnostic": {
"raw_hole_grid_hits": 3681,
"best_hole_clearance_device_px": 21.285841339339235
}
},
{
"name": "fClef",
"requirement": "DisjointComponents",
"subpath_count": 3,
"expected_subpath_count": 3,
"transform": {
"scale": 100.0,
"tx": 824.1999969258904,
"ty": 465.40000081062317,
"target_width": 1920.0,
"target_height": 1080.0
},
"bbox_staff": [
-0.019999999552965164,
-2.5399999618530273,
2.7360000610351562,
1.0479999780654907
],
"outer_contour_ring_index": 0,
"ring_signed_areas": [
2.5338203400622494,
0.15280048146661862,
0.1481298437718624
],
"points": [
{
"staff": [
0.5000000004470351,
-0.019999961853036992
],
"device": [
874.1999969705939,
467.39999699592687
],
"class": "Ink",
"clearance_device_px": 41.559502835282714,
"hole_evidence": null,
"subpath_index": 0
},
{
"staff": [
2.5160000038146926,
0.5000000011920931
],
"device": [
1075.7999973073597,
415.4000006914139
],
"class": "Ink",
"clearance_device_px": 21.97428696274997,
"hole_evidence": null,
"subpath_index": 1
},
{
"staff": [
2.5239999008178664,
-0.4960000205039976
],
"device": [
1076.599987007677,
515.000002861023
],
"class": "Ink",
"clearance_device_px": 21.14908118002104,
"hole_evidence": null,
"subpath_index": 2
}
],
"ink_candidates_found": 3,
"background_candidates_found": 0,
"ink_spacing_relaxed": false,
"background_spacing_relaxed": false,
"ink_satisfied": true,
"background_required": false,
"background_satisfied": true,
"subpath_coverage_required": true,
"subpath_coverage_satisfied": true,
"satisfied": true,
"hole_diagnostic": {
"raw_hole_grid_hits": 0,
"best_hole_clearance_device_px": null
}
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,314 @@
//! Generates the committed Round-1 oracle: `oracle.json` (machine-readable,
//! consumed by candidate runs in a later packet) and `ORACLE_SUMMARY.md`
//! (human-readable, for the user's pin-13 review). Run with `cargo run -p
//! round1-oracle` from `spikes/editor-toolkit/round1-oracle/`.
use epiphany_glyphs::BravuraGlyphCatalog;
use epiphany_layout_ir::GlyphCatalog;
use round1_oracle::{derive_glyph_oracle, GlyphOracle, Requirement, SampleClass};
use serde::Serialize;
use std::fmt::Write as _;
use std::fs;
/// Round 1's bounded-hole check class: "≥3 must-be-ink and ≥3 must-be-
/// background points, each inside a bounded hole".
const HOLE_GLYPHS: &[(&str, usize)] = &[
("gClef", 4),
("timeSig8", 3),
("accidentalFlat", 2),
("noteheadHalf", 2),
];
/// Round 1's disjoint-component check class: "no bounded hole ... ≥1 ink
/// point inside each of its three filled subpaths".
const DISJOINT_GLYPHS: &[(&str, usize)] = &[("fClef", 3)];
#[derive(Serialize)]
struct OracleFile {
contract: &'static str,
round: &'static str,
render_transform_rule: &'static str,
flatten_tolerance_staff_space: f64,
clearance_floor_device_px: f64,
glyphs: Vec<GlyphOracle>,
}
fn main() {
let catalog = BravuraGlyphCatalog;
let mut glyphs = Vec::new();
let mut findings = Vec::new();
for (name, expected_subpaths) in HOLE_GLYPHS {
let data = catalog
.render_data(name)
.unwrap_or_else(|| panic!("{name}: BravuraGlyphCatalog has no render data"));
match derive_glyph_oracle(
name,
&data.outline,
Some(*expected_subpaths),
Requirement::BoundedHole,
) {
Ok(oracle) => {
if oracle.subpath_count != *expected_subpaths {
findings.push(format!(
"{name}: parsed {} subpaths, contract's verified-starting-point section \
records {}",
oracle.subpath_count, expected_subpaths
));
}
if !oracle.satisfied {
let d = &oracle.hole_diagnostic;
let detail = if d.raw_hole_grid_hits == 0 {
"this glyph has NO bounded hole at all under even-odd fill — every \
subpath is either the outer silhouette or a disjoint ink island, none \
nested inside another"
.to_string()
} else {
format!(
"this glyph has a bounded hole ({} grid hits) but the best \
achievable clearance in it is {:.3} device px, below the \
{}px floor",
d.raw_hole_grid_hits,
d.best_hole_clearance_device_px.unwrap_or(f64::NAN),
round1_oracle::CLEARANCE_MIN_DEVICE_PX
)
};
findings.push(format!(
"{name}: fewer than {} must-be-background sample points could be \
derived {detail}. Per Round 1's hole-check clause ('each inside a \
bounded hole ... asserted by the derivation, not assumed'), no fallback \
point was substituted; {name}'s oracle carries ink points only and is \
NOT satisfied.",
round1_oracle::POINTS_PER_CLASS
));
}
glyphs.push(oracle);
}
Err(e) => findings.push(e),
}
}
for (name, expected_subpaths) in DISJOINT_GLYPHS {
let data = catalog
.render_data(name)
.unwrap_or_else(|| panic!("{name}: BravuraGlyphCatalog has no render data"));
match derive_glyph_oracle(
name,
&data.outline,
Some(*expected_subpaths),
Requirement::DisjointComponents,
) {
Ok(oracle) => {
if oracle.subpath_count != *expected_subpaths {
findings.push(format!(
"{name}: parsed {} subpaths, contract's verified-starting-point section \
records {}",
oracle.subpath_count, expected_subpaths
));
}
// `oracle.satisfied` is expected true here (no bounded-hole
// shortfall is possible for this class — see
// `derive_glyph_oracle`'s DisjointComponents arm, which only
// returns Ok once every subpath is covered), but this is
// reported as a finding rather than assumed, matching every
// other status check in this file.
if !oracle.satisfied {
findings.push(format!(
"{name}: disjoint-component coverage requirement not met — see \
subpath_coverage_satisfied in oracle.json"
));
}
glyphs.push(oracle);
}
Err(e) => findings.push(e),
}
}
let oracle_file = OracleFile {
contract: "spec/CONTRACT_EDITOR_T4_SPIKE.md Round 1 (criterion 1, compound-path fill \
correctness)",
round: "round1",
render_transform_rule: "device = (staff.x * scale + tx, ty - staff.y * scale); scale = \
100 device px per staff space; tx/ty center the glyph's own flattened bounding box \
in a 1920x1080 target (pin 4); staff-space is y-up, device space is y-down",
flatten_tolerance_staff_space: round1_oracle::FLATTEN_TOLERANCE,
clearance_floor_device_px: round1_oracle::CLEARANCE_MIN_DEVICE_PX,
glyphs,
};
let json = serde_json::to_string_pretty(&oracle_file).expect("oracle serializes");
fs::write("oracle.json", &json).expect("write oracle.json");
let summary = render_summary(&oracle_file, &findings);
fs::write("ORACLE_SUMMARY.md", &summary).expect("write ORACLE_SUMMARY.md");
println!("wrote oracle.json ({} bytes)", json.len());
println!("wrote ORACLE_SUMMARY.md");
if !findings.is_empty() {
println!("\nFINDINGS:");
for f in &findings {
println!(" - {f}");
}
}
}
fn render_summary(oracle: &OracleFile, findings: &[String]) -> String {
let mut s = String::new();
writeln!(
s,
"# Round 1 precommitted oracle — compound-path fill correctness\n"
)
.unwrap();
writeln!(
s,
"Generated by `round1-oracle` (`spikes/editor-toolkit/round1-oracle`). Governed by \
`spec/CONTRACT_EDITOR_T4_SPIKE.md` Revision 6, Round 1 (\"criterion 1, compound-path \
fill correctness\"). No rendering crate was used to produce this file — every point \
below is derived from the typed `PathCommand` outline alone.\n\n\
Two check classes, testing two different properties: **bounded-hole** (`gClef`, \
`timeSig8`, `accidentalFlat`, `noteheadHalf`) requires 3 ink and 3 must-be-background \
points inside a bounded hole; **disjoint-component** (`fClef`) has no bounded hole by \
design and instead requires 1 ink point inside each of its three filled subpaths, \
tagged with `subpath_index`.\n"
)
.unwrap();
writeln!(s, "## Render transform (pinned)\n").unwrap();
writeln!(
s,
"`{}`\n\n- Flatten tolerance: `{}` staff-space units (Bezier chord deviation).\n\
- Clearance floor: `{}` device px.\n",
oracle.render_transform_rule,
oracle.flatten_tolerance_staff_space,
oracle.clearance_floor_device_px
)
.unwrap();
writeln!(s, "## Overall status\n").unwrap();
writeln!(s, "| glyph | requirement | satisfied | ring_signed_areas |").unwrap();
writeln!(s, "|---|---|---|---|").unwrap();
for g in &oracle.glyphs {
let requirement = match g.requirement {
Requirement::BoundedHole => "BoundedHole",
Requirement::DisjointComponents => "DisjointComponents",
};
let areas = g
.ring_signed_areas
.iter()
.map(|a| format!("{a:.3}"))
.collect::<Vec<_>>()
.join(", ");
writeln!(
s,
"| `{}` | {} | **{}** | [{}] |",
g.name, requirement, g.satisfied, areas
)
.unwrap();
}
writeln!(
s,
"\n`fClef` is `satisfied = true` with zero background points — that is the correct, \
designed-for outcome for its `DisjointComponents` requirement class, not a shortfall. \
The `satisfied` column above is the field to read; `background_satisfied` alone would \
make that correct outcome indistinguishable from a bounded-hole glyph's genuine failure.\n"
)
.unwrap();
if !findings.is_empty() {
writeln!(s, "## Findings\n").unwrap();
for f in findings {
writeln!(s, "- **{f}**").unwrap();
}
writeln!(s).unwrap();
}
for g in &oracle.glyphs {
writeln!(s, "## `{}`\n", g.name).unwrap();
let requirement = match g.requirement {
Requirement::BoundedHole => "BoundedHole (≥3 ink, ≥3 background inside a bounded hole)",
Requirement::DisjointComponents => {
"DisjointComponents (no background requirement; ≥1 ink point per filled subpath)"
}
};
let subpath_note = match g.expected_subpath_count {
Some(exp) if exp == g.subpath_count => format!("matches recorded {exp}"),
Some(exp) => format!("**MISMATCH** — recorded {exp}, parsed {}", g.subpath_count),
None => "no recorded expectation".to_string(),
};
let areas = g
.ring_signed_areas
.iter()
.map(|a| format!("{a:.3}"))
.collect::<Vec<_>>()
.join(", ");
writeln!(
s,
"- Requirement class: {requirement}\n\
- Overall status: **satisfied = {}**\n\
- Subpaths: {} ({subpath_note})\n\
- Ring signed areas (staff-space², shoelace, ring order): `[{areas}]`\n\
- Bounding box (staff space): `{:?}`\n\
- Outer contour ring index: {}\n\
- Transform: scale={}, tx={:.3}, ty={:.3}, target={}x{}\n\
- background_required={}, background_satisfied={}\n\
- subpath_coverage_required={}, subpath_coverage_satisfied={}\n\
- Ink candidates found (>= {}px clearance): {}\n\
- Background/hole candidates found (>= {}px clearance): {}\n\
- Ink point spacing relaxed: {}\n\
- Background point spacing relaxed: {}\n",
g.satisfied,
g.subpath_count,
g.bbox_staff,
g.outer_contour_ring_index,
g.transform.scale,
g.transform.tx,
g.transform.ty,
g.transform.target_width as i32,
g.transform.target_height as i32,
g.background_required,
g.background_satisfied,
g.subpath_coverage_required,
g.subpath_coverage_satisfied,
oracle.clearance_floor_device_px,
g.ink_candidates_found,
oracle.clearance_floor_device_px,
g.background_candidates_found,
g.ink_spacing_relaxed,
g.background_spacing_relaxed,
)
.unwrap();
writeln!(
s,
"| class | subpath_index | staff (x, y) | device (x, y) | clearance (device px) | hole evidence |"
)
.unwrap();
writeln!(s, "|---|---|---|---|---|---|").unwrap();
for p in &g.points {
let class = match p.class {
SampleClass::Ink => "Ink",
SampleClass::Background => "Background",
};
let subpath = match p.subpath_index {
Some(i) => i.to_string(),
None => "-".to_string(),
};
let evidence = match &p.hole_evidence {
Some(ev) => format!(
"inside_outer_contour={}, even_odd_filled={}, nonzero_filled={} (outer ring {})",
ev.inside_outer_contour, ev.even_odd_filled, ev.nonzero_filled, ev.outer_contour_ring_index
),
None => "-".to_string(),
};
writeln!(
s,
"| {class} | {subpath} | ({:.4}, {:.4}) | ({:.2}, {:.2}) | {:.3} | {evidence} |",
p.staff.0, p.staff.1, p.device.0, p.device.1, p.clearance_device_px
)
.unwrap();
}
writeln!(s).unwrap();
}
s
}