feat: v0.3.7 — idle drift cruise: wire driftAngle/driftSpeed into the physics loop - #60
Merged
Merged
Conversation
… physics loop Through 0.3.6 driftAngle/driftSpeed were initialized per blob but never read: with no pointer, scroll, or devicemotion input (every idle desktop) the only motion was zero-mean jitter plus a slow bounded slosh, so the background read as frozen. The loop now applies a constant per-substep force along each blob's persistent heading with driftSpeed as the terminal speed under the unchanged *=0.992 damping (extracted to VELOCITY_DAMPING): blobs drift gently by default, reach walls, and bounce — recordBounce() already re-randomizes the heading on impact. The force is purely additive and consumes no randomness, so gravity/pointer/scroll feel is untouched, and reduced-motion behavior is unchanged (the cruise lives inside the step the component never runs under prefers-reduced-motion). driftSpeed init raised 0.01+rand*0.015 -> 0.05+rand*0.05 (terminal ~3-6 units/s in the 180-unit field; field crossing in ~30-60s). Deterministic unit coverage in tests/unit/idle-drift-cruise.test.ts: a differential run pair isolates the cruise term exactly, plus wall-bounce containment and the init floor.
Jess Sullivan (Jesssullivan)
added a commit
to Great-Falls-Tool-Bus/greatfallstoolbus.org
that referenced
this pull request
Sep 1, 2026
… desktop (#228) * feat(brand): tinyvectors 0.3.7 — blobs drift and bounce by default on desktop Root cause: through 0.3.6 the package initialized each blob's driftAngle/driftSpeed cruise field but no code ever read it, so with no pointer, scroll, or devicemotion input (i.e. every idle desktop) the only motion was zero-mean jitter plus a slow bounded slosh the engine's damping decorrelates in ~1.4s — the background read as frozen. Fixed upstream in tinyvectors v0.3.7 (tinyland-inc/tinyvectors#60, signed tag on 9b64b67): the physics loop now applies a constant per-substep force along each blob's persistent heading with driftSpeed as the terminal speed (~3-6 units/s in the 180-unit field), so blobs drift, reach the walls, and bounce; recordBounce() re-randomizes the heading on impact. The force is purely additive: the devicemotion enhancement (#224, iOS pill included) and the prefers-reduced-motion full freeze are unchanged. Consumes the release across every seam this repo pins, per the module's release ritual (tinyvectors docs/release-flow.md) and this repo's .bazelrc re-pin discipline, in one commit: - package.json tag-tarball pin -> v0.3.7, with the archive's sha256 SRI added to PINNED_INTEGRITY in scripts/build-tinyvectors.mjs (same value the registry source.json carries) and pnpm-lock.yaml following the pin - MODULE.bazel bazel_dep 0.3.6 -> 0.3.7 - .bazelrc registry pin f23d6975 -> ef734c4a (tinyland-inc/bazel-registry#115; the registry's .bazelversion at that commit re-read and still records estate value 8.2.1), with MODULE.bazel.lock refreshed in the same commit: every registry URL key re-keyed to the new SHA, tinyvectors 0.3.6 file hashes replaced by 0.3.7's (values verified against the served registry bytes) - src/lib/brand-vectors-motion-contract.test.ts pins the 0.3.7 floor, the PINNED_INTEGRITY entry for the pinned tag, and the layout call-site motion contract (animated + respectReducedMotion defaults kept, enableDeviceMotion stays the enhancement layer) Verification is remote-only per operator ruling 2026-09-01: upstream Verify + tag lanes green (typecheck, unit incl. the deterministic idle drift differential test, build, package, bundle-size, Bazel targets); registry validate + immutability gates green; this repo's CI is the evidence for the consumer bump. * fix(test): widen the version-floor reduce accumulator to number svelte-check narrows the accumulator of IDLE_DRIFT_FLOOR.reduce to the as-const literal union (0 | 3 | 7), so s * 1000 + n fails to type. Pass the number type argument explicitly; behavior unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Root cause
Through 0.3.6,
driftAngle/driftSpeedwere initialized per blob (since 0.3.0) but never read by the physics loop. With no pointer, scroll, or devicemotion input — i.e. every idle desktop — the only inputs were zero-mean jitter and a slow bounded slosh that the*= 0.992per-substep damping decorrelates in ~1.4 s, so the background read as frozen-with-a-shiver. The evidently-intended cruise field was dead code.Fix
driftAngleheading, with magnitudedriftSpeed * (1 - VELOCITY_DAMPING)sodriftSpeedis exactly the terminal cruise speed under the unchanged damping. Purely additive, consumes no randomness: gravity/pointer/scroll feel and transient-impulse decay are untouched.driftSpeedinit0.01 + rand * 0.015→0.05 + rand * 0.05(the dead-code-era values were weaker than the ambient slosh): terminal cruise ≈ 3–6 units/s in the 180-unit field, a field crossing in ~30–60 s. Blobs reach walls and bounce;recordBounce()already re-randomizes the heading on impact.VELOCITY_DAMPING(still 0.992); no behavior change.package.json/MODULE.bazel/BUILD.bazel, CHANGELOG entry, feel-contract status update.Reduced motion
Unchanged: the cruise lives inside the physics step, which
TinyVectorsnever runs while(prefers-reduced-motion: reduce)matches (respectReducedMotiondefaultstrueand renders the existing static frame).Verification
tests/unit/idle-drift-cruise.test.ts(deterministic, constant-0.5 mocked RNG):driftSpeedrange.Verification is remote-only per operator ruling: CI (
Verify→ js-bazel-package reusable workflow) runs typecheck, unit tests, build, package checks, bundle size, and the Bazel targets on repo-owned runners.