Contract revision 6: round 1 was testing the wrong property on the wrong glyphs
Building round 1's oracle exposed two defects in the round as written, both mine, and both invisible until something tried to satisfy it. The glyph set was chosen by subpath count. I wrote that 19 of the 37 bundled outlines have more than one subpath and named gClef, fClef, timeSig8 and accidentalFlat as the useful ones -- conflating multi-subpath with has-a-hole. fClef is the counter-example: its three subpaths are a bowl and two SOLID, disjoint dots, nested in nothing. Measured across all 37 by point-in-path, exactly twelve carry a bounded hole; fClef, cClef, barlineFinal and every repeat glyph carry none. Round 1 now runs five glyphs in two classes testing two different properties. Hole checks -- gClef, timeSig8, accidentalFlat and noteheadHalf, which is new and earns its place by being frequently repeated and semantically consequential (a filled counter renders half notes as quarter notes, a notation error rather than an artifact). Disjoint-component check -- fClef alone, no background requirement, instead requiring one ink point inside EACH of its three filled subpaths, tagged with its subpath index. That second class catches a tessellator that keeps only the largest contour, which would pass every hole check ever written. Hard failure is now stated as either: a bounded hole painted as ink, or a required filled subpath omitted. The oracle's status model is now specified rather than inferred from an absence. fClef passing with zero background points is a SATISFIED result under its own requirement class; recording it only as background_satisfied = false would make a correct outcome indistinguishable from a failed one. The second defect was the criterion itself. Ruling A said epaint does not implement even-odd/nonzero fill for paths with holes -- framing criterion 1 around the fill RULE. Bravura's contours are correctly oppositely wound (signed ring areas gClef [8.702, -0.691, -1.803, -0.509]; fClef [2.534, 0.153, 0.148], all positive, the same fact from the other side), so even-odd and nonzero AGREE on every bundled hole. The rule is not load-bearing; preserving every filled contour and every bounded counter is. The criterion is amended to compound-path / inner-subpath fill correctness, with a more accurate reason for excluding raw egui shapes than the one it replaces: PathShape is a single point loop documenting "Fill is only supported for convex polygons", so it cannot express compound-fill or subtractive-hole semantics -- a Shape::Vec can group loops, but grouping paints them, it does not subtract a counter from its enclosing contour. Signed areas are recorded from the oracle's adaptive flattening rather than an earlier coarse fixed-step measurement, with the note that magnitudes are flattening-dependent and the SIGNS are the claim. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RSX4zSLgKvtiXaPjnMqLGz
This commit is contained in:
parent
3af242d457
commit
b724e94faf
|
|
@ -1,13 +1,18 @@
|
||||||
# Contract: Editor T4 — the toolkit spike
|
# Contract: Editor T4 — the toolkit spike
|
||||||
|
|
||||||
**Revision 5** (2026-07-28), after four reviews. Revision 1 left discretion in
|
**Revision 6** (2026-07-28), after five reviews. Revision 1 left discretion in
|
||||||
the measurement and elimination mechanics; revision 2 reordered the ladder and
|
the measurement and elimination mechanics; revision 2 reordered the ladder and
|
||||||
pinned the deciding numbers, but its new structure carried its own defects —
|
pinned the deciding numbers, but its new structure carried its own defects —
|
||||||
a damage oracle that compared the wrong thing, correctness failures dressed as
|
a damage oracle that compared the wrong thing, correctness failures dressed as
|
||||||
environmental absences, and an escalation branch with no continuation.
|
environmental absences, and an escalation branch with no continuation.
|
||||||
Revisions 3 and 4 closed those and introduced smaller ones of their own — a
|
Revisions 3 and 4 closed those and introduced smaller ones of their own — a
|
||||||
damage gate covering one rung, a censored median that flattered silence, and a
|
damage gate covering one rung, a censored median that flattered silence, and a
|
||||||
latency threshold with no timer origin. This revision closes those.
|
latency threshold with no timer origin. Revision 5 closed those. **Revision 6 amends Round 1** after building its
|
||||||
|
oracle exposed two defects in the round as written: its glyph set was chosen by
|
||||||
|
subpath count rather than by measured holes (`fClef` has none), and it framed
|
||||||
|
criterion 1 around the fill *rule* when Bravura's oppositely-wound contours make
|
||||||
|
even-odd and nonzero agree. Both are corrected below, and Ruling A criterion 1
|
||||||
|
is amended to match.
|
||||||
|
|
||||||
Repo root `/home/jeans/Repos/active/epiphany`. Governed by
|
Repo root `/home/jeans/Repos/active/epiphany`. Governed by
|
||||||
`spec/PLAN_EDITOR_APP.md` Ruling A ("What this ruling does **not** pin: the
|
`spec/PLAN_EDITOR_APP.md` Ruling A ("What this ruling does **not** pin: the
|
||||||
|
|
@ -46,10 +51,31 @@ two make it possible at all.
|
||||||
`PathCommand::{MoveTo, LineTo, CurveTo, Close}` in staff-space units
|
`PathCommand::{MoveTo, LineTo, CurveTo, Close}` in staff-space units
|
||||||
(`glyphs/src/catalog.rs:21,39`; `layout-ir/src/glyph.rs:283`). No candidate
|
(`glyphs/src/catalog.rs:21,39`; `layout-ir/src/glyph.rs:283`). No candidate
|
||||||
needs to parse SVG `d` strings, and no glyph work belongs in this packet.
|
needs to parse SVG `d` strings, and no glyph work belongs in this packet.
|
||||||
* **Glyphs with holes are in the bundled set, and can be named rather than
|
* **Glyphs with holes are in the bundled set — but subpath count does not
|
||||||
assumed.** 19 of the 37 bundled outlines have more than one subpath;
|
identify them.** Revisions 1–5 named `gClef`/`fClef`/`timeSig8`/
|
||||||
`gClef` (4), `fClef` (3), `timeSig8` (3), `accidentalFlat` (2) are the
|
`accidentalFlat` on the strength of "19 of the 37 bundled outlines have more
|
||||||
useful ones. Criterion 1 has real material.
|
than one subpath". That conflates *multi-subpath* with *has a bounded hole*,
|
||||||
|
and `fClef` is the counter-example: its three subpaths are a bowl and **two
|
||||||
|
solid, disjoint dots**, nested in nothing. Measured over all 37 by
|
||||||
|
point-in-path (2026-07-28), exactly twelve carry a **bounded hole** —
|
||||||
|
`gClef`, `timeSig8`, `accidentalFlat`, `accidentalSharp`,
|
||||||
|
`accidentalNatural`, `noteheadHalf`, `noteheadWhole`, `noteheadDoubleWhole`,
|
||||||
|
`timeSig0`, `timeSig6`, `timeSig9`, `dynamicPiano` — while `fClef`, `cClef`,
|
||||||
|
`barlineFinal` and every repeat glyph carry none. Criterion 1 has real
|
||||||
|
material, and Round 1 below names it by that measurement rather than by
|
||||||
|
subpath count.
|
||||||
|
* **Bravura's contours are correctly oppositely wound**, so even-odd and
|
||||||
|
nonzero *agree* on every bundled hole. Signed ring areas, as measured by the
|
||||||
|
Round 1 oracle's adaptive flattening (tolerance 0.0005 staff-space, the
|
||||||
|
authoritative figures — magnitudes are flattening-dependent, the **signs**
|
||||||
|
are the claim): `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]`; and `fClef` `[2.534, 0.153, 0.148]` —
|
||||||
|
**all positive**, which is the same fact from the other side: no counter,
|
||||||
|
three filled components. The
|
||||||
|
fill **rule** is therefore not the load-bearing property here; **preserving
|
||||||
|
every filled contour and every bounded counter** is. Ruling A criterion 1 is
|
||||||
|
amended to say so.
|
||||||
* **Per-system ownership is populated only by the real solver.** `Engraver`'s
|
* **Per-system ownership is populated only by the real solver.** `Engraver`'s
|
||||||
casting module builds one `PrimitiveIndices` per system
|
casting module builds one `PrimitiveIndices` per system
|
||||||
(`engrave/src/casting.rs:1185`); the **stub solver publishes everything
|
(`engrave/src/casting.rs:1185`); the **stub solver publishes everything
|
||||||
|
|
@ -474,22 +500,42 @@ is a hard
|
||||||
criterion, and discovering its absence in round 3 would waste three rounds —
|
criterion, and discovering its absence in round 3 would waste three rounds —
|
||||||
which is the whole claim of "cheapest disqualifier first".
|
which is the whole claim of "cheapest disqualifier first".
|
||||||
|
|
||||||
**Round 1 — criterion 1, fill correctness (HARD).** Each candidate draws
|
**Round 1 — criterion 1, compound-path fill correctness (HARD).** Each
|
||||||
`gClef`, `fClef`, `timeSig8`, `accidentalFlat` from `BravuraGlyphCatalog`'s
|
candidate draws five glyphs from `BravuraGlyphCatalog`'s typed outlines under
|
||||||
typed outlines under pin 4's configuration. **Precommitted oracle (pin 13):**
|
pin 4's configuration, in **two check classes testing two different
|
||||||
for each glyph, ≥3 must-be-ink and ≥3 must-be-background sample points in
|
properties**. All sample points are **derived programmatically** by
|
||||||
staff-space coordinates, **derived programmatically** by an even-odd
|
point-in-path over the `PathCommand` outline — never chosen by eye — and every
|
||||||
point-in-path test over the `PathCommand` outline — not chosen by eye — each
|
point must lie **≥8 device pixels from any outline edge** at the pinned render
|
||||||
required to lie **≥8 device pixels from any outline edge** at the pinned
|
transform, so antialiasing cannot explain any result.
|
||||||
render transform, so antialiasing cannot explain any result.
|
|
||||||
**Every background point must lie inside a bounded hole** — enclosed by the
|
* **Hole checks — `gClef`, `timeSig8`, `accidentalFlat`, `noteheadHalf`.**
|
||||||
glyph's outer silhouette yet unfilled under even-odd — asserted by the
|
≥3 must-be-ink and **≥3 must-be-background points, each inside a bounded
|
||||||
derivation, not assumed. Background points merely outside the silhouette test
|
hole** — enclosed by the glyph's outer silhouette yet unfilled — asserted by
|
||||||
nothing: a renderer that fills holes solid passes them trivially, which was
|
the derivation, not assumed. A background point merely outside the silhouette
|
||||||
revision 2's false-pass path. The oracle file, the render transform, and the
|
tests nothing, since a renderer that fills holes solid passes it trivially.
|
||||||
expected class per point are committed before any candidate renders.
|
`noteheadHalf` is in this set deliberately: it is a frequently repeated and
|
||||||
*Fails hard:* holes that are not holes — the disqualification Ruling A
|
semantically consequential glyph — a filled counter renders half notes as
|
||||||
anticipated.
|
quarter notes, a notation error rather than a cosmetic artifact. (It is not
|
||||||
|
the single most-drawn glyph; `noteheadBlack` is, and it has no counter.)
|
||||||
|
* **Disjoint-component check — `fClef`.** It has **no bounded hole** (bowl plus
|
||||||
|
two solid dots), so it carries **no background requirement** and tests the
|
||||||
|
other half of compound-path correctness: **≥1 ink point inside each of its
|
||||||
|
three filled subpaths** — body and both dots — at the same clearance floor,
|
||||||
|
each tagged with its `subpath_index` so the oracle proves coverage of every
|
||||||
|
component rather than three generic ink points that could all land in the
|
||||||
|
bowl. A tessellator that keeps only the largest contour fails here and would
|
||||||
|
pass every hole check.
|
||||||
|
|
||||||
|
**The oracle's status model must be explicit, not inferred from an absence.**
|
||||||
|
Each glyph carries a requirement enum (or at minimum `background_required:
|
||||||
|
bool`) *plus* an overall satisfied status. `fClef` passing with zero background
|
||||||
|
points is a **satisfied** result under its own requirement class; recording it
|
||||||
|
only as `background_satisfied = false` would make a correct outcome
|
||||||
|
indistinguishable from a failed one.
|
||||||
|
|
||||||
|
The oracle file, the render transform, and the expected class per point are
|
||||||
|
committed before any candidate renders. *Fails hard:* **any bounded hole
|
||||||
|
painted as ink, or any required filled subpath omitted.**
|
||||||
|
|
||||||
**Round 2 — criterion 3, text (HARD).** W3 §5's five checks against pin 8's
|
**Round 2 — criterion 3, text (HARD).** W3 §5's five checks against pin 8's
|
||||||
stand-in and pin 10's reference emitter: (1) **faithful consumption** — draws
|
stand-in and pin 10's reference emitter: (1) **faithful consumption** — draws
|
||||||
|
|
|
||||||
|
|
@ -532,11 +532,25 @@ result rather than whether it can shape correctly.
|
||||||
What this ruling does **not** pin: the toolkit/tessellation stack. The T4
|
What this ruling does **not** pin: the toolkit/tessellation stack. The T4
|
||||||
spike decides it, bounded by these recorded criteria:
|
spike decides it, bounded by these recorded criteria:
|
||||||
|
|
||||||
1. **Fill correctness:** `epaint`'s filled-path tessellator does not implement
|
1. **Compound-path / inner-subpath fill correctness** (**amended 2026-07-28**;
|
||||||
even-odd/nonzero fill for paths with holes — and glyphs have holes — so
|
was "fill correctness", framed around the fill *rule*): `epaint`'s
|
||||||
"just egui shapes" is likely out; the candidates are lyon-tessellated
|
`PathShape` is a **single point loop** documenting "Fill is only supported
|
||||||
meshes inside egui, or a vector renderer (e.g. Vello) behind a window
|
for convex polygons" (`epaint-0.35.0/src/shapes/path_shape.rs:14`), so it
|
||||||
shell.
|
cannot express **compound-fill / subtractive-hole semantics** — a
|
||||||
|
`Shape::Vec` can group several loops, but grouping paints them, it does not
|
||||||
|
subtract a counter from its enclosing contour. Glyphs are multi-contour with
|
||||||
|
bounded counters, so "just egui shapes" is out; the
|
||||||
|
candidates are lyon-tessellated meshes inside egui, or a vector renderer
|
||||||
|
(e.g. Vello) behind a window shell.
|
||||||
|
**The fill rule is not the load-bearing property, and the original wording
|
||||||
|
implied it was.** Bravura's contours are correctly oppositely wound (measured
|
||||||
|
signed ring areas, e.g. `gClef` `[8.702, −0.691, −1.803, −0.509]`), so **even-odd
|
||||||
|
and nonzero agree on every bundled hole**. What a candidate must preserve is
|
||||||
|
**every filled contour and every bounded counter**: a tessellator that keeps
|
||||||
|
only the outer contour paints counters solid, and one that keeps only the
|
||||||
|
largest drops disjoint components such as `fClef`'s two dots. The T4 spike's
|
||||||
|
Round 1 tests both properties separately
|
||||||
|
(`spec/CONTRACT_EDITOR_T4_SPIKE.md`).
|
||||||
2. **Staged latency, not end-to-end latency:** reduce / engrave / scene-build
|
2. **Staged latency, not end-to-end latency:** reduce / engrave / scene-build
|
||||||
/ paint measured **separately** on large multi-system fixtures against
|
/ paint measured **separately** on large multi-system fixtures against
|
||||||
Chapter-10-style budgets (Fact 8). A toolkit verdict from an end-to-end
|
Chapter-10-style budgets (Fact 8). A toolkit verdict from an end-to-end
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue