Architecture hardening: enforce renderer parity, decompose god-files, fix shadow seams - #85
Architecture hardening: enforce renderer parity, decompose god-files, fix shadow seams#85apresmoi wants to merge 39 commits into
Conversation
…angle detection, core helper dedup)
…r/override/dedup caches
… throttle, zero-light ground gate)
…d+exported, PolyThreeMesh parity, morph core dep)
…hrottle hardening
…ametric-only controls
…d on member parity
…le crease neighbour
|
Update (31 commits). Two adversarial review rounds shaped this PR beyond the original scope. Round 1 found the mirror gate could be laundered by re-pinning the hash lock, and that package manifests were never validated — fixed with lane-parity diffing against the merge base and manifest checking. Round 2 found three residual bypasses: set-wide lane parity that let two unrelated one-lane edits cancel out, committed waivers that kept authorizing divergence after merging, and dependency aliases ( The same rounds found three real rendering defects: crease bleed could run with a silently-failed pre-blend (translucent receivers, breaking the idempotence invariant the design rests on); the pre-blend "pixel-identical" claim was overstated for groups whose members carry different normals (worst case 11/255); and shadow geometry had become camera-dependent while no renderer recomputed it on camera motion, so shadows went stale during orbit and popped on the next unrelated update. All three are fixed, the last via a camera visibility signature (castle 360° orbit: 0 → 71 re-emits, median step 0 ms — not a per-frame recompute). Additional breaking changes (
|
# Conflicts: # pnpm-lock.yaml # website/gallery-domformat-corpus/catalog.json # website/gallery-domformat-corpus/models/apoc-car.json # website/gallery-domformat-corpus/models/apoc-road-barrier.json # website/gallery-domformat-corpus/models/apoc-tire.json # website/gallery-domformat-corpus/models/apoc-wall-hole.json # website/gallery-domformat-corpus/models/cottage.json # website/gallery-domformat-corpus/models/glb-cheetah.json # website/gallery-domformat-corpus/models/glb-city-large-building.json # website/gallery-domformat-corpus/models/glb-city-skyscraper.json # website/gallery-domformat-corpus/models/glb-city-small-building.json # website/gallery-domformat-corpus/models/glb-dog.json # website/gallery-domformat-corpus/models/glb-dump-truck.json # website/gallery-domformat-corpus/models/glb-globe.json # website/gallery-domformat-corpus/models/glb-khronos-avocado.json # website/gallery-domformat-corpus/models/glb-medieval-sawmill-saw.json # website/gallery-domformat-corpus/models/glb-model-viewer-astronaut.json # website/gallery-domformat-corpus/models/glb-nasa-cubesat-1u.json # website/gallery-domformat-corpus/models/glb-nasa-flight-system-support.json # website/gallery-domformat-corpus/models/glb-nasa-gamma-ray-observatory.json # website/gallery-domformat-corpus/models/glb-nasa-icesat-a.json # website/gallery-domformat-corpus/models/glb-nasa-international-space-station.json # website/gallery-domformat-corpus/models/glb-nasa-opportunity.json # website/gallery-domformat-corpus/models/glb-nasa-orbiter-docking-system.json # website/gallery-domformat-corpus/models/glb-nasa-solid-rocket-booster.json # website/gallery-domformat-corpus/models/glb-nasa-space-shuttle-external-tank.json # website/gallery-domformat-corpus/models/glb-nasa-tdrs-a.json # website/gallery-domformat-corpus/models/glb-nasa-wide-field-planetary-camera.json # website/gallery-domformat-corpus/models/glb-opengameart-animated-pliers.json # website/gallery-domformat-corpus/models/glb-opengameart-animated-utility-knife.json # website/gallery-domformat-corpus/models/glb-owl.json # website/gallery-domformat-corpus/models/glb-policecar.json # website/gallery-domformat-corpus/models/glb-poly-pizza-box.json # website/gallery-domformat-corpus/models/glb-poly-pizza-fish.json # website/gallery-domformat-corpus/models/glb-poly-pizza-human-dude-guy.json # website/gallery-domformat-corpus/models/glb-poly-pizza-monkey.json # website/gallery-domformat-corpus/models/glb-poly-pizza-rock-medium.json # website/gallery-domformat-corpus/models/glb-poly-pizza-tiger.json # website/gallery-domformat-corpus/models/glb-rat.json # website/gallery-domformat-corpus/models/glb-robin.json # website/gallery-domformat-corpus/models/glb-smithsonian-morse-telegraph-key.json # website/gallery-domformat-corpus/models/glb-taxi.json # website/gallery-domformat-corpus/models/glb-truck.json # website/gallery-domformat-corpus/models/glb-urban-atm.json # website/gallery-domformat-corpus/models/glb-urban-billboard.json # website/gallery-domformat-corpus/models/glb-urban-box.json # website/gallery-domformat-corpus/models/glb-urban-bus.json # website/gallery-domformat-corpus/models/glb-urban-car.json # website/gallery-domformat-corpus/models/glb-urban-mailbox.json # website/gallery-domformat-corpus/models/glb-urban-pickup-truck.json # website/gallery-domformat-corpus/models/glb-urban-police-car.json # website/gallery-domformat-corpus/models/glb-urban-power-box.json # website/gallery-domformat-corpus/models/glb-urban-sports-car.json # website/gallery-domformat-corpus/models/glb-urban-suv.json # website/gallery-domformat-corpus/models/glb-urban-van.json # website/gallery-domformat-corpus/models/glb-zebra.json # website/gallery-domformat-corpus/models/insurgent.json # website/gallery-domformat-corpus/models/obj-opengameart-biplane-biplane.json # website/gallery-domformat-corpus/models/obj-opengameart-fire-extinguisher-extinguisher.json # website/gallery-domformat-corpus/models/obj-opengameart-game-cartridge-cartridge.json # website/gallery-domformat-corpus/models/obj-opengameart-haunted-house-hauntedhouse.json # website/gallery-domformat-corpus/models/obj-opengameart-low-poly-car-car.json # website/gallery-domformat-corpus/models/obj-quaternius-ultimate-spaceships-challenger-challenger.json # website/gallery-domformat-corpus/models/obj-quaternius-ultimate-spaceships-executioner-executioner.json # website/gallery-domformat-corpus/models/obj-quaternius-ultimate-spaceships-omen-omen.json # website/gallery-domformat-corpus/models/obj-quaternius-ultimate-spaceships-pancake-pancake.json # website/gallery-domformat-corpus/models/obj-quaternius-ultimate-spaceships-spitfire-spitfire.json # website/gallery-domformat-corpus/models/obj-quaternius-ultimate-spaceships-zenith-zenith.json # website/gallery-domformat-corpus/models/sting.json
…gnature lights parity
Architecture hardening pass over the whole monorepo, plus a shadow-quality
investigation that started from a visible artifact and ended in core.
All 23 commits are gated: 3,121 tests green, 0 typecheck errors, package +
website builds clean, mirror/boundary checks passing at every commit boundary.
Why
An audit of module boundaries, duplication, defaults, types and performance
turned up one root cause behind most of it: the three-renderer copy discipline
(vanilla / React / Vue) was enforced by prose in
AGENTS.mdand a PR checklist,with nothing mechanical behind it. It had already failed — several fixes existed
in one renderer only, producing live rendering bugs.
What landed
Enforcement (the reason the rest stays fixed)
pnpm check:boundaries— package dependency rules, deep-import bans, node-builtincontainment.
pnpm check:mirrors— byte-identity for react↔vue clones; hash-pinned lock for thestructurally-divergent vanilla↔framework mirrors, so editing one fails CI until
you re-pin and confirm all three renderers got the change.
pnpm typecheckper package (now including test files), wired into CI.Live bugs fixed (each was a one-renderer fix that never got mirrored)
seamBleedsilently ignored for textured triangles.strategies.disableand the owning document.Performance
frame — they now match vanilla, which never did. Caster-items, parametric-override
and overlap-dedup caches are shared across all three renderers.
updatePolygonedits.Consistency
seamBleedunified: one core-owned resolution (raw px,"auto"= 1.5), replacingtwo divergent semantics.
maxDistance→Infinityeverywhere, an 80 ms animated-shadowthrottle in all three renderers, ground-shadow gated on a real directional light.
Decomposition (coverage-baselined first, behavior-preserving)
createPolyScene.ts2,481 → 1,286 lines + 7 concept modules; region coverage80.4% → 84.4%.
PolyMesh1,554 → 498, Vue 1,455 → 419, into 8 mirrored modules each;coverage up on every axis. All pre-existing tests pass unmodified.
Shadow quality (traced from a visible artifact to root cause)
crease boundaries between face groups now bleed correctly. The last one was only
safe once solid single-light shadows switched to painting a pre-blended colour
opaquely instead of the shadow colour at partial alpha, making overlap idempotent.
Proven pixel-identical where nothing overlaps (0 of 607,200 px at opacity 1).
non-planar imported quads pushed genuinely-shared edges past the matching epsilon and
272 real creases were misclassified as silhouette. Castle missing-shadow pixels
117 → 70, now within 1 px of the brute-force bound.
Website
from a different base: shadow strength 0 still left a dark patch and the ground
shadow read ~68% deeper than the geometry justified. Ground now bakes honestly —
shadow ratio 0.370 → 0.657 vs the model's 0.662, strength 0 is genuinely clean, and
light-dragging got ~14% faster.
Shadow color.
.voximport; per-phase shadow timers wired; renderstats now report shadow subpath and path-data counts (the real cost drivers).
Breaking changes
seamBleedis raw px everywhere;"auto"now yields 1.5 px overscan in React/Vue(was none), and values > 1.5 are no longer clamped in vanilla.
maxDistancedefault 5000 →Infinityin React/Vue (Three parity).PolySceneprops,debugShowBackfaces, theresolveColorexport,and
usePolySceneContext's ignored options parameter.ShadowOptions→PolyShadowOptions(now exported by all three);Poly*CameraOptionsFromThree→Poly*CameraStateFromThree.the shadow colour at fractional alpha.
Review notes
The commits are ordered as coherent units and can be reviewed in sequence — the
enforcement commits come first, then bug fixes, then perf, then the refactors, then
the shadow work. Happy to split this into stacked PRs if you'd prefer that shape.
Deliberately not done, needing your call: curating
polycss'sexport * from core, the three incompatiblePolyMeshHandleshapes,polycss-fontsgeneric export names, hoisting the shared
styles.tsCSS, and an optionalshadow.mode: "flat"for artistically uniform shadows.