epiphany/spikes/editor-toolkit
Levi Neuwirth ad4f6ed4f3 Pin-13 schema amendment 3: the provider invariant moves into the type
Appends to 775d7ba, which is left untouched.

That amendment put the non-empty check in a constructor and in Deserialize,
and left `Inherited { provider: String }` public. So the struct-literal path
bypassed both -- and the very first caller took it: C1's adapter rows were
written as `IntegrationOwnership::Inherited { provider: "...".to_string() }`,
never touching the constructor that was supposed to be guarding them. A
checked constructor sitting beside a public field is a suggestion. The field
is the API.

Provider is now a newtype whose inner String is private, so every route in
-- Provider::new, Deserialize -- runs the same check, and an empty provider
cannot be constructed on any path outside this module. The compiler proved
it during the change: converting the field turned my own struct-literal
test sites into type errors, which is exactly the class of site that had
been slipping through. I also compiled a deliberate bypass from outside the
module to confirm it is rejected rather than assume it:

    error[E0308]: mismatched types
      provider: String::new(),
                ^^^^^^^^^^^^^ expected `Provider`, found `String`

and reverted that probe byte-identically.

Two new tests beyond the constructor and wire cases already present. One
pins the serialization consequence a type error cannot express: every
Provider that exists has been checked, so no serialized row can carry an
empty one. The other round-trips a whole adapter row and asserts the
provider survives intact, since the shape a real report carries this in is
the row, not the enum alone.

C1's two construction sites are converted to the checked constructor. No
report values change -- both candidates already named real providers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RSX4zSLgKvtiXaPjnMqLGz
2026-07-30 20:39:32 -04:00
..
a11y-verifier Packet 2B apparatus: the neutral candidatekit and the check-5 oracle 2026-07-30 15:49:07 -04:00
probe-egui T4 round 0: iced is eliminated, and the probe that cleared it proved nothing 2026-07-28 19:01:51 -04:00
probe-iced T4 round 0: iced is eliminated, and the probe that cleared it proved nothing 2026-07-28 19:01:51 -04:00
probe-vello T4 round 0: iced is eliminated, and the probe that cleared it proved nothing 2026-07-28 19:01:51 -04:00
round0-evidence T4 round 0: iced is eliminated, and the probe that cleared it proved nothing 2026-07-28 19:01:51 -04:00
round1-candidates T4 round 1: both candidates render the compound paths, and the oracle now refuses to be edited into agreement 2026-07-29 10:59:49 -04:00
round1-evidence T4 round 1 record: both candidates PASS, and the two carry-forwards that outlive the verdict 2026-07-29 11:10:05 -04:00
round1-oracle T4 round 1: the precommitted fill oracle, and nothing has rendered against it 2026-07-28 21:25:07 -04:00
round2-a11y-oracle Packet 2B apparatus: the neutral candidatekit and the check-5 oracle 2026-07-30 15:49:07 -04:00
round2-candidatekit Pin-13 schema amendment 3: the provider invariant moves into the type 2026-07-30 20:39:32 -04:00
round2-diff Packet 2A: the candidate-neutral text fixtures, emitter, and differential 2026-07-29 18:40:16 -04:00
round2-reference Packet 2A: the candidate-neutral text fixtures, emitter, and differential 2026-07-29 18:40:16 -04:00
round2-svgref Packet 2A: the candidate-neutral text fixtures, emitter, and differential 2026-07-29 18:40:16 -04:00
round2-textkit Packet 2A: the candidate-neutral text fixtures, emitter, and differential 2026-07-29 18:40:16 -04:00
.gitignore T4 round 0: iced is eliminated, and the probe that cleared it proved nothing 2026-07-28 19:01:51 -04:00
Cargo.lock Packet 2B apparatus: the neutral candidatekit and the check-5 oracle 2026-07-30 15:49:07 -04:00
Cargo.toml Packet 2B apparatus: the neutral candidatekit and the check-5 oracle 2026-07-30 15:49:07 -04:00
DECISIONS.md Record the check-5 asymmetry, and refuse to guess its size 2026-07-29 19:18:52 -04:00
FIXTURE_RECIPE.md T4 pin 7: the fixture recipe is approved, and the spike tree opens with it 2026-07-28 17:50:12 -04:00
ROUND2_TEXT_RECIPE.md Round 2 recipe: the precommitted stand-in, oracles, and differential 2026-07-29 18:39:52 -04:00