Upstream — what we're waiting on

An index, not a record. The issues on the owning repo are the record: the context, the workaround and the suggestion live there, self-contained for someone who has never seen this repo. Keeping a second copy here would drift — the issue gets refined in discussion while the local copy quietly ages into a description of a problem that has moved (practices/cross-project.md).

So each row is a link and one line. Mark ✅ RESOLVED (fixed in pkg@version) when it lands, and close the issue.

tosijs-3d

Finding Issue
1 No way to touch a mesh. Accepted and BUILT on main as <tosi-b3d-interactive>, shipping in 0.7.3 — adopt it and port our world rules onto it #36
2 RESOLVED (tosijs-3d@0.7.4–0.7.5) — vector3d/euler3d, ui.fieldGroup, a summonable on-screen keyboard, select3d menus, iconGrid3d, and popups that escape their panel. Panels size to content, which retires every hand-tuned height #37
3 No manipulator, and b3d-panel's coloured axes look exactly like one #38
4 RESOLVED (tosijs-3d@0.7.2) — destroyable="off" landed, credited to this project #39
5 b3d-turret/b3d-launcher take no library, so a turret cannot have its own mesh #34
6 b3d-spawner is player-relative — no way to spawn at an authored place #40
7 A scene-owned clock: effect timing can be scaled, craft motion cannot #41
9 RESOLVED (tosijs-3d@0.7.4) — getManifest(), getInfo(name) without instantiating, and getNames() narrows to declared items. Measured upstream at 559 raw nodes vs 131 declared #45
10 RESOLVED (tosijs-3d@0.7.4) — the normal map is generated procedurally, so there is no file and no path; an explicit normalMap that fails now logs instead of silently checkerboarding #46
11 b3d-destroyable cannot scale a library-backed piece at all — size is the placeholder cube's edge and is ignored once library is set. Measured: width identical at scale 1, 2 and 4 #47
12 b3d-destroyable drops rx/ry/rzinstantiate is called with position only, so a library-backed piece cannot be rotated at all. Measured: authored rot: [0,45,0] left the footprint identical #48
13 b3d-destroyable removed before its lib.ready.then instantiate resolves ORPHANS the node — nothing disposes it, ever. Measured: 4 rapid edits left 4 copies and 210 meshes where there were 81, and it never recovered #49
14 RESOLVED (tosijs-3d@0.7.4) — numeric fields scrub and type; slider3d's step always quantised and is now documented. Our snap cyclers STAY: they carry a 0 sentinel plus a doubling series, which is a cycler's job, not a slider's #50
15 Sky renders black on some loadsCLOSED, and it was OURS. Bisected in one page: <tosi-ensemble> in a plain <tosi-b3d> renders perfectly, and the editor with hideChrome renders perfectly, while the full editor beside them renders dark. The editor CHROME breaks the scene. The GL evidence (gl.isProgram false, glError 1282) was real; my explanation of it — a shared SkyMaterial program deleted by material churn — was not, and reducing to one SkyMaterial did not fix it #51
19 A STILL sky updates once and never recovers. b3d-skybox re-runs updateSky from its frame observer only when timeOfDay !== _lastSkyTime, and updateSky writes sunPosition/rayleigh/turbidity only inside if (sunEl?.light != null). The sun is a separate element whose light appears on its own schedule, so a first call that lands too early leaves the SkyMaterial at its defaults — a dark sky that reads as night. The default realtimeScale: 10 hides this by drifting the clock so the gate reopens every tick; set it to 0 for a reproducible scene and four loads in five come up dark. Ask: re-run when the INPUTS change (or when a sun appears), not only when the clock does #55
25 RESOLVED (tosijs-3d@0.8.0) — slider3d gained scale: 'log' | 'log2', snap and zeroStop, and skyboxSchema() ships realtimeScale as x-scale: log + x-zero-stop. ADOPTEDschema-panel reads x-zero-stop and the cycler is gone #62
26 RESOLVED (tosijs-3d@0.8.0) — tosijs-3d/scene-schemas ships JSON Schema for all nine primitives plus the hemispheric light, headless (verified importing it under Node here), with an extra override argument and SCENE_OMITTED naming the positional attributes a feature panel should drop. ADOPTEDpick() in features-scene.ts takes the shape of all ten from upstream, and runtime/scene-schemas.test.ts fails if we restate a range, unit, enum or scale. It found four more silent-nothing controls on the way in (underwaterFog typed boolean, preset: birds, where: air, mode: none), all four now migrated in existing files #63
24 RESOLVED; RECEIVING END READY, NO CALLER YET (tosijs-3d@0.8.0) — plain-JSON curves, normalizeCurve, and evaluateCurve(points, t) with no DOM (verified under Node here), plus curveProgram3d / curveMarkers with handleCommit(value, describe). schema-panel dispatches x-widget: 'curve' and 'light-program' and both are pinned by test — but nothing in this repo declares a curve: the lamp hands its whole settings to lightEditor3d. The natural first caller is provinceClimateSchema(), whose three channels are curves; upstream shipped it deliberately without a consumer, because the province REGISTRY has to exist first and that is written down as their step 1. Nothing to build here, and nothing to file #61
23 RESOLVED and ADOPTED (tosijs-3d@0.8.0) — spinner3d runs in the insert palette while the shelf mounts. Measured with cache-busted kit URLs: "loading 4 kits…" up from 1.0s to 2.0s, then gone. Indeterminate rather than progress3d, because mountLibraries resolves once for the whole shelf and faking a fraction is worse than admitting there is none #60
27 RESOLVED, PARTLY ADOPTED (tosijs-3d@0.8.0) — kind: 'button' + menu(row) is adopted: the piece list has per-row Enable/Disable, Duplicate and Delete. kind: 'icon' deliberately NOT adopted — an icon column reads its value as an iconGlyph NAME, and our feature icons are EMOJI by the registry's contract (registerFeature({ icon: '☀️' })), which is what lets a consumer's own feature appear with a glyph the editor never knew. Names would make every consumer register an SVG too, to gain nothing an author sees. So the missing scene vocabulary is moot for us #64
28 🟡 HALF (tosijs-3d@0.8.0) — ADOPTED for the schematerrainSchema() retired the invented units and the unbounded reach; our floor on tileSize stays, because it is the PRODUCT of two sliders that kills the tab and a schema cannot say that. No terrain EDITOR yet, and regenerate-on-change is still ours #66
29 RESOLVED and ADOPTED (tosijs-3d@0.8.0) — the piece list is a table per group with one filter field driving setFilter on the LIVE tables, so scroll, selection and focus survive typing. Measured here: filtering out the selected flagship left it selected and it came back when the filter cleared #67
30 RESOLVED (tosijs-3d@0.8.0) — source specifiers carry .js, and a test asserts it of the SOURCE so it fails at authoring time rather than after a publish. Deep package subpaths too. Verified here: import 'tosijs-3d/scene-schemas' and 'tosijs-3d/curve' both resolve under Node #69
28 RESOLVED (tosijs-3d@0.8.0) — lightEditor3d's teaching copy is opt-in now, so an embedded widget no longer ships demo prose into a consumer's panel #65
22 RESOLVED and ADOPTED (tosijs-3d@0.8.0) — scene.whenDisposed(cb) exists and returns an unsubscribe. We had already written against it; with the peer floor at 0.8.0 the call is no longer optional-chained, so a missing method would be loud rather than silently never observing disposal #58
21 🟡 FIXED UPSTREAM, UNVERIFIED HERE (tosijs-3d@0.8.0, #58) — "a move no longer costs a scene, and a genuine removal disposes the engine". Our deferred mount and lazy kit shelf are MITIGATIONS for this and #56 and stay until ~20 SPA round trips say otherwise. n=4 cannot tell "fixed" from "rarer" #58
20 A popup on the DOM layer cannot be moved. The move/close glyphs are picking-driven and scene-only, so nothing renders in the flat presentation — measured, zero data-presentation nodes in the layer. A keyboard summoned from a right-hand panel opens at x 1471, 360 wide, in a 1719 viewport: 112px off-screen with no way to recover it. Asked for drag on the DOM layer, or a viewport clamp #57
19 Constructing a b3d scene inside another component's rAF render pass corrupts materials — dark sky, WHITE meshes, empty scene, half-loaded scene, ~70% of loads, all one cause. Isolated by side-by-side comparison in one page. We defer our mount to a macrotask and it goes to zero; filed informationally in case b3d should defer its own engine creation, or the rule should be documented #56
17 RESOLVED in 0.7.6b3d-shadows no longer writes receiveShadows on instanced meshes. The write was already a no-op, so nothing that received shadows stops. Verified here: a full editor load now logs zero of them, where it was ~10,000 #53
18 RESOLVED in 0.7.6 — the icon LANGUAGE works on the texture path, so mirrored names resolve everywhere and no iconFlipX on IconGridItem is needed. Root cause was a trailing space in icon-data making a redirect unparseable as a name. Undo is a real ↰ again. ⚠️ iconExists() was added for exactly this check but is NOT re-exported from the barrel, so a consumer still cannot reach it #54
16 Touch camera: two-finger drag zooms instead of panning, and ⌃drag does not exist on touch — so a tablet cannot pan at all #52
8 RESOLVED in part (tosijs-3d@0.7.2) — exports is a map now, but it names ./demo-utils explicitly rather than a ./* pattern, so an arbitrary subpath is still unreachable. Closed upstream; we are not reopening, because the case that motivated it (a published, importable subpath) works #42

Stopgaps we own, and what retires them

Each of these is local complexity we carry because of a row above. When the issue lands, the workaround goes — a stopgap that outlives its reason is a fork nobody declared. One has already been collected: see the struck-through row.

| Ours | Retired by | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | | destroyable registers body: truegone in 0.7.2. Placement is uniform and destruction decorates a body it no longer has to create | ✅ #39 | | launchpad is registered editorOnly — authorable, and honestly marked as something the runtime will not build | #40 | | numberField + DOM key routing + our own active-field trackinggone in 0.7.4. vector3d/euler3d put a coordinate on ONE row and ui.fieldGroup owns exclusivity, commit-on-leave and key routing | ✅ #37 (items 1, 7) | | handles-view.ts, and the drag maths in handles.ts | #38 | | ctx.simTime() defaulting to wall-clock | #41 | | presets/world's own interactive (reach, activation, refusal) | 🔜 #36 in 0.7.3 | | The family-cycler + separate list standing in for a hierarchical palette | #37 (list virtualisation still open) | | Hand-tuned panel heightsgone in 0.7.5. height: 'fit' is the default and maxHeight scrolls; three separate clipping bugs came from guessing this number | ✅ #37 | | Deriving palette categories from NAME PREFIXES, when the library now declares real ones | #45 | | Our own copy of waterbump.pngdeleted in 0.7.4. The map is procedural now | ✅ #46 | | runtime/node-transform.ts — writing rotation AND scale past the element onto the instance root, plus whenMeshed's retry, because the instance does not exist when the element is appended | tosijs-3d #47, #48 | | Cannot redefine property: onBeforeViewRenderObservable on Linux/SwiftShader, every run — a one-time prototype augmentation guarded by a module-scope flag, double-firing. Non-fatal (the scene builds, the library mounts, the meshes resolve) but it is an uncaught page error, and our scene lane asserts a page throws nothing. Filtered BY NAME in tests/page-errors.ts with a pointer, so every other page error still fails the build; the filter comes out when this lands. Only found because we added CI — it reproduces on no machine here | tosijs-3d #78 | | place-mesh.ts's reapOrphan — watching for an instance that arrives after its element was removed, and disposing it | tosijs-3d #49 | | The sky's realtimeScale spelled as an enum so it renders as a cyclergone in 0.8.0. x-scale: log + x-zero-stop is a slider that spans decades and still reaches Off. The TOOL snap cyclers stay: a doubling series with a 0 sentinel is a cycler's job, not a slider's | tosijs-3d #50 | | 1.14 removed the DOC SYSTEM from the barrel, not only the doc browser. import 'tosijs-ui' no longer registers <tosi-doc-system>, and nothing says so — the site keeps its nav and layout, so it reads as working, while every html/js fence renders as inert <pre> and the doc-test corpus never appears. Measured on the published site: customElements.get('tosi-doc-system') === false. Fixed here by importing tosijs-ui/doc-system/doc-system.js explicitly; 3d.tosijs.net has the same symptom | tosijs-ui #159, #158 | | The doc system rewrites editor.md's <!-- toc --> block on every build, without the blank line Prettier's markdown formatter always inserts — so format and build undo each other and a --check gate cannot stay green. Surfaced by adding CI. editor.md is in .prettierignore meanwhile, which makes the repo's one hand-written doc page the only file the formatter does not check | tosijs-ui #165 | | editor.md's calc(100dvh - 4rem), a hand-tuned navbar offset | tosijs-ui #115 | | Nulling the camera input's private _pointA/_pointB on re-attach | Babylon (third-party; no upstream row) | | 31 | No colour control, while scene-schemas declares eight format: 'color' properties — four on the sky alone. FieldType has no color, and lightEditor3d sidesteps it with a hue slider. Anyone doing what #63 invites lands here at once. We use a hex inputField meanwhile: no swatch, no preview, and #eeeff is accepted and silently wrong | #72 |

tosijs

Finding Issue
E RESOLVED (tosijs@1.9.2) — a held boxed proxy is a live view of its path. .value used to resolve for SCALAR proxies and return the captured target for OBJECT ones, so one API disagreed with itself and it presents as a failed WRITE. Cost an afternoon here. Our test asserted the bug and is what failed on upgrade #35
F RESOLVED (tosijs@1.10.0) — Component's [key: string]: any index signature is gone, so tsc finally checks our components. It found this.seabed, an attribute whose declare line was never written and which therefore typed as any for as long as it has existed #36
H An unknown prop is assigned as a PROPERTY, so a props object built from untrusted data can set innerHTML and execute script — confirmed in real Chromium. elements.ts opens by promising construction without innerHTML, and tosijs#26 states the opposite runtime model outright ("an unknown prop is silently dropped"), which is the reading we built on. Half of it was genuinely ours (updateAttrs is element[key] = value) and is fixed here by declaredConfig; the library half protects every other consumer who turns document data into props #43
G withAttributes() breaks our .d.ts emit — its return type is not nameable from 'tosijs', so tsc -p tsconfig.build.json fails TS2742 and bun run build refuses. It is the shape tosijs's own migration note recommends, and we cannot take it. Using the documented ComponentAttrs alternative meanwhile; fixed upstream and unpublished, so switch when it lands #38

haltija

Finding Issue
D An agent driving a BACKGROUND tab cannot verify rendered output — rAF is throttled, a self-pausing scene stops, and hand-driving the frame loop changed the semantics enough to produce two false diagnoses in one session. Asks for a leased, reusable foreground instance #41

tosijs-ui

Finding Issue
E The documented import 'tosijs-ui/doc-browser' is a no-op, so 1.14 silently removed our doc-test corpus. That module has no top-level side effect, so the bare import is dropped; measured on a clean build, tosi-tests-done/pagesWithTests/createDocBrowser are all absent while live-example's strings are present. The site renders perfectly and window.__docTestResults never appears — our gate went from 5s to a 30s timeout, and without it the corpus would just have stopped existing #158
A Dev-server auth sessions live in new Map(), so every restart invalidates every issued edit link while the 30-day cookie stays valid — it presents as Safari eating cookies #114
B A full-screen page that is ONE element: markdown wraps it in a <p> and nothing in the chain has a definite height, so height: 100% collapses. Suggested fix is raw .html doc pages #115
C The dev server answers a missing asset with the SPA shell — HTML at 200 — so a 404 presents as a silently wrong render #116
D describeHolder() with no holder returns a rendered "pid undefined" warning rather than saying there is none — the reader added by #118 tells a caller the opposite of the truth #123

Not filed, deliberately

prefab means three things. tosijs-3d exports prefab for a registered (ctx) => Element[] factory (wrecks, debris, spawns); Unity means a serialized scene object with code; Manta's prefab.ts meant our format's ancestor. Not a request — nobody should rename anything over it — but a reader coming from Unity meets a second meaning in the same dependency graph, and it is worth knowing that is why this project's word is ensemble.