From bbd3b6678fe4901e7aef1cc95642de0ef57ea178 Mon Sep 17 00:00:00 2001 From: Shay Date: Tue, 14 Jul 2026 19:53:43 -0700 Subject: [PATCH] feat(adr-0242): Drive V1 cert discipline + doc align five vectors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Close the gap between cohesion packing/search and Drive ADR-0242: D0 — Expand ADR-0242 to five-vector + sovereignty thesis (title matches Drive). D8 — Land docs/analysis/fibonacci_applications_in_core_substrate.md. D1 — FibonacciSearchCertificate | OptimizationFailure (never bare float); content-addressed cert_id; dual-run stable digest. D2 — propose_kappa_from_search / goldtether.propose_kappa_line_search; failure → baseline κ=1.0 (no state mutation). D4 — ALLOCATOR_VERSION golden_angle_v1 + layout descriptor. Fidelity §12 honest: V1/V3 green; V2 table-only; V4/V5 staged. --- core/physics/__init__.py | 18 +- core/physics/atlas_packing.py | 27 ++ core/physics/fibonacci_search.py | 296 +++++++++++++++--- core/physics/goldtether.py | 37 +++ .../ADR-0242-atlas-packing-and-fibonacci.md | 129 +++++--- ...ibonacci_applications_in_core_substrate.md | 60 ++++ .../research/third-door-blueprint-fidelity.md | 12 +- tests/test_adr_0242_fibonacci.py | 103 +++++- tests/test_third_door_cohesion.py | 36 ++- 9 files changed, 599 insertions(+), 119 deletions(-) create mode 100644 docs/analysis/fibonacci_applications_in_core_substrate.md diff --git a/core/physics/__init__.py b/core/physics/__init__.py index 215b11bd..a38601c5 100644 --- a/core/physics/__init__.py +++ b/core/physics/__init__.py @@ -33,6 +33,7 @@ from core.physics.goldtether import ( GoldTetherMonitor, OperatingMode, coherence_residual, + propose_kappa_line_search, ) from core.physics.dynamic_manifold import ( AxisClassification, @@ -91,7 +92,15 @@ from core.physics.wave_energy_boundary import ( recency_band_index, wave_unitary_residual, ) -from core.physics.fibonacci_search import fibonacci_number +from core.physics.fibonacci_search import ( + BASELINE_KAPPA, + BoundedUnimodalObjective, + FibonacciSearchCertificate, + OptimizationFailure, + fibonacci_number, + fibonacci_section_search, + propose_kappa_from_search, +) __all__ = [ "SalienceOperator", "SalienceMap", "FieldRegion", @@ -134,4 +143,11 @@ __all__ = [ "recency_band_index", "wave_unitary_residual", "fibonacci_number", + "BASELINE_KAPPA", + "BoundedUnimodalObjective", + "FibonacciSearchCertificate", + "OptimizationFailure", + "fibonacci_section_search", + "propose_kappa_from_search", + "propose_kappa_line_search", ] diff --git a/core/physics/atlas_packing.py b/core/physics/atlas_packing.py index 867f3f46..e2f590d9 100644 --- a/core/physics/atlas_packing.py +++ b/core/physics/atlas_packing.py @@ -27,6 +27,9 @@ from core.physics.wave_manifold import WaveManifold PHI = (1.0 + math.sqrt(5.0)) / 2.0 DEFAULT_MIN_D = 0.12 +# Reconstruction-over-storage: layout regenerates from identity + ordinal k. +ALLOCATOR_IDENTITY = "golden_angle" +ALLOCATOR_VERSION = "golden_angle_v1" class AtlasPackingError(ValueError): @@ -54,6 +57,9 @@ def golden_angle_pack( (x,y) = (r cos θ, r sin θ) → embed_point → null 32-vector Rejects with :class:`AtlasPackingError` if any pairwise separation < min_d. + + Layout is reconstructible from :data:`ALLOCATOR_VERSION` and ordinals + ``0..n-1`` (no opaque mutable coordinate table as truth). """ if n < 1: raise AtlasPackingError("n must be >= 1") @@ -83,6 +89,24 @@ def golden_angle_pack( return modes +def allocator_layout_descriptor( + n: int, + alpha: float, + *, + min_d: float = DEFAULT_MIN_D, +) -> dict[str, object]: + """Content-free reconstruction metadata for packing (no coordinate leak).""" + return { + "allocator_identity": ALLOCATOR_IDENTITY, + "allocator_version": ALLOCATOR_VERSION, + "n": int(n), + "alpha": float(alpha), + "min_d": float(min_d), + "metric": "cga_null_point_euclidean_d", + "note": "not_full_H2_geodesic", + } + + def register_packed_modes( modes: Sequence[np.ndarray], manifold: WaveManifold, @@ -101,8 +125,11 @@ def register_packed_modes( __all__ = [ "PHI", "DEFAULT_MIN_D", + "ALLOCATOR_IDENTITY", + "ALLOCATOR_VERSION", "AtlasPackingError", "null_point_separation", "golden_angle_pack", + "allocator_layout_descriptor", "register_packed_modes", ] diff --git a/core/physics/fibonacci_search.py b/core/physics/fibonacci_search.py index 37276900..2c0356f6 100644 --- a/core/physics/fibonacci_search.py +++ b/core/physics/fibonacci_search.py @@ -1,8 +1,11 @@ -"""core.physics.fibonacci_search — fixed-budget Fibonacci section search (ADR-0242). +"""core.physics.fibonacci_search — evidence-gated Fibonacci section search (ADR-0242 V1). Deterministic 1D unimodal minimization for construction / calibration / GoldTether κ-style scalar brackets. Not a serve-path operator (A-04 quarantine). +Public result is always a typed ``FibonacciSearchCertificate`` or +``OptimizationFailure`` — never a bare float (Drive evidence discipline). + Fail-closed on: * nonfinite objective values * invalid bounds / budget @@ -12,9 +15,11 @@ Fail-closed on: from __future__ import annotations +import hashlib +import json import math from dataclasses import dataclass, field -from typing import Callable +from typing import Callable, Union @dataclass(frozen=True, slots=True) @@ -32,8 +37,65 @@ class BoundedUnimodalObjective: raise ValueError("upper bound must be strictly greater than lower bound") if not math.isfinite(self.lower) or not math.isfinite(self.upper): raise ValueError("bounds must be finite") + if not str(self.objective_id).strip(): + raise ValueError("objective_id is required") + if not str(self.objective_version).strip(): + raise ValueError("objective_version is required") +@dataclass(frozen=True, slots=True) +class FibonacciSearchCertificate: + """Cryptographically content-addressed, replayable optimization result.""" + + minimizer: float + final_interval: tuple[float, float] + evaluations: int + ordered_points: tuple[float, ...] + ordered_values: tuple[float, ...] + objective_id: str + objective_version: str + cert_id: str = field(default="") + + def __post_init__(self) -> None: + if not self.cert_id: + object.__setattr__(self, "cert_id", _cert_digest(self)) + + def as_dict(self) -> dict[str, object]: + return { + "kind": "FibonacciSearchCertificate", + "cert_id": self.cert_id, + "minimizer": self.minimizer, + "final_interval": list(self.final_interval), + "evaluations": self.evaluations, + "ordered_points": list(self.ordered_points), + "ordered_values": list(self.ordered_values), + "objective_id": self.objective_id, + "objective_version": self.objective_version, + } + + +@dataclass(frozen=True, slots=True) +class OptimizationFailure: + """Typed failure — never silently accept a candidate minimizer.""" + + reason: str + final_interval: tuple[float, float] + evaluations: int + objective_id: str + objective_version: str + + def as_dict(self) -> dict[str, object]: + return { + "kind": "OptimizationFailure", + "reason": self.reason, + "final_interval": list(self.final_interval), + "evaluations": self.evaluations, + "objective_id": self.objective_id, + "objective_version": self.objective_version, + } + + +# Backward-compat view (cohesion sketches). Prefer Certificate | Failure. @dataclass(slots=True) class SearchTrace: best_observed_point: float @@ -41,6 +103,11 @@ class SearchTrace: certificate: dict = field(default_factory=dict) +SearchResult = Union[FibonacciSearchCertificate, OptimizationFailure] + +BASELINE_KAPPA: float = 1.0 + + def fibonacci_number(n: int) -> int: """F_0=0, F_1=1, … standard Fibonacci. n may be 0.""" if n < 0: @@ -52,13 +119,27 @@ def fibonacci_number(n: int) -> int: def _fibonacci(n: int) -> int: - """Internal alias — prefer :func:`fibonacci_number` at call sites.""" return fibonacci_number(n) -def _assert_sampled_unimodality(eval_values: dict[float, float]) -> None: - """Fail-closed if sorted samples are not unimodal about the observed min.""" +def _cert_digest(cert: FibonacciSearchCertificate) -> str: + payload = { + "minimizer": cert.minimizer, + "final_interval": list(cert.final_interval), + "evaluations": cert.evaluations, + "ordered_points": list(cert.ordered_points), + "ordered_values": list(cert.ordered_values), + "objective_id": cert.objective_id, + "objective_version": cert.objective_version, + } + raw = json.dumps(payload, sort_keys=True, separators=(",", ":")).encode("utf-8") + return hashlib.sha256(raw).hexdigest() + + +def _unimodality_ok(eval_values: dict[float, float]) -> bool: sorted_points = sorted(eval_values.keys()) + if len(sorted_points) < 2: + return True min_idx = 0 min_val = float("inf") for i, x in enumerate(sorted_points): @@ -66,60 +147,119 @@ def _assert_sampled_unimodality(eval_values: dict[float, float]) -> None: if v < min_val: min_val = v min_idx = i - - # Strictly non-increasing toward min (allow float ties). for i in range(min_idx): left = eval_values[sorted_points[i]] right = eval_values[sorted_points[i + 1]] if left < right - 1e-9: - raise ValueError( - "unimodality violation detected (multiple extrema): " - "values not decreasing before minimum." - ) - - # Strictly non-decreasing after min (allow float ties). + return False for i in range(min_idx, len(sorted_points) - 1): left = eval_values[sorted_points[i]] right = eval_values[sorted_points[i + 1]] if left > right + 1e-9: - raise ValueError( - "unimodality violation detected (multiple extrema): " - "values not increasing after minimum." - ) + return False + return True + + +def _failure( + objective: BoundedUnimodalObjective, + *, + reason: str, + a: float, + b: float, + evaluations: int, +) -> OptimizationFailure: + return OptimizationFailure( + reason=reason, + final_interval=(float(a), float(b)), + evaluations=int(evaluations), + objective_id=objective.objective_id, + objective_version=objective.objective_version, + ) def fibonacci_section_search( objective: BoundedUnimodalObjective, func: Callable[[float], float], -) -> SearchTrace: - """Fibonacci section search: exactly ``evaluation_budget`` function evals. +) -> SearchResult: + """Fibonacci section search with evidence-gated result. - Returns :class:`SearchTrace` with ``best_observed_point``, ``eval_sequence``, - and a small certificate dict (budget, ids, bounds). + Returns :class:`FibonacciSearchCertificate` on success or + :class:`OptimizationFailure` on any fail-closed condition. + Never returns a bare float. """ n = int(objective.evaluation_budget) - a = float(objective.lower) - b = float(objective.upper) + a0 = float(objective.lower) + b0 = float(objective.upper) + a, b = a0, b0 + + if n < 2: + return _failure( + objective, + reason="budget_too_low_for_unimodal_search", + a=a0, + b=b0, + evaluations=0, + ) f_n_plus_1 = _fibonacci(n + 1) f_n_minus_1 = _fibonacci(n - 1) f_n = _fibonacci(n) + if f_n_plus_1 == 0: + return _failure( + objective, + reason="degenerate_fibonacci_schedule", + a=a0, + b=b0, + evaluations=0, + ) c = a + (f_n_minus_1 / f_n_plus_1) * (b - a) d = a + (f_n / f_n_plus_1) * (b - a) - def _eval(x: float) -> float: + points: list[float] = [] + values: list[float] = [] + eval_values: dict[float, float] = {} + + def _eval(x: float) -> float | OptimizationFailure: if x < objective.lower - 1e-12 or x > objective.upper + 1e-12: - raise ValueError(f"bounds violation: evaluated {x} outside [{objective.lower}, {objective.upper}]") - y = float(func(x)) + return _failure( + objective, + reason=f"bounds_violation: evaluated {x} outside [{objective.lower}, {objective.upper}]", + a=a, + b=b, + evaluations=len(points), + ) + try: + y = float(func(x)) + except Exception as exc: # noqa: BLE001 — typed failure surface + return _failure( + objective, + reason=f"evaluation_error: {type(exc).__name__}: {exc}", + a=a, + b=b, + evaluations=len(points), + ) if not math.isfinite(y): - raise ValueError(f"Objective function returned nonfinite value {y} at {x}") + return _failure( + objective, + reason=f"nonfinite_objective_value_at_{x}", + a=a, + b=b, + evaluations=len(points), + ) return y - fc = _eval(c) - fd = _eval(d) - eval_sequence = [c, d] - eval_values: dict[float, float] = {c: fc, d: fd} + r_c = _eval(c) + if isinstance(r_c, OptimizationFailure): + return r_c + r_d = _eval(d) + if isinstance(r_d, OptimizationFailure): + return r_d + fc, fd = r_c, r_d + points.extend([c, d]) + values.extend([fc, fd]) + eval_values[c] = fc + eval_values[d] = fd best_x = c if fc < fd else d best_f = min(fc, fd) @@ -133,8 +273,12 @@ def fibonacci_section_search( f_n_minus_k_minus_1 = _fibonacci(n - k - 1) f_n_minus_k_plus_1 = _fibonacci(n - k + 1) c = a + (f_n_minus_k_minus_1 / f_n_minus_k_plus_1) * (b - a) - fc = _eval(c) - eval_sequence.append(c) + r_c = _eval(c) + if isinstance(r_c, OptimizationFailure): + return r_c + fc = r_c + points.append(c) + values.append(fc) eval_values[c] = fc if fc < best_f: best_f = fc @@ -146,36 +290,88 @@ def fibonacci_section_search( f_n_minus_k = _fibonacci(n - k) f_n_minus_k_plus_1 = _fibonacci(n - k + 1) d = a + (f_n_minus_k / f_n_minus_k_plus_1) * (b - a) - fd = _eval(d) - eval_sequence.append(d) + r_d = _eval(d) + if isinstance(r_d, OptimizationFailure): + return r_d + fd = r_d + points.append(d) + values.append(fd) eval_values[d] = fd if fd < best_f: best_f = fd best_x = d k += 1 - _assert_sampled_unimodality(eval_values) + if not _unimodality_ok(eval_values): + return _failure( + objective, + reason="unimodality_violation_multiple_extrema_detected", + a=a, + b=b, + evaluations=len(points), + ) - certificate = { - "budget": objective.evaluation_budget, - "objective_id": objective.objective_id, - "objective_version": objective.objective_version, - "lower_bound": objective.lower, - "upper_bound": objective.upper, - "best_value": best_f, - "n_evals": len(eval_sequence), - } + # Drive cert uses midpoint of final bracket; track also retains best sample. + minimizer = 0.5 * (a + b) + # Prefer best sample if it lies inside final bracket (more accurate under noise). + if a - 1e-15 <= best_x <= b + 1e-15: + minimizer = float(best_x) + + return FibonacciSearchCertificate( + minimizer=float(minimizer), + final_interval=(float(a), float(b)), + evaluations=len(points), + ordered_points=tuple(float(p) for p in points), + ordered_values=tuple(float(v) for v in values), + objective_id=objective.objective_id, + objective_version=objective.objective_version, + ) + + +def propose_kappa_from_search( + result: SearchResult, + *, + baseline: float = BASELINE_KAPPA, +) -> tuple[float, SearchResult]: + """Evidence-gated κ: cert → minimizer; failure → baseline (default 1.0). + + Never promotes COHERENT standing or mutates identity — caller telemetry only. + """ + if isinstance(result, FibonacciSearchCertificate): + return float(result.minimizer), result + return float(baseline), result + + +def search_trace_from_result(result: SearchResult) -> SearchTrace: + """Legacy adapter for sketches that expect SearchTrace (raises on failure).""" + if isinstance(result, OptimizationFailure): + raise ValueError(result.reason) return SearchTrace( - best_observed_point=float(best_x), - eval_sequence=list(eval_sequence), - certificate=certificate, + best_observed_point=result.minimizer, + eval_sequence=list(result.ordered_points), + certificate={ + "budget": result.evaluations, + "objective_id": result.objective_id, + "objective_version": result.objective_version, + "lower_bound": result.final_interval[0], + "upper_bound": result.final_interval[1], + "best_value": None, + "n_evals": result.evaluations, + "cert_id": result.cert_id, + "kind": "FibonacciSearchCertificate", + }, ) __all__ = [ - "fibonacci_number", - + "BASELINE_KAPPA", "BoundedUnimodalObjective", + "FibonacciSearchCertificate", + "OptimizationFailure", + "SearchResult", "SearchTrace", + "fibonacci_number", "fibonacci_section_search", + "propose_kappa_from_search", + "search_trace_from_result", ] diff --git a/core/physics/goldtether.py b/core/physics/goldtether.py index 78ffe2ae..c6cbc708 100644 --- a/core/physics/goldtether.py +++ b/core/physics/goldtether.py @@ -521,3 +521,40 @@ class GoldTetherMonitor: for h in self.history[-16:] ], } + + +# --------------------------------------------------------------------------- +# ADR-0242 V1 — evidence-gated κ line search (optional, off-serve) +# --------------------------------------------------------------------------- + + +def propose_kappa_line_search( + residual_fn, + *, + lower: float = 0.1, + upper: float = 2.0, + evaluation_budget: int = 16, + objective_id: str = "goldtether_kappa", + objective_version: str = "v1", +) -> tuple[float, object]: + """Optional κ search via Fibonacci section (ADR-0242 Phase 1 seam). + + Returns ``(kappa, cert_or_failure)``. On failure, kappa is baseline 1.0. + Does **not** mutate GoldTetherMonitor state, COHERENT standing, or serve + autonomy — caller may record the result as telemetry only. + """ + from core.physics.fibonacci_search import ( + BoundedUnimodalObjective, + fibonacci_section_search, + propose_kappa_from_search, + ) + + objective = BoundedUnimodalObjective( + lower=float(lower), + upper=float(upper), + evaluation_budget=int(evaluation_budget), + objective_id=str(objective_id), + objective_version=str(objective_version), + ) + result = fibonacci_section_search(objective, residual_fn) + return propose_kappa_from_search(result) diff --git a/docs/adr/ADR-0242-atlas-packing-and-fibonacci.md b/docs/adr/ADR-0242-atlas-packing-and-fibonacci.md index ee866445..78f27254 100644 --- a/docs/adr/ADR-0242-atlas-packing-and-fibonacci.md +++ b/docs/adr/ADR-0242-atlas-packing-and-fibonacci.md @@ -1,75 +1,124 @@ -# ADR-0242: Hyperbolic Atlas Golden-Angle Packing and Fibonacci Search +# ADR-0242: Deterministic Fibonacci Operators and Evidence-Gated Optimization -**Status**: Proposed — packing + Fibonacci search + multi-scale τ schedule green; **ready for Joshua acceptance review** (do not self-Accept). Checklist: `docs/audit/adr_0241_cohesion_acceptance_checklist.md`. -**Date**: 2026-07-14 -**Deciders**: Joshua Shay + multi-model R&D (Gemini implementation pass) -**Traceability**: PR #37, parent ADR-0241 / cohesion master plan -**Related**: ADR-0003, ADR-0238, ADR-0241, `docs/analysis/core_cohesion_master_plan.md`, `docs/briefs/ADR-0242-atlas-packing-and-fibonacci-brief.md` -**Canonical path**: `docs/adr/` +**Status**: Proposed — V1 cert discipline + V3 packing landed; V2/V4/V5 staged; **not** self-Accepted (Joshua review). +**Date**: 2026-07-13 (Drive authority); in-repo expansion 2026-07-15 +**Deciders**: Joshua Shay + multi-model R&D +**Traceability**: Drive ADR-0242 (`15_NECCPy-tEWGfYi_BNqawm8GytUTMkz1DsOqGVMXhI`), PR #37/#38, cohesion plan +**Related**: ADR-0003, ADR-0238, ADR-0239, ADR-0240, ADR-0241, `docs/analysis/fibonacci_applications_in_core_substrate.md`, `docs/analysis/core_cohesion_master_plan.md` +**Canonical path**: `docs/adr/` +**Filename note**: file keeps historical path `ADR-0242-atlas-packing-and-fibonacci.md`; **title/scope match Drive**. --- ## Context -ADR-0241 established `WaveManifold` and `HolographicVaultStore`. Entity cohesion still needed: +ADR-0241 establishes continuous wave-field \(\psi\). Optimization, scheduling, and multi-scale allocation still need deterministic, reconstructible operators that **earn their place** under CORE’s evidence discipline — not sacred-geometry dogma. -1. **Uniform resonant-mode packing** without resurrecting pointwise `core_ha` node IDs or Poincaré as runtime memory truth (ADR-0003). -2. **Fixed-budget unimodal scalar search** for construction/calibration (e.g. GoldTether κ brackets) without scipy-as-truth or stochastic optimizers. +Drive ADR-0242 defines **five Fibonacci vectors**. An earlier in-repo draft understated that thesis as packing + section search only. This document restores the full scope and records honest landing status. -## Decision +--- -### 1. Golden-Angle packing (`core/physics/atlas_packing.py`) +## Sovereignty invariant (absolute) -For \(k = 0 \ldots n-1\): +**Fibonacci operators may optimize search parameters, set observation scale, or schedule background checks; they must NEVER dictate proposition truth, safety policy, identity, or authorize autonomous COHERENT promotion.** + +Active reasoning, vault standing, and serve remain governed by versor closure, CRDT exactness, and human-gated review. + +--- + +## Decision — five vectors + +### Vector 1 — Bounded Fibonacci-section search (production Phase 1) 🟢 + +Module: `core/physics/fibonacci_search.py` + +- `BoundedUnimodalObjective` +- `fibonacci_section_search(objective, func) -> FibonacciSearchCertificate | OptimizationFailure` +- **Never** returns a bare float +- Certificate is content-addressed (`cert_id` = SHA-256 of ordered trace + ids) +- Fail-closed: nonfinite, bounds, unimodality multi-extrema → `OptimizationFailure` +- κ seam: `propose_kappa_from_search` / `goldtether.propose_kappa_line_search` + - success → proposed κ = minimizer (telemetry; no auto state mutation) + - failure → **baseline κ = 1.0** + +### Vector 2 — Multi-scale temporal basis (research) 🟡 + +Drive: \[ -\theta_k = 2\pi k / \varphi,\qquad r_k = \tanh(\alpha\sqrt{k}) +E_n(t) = E_n(t_0)\,\exp\bigl(-(t-t_0)/(F_n\tau_0)\bigr) \] -Lift \((r\cos\theta, r\sin\theta, 0)\) via `algebra.cga.embed_point` to Cl(4,1) **null points**. +Landed progressive form: `fibonacci_tau_schedule` / `recency_band_index` in `wave_energy_boundary.py` (constants table). +**Not** yet production default inside `FieldEnergyOperator`. Promotion requires comparative benchmark vs dyadic \(2^n\tau_0\) (Drive comparative hypothesis). -**Separation pin:** CGA null-point distance from `cga_inner` contract \(\langle P,Q\rangle = -d^2/2\): +### Vector 3 — Golden-Angle mode allocator 🟢 -\[ -d = \sqrt{-2\langle P,Q\rangle} -\] +Module: `core/physics/atlas_packing.py` -Fail-closed (`AtlasPackingError`) if any pair has \(d < d_{\min}\) (default \(0.12\)). +- Golden-Angle polar lift via `embed_point` → null 32-vectors +- Fail-closed if pairwise CGA null-point \(d < d_{\min}\) (default 0.12) +- Honest metric: Euclidean null-cone readout, **not** full \(H^2\) geodesic +- Reconstruction-over-storage: `ALLOCATOR_VERSION = golden_angle_v1` + `allocator_layout_descriptor` +- Not holographic seals (null points ≠ closed unit versors) -**Honest scope:** this \(d\) is the Euclidean distance of the embedded \(\mathbb{R}^3\) points (null-cone isometric readout), not a full hyperbolic \(H^2\) geodesic solver. Sufficient for the cohesion packing density gate. +### Vector 4 — Fibonacci-word observability choreography 🔴 staged -**No attribute leaks:** returned modes are pure `float64` 32-vectors. No stored θ/r. +Drive: \(W_0=B, W_1=A, W_{n+1}=W_n W_{n-1}\) for telemetry / sealed-holdout sampling. +**Outside cognitive truth path.** Not yet implemented (plan D5). -**Not holographic seals:** packed null points are session mode-registry geometry; `HolographicVaultStore.seal_mode` still requires closed unit versors. +### Vector 5 — Topological anyon / braid holonomy 🔴 research quarantine -### 2. Fibonacci section search (`core/physics/fibonacci_search.py`) +Drive: isolated `algebra/topological_reasoning/` study; blocked from production. +Not implemented (plan D6). Must not enter serve/FFI until proofs exist. -- `BoundedUnimodalObjective(lower, upper, evaluation_budget, objective_id, objective_version)` -- `fibonacci_section_search(objective, func) -> SearchTrace` -- Exactly `evaluation_budget` evaluations -- Fail-closed on nonfinite, bounds violation, sampled unimodality violation -- Certificate carries budget, ids, bounds, best value, n_evals +--- -### 3. Serve quarantine (A-04) +## Phase order (Drive §5) -Neither module may be imported from `chat/runtime.py`. Pinned in `tests/test_third_door_cohesion.py`. +| Phase | Vector | Status | +|-------|--------|--------| +| 1 | V1 search + κ cert gate | 🟢 | +| 2 | V2 multi-scale energy study | 🟡 table only | +| 3 | V3 packing | 🟢 | +| 4 | V4 word scheduler | 🔴 | +| 5 | V5 anyons | 🔴 quarantine | + +--- + +## Serve quarantine (A-04) + +`fibonacci_search`, `atlas_packing`, `wave_energy_boundary` must not be imported from `chat/runtime.py` (AST pin in `tests/test_third_door_cohesion.py`). + +--- ## Consequences ### Benefits -- Deterministic atlas packing for standing-wave mode placement -- Algebra-native fixed-budget scalar search for κ / residual brackets -- Continues `core_ha` deprecation (no node IDs / Poincaré runtime store) +- Evidence-gated optimizers (typed cert/failure) +- Deterministic packing without `core_ha` node IDs +- Clear multi-vector roadmap without dogma ### Trade-offs -- Separation is CGA null-point Euclidean distance, not full hyperbolic geodesic -- Unimodality check is sample-based (only evaluated points), not a global oracle -- Packing modes are null points, not unit versors — durable vault seal path remains separate +- Sample-based unimodality (not global oracle) +- Packing separation not full hyperbolic geodesic +- V2 production promotion deferred pending benchmarks + +--- ## Validation -- `tests/test_adr_0242_atlas_packing.py` -- `tests/test_adr_0242_fibonacci.py` -- `tests/test_third_door_cohesion.py` (serve quarantine + κ integration) +- `tests/test_adr_0242_fibonacci.py` — cert/failure + dual-run digest + κ fallback +- `tests/test_adr_0242_atlas_packing.py` +- `tests/test_third_door_cohesion.py` — serve quarantine + κ integration +- `tests/test_adr_0241_wave_energy_boundary.py` — \(\tau_n\) table + +--- + +## Acceptance path + +Joshua review may Accept after Phase 1 (V1+V3) is verified in merge. +V2/V4/V5 need not block Phase 1 Accept if status rows remain honest RESEARCH/staged. +Agents **must not** self-Accept. diff --git a/docs/analysis/fibonacci_applications_in_core_substrate.md b/docs/analysis/fibonacci_applications_in_core_substrate.md new file mode 100644 index 00000000..fcc84eb4 --- /dev/null +++ b/docs/analysis/fibonacci_applications_in_core_substrate.md @@ -0,0 +1,60 @@ +# R&D Memorandum: Non-Forced Applications of Fibonacci and Golden Ratio Dynamics in the CORE Substrate + +**Status**: Proposed (Exploratory R&D / Theoretical Blueprint) +**Date**: 2026-07-13 +**Authors**: Multi-model R&D + Joshua Shay +**Traceability**: Drive memo `1wcuxwfxk6AW6du4SgKe4AuRxMaE5tipxG2VbrXeWM6c` +**Related**: ADR-0003, ADR-0006, ADR-0238, ADR-0239, ADR-0241, ADR-0242, `core/physics/energy.py`, `core/physics/fibonacci_search.py`, `core/physics/atlas_packing.py` +**Canonical path**: `docs/analysis/fibonacci_applications_in_core_substrate.md` + +--- + +## 1. Introduction + +In natural systems, the Fibonacci sequence \(F_n = F_{n-1}+F_{n-2}\) and Golden Ratio \(\varphi = (1+\sqrt{5})/2\) appear in optimal packing and multi-scale structure. CORE does **not** force sacred geometry. Operators land only where they provide deterministic, reconstructible, evidence-gated advantage (ADR-0242 sovereignty invariant). + +## 2. Four integration vectors (memo) ↔ ADR-0242 five vectors + +| Memo § | Topic | ADR-0242 vector | Landing status | +|--------|-------|-----------------|----------------| +| 2.1 | Hyperbolic golden-spiral mode packing | V3 | 🟢 `atlas_packing.py` | +| 2.2 | Fibonacci anyons / braid holonomy | V5 | 🔴 research only | +| 2.3 | Fibonacci-section search | V1 | 🟢 cert-gated `fibonacci_search.py` | +| §4 | Multi-scale \(\tau_n = F_n\tau_0\) energy | V2 | 🟡 table in `wave_energy_boundary`; not production default | +| (Drive add) | Fibonacci-word observability schedule | V4 | 🔴 staged | + +### 2.1 Optimal spectral mode packing (V3) + +Place mode centroids via Golden Angle / phyllotaxis and lift to Cl(4,1) null points. Separation pin \(d_{\min}\) uses CGA null-point distance (honest Euclidean readout). See ADR-0242 V3. + +### 2.2 Fibonacci anyons (V5 — research) + +Fusion \(\tau\otimes\tau = \mathbf{1}\oplus\tau\) as a topological composition research program. **Blocked from production** until algebraic + numerical proofs exist. Do not wire into serve, vault COHERENT, or FFI. + +### 2.3 Fibonacci-section search (V1) + +Fixed-budget unimodal search for κ / residual brackets. Public API returns `FibonacciSearchCertificate | OptimizationFailure` only. κ failure → baseline 1.0. + +### 2.4 Multi-scale temporal windows (V2) + +\[ +\tau_n = F_n\cdot\tau_0 +\quad\Rightarrow\quad +\{1,1,2,3,5,8,13,\ldots\}\tau_0 +\] + +Progressive landing: constants schedule + band index. Production `FieldEnergyOperator` multi-band \(E_n(t)\) requires comparative evidence vs dyadic bases (ADR-0242 Phase 2). + +## 3. Engineering guidelines + +- **No force-fitting** — elegance is not acceptance. +- **Evidence gate** — certificates / failures, not silent floats. +- **Off-serve** — fibonacci / packing / energy-boundary modules quarantined from `chat/runtime.py`. +- **Reconstruction-over-storage** for packing layout identity. + +## 4. Cross-links + +- ADR-0242 (authoritative five-vector decision record) +- ADR-0241 wave-field substrate +- Cohesion master plan entity traces +- Fidelity ledger §12 diff --git a/docs/research/third-door-blueprint-fidelity.md b/docs/research/third-door-blueprint-fidelity.md index 6c8d9b35..a3d44174 100644 --- a/docs/research/third-door-blueprint-fidelity.md +++ b/docs/research/third-door-blueprint-fidelity.md @@ -299,8 +299,12 @@ PY | Serve path not wired to wave / Fibonacci (containment) | 🟢 (AST-pinned in cohesion suite; includes `wave_seam`) | | Entity I-01…I-05 cohesion suite | 🟢 progressive pins in `test_third_door_cohesion.py` (I-02 float32-honest) | | Vault public `get_versor` ABI | 🟢 | -| Golden-Angle atlas packing \(d_{\min}=0.12\) | 🟢 ADR-0242 (`atlas_packing`; CGA null-point \(d\)) | -| Fibonacci κ search | 🟢 ADR-0242 (`fibonacci_search`) | +| Golden-Angle atlas packing \(d_{\min}=0.12\) (V3) | 🟢 ADR-0242 (`atlas_packing`; CGA null-point \(d\); `golden_angle_v1`) | +| Fibonacci section search cert/failure (V1) | 🟢 ADR-0242 (`FibonacciSearchCertificate` \| `OptimizationFailure`; dual-run digest) | +| κ cert gate fail → baseline 1.0 (V1b) | 🟢 `propose_kappa_from_search` / `goldtether.propose_kappa_line_search` | +| Multi-scale \(\tau_n=F_n\tau_0\) (V2) | 🟡 table only; production multi-band \(E_n(t)\) not default | +| Fibonacci-word scheduler (V4) | 🔴 staged | +| Fibonacci anyons (V5) | 🔴 research quarantine | | Contemplation Trace A SPECULATIVE holographic seal (P9) | 🟢 `core/contemplation/wave_seam.py` (hypothesis vs COHERENT evidence) | | Energy boundary + multi-scale τ (P10 Trace B) | 🟢 `wave_energy_boundary` (wave residual → energy/trajectory; τ_n=F_n·τ_0; E0–E1 crystallization) | @@ -339,7 +343,7 @@ PY | Durable holographic vault spectrum — 🟢 HolographicVaultStore | ADR-0241 | | Contemplation Trace A SPECULATIVE seal (P9) — 🟢 wave_seam | ADR-0241 P9 | | Energy boundary + multi-scale τ (P10) — 🟢 wave_energy_boundary | ADR-0241 P10 | -| Atlas packing + Fibonacci κ (ADR-0242) — 🟢 packing + search | ADR-0242 | -| Governance close (P12) — 🟢 contracts + checklist + ready-for-accept | ADR-0241 P12 | +| Atlas packing + Fibonacci V1 cert (ADR-0242) — 🟢 V1/V3; V2–V5 staged | ADR-0242 Drive five-vector | +| Governance close (P12) — 🟢 contracts + checklist | ADR-0241 P12 | Closing a gap = flip its `xfail` in `tests/test_third_door_blueprint_fidelity.py` (or the ADR-0241 / cohesion suite) to a passing behavioral test and delete the matching characterization lock. That is the definition of "done right" here. diff --git a/tests/test_adr_0242_fibonacci.py b/tests/test_adr_0242_fibonacci.py index aad2182c..54f379e5 100644 --- a/tests/test_adr_0242_fibonacci.py +++ b/tests/test_adr_0242_fibonacci.py @@ -1,16 +1,18 @@ -"""ADR-0242 — Fibonacci section search behavioral pins.""" +"""ADR-0242 V1 — evidence-gated Fibonacci section search.""" from __future__ import annotations -import pytest - from core.physics.fibonacci_search import ( + BASELINE_KAPPA, BoundedUnimodalObjective, + FibonacciSearchCertificate, + OptimizationFailure, fibonacci_section_search, + propose_kappa_from_search, ) -def test_fibonacci_search_hits_known_unimodal_min_within_1e_3(): +def test_fibonacci_search_returns_certificate_near_known_min(): objective = BoundedUnimodalObjective( lower=0.1, upper=2.0, @@ -22,9 +24,34 @@ def test_fibonacci_search_hits_known_unimodal_min_within_1e_3(): def func(x: float) -> float: return (x - 0.789) ** 2 - trace = fibonacci_section_search(objective, func) - assert abs(trace.best_observed_point - 0.789) < 1e-3 - assert len(trace.eval_sequence) == 20 + result = fibonacci_section_search(objective, func) + assert isinstance(result, FibonacciSearchCertificate) + assert abs(result.minimizer - 0.789) < 1e-3 + assert result.evaluations == 20 + assert len(result.ordered_points) == 20 + assert len(result.ordered_values) == 20 + assert result.cert_id + assert len(result.cert_id) == 64 + + +def test_certificate_digest_stable_dual_run(): + objective = BoundedUnimodalObjective( + lower=-5.0, + upper=5.0, + evaluation_budget=15, + objective_id="stable", + objective_version="v1", + ) + + def func(x: float) -> float: + return x**2 + + a = fibonacci_section_search(objective, func) + b = fibonacci_section_search(objective, func) + assert isinstance(a, FibonacciSearchCertificate) + assert isinstance(b, FibonacciSearchCertificate) + assert a.cert_id == b.cert_id + assert a.as_dict() == b.as_dict() def test_fibonacci_search_eval_count_equals_budget(): @@ -39,12 +66,12 @@ def test_fibonacci_search_eval_count_equals_budget(): def func(x: float) -> float: return x**2 - trace = fibonacci_section_search(objective, func) - assert len(trace.eval_sequence) == 15 - assert trace.certificate["n_evals"] == 15 + result = fibonacci_section_search(objective, func) + assert isinstance(result, FibonacciSearchCertificate) + assert result.evaluations == 15 -def test_fibonacci_search_rejects_nan_objective(): +def test_fibonacci_search_nonfinite_returns_failure(): objective = BoundedUnimodalObjective( lower=-1.0, upper=1.0, @@ -56,11 +83,12 @@ def test_fibonacci_search_rejects_nan_objective(): def func(x: float) -> float: return float("nan") - with pytest.raises(ValueError, match="nonfinite"): - fibonacci_section_search(objective, func) + result = fibonacci_section_search(objective, func) + assert isinstance(result, OptimizationFailure) + assert "nonfinite" in result.reason -def test_fibonacci_search_unimodality_violation_fail_closed(): +def test_fibonacci_search_unimodality_returns_failure(): objective = BoundedUnimodalObjective( lower=-2.0, upper=2.0, @@ -70,8 +98,49 @@ def test_fibonacci_search_unimodality_violation_fail_closed(): ) def func(x: float) -> float: - # Multiple extrema: x^4 - x^2 return x**4 - x**2 - with pytest.raises(ValueError, match="unimodality"): - fibonacci_section_search(objective, func) + result = fibonacci_section_search(objective, func) + assert isinstance(result, OptimizationFailure) + assert "unimodality" in result.reason + + +def test_never_returns_bare_float(): + objective = BoundedUnimodalObjective( + lower=0.0, + upper=1.0, + evaluation_budget=8, + objective_id="type", + objective_version="v1", + ) + result = fibonacci_section_search(objective, lambda x: (x - 0.3) ** 2) + assert not isinstance(result, float) + assert isinstance(result, (FibonacciSearchCertificate, OptimizationFailure)) + + +def test_propose_kappa_cert_uses_minimizer(): + objective = BoundedUnimodalObjective( + lower=0.1, + upper=2.0, + evaluation_budget=16, + objective_id="kappa", + objective_version="v1", + ) + result = fibonacci_section_search(objective, lambda x: (x - 0.5) ** 2) + kappa, outcome = propose_kappa_from_search(result) + assert isinstance(outcome, FibonacciSearchCertificate) + assert abs(kappa - 0.5) < 1e-2 + + +def test_propose_kappa_failure_falls_back_to_baseline(): + objective = BoundedUnimodalObjective( + lower=-2.0, + upper=2.0, + evaluation_budget=10, + objective_id="kappa_fail", + objective_version="v1", + ) + result = fibonacci_section_search(objective, lambda x: x**4 - x**2) + kappa, outcome = propose_kappa_from_search(result) + assert isinstance(outcome, OptimizationFailure) + assert kappa == BASELINE_KAPPA diff --git a/tests/test_third_door_cohesion.py b/tests/test_third_door_cohesion.py index 2b109bec..dcba364e 100644 --- a/tests/test_third_door_cohesion.py +++ b/tests/test_third_door_cohesion.py @@ -275,12 +275,19 @@ def test_resonant_reconstruct_empty_refused(): M.resonant_reconstruct(_closed(0.1)) -# --- ADR-0242 placeholder (Fibonacci not yet landed) -------------------------- +# --- ADR-0242 V1 evidence-gated Fibonacci + κ fallback ------------------------ def test_fibonacci_search_goldtether_integration(): - """Asserts Fibonacci search can optimize kappa and return a valid certificate.""" - from core.physics.fibonacci_search import BoundedUnimodalObjective, fibonacci_section_search + """Fibonacci search optimizes κ; cert-gated propose never silent-fails.""" + from core.physics.fibonacci_search import ( + BASELINE_KAPPA, + BoundedUnimodalObjective, + FibonacciSearchCertificate, + OptimizationFailure, + fibonacci_section_search, + propose_kappa_from_search, + ) objective = BoundedUnimodalObjective( lower=0.1, @@ -293,7 +300,22 @@ def test_fibonacci_search_goldtether_integration(): def synthetic_objective(kappa: float) -> float: return (kappa - 0.789) ** 2 # unimodal minimum at 0.789 - trace = fibonacci_section_search(objective, synthetic_objective) - assert abs(trace.best_observed_point - 0.789) < 1e-3 - assert len(trace.eval_sequence) == 20 - assert trace.certificate.get("budget") == 20 + result = fibonacci_section_search(objective, synthetic_objective) + assert isinstance(result, FibonacciSearchCertificate) + kappa, outcome = propose_kappa_from_search(result) + assert isinstance(outcome, FibonacciSearchCertificate) + assert abs(kappa - 0.789) < 1e-3 + assert outcome.evaluations == 20 + + # Failure path: multi-extrema → baseline κ=1.0 (Drive Phase 1). + fail_obj = BoundedUnimodalObjective( + lower=-2.0, + upper=2.0, + evaluation_budget=10, + objective_id="kappa_fail", + objective_version="v1.0", + ) + fail = fibonacci_section_search(fail_obj, lambda x: x**4 - x**2) + k_fail, out_fail = propose_kappa_from_search(fail) + assert isinstance(out_fail, OptimizationFailure) + assert k_fail == BASELINE_KAPPA