C1 (egui + lyon) and C2 (vello) land together, from one commit, because
scoring either against an apparatus the other had already moved would not
be a comparison. Both were built against the pin-13 oracle frozen at
694d135 and its three schema amendments, all committed before either
candidate existed.
Both pass: Pass / Pass / NOT RUN / Pass / Pass, 80/80 hit-test probes each,
five live out-of-process AT-SPI readbacks each, no bus-unreachable
evidence claimed. Check 3 is NOT RUN by the 1.2 ruling, so both criterion
cells are NOT RUN and both candidates are eligible -- check 3 is not
disqualifying, and the checks that are (2 and 5) both pass.
Neither candidate re-shapes. Each takes glyph ids and offsets from the
resolved data and draws those glyphs at those positions; outline
extraction and path conversion are candidate-owned, the staff-to-device
transform is shared because re-implementing it would inject a divergence
check 1 is not measuring. D1 is 0 on all ten rasters, worst D2 0.14%
against a 2% tolerance, worst D4 1.22%. No tolerance was touched.
Round 1's binaries are byte-identical. Both candidates added Round 2 entry
points beside them rather than editing frozen evidence.
The cost measurement, which is why the packet exists:
ReportPart C1 C2
TextRendering 651 342
HitTestResolution 228 254
AccessibilityTreeConstruction 64 109
AccessibilityIntegrationWiring 62 199
FixtureAndReportPlumbing 1845 1925
Product-side accessibility -- tree construction plus integration wiring --
is 126 for C1 against 308 for C2: 2.4x, 182 lines. C1 inherits eframe's
AccessKit path and writes a single 62-line file to reach it; C2 inherits
nothing from vello and writes 199 lines of adapter lifecycle, event loop,
and bridge setup. C1 also writes *less* semantic-node code, 64 against 109.
That figure survived four reattributions, and the earlier ones were wrong
in ways worth recording so the next measurement is not made the same way:
- The first reading, 190 vs 30, was backwards. C1's tree row counted a
file that also held cosmetic glyph rendering; C2's excluded wiring that
belonged in it. Both errors pushed the same direction, which is exactly
why the number looked like a clean story.
- The second attribution put verifier subprocess orchestration under
AccessibilityIntegrationWiring, so C1's row grew 692 -> 1011 -> 1066
across two review rounds while measuring nothing but how much review its
harness attracted. That machinery is spike apparatus, and it is
FixtureAndReportPlumbing now.
- The mapping was disjoint before it was exhaustive: a 37-line file sat in
no part at all. Both candidates now assert every source file is claimed
by exactly one part and fail naming any that is not.
- C2 serialized two rows for one part while C1 serialized one. My own
comparison script summed them silently, which is how it survived a
review; it now refuses to aggregate and fails instead.
Three caveats belong with the number rather than under it. By non-comment
code the same comparison reads 55 vs 176, a 3.2x ratio -- same direction,
larger gap, because C1's files are proportionally more documentation; the
committed reports encode whole-file maintenance surface, so that is the
official figure and this is the sensitivity check. The dependency delta
points the other way: C1 carried accesskit at the Round 1 baseline and C2
carried none, yet both pull the same 16-17 AccessKit/AT-SPI/zbus crates
once a live tree exists, so inheritance saved code and not dependencies.
And roughly 1,900 lines per candidate is spike-only plumbing -- verifier
orchestration, evidence handling, report assembly -- that no real editor
would carry.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RSX4zSLgKvtiXaPjnMqLGz