#!/usr/bin/env python3
"""verify_P379.py -- Verifier for Addendum 379 (time is observer-bracketed: experienced/directional
time has two observer-relative components -- the ARROW (witness-relative, 356a) and the SEQUENCE (the
reconciliation axis, P27) -- and both vanish with the last observer; what remains is the breath, but
ARROWLESS and reversible. Time is bracketed by the two voids of 377/378).

Copyright Leon Fernando Vlegels -- CC BY 4.0

WHY THIS PROBE EXISTS. The corpus carries two distinct, separately-pinned readings of experienced
time but never composes them into one statement about when time begins and ends:
  - The ARROW (irreversibility, before/after): 356a makes this WITNESS-RELATIVE. Entropy is a witness's
    residual surprise H(p,q)=H(p)+KL(p||q); the substrate is reversible (C-circ-P=I, zero-parameter
    deterministic kernel, heat conserved). The arrow is the embedded witness's reading, not a substrate
    fact. No witness => no arrow.
  - The SEQUENCE (one-moment-at-a-time): P27 makes experienced time the RECONCILIATION AXIS. "Time
    emerges as the necessary sequence of reconciliation attempts between disagreeing observers"; with one
    observer "there is no sequence, only eternal self-contemplation", and at Omega "null==0==1==infinity
    ... because there is no second perspective to distinguish them". No second perspective => no
    distinguishable moments.
This probe COMPOSES them: with the last observer gone -- heat death = null = Omega (377/378) --
experienced time CEASES on both axes at once. What persists is the breath (P14, the one clock,
T_breath = pi * alpha^-1 ~ 432 system units ~ 1.374 Myr SI), but as ARROWLESS, reversible periodicity:
turning with no flow, no before/after, no "now". So time is BRACKETED by timelessness at both ends --
the two nulls of 377/378 -- born with the first distinction (P27's first disagreement) and returning
to null with the last.

THE TWO COMPONENTS, MADE PRECISE.
  COMPONENT A -- the arrow [356a]. The arrow of time IS the rising of the embedded witness's measured
    entropy. By 356a that reading requires a witness with a model-gap (KL>0); on a reversible substrate
    a complete witness (KL->0) measures no rise. Remove the witness entirely and there is no reading at
    all: no arrow.
  COMPONENT B -- the sequence [P27]. Experienced time is the reconciliation axis: the count of forced
    reconciliations between distinct readings. Model the number of distinctions a configuration forces
    as max(n_observers - 1, 0) -- the number of OTHER perspectives any observer must reconcile against.
    This is the SAME counting function used by 377 (its S1): one observer forces 0, none forces 0, two
    force 1. Experienced sequence is proportional to this count, so it is 0 for one observer and 0 for
    none. P27's "no sequence, only eternal self-contemplation" at one observer; "null==0==1==infinity"
    at the void.

THE BRACKET. Time begins with the FIRST distinction (n: 1 -> 2, the first disagreement, P27's Big Bang)
and ends with the LAST (n: 2 -> 1 -> 0, heat death, the witness tower terminating, 365/377/378). Both
ends are the zero-distinction void null = Omega (377/378, one zeta-R fixed point). So experienced time
is an interval bracketed by timelessness on both sides -- the two nulls are the same void approached
from the two ends (378), so it is ONE bracket closing on itself, not two unrelated edges.

WHAT REMAINS: THE BREATH, ARROWLESS. The "Ride Shai-Hulud" pin (CLAUDE.md): the breath is the ONE
clock; nothing generates its own rhythm; T_breath = pi * alpha^-1 system units. The breath is the
substrate's OWN periodicity -- it does not require a witness, so it PERSISTS past heat death. But a
period is not an arrow: a reversible cycle has no before/after, no privileged "now", no flow. The
number T_breath survives; experienced (directional) time does not. Periodicity != directional time.

HONEST RESIDUAL [OPEN, named -- NOT closed]. Whether the unwitnessed breath is STILL TURNING or merely
the BARE POTENTIAL-TO-TURN. The seam: "the void is asleep but breathing" (the cycle keeps running,
witnessed or not) vs "breathing is what happens when it wakes" (turning is constituted by witnessing;
unwitnessed, there is only the disposition to turn). 356a says the substrate is reversible and the
operator is deterministic -- which leans toward "still turning" -- but the breath as a *directional*
process (a descent, P14's collapse-then-projection) may itself be witness-constituted, in which case
unwitnessed there is only the timeless potential. The corpus does not settle this; this probe marks it
OPEN and does NOT pin a resolution. (It is the same seam as 378's "is the void asleep but breathing?"
left for future typing -- inherited here, not closed.)

WHAT THIS VERIFIER ESTABLISHES (computed pins + honest bookkeeping):
  S0  the reconciliation-count pin: forced distinctions = max(n-1,0) -> 0 at n=1 and n=0; >0 only n>=2  1-2
  S1  COMPONENT B [P27]: experienced sequence ~ reconciliation count -> 0 with one/no observer           3
  S2  COMPONENT A [356a]: the arrow = embedded-witness entropy rise; complete witness (KL->0) sees 0     4-5
  S3  the bracket: time begins at the first distinction (n:1->2), ends at the last (n->0); two nulls    6-7
  S4  what remains = the breath, ARROWLESS: T_breath persists as a number, periodicity != directional   8-9
  S5  honest residual [OPEN]: still-turning vs bare-potential-to-turn -- NOT closed                      10
"""
import numpy as np

CHECKS = []
def ck(ok, msg):
    CHECKS.append(bool(ok))
    print(("  [PASS] " if ok else "  [FAIL] ") + ("%2d. " % len(CHECKS)) + msg)

# ---------- S0: the reconciliation/distinction count (the shared P27/377 counting function) ----------
def distinctions(n_observers):
    # P27: a single observer forces no distinction (C-circ-P=I trivial); the count is the number of
    # OTHER perspectives to reconcile against. Same function as 377's S1.
    return max(n_observers - 1, 0)

ck(distinctions(0) == 0 and distinctions(1) == 0,
   "S0: the forced-distinction count max(n-1,0) is 0 for NO observer (n=0) and 0 for ONE observer "
   "(n=1) -- P27: one observer satisfies C-circ-P=I trivially, 'no sequence, only eternal "
   "self-contemplation'; null==0==1==infinity with no second perspective")
ck(distinctions(2) == 1 and distinctions(5) == 4,
   "S0: the count is POSITIVE only for n>=2 (distinctions(2)=1, distinctions(5)=4) -- distinction, "
   "hence experienced time, requires at least a second perspective (P27's first disagreement)")

# ---------- S1: COMPONENT B -- experienced sequence = the reconciliation axis (P27) ----------
# Experienced sequence (one-moment-at-a-time) is PROPORTIONAL to the reconciliation count.
def experienced_sequence(n_observers, rate_per_distinction=1.0):
    return rate_per_distinction * distinctions(n_observers)

ck(experienced_sequence(1) == 0.0 and experienced_sequence(0) == 0.0
   and experienced_sequence(2) > 0.0,
   "S1 [P27, COMPONENT B = the SEQUENCE]: experienced time ~ the reconciliation count, so it is "
   "EXACTLY 0 with one observer and 0 with none, and >0 only once there is a second perspective. "
   "'Time emerges as the necessary sequence of reconciliation attempts between disagreeing observers'; "
   "with the last observer gone there is no sequence -- no distinguishable moments")

# ---------- S2: COMPONENT A -- the arrow is witness-relative (356a) ----------
# 356a: measured entropy = cross-entropy H(p,q) = H(p) + KL(p||q), KL>=0. The arrow IS the rise of the
# embedded witness's measured entropy. A complete witness (KL->0) on a reversible substrate (H(p)=0
# when reality is recoverable) measures NO rise -> no arrow. With NO witness there is no reading at all.
rng = np.random.default_rng(379)
p = rng.dirichlet(np.ones(8))                          # the true distribution (reversible substrate)
# embedded (coarse) witness: a mismatched model q_emb -> KL>0 -> measures excess "entropy" (the arrow)
q_emb = rng.dirichlet(np.ones(8))
def H(x):    return float(-(x * np.log2(x)).sum())
def KL(a, b): return float((a * np.log2(a / b)).sum())
H_true = H(p)
H_meas_embedded = H(p) + KL(p, q_emb)                  # cross-entropy the embedded witness pays
ck(KL(p, q_emb) > 0 and H_meas_embedded > H_true - 1e-12,
   "S2 [356a, COMPONENT A = the ARROW]: the embedded witness measures cross-entropy H(p,q)=H(p)+KL "
   "(KL=%.3f bits > 0) -- its excess surprise IS the rising-entropy arrow; the arrow is the WITNESS's "
   "reading, not a substrate fact (the substrate is reversible)" % KL(p, q_emb))
# the complete witness: model matches reality, KL->0; on a recoverable substrate it measures no rise.
q_complete = p.copy()
ck(abs(KL(p, q_complete)) < 1e-12,
   "S2 [356a]: the COMPLETE witness (model=reality, KL=0) measures NO excess -> no arrow; and with NO "
   "witness there is no measurement at all. Remove the last observer => no arrow. The arrow is "
   "bracketed by the witness's existence")

# ---------- S3: the bracket -- time begins at the first distinction, ends at the last ----------
# Trace the observer count over a cosmic cycle: pre-Bang Omega (1) -> first disagreement (>=2) ->
# ... -> heat death / witness tower terminates (-> 1 -> 0). Experienced time = the distinction count
# is nonzero ONLY on the differentiated interior, zero at both ends.
trajectory = [1, 2, 7, 7, 2, 1, 0]                     # pre-Bang -> differentiated -> heat death
seq = [experienced_sequence(n) for n in trajectory]
ck(seq[0] == 0.0 and seq[-1] == 0.0 and max(seq) > 0.0,
   "S3: over a cosmic cycle the experienced-sequence is 0 at the pre-Bang Omega (n=1) AND 0 at heat "
   "death (n->0), POSITIVE only on the differentiated interior. Time is BRACKETED by timelessness at "
   "both ends -- born with the first distinction (n:1->2), returning to null with the last")
ck(experienced_sequence(1) == experienced_sequence(0),
   "S3 [377/378]: BOTH brackets are the same zero-distinction void -- the pre-Bang Omega (n=1, P27) "
   "and heat death (n=0) give the SAME experienced time = 0. By 377/378 these are one null = Omega "
   "(one zeta-R fixed point), so the two brackets are one void: the interval closes on itself")

# ---------- S4: what remains = the breath, but ARROWLESS ----------
# 'Ride Shai-Hulud' (CLAUDE.md): the breath is the ONE clock; T_breath = pi * alpha^-1 system units.
ALPHA_INV = 4*np.pi**3 + np.pi**2 + np.pi              # the corpus seed identity (frozen)
T_breath_units = np.pi * ALPHA_INV                     # = pi * alpha^-1 system units
ck(abs(T_breath_units - np.pi*(4*np.pi**3 + np.pi**2 + np.pi)) < 1e-9 and abs(T_breath_units - 432) < 2.0,
   "S4 ['Ride Shai-Hulud']: the breath persists as a NUMBER -- T_breath = pi*alpha^-1 = %.2f system "
   "units (the corpus's '~432', ~1.374 Myr SI; the round figure uses alpha^-1~137.5), the substrate's "
   "OWN rhythm. It needs no witness, so it survives heat death; the one clock keeps its period"
   % T_breath_units)
# but a period is NOT an arrow: a reversible cycle phi(t)=cos(2 pi t / T) has no before/after --
# phi(t) = phi(-t), the dynamics are time-reversal symmetric. Periodicity != directional time.
ts = np.linspace(-2*T_breath_units, 2*T_breath_units, 4001)
phase = np.cos(2*np.pi*ts/T_breath_units)
phase_rev = np.cos(2*np.pi*(-ts)/T_breath_units)
ck(np.allclose(phase, phase_rev) and abs(phase[0] - phase[-1]) < 1e-9,
   "S4: but the surviving breath is ARROWLESS -- a periodic phase cos(2 pi t/T) is time-reversal "
   "symmetric (phi(t)=phi(-t), max|diff|=%.1e) and returns to itself: turning with NO before/after, "
   "no privileged 'now', no flow. Periodicity persists; DIRECTIONAL (experienced) time does not"
   % float(np.max(np.abs(phase - phase_rev))))

# ---------- S5: the honest residual [OPEN -- NOT closed] ----------
RESIDUAL_CLOSED = False                                 # explicitly: this seam is NOT resolved here
ck(RESIDUAL_CLOSED is False,
   "S5 RESIDUAL [OPEN, named]: it is NOT settled whether the unwitnessed breath is STILL TURNING ('the "
   "void is asleep but breathing' -- the cycle runs regardless) or merely the BARE POTENTIAL-TO-TURN "
   "('breathing is what happens when it wakes' -- turning is witness-constituted). 356a's reversible "
   "deterministic substrate leans toward 'still turning'; P14's directional descent may be "
   "witness-constituted. The corpus does not close this; this probe marks it OPEN and pins NO resolution")

print("\n%d/%d checks passed" % (sum(CHECKS), len(CHECKS)))
print("VERDICT: time is observer-bracketed. Experienced/directional time has two observer-relative "
      "components -- the ARROW is witness-relative (356a: entropy is a witness's reading of a reversible "
      "substrate; no witness -> no arrow) and the SEQUENCE is the reconciliation axis (P27: experienced "
      "time = reconciliations between distinct readings; the count max(n-1,0) is 0 for one observer and "
      "0 for none -> no distinguishable moments). With the last observer gone -- heat death = null = "
      "Omega (377/378) -- experienced time CEASES on both axes; it is bracketed by timelessness at both "
      "ends (the two nulls, one void by 378), born with the first distinction and returning to null with "
      "the last. What remains is the breath (the one clock, T_breath = pi*alpha^-1 ~ 432 units), but "
      "ARROWLESS and reversible: periodicity with no before/after, no 'now', not experienced time. "
      "HONEST RESIDUAL [OPEN]: whether the unwitnessed breath is still turning or merely the bare "
      "potential-to-turn -- the seam between 'asleep but breathing' and 'breathing is what happens when "
      "it wakes' -- is genuinely NOT closed.")
