Everything started and not finished, gathered out of a dozen plans into one list you could pick up from. · Rendered from docs/OPEN-WORK.md in the project repository · view as Markdown

Open work

Everything this repository has started and not finished, in one place. It was gathered on 2026-08-31 from the "still open", "not built" and "deferred" sections that were scattered across a dozen separate plans, and each item names the file and the code it was read out of so it can be checked rather than believed.

Two neighbours to this file:

An item leaves this file when it ships, and its plan — if it had one — moves to [archive/](archive/README.md).


0. Kerr black hole optics — the museum, the frame budget, and the art

[KERR-BLACK-HOLE-OPTICS.md](KERR-BLACK-HOLE-OPTICS.md) records what is built and every number it was measured at. Four things are open, and the first is by far the largest.

The museum (the plan's M5) — in, 2026-09-07, with the caveats the plan predicted

The Kerr black hole now stands at the end of the Golden Funnel, at the formula's origin five metres under the floor, in the owner's numbers: a* = 0.382 turning clockwise seen from above, a disk out to 60 r_g, H/r = 0.060, an optical depth of 0.35, everything else the study page's default. One and a half metres to the gravitational radius (2026-09-08: three times the diameter it opened at), so the disk is 180 m across in a room 240 m wide, the shadow 15 and the horizon nearly 6.

At that size the shadow is wider than the 5 m the exhibit hangs below the floor, so the dark region rises above the floor plane and a visitor standing beside it sees the black disc cut into the room rather than lie under it. Nothing solid moved: the horizon is 2.9 m and still well under. A shadow is the set of directions whose light was captured, not a surface, and those directions reach above the plane at every scale — it only shows as a rise once the shadow is bigger than the drop. The orb's vote now dresses the same hole in one of the tracer's three skins: the two words already on the wire (white, warm) name the ice and NASA skins and physical is new, so a server still on the two-word list drops a physical vote and the orb's own 2.5 s fallback wears it locally until the server's copy of presenceProtocol.js gains the word.

How it sits in the room (render/kerrExhibit.ts, KERR_MUSEUM_MAIN_GLSL, model/manifoldKerr.js), because each of these is a choice:

Still open, and named here rather than smoothed over:

The ride falls — a capture orbit, through the horizon, 2026-09-09

The Golden Funnel ends in a near-critical capture orbit watched from inside it (KERR-BLACK-HOLE-OPTICS.md §9b). The whole coaster stands 25 m above the hole, the ride runs to the spiral's point (0.6 m from the axis, 21 r_g from the hole), the camera is pushed in to the eye a turn and a half before the end and rides the last turns from it, and is thrown ALONG THE TRACK at 0.3221 c — the last speed this side of the separatrix, E = 1.0049, nearly polar — whirls about two turns between 5 and 4 r_g, falls, crosses the horizon and stops at 0.6 r₊, over 45 s of playback on a four-stretch schedule that shows the far part quickest and the crossing slowest, with the gas on the camera's clock and the aim riding the shadow's rim once the shadow is too big to look at; then three seconds of black, and the room. (A glowing line along the curve was tried and removed at the owner's word.) Recorded uncut from the museum's own canvas: assets/kerr-plunge/museum-capture.mp4.

Open:


1. Discovery — the three requirements that are still unmet

[DISCOVERY-SEO-GEO.md](DISCOVERY-SEO-GEO.md) lists these under "Still open". All three were re-checked against the build on 2026-08-31 and all three are still true.

R4 — the preview image is shared, not per room

Half done, 2026-08-31. The gap was total: no og:image existed anywhere, so no page had a link-preview thumbnail — and the landing page was worse than bare, because twitter:card = summary_large_image promises a big-picture card and there was no picture, so it rendered as a text box.

There is now one card for the whole site: public/og-cover-v1.jpg, 1200 x 630, a crop of the museum's own constellation portal. src/inception/discovery/socialCard.js owns it, both generated templates call it, index.html repeats it under test, and the build refuses if the file is missing from dist/.

What is still owed is what R4 actually asks for: a curated screenshot per room, rendered headlessly at build time — "a room, not a logo", because the card beside an answer about Van Gogh House should show Van Gogh House. The seam is ready for it: give socialCard.js a per-page lookup and let the shared card stay the fallback for pages that are not a room.

Two things to know before building it. Headless capture of this museum means booting WebGL, waiting for a room's textures to upload (see [PERFORMANCE.md](PERFORMANCE.md) — arrival is not instant) and reading the canvas back, which needs preserveDrawingBuffer or a capture inside the render loop. And a scraper caches a card by URL, so a new or changed image ships under a new -vN name rather than replacing bytes at the old one.

R5 — no hreflang pair

There is no hreflang in src/, scripts/ or index.html. The policy is EN + ZH, both indexable, paired. The blocker named in the requirement still stands: the room documents carry no translated title, so there is nothing to build a ZH twin out of yet. That is the first piece of work, and it is a content change to content/inception/rooms/*.room.json, not a renderer change.

R6 — noindex has been removed, and the rest of R6 has not been re-checked

The requirement says index.html carries <meta name="robots" content="noindex"> and keeps it until the public surface exists. That meta tag is no longer in index.html. Whether the public surface now genuinely satisfies R6 — public-snapshot layer, no real names, no class membership, no draft history — is a decision that should be recorded rather than inferred from a deleted line. The two automated guards (no owner email, no password, and a room in the sitemap only if its document says visibility: public) still run and still pass; they are narrower than R6.

Per-artwork pages

Rooms have pages; individual paintings do not, because the public-snapshot layer that decides what an artwork may say (execution plan §2.3) is not built.


2. Standalone mode — the missing half of import/export

From [UI-REPOSITORY-SCOPE.md](UI-REPOSITORY-SCOPE.md), which calls standalone mode the primary acceptance target.

There is exactly one file input in the whole client and it belongs to the publish flow. Standalone therefore has export and file-keeping only. Missing:

The document is explicit that building local import is the next piece of work and not a capability it should claim. Note the ordering rule in [CROSS-REPO-HANDOFFS.md](CROSS-REPO-HANDOFFS.md) Part 2: the .ispack contract belongs to Lucas Visual Art Lab and must not be re-derived here.

Sealed-collision coverage does not travel

The solidCollisionBox invariant — a sealed interior must cover a measured object's real geometry, not its centred footprint — is asserted by tests/inception-solid-interior.test.js in the source repository, because that test reads server/rooms.js. This repository has the collider fix and library-glb-collider.test.js, but no coverage of sealed collision. Splitting the server-free half of that test out is separate, unclaimed work.


3. Narration and subtitles

The Manifold rides have no recordings

[MANIFOLD-TOUR-NARRATION.en.md](MANIFOLD-TOUR-NARRATION.en.md) is confirmed by the owner and shipping as subtitles — src/inception/tour/manifoldNarration.js is the runtime source of truth — but no voice exists. The subtitles stand on their own until one does. English only, deliberately: the field for a Chinese caption track is left out rather than left empty.

The Van Gogh opening revision is still a proposal

[VAN-GOGH-DEMO-NARRATION.en.md](VAN-GOGH-DEMO-NARRATION.en.md) carries one proposed Phase 2 opening for the first painting that is editorial until the owner finalizes it; recorded cue 01-lines-and-people is unchanged and stays that way until then. tests/demo-narration-docs.test.js pins this: it asserts the document still says "This is a script proposal, not a new recording", so finalizing the copy means changing that test in the same commit.

The Chinese track is a review document, not a voice

[VAN-GOGH-DEMO-NARRATION.zh.md](VAN-GOGH-DEMO-NARRATION.zh.md) mirrors the English cue ids for review only. The demo plays the English recordings; no Chinese audio has been generated, and nothing authorizes it into the runtime.


4. The standalone demo runtime is scheduled for retirement, and still here

Issue #12 made the guided demo an ordinary museum visit driven by ?room=<id>&tour=<id>; the result is recorded in [archive/ROOM-LAUNCH-AND-TOURS.md](archive/ROOM-LAUNCH-AND-TOURS.md). The owner cancelled the earlier plan to relocate the standalone demo to lucasgame-academy (engine mismatch — that site has its own lesson-player), and accepted that the standalone runtime is retired rather than moved.

It has not been retired yet. Still present and still built:

demo/src/main.js
demo/src/shell.js
demo/src/world/{demoWorld,scene,input,readers}.js

Two pieces remain, and both are gated on a human watching the in-museum tour at real frame rates first — nobody has:

  1. reduce /demo to a thin shell that forwards into the museum entry;
  2. delete the old runtime modules above.

Do not schedule this from a browser-pane capture. The pane throttles requestAnimationFrame when hidden, so tour pacing measured there is not what a visitor sees.


5. The object library needs content, not code

[OBJECT-LIBRARY.md](OBJECT-LIBRARY.md) is complete end to end — ownership, R2 serving and the GLB prop renderer are all built and the museum draws from a bucket that holds reviewed objects. What it says remains is content:

The browsing half of that shipped as the object storage building and its item bar ([archive/OBJECT-STORAGE-BUILDING.md](archive/OBJECT-STORAGE-BUILDING.md)); the per-room placement control did not.

A room's door has no art and no editor control

[archive/ROOM-DOOR-AND-TRANSIT.md](archive/ROOM-DOOR-AND-TRANSIT.md) records the ownership rule as accepted by the owner, and the door's own art and its editor control as not built. A centre-out dissolve was tried and rejected the same day; the door stays the plain sheet of light the document describes. Anyone reopening this should read that rejection first.


6. .lpr — one guard gap, and a stale status line

[LPR-FORMAT.md](LPR-FORMAT.md) is the format's own contract and stays a living document. Two things in it are owed.

The recompile tripwire cannot see shader edits

npm run check recompiles every .lpp and compares to the committed .lpr.json byte for byte, so a compiler or registry change that would alter an existing painting fails before it can be committed. That guard is blind to GLSL: editing the shader for photo-nebula-breath@2 leaves every package byte-identical, check stays green, and every painting using that behavior quietly looks different. Today only the two-implementation cross-check tests stand in the way. The document names the fix if the vocabulary grows — a reference-render snapshot per behavior, hashing a small offscreen render — and it has not been built.

The status line is out of date

The document's own header still says "Nothing here is wired into the museum runtime — the inherited renderer still draws every room." That is no longer true: src/inception/artwork/lprSurface.ts, src/inception/artwork/lprMarksSurface.ts, src/inception/lpr/markShader.js and src/inception/world/render/paintScheduler.js are all in the runtime, and the GPU marks path has its own section in [PERFORMANCE.md](PERFORMANCE.md) dated 2026-08-17. The header needs rewriting by someone who can state what v2 still owes.

The corpus it points at, content/live-projects/, does not exist in this repository — the .lpp authoring masters stayed on the other side of the split, and only the compiled content/lpr/*.lpr.json outputs are here. So node scripts/lpp-report.mjs cannot be run from this checkout either.


7. Stale claims worth correcting when someone next edits these files

Small, and none of them affect the running museum — but each one will mislead the next reader.

WhereWhat it saysWhat is true on 2026-08-31
[UI-REPOSITORY-SCOPE.md](UI-REPOSITORY-SCOPE.md)Matthew's L-City floor is uploadState: pending, its R2 URL 404s, and it costs 451,541 bytes from the static host per cold visitThe manifest has no pending rows at all; matthew-l-city/floor-v1.jpg carries a real publicUrl, hash and distFile. The bill it describes has been paid
[DISCOVERY-SEO-GEO.md](DISCOVERY-SEO-GEO.md)index.html carries noindex and keeps itThe tag is gone — see §1 above
[LPR-FORMAT.md](LPR-FORMAT.md)nothing is wired into the museum runtimeIt is — see §6 above
[archive/R2-STATIC-ASSET-MIGRATION-EXECUTION-PLAN.en.md](archive/R2-STATIC-ASSET-MIGRATION-EXECUTION-PLAN.en.md)Status: ready for implementationPhases A–F are done; this is why it is in the archive. Phase G belongs to the other repository

8. A prerequisite, for whenever a preview origin is wanted

Not work, but the thing that is always discovered too late. From [UI-REPOSITORY-SCOPE.md](UI-REPOSITORY-SCOPE.md): a preview origin needs two allowlist additions, not one.

  1. the API's ALLOWED_ORIGINS, so connected-mode QA can reach it;
  2. the R2 bucket's CORS allowlist, which today permits https://is.lucasacademy.org, https://inception-space.onrender.com and http://localhost:5173 only.

Verified locally: a production build served from an unlisted origin has every R2 asset blocked by CORS, and the transit chamber then fails entry rather than downgrading silently. Both allowlists live in the other repository.