Skip to content

terni: the fractal feature (darkness as a set, twists show, membership) - #3

Merged
systemic-engineer merged 8 commits into
mainfrom
reed/fractal
Nov 2, 2026
Merged

systemic-engineer merged 8 commits into
mainfrom
reed/fractal

Conversation

@systemic-engineer

Copy link
Copy Markdown
Contributor

Adds terni's additive fractal feature (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.
  • join keeps every part; view(&order) projects under a caller TwistOrder with no default. Twists are not darknesses: a known twist can outrank darkness and shows as Partial, with darknesses kept in zoom().
  • 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

systemic-engineer and others added 8 commits November 2, 2026 08:12
… 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
@systemic-engineer
systemic-engineer merged commit e05d7e0 into main Nov 2, 2026
1 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant