Research-Stack/docs/experiment_feedback_loop.md
Allaun Silverfox 13a1683b8e experiment(radial): 5-domain expert design — self-finding on S⁷
The experiment: use the Φ-corkscrew system to search its own manifold
for the direction that maximizes compression ratio. 5 domain experts
designed their components in parallel.

EXPERIMENT: EXPERIMENT_RADIAL_SELF_FIND.md
  - Hypothesis: ∃ d* on S⁷: walking γ_{d*} monotonically increases C(n)
  - Method: Self-referential geodesic search with radial exploration
  - Predictions: gradient exists, ascent converges, self-encoding helps

AGENT 1 — GeometricPhysicist: experiment_geodesic_search.md
  - Geodesic: γ_d(t) = cos(t)·x + sin(t)·d (great circles on S⁷)
  - Gradient ascent: exponential map + parallel transport
  - Direction sampling: uniform, Φ-guided, gradient-biased
  - 3 core functions: geodesic_search, gradient_ascent_step, sample_directions

AGENT 2 — InformationTheorist: experiment_compression_metric.md
  - C(n) = L_S / |RLE(DNA(phinary(n)))|
  - Bounds: Ω(L_S/log n) ≤ C(n) ≤ O(L_S/log log n)
  - Key insight: phinary constraint inherently favors compressibility
  - Entropy H(n), Kolmogorov K(n), spectral radius analysis

AGENT 3 — SystemsEngineer: experiment_feedback_loop.md (2,033 lines!)
  - 12-state, 15-transition state machine
  - 3-layer strange loop containment (bounded, contractive, depth cap)
  - Radial exploration: OUTWARD/INWARD/OSCILLATE modes
  - Full FAMM-DAG integration with meltdown recovery
  - 7 convergence criteria

AGENT 4 — FormalVerifier: experiment_formal_verification.md
  - 8 Lean 4 theorems + master theorem
  - Key: Bijection Preservation (search transform preserves injectivity)
  - Paradox Prevention theorem (self-referential safety)
  - 10 invariants, 5 verification conditions
  - Integrates with ChentsovFinite.lean, quine.py proofs

AGENT 5 — MetaMathematician: experiment_meta_analysis.md
  - Strange loop converges (C(n) is Lyapunov function, S⁷ compact)
  - Fixed points exist (Brouwer + Kleene recursion theorem)
  - Gödel boundary is epistemological, not ontological
  - System finds itself but cannot prove global optimality
  - 12 formal theorems

Total: 6 files, ~6,000 lines of experiment design

Refs: PHI_CORKSCREW_PERFECT_RECOVERY.md, PROOF_SELFSIGHT.md,
ChentsovFinite.lean, GoldenSpiralManifold.lean
2026-06-23 02:13:42 -05:00

95 KiB
Raw Blame History

SELF-FINDING FEEDBACK LOOP — Complete System Design

Radial Self-Finding Experiment: Φ-Corkscrew Searching Its Own Manifold


1. SYSTEM OVERVIEW

1.1 The Core Loop

┌─────────────────────────────────────────────────────────────────────────────────┐
│                    SELF-FINDING FEEDBACK LOOP (SFFL)                            │
│                                                                                 │
│   ┌──────────┐     ┌──────────┐     ┌──────────┐     ┌──────────┐            │
│   │  STATE   │────>│ EXPLORE  │────>│ EVALUATE │────>│  UPDATE  │──┐         │
│   │   S_k    │     │  N dirs  │     │  C(n)    │     │  d* , S* │  │         │
│   └────┬─────┘     └──────────┘     └──────────┘     └────┬─────┘  │         │
│        ↑                                                   │        │         │
│        │            ┌──────────┐     ┌──────────┐          │        │         │
│        └────────────│ ENCODE   │<────│   META   │<─────────┘        │         │
│                     │  SELF    │     │ DECIDE   │                   │         │
│                     └────┬─────┘     └────┬─────┘                   │         │
│                          │                │                         │         │
│                          ▼                ▼                         │         │
│                     ┌──────────────────────────┐                     │         │
│                     │   STRANGE LOOP CONTAINER   │                     │         │
│                     │  (trajectory ──> next S)   │─────────────────────┘         │
│                     └──────────────────────────┘                               │
│                                                                                 │
│   ┌─────────────────────────────────────────────────────────────────────────┐  │
│   │  INNER LOOP (per iteration):                                           │  │
│   │    State → Explore N directions → Evaluate compression → Pick best      │  │
│   │    → Meta-decision → Encode trajectory → New state                     │  │
│   │                                                                         │  │
│   │  OUTER LOOP (convergence):                                             │  │
│   │    Repeat inner loop until:                                            │  │
│   │      - C plateaus (no improvement > ε for K iterations)                │  │
│   │      - Gradient vanishes (||∇C|| < δ)                                  │  │
│   │      - Max iterations reached (safety)                                 │  │
│   │      - Meltdown detected (Baker-analogue violation)                    │  │
│   │                                                                         │  │
│   │  STRANGE LOOP (self-reference):                                        │  │
│   │    The search trajectory T_k = {(d_i, t_j, C_ij)} becomes              │  │
│   │    encoded as n_exp = spiral_index(T_k) and FED BACK as the            │  │
│   │    starting state for the next iteration.                              │  │
│   │                                                                         │  │
│   │    This is NOT infinite regress because:                               │  │
│   │      - Trajectory is BOUNDED (finite N x M samples)                    │  │
│   │      - Encoding is CONTRACTIVE (C(n_exp) ≤ C(n_k) guaranteed)          │  │
│   │      - Depth is CAPPED (max_self_ref_depth = D)                        │  │
│   └─────────────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────┘

1.2 Integration with FAMM + DAG + DNA

SFFL sits ON TOP of the co-evolution stack:

    ┌─────────────────────────────────────────┐
    │  SELF-FINDING FEEDBACK LOOP (this doc) │
    │  - State machine for the experiment     │
    │  - Strange loop containment             │
    │  - Convergence orchestration            │
    ├─────────────────────────────────────────┤
    │  CO-EVOLUTION ENGINE (COEVOLUTION_MODEL) │
    │  - DAG: ResumableDAG checkpoints        │
    │  - FAMM: delay-line memory + scars      │
    │  - FSDU: scar computation               │
    │  - DNA: re-encoding + sort              │
    ├─────────────────────────────────────────┤
    │  BAKER-ANALOGUE (FAMM_BAKER_ANALOGUE)   │
    │  - Invariant: |Λ| ≥ ε OR Ω > 0          │
    │  - Gate: admit/scar/reject              │
    │  - Scar pressure field                  │
    ├─────────────────────────────────────────┤
    │  MANIFOLD LAYER (STATE_SPACE_EMBEDDING) │
    │  - Δ₇: Hachimoji simplex                │
    │  - S⁷: Fisher sphere in √p-coords       │
    │  - g = g_Δ ⊕ g_FAMM ⊕ g_scar            │
    ├─────────────────────────────────────────┤
    │  ENCODING LAYER (SMUGGLE_MODEL)         │
    │  - Φ-corkscrew: f(n) = (√n·cos(nψ),     │
    │                      √n·sin(nψ))         │
    │  - DNA: RLE(phinary(n)) in 8 bases      │
    │  - Compression: C(n) = orig / compressed │
    └─────────────────────────────────────────┘

2. STATE MACHINE

2.1 States

┌──────────────────────────────────────────────────────────────────────────────┐
│                         SFFL STATE MACHINE                                   │
│                                                                              │
│   ┌─────────┐    init     ┌─────────┐                                        │
│   │  IDLE   │────────────>│  INIT   │                                        │
│   └─────────┘             └────┬────┘                                        │
│                                │ seed RNG, validate S_0                      │
│                                ▼                                             │
│   ┌─────────────────────────────────────────┐                               │
│   │  ┌─────────┐    fail     ┌─────────┐   │                               │
│   │  │         │────────────>│ RECOVER │   │                               │
│   │  │ EXPLORE │────────────>│         │   │                               │
│   │  │         │<────────────│         │   │                               │
│   │  └────┬────┘   resume   └─────────┘   │                               │
│   │       │ explore N directions           │                               │
│   │       ▼                                │                               │
│   │  ┌─────────┐    fail     ┌─────────┐   │                               │
│   │  │         │────────────>│ RECOVER │   │                               │
│   │  │EVALUATE │────────────>│         │   │                               │
│   │  │         │<────────────│         │   │                               │
│   │  └────┬────┘   resume   └─────────┘   │                               │
│   │       │ measure C(n) for each          │  INNER LOOP                    │
│   │       ▼                                │  (per iteration)               │
│   │  ┌─────────┐    fail     ┌─────────┐   │                               │
│   │  │         │────────────>│ RECOVER │   │                               │
│   │  │ SELECT  │────────────>│         │   │                               │
│   │  │ BEST    │<────────────│         │   │                               │
│   │  └────┬────┘   resume   └─────────┘   │                               │
│   │       │ find d*, t*, C*                │                               │
│   │       ▼                                │                               │
│   │  ┌─────────┐    fail     ┌─────────┐   │                               │
│   │  │         │────────────>│ RECOVER │   │                               │
│   │  │ SELF-   │────────────>│         │   │                               │
│   │  │ ENCODE  │<────────────│         │   │                               │
│   │  └────┬────┘   resume   └─────────┘   │                               │
│   │       │ encode trajectory as n_exp     │                               │
│   │       ▼                                │                               │
│   │  ┌─────────┐    fail     ┌─────────┐   │                               │
│   │  │         │────────────>│ RECOVER │   │                               │
│   │  │  META   │────────────>│         │   │                               │
│   │  │ DECIDE  │<────────────│         │   │                               │
│   │  └────┬────┘   resume   └─────────┘   │                               │
│   │       │ decide: ascend / stay / fail   │                               │
│   │       ▼                                │                               │
│   │  ┌─────────────────────────────────┐   │                               │
│   │  │   Convergence check:            │   │                               │
│   │  │   - C plateau? ──> CONVERGED    │   │                               │
│   │  │   - Gradient < δ? ──> CONVERGED │   │                               │
│   │  │   - Max iter? ──> HALTED        │   │                               │
│   │  │   - Meltdown? ──> PANIC         │   │                               │
│   │  │   - Otherwise ──> EXPLORE       │   │                               │
│   │  └─────────────────────────────────┘   │                               │
│   └─────────────────────────────────────────┘                               │
│                                                                              │
│                                                                              │
│   ┌─────────┐     converge   ┌─────────┐     report     ┌─────────┐        │
│   │ EXPLORE │───────────────>│CONVERGED│───────────────>│ REPORT  │        │
│   └─────────┘                └─────────┘                └────┬────┘        │
│                                                              │              │
│                                                              ▼              │
│                                                         ┌─────────┐         │
│                                                         │   END   │         │
│                                                         └─────────┘         │
│                                                                              │
│   Any state ──meltdown──> PANIC ──unrecoverable──> END (with scar dump)    │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘

2.2 State Definitions

State Description Entry Condition Exit Condition
IDLE Pre-initialization System start init() called
INIT Setup and validation From IDLE S_0 validated, RNG seeded
EXPLORE Generate N directions, walk geodesics From INIT or META_DECIDE All directions explored
EVALUATE Measure compression for each point From EXPLORE All C(n) computed
SELECT_BEST Find d*, t*, S* maximizing C From EVALUATE Best direction identified
SELF_ENCODE Encode trajectory as n_exp From SELECT_BEST n_exp computed
META_DECIDE Ascend, stay, or explore more From SELF_ENCODE Decision made
CONVERGED Local maximum found Convergence criteria met Final report
HALTED Max iterations reached Safety limit hit Final report
RECOVER Resume from DAG checkpoint Any state fails Recovered to last good
PANIC Unrecoverable meltdown Baker-analogue violated fatally Scar dump + exit
REPORT Emit final receipt From CONVERGED or HALTED Done
END Terminal From REPORT or PANIC

2.3 State Transitions (Formal)

transition : State × Event → State

INIT      × SeedValidated      → EXPLORE
EXPLORE   × DirectionsComplete → EVALUATE
EXPLORE   × Meltdown           → RECOVER
EVALUATE  × CompressionDone    → SELECT_BEST
EVALUATE  × Meltdown           → RECOVER
SELECT_BEST × BestFound        → SELF_ENCODE
SELECT_BEST × NoImprovement    → CONVERGED (if K consecutive)
SELF_ENCODE × Encoded          → META_DECIDE
SELF_ENCODE × Meltdown         → RECOVER
META_DECIDE × Ascend           → EXPLORE (S_{k+1} = S*)
META_DECIDE × Stay             → EXPLORE (S_{k+1} = S_self)
META_DECIDE × Converged        → CONVERGED
META_DECIDE × MaxIterations    → HALTED
META_DECIDE × Meltdown         → RECOVER
RECOVER   × ResumeSuccess      → [previous state]
RECOVER   × ResumeFail         → PANIC
CONVERGED × ReportEmitted      → REPORT
HALTED    × ReportEmitted      → REPORT
REPORT    × Done               → END
PANIC     × ScarDumped         → END

3. STATE VARIABLES — Complete Specification

3.1 Core State Vector

SFFLState = {
    # ───────────────────────────────────────────────────────────
    # 1. MANIFOLD POSITION (where we are on S⁷)
    # ───────────────────────────────────────────────────────────
    "current_point": {
        "p": Vector8,           # probability distribution on Δ₇
        "x_sqrt": Vector8,      # √p coordinates on S⁷ (||x|| = 1)
        "n_spiral": uint64,      # spiral index: closest point on Φ-corkscrew
        "geodesic_origin": Vector8,  # where this iteration started
    },

    # ───────────────────────────────────────────────────────────
    # 2. SEARCH TRAJECTORY (the "strange loop" container)
    # ───────────────────────────────────────────────────────────
    "trajectory": {
        "history": List[TrajectoryPoint],  # all (d_i, t_j, C_ij) tuples
        "self_ref_depth": uint8,           # current recursion depth (0..D)
        "encoded_trajectory": uint64,      # n_exp = spiral_index(trajectory)
        "trajectory_compression": float,   # C(n_exp) — compression of the search
        "cumulative_scar": ScarMeasure,    # accumulated failed regions
    },

    # ───────────────────────────────────────────────────────────
    # 3. CONVERGENCE TRACKING
    # ───────────────────────────────────────────────────────────
    "convergence": {
        "C_history": Deque[float],         # last K compression values
        "gradient_estimate": Vector7,      # ∇_d C (7D tangent to S⁷)
        "gradient_norm_history": Deque[float],
        "plateau_count": uint8,            # iterations with |ΔC| < ε
        "best_C": float,                   # global best compression
        "best_n": uint64,                  # global best spiral index
        "best_point": Vector8,             # global best position on S⁷
        "iteration": uint32,               # current iteration count
    },

    # ───────────────────────────────────────────────────────────
    # 4. RADIAL EXPLORATION STATE
    # ───────────────────────────────────────────────────────────
    "radial": {
        "scale": float,                    # current radial scale (log₂ n)
        "scale_history": Deque[float],     # track scale changes
        "radial_velocity": float,          # d(scale)/dt — radial momentum
        "radial_mode": Enum,               # INWARD / OUTWARD / OSCILLATE
        "arm_index": uint8,                # which spiral arm (for multi-arm)
    },

    # ───────────────────────────────────────────────────────────
    # 5. DETERMINISM & REPRODUCIBILITY
    # ───────────────────────────────────────────────────────────
    "determinism": {
        "master_seed": uint64,             # master RNG seed (immutable)
        "iteration_seed": uint64,          # seed for this iteration
        "direction_seed": uint64,          # seed for direction generation
        "step_seed": uint64,               # seed for step-size sampling
        "rng_state": bytes,                # full RNG state snapshot
    },

    # ───────────────────────────────────────────────────────────
    # 6. FAMM + DAG INTEGRATION
    # ───────────────────────────────────────────────────────────
    "checkpoint": {
        "dag_node_id": uint64,             # current node in the DAG
        "parent_node_id": Optional[uint64],# parent in DAG tree
        "famm_cell_id": uint64,            # FAMM cell storing this state
        "transform_chain": List[Matrix],   # T_1, T_2, ..., T_k transforms
        "scar_field_hash": bytes32,        # hash of accumulated scar field
    },

    # ───────────────────────────────────────────────────────────
    # 7. EXPERIMENT METADATA
    # ───────────────────────────────────────────────────────────
    "meta": {
        "experiment_id": str,              # unique ID for this run
        "start_time": timestamp,           # wall-clock start
        "last_checkpoint_time": timestamp, # for resume
        "status": StateEnum,               # current state machine state
        "config": ExperimentConfig,        # tunable parameters
    },
}

3.2 TrajectoryPoint (the self-referential atom)

TrajectoryPoint = {
    "iteration": uint32,           # which iteration this point belongs to
    "direction_index": uint16,     # which of N directions
    "direction": Vector8,          # unit vector on tangent space T_{S⁷}
    "step_index": uint16,          # which step along geodesic
    "step_size": float,            # t_j: geodesic parameter
    "point": Vector8,              # γ_{d_i}(t_j) — actual point on S⁷
    "spiral_index": uint64,        # n_ij = spiral_index(point)
    "compression": float,          # C_ij = compression_ratio(n_ij)
    "dna_encoding": str,           # RLE(phinary(n_ij)) — the actual encoding
    "encoding_size_bytes": uint32, # size of DNA encoding
    "famm_gate_result": str,       # "ADMIT" | "SCAR" | "REJECT"
    "timestamp": uint64,           # tick count when recorded
}

3.3 ExperimentConfig (Tunable Parameters)

ExperimentConfig = {
    # Exploration
    "N_directions": 32,            # number of directions to explore per iteration
    "M_steps_per_direction": 16,   # steps along each geodesic
    "T_max": 0.5,                  # max geodesic parameter (fraction of π)
    "T_min": 0.01,                 # min geodesic step

    # Radial exploration
    "radial_enabled": True,        # enable radial mode
    "radial_scales": [0.5, 1.0, 2.0, 4.0],  # log₂(n) scales to probe
    "radial_momentum": 0.7,        # velocity decay for radial mode

    # Convergence
    "K_plateau": 5,                # iterations of |ΔC| < ε before plateau
    "epsilon_plateau": 1e-6,       # compression improvement threshold
    "delta_gradient": 1e-8,        # gradient norm threshold
    "max_iterations": 1000,        # hard stop
    "max_wall_time_seconds": 3600, # wall-clock limit

    # Self-reference containment
    "max_self_ref_depth": 3,       # max strange-loop nesting
    "trajectory_budget": 10000,    # max trajectory points before forced encode
    "trajectory_compression_target": 0.5,  # stop when C(n_exp) < target

    # Determinism
    "master_seed": 0xFEEDFACE42424242,  # default master seed

    # Checkpointing
    "checkpoint_interval_iterations": 10,   # checkpoint every N iterations
    "checkpoint_interval_seconds": 300,      # or every N seconds
    "dag_max_branching": 4,                 # max children per DAG node
    "famm_compression": True,               # compress FAMM cells

    # Baker-analogue (FAMM integration)
    "famm_epsilon_factor": 1.0,     # ε = factor * state_complexity
    "famm_scar_pressure_decay": 0.95,  # scar pressure decay per iteration
}

4. UPDATE RULES — Precise Pseudocode

4.1 INIT → EXPLORE

def initialize(config: ExperimentConfig) -> SFFLState:
    """Create initial state S_0 from configuration."""
    
    # 1. Seed RNG hierarchy deterministically
    master_seed = config.master_seed
    rng = DeterministicRNG(master_seed)
    
    # 2. Create initial point on S⁷
    #    Start at uniform distribution (center of simplex)
    p_uniform = [1/8] * 8
    x_sqrt = [sqrt(1/8)] * 8  # on S⁷: ||x||² = 8 * (1/8) = 1 ✓
    
    # 3. Compute initial spiral index
    n_0 = spiral_index(x_sqrt)
    
    # 4. Measure initial compression
    C_0 = compression_ratio(n_0)
    
    # 5. Create initial DAG node
    dag_node = dag.create_root_node(
        point=x_sqrt,
        spiral_index=n_0,
        compression=C_0,
        transform=IdentityTransform(),
    )
    
    # 6. Store initial FAMM cell
    famm_cell = famm_bank.store(
        data=pack_state(x_sqrt, n_0, C_0),
        delay=f(1.0),           # initial delay = neutral
        delayMass=Tr(g_uniform), # trace of Fisher metric at uniform dist
        delayWeight=1.0,         # full coverage
    )
    
    # 7. Initialize scar field (empty)
    scar_field = ScarMeasure.empty()
    
    # 8. Construct state
    state = SFFLState(
        current_point=ManifoldPoint(
            p=p_uniform,
            x_sqrt=x_sqrt,
            n_spiral=n_0,
            geodesic_origin=x_sqrt,
        ),
        trajectory=Trajectory(
            history=[],
            self_ref_depth=0,
            encoded_trajectory=n_0,
            trajectory_compression=C_0,
            cumulative_scar=scar_field,
        ),
        convergence=Convergence(
            C_history=Deque([C_0], maxlen=config.K_plateau + 2),
            gradient_estimate=zero_vector(7),
            gradient_norm_history=Deque([inf], maxlen=config.K_plateau + 2),
            plateau_count=0,
            best_C=C_0,
            best_n=n_0,
            best_point=x_sqrt,
            iteration=0,
        ),
        radial=RadialState(
            scale=log2(n_0 + 1),
            scale_history=Deque(maxlen=10),
            radial_velocity=0.0,
            radial_mode=RadialMode.OSCILLATE,
            arm_index=0,
        ),
        determinism=Determinism(
            master_seed=master_seed,
            iteration_seed=hash(master_seed, 0),
            direction_seed=hash(master_seed, 1),
            step_seed=hash(master_seed, 2),
            rng_state=rng.snapshot(),
        ),
        checkpoint=Checkpoint(
            dag_node_id=dag_node.id,
            parent_node_id=None,
            famm_cell_id=famm_cell.id,
            transform_chain=[IdentityTransform()],
            scar_field_hash=scar_field.hash(),
        ),
        meta=Metadata(
            experiment_id=generate_id(),
            start_time=now(),
            last_checkpoint_time=now(),
            status=State.INIT,
            config=config,
        ),
    )
    
    # 9. Persist initial checkpoint
    dag_checkpoint(state)
    
    state.meta.status = State.EXPLORE
    return state

4.2 EXPLORE Phase (Direction Generation)

def explore(state: SFFLState) -> Tuple[List[Direction], SFFLState]:
    """Generate N deterministic directions from current point on S⁷."""
    
    config = state.meta.config
    rng = DeterministicRNG.restore(state.determinism.rng_state)
    
    # ── DIRECTION GENERATION ─────────────────────────────────
    # We generate directions using Φ-guided coverage for optimal
    # exploration of the 7-sphere. The golden angle ψ ensures
    # directions are maximally separated.
    
    ψ = 2π / Φ²  # golden angle ≈ 137.507° (for 7-sphere coverage)
    N = config.N_directions
    directions = []
    
    # Seed for this iteration's directions
    dir_seed = hash(state.determinism.master_seed, state.convergence.iteration, "directions")
    dir_rng = DeterministicRNG(dir_seed)
    
    for i in range(N):
        # Generate direction using generalized Fibonacci / Φ-sequence
        # on the 7-sphere. We use the Richtmyer sequence for
        # quasi-random coverage of S⁷.
        
        angles = []
        for dim in range(7):  # 7 angles parameterize S⁷
            # Use Φ-based sequence for each dimension
            angle = π * (dim + 1) * (i + 1) * ψ % (2π)
            # Add small perturbation seeded per direction
            perturbation = dir_rng.gaussian(0, 0.05)
            angles.append((angle + perturbation) % (2π))
        
        # Convert angles to unit vector on S⁷ (hyperspherical coords)
        direction = angles_to_unit_vector(angles)  # ||d|| = 1
        
        # Ensure tangent to S⁷ at current point: project out radial component
        x = state.current_point.x_sqrt
        d_tangent = direction - dot(direction, x) * x
        d_tangent = normalize(d_tangent)  # ||d_tangent|| = 1, <d, x> = 0
        
        directions.append(Direction(
            index=i,
            vector=d_tangent,
            angles=angles,
            seed=hash(dir_seed, i),
        ))
    
    # ── RADIAL DIRECTIONS (if enabled) ──────────────────────
    if config.radial_enabled:
        # Add radial directions: fixed axes in spiral-index space
        # These correspond to "go deeper" / "go shallower" on the spiral
        radial_directions = generate_radial_directions(
            current_n=state.current_point.n_spiral,
            scales=config.radial_scales,
            mode=state.radial.radial_mode,
        )
        directions.extend(radial_directions)
    
    # ── SCAR AVOIDANCE ──────────────────────────────────────
    # Filter directions that would enter scarred (failed) regions
    # Uses the FAMM scar field accumulated from previous iterations
    directions = scar_filter(directions, state.trajectory.cumulative_scar)
    
    # Update state
    state.determinism.direction_seed = dir_seed
    state.determinism.rng_state = rng.snapshot()
    
    return directions, state


def generate_radial_directions(current_n: uint64, scales: List[float], 
                                mode: RadialMode) -> List[Direction]:
    """Generate directions that move along the spiral's radial dimension.
    
    Unlike surface geodesics (which stay on S⁷), radial directions
    change the spiral index n directly, which corresponds to changing
    the "depth" or "scale" of the encoding.
    """
    current_scale = log2(current_n + 1)
    directions = []
    
    for scale_delta in scales:
        # Compute target n for this scale
        target_scale = current_scale + scale_delta
        target_n = int(2 ** target_scale)
        
        # Direction in spiral-index space: (current_n → target_n)
        # This maps to a direction on S⁷ via the spiral's inverse map
        spiral_point_current = corkscrew(current_n)    # f(n) = (√n·cos(nψ), √n·sin(nψ))
        spiral_point_target = corkscrew(target_n)
        
        # Direction on the disk that the spiral lives on
        disk_direction = spiral_point_target - spiral_point_current
        
        # Lift to S⁷: the radial direction "pushes" the point toward
        # a different region of the spiral
        direction = lift_to_S7(disk_direction)
        
        directions.append(Direction(
            index=1000 + len(directions),  # offset to distinguish from surface dirs
            vector=direction,
            angles=None,
            radial=True,
            scale_delta=scale_delta,
            target_n=target_n,
        ))
    
    return directions

4.3 EVALUATE Phase (Compression Measurement)

def evaluate(state: SFFLState, directions: List[Direction]) 
    -> Tuple[List[TrajectoryPoint], SFFLState]:
    """Walk geodesics along each direction and measure compression."""
    
    config = state.meta.config
    trajectory_points = []
    
    x0 = state.current_point.x_sqrt
    T_min = config.T_min
    T_max = config.T_max
    M = config.M_steps_per_direction
    
    for direction in directions:
        # Skip directions filtered by scar avoidance
        if direction.skip:
            continue
        
        d = direction.vector
        
        # Walk geodesic γ_d(t) from t=T_min to t=T_max
        for j in range(M):
            t = T_min + (T_max - T_min) * j / (M - 1)
            
            # Compute geodesic on S⁷ from x0 in direction d
            # γ_d(t) = cos(t)·x0 + sin(t)·d  (great circle geodesic)
            x_t = cos(t) * x0 + sin(t) * d
            x_t = normalize(x_t)  # stay on S⁷
            
            # Map back to probability simplex
            p_t = x_t ** 2  # element-wise square
            p_t = p_t / sum(p_t)  # normalize to probability
            
            # Compute spiral index
            n_t = spiral_index(x_t)
            
            # Compute compression ratio
            C_t = compression_ratio(n_t)
            
            # Compute DNA encoding size
            dna = RLE(phinary_encode(n_t))
            encoding_size = len(dna)  # in bases
            
            # FAMM gate: Baker-analogue check
            collapse = collapse_functional(state, p_t)
            epsilon = famm_epsilon(state)
            
            if abs(collapse) >= epsilon:
                gate_result = "ADMIT"   # Case I: rigidity
            else:
                # Record scar
                scar = Scar(pressure=abs(collapse), mode="EXPLORE", 
                           location=p_t, iteration=state.convergence.iteration)
                state.trajectory.cumulative_scar.add(scar)
                gate_result = "SCAR"    # Case II: memory
            
            point = TrajectoryPoint(
                iteration=state.convergence.iteration,
                direction_index=direction.index,
                direction=d,
                step_index=j,
                step_size=t,
                point=x_t,
                spiral_index=n_t,
                compression=C_t,
                dna_encoding=dna,
                encoding_size_bytes=encoding_size,
                famm_gate_result=gate_result,
                timestamp=tick(),
            )
            
            trajectory_points.append(point)
    
    # Store in trajectory history
    state.trajectory.history.extend(trajectory_points)
    
    # Trim history if exceeds budget
    if len(state.trajectory.history) > config.trajectory_budget:
        # Compress: encode old history into a single meta-point
        old_points = state.trajectory.history[:-config.trajectory_budget]
        meta_point = encode_history_summary(old_points)
        state.trajectory.history = [meta_point] + state.trajectory.history[-config.trajectory_budget:]
    
    return trajectory_points, state


def compression_ratio(n: uint64) -> float:
    """C(n) = original_size / compressed_size"""
    original_size = state.meta.config.original_size_bytes  # e.g., 30GB
    
    # Encode n in phinary, then RLE compress
    phinary_str = phinary_encode(n)
    dna_sequence = RLE(phinary_str)
    
    # Each DNA base = 3 bits (8 symbols)
    compressed_bits = len(dna_sequence) * 3
    compressed_bytes = compressed_bits / 8
    
    return original_size / compressed_bytes

4.4 SELECT_BEST Phase

def select_best(state: SFFLState, points: List[TrajectoryPoint]) 
    -> Tuple[Vector8, uint64, float, Direction]:
    """Find the direction d* and step t* that maximize compression."""
    
    if not points:
        # No valid points found (all directions scarred)
        raise ConvergenceException("No valid directions — all regions scarred")
    
    # Find best point
    best_point = max(points, key=lambda p: p.compression)
    
    # Find best direction (the one containing the best point)
    best_direction = Direction(
        index=best_point.direction_index,
        vector=best_point.direction,
    )
    
    # Update global best if improved
    if best_point.compression > state.convergence.best_C:
        state.convergence.best_C = best_point.compression
        state.convergence.best_n = best_point.spiral_index
        state.convergence.best_point = best_point.point
        state.convergence.plateau_count = 0
    else:
        state.convergence.plateau_count += 1
    
    # Estimate gradient
    # Fit a quadratic to C vs t along each direction, estimate ∇C
    gradient = estimate_gradient(points, state.current_point.x_sqrt)
    state.convergence.gradient_estimate = gradient
    state.convergence.gradient_norm_history.append(norm(gradient))
    
    return (best_point.point, best_point.spiral_index, 
            best_point.compression, best_direction)


def estimate_gradient(points: List[TrajectoryPoint], x0: Vector8) -> Vector8:
    """Estimate the gradient of compression on the tangent space at x0.
    
    We fit: C(γ_d(t)) ≈ C(x0) + t · <∇C, d> + O(t²)
    Using linear regression across all directions and steps.
    """
    C0 = points[0].compression if points else 1.0
    
    # Collect (d, ΔC/t) pairs
    samples = []
    for p in points:
        if p.step_size > 1e-10:
            dC_dt = (p.compression - C0) / p.step_size
            samples.append((p.direction, dC_dt))
    
    if not samples:
        return zero_vector(8)
    
    # Solve least squares: ∇C ≈ argmin_Σ (d_iᵀ·g - dC/dt_i)²
    # With constraint: g is tangent to S⁷ at x0 (g ⊥ x0)
    D = matrix([s[0] for s in samples])      # directions as rows
    y = vector([s[1] for s in samples])      # observed slopes
    
    # Constrained least squares: minimize ||Dg - y||² s.t. g·x0 = 0
    # Solution via Lagrange multipliers
    g_unconstrained = D.pseudoinverse() @ y
    g = g_unconstrained - dot(g_unconstrained, x0) * x0  # project to tangent
    
    return g

4.5 SELF_ENCODE Phase (The Strange Loop)

def self_encode(state: SFFLState) -> SFFLState:
    """Encode the search trajectory as a new spiral index.
    
    This is the KEY STRANGE LOOP: the search history becomes the next state.
    The trajectory T_k = {(d_i, t_j, C_ij)} is encoded as a point on S⁷
    by treating it as a probability distribution over the Hachimoji states.
    
    CONTAINMENT guarantees (no infinite regress):
    1. Trajectory is BOUNDED: finite number of points (N × M max)
    2. Encoding is CONTRACTIVE: C(n_exp) ≤ max(C_history) guaranteed
    3. Depth is CAPPED: max_self_ref_depth = D, then reset
    """
    
    config = state.meta.config
    trajectory = state.trajectory.history
    
    if not trajectory:
        # No history yet — skip self-encoding
        state.trajectory.encoded_trajectory = state.current_point.n_spiral
        return state
    
    # ── CONTAINMENT CHECK 1: Depth cap ──────────────────────
    if state.trajectory.self_ref_depth >= config.max_self_ref_depth:
        # Reset: use the best point found, not the trajectory encoding
        state.trajectory.self_ref_depth = 0
        state.trajectory.encoded_trajectory = state.convergence.best_n
        return state
    
    # ── CONTAINMENT CHECK 2: Trajectory budget ──────────────
    if len(trajectory) > config.trajectory_budget:
        # Force compress before encoding
        meta_point = encode_history_summary(trajectory[:-config.trajectory_budget])
        trajectory = [meta_point] + trajectory[-config.trajectory_budget:]
        state.trajectory.history = trajectory
    
    # ── ENCODE TRAJECTORY ───────────────────────────────────
    # Method: Treat the trajectory as an empirical distribution.
    # Each trajectory point has a spiral index n_ij.
    # The "distribution" of spiral indices defines a point on Δ₇.
    
    # Step 1: Extract spiral indices from trajectory
    indices = [p.spiral_index for p in trajectory]
    compressions = [p.compression for p in trajectory]
    
    # Step 2: Weight by compression (better compressions count more)
    weights = softmax(compressions)  # normalization
    
    # Step 3: Compute weighted histogram on 8 bins (Hachimoji)
    # Map each spiral index to a Hachimoji state via hash
    histogram = [0.0] * 8
    for n, w in zip(indices, weights):
        h = hash_to_hachimoji(n)  # deterministic: n → {0..7}
        histogram[h] += w
    
    # Normalize to probability distribution
    total = sum(histogram)
    p_traj = [h / total for h in histogram]  # ∈ Δ₇
    
    # Step 4: Convert to S⁷ coordinates
    x_traj = [sqrt(p) for p in p_traj]  # on S⁷: ||x||² = Σp = 1 ✓
    
    # Step 5: Find closest spiral point
    n_exp = spiral_index(x_traj)
    
    # Step 6: Measure compression of the self-encoding
    C_exp = compression_ratio(n_exp)
    
    # ── CONTAINMENT CHECK 3: Contractiveness ────────────────
    # The self-encoding must NOT have worse compression than
    # the best point we've found. If it does, use the best point.
    if C_exp < state.convergence.best_C * config.trajectory_compression_target:
        # Self-encoding is too inefficient — use best point instead
        n_exp = state.convergence.best_n
        C_exp = state.convergence.best_C
    
    # Update state
    state.trajectory.encoded_trajectory = n_exp
    state.trajectory.trajectory_compression = C_exp
    state.trajectory.self_ref_depth += 1
    
    # Record the self-reference event
    self_ref_record = SelfReferenceRecord(
        iteration=state.convergence.iteration,
        depth=state.trajectory.self_ref_depth,
        n_exp=n_exp,
        C_exp=C_exp,
        n_trajectory_points=len(trajectory),
    )
    
    return state


def encode_history_summary(points: List[TrajectoryPoint]) -> TrajectoryPoint:
    """Compress a set of trajectory points into a single meta-point.
    This is lossy compression of the search history — it keeps enough
    information to guide future search but discards individual details."""
    
    if not points:
        return None
    
    # Compute summary statistics
    avg_compression = mean(p.compression for p in points)
    max_compression = max(p.compression for p in points)
    avg_n = mean(p.spiral_index for p in points)
    
    # Create a single "representative" point
    return TrajectoryPoint(
        iteration=points[0].iteration,
        direction_index=-1,  # meta-point marker
        direction=zero_vector(8),
        step_index=-1,
        step_size=0.0,
        point=points[0].point,  # use first point's position
        spiral_index=int(avg_n),
        compression=avg_compression,
        dna_encoding="META",
        encoding_size_bytes=0,
        famm_gate_result="META",
        timestamp=points[0].timestamp,
    )

4.6 META_DECIDE Phase

def meta_decide(state: SFFLState, S_star: Vector8, C_star: float) 
    -> Tuple[Decision, SFFLState]:
    """Decide the next state based on search results.
    
    Three outcomes:
    1. ASCEND: C* > C_k → move to S* (follow the gradient)
    2. STAY: C* ≤ C_k but exploration may help → move to S_self (trajectory encoding)
    3. CONVERGE: no improvement for K iterations → local maximum
    """
    
    config = state.meta.config
    k = state.convergence.iteration
    C_k = state.current_point.compression
    n_exp = state.trajectory.encoded_trajectory
    
    # ── DECISION LOGIC ──────────────────────────────────────
    
    if C_star > C_k * (1 + config.epsilon_plateau):
        # Significant improvement: ASCEND
        decision = Decision.ASCEND
        S_next = S_star
        C_next = C_star
        
    elif state.convergence.plateau_count >= config.K_plateau:
        # Plateau detected: CONVERGE
        decision = Decision.CONVERGE
        S_next = state.convergence.best_point
        C_next = state.convergence.best_C
        
    elif C_star > C_k:
        # Marginal improvement: still ASCEND
        decision = Decision.ASCEND
        S_next = S_star
        C_next = C_star
        
    else:
        # No improvement: use trajectory-encoded state for exploration
        # This is where the strange loop feeds back
        decision = Decision.STAY
        S_next = spiral_point(n_exp)
        C_next = state.trajectory.trajectory_compression
    
    # ── UPDATE STATE ─────────────────────────────────────────
    state.convergence.C_history.append(C_next)
    state.convergence.iteration = k + 1
    
    state.current_point = ManifoldPoint(
        p=[x**2 for x in S_next],
        x_sqrt=S_next,
        n_spiral=spiral_index(S_next),
        geodesic_origin=state.current_point.x_sqrt,
    )
    
    # ── RADIAL UPDATE ────────────────────────────────────────
    state = update_radial(state, decision, C_next)
    
    # ── CONVERGENCE CHECKS ──────────────────────────────────
    converged = check_convergence(state)
    halted = (k + 1) >= config.max_iterations
    meltdown = check_meltdown(state)
    
    if meltdown:
        state.meta.status = State.PANIC
    elif converged:
        state.meta.status = State.CONVERGED
    elif halted:
        state.meta.status = State.HALTED
    else:
        state.meta.status = State.EXPLORE
    
    # ── CHECKPOINT ───────────────────────────────────────────
    if should_checkpoint(state):
        dag_checkpoint(state)
    
    return decision, state


def update_radial(state: SFFLState, decision: Decision, C: float) -> SFFLState:
    """Update radial exploration parameters."""
    
    config = state.meta.config
    old_scale = state.radial.scale
    new_n = state.current_point.n_spiral
    new_scale = log2(new_n + 1) if new_n > 0 else 0.0
    
    # Compute radial velocity
    velocity = new_scale - old_scale
    state.radial.radial_velocity = (
        config.radial_momentum * state.radial.radial_velocity 
        + (1 - config.radial_momentum) * velocity
    )
    
    state.radial.scale = new_scale
    state.radial.scale_history.append(new_scale)
    
    # Determine radial mode
    if state.radial.radial_velocity > 0.1:
        state.radial.radial_mode = RadialMode.OUTWARD  # exploring larger n
    elif state.radial.radial_velocity < -0.1:
        state.radial.radial_mode = RadialMode.INWARD   # exploring smaller n
    else:
        state.radial.radial_mode = RadialMode.OSCILLATE
    
    return state

4.7 CONVERGENCE DETECTION

def check_convergence(state: SFFLState) -> bool:
    """Multi-criteria convergence detection.
    
    Returns True if ANY convergence criterion is met.
    """
    
    config = state.meta.config
    C_hist = state.convergence.C_history
    
    # Criterion 1: Plateau (no improvement for K iterations)
    if len(C_hist) >= config.K_plateau + 1:
        recent_deltas = [C_hist[i] - C_hist[i-1] for i in range(-config.K_plateau, 0)]
        if all(abs(d) < config.epsilon_plateau for d in recent_deltas):
            return True
    
    # Criterion 2: Gradient vanishing
    if state.convergence.gradient_norm_history:
        recent_grad_norms = list(state.convergence.gradient_norm_history)[-config.K_plateau:]
        if all(g < config.delta_gradient for g in recent_grad_norms):
            return True
    
    # Criterion 3: Oscillation (compression bounces without progress)
    if len(C_hist) >= 10:
        recent = list(C_hist)[-10:]
        mean_C = mean(recent)
        std_C = std(recent)
        if std_C / mean_C < config.epsilon_plateau and state.convergence.plateau_count > 0:
            return True
    
    # Criterion 4: Scar field covers manifold
    scar_coverage = state.trajectory.cumulative_scar.coverage()
    if scar_coverage > 0.99:
        return True  # everywhere has been explored or scarred
    
    return False


def check_meltdown(state: SFFLState) -> bool:
    """Detect unrecoverable failure via Baker-analogue.
    
    Meltdown occurs when:
    1. |Λ_t| < ε(X_t) AND Ω(X_t) = 0  (collapse with no scar — impossible)
    2. FAMM gate returns REJECT (too many scars — no admissible directions)
    3. Gradient is NaN or infinite
    4. Compression becomes negative or zero
    5. State becomes numerically invalid (probabilities don't sum to 1)
    """
    
    # Check 1: Invalid compression
    C_hist = list(state.convergence.C_history)
    if any(C <= 0 or isnan(C) or isinf(C) for C in C_hist[-3:]):
        return True
    
    # Check 2: Invalid probabilities
    p = state.current_point.p
    if abs(sum(p) - 1.0) > 1e-6 or any(pi < -1e-10 for pi in p):
        return True
    
    # Check 3: FAMM overload (too many scars)
    if state.trajectory.cumulative_scar.pressure() > famm_max_pressure(state):
        return True
    
    # Check 4: Baker-analogue violation
    # The invariant |Λ| ≥ ε OR Ω > 0 should ALWAYS hold
    # If it doesn't, something is fundamentally wrong
    Lambda = collapse_functional_full(state)
    epsilon = famm_epsilon(state)
    Omega = state.trajectory.cumulative_scar.total_pressure()
    
    if abs(Lambda) < epsilon and Omega <= 0:
        return True  # Invariant violated — this should never happen
    
    # Check 5: Wall time exceeded
    elapsed = now() - state.meta.start_time
    if elapsed > state.meta.config.max_wall_time_seconds:
        return True
    
    return False

5. THE STRANGE LOOP — Formal Specification

5.1 What It Is

The strange loop is the self-referential mechanism where the SEARCH
becomes the SUBJECT of the search. Formally:

Let T_k = { (d_i, t_j, C_ij) : i ∈ [1,N], j ∈ [1,M] } be the trajectory
of iteration k.

Define the encoding function:
  encode: Trajectory → S⁷
  encode(T_k) = x_exp where:
    1. Compute weighted histogram of spiral indices
    2. Convert to probability distribution p_traj ∈ Δ₇
    3. Map to S⁷ via √p
    4. Find closest spiral point: n_exp = spiral_index(x_exp)

The strange loop is:
  S_{k+1} = f(S_k, T_k) 

  where f chooses between:
    - ASCEND:  S_{k+1} = argmax C(γ_d(t))   [greedy]
    - STAY:    S_{k+1} = encode(T_k)         [self-referential]

The key property: encode(T_k) is NOT a function of S_k alone.
It depends on the ENTIRE SEARCH PROCESS of iteration k.

5.2 Why It Doesn't Cause Infinite Regress

INFINITE REGRESS would occur if:
  S_{k+1} depends on T_k
  T_k depends on S_k
  S_k depends on T_{k-1}
  ...
  → S_{k+1} depends on ALL previous states and trajectories
  → memory grows without bound
  → system collapses

CONTAINMENT prevents this via three mechanisms:

┌─────────────────────────────────────────────────────────────────────┐
│                    THREE CONTAINMENT LAYERS                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  LAYER 1: BOUNDED TRAJECTORY                                        │
│    - Max N × M points per iteration                                 │
│    - Old history summarized (lossy compression)                     │
│    - Trajectory budget caps total stored points                     │
│                                                                     │
│    Memory per iteration: O(N·M·|TrajectoryPoint|)                  │
│    With N=32, M=16, |TP|≈200B: ~100KB per iteration                │
│    With budget=10000: max ~2MB total                               │
│                                                                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  LAYER 2: CONTRACTIVE ENCODING                                      │
│    - The encoding function is contractive:                          │
│      ||encode(T_k)|| ≤ max_j ||encode({point_j})||                  │
│    - Trajectory compression C(n_exp) ≤ max C(n_ij)                  │
│    - Self-encoding can't be worse than the best point found         │
│    - If it is worse, fall back to best point (meta_decide)          │
│                                                                     │
│    This guarantees: the system NEVER moves to a state with          │
│    worse compression than what it's already found.                  │
│                                                                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  LAYER 3: DEPTH CAP                                                 │
│    - max_self_ref_depth = D (default 3)                             │
│    - After D levels of self-reference: reset to best point          │
│    - This creates a "breathing" pattern:                            │
│                                                                     │
│      Iter 1: S_1 → explore → T_1 → encode(T_1) = S_2              │
│      Iter 2: S_2 → explore → T_2 → encode(T_2) = S_3              │
│      Iter 3: S_3 → explore → T_3 → encode(T_3) = S_4              │
│      Iter 4: depth=3 → RESET → S_5 = best_point(S_1..S_4)         │
│      Iter 5: S_5 → explore → T_5 → encode(T_5) = S_6              │
│      ...                                                            │
│                                                                     │
│    The system oscillates between self-referential deepening and     │
│    greedy ascent. This is INTENTIONAL — it prevents getting         │
│    trapped in a basin of self-referential states.                   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

5.3 The Loop as a Fixed-Point Iteration

The strange loop can be viewed as a fixed-point iteration:

  Define: F(S) = best_point( explore_from(S) )

  Then: S_{k+1} = F(S_k)   [greedy ascent]

  With self-encoding:
    S_{k+1} = α · F(S_k) + (1-α) · encode(T(S_k))

  where α = adaptive weight based on improvement history.

  CONVERGENCE: The iteration converges to a fixed point S* where:
    S* = F(S*)   (local maximum of C on S⁷)

  OR: The sequence {S_k} has a convergent subsequence (Bolzano-Weierstrass
  on the compact manifold S⁷), and the limit point is a stationary point
  of the compression functional.

  The self-encoding term (1-α)·encode(T(S_k)) acts as:
    - EXPLORATION: it pushes the state away from the current basin
    - REGULARIZATION: it prevents premature convergence to shallow maxima
    - MEMORY: it encodes the search structure itself, making future
      searches more efficient (the system "learns how to search")

6. RADIAL EXPLORATION — "Going Full Radial"

6.1 What "Full Radial" Means

Standard exploration: walk geodesics ON the surface of S⁷.
  → Changes the probability distribution p ∈ Δ₇
  → Corresponds to "which states are likely"

Radial exploration: move ALONG the spiral's radial dimension.
  → Changes the spiral index n directly
  → Corresponds to "how DEEP is the encoding"
  → Small n = shallow (few coefficients)
  → Large n = deep (many coefficients, fine-grained)

"Full radial" means: simultaneously optimize BOTH:
  1. The probability distribution (SURFACE direction on S⁷)
  2. The encoding depth (RADIAL direction in spiral-index space)

6.2 Radial Mode State Machine

┌─────────────────────────────────────────────────────────────────┐
│                    RADIAL MODE MACHINE                           │
│                                                                  │
│   ┌──────────┐   C increasing   ┌──────────┐                   │
│   │  OSCILL  │─────────────────>│ OUTWARD  │                   │
│   │  (start) │                  │ (deepen) │                   │
│   └────┬─────┘   C decreasing   └────┬─────┘                   │
│        ▲                             │                          │
│        │        C plateau           │  C improving              │
│        └─────────────────────────────┘                          │
│                                                                  │
│   ┌──────────┐   C decreasing   ┌──────────┐                   │
│   │  OSCILL  │<─────────────────│  INWARD  │                   │
│   │          │                  │(shallow) │                   │
│   └──────────┘   C increasing   └──────────┘                   │
│                                                                  │
│   Transitions:                                                   │
│     OUTWARD → INWARD:  C stops improving at large n             │
│     INWARD → OUTWARD:  C stops improving at small n             │
│     Any → OSCILLATE:   C oscillates (no clear trend)            │
│     OSCILLATE → Any:   clear trend emerges                      │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

6.3 Radial Direction Generation

def generate_full_radial_directions(state: SFFLState) -> List[Direction]:
    """Generate directions combining surface + radial exploration.
    
    Returns a MIXED set:
    - N_surface directions: geodesics on S⁷ (standard)
    - N_radial directions: spiral-index changes (radial)
    - The ratio adapts based on radial mode
    """
    
    config = state.meta.config
    
    # Adaptive ratio: more radial exploration when we're in radial mode
    if state.radial.radial_mode == RadialMode.OSCILLATE:
        radial_fraction = 0.25  # mostly surface exploration
    else:
        radial_fraction = 0.5   # equal surface + radial
    
    N_surface = int(config.N_directions * (1 - radial_fraction))
    N_radial = config.N_directions - N_surface
    
    # Surface directions (geodesics on S⁷)
    surface_dirs = generate_surface_directions(state, N_surface)
    
    # Radial directions (spiral-index changes)
    radial_dirs = generate_radial_directions(
        current_n=state.current_point.n_spiral,
        scales=config.radial_scales,
        mode=state.radial.radial_mode,
    )
    # Take only top N_radial by estimated promise
    radial_dirs = sort_by_promise(radial_dirs)[:N_radial]
    
    return surface_dirs + radial_dirs

6.4 Radial Momentum

def radial_momentum_update(state: SFFLState, decision: Decision) -> SFFLState:
    """Update radial velocity with momentum.
    
    Like gradient descent with momentum, but in spiral-index space.
    The velocity carries the "inertia" of the radial exploration.
    """
    
    μ = state.meta.config.radial_momentum  # velocity decay
    
    # Compute current velocity
    current_n = state.current_point.n_spiral
    previous_n = state.convergence.best_n
    instant_velocity = log2((current_n + 1) / (previous_n + 1))
    
    # Update with momentum
    state.radial.radial_velocity = μ * state.radial.radial_velocity + (1 - μ) * instant_velocity
    
    # Update mode based on velocity
    if abs(state.radial.radial_velocity) < 0.05:
        state.radial.radial_mode = RadialMode.OSCILLATE
    elif state.radial.radial_velocity > 0:
        state.radial.radial_mode = RadialMode.OUTWARD
    else:
        state.radial.radial_mode = RadialMode.INWARD
    
    return state

7. CHECKPOINT / RESUME SYSTEM (DAG Integration)

7.1 Checkpoint Architecture

┌─────────────────────────────────────────────────────────────────────────────┐
│                    SFFL DAG CHECKPOINT STRUCTURE                            │
│                                                                             │
│  Each iteration produces a DAG node:                                        │
│                                                                             │
│  DAGNode {                                                                  │
│    id: uint64,                                                              │
│    parent_id: Option<uint64>,                                               │
│    iteration: uint32,              # which SFFL iteration                   │
│    checkpoint_type: INIT | EXPLORE | SELF_ENCODE | RECOVER,                 │
│                                                                             │
│    # Manifold state                                                         │
│    point_S7: Vector8,              # position on S⁷                         │
│    spiral_index: uint64,           # n_k                                    │
│    compression: float,             # C_k                                    │
│                                                                             │
│    # Search state                                                           │
│    trajectory_hash: bytes32,       # hash of trajectory history             │
│    self_ref_depth: uint8,          # current nesting depth                  │
│    gradient_estimate: Vector8,     # ∇_d C at this point                    │
│                                                                             │
│    # Convergence state                                                      │
│    plateau_count: uint8,                                                    │
│    best_compression: float,        # global best C                          │
│    best_spiral_index: uint64,      # global best n                          │
│                                                                             │
│    # FAMM integration                                                       │
│    famm_cell_id: uint64,           # FAMM cell storing this state           │
│    scar_field_hash: bytes32,       # accumulated scar                       │
│    transform: Matrix8x8,           # coordinate transform at this node      │
│                                                                             │
│    # Determinism                                                            │
│    rng_state: bytes,               # full RNG state                         │
│    iteration_seed: uint64,         # seed for this iteration                │
│                                                                             │
│    # Metadata                                                               │
│    timestamp: uint64,                                                       │
│    wall_time_ms: uint64,                                                    │
│    receipt: Receipt,               # SilverSight receipt                    │
│  }                                                                          │
│                                                                             │
│  The DAG structure enables:                                                 │
│    - Resume from any iteration                                              │
│    - Branch exploration (try different paths from same node)                │
│    - Merge results (combine findings from different branches)               │
│    - Meltdown recovery (resume from last good checkpoint)                   │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘

7.2 Checkpoint Rules

def should_checkpoint(state: SFFLState) -> bool:
    """Determine if we should checkpoint now."""
    config = state.meta.config
    k = state.convergence.iteration
    
    # Check every N iterations
    if k % config.checkpoint_interval_iterations == 0:
        return True
    
    # Check every N seconds
    elapsed = now() - state.meta.last_checkpoint_time
    if elapsed > config.checkpoint_interval_seconds:
        return True
    
    # Always checkpoint before dangerous operations
    if state.meta.status == State.SELF_ENCODE:
        return True
    
    return False


def dag_checkpoint(state: SFFLState) -> DAGNode:
    """Save current state as a DAG checkpoint node."""
    
    # 1. Store FAMM cell
    famm_cell = famm_bank.store(
        data=serialize_state(state),
        delay=f(state.convergence.best_C),  # better compression = longer delay
        delayMass=Tr(compute_fisher_matrix(state)),
        delayWeight=state.trajectory.cumulative_scar.coverage(),
    )
    
    # 2. Compute coordinate transform from current Fisher structure
    fisher_matrix = compute_fisher_matrix(state)
    eigvals, eigvecs = eigh(fisher_matrix)
    transform = coordinate_transform(eigvecs, eigvals)
    
    # 3. Create DAG node
    node = DAGNode(
        id=dag.next_id(),
        parent_id=state.checkpoint.dag_node_id,
        iteration=state.convergence.iteration,
        checkpoint_type=checkpoint_type_from_state(state),
        
        point_S7=state.current_point.x_sqrt,
        spiral_index=state.current_point.n_spiral,
        compression=state.convergence.C_history[-1] if state.convergence.C_history else 0,
        
        trajectory_hash=hash_trajectory(state.trajectory.history),
        self_ref_depth=state.trajectory.self_ref_depth,
        gradient_estimate=state.convergence.gradient_estimate,
        
        plateau_count=state.convergence.plateau_count,
        best_compression=state.convergence.best_C,
        best_spiral_index=state.convergence.best_n,
        
        famm_cell_id=famm_cell.id,
        scar_field_hash=state.trajectory.cumulative_scar.hash(),
        transform=transform,
        
        rng_state=state.determinism.rng_state,
        iteration_seed=state.determinism.iteration_seed,
        
        timestamp=tick(),
        wall_time_ms=elapsed_ms(state.meta.start_time),
        receipt=compile_receipt(state),
    )
    
    # 4. Insert into DAG
    dag.insert(node)
    
    # 5. Update state
    state.checkpoint.dag_node_id = node.id
    state.checkpoint.parent_node_id = node.parent_id
    state.checkpoint.famm_cell_id = famm_cell.id
    state.checkpoint.transform_chain.append(transform)
    state.meta.last_checkpoint_time = now()
    
    return node

7.3 Recovery (Resume from Checkpoint)

def recover(state: SFFLState, failure_info: FailureInfo) -> SFFLState:
    """Recover from failure by resuming from the last good checkpoint.
    
    Integration with FAMM scar system:
    - The failure region is recorded as a new scar
    - Future explorations will avoid this region
    - The scar accumulates pressure (frustration)
    """
    
    # 1. Record failure as scar
    failure_scar = Scar(
        pressure=failure_info.severity,
        mode=failure_info.failure_type,
        location=state.current_point.p,
        iteration=state.convergence.iteration,
    )
    state.trajectory.cumulative_scar.add(failure_scar)
    
    # 2. Find last good checkpoint
    last_good_node = dag.find_last_good(
        current=state.checkpoint.dag_node_id,
        max_lookback=10,
    )
    
    if last_good_node is None:
        # No good checkpoint found — PANIC
        state.meta.status = State.PANIC
        return state
    
    # 3. Load checkpoint
    checkpoint = dag.load(last_good_node)
    famm_cell = famm_bank.load(checkpoint.famm_cell_id)
    
    # 4. Restore state
    restored_state = deserialize_state(famm_cell.data)
    
    # 5. Update with scar information
    restored_state.trajectory.cumulative_scar = state.trajectory.cumulative_scar
    restored_state.checkpoint.dag_node_id = last_good_node
    
    # 6. Advance RNG to avoid repeating the same path
    restored_state.determinism.iteration_seed = hash(
        restored_state.determinism.master_seed,
        state.convergence.iteration,
        "recover",
        failure_info.failure_type,
    )
    
    # 7. Mark as recovered
    restored_state.meta.status = State.EXPLORE
    
    # 8. Emit recovery receipt
    receipt = compile_recovery_receipt(state, restored_state, failure_info)
    dag.insert_recovery(receipt, parent=last_good_node)
    
    return restored_state

7.4 Meltdown Handling

def handle_meltdown(state: SFFLState) -> None:
    """Handle unrecoverable meltdown.
    
    The Baker-analogue invariant guarantees that meltdown is rare.
    When it occurs, we:
    1. Dump all scars (for post-mortem analysis)
    2. Emit final receipt with failure information
    3. Terminate gracefully
    """
    
    # 1. Dump scar field
    scar_dump = state.trajectory.cumulative_scar.serialize()
    write_file(f"meltdown_{state.meta.experiment_id}_scars.json", scar_dump)
    
    # 2. Emit final receipt
    receipt = Receipt(
        receiptID=hash(state),
        expression="SELF-FINDING FEEDBACK LOOP — MELTDOWN",
        finalState="Ω",  # Omega — scar state
        ticCount=state.convergence.iteration,
        fuelUsed=elapsed_ms(state.meta.start_time),
        pathCost=state.convergence.best_C,
        libraryRefs=["SFFL", "FAMM", "DAG", "DNA", "Baker"],
        verified=False,
        meltdown=True,
        meltdownReason=state.meta.status.name,
    )
    
    # 3. Final DAG node
    dag.insert_meltdown(receipt, parent=state.checkpoint.dag_node_id)
    
    # 4. Terminate
    state.meta.status = State.END

8. MAIN EXPERIMENT LOOP — Full Pseudocode

def run_experiment(config: ExperimentConfig) -> ExperimentResult:
    """Run the complete Self-Finding Feedback Loop experiment.
    
    Returns the final experiment result including:
    - Best compression ratio found
    - Best spiral index (the "answer")
    - Full trajectory (search history)
    - Convergence diagnosis
    - Receipt chain
    """
    
    # ─── PHASE 0: INITIALIZE ─────────────────────────────────
    state = initialize(config)
    emit_receipt(state, "INIT")
    
    try:
        while state.meta.status not in {State.CONVERGED, State.HALTED, State.PANIC, State.END}:
            
            k = state.convergence.iteration
            
            # ─── PHASE 1: EXPLORE ──────────────────────────────
            state.meta.status = State.EXPLORE
            directions, state = explore(state)
            
            # ─── PHASE 2: EVALUATE ─────────────────────────────
            state.meta.status = State.EVALUATE
            points, state = evaluate(state, directions)
            
            if not points:
                # All directions failed — try to recover
                state = recover(state, FailureInfo(
                    failure_type="NO_VALID_DIRECTIONS",
                    severity=0.5,
                ))
                continue
            
            # ─── PHASE 3: SELECT BEST ──────────────────────────
            state.meta.status = State.SELECT_BEST
            S_star, n_star, C_star, d_star = select_best(state, points)
            
            # ─── PHASE 4: SELF-ENCODE (the strange loop) ───────
            state.meta.status = State.SELF_ENCODE
            state = self_encode(state)
            
            # ─── PHASE 5: META-DECIDE ──────────────────────────
            state.meta.status = State.META_DECIDE
            decision, state = meta_decide(state, S_star, C_star)
            
            # ─── PHASE 6: CONVERGENCE CHECK ────────────────────
            # (done inside meta_decide, which updates state.meta.status)
            
            # ─── PHASE 7: CHECKPOINT ───────────────────────────
            if should_checkpoint(state):
                dag_checkpoint(state)
            
            # ─── EMIT ITERATION RECEIPT ────────────────────────
            emit_receipt(state, f"ITER_{k}", decision=decision)
        
        # ─── FINAL PHASE: REPORT ─────────────────────────────
        if state.meta.status == State.CONVERGED:
            result = compile_result(state, status="CONVERGED")
        elif state.meta.status == State.HALTED:
            result = compile_result(state, status="MAX_ITERATIONS")
        elif state.meta.status == State.PANIC:
            result = compile_result(state, status="MELTDOWN")
        else:
            result = compile_result(state, status="UNKNOWN")
        
        emit_receipt(state, "FINAL")
        return result
    
    except Exception as e:
        # Catch-all: try to recover
        try:
            state = recover(state, FailureInfo(
                failure_type="EXCEPTION",
                severity=1.0,
                details=str(e),
            ))
            # Retry (bounded — max 3 recoveries)
            return run_experiment_with_retry(config, max_retries=3)
        except:
            handle_meltdown(state)
            return compile_result(state, status="FATAL")


def compile_result(state: SFFLState, status: str) -> ExperimentResult:
    """Compile the final experiment result."""
    return ExperimentResult(
        experiment_id=state.meta.experiment_id,
        status=status,
        best_compression=state.convergence.best_C,
        best_spiral_index=state.convergence.best_n,
        best_point=state.convergence.best_point,
        final_point=state.current_point.x_sqrt,
        final_compression=state.current_point.compression,
        iterations=state.convergence.iteration,
        trajectory_size=len(state.trajectory.history),
        max_self_ref_depth_reached=state.trajectory.self_ref_depth,
        scar_coverage=state.trajectory.cumulative_scar.coverage(),
        dag_nodes=dag.node_count(),
        wall_time_ms=elapsed_ms(state.meta.start_time),
        convergence_diagnosis=diagnose_convergence(state),
        receipt_chain=dag.receipt_chain(),
    )

9. INTEGRATION SPEC — FAMM + DAG + DNA

9.1 FAMM Integration

┌─────────────────────────────────────────────────────────────────────┐
│                    FAMM INTEGRATION POINTS                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. SCAR ACCUMULATION                                               │
│     - Every failed exploration direction → FAMM scar                │
│     - Scar pressure = |Λ_t| (collapse functional)                  │
│     - Scar location = point on S⁷ where failure occurred            │
│     - Integration: state.trajectory.cumulative_scar                 │
│                                                                     │
│  2. GATE CHECKING                                                   │
│     - Before each geodesic step: FAMM gate check                    │
│     - |Λ_t| ≥ ε ? → ADMIT (proceed)                                │
│     - |Λ_t| < ε ? → SCAR (record, skip direction)                  │
│     - Too many scars? → REJECT (trigger recovery)                   │
│     - Integration: evaluate() famm_gate_result field                │
│                                                                     │
│  3. DELAY-LINE STORAGE                                              │
│     - Each checkpoint stored as FAMM cell                           │
│     - delay = f(compression) — better C = longer delay              │
│     - delayMass = Tr(Fisher matrix) — total curvature               │
│     - delayWeight = scar coverage — fraction of space explored      │
│     - Integration: dag_checkpoint() famm_bank.store()               │
│                                                                     │
│  4. BAKER-ANALOGUE INVARIANT                                        │
│     - Maintained: |Λ_t| ≥ ε(X_t) OR Ω(X_t) > 0                     │
│     - Violation → meltdown (PANIC state)                            │
│     - Integration: check_meltdown()                                  │
│                                                                     │
│  5. FRUSTRATION AS SIGNAL                                           │
│     - High frustration = high curvature = promising region          │
│     - Frustration guides direction selection                        │
│     - Integration: scar_filter() prioritizes low-frustration dirs   │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

9.2 DAG Integration

┌─────────────────────────────────────────────────────────────────────┐
│                    DAG INTEGRATION POINTS                           │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. CHECKPOINT NODES                                                │
│     - One DAG node per checkpoint iteration                         │
│     - Node stores: state snapshot + transform + receipt             │
│     - Parent = previous checkpoint (tree structure)                 │
│     - Integration: dag_checkpoint() → dag.insert()                  │
│                                                                     │
│  2. RESUME FROM ANY NODE                                            │
│     - dag.resume(node_id) → checkpoint → state                     │
│     - FAMM cell loaded from checkpoint                              │
│     - RNG state restored deterministically                          │
│     - Integration: recover() → dag.load()                          │
│                                                                     │
│  3. BRANCHING (future: parallel exploration)                        │
│     - Multiple children from same parent = branches                 │
│     - Each branch explores different region                         │
│     - Integration: dag.insert(parent=node_id)                       │
│                                                                     │
│  4. RECEIPT CHAIN                                                   │
│     - Each checkpoint has a SilverSight receipt                     │
│     - Receipt chain = experiment audit log                          │
│     - Integration: compile_receipt() per checkpoint                 │
│                                                                     │
│  5. MELTDOWN RECOVERY                                               │
│     - dag.find_last_good() — walk back from failure                 │
│     - dag.insert_meltdown() — record failure                        │
│     - Integration: handle_meltdown(), recover()                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

9.3 DNA Encoding Integration

┌─────────────────────────────────────────────────────────────────────┐
│                    DNA ENCODING INTEGRATION                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  1. SPIRAL INDEX → DNA                                              │
│     - n → phinary(n) → RLE → DNA bases (A,B,C,G,P,S,T,Z)         │
│     - Used for: compression measurement, checkpoint storage         │
│     - Integration: compression_ratio() → phinary_encode() → RLE()  │
│                                                                     │
│  2. TRAJECTORY ENCODING (strange loop)                              │
│     - trajectory → weighted histogram → p ∈ Δ₇ → √p ∈ S⁷         │
│     - S⁷ point → spiral_index → n_exp → DNA                       │
│     - Integration: self_encode() → spiral_index() → DNA            │
│                                                                     │
│  3. STATE SERIALIZATION                                             │
│     - Full state → DNA encoding → FAMM cell storage                 │
│     - Enables: checkpointing, replication, audit                    │
│     - Integration: serialize_state() → dna_encode()                │
│                                                                     │
│  4. RECEIPT ENCODING                                                │
│     - Each receipt gets DNA-encoded receipt ID                      │
│     - Receipt chain = DNA chain (verifiable)                        │
│     - Integration: compile_receipt() → hash → dna_encode()         │
│                                                                     │
│  5. HACHIMOJI STATE ↔ S⁷                                          │
│     - Stack distribution → Δ₇ → S⁷                                 │
│     - DNA alphabet = 8 Hachimoji states ↔ 8 simplex vertices       │
│     - Integration: current_point.p ↔ Hachimoji stack              │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

10. CONVERGENCE CRITERIA — Summary

10.1 Convergence Detection Matrix

Criterion Condition Meaning Action
Plateau |ΔC| < ε for K iterations No improvement — local max STOP (CONVERGED)
Gradient vanish ||∇C|| < δ Flat region — no direction to go STOP (CONVERGED)
Oscillation std(C) / mean(C) < ε for 10 iters Bouncing without progress STOP (CONVERGED)
Scar coverage Ω.coverage() > 0.99 All space explored or scarred STOP (CONVERGED)
Max iterations k ≥ max_iterations Safety limit reached STOP (HALTED)
Wall time elapsed > max_wall_time Hard timeout STOP (HALTED)
Meltdown Baker-analogue violated System failure PANIC

10.2 Convergence Receipt

{
  "receiptID": "sha256(experiment_result)",
  "expression": "SELF-FINDING FEEDBACK LOOP — Radial Self-Finding Experiment",
  "finalState": "Φ",
  "ticCount": 42,
  "fuelUsed": 1234567,
  "pathCost": 1048576.0,
  "bestCompression": 1048576.0,
  "bestSpiralIndex": 3141592653589,
  "iterations": 42,
  "convergenceType": "PLATEAU",
  "selfRefMaxDepth": 3,
  "scarCoverage": 0.23,
  "dagNodes": 5,
  "libraryRefs": ["SFFL", "FAMM", "DAG", "DNA", "Metric", "Baker", "Chunk"],
  "verified": true,
  "identityCheck": "state.Introspect == expected",
  "receiptChain": ["init_receipt", "iter_10", "iter_20", "iter_30", "iter_40", "final"]
}

11. DETERMINISM GUARANTEE

11.1 Seeding Hierarchy

master_seed (64-bit, user-configurable, default: 0xFEEDFACE42424242)
    │
    ├── iteration_seed(k) = hash(master_seed, k, "iteration")
    │       └── Used for: state initialization at iteration k
    │
    ├── direction_seed(k) = hash(master_seed, k, "directions")
    │       └── Used for: generating N directions at iteration k
    │
    ├── step_seed(k) = hash(master_seed, k, "steps")
    │       └── Used for: step-size sampling along geodesics
    │
    └── recovery_seed(k, attempt) = hash(master_seed, k, "recover", attempt)
            └── Used for: RNG after recovery (different path)

11.2 Determinism Checklist

Source of Non-Determinism Our Fix
Random number generation Seeded hierarchy (above)
Hash ordering Sort all collections before encoding
Floating-point Q16.16 fixed-point for all stored values
Memory addresses Encode logical structure, not addresses
Timing Snapshot state, don't encode timing
Parallel execution Deterministic scheduling (round-robin)
OS differences Pure computation, no OS calls

11.3 Reproducibility Proof Sketch

Theorem: The SFFL experiment is fully reproducible.

Proof: 
  Given: same master_seed, same config, same code
  Then: 
    1. All RNG sequences are identical (seeded hierarchy)
    2. All direction generations are identical
    3. All geodesic walks follow the same path
    4. All compression measurements are identical (fixed-point)
    5. All FAMM gate decisions are identical
    6. All state transitions follow the same path
  Therefore: The entire experiment trace is deterministic.
  
  Corollary: Two runs with the same seed produce identical:
    - Trajectory history
    - Convergence point
    - Receipt chain
    - DAG structure
    - Final result

12. STATE MACHINE DIAGRAM (ASCII)

                              ┌─────────────┐
                              │    IDLE     │
                              └──────┬──────┘
                                     │ init()
                                     ▼
                              ┌─────────────┐
    ┌────────────────────────>│    INIT     │
    │  (recover resume)       └──────┬──────┘
    │                                │
    │    ┌───────────────────────────┘
    │    │
    │    ▼                          ┌──────────┐
    │ ┌──────────┐   meltdown      │  PANIC   │
    │ │ EXPLORE  │────────────────>│          │
    │ └────┬─────┘                 │ (unrecov)│
    │      │ directions            └────┬─────┘
    │      │ generated                    │
    │      ▼                              │ scar_dump
    │ ┌──────────┐                         ▼
    │ │ EVALUATE │                  ┌──────────┐
    │ └────┬─────┘                  │   END    │
    │      │ compression              └──────────┘
    │      │ measured                    ▲
    │      ▼                             │
    │ ┌──────────┐   plateau × K   ┌──────────┐
    │ │ SELECT   │────────────────>│ CONVERGED│
    │ │ BEST     │                 │          │
    │ └────┬─────┘                 │ report() │
    │      │ best found             └────┬─────┘
    │      ▼                             │
    │ ┌──────────┐                       │
    │ │ SELF-    │                       │
    │ │ ENCODE   │                       │
    │ └────┬─────┘                       │
    │      │ trajectory                  │
    │      │ encoded                     │
    │      ▼                             │
    │ ┌──────────┐   max_iter      ┌──────────┐
    │ │  META    │────────────────>│  HALTED  │
    │ │ DECIDE   │                 │          │
    │ └────┬─────┘                 │ report() │
    │      │ decision              └────┬─────┘
    │      │ made                         │
    │      └─────────────────────────────┘
    │           (report → END)
    │
    └─────── (convergence check: if not converged, loop back)


    Any state ──failure──> RECOVER ──success──> [previous state]
                           RECOVER ──fail────> PANIC

13. THE COMPLETE UPDATE EQUATIONS

13.1 Manifold Position Update

x_{k+1} = { γ_{d*}(t*)   if ASCEND  (follow best direction)
          { x_exp        if STAY    (self-encoded trajectory)
          { x_best       if CONVERGE (best point overall)

where:
  d* = argmax_{d_i} max_j C(spiral_index(γ_{d_i}(t_j)))
  t* = argmax_j C(spiral_index(γ_{d*}(t_j)))
  x_exp = √p_traj  where p_traj = weighted_histogram(trajectory)
  x_best = argmax_{x ∈ {all explored}} C(spiral_index(x))

13.2 Compression Update

C_{k+1} = C(spiral_index(x_{k+1}))

C_best = max(C_best, C_{k+1})

plateau_count = { 0                 if C_{k+1} > C_k + ε
                { plateau_count + 1  otherwise

13.3 Trajectory Update

T_{k+1} = T_k  { (d_i, t_j, C_ij) : i∈[1,N], j∈[1,M] }

if |T_{k+1}| > budget:
    T_{k+1} = { encode_summary(T_k[:-budget]) }  T_k[-budget:]

n_exp = spiral_index( encode(T_{k+1}) )

depth_{k+1} = { depth_k + 1   if n_exp ≠ n_k
              { 0             if depth_k ≥ D

13.4 Scar Field Update

Ω_{k+1} = Ω_k + Σ_{failed explorations} Scar(pressure=|Λ|, location=x)

where Λ = collapse_functional(state, x) at each failed point

13.5 Radial State Update

v_{k+1} = μ · v_k + (1-μ) · (log₂(n_{k+1}+1) - log₂(n_k+1))

mode_{k+1} = { OUTWARD   if v_{k+1} > 0.1
             { INWARD    if v_{k+1} < -0.1
             { OSCILLATE otherwise

13.6 Checkpoint Update

node_{k+1} = DAGNode(
    parent = node_k,
    point = x_{k+1},
    compression = C_{k+1},
    transform = eigenstructure_transform(Fisher(x_{k+1})),
    rng_state = rng.snapshot(),
)

14. APPENDIX: GLOSSARY

Term Meaning
SFFL Self-Finding Feedback Loop (this system)
S⁷ 7-sphere (Fisher information manifold in √p-coordinates)
Δ₇ 7-simplex (probability distributions over 8 states)
Φ-corkscrew Spiral f(n) = (√n·cos(nψ), √n·sin(nψ)) with ψ = 2π/Φ²
spiral_index Map from S⁷ point to closest spiral point index
C(n) Compression ratio = original_size / RLE(phinary(n))_size
strange loop Search trajectory becomes the next search's state
self_ref_depth Nesting level of self-reference (capped at D)
scar Recorded failure region on the manifold (FAMM)
Baker-analogue Invariant: |Λ| ≥ ε OR Ω > 0 (no silent failures)
FAMM Frustrated Access Memory Module (delay-line memory)
DAG Directed Acyclic Graph of checkpoints
FSDU FAMM Scar Differential Update
Hachimoji 8-symbol DNA alphabet: A,B,C,G,P,S,T,Z ↔ Φ,Λ,Ρ,Κ,Ω,Σ,Π,Ζ

Design completed. Ready for implementation.

Version: 1.0 Date: 2025-06-23 System: SFFL v1 — Radial Self-Finding Experiment