API reference

Platform parity matrix

Which FieldHandle methods ship on each surface. JS is the source of truth. @fundamental-engine/three delegates all 52 methods to the wrapped engine — 52/52. Swift (50/52) and Kotlin (50/52) are native ports, mirrored but currently trailing the newest additions (see the table below for which methods and why). The cross-plane physics is identical (the 36-force conformance suite asserts it) regardless of API-surface gaps. This matrix tracks API surface parity.

Three distinct axes — don't conflate them. API parity (this matrix): the FieldHandle method surface — 52/52 Three.js, 50/52 Swift, 50/52 Kotlin. Conformance: the force math matches, asserted by the shared cross-plane golden (the 36-force suite). Production readiness: packaging, platform polish, and docs — this is Preview and differs by host. Native ports are at FieldHandle API parity, but packaging, platform polish, and production-readiness differ by host.
How to read this table. A green chip means the method ships on that platform. A grey chip means it is not yet implemented (or not applicable for that platform — see the note column for context). The counts below each platform header show what fraction is covered.

FieldHandle coverage

Method Three.js
52/52 (100%)
Swift
50/52 (96%)
Kotlin
50/52 (96%)
Notes
scan
rescan alias of scan
setAccent
setPalette
setFormation
setWaveStyle
setWaveCenter
setSeparation Kotlin fun setSeparation(Float) coexists with var separation via @JvmName on the property
setAttention
setCausality
setHeatmap
setDprCap Three.js delegates but DPR is renderer-owned; native stores in FieldOptions / FieldHandle
setQualityTier
setRender render surface is host-owned on native + Three.js; Kotlin host reads renderMode
setOverlay use threeBackend() for Three.js diagnostic overlays
setBackground web canvas clearing; native stores in FieldOptions.background
threads visual layer — glowing connector lines
burst
flowTo
clearFlow
seed
addAgent AgentSpec / AgentHandle; Kotlin init-block wires tickAgents() via onAfterTick; Swift uses UUID-keyed agent list
addBody
addEdge
readEdges
addField
sampleField
atomAt
focusAt
clearFocus
particleCount
energy
query structured read of bodies/metrics/relationships; the influences/projections/dimensions lanes stay empty on the ports until an accumulator/registry/dimension lane lands (JS field names kept)
snapshot point-in-time field capture; body data withheld by default (tightest-wins profile)
diff pure comparison of two snapshots — added/removed/changed bodies, metric deltas, relationship + formation changes
replay causal replay over a snapshot pair; force-attributed steps empty-for-now on the ports (no impulse accumulator yet)
forAgent capability-scoped, redacted, read-only agent view (agent-readable is not agent-writable)
sample force-probe at world point; Swift delegates to forceAt(); Kotlin delegates to controller.sample() → forceAt()
sampleScalar
sampleGradient
grid named ScalarGrid — lazy get/create, same grid as env.grid in the force system
on UUID-keyed subscriber bus; FieldEvent enum (tick/bodyAdd/bodyRemove + captured/released, the JS bus keys; #1020); returns Subscription
readParticles
readParticleIds Particle.id (stable, auto-incremented by FieldStore.add); fills an Int buffer
readParticleChannels samples named ScalarGrids at each particle position; stride = names.count/size
registerOverlay OverlayRenderer protocol/interface; host reads overlayRegistry and calls render() each frame
scrollV DOM/UIKit scroll velocity; Kotlin: scrollV() + feedScrollV(); Three.js returns 0 in headless
setVisible
destroy
setPolicy runtime FieldPolicy (motion/privacy budgets); mirrored on all three planes
focus focus/attention substrate (EXPERIMENTAL, shipped 0.9.4) — operator/agent attention write; Swift + Kotlin ports are a batched follow-up
focusState focus/attention substrate (EXPERIMENTAL, shipped 0.9.4) — the ranked, thresholded attention read; Swift + Kotlin ports are a batched follow-up

Platform notes

All three platforms briefly shipped the full 44-method surface as of June 2026 (#822 Swift, #823 Kotlin) — the JS-side surface has grown since (now 52 methods; see the live counts above), and the ports have not fully caught up. Some methods behave differently across platforms by design:

Three.js — 52/52, host-context notes
@fundamental-engine/three delegates all 52 methods to the wrapped FieldHandle. Some are contextually different in a 3D scene: setRender / setOverlay / setBackground are owned by the Three.js renderer — use threeBackend() for diagnostic overlays. scrollV returns 0 (no DOM scroll). scan / rescan are called internally; in Three.js register bodies via layer.addBody(mesh, spec).
sample — force probe
Swift delegates to forceAt(bodies:forces:env:at:) in Streamlines.swift. Kotlin delegates to FieldController.sample() which calls the same forceAt() function used by the streamlines overlay. Both are safe to call between ticks.
on — event bus
Both platforms use a UUID-keyed subscriber registry (not closure equality, which doesn't hold across captures). FieldEvent.tick fires after every simulation step via an onAfterTick hook. bodyAdd / bodyRemove fire from the addBody / remove path. Returns a Subscription; call .cancel() to unsubscribe.
addAgent — autonomous consumers
AgentSpec carries a position closure sampled each tick; onInfluence receives the net force vector at that point. Agents are ticked via the same onAfterTick hook as the event bus, after each force step.
readParticleIds / readParticleChannels
Particle.id is assigned by FieldStore.add() via a monotonically increasing counter — stable for the lifetime of the pool. readParticleChannels samples each named ScalarGrid at each particle's position; the output stride equals the number of channel names.
registerOverlay
OverlayRenderer is a protocol (Swift) / interface (Kotlin). The FieldHandle keeps a [String: OverlayRenderer] registry the platform host frame loop reads to call render() after the underlay draw each frame. No deep engine integration — pure registry delegation.