- readsthis repo's live issues and PRs
- becomesactivity + recency → mass; references bind items
- writes
--w--field-attention - you seeactive work reads heavy; referenced items move together; the cycle fills like a vessel
No canvas is drawn here — the field is invisible; these variables are its only output. Without it you would build: a priority field, a linked-issues query, and a sprint board.
field-ui · invisible fields · backlog
Work has weight.
This one is the repo measuring itself: the 57 most recent work items from field-ui's own repository — the issues and pull requests that built the engine rendering this page. A tracker flattens them into identical rows; here each item is a body, and its mass is a blend of activity (discussion) and freshness (how recently it was touched). Heavier items read darker, heavier, more anchored.
Work also binds: when an item references another, hovering it threads back to what it builds on — across lanes. The board has two: In flight and Shipped, and the shipping cycle has visible capacity — everything closed or merged in the 14 days before the snapshot accretes into the bar that heads the Shipped lane. Switch the weighting and watch each lane re-settle; toggle the field off and it collapses to a plain tracker. And the cards drag — pick one up and triage the board by hand. It's a local sandbox: the arrangement saves in your browser, and GitHub is never written.
size = activity, comment-leaning — the items people argue about carry the mass · color = kind — teal pull requests, blue issues
- Aa size = the weighting signal
- color = kind (teal PR · blue issue)
- hover → threads to the items it references
- the cycle bar is a sink — shipped work accretes into it
- the soft glow = live density — the hidden
engine writes
--dto every card each frame; it gathers under your cursor and ebbs back
drag to triage — local only, GitHub unchanged
Draggable work item. Press Space or Enter to lift the card, then arrow keys to move it: up and down within the lane, left and right across lanes. Press Space or Enter again to drop, or Escape to cancel. Rearranging is a local triage sandbox — GitHub is not modified.
In flight 3
Shipped 54
- #293 PR merged feat: FieldHandle diagnostics, packaging checks, DataConsole perf panel, observable surface docs
- #292 PR merged feat(site): atom card close button + fix all 132 particle link targets
- #279 PR merged feat(elements): Custom Elements Manifest for the field-ui web components
- #291 PR merged feat(home): atom inspect — dwell-to-focus a particle, click to open (no auto-tooltip)
- #290 PR merged perf(site): cache the project atoms in IndexedDB (localStorage fallback)
- #288 PR merged feat(site): evidence — a colour lens (a second visual channel from the engine)
- #289 PR merged feat: particles carry data — the home field is seeded with the 132 project atoms
- #287 PR merged feat(site): Evidence Field — controls + legend so the uniqueness is clear
- #286 PR merged docs(site): CDN hero, @fundamental-engine/vanilla as default door, demote kit
- #282 PR merged feat(site): home 'Gallery' chapter — a live bench of what the field can do
- #284 PR merged feat(site): /evidence — the Evidence Field (field-ui, no particles, real OpenAlex data)
- #285 PR merged docs: coherence pass for @fundamental-engine/core, kit, and CI provenance release
- #281 PR merged docs+release: expand adapter READMEs, add provenance workflow (0.2.2)
- #280 PR merged feat(site): hero → @fundamental-engine/elements + @fundamental-engine/kit on the install grid
- #278 PR merged Scope core as @fundamental-engine/core, publish 0.2.1, add @fundamental-engine/kit umbrella
- #277 PR merged fix(site): install + version-posture coherence; resolve web-platform citations
- #276 PR merged docs: honesty + accuracy pass (perf measured, paper review wording, contract delimiter)
- #275 PR merged refactor(site): centralize the Field Manual chrome into shared components
- #274 PR merged feat(site): foundation fields + Body Interaction Model below the home substrate
- #273 PR merged fix(site): remove the broken StartHereLede container from the home
- #272 PR merged feat(site): eli5 — Body interaction model section (interactive sink/accretion)
- #271 PR merged feat(site): eli5 ch.II — Natural Field names + per-field visual grammar
- #269 PR merged feat(site): recipes hub + per-recipe pages with live previews (Phase 1)
- #268 PR merged refactor(recipes): rename tiers to a complexity ladder (applied/systems/operational)
- #267 PR merged docs: rebuild forces-engine.md against current main
- #266 PR merged feat: Field Surfaces — render the field over & under content (setOverlay API)
- #265 PR merged feat(site): eli5 four forces play OVER + UNDER the content (immersive)
- #262 PR merged fix: catalog field:relocated + correct stale 34→35 force count
- #261 PR merged docs/site: align terminology with the Field Agent Consumption Model
- #258 PR merged feat(site): refactor /eli5 into a story that builds (Substrate-style)
- #283 PR merged fix(site): hero → @fundamental-engine/kit, dynamic footer version, document the kit
- #254 PR merged docs/site: api/options shows required host; drop dead study metric keys
- #252 PR merged fix: risk supplied-only (#226) + memory classification guard (#227)
- #245 PR merged docs(writings): add "field-ui, explained simply" — the plain-language tour
- #251 PR merged feat(site): add /eli5 — a playful second homepage (ELI5 narrative)
- #270 PR merged feat(recipes): generated local datafile of the recipe catalog (data/recipes.json)
- #264 PR merged feat(site): make eli5 ch.II four forces interactive on the main field
- #263 PR merged docs: force count 34→35 in Paper 1 (+ site copy); tighten inspect floor
- #222 PR merged fix(platform): compute real relationship resolution (stop hardcoding relResolved = relTotal)
- #223 PR merged fix(core): classify memory as a semantic metric, not a physical natural force
- #239 PR merged fix: unbreak main — @fundamental-engine/core in research papers + HomeHero metric claim
- #220 PR merged fix(platform): never fabricate confidence from relationship presence
- #244 PR merged feat(site): /writings datastore section — mermaid, latex, code; research migrates in
- #229 PR merged feat(site): Wave 2 — /docs/narrative on the data-attribute model + FieldLoopDemo render fix
- #234 PR merged fix(site): diagnostics export reflects active mode; snapshots is a reference table
- #240 PR merged feat(site): publish the field-ui research paper family at /research
- #241 PR merged feat(site): render research-paper math with KaTeX
- #250 issue closed docs/site: study mappers pass undeclared metrics + RenderLayer particles-vs-dots naming (low)
- #249 issue closed docs/site: api/options FieldOptions table omits host (required) + feedbackSink
- #248 issue closed docs: interaction-and-relationship agent-type union vs FieldAgentKind (precision)
- #247 issue closed docs: authoring-and-recipes has fabricated tokens + incomplete schema (§4/§5/§7/§10)
- #246 issue closed docs: visualization-methods-taxonomy render-mode table is stale (lists nonexistent modes)
- #227 issue closed decision: memory passport family axis (natural vs extended vs new metric value)
- #226 issue closed fix(platform): risk metric defaults to 0 (same anti-pattern as the confidence default)
How it's built
Every work item is an ordinary <li> with a few data attributes — the
GitHub API response, flattened into markup. field-ui runs an invisible field over the
list and the type carries the measurement: activity as weight, kind as color, references
as hover threads. No canvas, no chart library. Two live channels ride on top: the page's
hidden engine writes --d (local particle density) to every
data-hot card each frame, and the scoped recipe's attention lane writes an
eased --field-attention — CSS turns both into a felt glow and lift, and both
go quiet when the field is off. Each card also declares its updatedAt as
data-field-at, so the pipeline's recency lane is grounded in the data's own
timestamp — --field-recency is freshness(updatedAt, now), decaying
against the real clock rather than inferred from interaction. The drag is hand-rolled pointer events — no library, no
HTML5 drag-and-drop — and it's a local triage sandbox: the arrangement persists to
localStorage, and GitHub is never written.
1 — each work item is a field body
<li
id="wi-294"
data-body="attract"
data-strength="1.42"
data-feedback
data-hot
data-act="0.91" data-rec="0.99"
data-field-at="2026-06-09T22:41:00Z"
data-field-halflife="86400000"
data-refs="wi-282 wi-269"
style="--w: 0.94; --cat: #2dd4bf;"
>
<!-- #number · kind · title · author -->
</li>
<!-- data-rec is the snapshot's freshness —
freshness(updatedAt, snapshot, 24h), the
@fundamental-engine/core temporal kernel. data-field-at
declares the same updatedAt as WORLD TIME, so
the platform's recency lane is grounded in the
data: --field-recency = freshness(at, now). --> data-act/data-rec— the normalized signals the lenses re-blend (data-recis thefreshness()kernel overupdatedAt, half-life 24h)data-field-at— the declared world timestamp; the platform grounds its recency lane in it (--field-recency)data-refs— the items this one references (the hover threads)data-strength— gravitational mass from the blended weightdata-hot— opts into the live density gather: hover and--dclimbs toward 1
2 — the cycle bar's two honest channels
/* the cycle bar is a real sink body that also
declares itself as its own measurement:
<div id="wl-cycle" data-body="sink" data-absorb
data-max="8" data-feedback data-hot
data-field-visual-for="#wl-cycle"
data-field-visual-role="measurement">
channel 1 — data arithmetic: the FILL is
shipped ÷ capacity from closedAt dates. */
width: 100%; /* 54/20 this cycle */
/* channel 2 — the live engine: --load (0..1) as
particles accrete into the sink, blended with
--live (the engine's local density, --d). */
box-shadow: 0 0
calc((var(--load, 0) + var(--live) * 0.5) * 22px)
color-mix(in srgb, var(--accent)
calc(var(--load, 0) * 40% + var(--live) * 20%),
transparent);
Two channels, kept honest: the fill is static math over the snapshot's
closedAt dates; the glow is the live engine — --load from a
real sink body, blended with the local density --d. The bar
also names itself as a measurement visual
(data-field-visual-for), so its provenance is declared, not implied.
3 — CSS reads the weight and the live channels
.wl-title {
font-variation-settings:
'wght' calc(380 + var(--w) * 360);
}
.wl-item {
/* --d: the engine's live local density,
written every frame; it gathers toward 1
when a data-hot card is hovered/focused.
--field-attention: the scoped recipe's
eased attention lane (hover/focus +
viewport-center proximity + visibility). */
--live: var(--d, 0);
box-shadow: 0 0 calc(var(--live) * 16px) -6px
color-mix(in srgb, var(--cat)
calc(var(--live) * 55%), transparent);
background: color-mix(in srgb, var(--text)
calc(1.5% + var(--w) * 4% + var(--live) * 4%
+ var(--field-attention, 0) * 4%),
transparent);
}
Switching the lens re-blends --w from data-act and
data-rec, then FLIP re-sorts each lane so the reflow is felt, not cut —
on the current arrangement, so re-sorting a hand-triaged lane re-orders it;
the lens always wins the order. The glow and lift read --d and
--field-attention — both written by the running field, both zeroed when
it's off.
4 — the drag is pointer events, by hand
// hand-rolled pointer drag — no library, no HTML5 DnD.
card.addEventListener("pointerdown", (e) => {
if (e.target.closest("a")) return; // links still click
pend(e); // arms only after 6px of travel
});
function lift(card, e) { // past the threshold
card.setPointerCapture(e.pointerId);
placeholderFor(card); // a gap holds the origin slot
card.classList.add("wl-drag"); // fixed, grabbing,
// touch-action: none
// pick a card up and the field re-measures it in
// flight: data-active marks the body engaged, so the
// attention metric writes a rising --field-attention.
card.setAttribute("data-active", "");
}
function track(e) { // every pointermove
card.style.transform = `translate(${e.clientX - x0}px,
${e.clientY - y0}px) scale(1.03)`;
placeSlotIndicator(e); // the slim line between cards
edgeScroll(e.clientY); // ±60px, proportional speed
}
function drop() { // pointerup — Esc/pointercancel aborts
insertAtSlot(card); // displaced cards FLIP-settle
card.removeAttribute("data-active");
recountLanes(); // counts + cycle bar go "(local)"
save(); // localStorage only — GitHub is never written
}
Pick a card up and the field re-measures it in flight: data-active marks
the dragged body as engaged, so the attention lane's --field-attention
rises while you hold it. Drops FLIP-settle the displaced cards, recount both lanes,
and re-run the cycle arithmetic — marked (local) when it diverges from the
snapshot. Keyboard works too: Space lifts, arrows move, Escape cancels.