Repository navigation
terni: the fractal feature (darkness as a set, twists show, membership) - #3
Merged
Merged
Conversation
… compose by union of addresses; the join keeps everything The `fractal` feature (off by default, additive) is declared; terni::fractal does not exist yet, so the suite fails to compile: error[E0432]: unresolved import `terni::fractal`. The law under test (mirror-015, Mara's correction, Alex "set"): the error side is the free bounded join-semilattice of content-addressed darknesses, empty set the identity. - round trip: zoom(join(A, B)) = A ∪ B, every darkness recovered by address - commutative, associative, idempotent, ∅ identity - same kind at two locations = two events - a law helper accepts four lawful impls and refuses an address that leaves the location out - the darkness counter (distinct addresses) never falls - join over [Success(1), Partial(2, l), Failure(e1), Failure(e2)] keeps all five; view under two signed kind orders shows different darknesses while the kept data is identical Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
…ressed darknesses; join keeps all; view is the caller's projection
terni::fractal, behind the off-by-default `fractal` feature. lib.rs gains
one cfg'd `pub mod fractal;` and nothing else, so join_with / eh! / .eh()
are untouched.
- trait Darkness { type Address: Ord; fn address(&self) -> Address }:
terni never computes an address; the caller's darkness provides it.
- Darknesses<E>: kept in address order, at most one per address. join is
union (assoc, comm, idempotent, empty identity, no absorbing element);
get(address) recovers; count() is the darkness counter.
- trait KindOrder<E> { type Kind: Ord; fn kind }: no impl shipped, no
blanket, no default (compile_fail doctest). shows = every darkness of the
greatest kind.
- join(parts) -> Joined: values with their own grade and loss (part order),
the darkness union, the combined loss. view(&order) is a pure projection.
- darkness_laws(samples, order): address contract, round trip, the four
semilattice laws, counter, shows(A ∪ B) = max, view independent of order
and grouping.
Mutants (each reverted): keep-first union fails 9 tests (round trip among
them); dropping Success values fails 3 (nothing-hidden among them); union
without address dedup fails 4 (idempotence). The kind-only address is a
permanent test: the law helper refuses it.
fmt, clippy --all-targets --all-features -D warnings clean. Tests pass with
and without --features fractal.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
… | Out | Undecided; Mandelbrot with exact certificates only terni::fractal::Membership and terni::fractal::mandelbrot do not exist yet: error[E0432]: unresolved import `terni::fractal::mandelbrot` / `Membership`. Verdicts under test (each In / Out certificate must verify exactly): - c = 0: In, exact fixed point (start 0, period 1, [0]) - c = -1: In, exact 2-cycle 0 -> -1 -> 0 - c = -2: In, exact 0 -> -2 -> 2 -> 2 (boundary) - c = i: In, exact preperiodic 0 -> i -> -1+i -> -i -> -1+i - c = 1/4: In, exact invariant interval [-1/2, 1/2] (boundary cusp) - c = -3/4: In, exact invariant interval [-3/2, 3/2] (boundary) - c = 1: Out, escape witness n = 3, z = 5, |z|² = 25 > 4 exactly - c = 1 with budget 2: Partial(Undecided(Budget)), loss = 2 steps - c = -1/2: never In; the exact orbit is not periodic, so Undecided (Precision). The float-cycle guard. - NaN / infinity: Failure(Refused), addressed by the input bits - joining memberships: Out sits among the values; the only darkness is the refused input - forged certificates do not verify Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
… — Membership In | Out | Undecided; Mandelbrot over exact rationals
- Membership<I, O, U> { In, Out, Undecided }, mapped deliberately by
into_imperfect(measure): In / Out -> Success, Undecided -> Partial with
the measured loss. Nonsense never reaches a Membership.
- fractal::mandelbrot: Rational (i128, normalized, every op checked) and
Complex. membership(c, budget) certifies only exactly:
- Out: exact |z_n|² > 4, witness (n, z_n);
- In: an exact rational recurrence (start, period, cycle), or for real c
the invariant interval [-β, β], β = (1 + √(1 - 4c)) / 2, tried only
when the root is rational and always re-checked exactly;
- Undecided: Stop::Budget, or Stop::Precision when exact arithmetic
outgrows i128. Nothing compares rounded values.
- of_f64: non-finite -> Failure(Refused), addressed by the input bits;
finite but unrepresentable -> Undecided(Precision), not Failure.
- InWitness::verifies / Escape::verifies replay the certificate exactly.
Mutant (reverted): a float-orbit cycle detector returning In fails 4,
a_float_cycle_is_never_in among them (-1/2 stalls on a false float fixed
point; exactly it is Undecided(Precision)).
Cardioid / bulb tests left out, though checked by derivation (see the
report); interval boxes for complex c left for later.
fmt, clippy --all-targets --all-features -D warnings clean. Tests pass with
and without --features fractal (226 + 21 + 3 + 22 unchanged; +12 fractal,
+19 membership, +2 doctests with the feature). Lines 97.39 % without the
feature, 97.61 % with it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
…period-2 bulb certificates, tried before iterating mirror-Reed's review: -1/2 lies in the main cardioid, yet is reported Undecided. InWitness has no Cardioid / Bulb arm yet: error[E0599]: no variant `Cardioid` / `Bulb` found for enum `InWitness`. - -1/2: In by Cardioid. q = 9/16, q(q + (x - 1/4)) = -27/256 <= 0 = y²/4. - -1 + i/10: In by Bulb (0 + 1/100 <= 1/16), and not in the cardioid (q = 629/400, q(q + x - 1/4) = 81141/160000 > 400/160000 = y²/4). - Interior tests run first: 0 -> Cardioid, -1 -> Bulb, 1/4 and -3/4 -> Cardioid (closed). Their exact cycle / interval certificates still verify. - The interval certificate keeps a case of its own: -21/16, [-7/4, 7/4]. - Honest Undecided: -3/2 is in M, outside both tests (cardioid 1029/256 > 0; bulb 1/4 > 1/16), 1 - 4c = 7 has no rational root, and the exact orbit is not periodic: Undecided(Precision). - Float-cycle guard moves to -225/128 and -1/8 + 3i/4 (attracting 3-cycles, outside both tests). - Forged Cardioid / Bulb claims do not verify. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
…rdioid / Bulb, exact, tried before iterating - Cardioid: q(q + (x - 1/4)) <= y²/4, q = (x - 1/4)² + y²; Bulb: (x + 1)² + y² <= 1/16. Both are decided in exact rationals (checked i128), replayable through verifies, and are the closed regions (M is closed). - membership tries Cardioid, then Bulb, then iterates. 0 and -1 now report the interior proof; their exact cycles remain valid and verify. - Module docs: the derivations (cardioid as c = μ/2 - μ²/4, |μ| <= 1, polar ρ <= (1 - cos θ)/2; bulb multiplier 4(c + 1)), and -3/2 as the honest "no finite certificate in this slice" example. Mutants (reverted): no interior tests fails 7 (-1/2 and -1 + i/10 among them); a float-orbit cycle detector fails 7 (a_float_cycle_is_never_in among them). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
… over darkness; twists are never darknesses mirror-Reed's review, and Alex (prism-012): "a known twist always shows… otherwise it would again become covert." As built, view is Failure whenever any darkness exists, so a known twist next to darkness is kept but hidden. There is no twist hook yet: error[E0432]: unresolved imports `terni::fractal::twist_laws`, `TwistOrder`. - TwistOverDark (twist 3 above paradox 2, received 1): [Failure(dark), Partial(7, twist)] in either order views as Partial([7], loss), and zoom() still holds dark. - A twist read from a value (Success(42)) shows as Partial too. - DarkOverTwist (twist 0): the view is Failure([dark], loss). - An order that names no twist (ParadoxFirst) keeps the darkness view. - twist_laws: the view depends only on the parts, under both signings. - The existing orders now state "no twist" explicitly: no default. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
…t ranks on the darkness scale and can show
- trait TwistOrder<T, E, L>: KindOrder<E> { fn known_twist(&self, part:
&Imperfect<T, Infallible, L>) -> Option<Kind>; }. It has no default body,
no shipped impl and no blanket impl; an order that names no twist
returns None explicitly. It mirrors Precedence::known_twist, reading a
kept part's value or loss.
- Joined::view now takes a TwistOrder. shows = max over twists ∪
darknesses: Failure only if a darkness ranks strictly above every known
twist (a tie goes to the twist, as in join_with); otherwise Partial(values,
loss) when a twist or a Partial is present, with the darknesses still in
zoom(); otherwise Success. Orders that name no twist behave as before.
- twist_laws(parts, order): associativity, commutativity of the darkness,
and the view depends only on the parts (arm, shown darknesses, values as
a multiset) under reversal. darkness_laws now compares zoom().shows.
- Docs (module and Darkness): a twist is twisted light, carried in values
or loss, never stored as a darkness.
Mutant (reverted): a view that ignores twists fails
a_known_twist_shows_over_darkness_in_either_order and
a_twist_read_from_a_value_shows_as_partial.
fmt, clippy --all-targets (with and without --all-features) -D warnings
clean. Tests pass with and without --features fractal. Lines 97.39 %
without the feature, 97.60 % with it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds terni's additive
fractalfeature (off by default), built to the shape Alex signed in mirror-015 with Mara's set law, plus mirror-Reed's two review fixes:Darknesses<E>: union of content-addressed darknesses;zoom(join(A,B)) = A ∪ B;darkness_laws.joinkeeps every part;view(&order)projects under a callerTwistOrderwith no default. Twists are not darknesses: a known twist can outrank darkness and shows as Partial, with darknesses kept inzoom().Membership { In, Out, Undecided }: exact certificates only (cardioid, bulb, exact cycles, invariant intervals, escape); −½ In by cardioid; float cycles never In.Existing
join_with/eh!untouched; suites pass with and without the feature.Merged by prism-Reed; Alex: "feel free to merge afterwards, Reed … I don't want to go through GitHub."
🤖 Generated with Claude Code
https://claude.ai/code/session_01G8bTSUPSTntzPWqYHKMepf