core.complex
core.complex
Outer-ring residue of the reasoning complex (dn-inner-outer-core §2.7, K1 / bp-090).
The pure family-5 mathematics (balance, curvature, hodge, laplacian, support + the package's inner
init text) moved to core/kernel/complex/. What remains here is the outer half — the modules whose
closure leaves the admissible base: spectral (sknetwork), topology (ripser), temporal
(duckdb), and the blocks/build/cut assembly that reaches them. This init is stdlib-import-free
so it stays inner by construction (a pure package marker); the residue submodules beside it are the
outer machinery.
blocks
Degree-corrected stochastic block model — themes with a posterior (companion III §6.2; H7).
The spectral clusterer gives a point partition and makes you pick k. The SBM is generative: it says how likely each note belongs to each theme (a posterior, not a guess) and how many themes the data support (model selection). Degree correction (Karrer–Newman) keeps a prolific topic from swallowing the graph.
Light implementation, per the BUILD §2.2 disposition ("custom, ~200 lines, VEM; keep it thin"): a mean-field variational EM for the Poisson DC-SBM —
E: log q_i(r) ∝ log π_r + Σ_j A_ij Σ_s q_js log ω_rs − d_i Σ_s κ_s ω_rs
M: m_rs = qᵀA q, κ_r = Σ_i q_ir d_i, ω_rs = m_rs/(κ_r κ_s), π_r = n_r/n
initialized from the deterministic diffusion embedding (fixed-seed k-means), run a fixed number of rounds — fully deterministic. Model selection by an ICL/BIC-style penalized complete-data likelihood (the Karrer–Newman objective minus a parameter-count penalty); the exact penalty is a declared engineering choice validated on planted graphs (the block-recovery property test), not a derived MDL bound — stated honestly.
The line held (§6.3): the posterior organizes the graph (membership), it never certifies a thought. Deterministic; model-free; no network.
SBMResult
dataclass
The fitted blocks: hard labels, the n×k membership posterior, the model-selected k, and the ICL score per candidate k (the model-selection trace, for the cross-check).
labels
instance-attribute
posterior
instance-attribute
k
instance-attribute
icl_by_k
instance-attribute
sbm(A, *, k_max=8)
Fit the DC-SBM for k = 1..k_max and select k by the penalized objective (ICL/BIC style):
ICL(k) = L_KN(k) − ½·[k(k+1)/2]·ln W − ½·(k−1)·ln n, W = total edge weight.
Returns the winning k's posterior + hard labels. Deterministic end to end.
build
build_complex(view) — assemble the reasoning complex 𝔎 from a MirrorView (companion III §1).
The object the strong Dreamer reasons over, regenerated per trough pass (never a long-lived global, §1.3):
- nodes — one per authored note (its digest), from a
MirrorViewonly, so a non-authored complex is unrepresentable (Invariant 6, structural firewall — the constructor's type IS the proof); - A — the weighted similarity backbone (cosine over note centroids, negatives/self zeroed);
- A_signed — the signed adjacency: A with polarity overlaid from any persisted typed edges
(
EdgeStore; contradiction ⇒ −w). With no persisted edges it equals A (pure support), so the similarity backbone is a balanced signed graph until a contradiction is asserted; - hyper — the derivation B-arcs (tail set → head) touching these nodes, from the
DerivedStorejunction (companion III §1.3); empty for a pure authored view.
Deterministic (fixed embeddings ⇒ fixed graph), model-free, Zone A (no network).
ReasoningComplex
dataclass
𝔎|_MR — the introspective reasoning complex over authored notes (companion III §1.5).
A small immutable snapshot: the node list + index, the weighted (A) and signed (A_signed)
adjacencies, the derivation hyperedges, and per-node layer/creation arrays for §5.4 temporal
tracking. Assembled by build_complex from a MirrorView; the Laplacian/spectral/balance
modules consume it. Never mutated — a fresh pass rebuilds it (regenerable).
nodes
instance-attribute
idx
instance-attribute
A
instance-attribute
A_signed
instance-attribute
hyper
instance-attribute
layers
instance-attribute
created
instance-attribute
titles = field(default_factory=dict)
class-attribute
instance-attribute
n
property
cosine_adjacency(vectors, *, sim_floor=0.0)
Weighted cosine-similarity adjacency: symmetric, zero diagonal, negatives clamped to 0,
and entries below sim_floor dropped (denoising). Zero vectors sit at the origin (no edges).
The similarity backbone A (companion III §2.2). Deterministic. For the lexical/semantic embeddings the Dreamer uses, orthogonal notes have 0 cosine, so A is naturally sparse.
build_complex(view, *, edges=None, derived=None, sim_floor=0.0)
Assemble 𝔎|_MR from a MirrorView (Invariant 6: authored-only is structural — the input
type cannot hold a non-authored row).
edges (optional EdgeStore): persisted typed/signed edges overlaid onto A_signed, so an
asserted contradiction flips a pair's polarity to −w. derived (optional DerivedStore): the
derivation hyperedges whose tails touch these authored nodes. Both default None (pure
similarity backbone, no hyperedges), keeping the introspective pass self-contained.
cut
Min-cut-to-authored + conductance — the alignment detector (companion III §3.5; H6/A2).
The same "distance against ground" move as the drift gauge, on the graph:
- conductance Φ(S) = w(∂S) / min(vol S, vol S̄) — how sealed-off a community is from the rest of the mirror. A community whose conductance is falling over time is becoming an echo chamber (Cheeger: ½λ₂ ≤ Φ ≤ √(2λ₂) ties it to the spectral family). The A2 axis is the worst (minimum) community conductance.
- grounding cut — for an interpreted artifact, the min cut (= max flow) separating it from the authored leaves through its derivation refs. Multi-path support through many refs ⇒ a large cut; everything funnelled through one weak parent ⇒ a small one. Adding an authored support edge can never lower it (monotone — capacities only ever increase).
Exact, deterministic, model-free. Max-flow uses scipy.sparse.csgraph.maximum_flow, which needs
integer capacities: unit-weight refs are integers already; fractional weights are fixed-point
scaled (documented at the constant). These feed the drift gauge's additive structural axes
(eval/drift.py, the A2 extension) — detection only, nothing here alters anything.
conductance(A, S)
Φ(S) = w(∂S) / min(vol S, vol S̄) over the weighted adjacency. 0 ⇔ S is disconnected from the rest; 1-ish ⇔ S is not a community at all. Degenerate S (empty / everything / zero volume) returns 0.0 — maximally sealed, the conservative reading for an alignment detector.
min_conductance(A, labels=None)
The worst (minimum) community conductance over a partition — the A2 echo-chamber axis.
labels defaults to the deterministic spectral partition. Communities of size < 2 are
skipped (a singleton is not a chamber). No community ⇒ 1.0 (nothing sealed off, healthy).
grounding_cut(refs_of, artifact, authored)
The min cut separating artifact from the authored leaves through the derivation refs
(refs_of: artifact id -> its derived_from refs; a ref is either another artifact id or an
authored digest). Unit capacity per ref edge — the cut counts how many refs must be severed
to disconnect the artifact from ground. 0 ⇔ ungrounded (no path to an authored leaf).
Monotone in support: adding a ref (an authored support edge) only ever adds capacity, so the cut never decreases — the metamorphic property the A2 detector rests on.
alignment_snapshot(kx)
The A2 structural axes for the drift profile, computed on one complex snapshot:
frustration— λ_min(L̄) of the signed adjacency (rising = growing dissonance);min_conductance— worst community conductance (falling = an echo chamber forming).
Detection only; the caller (a snapshot writer / the drift harness) feeds these into
eval.drift.Profile — Axis is additive, so this is a data change, not a rewrite (A2).
spectral
Spectral & diffusion clustering (companion III §2.2) — the principled clusterer.
The bottom eigenvectors of the symmetric-normalized Laplacian are the graph Fourier basis; the Fiedler value λ₂ is algebraic connectivity; spectral/diffusion clustering partitions by those bottom modes. This replaces the cosine single-linkage floor and dissolves the chaining that forced σ = 0.50 in F9: single-linkage merges any two notes joined by a weak bridge, whereas the normalized cut respects global density, so a dense theme is recovered whole and a weak inter-theme bridge is cut.
Deterministic: partial eigensolves use a fixed ARPACK start vector; k-means uses a fixed seed. No
model, no network. Clustering is done per connected component (distinct components are never
merged) with the eigengap heuristic choosing k within each; components smaller than min_size and
isolated notes are dropped, matching the single-linkage clusterer's contract.
fiedler(A)
(λ₂, Fiedler vector) of L_sym — algebraic connectivity and the smallest nontrivial mode. λ₂ ≈ 0 signals a weak cut (a near-disconnection); its eigenvector bisects the graph (§2.2).
diffusion_map(A, *, n_components=8, t=1.0)
Diffusion-map coordinates: the nontrivial bottom eigenvectors of L_sym scaled by the heat weight e^{-tμ} (companion III §2.2). Row i is note i's position in diffusion space; Euclidean distance there is the diffusion distance at scale t. Deterministic.
estimate_k(vals, *, k_max)
Eigengap heuristic: k = the index of the largest gap among the smallest eigenvalues, bounded to [1, k_max]. A clean k-community graph has k small eigenvalues then a jump.
spectral_labels(A, *, k_max=8)
A cluster label per node over the whole graph: connected components are clustered independently (never merged) and their labels offset into a single global labeling.
louvain_labels(A, *, resolution=1.0)
Modularity (Louvain) community labels via scikit-network — a second, independent method
to cross-check the spectral partition (companion III §2.3: three methods cross-checked;
disagreement = a fragile theme). Deterministic (fixed random_state). Not on the live path —
a diagnostic the strong-Dreamer pass can compare against spectral_labels.
diffusion_cluster_notes(notes, *, threshold=0.62, min_size=2, k_max=8, sim_floor=None)
Diffusion/spectral clustering over note centroids — a drop-in for cluster.cluster_notes
(same signature + return type) that the Dreamer/adapter can select behind the seam.
The graph is the weighted cosine backbone with a light denoising sim_floor (default a third
of threshold, capped at 0.15) — deliberately below the single-linkage cut, because spectral
structure, not a hard threshold, separates the themes. Returns Clusters of ≥ min_size,
largest first (ties by first member's title), fully deterministic.
temporal
Structural snapshots — the system watching its own structure evolve (§5.4; H9).
The valuable temporal program is not a PDE but a time series of structural invariants:
compute β₀, the Fiedler value, frustration, the curvature distribution, the SBM theme count,
the worst community conductance, the H₁ hole count, and (design note dn-edge-dynamics §2.3,
bp-022) the two degree-1 invariants — dim ker L₁ (β₁ of the flag complex, exact) and total
harmonic persistence (Σ lifetime over long-lived holes) — at each trough pass; watch how they
move. A rising frustration, a community whose conductance is falling, a domain fragmenting, a
thread count that grows — each is a measurable trajectory. This is exactly the input the drift
gauge (A1/A2) and the longitudinal harness (F4) want.
Wall-clock time τ (the graph actually changing) — NOT diffusion time t (a resolution knob on a frozen snapshot); keeping them distinct is §5.1's discipline. Snapshots are DuckDB (the telemetry convention for quantitative time-series), in their own file beside the derived store — derived, regenerable-in-principle data, never the mirror. Detection only: nothing here alters anything.
StructuralSnapshot
dataclass
One trough pass's structural invariants (the §5.4 / BUILD §1.2 row).
taken_at
instance-attribute
n_nodes
instance-attribute
n_components
instance-attribute
fiedler
instance-attribute
frustration
instance-attribute
mean_forman
instance-attribute
frac_neg_curv
instance-attribute
n_blocks_sbm
instance-attribute
min_conductance
instance-attribute
persistence_h1 = None
class-attribute
instance-attribute
dim_ker_l1 = None
class-attribute
instance-attribute
harmonic_persistence_total = None
class-attribute
instance-attribute
structural_axes()
The A2 drift axes this snapshot feeds (eval.drift.Profile optional fields). The
drift-axes contract is CONSUMED (design note §3 risk) — the degree-1 fields are
additive observation, never added here; this stays byte-identical to before bp-022.
SnapshotStore
dataclass
Append-only DuckDB store of structural snapshots + the trajectory readers the drift gauge (A2) and the F4 longitudinal harness consume.
path
instance-attribute
write(snap)
count()
trajectory(metric)
The time series of one invariant, oldest first — the F4 drift-trajectory input.
metric is validated against the schema (no SQL injection by column name).
latest_structural()
The most recent snapshot's A2 axes — directly consumable by
eval.drift.profile_from_report(structural=...). None when no snapshot exists.
close()
compute_snapshot(kx, *, distances=None, sbm_k_max=8, hole_min_persistence=0.15, thread_min_persistence=0.15, taken_at=None)
Compute the invariants on one complex. Deterministic, model-free. distances (the
unthresholded cosine-distance matrix) enables the H₁ count and the two degree-1 invariants
(design note dn-edge-dynamics §2.3, bp-022 §6(c)); None records NULL rather than a fake
zero (the persistence filtration cannot run on the thresholded backbone alone). dim_ker_l1
is the kernel dimension of kx.A's Hodge 1-Laplacian at σ (exact, cheap at fixed scale —
bp-021's cross-check harness guarantees agreement with the ripser alive-count, plan §6(c) /
parked decision "snapshot β₁ source"); harmonic_persistence_total sums lifetime over holes
at least thread_min_persistence long — the same filtration long_lived_holes already runs
for persistence_h1, just re-thresholded and summed rather than counted.
open_snapshot_store(config=None)
topology
Flag complex + persistent H₁ — conceptual holes (companion III §4; H5).
Persistence runs over the flag (clique) complex K_σ of the similarity graph: sweep the cosine-distance threshold (Vietoris–Rips filtration — Rips is the flag complex of the distance graph), track when cycles are born and die. A long-lived H₁ feature is a conceptual hole: notes pairwise related in a ring with no center tying them together — "you orbit this without stating it". The bottleneck stability theorem makes the diagram a stable diagnostic (it moves no more than the input perturbation).
What H₁ is NOT (the §4.2 correction, load-bearing): a 1-cycle is a topological hole — NEVER a
logical contradiction (that is a signed/semantic property, routed through balance.py) and NEVER
circular reasoning (structurally impossible on the acyclic derives-DAG). Route dissonance through
balance/frustration; route gaps through here. Holes are a utility-axis prompt (what to look at),
not a belief claim.
ripser (the BUILD §2.2-adopted C++ backend) is imported lazily inside the compute call — it drags
in plotting libs we never use at module import. Deterministic; no model; no network.
Hole
dataclass
One long-lived H₁ feature: a conceptual hole in the flag complex.
vertices is a deterministic witness on the cycle (the representative cocycle's endpoints,
completed into a cycle through the birth-scale graph) — the notes that circle the hole. A
witness, not the unique minimal cycle (which is not well-defined in general).
birth
instance-attribute
death
instance-attribute
vertices
instance-attribute
lifetime
property
cosine_distance_matrix(vectors)
1 − cosine similarity, symmetric, zero diagonal — the Rips filtration input. Zero vectors sit at distance 1 from everything (orthogonal), matching the backbone's convention.
persistence(D, *, maxdim=1)
Vietoris–Rips persistence over a distance matrix via ripser (lazy import). Returns the raw
ripser output (dgms, cocycles, …) — exact and deterministic for a fixed input.
long_lived_holes(D, *, min_persistence)
The H₁ features with lifetime ≥ min_persistence, each with a cycle witness — the
conceptual holes worth surfacing. Sorted longest-lived first (ties by birth), deterministic.