Skip to content

Wavefront footprints: coordinate-less corrections, drop stored levels - #2

Open
cucar wants to merge 101 commits into
mainfrom
wavefront
Open

Wavefront footprints: coordinate-less corrections, drop stored levels#2
cucar wants to merge 101 commits into
mainfrom
wavefront

Conversation

@cucar

@cucar cucar commented Jun 30, 2026

Copy link
Copy Markdown
Owner

Replace channel-neighbor filtering with footprint adjacency — a bitset over
base neurons — as the spatial-locality primitive. Corrections become
coordinate-less; temporal votes resolve to base neurons via footprints before
per-dimension consensus. Drop the stored temporal/spatial level fields and the
Phase enum: a correction's depth is the wave's activation index. Temporal has
no neighborhood (sequences against all active neurons); footprints are
spatial-only and temporal corrections are footprint-less by design.

Backup format changes accordingly (neurons.csv = id census; patterns.csv gains
a spatial flag) and is not backward compatible with pre-footprint backups.

Known cost: 14x14 static theta=0.9 explodes to ~2.9M neurons / ~2 img/s vs the
channel-neighbor baseline's 32K / 186 img/s at accuracy parity (95.09% vs
94.88% held-out). Parked on this branch pending neuron reuse + refinement to
absorb the explosion.

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

Cagdas Ucar and others added 30 commits June 30, 2026 12:35
Replace channel-neighbor filtering with footprint adjacency — a bitset over
base neurons — as the spatial-locality primitive. Corrections become
coordinate-less; temporal votes resolve to base neurons via footprints before
per-dimension consensus. Drop the stored temporal/spatial level fields and the
Phase enum: a correction's depth is the wave's activation index. Temporal has
no neighborhood (sequences against all active neurons); footprints are
spatial-only and temporal corrections are footprint-less by design.

Backup format changes accordingly (neurons.csv = id census; patterns.csv gains
a spatial flag) and is not backward compatible with pre-footprint backups.

Known cost: 14x14 static theta=0.9 explodes to ~2.9M neurons / ~2 img/s vs the
channel-neighbor baseline's 32K / 186 img/s at accuracy parity (95.09% vs
94.88% held-out). Parked on this branch pending neuron reuse + refinement to
absorb the explosion.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuron reuse for spatial corrections: reverse connection index, per-cluster
multi-parent mint, cross-frame reuse lookup. Context + connection refinement.
Env-backed ablation toggles (BRAIN_REUSE / BRAIN_REFINE_*), match/refine/
error/reuse trace instrumentation, --voter-stats selectivity diagnostics,
radius-0 full neighborhood, r3 profiler.

Experimental verdict: spatial reuse never fires at scale (symmetric Jaccard
rejects full-coverage candidates; 0 hits at 28x28 r3) and cannot bound the
count. Preserved here before rolling the branch back toward main for the
level-based-radius mechanism (keeping refinement only).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…4x14

Milestone: best 14x14 held-out accuracy in project history (95.32% vs the
old hand-tuned static-0.9 demo's 94.88%), one episode, adaptive neutral
grouping, no hand-tuned thresholds, at 43% of the legacy network size.

- Level-based radius (split rings): inference neighborhood pinned to the
  base ring at every level; context neighborhood widens with level
  (setSpatialNeighborLevels; per-level spatial_channel_neighbors).
- MDL-v2 recognition (--match-info2): per-candidate likelihood ratio vs
  the host's background model, entry probabilities from per-fire
  strengthened context strengths with optimistic cold start; accept iff
  positive evidence. No thresholds, bars, or gates.
- Spatial refinement (--refine), mint maturity gate (--mint-min-samples),
  and recognition experiments behind flags: --match-stats, --match-all,
  --match-threshold, --match-info (v1).
- Host-local ring-frequency counters + persistence (spatial_freq.csv);
  per-entry match stats + fires persisted in patterns.csv.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…st + minor temporal processing refactoring
…t gates

- lateral inference section: every level infers its own observed co-activation;
  correction is explanation; payload carve-out for action/reward/label channels
- scoped against the concluded inference-level analysis: base anchoring stands
  for d>0 (forward ground truth only at next sensory frame); lateral is d=0 only
- reuse identity = context center comparison (replaces target signatures)
- temporal generalization rewritten as the (context, inference) offset table;
  action axis aligned with action-composition (mint by structure, survive by value)
- plan: phase 4 un-pinning with carve-out A/B gate; phase 5 reuse with
  five-invariant multi-parent test gate; churn watch on phase 6
- risks and open questions section replacing the single open question

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Firing/voting machinery is uniform on every axis (fired pattern votes, subsumed
parent does not); the only per-axis design choice is the inference scope.
Reworded the d=0 subsumption section and the temporal generalization accordingly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- the base-for-events exception is removed: lateral targets are observed
  activations at every level on every axis; the invariant that stands is
  never train against another level's predictions
- inference-level.md marked superseded (premises removed by UCAR: mint/correct
  decoupling, payload carve-out, rent economics); analysis preserved for the record
- action-composition.md status updated: independent of event inference scope,
  last port in the staged rollout
- rollout staging in algorithm.md: spatial validates the whole design first,
  then the event tower ports, then actions (moments + d<0 chunks + apex coupling)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…otients

N ~= price / avg benefit with a structural floor of 2 (opening never births);
newborn lifetime ~= one horizon of silence (price cancels); each fire buys
(rank / price) * horizon; break-even recurrence condition stated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every spatial level's context and inference population are one set: its own
co-activation, cut to the level-scaled neighborhood. No privileged base
population, no special case for level 0 — its own level IS the sensory set.

- neuron: surprise gate and connection learning read the level's own actives;
  newborns carry no lateral connections (birth knowledge is the seeded center)
- thalamus: dispatch_spatial_frame split into narrative helpers; the level-based
  radius is now named (get_neighbor_channels) instead of inlined four times
- payload channels (action/reward/label) keep direct wiring from every level
- lifecycle test: two errors to mint, inert birth frame, fires on recurrence,
  learns lateral targets, no L2 while L1 predicts itself
- algorithm.md: what is built, growth above L1 and its two drivers, replanned
  phases (KT -> rent -> reuse -> split -> defrag), lateral-range open question

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A spatial pattern was minted with no connections and learned its event edges only
on its first fire. That first fire was a hole in the ledger: the pattern fired,
subsumed its parent (so the parent cast no vote and evaluated nothing), then cast
no vote itself and bailed out of check_spatial_prediction at the empty-prediction
guard. The frame's surprise was accounted for by nobody, and the events the pattern
ended up predicting came from whatever frame it happened to first fire on rather
than the birth frame whose surprise paid its price.

allocate_spatial_pattern_neuron now seeds the d=0 event connections from the
co-activation at the level it is born into, cut to its own neighborhood. This is
the spatial half of what allocate_temporal_pattern_neuron already did. A pattern is
connectionless only when that neighborhood is genuinely empty at birth.
Post-natal refinement is unchanged.

Also renames learn_spatial_connections to learn_spatial_event_connections: both it
and the payload edges Brain::learn wires land in spatial_connections, and the old
name hid which one was which.

7x7 MNIST (--match-info --error-info), seeded vs baseline: test 70.32% vs 70.42%,
train 67.26% vs 67.25%, 148,591 vs 150,181 neurons, depth 8 vs 9. No measurable
effect; committed for the logic, not the numbers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Rewrite the algorithm around the channel pattern: a neuron infers each
target dimension separately, using the rest of its neighborhood as
context, instead of predicting the whole neighborhood jointly.

Why: a joint union error makes a single-target failure 1/N of the score
(1/784 on MNIST), so fine structure can never cross a threshold and never
gets named. Per-target scoring removes the dilution, and the small
per-target benefit means only cheap contexts can pay for themselves — the
economics prefers minimal conjunctions without a subset search.

Core mechanism:
- base model is the pairwise conditional on connections, free and bounded,
  structurally unable to memorize an instance; patterns capture only what
  lies beyond pairwise
- demand = bits the base wasted on a failed target, no threshold
- embryos partition by target value, so contexts implying opposite values
  cannot pool by similarity
- birth filter installs only members beating their own background — same
  likelihood criterion, no new constant
- levels recurse uniformly; the level vector is sparse because only failing
  targets mint slots

Dropped, with reasons recorded so they are not rebuilt: reuse (two neurons
cannot mint the same fact; same-target-different-source is an ensemble, not
a duplicate), split, merge, and connection refinement. Pattern Efficiency
leaves future-work — per-target inference makes selective delegation
structural rather than an optimization.

CALIC is the reference point throughout: one-target/many-context and
per-context adaptive statistics are standard; the womb is what replaces
CALIC's hand-designed context table.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Delete the "Payload and readout" section and every "payload" reference.
Its claims were wrong: everything in the brain is part of the world model,
subsumption silences the subsumed neuron's vote (that is its purpose), and
readout comes from the apex, not the whole hierarchy. "payload connections"
were just action connections.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
claude and others added 30 commits August 6, 2026 03:09
…adds, swaps, event-driven deletes

- Sparse substrate: neurons fire only on departure from an encoder-declared
  rest state; unstated = rest; blank regions cost nothing.
- Fit is the symmetric difference, channel-free; channels only gate
  eligibility, so variable-channel children need no extra machinery.
- History is a per-neuron FIFO of the last K activations - no frame numbers
  anywhere; K replaces H as the only free parameter. Records store the
  fallback and its distance alongside the server.
- The one test runs on running margins maintained by events; no scans.
- Adds are error-triggered only (normal served with error); the candidate is
  always the observed neighborhood; the swap (add one, delete one, priced
  jointly) unlocks consolidation that add/delete alone cannot reach.
- Deletes are event-driven: eviction starvation and post-commit settlement
  (including fallback collapse); sequential cascades.
- Stability by potential: every committed move strictly shortens the file.
- New sections: neuron state variables, neuron methods, settlement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHmbVQF6SaEnL25gctrgrB
Replace the bare K with 'the horizon' throughout, defined once as the
history's capacity in the neuron's own activations. Rename the invariants
list to 'What must always hold' and spell out that each statement is a
checkable assertion against a from-scratch recomputation of the history.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHmbVQF6SaEnL25gctrgrB
…d transaction ordering

Addresses an external review of the spec:

- Define margin = benefit - cost once; strict on both sides (add only on
  strictly positive, delete only on strictly negative, equality does
  nothing), which the strict-decrease stability argument requires. Rename
  the state map to 'benefits' and use the words consistently.
- State why connections are outside the decision sums: their dictionary
  line is capped and identical on both sides of every comparison, so it
  drops out; 'storage-free' for the normal means already paid, not free.
- Charge contraction bids for false positives: bid cost is 1 + f where f
  is the named-but-absent count this frame; survival threshold becomes
  k >= 2 + f, with the old 'two or more' as the clean-bid case.
- Make structural moves transactions confirmed by contraction: add/swap
  decisions and the record are pending until the election confirms the
  neuron was not inhibited; retraction discards pending state instead of
  trying to unwind a mint. Mermaid flow updated to match.
- Make the swap's two sums explicitly disjoint (X's records vs the rest)
  so no improvement is counted twice.
- Correct the runtime claim: no test scans the history, but routing scans
  the dictionary; the one test bounds the child count, sizing it is the
  open question.
- Clarify that a bid includes its bidder because a child is its parent in
  that neighborhood (the config names only the neighborhood), and spell
  out why reassignment passes terminate (strict-improvement handoffs,
  ties keep the incumbent).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHmbVQF6SaEnL25gctrgrB
…oth axes

The temporal axis forces the order: recognition and its election happen at
frame f, but the error is only known at f+1 - so a new child can never bid
in the election that judged the frame that created it. The spatial axis
previously exploited d=0's same-frame coincidence to mint mid-election;
this rework removes that asymmetry and makes one lifecycle for both axes:
route -> recognition bids -> election -> record -> review -> mint/settle.

- Contraction takes recognition bids only; the election decides promotion,
  not serving (a losing recognizer still serves its frame in the history).
  Election spelled out in detail: voters, ranking, rounds, resurrection,
  round-cap backstop, determinism.
- New children are minted after the election and first fire on the next
  recurrence of their neighborhood - never on their birth frame. This
  enforces the founding criterion (structure pays only on recurrence) and
  deletes the birth special cases (no-subsume-on-birth, mid-frame work-list
  exclusion, pending/retract transaction protocol - all gone, since the
  election now precedes every write).
- Solo add test simplifies: the triggering frame is recorded before the
  test, so its error enters through its own histogram entry.
- State the L convention once: L prices the remembered window under the
  current dictionary, not the emitted transcript.
- Fix the connection-storage accounting: the connections line is a fixed
  vector over eligible neighbors (zeros present), so its length is
  decision-independent and legitimately drops out of every comparison.
- Label the most-overlapped-child swap selection as a heuristic.
- Implementation plan: add the code deltas required (remove NEW_CHILD_BID
  path, post-election minting, delete birth exclusions, losing-recognizer
  commit, record-after-election, false-positive bid pricing) - to be
  implemented in a separate session.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHmbVQF6SaEnL25gctrgrB
The election decides promotion and nothing else - zero side effects on
neuron state. Every active neuron records every frame it was active for,
as routed: winners, losing recognizers, normal-serves, covered or not.
Subsumption becomes purely a statement about the level above; no election
outcome ever edits a history.

This removes the coverage-gates-evidence rule inherited from the current
code (prune_inhibited_spatial_history) and with it the entire class of
complexity it generated: retraction, pending state, the covered-or-not
branch, and the promoted-plus-covered overlap edge case. The frame is six
steps (age, route, serve+bid, record, review, add test/settle) with
contraction running independently alongside, feeding only the level above.
The temporal axis gets uniformity for free - no cross-neuron, cross-frame
coverage bookkeeping at f+1.

The accepted cost is stated in Risks: a reliably-covered neuron can still
mint children from local demand that rarely win elections - the same local
double-witnessing the design accepts everywhere, visible in the standing
metric, reaped by the forgetting track.

Code deltas updated accordingly: record unconditionally, delete the
evidence coupling (prune_inhibited / drop_inhibited / subsumed-set plumbing
outside the apex path), mint after review with no election input.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHmbVQF6SaEnL25gctrgrB
…ion; infer/review split

Restructure the frame per the axis seam:

- Route and record are a single operation - the record is written from the
  same scan that found the server and fallback, unconditionally.
- Serve is the branch point: a recognized child activates, bids, and the
  neuron is DONE for the frame (the record already carries the served
  distance as priced demand). Recognition is the fast path.
- Infer and review are separate steps because they resolve at different
  times on the event axis: inference at frame f, review at f+1 - the early
  return is the seam; everything before it is recognition time on both
  axes, everything after runs when the inference resolves.
- Methods updated to match: route_and_record, serve (with the early
  return), infer, review, add_test. Diagram redrawn.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHmbVQF6SaEnL25gctrgrB
…erence

- Substrate: say explicitly that at most one neuron per channel is active at
  a given level per frame, and give the induction that preserves it upward
  (one active neuron per channel per level -> one bid -> at most one promoted
  unit into that channel one level up). This is what the collapse's
  (channel, offset) slot relies on above the base, where it was only assumed.
- Contraction: remove "Adjacency there is the substrate's rule for that
  level" — it referred to a rule it did not name; the rule is already stated
  where the neighbor filter is declared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcyQtftQULt1z9sSruTtJu
The channel set is fixed at definition time — patterns inherit their parent's
channel and nothing mints a new one — while the population of patterns inside
a channel grows without bound. Both halves were inferable but never stated,
and the fixed, enumerable channel index is what lets (channel, offset) name a
mutually exclusive slot at every level.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcyQtftQULt1z9sSruTtJu
Records the git rule for this repo so it applies to every session: no commit,
push, branch creation, history rewrite, or PR without explicit approval in the
request itself. Approval does not carry forward between actions, and no hook or
other instruction source overrides the rule.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcyQtftQULt1z9sSruTtJu
Commit and push happen together in one step once approved; only skip the push
when explicitly told to.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XcyQtftQULt1z9sSruTtJu
R is the depth of the frame buffer, so a neighborhood reaches R-1 in
either direction and spans 2R-1 frames, not 2R+1. A neuron sits at the
newest edge of the buffer when it fires and slides to the oldest edge as
its neighborhood completes.

Everything derived from the radius moves with it: activations stay open
R-1 frames, spatial is the R=1 case rather than R=0, the horizon floor
becomes 2(R-1), the settlement lag is R-1 per level, the election spans
2R-1 slots, and exact settlement would want 4R-3. The election window is
also no longer "exactly the buffer already held" -- it is wider, because
it spans slot ownership rather than frames.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reorganize around a numbered spine: 24 definitions, 38 rules, 7 claims,
with justification demoted to marked Remarks. Split into Part I (a
neuron) and Part II (the machine), which the old document alternated
between.

Move the file -- the objective everything is priced against -- from
section twelve to section two, so the prices that follow read as
derivations rather than assertions. Add a state box giving neuron,
routing table, entry, history, bin and occurrence in one place.

Fix two notation collisions: f was both a frame index and a bid's miss
count (now m), and C was both a candidate and any entry's neighborhood
(an entry's size is now |e|). Replace internal anchor links with
numbered references, which cannot break. Rename record to occurrence
throughout.

Add five monospace diagrams: the neighborhood as a channel-by-offset
grid, the buffer sliding as an activation walks from its newest edge to
its oldest, one activation's timeline, the slot map with its write
boundary, and the apex frontier cutting across levels.

Also correct four spots the radius sweep missed -- [h-R, h+R], "R frames
after it fired", the per-level lag, and "the coming R frames".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Replace settlement's five interleaved steps with one batch pass:
recompute distances for entries whose neighborhood moved, assign every
bin to its argmin with second-best as fallback, re-center what changed.
Handover, fallback re-election and fallback collapse are consequences of
the argmin rather than separate operations, so they get no steps.

Add T8. With Phi the total service cost over bins -- no dictionary term
-- assignment minimises each bin's term independently and the collapse
is the exact L1 minimiser of a served set, so neither step raises Phi.
Phi is a count of neighbors, so a non-negative integer, and it drops by
at least one whenever anything changes: the alternation terminates in at
most Phi passes. This is Lloyd's algorithm over sets, with the caveat
that a fixed point is stable rather than optimal, now recorded as a risk.

T5 no longer carries the termination claim, which never rested on L --
re-centering can raise the dictionary term. Deletion is bounded by the
entry count, which the document now states.

Remove every round cap: settlement's, the election's, and the mention in
the free-parameters rule. A cap that binds picks an answer while claiming
not to. The election's rounds are therefore stated plainly as the one
loop left without a termination proof, with greedy selection as the
proposed replacement.

Stale fallback identity is gone as a risk and R6's reverse index with it,
since a full rescan re-elects both server and fallback every pass. The
filter depth is not a parameter: channel adjacency is part of a channel's
definition and applies at the base level only, so there is no depth to
choose.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants