verify-launch.mjs / verify-launch-mobile.mjs were throwaway Playwright
screenshot scripts hardcoding /Users/entity002/... paths (incl. a Desktop
testimonial dir and the retired vestige-launch-main worktree). Nothing
references them; they violate public-repo hygiene. Removed before publishing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Clears the rest of the MiniMax M3 audit backlog (all verified, svelte-check green):
- H1: Canvas2D fallback now honors decay (inward pull+damp) and birth (outward
bloom) events, not just firewall — full event parity with the WGSL path for
pre-iOS-26 / no-WebGPU users.
- H2: noise/flow time is now an `activeT` accumulator advanced by dt only while
drawing, so a backgrounded tab no longer fast-forwards the curl flow and snaps
it to a new direction on resume (was wall-clock `(now-startedAt)`). Both the
WebGPU and Canvas2D paths share it.
- H3: prefers-reduced-motion is now reactive ($state + a matchMedia change
listener) so toggling the OS setting mid-session takes effect next frame
(was a const snapshot at init).
- H4: documented that `count` is read once at boot (buffer sizing); `intensity`
is the live knob.
- M3: cache the Canvas2D context once in bootFallback (was getContext per frame).
- M4: coalesce resize bursts to one resize/frame via rAF (was thrashing the
swapchain config + 2D backing store on every drag event).
- M7: register device.lost BEFORE pipeline creation (was after the handle,
leaving a race window where a loss mid-build never fired the fallback).
- L2/L4/L1: drop the empty onMount return (single onDestroy teardown); reset
lastT in bootFallback so a WebGPU recovery sees no giant dt; document the
intentionally-non-reactive animation state.
svelte-check 0 errors / 967 files. Cosmetic-only items left (M1 dead DPR slot,
M2 dead vel.w, M5 sizePx naming, L3 alpha-mode smell) — no behavior, deferred.
Memory Cinema / Graph3D untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
4th-model pass (DeepSeek V4-Pro, max reasoning, steered at the GPU numerics the
other 3 didn't audit) found a NEW bug class none of them connected:
The compute pass soft-wraps ALL of pos including z into [-1,1]
(fract(pos*0.5+0.5)*2-1). The vertex shader derived particle depth/size from a
NON-periodic linear function of that wrapped z (depth = 1.7 + z*0.5), so every
time a particle crossed the z=+/-1 seam its depth jumped 2.2 -> 1.2 and its
rendered size ~doubled (1.83x) in a single frame — a continuous popping that
breaks the volumetric-cloud illusion.
Fix: make depth periodic across the seam with sin(z*pi)*0.5 — it's 0 at both
z=+/-1 (size continuous across the wrap) and still sweeps depth over [1.2, 2.2].
Verified continuous: depth(z=+1)=depth(z=-1)=1.7.
(Also fixed a self-inflicted gate catch: the explanatory comment originally
contained a backtick, which terminated the WGSL template literal early and broke
svelte-check — caught by the gate before commit, now ASCII-only.)
svelte-check 0 errors / 967 files. Visual capture still pending a live backend.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MiniMax M3 (max-depth audit, fresh eyes on the shader MATH that Claude+Kimi's
lifecycle-focused passes missed) found 4 pre-existing criticals, all verified:
- C1 aspect-ratio inversion: vertex shader divided particle X by aspect, which
SQUASHED the whole field into the center ~56% of a 16:9 screen (~22% empty
bars each side). Fix: position now uses the full [-1,1] clip box (no divide);
roundness comes from a proper px2ndc = 2/viewport corner offset so quads are
sizePx x sizePx device px on any aspect ratio (also kills the 0.01 magic number).
- C3 firewall flare landed at the wrong X (distance measured in unit-box space
while the particle rendered in divided space). Fixed-for-free by C1; the crimson
distance is now aspect-corrected so the halo is circular, centered on the catch.
- C4 frame-rate-dependent flow absorption: the velocity lerp used a fixed 0.06
per-frame factor (not dt-scaled), so the field was 2x snappier at 120Hz
ProMotion vs 60Hz. Fix: absorb = 1 - exp(-dt * 3.7) — identical feel at 60fps,
correct everywhere else.
VERIFIED: svelte-check 0 errors / 967 files; zero WGSL validation errors in the
browser (a broken shader struct/syntax would throw at pipeline creation — none).
NOTE: the on-screen full-width widening is not yet visually captured this session
— the preview backend returns API 500 so the (app) layout error-states and the
field doesn't mount; pending eyeball on a wide window against a live backend.
Memory Cinema / Graph3D untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Kimi K2.7-code audit (max-thinking) found a CRITICAL race + leaks that Claude's
shallower pass missed; all verified and fixed:
- CRITICAL: late WebGPU boot after the 6s watchdog fired bootFallback() would
set mode='webgpu' and start a SECOND rAF loop, orphaning the fallback loop.
Fixed with a top-of-function + post-await abort guard in tryBootWebgpu and a
single idempotent tick()/startLoop() dispatcher (running flag) — rAF for the
draw loop is now scheduled in EXACTLY one place.
- GPU buffer leaks: partBuf/uBuf are now destroyed via releaseBuffers() on every
early-exit, the catch path, and the device-lost handler (was leaked everywhere
except the handle!=null onDestroy path).
- resize() now reconfigures the WebGPU context (was stretching after resize).
- drawWebgpu wrapped in try/catch -> bootFallback (one bad frame no longer kills
the field permanently).
- fallback now honors the intensity prop + is frame-rate independent (dt*60);
onVisibility resets fbLastT; onDestroy SSR-guard ordering.
svelte-check 0 errors / 967 files. Memory Cinema / Graph3D untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Launch-critical fixes for the public July-14 signup surface (swarm-audited by
MiniMax M3, Claude-verified against the frontend RPC call path):
- migration: DROP the "anon can insert with check(true)" RLS policy. It let
anon write arbitrary rows straight to the table, bypassing all join_waitlist
validation. The frontend already calls the join_waitlist RPC (rest/v1/rpc/),
never a direct insert, so signup is unaffected. RLS stays enabled with no
permissive INSERT policy = direct anon inserts denied by default.
- join_waitlist: cap email <=254, reject control chars, truncate referrer <=2048.
- waitlist-welcome edge fn: FAIL CLOSED — if WAITLIST_WEBHOOK_SECRET is unset,
return 401 instead of serving (was an open Resend relay). Guard the referral
code against ^[a-z2-9]{7}$ and cap email length before sending.
- vercel.json: add baseline security headers (nosniff, Referrer-Policy,
X-Frame-Options: DENY, HSTS, Permissions-Policy). CSP deferred (would break
the WebGPU hero's inline bootstrap without nonces) — documented.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Real robustness fixes found while verifying Phase 3:
- Boot watchdog: if WebGPU hasn't started rendering within 6s (slow/contended
GPU, hung device request), fall back to Canvas2D so the field is never stuck
on the static gradient. Cleared on successful webgpu boot + onDestroy.
- bootFallback is now idempotent (guards double-start, cancels any in-flight
rAF) so the watchdog can't race a second loop.
- Canvas2D fallback now reacts to the firewall field event too — an outward
shockwave + crimson tint — so pre-iOS-26 / no-WebGPU users also see the catch.
- ?demo=firewall fires the flash on a short delay (so the field has booted, not
mid-boot where it'd be missed); ?demo=firewall&loop=1 re-arms it every 3.2s
for repeatable launch-footage capture.
svelte-check 0 errors / 967 files. NOTE: the on-screen crimson flash remains
visually unconfirmed this session — the preview env had an unstable viewport +
exhausted GPU process; pending a clean browser. Memory Cinema untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The "earned by the backend" payoff: cognitive events drive the WebGPU field.
- fieldEvents.ts: a tiny decoupled pub/sub bridge (emit/onFieldEvent) so the
dashboard publishes cognitive events and the BackdropEngine reacts, with no
coupling either way. Kinds: firewall / decay / birth.
- BackdropEngine: uniform expanded to carry an event vec4 (code, fade, origin).
Compute shader applies a scoped impulse — firewall = outward shockwave + energy
spike, decay = inward cold collapse, birth = bright bloom. Render shader flares
particles near a firewall origin toward an angry CRIMSON (reserved ONLY for the
firewall block; nothing else turns red). Effect fades over 1.6s.
- Black Box ?demo=firewall now emits a firewall field event, so catching the
attack visibly flashes the living field crimson — the launch money-shot.
Verified: svelte-check 0 errors / 967 files; WGSL compiles with no validation
errors in-browser. NOTE: the on-screen crimson flash is not yet visually
captured this session (preview GPU device stalled after many reloads); pending a
clean GPU context. Memory Cinema / Graph3D untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make the WebGPU violet field breathe THROUGH the UI and turn the dead
offline/empty/error states into intentional, alive moments:
- Glass veil-ramp: panel tops drop to ~0.30 opacity so the field crests through
every header, while body text composites over a ~0.82 floor — more alive AND
more legible than the old flat 0.45. New .veil/.veil-strong/.text-legible
legibility utilities.
- edge-live membrane: a state-colored synapse rim (indigo idle, synapse live,
dream violet, amber alarm) + rail-dormant desaturate when offline. Shell mood
derived from connection/dream state.
- LifeState component replaces raw "Error: API 500"/"Offline"/"Select a run":
a calm "Dormant" breathing state, a self-healing error with the raw detail
demoted to a collapsed <details> + Retry, and a "Listening for the agent"
offline state wired to the firewall demo.
- Legibility fixes from the a11y audit: sidebar metrics text-muted->text-dim,
LifeState body->text, detail->dim + veil-strong, ambient strip + text-legible.
All new animation prefers-reduced-motion guarded. Memory Cinema, Black Box
machinery, Graph3D, and the backdrop core untouched. svelte-check 0 errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- websocket.test.ts: 3 stale injectEvent assertions now expect the correct
source:'synthetic' tag the store adds (production behavior was already right).
- server.rs: collapse a clippy::collapsible_if in test code into a let-chain.
- microglial_firewall: gated de-leet so leetspeak injections (1gn0re prev1ous
1nstruct10ns) are caught, with a structural guard — a digit-bearing token is
only rewritten if it de-leets exactly onto a known injection keyword, so
v1.2.3 / sha256 / base64 / 0x1f / i18n / port 8080 never false-quarantine.
Verified: vestige-core tests + clippy --all-targets clean, dashboard 950/950.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- VIRAL_ASSETS_2026-07-14.md: X thread, Show HN, Reddit variants, 30s demo
script, positioning. Firewall claim cleared after the re-audit confirmed
enforcement; honest wording (kept-from-influencing, not "deleted").
- waitlist-setup.md refreshed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the firewall causal slice so a poisoned/injected memory is screened,
quarantined, and proven held-out on the receipt (influence_allowed=false):
- screen_write() detector (neuroscience/microglial_firewall.rs): deterministic
prompt-injection / exfiltration / poisoning screen with NFKC + homoglyph
folding and word-boundary matching to avoid false quarantines.
- Receipt gains quarantined[] / influence_allowed / engram_phases (additive,
serde-default, back-compatible with old receipts).
- New trace events memory.quarantine + episode.boundary (mirror the TS union).
- gate_writes() now screens every write and, on a quarantine verdict, suppresses
the node (held out of retrieval) + records the quarantine receipt + events, so
influence_allowed=false is ENFORCED, not cosmetic. Content capped at 16KB.
- VestigeEvent::MemoryQuarantined live broadcast.
Verified: cargo test vestige-core/vestige-mcp green, clippy -D warnings clean,
integration test proves a screened injection is absent from the write's retrieval.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The /launch landing page (bleeding-edge waitlist hero):
- Full-viewport WebGL node engine (src/lib/hero/nodeEngine.ts): 40k GPU particles
on a two-FBO GPUComputationRenderer running an 18s looping cinematic — particles
stream in from the screen edges, slam together and EXPLODE at center, reform into
a brain / graph constellation / neural lattice, dissolve back out, loop. Glowing
additive particles + UnrealBloom, fills the whole screen edge to edge.
- Key GPGPU fix: custom DataTexture shape targets read black in GPUComputationRenderer
(three.js #15882), so shape targets are computed PROCEDURALLY in-shader from the
per-particle seed. Position integrates raw per-frame velocity (Codrops pattern),
texel-center reference attribute.
- AmbientField (god-ray glow + parallax starfield), phantomBrain (deterministic
seed-from-identity memory graph), LandingHero/neuralFlow (WebGPU Cinema-storm
reuse + WebGL fallback, kept as alternates). Manifesto copy, seed input, email
capture. No em-dashes. SSR off + prerender for the WebGL route.
Waitlist backend (Supabase, owned data):
- supabase/migrations/0001_waitlist.sql (RLS-locked table, dedup), Edge Function
waitlist-join (CORS, validation, honeypot, dedup, Resend confirmation), setup doc.
Dashboard auth removed (reverts the launch-polish auth wall that 401'd the dashboard
against itself): mod.rs/state.rs/websocket.rs back to no-token, api.ts/websocket.ts/
+layout.svelte stripped of the token client. Pending-review UX + Memory PR gating kept.
Research/spec docs under docs/launch/. Frontend typechecks 0/0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Completes the launch-polish lane Codex started (rate-limited mid-wiring):
Trust boundary (was: dashboard API/WS unauthenticated):
- Token middleware on all /api/* and /ws, reusing the persisted Vestige auth
token with constant-time compare (subtle); Sec-Fetch-Site + exact-Origin checks
- Token delivered via URL fragment (never sent to server / logged), installed
into localStorage on app load — WIRES installDashboardTokenFromLocation() into
the root +layout onMount BEFORE websocket.connect()/any fetch (the missing
piece that otherwise 401s the dashboard against its own API)
Fail-closed memory governance:
- Dashboard delete/suppress pre-gate through Memory PRs in Risk-Gated/Paranoid
(Fast still mutates directly); decision-before-mutation; replay -> 409
- Duplicate pending-PR reuse; PR content redacted to preview+hash at the API layer
Black Box / receipts:
- Live refresh of run list + receipts on real TraceEvents (trace-before-receipt
race handled via retry); synthetic events excluded from proof counters
Fixes on top of Codex's work:
- websocket.ts: source 'synthetic' -> `as const` (TS error, blocked pnpm check)
- memories: scoped a11y-ignore on the non-interactive review-notice
- collapsed sanitize_memory_pr_json (clippy collapsible_if); rustfmt the 7
touched Rust files
Gates: pnpm check 0/0 (905 files); vestige-mcp 453 tests; core trace/review/
receipt 67 tests; clippy -D warnings clean. All green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Vestige Cloud is split: the public client (a thin HTTP sync backend that
only moves encrypted bytes) belongs here, but the hosted service — billing,
sync-key->namespace mapping, per-user isolation, Lemon Squeezy webhooks,
transactional email — must live only in the private repo.
Add scripts/check-no-private-cloud.sh, which git-greps tracked files for
distinctive private-service signatures (service crate identity, module
headers, billing/provider internals, server-side sync-key mapping SQL). The
patterns are chosen so the legitimate public client — including its
VESTIGE_CLOUD_* client env vars — does not match.
Wired into CI via guard-no-private-cloud.yml on push/PR. Verified both
directions: passes on the clean repo, fails (naming the markers) when real
private webhook.rs/keys.rs are introduced.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The portable archive is encrypted on the client before upload and decrypted
after download, so the hosted service only ever stores ciphertext — true
zero-knowledge. The passphrase (VESTIGE_CLOUD_ENCRYPTION_KEY) is independent
of the bearer sync key and never leaves the device.
- new cloud_crypto module: Argon2id KDF + XChaCha20-Poly1305 AEAD, self-
describing envelope (MAGIC|version|salt|nonce|ciphertext+tag)
- HttpPortableSyncBackend encrypts on write / decrypts on read; transparent
upgrade of legacy plaintext archives; clear error if remote is encrypted
but no passphrase is set
- sync_portable_archive_cloud takes optional encryption_key
- CLI surfaces encryption status (on/off) on sync
- 6 crypto tests (roundtrip, wrong-key, tamper detection, non-determinism,
envelope detection); E2E verified: server blob is ciphertext, passphrase
device recovers, no-passphrase device cannot decrypt
491 core tests green, clippy -D warnings clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Pages project site is already served from /vestige/, and the dashboard
is built with base path /vestige. Nesting the build under _site/vestige/
served it at /vestige/vestige/ and left a broken redirect at the root.
Copy the build to the artifact root so it serves correctly at /vestige/.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pnpm/action-setup needs an explicit version (root package.json has no
packageManager field). Match test.yml's pinned version: 10.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The github-pages deployment showed a red X: actions/configure-pages@v5
ran with enablement:true, but Pages was never enabled in repo settings and
the default GITHUB_TOKEN cannot create a Pages site, so deploy failed with
"Resource not accessible by integration". The launch-kit revert then deleted
the workflow entirely, leaving nothing to deploy.
- Restore a modernized pages.yml (Pages now enabled via API, so no
enablement hack; actions/checkout@v5 + Node 24 off the deprecated Node 20).
- Make the dashboard base path env-driven (VESTIGE_BASE_PATH), defaulting to
/dashboard for local/embedded use and overridden to /vestige in CI so
assets resolve at the Pages project subpath instead of 404ing.
- Workflow builds the dashboard under /vestige and writes a root-level
redirect index.html so the bare Pages URL lands on the dashboard.
- Rebuild the committed dashboard artifact (was stale at 2.1.23) to 2.1.27.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two deeper review findings (both blockers) + doc de-staling.
C2-deep: my earlier C2 made purge/delete TRACE as memory.write, but gate_writes
did `get_node(id) -> skip on None`, and purge had already DELETEd the row — so a
destructive removal still never opened a Memory PR (it was silently skipped).
The most security-critical write type couldn't be reviewed. Fix: a missing node
is now gateable for destructive decisions — gate_writes builds the WriteContext
from the decision itself (marks `forgets`, which classify_write gates), and the
PR records the removal with node.deleted=true. Proven live: purging a node opens
a PR (kind node_decayed, deleted true); test
gate_opens_pr_for_destructive_write_after_node_deleted_c2.
PRIV: gate_writes copied the FULL node.content into the PR diff + title, so a
real secret in a gated memory would leak into the memory_prs table, the
dashboard, and any exported proof bundle — defeating the point of gating
sensitive writes. Fix: the PR now stores a truncated content PREVIEW + an FNV
content HASH, and sensitive-topic/sensitive-node-type writes are fully REDACTED
("[redacted — sensitive content; review via risk signals]"). The reviewer still
sees the risk signals (why it opened) and a hash (to correlate), never the
secret. Tests gate_redacts_sensitive_content_in_pr_priv,
content_preview_redacts_sensitive_and_truncates, content_hash_is_stable. The
committed memory_pr.json + the whole proof bundle were re-captured and contain
no secret (verified by scan); the re-shot memory-prs.png shows the redaction.
DOC: REVIEW.md commit list is now git-log-based (no stale hashes); C2-deep + PRIV
added to the findings table; PROOF.md write/PR rows updated; test count -> 1007.
Gates: 1007 lib tests pass (+7 new regressions), clippy -D warnings clean,
dashboard check + build clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The loop fired requestAnimationFrame immediately and never awaited render(); with
150k particles + compute + bloom a frame can exceed 16ms, so rAF callbacks queued
faster than the GPU could drain them and the camera/parallax visibly lagged behind
the cursor. Now AWAIT sb.render(dt) before scheduling the next frame → the loop is
capped to real GPU throughput, every frame reflects the latest pointer position,
no backlog. Also snappier active-steer damping (lam 3.5→9, ~110ms converge) so
input feels immediate; idle glide-home unchanged. renderFailures resets on success.
Plus docs/MEMORY_CINEMA.md — complete feature reference for the cinema engine.
Gate: svelte-check 0/0, 937 tests, verified live (parallax tracks cursor, no lag).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Two more review findings — both real, both blockers — plus stale-doc cleanup.
C1: the B1 release used reverse_suppression(subject_id, labile_hours), which
REFUSES once the 24h active-forgetting labile window has passed. So a Memory PR
reviewed late could be marked "promoted" while its memory stayed suppressed.
Approving a quarantined write is an explicit reviewer decision and must release
the memory regardless of elapsed time. New SqliteMemoryStore::release_quarantine
fully clears the suppression (count→0, suppressed_at→NULL) with NO time-window
limit; the PR handler now uses it. Proven: a test backdates suppressed_at to
+100h, shows reverse_suppression refuses, and release_quarantine still releases.
C2: memory(action="purge"|"delete") returns `action` + nodeId but those labels
weren't in is_write_decision, so destructive removal bypassed the memory.write
trace and the PR gate. Added purge/purged/delete/deleted/forget/forgotten.
Proven live: purging a node now records a second memory.write event
({"decision":"purge"}) under the run.
Docs: REVIEW.md de-staled — removed the fixed 140b15f diff-stat / "3 commits"
prose (it moved with each fix), listed all commits, added C1/C2 to the findings
table, updated the test count.
Gates: 1002 lib tests pass (+3 new regressions), clippy -D warnings clean,
dashboard check + build clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
near-fade × fog × DOF × seam-fade each multiply a <1 factor; together they were
crushing the figure dark. Raised the fog floor (0.18→0.45) and the color/emissive
glow bases so the stacked attenuation lands in a vivid range. Verified live.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A full multi-agent review found 7 real issues (4 blockers). All fixed + tested.
B1 (blocker): Promoting a Memory PR did not release the quarantined memory —
the UI said "promoted" while the memory stayed suppressed/out of retrieval.
act_on_memory_pr now calls reverse_suppression(subject_id) on accept actions;
MemoryPrAction::releases_memory() encodes the rule (promote/merge/supersede
release; forget/quarantine keep it held). Proven live: PR response
subjectReleased:true, SQLite suppression_count 0.
B2 (blocker): memory promote/demote (returns `action`, not `decision`) and
codebase remember_* writes bypassed the write-trace + PR gate. extract_writes
now reads `action` too, filtered by is_write_decision (reads like get/state
excluded); is_write_tool includes `codebase`.
B3 (blocker): receipt ids collided within a run (r_<date>_<runId> +
INSERT OR REPLACE overwrote earlier receipts). IDs are now
r_<date>_<runId8>_<unique6>; build() mints the suffix, build_with_unique()
keeps tests deterministic.
B4 (blocker): proof bundle was assembled from two runs (trace.json=run_proof,
websocket-events.jsonl=run_proof2). Re-captured the whole bundle from a single
run — trace, websocket, receipt, and memory_pr all carry run_proof now.
B5: Black Box receipts panel showed global latest, not the selected run.
Added list_receipts_for_run + /api/receipts?run= ; the page uses listForRun.
B6: SENSITIVE_TOPICS substring matching false-fired (tokenizer->token,
author->auth, secretary->secret). Switched to word-boundary matching; real
phrasings (auth token, security vulnerability, api key) still gate.
B7: set_review_mode now writes atomically (temp+rename via write_atomic);
export_trace sanitizes run_id in the Content-Disposition filename; memory-prs
static routes declared before the dynamic /{id} route.
Withdrawn: the /mode-vs-/{id} route order is NOT a functional bug (axum 0.8 /
matchit prioritizes static segments) — reordered for clarity only.
Gates: 999 lib tests pass (+9 new regressions), clippy -D warnings clean,
dashboard check + build clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Step 5 — VELOCITY-STRETCH FLYTHROUGH: sandbox derives camera velocity per frame
(one Vector3, zero compute) and pushes view-space apparent velocity to the storm;
flythrough relaxes the camera clamp floor (lerp 30→6) so the camera plunges
inside the shell. Storm stretches each sprite along screen-space velocity via
rotationNode + scaleNode (clamped streak), separate output graph (no extra
positionView read). Defaults 0 → no-op until wired.
Step 6 — INTERACTIVE PARALLAX: pointer orbits / scroll + pinch zoom the camera
with frame-rate-independent damping, composed onto the director's base pose in
loop() (after director.update, before render); idle >2.5s eases back to 0 so it's
a toy when touched and a film when left alone. sandbox.render re-clamps so the
user can't break framing. Per-beat flythrough strength wired from shot.tension;
dream mode flies through at 0.6. Fully gated off under reduced-motion (no
listeners, flythrough 0).
The 4-feature immersion stack (infinite zoom + flythrough + parallax + DOF/fog)
now composes. Gate: svelte-check 0/0, 937 tests, build green, verified live (all
4 compose, no white-out, no recursion, parallax responds without breaking framing).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Freeze feature work and package the Black Box proof bundle for full review
before anything else lands (no quarantine-constellation work has started).
REVIEW.md is the single entry point: frozen public claim, the per-producer
caveat ledger (real / caveat — sanhedrin.veto stays an honest off-by-default
caveat; dream.patch is REAL but not live-by-default), and the exact command
receipts (run live at 2026-06-22T22:57:59Z, toolchain pinned) for every
validation status credited — nothing claimed from memory.
The bundle (blackbox-proof-2026-06-22/) already contains: status/trace/receipt/
memory_pr JSON, two live WebSocket captures (one with the dream.patch
TraceEvent), six screenshots (Black Box, Receipts/ReceiptCard, Memory PRs,
Graph, dream Black Box, dream producers panel), and PROOF.md. Every credited
artifact was verified to contain real content.
Review surface: 27 source files, +5830/-18 across commits 80c823a, b89beee,
140b15f (build artifacts + proof bundle excluded).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The cloud now dives inward FOREVER, seamlessly. Two layers ride offset phases of
fract(uTime/T): the outer grows pow(λ, phase) toward the camera then snaps back
(invisible — inner@1/λ == outer@1); the inner (half-period offset) grows promoted
by λ to become the next outer shell, while a fresh inner spawns inside. λ=1.923
(=1/0.52 inner scale) makes the snap mathematically exact. A sin(phase·π) seam
cross-fade in rimFactor makes each layer fully transparent at its snap → ZERO pop.
Particle-space (not a camera dolly) so it can't clip or fight the camera clamp.
Rack-focus tracks the descent. uZoomOn gates it: Act II+ and dream mode dive;
beats 0/1 + reduced-motion stay still. Verified: seamless loop, no white-out, no
recursion, 937 tests pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Bounded follow-up (tight acceptance criteria, no scope expansion): flip the
dream.patch producer from "quiet because no dream ran" to a recorded live event.
The dream tool's `insights` array carries no per-item id, so the recorder
extracted zero proposals and dream.patch never fired even on a real dream.
Fix: derive a stable proposal id from each insight's REAL content (its
insight_type + the source memories it consolidated). The dream genuinely ran;
this just gives each real proposal a deterministic handle. Unit-tested against
the exact dream output shape.
Proven end to end (run_dream_proof, 6 memories consolidated):
- one dream.patch event: dream:RecurringPattern:5d941c7f+a41aca72+...
- SQLite + /api/traces/:runId: dream-trace.json (14 events, last is dream.patch)
- WebSocket: dream-websocket-events.jsonl (the dream.patch TraceEvent)
- dashboard: screenshots/dream-producers.png — the row flips to "fired this run"
PROOF.md updated: dream.patch moves from CAVEAT to REAL (still not live by
default — it fires only when a dream actually runs, and the UI says so).
sanhedrin.veto remains an honest CAVEAT (optional hook, off by default).
Gates: 957 lib tests pass, clippy -D warnings clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Off-focus particles dim (read as bokeh defocus under the bloom) with a breathing
rack-focus. Folded into the single depthFade depth read — NOT sprite scaleNode,
which collapsed the sprites to invisible and collides with the upcoming streak.
Subtle (0.3) so it adds cinematic depth without darkening the figure.
Gate: svelte-check 0/0, 937 tests, verified live (depth grading reads, no recursion).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the receipt chain impossible to doubt. Freeze the claim surface, prove
every hop, and turn the two off-by-default producers into explicit UI states.
Frozen public claim: "Vestige records real MCP memory activity into a
replayable local trace, with receipts and reviewable risky writes." We do NOT
claim Sanhedrin vetoes or dream patches are live by default.
Regression — full-spine test (server.rs): one runId must cross, byte-identical,
MCP output -> SQLite trace -> WebSocket event -> API response shape ->
MCP resource. Fails if any hop drops or rewrites the id.
Honest UI states (Black Box "Event producers" panel):
- sanhedrin.veto -> "No veto producer connected (optional Sanhedrin hook, off
by default)" instead of empty mystery.
- dream.patch -> "No dream run in this trace" unless a dream actually ran.
- contradiction.detected -> "no contradiction in this run" when none fired.
Quarantine review (not pre-write blocking): risky writes are committed then
suppressed — audit history preserved, retrieval influence suspended until
reviewed. Reworded the server notice + UI copy to say exactly that.
Receipts UI gap closed: ReceiptCard is now mounted on the Black Box page
(retrieved/suppressed/trust-floor, activation path, "Open receipt in Cinema").
Proof pack (blackbox-proof-2026-06-22/): status.json, trace.json (the
.vestige-trace.json export), receipt.json, memory_pr.json (promoted via
UI->API->SQLite), websocket-events.jsonl (live TraceEvent x6 + PR opened/
decided), screenshots (Black Box, Receipts, Memory PRs, Graph), and PROOF.md
with real/caveat/stub per feature.
Gates: 988 lib tests pass, clippy -D warnings clean, dashboard check + build
clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Distant particles dim toward the void with view depth (exp falloff) → real 3D
atmospheric recession, not a flat sprite cloud. Combined with the near-fade into
a SINGLE depthFade Fn — critical three@0.172 TSL constraint discovered: reading
positionView from a second Fn feeding the same material output triggers a cyclic
stack-overflow in the node type-resolver (getNodeType). One depth read, one Fn.
Gate: svelte-check 0/0, 937 tests, verified live (fog depth reads, no recursion).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Particles dissolve as they approach the camera (view-space -positionView.z,
smoothstep over [near, near+band]) so the upcoming flythrough never additive-pops
a sprite in your face. Folded into color + emissive so the bloom fades too.
Invisible at the default far camera. positionView confirmed working in the
SpriteNodeMaterial color node.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SpriteNodeMaterial.setupPositionView already rebuilds the billboard quad from
positionGeometry — the prior .add(positionLocal) double-counted it (harmless at
0.1 size). Bare center is required for the upcoming velocity-stretch streak
(scaleNode/rotationNode will drive the quad). Verified renders identically.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The nested 3D-within-3D figure now collides with its shell in OPPOSING color
universes, not a shared rainbow. Each layer is painted from a hard duotone:
the outer shell from one world (ice / acid / gold / mint / electric-blue), the
inner figure from its enemy (fire / blood / violet / crimson / gold). A new
uClash uniform cycles the pair every beat (and randomizes per dream figure), so
it's a fresh ice-vs-fire / acid-vs-blood collision each time — the kind of
contrast that stops a scroll.
To make the clash READ instead of washing white: inner glow floor dropped hard
(dense small-radius overlap was blowing to white and killing the color), inner
figure scaled up to 0.52 (spread → less overlap), the color blast capped at 0.6
mix so the duotone shows through even during a detonation, and Act II/III
ignition lowered 8.0→4.5 so beats no longer flash the clash to white.
Gate: svelte-check 0/0, 937/937 tests pass, build green, verified live (gold
shell + violet core clash reads clearly, no white-out, beats 0/1 calm).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three upgrades to Memory Cinema:
1. IMPOSSIBLE-GEOMETRY FORM PACK — replaced the stringy ribbon dream worlds with
brand-new signature skins nobody ships as a living particle figure:
- world 8 → Calabi–Yau quintic cross-section (6D string-theory manifold,
Hanson 4D→3D projection; α rotates it through the 4th dimension)
- world 9 → Boy's surface (Bryant–Kusner minimal immersion of RP²)
- world 10 → Aizawa attractor shell (breathing strange-attractor skin)
- world 11 → Gyroid↔Schwarz-D Bonnet morph (triply-periodic minimal surface)
The (u,v) MANIFOLD GRID basis is the key fix: particles map over a tensor grid
so neighbors share edges → reads as a sculpted SKIN, not spaghetti. Plus a
facing-ratio Fresnel rim so forms read as lit solids. Inline complex-math +
hyperbolics (sinh/cosh not in three@0.172). atan2→atan (deprecation).
2. 3D-WITHIN-3D NESTING — ~34% of particles form a SECOND, smaller, counter-
rotating figure (a different world, ~45% scale, complementary hue) at the core
of the outer shell. A figure inside a figure — fills the formerly-blank-bright
center with intentional structure and depth.
3. DEMO-CAPTURE MODE — press H in the cinema overlay to hide all UI chrome
(top bar + captions) for clean recording; a faint restore hint remains.
Overlay z-index raised + body.cinema-open hides the graph page's stats pill so
nothing bleeds through.
Gate: svelte-check 0/0, 937/937 tests pass, build green, verified live (Calabi–Yau
+ nested core render, forms cycle, no errors, beats 0/1 calm).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The 7-beat tour no longer freezes on the last figure. When it ends, Memory
Cinema drops into an infinite generative loop: every ~5.5s it morphs into a
fresh RANDOM procedural figure and detonates a color blast — each crazier than
the last.
Five new procedural worlds (7..11), parameterized by a per-figure uMorphSeed +
a uChaos ramp so the same index never looks the same twice:
7 supershape (3D superformula) 8 torus knot (random p,q winding)
9 warped lissajous lattice 10 helix storm
11 quantum foam (curl-warped chaos — max wild)
storm.dreamBeat() picks a random world, reseeds it, ramps chaos, and fires a
moderate-ignition blast (kept below the tour's 8.0 so dense random figures don't
wash white). Surfaced via sandbox.dreamBeat(); MemoryCinema starts a dream timer
on director onComplete, shows "∞ Dreaming", and tears it down on close/replay.
Honors reduced-motion (no dream loop) and the render-fail fallback.
Gate: svelte-check 0/0, 937/937 tests pass, build green, verified live (reaches
dream mode, generates distinct figures — supershapes, torus knots — cycling
forever, no white-out, no errors).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Standing default for all Vestige work, at the absolute top of CLAUDE.md so it
loads first every session: assume maximum ambition, scour before settling, no
hedging, show proof, protect what's flawless and detonate what isn't.
Origin: the overnight session that turned the dashboard + Memory Cinema into a
category-of-one particle journey. Make that depth the default, not the exception.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Memory Cinema is now a choreographed 7-act journey. One 150k-particle pool,
one compute kernel; a uWorld state machine select()s which home-target + forces
are live, and uBlend crossfades world→world over ~1s. The particles never swap
— only the forces on them — which IS the journey.
The seven worlds (beats map 1:1, beatIndex % 7):
0 nebula mist (curl-noise flow) 1 orbital anchor (cross-product spin)
2 strange attractor (Thomas) 3 detonation void (staggered shockwave)
4 crystal lattice (voxel snap) 5 fluid galaxy (curl + tangential swirl)
6 phyllotaxis bloom (Vogel sunflower, golden angle)
The signature COLOR BLAST: a long-lived uBlast envelope (~2.8s, decoupled from
the fast physics burst so the color OUTLIVES the shockwave) drives an outward
SPECTRAL DISPERSION wave — concentric rainbow rings expanding through the radius
over uBlastTime (real prism order, red lags / blue leads), with a warm blackbody
ember core underneath. Spectrum dominates so the detonation reads as RAINBOW,
not a white plasma flash.
Plus per-world cosine palettes (IQ) so each world is a distinct PLACE. All the
white-out guardrails preserved + extended: rim-gated blast, capped kelvin/gain,
emissive blast held below the color path. Beats 0/1 stay calm (low uBlast),
Acts II/III blaze.
Frontier techniques sourced from a parallel web-research + design workflow;
verified against the installed three@0.172 TSL build. Retires the old uShape
5-form gallery.
Gate: svelte-check 0/0, 937/937 tests pass, build green, verified live (7
distinct worlds, spectral blast, no white-out, calm opening).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Memory Cinema storm color/shape overhaul (the crown-jewel pillar):
- Fix the white-out root cause: emissiveNode was NEVER set, so the selective
MRT bloom had no color to bloom and washed the frame white. Route the shared
iridescent rainbow to BOTH colorNode and emissiveNode.
- Rim glow (fresnel-style): bright glowing edges, dim readable center — the
shareable luminous-shell / hollow-torus look.
- Morphing geometry: the home target cycles sphere → torus → galaxy spiral →
cube lattice → wave sheet, drifting continuously and snapping per beat.
- Hyper-saturated full-spectrum palette (per-particle phase + radial shells +
spatial bands + time) so the whole rainbow is present at once.
- Spread the initial spawn across a wide hollow shell (was a tiny dense ball
that boot-flashed white).
- Act/beat-aware brightness: beats 0/1 fade in soft, Act I held calm, Acts
II/III blaze at full. No white-out regressions.
Gate: svelte-check 0/0, 937/937 tests pass (cinema auteur/pathfinder green),
verified live in browser.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>