luv

Workshop wiki

frontier-traversals.org

Frontiers, memoization, and materialized worlds

Materialized worlds deserve a frontier language #X7Q90E

This page takes an affirmative position: frontier-shaped computation is a real organizing principle for luvcraft, and Common Lisp gives us unusually good means to make that principle executable. The intention is not merely to extract a queue utility from lighting. It is to grow a small frontier language in which a derived world can state, at its own semantic level:

LayerWhat becomes sayable
derived-product lifecyclecapture a source, build and settle a candidate, validate it, publish coherently
frontier maintenanceseed, reserve, expose relations, admit, prioritize, coalesce, commit
local lawwhat light, water, fire, connectivity, copying, or another materialization actually means

This is generality as clarification. A light module should be able to read primarily as the law of voxel light: where illumination originates, how a face relation attenuates it, how competing contributions join, and what counts as fixation. Packed buckets, chunk crossings, candidate extent, counters, and publication remain fully real, but become named machinery rather than hundreds of lines interleaved with that law. The same gain is available to fluid motion, fire, components, terminal surfaces, dependency rebuilding, and other materialized worlds without pretending that those domains have the same transfer rule.

The first executable slice now lives beside the established lighting system. luvcraft/frontier.lisp defines inspectable frontier programs, retained execution evidence, packed finite priority buckets, and a compiler-visible voxel-relation traversal. luvcraft/frontier-light.lisp uses that vocabulary for a greenfield, from-scratch monotone light program:

frontiers:define-frontier-programvoxel-light-addition:family:monotone-max-fixpoint:frontier-layout:brightest-first-buckets:neighborhood:voxel-face-relations

The declaration is an inspectable CLOS definition, while its realization is one closed loop over specialized arrays. On a three-chunk proof world with vertical and lateral seams, occlusion, a sky shaft, and competing emitters, the new program produces exactly the reference oracle's sky and block arrays with the same number of site visits. The compiled program is now the only production solver. The deliberately simple oracle lives in the explicit luvcraft/light-reference system: it can compare a captured candidate without publishing it, but cannot be selected accidentally by runtime dispatch:

asdf:load-system"luvcraft/light-reference"
luvcraft.light-reference:compare-voxel-light-solvers
luvcraft:luvcraft-session-worldluvcraft:*session*
:candidate:compiled

#53Q1II states the paradigm explicitly: these are compiled sparse kernels, formed by composing a frontier/control IR with the quantity-checked arithmetic IR and lowering the result to a chosen scalar, SIMD, or GPU execution plan. #PJY6E1 records the first real compiler path: the same voxel-light-addition definition now also carries its local law, and compile-frontier-program closes it over the sky or block field into one scalar loop that agrees exactly with both older solvers and runs faster than either. #T2G95K describes the kernel language, #FE0O5R what a family contributes, #716UN6 how bindings reach storage, and #55IRJO the terminal wall as the second compiled client.

The retired solver remains only as test/reference evidence. Incremental invalidation, removal, and residency reconciliation have since joined the addition fixpoint as compiled frontier programs (#K3WRD3). Misspelled or retired solver names signal rather than silently changing algorithms. This keeps differential evidence available without preserving a second operational truth.

The proof carries cost evidence at the same semantic boundaries. Both solvers emit nested CPU/Tracy zones for the whole solve, sky and block seeding, propagation, and frontier draining. Each retained frontier execution records semantic evidence--visits, relations, admissions, crossings, and peak frontier size--while Tracy owns interactive temporal structure. The CPU trace and the retained A/B result record allocated bytes, garbage-collection time, and the number of automatic collections crossing each dynamic extent. A/B comparison therefore asks four different questions without confusing them: are the fields identical, did the programs perform the same semantic work, where did the physical realizations spend time, and how much memory pressure did they create? The ordinary production worker traverses these same zones, so a live Tracy capture observes the selected solver in the actual asynchronous world path, not only in a special benchmark. #J5KRQ9 explains how these instruments compose.

The first terrain measurement is already useful specialization evidence. On fifteen alternating solves of the same nine-chunk captured world, both programs produced equal fields and made 30,534 site visits. The medians were 22.676 ms and 1.125 MiB allocated for the legacy solver, versus 30.784 ms and 2.560 MiB for the frontier solver: 1.36 times the time and 2.28 times the allocation. A sustained batch of forty equivalent captures made the memory pressure tangible: 51 MiB allocated by the legacy solver and 102 MiB by the frontier solver, with one garbage collection crossing each batch.

That original result is retained here because the ensuing explanation is a small demonstration of the language paying for itself. The fields and visit counts excluded semantic divergence; matching 2,304-site seed frontiers and identical bucket capacities excluded different growth. Phase allocation then isolated the excess to admission, where one runtime-constructed type specifier allocated three conses on every push. #GJZL85 records the fix and the reversal of the allocation result. The remaining time difference now exposes a clean representation question, including the sealed-dispatch possibility in #U84XNW, rather than an indistinct mixture of algorithm and garbage collection.

defclass frontier-program-definition frontier.lisp:51
defclassfrontier-program-definition
name:initarg:name:readerfrontier-program-definition-name
family:initarg:family:readerfrontier-program-definition-family
frontier-layout:initarg:frontier-layout:readerfrontier-program-definition-frontier-layout
neighborhood:initarg:neighborhood:readerfrontier-program-definition-neighborhood
fields:initarg:fields:initformnil:readerfrontier-program-definition-fields
constants:initarg:constants:initformnil:readerfrontier-program-definition-constants
predicates:initarg:predicates:initformnil:readerfrontier-program-definition-predicates
transfer:initarg:transfer:initformnil:readerfrontier-program-definition-transfer
admission:initarg:admission:initformnil:readerfrontier-program-definition-admission
priority:initarg:priority:initformnil:readerfrontier-program-definition-priority
retain-admissions-p:initarg:retain-admissions-p:initformnil:readerfrontier-program-definition-retain-admissions-p
source-form:initarg:source-form:readerfrontier-program-definition-source-form
revision:initform
gensym"FRONTIER-PROGRAM-"
:readerfrontier-program-definition-revision
:documentation

One live semantic account of frontier-shaped materialization work. #X7Q90E

The definition names the dynamic family, physical frontier layout, and neighborhood at an aggregate boundary, and states its local law: field roles, realization constants, relation predicates, and the arithmetic TRANSFER, ADMISSION, and PRIORITY forms over them. Concrete methods on EXECUTE-FRONTIER-PROGRAM lower that account by hand; compile-frontier-program lowers it mechanically over bound fields.

defmacro do-voxel-frontier-relations frontier.lisp:359
defmacrodo-voxel-frontier-relations
sourcesource-offsetprioritytargettarget-offsetdirectiondestinationcrossingavailabilityfrontierwindowdomaindirections&keyexecutionresult
&bodybody

Drain FRONTIER and execute body once for every spatial relation it exposes.

source is a retained aggregate materialization and SOURCE-OFFSET is its dense site identity. TARGET is the local source or a materialization selected by WINDOW at a crossing. DESTINATION has dynamic extent. The client body owns admission, transfer, mutation, and unavailable-neighbor semantics; the macro keeps traversal and value lifetimes visible to the compiler. This is the manually staged lowering which compile-frontier-program now generates. #X7Q90E

let
present-p
gensym"PRESENT-P"
local
gensym"LOCAL"
resolved
gensym"RESOLVED"
execution-value
gensym"EXECUTION"
`
let
,execution-value,execution
loopuntildo
multiple-value-bind
,source,source-offset,priority,present-p
declare
ignore,present-p
let
,local
chunk-domain-local-coordinate,domain,source-offset
declare
dynamic-extent,local
when,execution-value
incf
frontier-execution-visits,execution-value
do-chunk-window-neighbors
,target-offset,destination,crossing,direction,resolved,availability,window,domain,local,directions
when,execution-value
incf
frontier-execution-relations,execution-value
when,crossing
incf
frontier-execution-crossings,execution-value
when
eq,availability:unavailable
incf
frontier-execution-unavailable,execution-value
let
,target
ecase,availability
:local,source
:available,resolved
:unavailablenil
,@body
finally
return,result
defparameter *voxel-light-solver* light.lisp:420
defparameter*voxel-light-solver*:compiled

The voxel-light program selected for production solves.

Only :COMPILED is implemented by the runtime. The legacy implementation is loaded explicitly by the LUVCRAFT/LIGHT-REFERENCE system as a differential test oracle; unsupported names signal through the closed EQL dispatch. #X7Q90E #PJY6E1 #K3WRD3

Frontier is an operational pattern, not merely a queue #NXXOQT

The small Haskell repository mbrock/frontier at 1688ab1 asks why breadth-first numbering, A* search, and Cheney copying garbage collection can all become instances of one short program. Its answer is more specific than “they use a worklist.” Each computation combines:

The repository is useful to luvcraft as source evidence, not as a library to port. Its Map, Seq, lists of plans, and monadic interfaces make the relationships unusually legible. Luvcraft's lighting evidence #QS1ERH says that a voxel implementation needs quite different physical machinery: packed parallel vectors, small finite priority buckets, dense fields, and compiler-visible iteration. The source can teach the separation of responsibilities without prescribing the hot-loop representation.

This page first describes what the Haskell program actually does. It then uses that account to classify the frontier-shaped work already present, or plausible, in a Minecraft-like world. Claims about frontier are observations of that repository; the final vocabulary is a proposal for luvcraft.

Five roles make the engine legible #6BM1IQ

The public types in FrontierTraversal.hs divide the computation into five roles. Omitting monadic plumbing, their shape is:

data Step f b a e
  = Done b
  | Kids (f (a, e))

data Node a b = Node
  { nodeSeed   :: a
  , nodeResult :: b
  }

data Plan a b k = Plan
  { planKey    :: k
  , planSeed   :: a
  , planUpdate :: Node a b -> BucketUpdate (Node a b)
  }

data FrontierAlg m f a b k e = FrontierAlg
  { initResult   :: a -> m b
  , commitResult :: Node a b -> f b -> m ()
  , planChildren :: Node a b -> f (a, e) -> m [Plan a b k]
  , priorityOf   :: Node a b -> k
  }
Type parameterMeaning in one traversal
aseed or source identity
breserved result associated with that identity
einformation on an outgoing edge
fone layer of adjacent structure
kfrontier priority or scheduling class
meffects and client state used while traversing

Step lets unfolding either expose a layer of labelled children or stop with a completed result. Node keeps a seed beside the result already reserved for it. Plan is a scheduling instruction rather than a child: it adds a priority and a bucket-update policy. FrontierAlg supplies the four client decisions. Separate MonadMemo and MonadFrontier interfaces supply identity and scheduling storage.

The type variables are not decoration. They prevent a common collapse in which “neighbor,” “unvisited node,” “queued item,” and “computed result” all become one vaguely shaped record.

Reservation precedes adjacency; commitment follows naming #L4WPDP

The essential ordering appears in drainFrontier. Roots are first ensured in the memo and pushed. Each iteration then performs this sequence:

flowchart TD
  R["root seed"] --> I["look up or init result"]
  I --> Q["push frontier item"]
  Q --> P["pop minimum key"]
  P --> U["unfold seed"]
  U -->|"Done b"| D["write final memo result"]
  U -->|"Kids"| C["plan children"]
  C --> S["ensure each child's result; schedule admitted work"]
  S --> M["look up every child result"]
  M --> F["commit parent from reserved child results"]
  D --> P
  F --> P

“Child results are available” has a precise and slightly surprising meaning: they have been initialized and memoized, but their own nodes need not yet have left the frontier. The parent therefore does not wait for a recursive post-order fold. It can commit as soon as stable names for its children exist.

For a seed a, let \mu(a) be its memoized result. The scheduler establishes the implication

a \text{ is scheduled} \Longrightarrow \mu(a) \text{ already exists}.

When a parent with children a_1,\ldots,a_n commits, every \mu(a_i) exists even though some a_i may remain pending. This is the small invariant that makes shared and cyclic structures ordinary rather than special cases.

Memoization is identity preservation, not just a visited set #AQ5EDF

A visited bit answers whether an identity has been encountered. The MonadMemo relationship answers a stronger question: what stable result has been assigned to this seed? lookupOrInit performs the only reservation and writes it immediately, so every later encounter observes the same result.

That distinction matters on a directed acyclic graph with sharing. If two parents point to one child c, both receive the same \mu(c); traversal does not duplicate the child's materialization. On a cycle, an edge back to an already discovered seed also finds a result which can be named before either object is fully committed.

The memo can still be trivial for algorithms that need only discovery. BFS numbering uses the result as a visit number. A voxel connected-component pass might use a bitfield plus a component identifier. A copying collector uses a forwarding address. The general lesson is that discovery often creates a durable correspondence, not merely a boolean historical fact.

Cheney collection is breadth-first materialization #RLNHEF

The repository's most clarifying example is the Cheney heap. The correspondence is exact:

Frontier roleCheney role
seed afrom-space pointer
result breserved to-space pointer
memo a \mapsto bforwarding table
unfolderread the source object's child pointers
initResultallocate the next to-space address
planChildrenenqueue referenced source objects
commitResultinstall an object using forwarded child pointers
FIFO frontierbreadth-first copying order
flowchart LR
  FP["from pointer p"] -->|"initResult"| FWD["forwarding p ↦ q"]
  FWD --> Q["reserved to pointer q"]
  FP -->|"unfold"| OBJ["object containing p₁ … pₙ"]
  OBJ --> ENSURE["ensure forwarding pᵢ ↦ qᵢ"]
  ENSURE --> COPY["commit object at q containing q₁ … qₙ"]

Reservation is the forwarding-pointer operation. Commitment copies the one object layer after every child pointer has a to-space name. Shared children remain shared because lookupOrInit cannot allocate them twice. Garbage never enters the frontier because traversal begins only from roots. A Lens Traversal describes an arbitrary root structure, allowing the final pass to rewrite every root through the forwarding memo.

The property tests in test/Main.hs check structure preservation, compact pointer ranges, garbage removal, and preservation of sharing in generated DAGs. The abstraction is therefore not supported only by suggestive examples; the tests exercise precisely the identity claims that make the example interesting.

BFS and A* differ mainly at admission and order #BNUDE9

BFS numbering gives every new seed the next integer in initResult, commits nothing, assigns the neutral priority (), and enqueues every child. FIFO order within the single priority bucket determines the numbering.

A* leaves the memoized result trivial and keeps best-known path costs g(s) in client state. For an edge s \xrightarrow{w} t, planning computes

g'(t) = g(s) + w

and emits a plan only when g'(t) < g(t). Its priority is

f(t) = g'(t) + h(t).

When the goal leaves the minimum frontier, the unfolder returns Done and the remaining work short-circuits. Thus the same runner expresses two visibly different algorithms because adjacency, admission, priority, and stopping are separate decisions.

This example also exposes a limit. A* may plan the same state again when its best-known cost improves. The memo says that the state has a stable result; the external g field says that its current approximation changed. “Has an identity” and “has reached its final value” are different predicates.

Bucket updates make duplicate work a policy question #BJCG8G

The concrete priority queue is a map from keys to FIFO sequences, accompanied by a min-priority queue of nonempty keys. BucketUpdate receives the proposed item and the existing sequence at one key, then returns a possibly changed sequence and a boolean saying whether it added work. The supplied policies are only enqueue and skip, but the seam can express replacement, deduplication, beam-width limits, or domain-specific coalescing.

This is more than a queue convenience. It puts the question “does this newly observed relation justify future work?” beside the algorithm that knows the answer. A generic queue cannot infer that a dimmer light arrival is obsolete, that two fluid updates at one site should merge, or that a path with a worse cost should disappear. Conversely, baking one deduplication rule into the frontier would make it wrong for clients that deliberately revisit a site.

The relevant abstraction boundary is therefore admission and coalescing, not merely push and pop.

The repository became clearer by becoming less grand #3Y7EQ1

The Git history is part of the evidence. Early versions explored Elgot algebras, hylomorphisms, and several Cheney-specific recursion-scheme modules. Commit 932631b replaced roughly 1,500 lines of those experiments with about 700 lines centered on FrontierTraversal and Heap. The final commit's own message says “change terminology to be less pretentious,” and the README now leads with a worklist-driven traversal engine.

That evolution did not abandon the underlying structure. It found an operational vocabulary in which the structure could be inspected:

unfold
reserve
plan
schedule
look up
commit

This is a useful precedent for luvcraft. Mathematical interpretations can help discover laws and counterexamples, as #EQ6GLY argues, while the engine still speaks in terms a profiler and debugger can show directly.

Minecraft contains several families of frontier work #SRJEKA

“Flood fill” is too narrow a name for the work a voxel game performs, while “general graph solver” is too broad to guide representation. The useful middle ground is a family of spatial maintenance problems sharing explicit frontiers and materialized state:

WorkFrontier itemMaterialized stateAdmission or priority
sky and block light additionchunk entry, cell offset, levelbest light levelenqueue only a strict improvement; brightest first
light removalcell and invalidated levelcandidate light fieldremove dependents, then reseed surviving sources
terminal-wall discoveryblock site and display facemembership/component IDmatching coplanar terminal material and not yet visited
fluid flowactive cell, face, pressure or levelvolume and flow statechanged capacity/pressure; often priority or time ordered
fireburning or heat-bearing sitefuel, heat, burn stateignition threshold and scheduled decay
redstone-like signalscomponent port or conductor sitesignal level and device stateenqueue when output changes; order may affect glitches
navigation and reachabilitycell or navigation nodecost, predecessor, regionunseen or improved path cost
terrain/ecology influencesite and influence valuedistance, moisture, fertilitystrict improvement or threshold crossing
falling-block or support updateschanged support sitestability/component stateadjacent support relation changed
chunk productionchunk request and dependency stampstaged world productpriority from visibility/distance; reject stale results
critter perception or soundsource/site/intensitytransient influence fieldattenuated contribution remains significant

Some rows operate over the six face-neighbor relation; others use faces, ports, visibility sets, chunk dependencies, or a metric radius. #E4T0PD is therefore still the right separation: the domain owns primitive stepping, a neighborhood policy chooses relations, and the maintenance rule decides what those relations mean.

Discover, relax, and invalidate are three different dynamics #DURBKN

The workloads fall into at least three algorithmic families.

  1. Discover once. Connected components and terminal-wall assembly usually assign each reachable site once for one source revision. A visited bit or component memo prevents repeated work.
  1. Relax monotonically. Distances, influence, and light addition keep a best-known value. For a transfer T_e along edge e and join \sqcup, a site changes by

    x_v \leftarrow x_v \sqcup T_e(x_u).

    It enters the frontier only when this update strictly changes x_v. Finite light levels make termination especially plain.

  1. Invalidate and rebuild. Removing a source, conductor, support, or resident neighbor can make a previously justified value too large. The system must trace invalid dependencies or conservatively clear a region, then run monotone addition again from surviving evidence. Voxel lighting's removal and addition queues in #SKRELT are the current concrete example.

These families can share storage, adjacency, counters, and scheduling machinery. They should not be forced through one callback protocol that pretends deletion is an ordinary join or that every discovered node is final. The fixed-point shape proposed in #BA9MCA is one client protocol over a more basic frontier substrate, not the definition of that substrate.

define-frontier-program voxel-light-removal frontier-light.lisp:168

Invalidation. Removing a source, an occluder's disappearance being an addition, or a departed neighbour can leave levels that no surviving source justifies. The removal program clears every level the removed site fed--strictly dimmer, or equal for direct sky continuing down--and re-admits the cleared site at the level it had; a lit neighbour it did not feed is handed to the addition frontier as a surviving source. The cleared set is the execution's retained admissions. #K3WRD3 #DURBKN

frontiers:define-frontier-programvoxel-light-removal:family:invalidation:frontier-layout:brightest-first-buckets:neighborhood:voxel-face-relations:fields
level:invalidatedt
:constants
direct-direction
:predicates
direct
direction=direct-direction
:admission
or
<
leveltarget
levelsource
anddirect
=
leveltarget
levelsource
:retain-admissionst
defgeneric frontier-family-check-definition frontier.lisp:186

Families are the semantic dynamics of #DURBKN. Each family knows which roles a program must declare and what its default admission, commit, and priority laws are. A definition is checked against its family at definition time so a wrong program fails before any realization.

defgenericfrontier-family-check-definition
:documentation

Signal an error unless definition is well formed for family.

Terminal walls supply a second, deliberately simpler client #K3PCP3

A planar rectangle of adjacent terminal-material blocks is a useful discover-once client. Starting from a placed or changed block face, the pass can traverse coplanar face neighbors of the same material, reserve a candidate surface identity, and collect bounds and membership. It then validates that the bounding rectangle is full and publishes one display surface over the participating blocks.

flowchart LR
  E["block edit"] --> S["seed affected terminal faces"]
  S --> W["discover coplanar component"]
  W --> B["accumulate orientation and bounds"]
  B --> V{"every rectangle site present?"}
  V -->|yes| P["publish terminal surface materialization"]
  V -->|no| X["publish components or no display, by chosen rule"]
  P --> G["project terminal grid and Slug draws over the whole face"]

Unlike light, the terminal surface need not revisit a site because a numeric approximation improved. Unlike a permanent world entity, its identity is derived from block material, orientation, adjacency, and source revisions. Breaking one block invalidates the old component and may discover several new ones. That places terminal walls between ordinary component labeling and incremental connectivity.

The terminal grid described by #RD8AEI remains a separate domain. The block frontier discovers where the display surface exists; Ghostty and the terminal presentation determine what cells the display contains. Surface geometry maps between those domains without making one terminal cell equal to one voxel block.

define-frontier-program terminal-surface-discovery terminal-wall.lisp:546

Discovery is a discover-once frontier program (#K3PCP3): starting from one exposed terminal face, admit coplanar neighbours which are the same material and exposed, mark each once, and retain the admitted component. The compiled realization walks chunk offsets through the world's chunk window; no coordinate objects, hash keys, or conses appear per site.

frontiers:define-frontier-programterminal-surface-discovery:family:discover-once:frontier-layout:lifo-stack:neighborhood
:voxel-relationscoplanar-directions
:fields
visited:memot
terminalexposed
:constants
materialoutwardabsent-neighbor-policycoplanar-directionsmemo
:admission
and
terminaltarget
exposedtarget
:retain-admissionst

Voxel efficiency requires translating the algebra, not its objects #RR9ODK

The Haskell carrier deliberately favors clarity: Map memoization, a Map of Seq priority buckets, allocated lists of Plan values, traversable child layers, and monadic state. Those choices make the experiment easy to vary and test. They are not an acceptable inner-loop cost model for millions of voxel visits.

Luvcraft's existing packed light worklist records the relevant facts. Moving from retained structures and conses to parallel vectors reduced one measured solve from about 264 MB to 31.8 MB consed without changing its 2.43 million visits. Changing scheduling to sixteen brightest-first buckets then reduced the solve to about 13.3 MB, 340,050 visits, and 0.18 seconds. Representation and order were independent performance dimensions.

The luvcraft translation should therefore preserve semantic seams while specializing physical execution:

Semantic roleHot representation
seed identityretained chunk-window entry plus dense domain offset
priority ksmall integer bucket or client-specific packed key
memo/resultdense field lane, bitset, component lane, or side table
child layercompiler-visible neighborhood iteration with dynamic-extent coordinates
planimmediate admission branch; no allocated plan object
bucket updateclient-specialized enqueue, skip, replace, or coalesce operation
commitdirect writes into a candidate materialization

One dispatch when choosing a maintenance policy may be useful. Generic function calls, closures, conses, and coordinate allocation per edge would put abstraction precisely where #FGT96H says the current profiler is most sensitive. A macro can expose the algebraic phases to source readers while expanding the trusted inner loop over primitive arrays.

A frontier language composes meaning with specialized execution #QHBZJZ

The unification is real precisely because it is layered. We do not need one generic call per edge, or one object shape for every domain, to possess a shared language. We need stable compositional roles which can be lowered to the right concrete execution:

flowchart TB
  D["chunk domains and checked windows"] --> N["client neighborhood iteration"]
  F["materialized fields and revisions"] --> M["maintenance policy"]
  N --> M
  P["packed frontier storage and priority discipline"] --> M
  M --> C["candidate mutation / result reservation / commit"]
  C --> U["coherent publication"]

The reusable words are concrete and already beginning to exist:

Client programs own transfer laws, admission predicates, removal semantics, stopping conditions, and the interpretation of unavailable neighbors. This is what makes the abstraction powerful: light remains unmistakably light and a terminal wall remains unmistakably a terminal wall, while both can speak in the same precise language about frontier, domain, materialization, extent, and publication.

Frontier programs are compiled sparse kernels #53Q1II

The proposed frontier language is a DSL compiler, not a generic worklist framework whose inner loop depends on accidental devirtualization. A live, inspectable program definition remains open to Common Lisp development; one compilation closes that definition over particular fields, domains, neighborhoods, representations, and an execution plan, then emits the exact scalar, SIMD, or GPU machinery required by that realization. This is the explicit staging which C++ templates and Haskell type-class specialization obtain through their host languages, but here the generated program and every choice which produced it can themselves be ordinary Lisp objects.

The compiler composes two deliberately different languages:

flowchart TB
  F["frontier program IR<br/><small>family, domain, neighborhood, effects, fixation, publication</small>"]
  A["arithmetic IR<br/><small>quantity-checked transfer, join, admission, priority</small>"]
  C["frontier compiler<br/><small>bind fields and choose a physical plan</small>"]
  S["closed scalar Lisp loop"]
  V["columnar SIMD batches"]
  G["bulk GPU passes"]
  W["GPU work graph"]
  F --> C
  A --> C
  C --> S
  C --> V
  C --> G
  C --> W

The arithmetic language owns pure value laws: derive a propagation loss, compute a candidate, compare it with a destination, join compatible values, and derive a priority. The frontier language owns work-generating effects: seed, expose a relation, read and commit fields, admit another site, settle or invalidate work, and publish a coherent candidate. Chunk lookup, unavailable neighbors, queues, atomics, revision stamps, and publication do not become arithmetic expressions. Conversely, a light attenuation law should not be duplicated as handwritten scalar, SIMD, and shader arithmetic. This sharpens the local-law boundary anticipated by #WEE8P5 and realizes the checked field kernel of #ADR040 through the multi-backend arithmetic medium #5N6SOQ.

One execution plan need not contain a conventional queue. The physical meaning of “unsettled work” may be a packed bucket frontier, a FIFO, an active bitset, current/next append buffers, component parents undergoing pointer jumping, or records emitted between GPU nodes. Two sources make that range concrete:

These are source observations, not a claim that luv already has either GPU backend. Their design consequence is that :frontier-layout alone is too narrow to describe compilation: layout is one part of an execution plan. The compiler may select a different algorithmic realization when the program declares and tests the laws which justify it--for example monotonicity, associative joining, an acyclic recipient relation, finite priority, or a bounded round count. Such laws are semantic claims with differential and property evidence, never optimistic compiler annotations.

The same source can make SIMD explicit without demanding that irregular scheduling itself vectorize. A plan may drain a homogeneous bucket cohort, separate same-materialization interior sites from crossings, borrow raw columns once, evaluate transfer and admission over lanes and masks, compact successful lanes, and handle a scalar tail. Selection occurs outside the hot loop. The scalar lowering remains the reference realization for exact field, visit, and arithmetic conformance.

Quantity meaning survives compilation while quantity wrappers do not. The current :sky-propagation-level and :block-propagation-level fields are already different dimensionless kinds over the same u8 encoding; neither should be renamed radiance or illuminance merely because future lighting will be more physical. A richer kernel may distinguish radiance, irradiance, luminance, spectral or photon quantities, material transmittance, and photopic, scotopic, or mesopic conditions at its checked boundary, then still execute over plain integer or floating lanes. Physicalization therefore strengthens this compiler seam: it does not make a quantity object per voxel.

The current implementation is a useful manually staged compiler prototype:

Present definitionCompiler reading
define-frontier-programembryonic semantic source definition
compile-frontier-programsemantic program and field bindings become one realization
do-voxel-frontier-relationsfused scalar loop template with compiler temporaries exposed
bucket-frontierone physical scheduler and record store
inline light bodynot-yet-reified arithmetic kernel
reference/candidate A/Bexplicit test-system conformance and cost evidence

The large binding list of do-voxel-frontier-relations is thus not the desired human-facing API. It is evidence about the lowered loop. A pleasant kernel source should primarily name fields, relations, transfer, join, admission, priority, and lifecycle; the compiler introduces offsets, crossing flags, buffer access, counters, and temporaries while retaining source provenance for inspection. CLOS remains the open control plane for definitions and backend protocols, while generated code deliberately contains no generic dispatch at the per-site or per-relation grain.

defvar *lisp-arithmetic-lowering* compiler.lisp:253

Scalar lowering. The generic realization above dispatches on numbers versus vectors at run time so one compiled function can serve every representation. A hot loop whose operands are known scalars wants the ordinary Common Lisp operators instead, so that declared integer or float types flow through the emitted arithmetic. The choice is made once, by the caller lowering an expression, and never per operation.

defvar*lisp-arithmetic-lowering*:generic

How lower-lisp-arithmetic-expression emits calls: :GENERIC uses the representation-dispatching lisp-add family; :SCALAR emits CL operators over declared scalar operands. #53Q1II

define-lisp-arithmetic-function light-propagation-loss arithmetic.lisp:25

Voxel light loses one attenuation step per cell entered plus the entered cell's own opacity, except that a direct transmission (sky light continuing straight down) pays only the opacity. This is the one local law shared by the legacy solver, the seeds, and the compiled frontier kernel, which inlines the checked definition rather than calling this function. #53Q1II

lisp:define-lisp-arithmetic-functionlight-propagation-loss
opacity:quantity:block-light-attenuation-step:unit:one
direct-transmission-p
ifdirect-transmission-popacity
+opacity
lang:quantity1:quantity:block-light-attenuation-step:unit:one
defclass frontier-realization frontier.lisp:468

------------------------------------------------------------------------ Realizations

defclassfrontier-realization
definition:initarg:definition:readerfrontier-realization-definition
revision:initarg:revision:readerfrontier-realization-revision
bindings:initarg:bindings:readerfrontier-realization-bindings
site-domain:initarg:site-domain:readerfrontier-realization-site-domain
maximum-priority:initarg:maximum-priority:readerfrontier-realization-maximum-priority
priority-meaning:initarg:priority-meaning:readerfrontier-realization-priority-meaning
transfer:initarg:transfer:readerfrontier-realization-transfer
admission:initarg:admission:readerfrontier-realization-admission
priority:initarg:priority:readerfrontier-realization-priority
drain-form:initarg:drain-form:readerfrontier-realization-drain-form
admit-form:initarg:admit-form:readerfrontier-realization-admit-form
relate-form:initarg:relate-form:readerfrontier-realization-relate-form
drain-function:initarg:drain-function:readerfrontier-realization-drain-function
admit-function:initarg:admit-function:readerfrontier-realization-admit-function
relate-function:initarg:relate-function:readerfrontier-realization-relate-function
:documentation

One program compiled over bound fields into closed scalar Lisp.

TRANSFER, ADMISSION, and PRIORITY are the checked arithmetic expression graphs; DRAIN-FORM and ADMIT-FORM are the emitted lambda forms; the two functions are their compiled realizations. ADMIT-FUNCTION seeds one site through the same admission and commit law as a relation, or is NIL when the law needs a source. RELATE-FUNCTION exposes one relation from a virtual source whose field values are supplied as arguments, so a boundary such as open sky is the program's own transfer law rather than client arithmetic. #53Q1II #581ZQP

defun compile-frontier-program frontier.lisp:923
defuncompile-frontier-program
program&keybindingssite-domain
compilet

Close program over field bindings and emit its scalar realization.

site-domain is a form over MATERIALIZATION yielding the chunk domain that gives a site's dense offset spatial meaning. Each field role of the program must have one frontier-field-binding. The laws are parsed and quantity checked against the bound fields, lowered with scalar arithmetic, and spliced into one closed loop over raw buckets and lanes. With compile NIL the forms are emitted but not compiled, for inspection. #53Q1II #T2G95K #716UN6

let*
definition
if
symbolpprogram
or
error"No frontier program named ~S."program
program
roles
frontier-program-definition-fieldsdefinition
constants
frontier-program-definition-constantsdefinition
fields
mapcar
lambda
role
let*
name
frontier-field-role-namerole
binding
or
findnamebindings:key#'frontier-field-binding-name
error"Program ~S field ~S is unbound."
frontier-program-definition-namedefinition
name
flet
lanes
which
loopfor
lane-name
in
frontier-field-binding-lanesbinding
collect
conslane-name
make-symbol
formatnil"~A/~A/~A"whichnamelane-name
make-instance'frontier-lowered-field:bindingbinding:source-parameter:target-parameter:source-lanes
lanes'source
:target-lanes
lanes'target
:source-variable:target-variable
roles
predicates
frontier-program-definition-predicatesdefinition
constant-parameters
mapcar
lambda
name
constants
predicate-parameters
mapcar
lambda
predicate
make-frontier-parameter
frontier-relation-predicate-namepredicate
nil
predicates
environment
append
loopforloweredinfieldscollect
cons
lang:arithmetic-object-name
lowered-field-source-parameterlowered
lowered-field-source-parameterlowered
collect
cons
lang:arithmetic-object-name
lowered-field-target-parameterlowered
lowered-field-target-parameterlowered
mapcar
lambda
parameter
cons
lang:arithmetic-object-nameparameter
parameter
appendconstant-parameterspredicate-parameters
compilation
make-instance'frontier-compilation:definitiondefinition:fieldsfields:constantsconstant-parameters:predicatespredicate-parameters:environmentenvironment:site-domainsite-domain
unlesssite-domain
error"COMPILE-FRONTIER-PROGRAM needs a :SITE-DOMAIN template."
dolist
loweredfields
let
role
find
frontier-field-binding-name
lowered-field-bindinglowered
roles:key#'frontier-field-role-name
when
and
frontier-field-binding-lazy-p
lowered-field-bindinglowered
or
frontier-field-role-relaxed-prole
frontier-field-role-memo-prole
error"The ~S field is relaxed or a memo and cannot be bound lazily."
frontier-field-role-namerole
dolist
predicatepredicates
when
and
eq
frontier-relation-predicate-kindpredicate
:direction=
not
member
frontier-relation-predicate-argumentpredicate
constants
error"Predicate ~S names ~S, which is not a program constant."
frontier-relation-predicate-namepredicate
frontier-relation-predicate-argumentpredicate

Parse and check the laws.

setf
compilation-transfercompilation
parse-frontier-lawcompilation
frontier-program-definition-transferdefinition
compilation-admissioncompilation
parse-frontier-lawcompilation
frontier-program-definition-admissiondefinition
compilation-prioritycompilation
parse-frontier-lawcompilation
frontier-program-definition-prioritydefinition
let
relaxed
whenrelaxed
ensure-law-fits-field
compilation-transfercompilation
relaxed"transfer"
ensure-law-fits-field
compilation-prioritycompilation
relaxed"priority"
let*
relaxed-binding
andrelaxed
lowered-field-bindingrelaxed
maximum-priority
drain-form
admit-form
relate-form
make-instance'frontier-realization:definitiondefinition:revision
frontier-program-definition-revisiondefinition
:bindingsbindings:site-domainsite-domain:maximum-prioritymaximum-priority:priority-meaning
andrelaxed-binding
frontier-field-binding-declarationrelaxed-binding
:transfer
compilation-transfercompilation
:admission
compilation-admissioncompilation
:priority
compilation-prioritycompilation
:drain-formdrain-form:admit-formadmit-form:relate-formrelate-form:drain-function
andcompile
compilenildrain-form
:admit-function
andcompileadmit-form
compileniladmit-form
:relate-function
andcompilerelate-form
compilenilrelate-form

The kernel language names fields, constants, predicates, and laws #T2G95K

A frontier program is now written as its own semantic source rather than as a name attached to a handwritten loop. Voxel light reads:

frontiers:define-frontier-programvoxel-light-addition:family:monotone-max-fixpoint:frontier-layout:brightest-first-buckets:neighborhood:voxel-face-relations:fields
level:relaxedt
opacity
:constants
direct-direction
:predicates
direct
direction=direct-direction
:transfer

The clauses divide along the two languages of #53Q1II. :fields names roles the program reads or writes at source and target without saying where they live. :constants are values supplied when a realization runs; :predicates are raw truth values about the exposed relation, such as whether its direction is the constant direct-direction or whether it crosses a chunk. :transfer, :admission, and :priority are arithmetic expressions over (FIELD ROLE) reads, predicates, and constants, parsed by the arithmetic frontend and quantity checked against the bound fields, so the one transfer law is checked once as sky propagation levels and once as block propagation levels. as-field-quantity is the explicit boundary at which attenuation steps become propagation-level differences; the checker refuses the subtraction without it. light-propagation-loss is an ordinary define-lisp-arithmetic-function: the seeds call it as a function, while the kernel inlines its checked definition.

A realization exposes three entry points besides the drain: admit seeds a site through the family's law with a supplied value, relate exposes one relation from a virtual source (#581ZQP), and schedule pushes a site whose value stands for reconsideration. Families with a secondary effect take a companion frontier (#ZEENY3).

The realization retains everything the reader could want: the parsed expressions with their quantity specifications, the emitted lambda forms, and the compiled functions. frontier-realization-drain-form prints the whole loop, and the light tests assert that it contains no arithmetic dispatch and no funcall. The reserved words of the language--source, target, materialization, offset, value, window, crossing, direction=--are recognized by name so programs and bindings can be written in their client packages.

defun compile-frontier-program frontier.lisp:923
defuncompile-frontier-program
program&keybindingssite-domain
compilet

Close program over field bindings and emit its scalar realization.

site-domain is a form over MATERIALIZATION yielding the chunk domain that gives a site's dense offset spatial meaning. Each field role of the program must have one frontier-field-binding. The laws are parsed and quantity checked against the bound fields, lowered with scalar arithmetic, and spliced into one closed loop over raw buckets and lanes. With compile NIL the forms are emitted but not compiled, for inspection. #53Q1II #T2G95K #716UN6

let*
definition
if
symbolpprogram
or
error"No frontier program named ~S."program
program
roles
frontier-program-definition-fieldsdefinition
constants
frontier-program-definition-constantsdefinition
fields
mapcar
lambda
role
let*
name
frontier-field-role-namerole
binding
or
findnamebindings:key#'frontier-field-binding-name
error"Program ~S field ~S is unbound."
frontier-program-definition-namedefinition
name
flet
lanes
which
loopfor
lane-name
in
frontier-field-binding-lanesbinding
collect
conslane-name
make-symbol
formatnil"~A/~A/~A"whichnamelane-name
make-instance'frontier-lowered-field:bindingbinding:source-parameter:target-parameter:source-lanes
lanes'source
:target-lanes
lanes'target
:source-variable:target-variable
roles
predicates
frontier-program-definition-predicatesdefinition
constant-parameters
mapcar
lambda
name
constants
predicate-parameters
mapcar
lambda
predicate
make-frontier-parameter
frontier-relation-predicate-namepredicate
nil
predicates
environment
append
loopforloweredinfieldscollect
cons
lang:arithmetic-object-name
lowered-field-source-parameterlowered
lowered-field-source-parameterlowered
collect
cons
lang:arithmetic-object-name
lowered-field-target-parameterlowered
lowered-field-target-parameterlowered
mapcar
lambda
parameter
cons
lang:arithmetic-object-nameparameter
parameter
appendconstant-parameterspredicate-parameters
compilation
make-instance'frontier-compilation:definitiondefinition:fieldsfields:constantsconstant-parameters:predicatespredicate-parameters:environmentenvironment:site-domainsite-domain
unlesssite-domain
error"COMPILE-FRONTIER-PROGRAM needs a :SITE-DOMAIN template."
dolist
loweredfields
let
role
find
frontier-field-binding-name
lowered-field-bindinglowered
roles:key#'frontier-field-role-name
when
and
frontier-field-binding-lazy-p
lowered-field-bindinglowered
or
frontier-field-role-relaxed-prole
frontier-field-role-memo-prole
error"The ~S field is relaxed or a memo and cannot be bound lazily."
frontier-field-role-namerole
dolist
predicatepredicates
when
and
eq
frontier-relation-predicate-kindpredicate
:direction=
not
member
frontier-relation-predicate-argumentpredicate
constants
error"Predicate ~S names ~S, which is not a program constant."
frontier-relation-predicate-namepredicate
frontier-relation-predicate-argumentpredicate

Parse and check the laws.

setf
compilation-transfercompilation
parse-frontier-lawcompilation
frontier-program-definition-transferdefinition
compilation-admissioncompilation
parse-frontier-lawcompilation
frontier-program-definition-admissiondefinition
compilation-prioritycompilation
parse-frontier-lawcompilation
frontier-program-definition-prioritydefinition
let
relaxed
whenrelaxed
ensure-law-fits-field
compilation-transfercompilation
relaxed"transfer"
ensure-law-fits-field
compilation-prioritycompilation
relaxed"priority"
let*
relaxed-binding
andrelaxed
lowered-field-bindingrelaxed
maximum-priority
drain-form
admit-form
relate-form
make-instance'frontier-realization:definitiondefinition:revision
frontier-program-definition-revisiondefinition
:bindingsbindings:site-domainsite-domain:maximum-prioritymaximum-priority:priority-meaning
andrelaxed-binding
frontier-field-binding-declarationrelaxed-binding
:transfer
compilation-transfercompilation
:admission
compilation-admissioncompilation
:priority
compilation-prioritycompilation
:drain-formdrain-form:admit-formadmit-form:relate-formrelate-form:drain-function
andcompile
compilenildrain-form
:admit-function
andcompileadmit-form
compileniladmit-form
:relate-function
andcompilerelate-form
compilenilrelate-form

Families own admission, commit, and priority #FE0O5R

The :family clause is semantic, not a label. #DURBKN's dynamics become compiler knowledge:

FamilyRequiresAdmits a target whenCommitsSchedules at
:monotone-max-fixpointone :relaxed field and a :transferthe transfer exceeds the field's valuethe transfer into the fieldthe transfer, or a stated :priority
:discover-onceone :memo field and an :admissionthe memo is clear and the admission holdsthe memo0, or a stated :priority
:invalidationone :invalidated field and an :admission (dependency)the target is lit and depended on the sourcezero into the fieldthe level the target had; an independent lit target is instead handed to the companion frontier

A definition is checked against its family when it is defined, so a monotone program without a relaxed field fails before any realization. This is why the light program states only its transfer, and the terminal program only its admission: strict improvement, brightest-first scheduling, and visit-once memoization are what those families mean. #ZEENY3 adds the third dynamic of #DURBKN. Further families (A*-style external cost, bounded rounds) add methods on frontier-family-law-forms without touching any client.

defgeneric frontier-family-law-forms frontier.lisp:811
defgenericfrontier-family-law-forms
familycompilationcandidate-variablelowering-environment&keyseed-p
:documentation

Return (VALUES TEST-FORM COMMIT-FORMS PRIORITY-FORM OTHERWISE-FORMS) for one exposed target under family, given the lowering environment of bound field values. candidate-variable names the transfer result for monotone families, or the supplied value when seed-p says the target is being seeded rather than reached through a relation. OTHERWISE-FORMS run when the test fails, for families with a secondary effect. #FE0O5R

Bindings close a program over storage #716UN6

compile-frontier-program takes the definition, one frontier-field-binding per role, and a site-domain template. A binding names the represented-value declaration that gives the field its quantity and Lisp type (for light, the :sky-light voxel field definition and the light-opacity slot declaration), the lanes it borrows once per materialization, and read and write templates over those lanes:

frontiers:make-frontier-field-binding'opacity:declaration:lanes'
losses:type
simple-array
unsigned-byte8
indices
light-region-entry-indicesmaterialization
:type
simple-array
unsigned-byte16
:read'
areflosses
arefindicesoffset

The emitted loop binds the raw bucket vectors and counters once, borrows a popped source's lanes and reads its field values once per pop, and at each relation either reuses those lanes (a local step) or borrows the crossing materialization's (an if crossing). Field values are read into declared variables, so the inlined law is fixnum arithmetic over (unsigned-byte 8) reads. A :lazy binding is instead read where the law mentions it, which lets a short-circuiting admission skip an expensive probe. The popped site is validated once and its relations are primitive fixnum steps through do-chunk-site-neighbors (#FGT96H). Nothing per relation is generic, rechecked, or allocated; the only allocation left in a warmed drain is the window's coordinate key at chunk crossings (#L84JCX), and a test bounds it by the crossing count.

The brightest-first layout takes its bucket count from the relaxed field's legal values, so the frontier's priority meaning is the field definition itself. Realizations are cached per bound field and invalidated by the definition's revision, so redefining the program in a running image recompiles on next use.

defun compile-frontier-program frontier.lisp:923
defuncompile-frontier-program
program&keybindingssite-domain
compilet

Close program over field bindings and emit its scalar realization.

site-domain is a form over MATERIALIZATION yielding the chunk domain that gives a site's dense offset spatial meaning. Each field role of the program must have one frontier-field-binding. The laws are parsed and quantity checked against the bound fields, lowered with scalar arithmetic, and spliced into one closed loop over raw buckets and lanes. With compile NIL the forms are emitted but not compiled, for inspection. #53Q1II #T2G95K #716UN6

let*
definition
if
symbolpprogram
or
error"No frontier program named ~S."program
program
roles
frontier-program-definition-fieldsdefinition
constants
frontier-program-definition-constantsdefinition
fields
mapcar
lambda
role
let*
name
frontier-field-role-namerole
binding
or
findnamebindings:key#'frontier-field-binding-name
error"Program ~S field ~S is unbound."
frontier-program-definition-namedefinition
name
flet
lanes
which
loopfor
lane-name
in
frontier-field-binding-lanesbinding
collect
conslane-name
make-symbol
formatnil"~A/~A/~A"whichnamelane-name
make-instance'frontier-lowered-field:bindingbinding:source-parameter:target-parameter:source-lanes
lanes'source
:target-lanes
lanes'target
:source-variable:target-variable
roles
predicates
frontier-program-definition-predicatesdefinition
constant-parameters
mapcar
lambda
name
constants
predicate-parameters
mapcar
lambda
predicate
make-frontier-parameter
frontier-relation-predicate-namepredicate
nil
predicates
environment
append
loopforloweredinfieldscollect
cons
lang:arithmetic-object-name
lowered-field-source-parameterlowered
lowered-field-source-parameterlowered
collect
cons
lang:arithmetic-object-name
lowered-field-target-parameterlowered
lowered-field-target-parameterlowered
mapcar
lambda
parameter
cons
lang:arithmetic-object-nameparameter
parameter
appendconstant-parameterspredicate-parameters
compilation
make-instance'frontier-compilation:definitiondefinition:fieldsfields:constantsconstant-parameters:predicatespredicate-parameters:environmentenvironment:site-domainsite-domain
unlesssite-domain
error"COMPILE-FRONTIER-PROGRAM needs a :SITE-DOMAIN template."
dolist
loweredfields
let
role
find
frontier-field-binding-name
lowered-field-bindinglowered
roles:key#'frontier-field-role-name
when
and
frontier-field-binding-lazy-p
lowered-field-bindinglowered
or
frontier-field-role-relaxed-prole
frontier-field-role-memo-prole
error"The ~S field is relaxed or a memo and cannot be bound lazily."
frontier-field-role-namerole
dolist
predicatepredicates
when
and
eq
frontier-relation-predicate-kindpredicate
:direction=
not
member
frontier-relation-predicate-argumentpredicate
constants
error"Predicate ~S names ~S, which is not a program constant."
frontier-relation-predicate-namepredicate
frontier-relation-predicate-argumentpredicate

Parse and check the laws.

setf
compilation-transfercompilation
parse-frontier-lawcompilation
frontier-program-definition-transferdefinition
compilation-admissioncompilation
parse-frontier-lawcompilation
frontier-program-definition-admissiondefinition
compilation-prioritycompilation
parse-frontier-lawcompilation
frontier-program-definition-prioritydefinition
let
relaxed
whenrelaxed
ensure-law-fits-field
compilation-transfercompilation
relaxed"transfer"
ensure-law-fits-field
compilation-prioritycompilation
relaxed"priority"
let*
relaxed-binding
andrelaxed
lowered-field-bindingrelaxed
maximum-priority
drain-form
admit-form
relate-form
make-instance'frontier-realization:definitiondefinition:revision
frontier-program-definition-revisiondefinition
:bindingsbindings:site-domainsite-domain:maximum-prioritymaximum-priority:priority-meaning
andrelaxed-binding
frontier-field-binding-declarationrelaxed-binding
:transfer
compilation-transfercompilation
:admission
compilation-admissioncompilation
:priority
compilation-prioritycompilation
:drain-formdrain-form:admit-formadmit-form:relate-formrelate-form:drain-function
andcompile
compilenildrain-form
:admit-function
andcompileadmit-form
compileniladmit-form
:relate-function
andcompilerelate-form
compilenilrelate-form

Terminal walls are the second compiled client #55IRJO

#K3PCP3 asked for terminal discovery as a deliberately simpler client. It now is one program:

frontiers:define-frontier-programterminal-surface-discovery:family:discover-once:frontier-layout:lifo-stack:neighborhood
:voxel-relationscoplanar-directions
:fields
visited:memot
terminalexposed
:constants
materialoutwardabsent-neighbor-policycoplanar-directionsmemo
:admission
and
terminaltarget
exposedtarget
:retain-admissionst

Its window is the block world itself, whose chunks are the materializations and whose locate-chunk-window-site continues a step across a seam. The memo is a per-chunk bit vector owned by one discovery's table; terminal is an eq against the constant material through the chunk's content column; exposed is a lazy probe of the outward neighbour. Because the program retains admissions, the execution hands back the component as one packed buffer of chunk and offset, and find-terminal-surface folds that into projections and a rectangle test. The old hash-of-coordinate-lists walk is gone; the earlier expectations (rectangle, L-shape, covered, wrong material) and a seam-straddling rectangle whose retained component is exactly its eighteen blocks are the tests.

Invalidation is a family with a companion frontier #ZEENY3

Removing a source, or a departed neighbour, leaves levels no surviving source justifies. #DURBKN argued that this is a different dynamic from addition, not an option on it; it is now the :invalidation family, and voxel light's removal program reads:

frontiers:define-frontier-programvoxel-light-removal:family:invalidation:frontier-layout:brightest-first-buckets:neighborhood:voxel-face-relations:fields
level:invalidatedt
:constants
direct-direction
:predicates
direct
direction=direct-direction
:admission
or
<
leveltarget
levelsource
anddirect
=
leveltarget
levelsource
:retain-admissionst

Three things distinguish the family. First, the source's value is not a field read: a cleared site's field is already zero, so (level source) is the priority it was admitted at--the level it had. Second, the family has a secondary effect: a lit target that the source did not feed is a surviving source, and the drain hands it to a companion frontier--here the addition program's--at its own level, counted as an emission. Third, the retained admissions are the cleared set, which the client walks afterwards to re-admit emitters and relate open sky (#581ZQP) before draining addition.

The compiled reconciler in frontier-light.lisp composes exactly the legacy sequence from these words: invalidate dirty cells and departed neighbours' faces (admit with the old level), drain removal with addition as companion, reseed emitters and open sky over the cleared set, seed arrivals (relate for sky, admit for emitters, schedule for resident neighbours' facing sites, whose values already stand but whose relations must be exposed again), then drain addition. reconcile-lighting selects it through *voxel-light-solver* :compiled.

Evidence is differential and exact: the incremental, random-edit, departure, re-arrival, same-key replacement, and cross-chunk crystal tests run under both reconcilers against the from-scratch reference; a roofing test checks that sky removal clears exactly the sixteen cells of the beam and emits survivors. Over forty ten-edit bursts on six chunks both reconcilers visited 121,110 cells; the compiled one settled a burst in a median 0.55 ms against the legacy 1.25 ms.

The shared questions are now concrete #7U572V

The frontier repository and luvcraft's two clients replace the vague question “should we generalize the flood fill?” with questions that can be answered in code and measurements:

The exciting criterion is semantic compression with mechanical strength: clients share storage and iteration laws, retain their own meanings, allocate no per-edge garbage, and become easier to read and observe than their separate predecessors. If several modules can become short declarations of their world laws while the generated or macro-expanded loops remain excellent, that is not abstraction for its own sake. It is the engine discovering one of its native languages. #53Q1II now names the compiler architecture which makes that criterion explicit rather than leaving specialization to macro convention or implementation luck.

Tracy aligns temporal structure with semantic work #J5KRQ9

with-cpu-trace-zone is one instrumentation vocabulary with two independent observers. Its outer observer is a real Tracy zone. When Tracy is stopped, the path is one special-variable test. When Tracy is running, a literal zone uses an interned foreign source location and one begin/end FFI pair. The inner observer is luv's bounded cpu-trace tree, enabled only around an explicit retained capture. It samples host time, allocated bytes, and GC clocks at zone boundaries. The frontier code does not maintain a third per-execution stopwatch: retained executions keep semantic counters, while Tracy and the explicit A/B observation own time.

This division follows the instruments' actual powers:

InstrumentBest question
Tracy zoneswhich temporal region was active, nested under which thread and frame?
Tracy zone valueshow much semantic work did this particular interval perform?
Tracy plotshow did allocation or GC observations change along the capture timeline?
runtime observationhow many process-wide bytes and collections crossed one explicit A/B extent?
SB-SPROF allocation modewhich sampled Lisp call stacks were active at allocation-region refills?
source and disassemblywhich exact form allocates, dispatches, or escapes?

The drain zones now attach their visit count through Tracy's zone-value API. The A/B comparator emits reference/candidate allocated-byte, GC-millisecond, and collection-count plots. A thirty-pair capture therefore showed every sky drain beside the value 30,534, and the steady allocation samples for both solvers converged to 1,179,696 bytes after #GJZL85. A separate sixty-pair capture measured mean sky propagation at 23.03 ms legacy and 27.63 ms frontier. Tracy thus says both when and how much semantic work; the allocation plot rules out GC as the steady explanation for the remaining time gap.

Tracy also has a C memory-allocation API, but using it honestly would require allocator-level object addresses and matching frees. SBCL owns a moving generational heap, so emitting a fake Tracy allocation for each sampled byte delta would manufacture object identities and lifetimes that do not exist. For Lisp heap attribution, zone-level byte deltas plus SB-SPROF and compiler inspection are the sounder composition.

Fast generic functions can specialize a sealed semantic domain #U84XNW

Marco Heisig's fast-generic-functions turns a CLOS generic function into a compiler-specializable one. A client defines the generic function with fast-generic-function as its metaclass, seals a chosen argument domain after installing methods, and supplies enough static argument type information at call sites. On SBCL, the library installs IR1 transforms. The default optimized call bypasses the discriminating function and calls a compiled effective method directly; when every applicable method declares the inlineable method property, it can inline the complete effective method.

This is a beautiful fit for closed physical realization beneath an open semantic boundary, but sealing has exact consequences. No method may later change behavior inside the sealed domain. User-defined standard classes must participate through a sealable metaclass and externalizable prototype instances. The project itself recommends putting definitions, methods, and sealing in separate load stages and measuring with sealing disabled as an A/B control.

The current light result makes its relevance precise:

There are therefore two excellent proof candidates. One makes the frontier accessors fast generic functions and seals the bucket-frontier domain. The other binds the CLOS owner's raw buckets and counters once, runs a compiler-visible drain over local primitive state, and writes the counters back at the boundary. The former tests whether sealed CLOS can itself be the zero-overhead physical language; the latter preserves unrestricted live CLOS at the boundary. Comparing their generated code, live redefinition behavior, and whole-solver Tracy capture remains informative. The compiler proposal #53Q1II gives the second candidate a larger meaning: raw binding is not an adapter around CLOS but one deliberate lowering of an open semantic program. Fast generic functions remain a valuable A/B realization, not a prerequisite for zero-overhead frontier semantics.

DONE Remove the per-admission type construction #GJZL85

Intent: explain and remove the frontier solver's measured allocation excess without weakening the semantic frontier API.

Evidence: bucket-frontier-push constructed `(integer 0 ,maximum-priority) for every runtime typep. Three conses per admission predicted approximately 108 KiB for the 2,304 initial sky sites and 1.27 MiB for propagation, matching the phase measurements. Replacing it with integer and range predicates changed forty terrain sky propagations from 88.18 MiB to 37.24 MiB; the legacy batch used 37.56 MiB. Frontier seeding fell to 6.82 MiB versus legacy's 8.37 MiB. A focused warmed test now admits and removes 8,192 sites under a 4 KiB allocation ceiling.

Done when: allocation attribution predicts the measured delta, the physical fix preserves exact field and visit equality, and a regression rejects a return of per-site type construction.

DONE Begin frontier light beside the oracle #DVUZ6H

The first greenfield program has its own inspectable declaration, packed brightest-first frontier, relation traversal, counters, exact oracle comparison, and live selector. It reuses capture and publication on purpose: those shared boundaries make the A/B result exact while the new execution model proves itself.

A warmed two-chunk live-image snapshot ran seven exact A/B pairs. Legacy solves ranged from 11.7 to 12.3 ms and frontier solves from 15.7 to 16.3 ms on this machine. The nested trace localized the present difference to frontier sky seeding and propagation. This is an optimization map, not a verdict on the language: both programs visited the same sites and produced identical fields, while the new semantic boundaries made their physical cost directly comparable.

DONE Compile the monotone light kernel to scalar Lisp #PJY6E1

Intent: turn the manually staged frontier-light proof into the smallest real compiler path described by #53Q1II. Reify the local transfer, join, admission, and priority arithmetic with checked field meanings; make the program definition drive a scalar execution plan; and emit one closed Lisp loop over bound raw storage. Keep the existing handwritten frontier solver and legacy solver unchanged as two independent oracles.

Evidence: voxel-light-addition now carries its fields, constants, predicates, and transfer (#T2G95K); compile-frontier-program (#716UN6) realizes it once over the sky field and once over the block field, and solve-light-region-using :compiled drives both. On the three-chunk proof world the compiled solver produces the legacy oracle's exact sky and block arrays with the same 12,458 visits, and its executions report the same visits, relations, and crossings as the handwritten frontier lowering. On fifteen alternating solves of the nine-chunk little world all three programs made 30,534 visits; medians were 22.9 ms for the legacy solver, 28.0 ms for the handwritten frontier program, and 20.3 ms for the compiled kernel, with 1.1 MiB allocated by each. A batch of forty captures took 920, 1150, and 813 ms respectively. Once the emitted loop stepped through the trusted scope of #FGT96H, the compiled median fell further to 6.1 ms and the batch to 242 ms. The emitted form is inspectable and inlines the checked light-propagation-loss law as ordinary fixnum arithmetic; a warmed drain over the proof world's 68,000 relations allocates only the crossing lookups. The one supporting arithmetic-language change was a scalar lowering mode plus logical and, or, and not.

Done when: one inspectable source definition can be recompiled in the live image; its generated scalar realization contains no per-site generic dispatch or allocation; its sky and block fields and visit counts agree exactly with both current oracles; its emitted form and compiler output are inspectable; and Tracy attributes any remaining cost at the same semantic zones. All of these hold; SIMD, GPU lowering, invalidation, and a final surface syntax remain outside this proof.

The later retirement cut kept that proof but removed both old runtime choices. Production calls can now reach only the compiled realization; the simple from-scratch oracle and comparator load only with luvcraft/light-reference.

defun solve-compiled-light-region frontier-light.lisp:121
defunsolve-compiled-light-region
region

Solve region from scratch with the compiled voxel-light realization. #PJY6E1

let*
sky-execution
block-execution
frontiers:make-realization-executionblockregionblock-frontier
with-cpu-trace-zone
:lighting/compiled/seed-sky
seed-compiled-sky-boundariesskyregionsky-frontiersky-execution
with-cpu-trace-zone
:lighting/compiled/propagate-sky
with-cpu-trace-zone
:lighting/compiled/drain-sites:tracy-value
frontiers:frontier-execution-visitssky-execution
frontiers:drain-frontier-realizationskyregionsky-frontiersky-execution:direct-direction+voxel-negative-y+
with-cpu-trace-zone
:lighting/compiled/seed-block
seed-compiled-emittersblockregionblock-frontierblock-execution
with-cpu-trace-zone
:lighting/compiled/propagate-block
with-cpu-trace-zone
:lighting/compiled/drain-sites:tracy-value
frontiers:frontier-execution-visitsblock-execution
frontiers:drain-frontier-realizationblockregionblock-frontierblock-execution:direct-directionnil
valuesregion
+
frontiers:frontier-execution-visitssky-execution
frontiers:frontier-execution-visitsblock-execution
listsky-executionblock-execution
defparameter *voxel-light-solver* light.lisp:420
defparameter*voxel-light-solver*:compiled

The voxel-light program selected for production solves.

Only :COMPILED is implemented by the runtime. The legacy implementation is loaded explicitly by the LUVCRAFT/LIGHT-REFERENCE system as a differential test oracle; unsupported names signal through the closed EQL dispatch. #X7Q90E #PJY6E1 #K3WRD3

DONE Compile the sky seeds as boundary transfers #581ZQP

Intent: let the realization admit a virtual open-sky source through the program's own transfer law, so seeding stops restating the loss arithmetic in client code and a boundary is just a relation whose source is not a site.

Evidence: every realization now also emits a relate entry (relate-frontier-realization-site): the source role's field values arrive as keyword arguments named by role, the relation direction as an argument, and the crossing predicate is true, after which the target is tested, committed, and admitted by exactly the relation body. Sky seeding calls it with :level 15 and the inward direction of each open face; the loss arithmetic no longer appears in frontier-light.lisp. Fields and the 12,458 proof-world visits are unchanged against both oracles, and a test relates one virtual source straight down (15), laterally (14), into an opaque cell (not admitted), and dimly into an already-brighter site (not admitted).

Done when: sky seeding calls a compiled entry with the source level and the inward direction, the transfer law appears once in the program, and the compiled solver's fields and visits are unchanged. All hold.

defun seed-compiled-sky-boundaries frontier-light.lisp:78

The compiled solver. Seeds and drains both go through the realization: a sky boundary is a virtual source at full brightness whose loss follows the same law, and an emitter is a value joined into the block field.

defunseed-compiled-sky-boundaries
realizationregionfrontierexecution&keykeyentry

Relate open sky into every open face of region's entries, or of entry.

flet
seed
keyentry
dolist
when

Open sky is a virtual source at full brightness beyond the face; the relation into the entry runs the other way. The program's own transfer law decides the level and admission. #581ZQP

let
map-entry-face-sitesentrydirection
lambda
offsetlocal
valueslocal
frontiers:relate-frontier-realization-siterealizationregionfrontierexecutionentryoffsetinward:direct-direction+voxel-negative-y+:level+maximum-light-level+
ifentry
seedkeyentry
maphash#'seed
light-region-entriesregion
defclass frontier-realization frontier.lisp:468

------------------------------------------------------------------------ Realizations

defclassfrontier-realization
definition:initarg:definition:readerfrontier-realization-definition
revision:initarg:revision:readerfrontier-realization-revision
bindings:initarg:bindings:readerfrontier-realization-bindings
site-domain:initarg:site-domain:readerfrontier-realization-site-domain
maximum-priority:initarg:maximum-priority:readerfrontier-realization-maximum-priority
priority-meaning:initarg:priority-meaning:readerfrontier-realization-priority-meaning
transfer:initarg:transfer:readerfrontier-realization-transfer
admission:initarg:admission:readerfrontier-realization-admission
priority:initarg:priority:readerfrontier-realization-priority
drain-form:initarg:drain-form:readerfrontier-realization-drain-form
admit-form:initarg:admit-form:readerfrontier-realization-admit-form
relate-form:initarg:relate-form:readerfrontier-realization-relate-form
drain-function:initarg:drain-function:readerfrontier-realization-drain-function
admit-function:initarg:admit-function:readerfrontier-realization-admit-function
relate-function:initarg:relate-function:readerfrontier-realization-relate-function
:documentation

One program compiled over bound fields into closed scalar Lisp.

TRANSFER, ADMISSION, and PRIORITY are the checked arithmetic expression graphs; DRAIN-FORM and ADMIT-FORM are the emitted lambda forms; the two functions are their compiled realizations. ADMIT-FUNCTION seeds one site through the same admission and commit law as a relation, or is NIL when the law needs a source. RELATE-FUNCTION exposes one relation from a virtual source whose field values are supplied as arguments, so a boundary such as open sky is the program's own transfer law rather than client arithmetic. #53Q1II #581ZQP

defun relate-frontier-realization-site frontier.lisp:565
defunrelate-frontier-realization-site
realizationwindowfrontierexecutionmaterializationoffsetdirection&restarguments

Expose one relation into MATERIALIZATION/OFFSET from a virtual source.

arguments supply the program's constants and, keyed by role name, the source field values the transfer reads; direction is the relation's direction as seen from that source. The target is tested, committed, and admitted by the same law as an ordinary relation. Return whether it was admitted. #581ZQP

apply
frontier-realization-relate-functionrealization
windowfrontierexecutionmaterializationoffsetdirectionarguments

DONE Give frontier light its own invalidation program #K3WRD3

Intent: state removal and incremental reconsideration in the same compiled vocabulary after the monotone kernel establishes its source and lowering boundary.

Evidence: #ZEENY3. voxel-light-removal is an :invalidation program whose compiled drain reads like unlight-light-region but is emitted from the family and the one dependency law; the compiled reconciler composes it with the addition program through admit, relate, schedule, and the companion frontier. Removal executions retain the cleared set and count visits, relations, crossings, admissions, and emissions (survivors handed on). Under *voxel-light-solver* :compiled every incremental test converges to the from-scratch reference across edits, emitters appearing and vanishing, departures, re-arrivals with fresh edits, same-key chunk replacement, and crystals across chunk boundaries; forty random edit bursts visit the same 121,110 cells as the legacy reconciler at a median 0.55 ms against 1.25 ms.

Done when: invalidation and re-admission are explicit program operations, executions retain stale and useful work counters, and the compiled program converges bit-for-bit with from-scratch frontier light across each residency and edit case above. All hold. The subsequent retirement cut removed the legacy incremental reconciler altogether; light-matches-reference-p now asks the separate luvcraft/light-reference system for a from-scratch oracle and compares that result with the production compiled path.

define-frontier-program voxel-light-removal frontier-light.lisp:168

Invalidation. Removing a source, an occluder's disappearance being an addition, or a departed neighbour can leave levels that no surviving source justifies. The removal program clears every level the removed site fed--strictly dimmer, or equal for direct sky continuing down--and re-admits the cleared site at the level it had; a lit neighbour it did not feed is handed to the addition frontier as a surviving source. The cleared set is the execution's retained admissions. #K3WRD3 #DURBKN

frontiers:define-frontier-programvoxel-light-removal:family:invalidation:frontier-layout:brightest-first-buckets:neighborhood:voxel-face-relations:fields
level:invalidatedt
:constants
direct-direction
:predicates
direct
direction=direct-direction
:admission
or
<
leveltarget
levelsource
anddirect
=
leveltarget
levelsource
:retain-admissionst
defun reconcile-compiled-lighting frontier-light.lisp:405
defunreconcile-compiled-lighting
stateregion

Settle state's dirty cells, departures, and arrivals over candidate region with the compiled removal and addition programs. Return the executions and the total visits. #K3WRD3

let
world
lighting-state-worldstate
with-cpu-trace-zone
:lighting/compiled/invalidate
maphash
lambda
declare
ignorepresent
multiple-value-bind
entryoffset
whenentry
invalidate-compiled-light-sitereconciliationentryoffset
lighting-state-dirty-cellsstate
maphash
lambda
declare
ignorepresent
dolist
let*
neighbor-key
entry
multiple-value-bind
chunkpresent-p
world-chunk-at-coordinateworldneighbor-key
andpresent-p
or
gethashneighbor-key
light-region-entriesregion
add-light-region-entryregionchunk:from-field-pt
declare
dynamic-extentneighbor-key
whenentry
lighting-state-departuresstate
with-cpu-trace-zone
:lighting/compiled/remove
with-cpu-trace-zone
:lighting/compiled/reseed
map-cleared-light-sites
lambda
entryoffset
reseed-compiled-emitterreconciliationentryoffset
second
compiled-light-reconciliation-removal-executionsreconciliation
map-cleared-light-sites
lambda
entryoffset
reseed-compiled-open-skyreconciliationentryoffset
first
compiled-light-reconciliation-removal-executionsreconciliation
maphash
lambda
declare
ignorepresent
lighting-state-arrivalsstate
with-cpu-trace-zone
:lighting/compiled/propagate
let
executions
append
compiled-light-reconciliation-removal-executionsreconciliation
compiled-light-reconciliation-addition-executionsreconciliation
valuesexecutions
reduce#'+executions:key#'frontiers:frontier-execution-visits
deftest compiled-random-edits-and-residency-match-the-reference-solver light-tests.lisp:584
deftestcompiled-random-edits-and-residency-match-the-reference-solver

The compiled removal and addition programs must reproduce the reference field across the same edit bursts, departure, and re-arrival. #K3WRD3

defparameter *voxel-light-solver* light.lisp:420
defparameter*voxel-light-solver*:compiled

The voxel-light program selected for production solves.

Only :COMPILED is implemented by the runtime. The legacy implementation is loaded explicitly by the LUVCRAFT/LIGHT-REFERENCE system as a differential test oracle; unsupported names signal through the closed EQL dispatch. #X7Q90E #PJY6E1 #K3WRD3

defgeneric reconcile-light-region-using light.lisp:629
defgenericreconcile-light-region-using
solverstateregion
:documentation

Settle state's dirty cells, departures, and arrivals over candidate region with the explicitly implemented incremental relighter named by solver. There is deliberately no default method: unsupported names signal rather than falling back to a different algorithm. #K3WRD3