Commit graph

100 commits

Author SHA1 Message Date
Sam Valladares
4c6a24a35a feat(journey): wire Receipt → centered Graph → auto-Cinema → Explore, all base-safe
The hero journey now flows through visible controls with cognitive context that
survives navigation (os-nav.ts gets its first real consumers):
- /dashboard/ redirects to /dashboard/palace (the home), base-safe (was a bare
  goto('/graph') that escaped the base + landed on the wrong organ).
- ReceiptCard 'Open in Cinema' uses osGoto with {memory, focus, receipt, cinema}
  — fixes the base-escape 404 AND carries the full evidence set.
- Graph consumes ?memory= (canonical; ?center= legacy alias), centers on it, and
  a Graph-OWNED one-shot bridge auto-launches the PROTECTED Cinema by clicking its
  own .cinema-launch control (MemoryCinema untouched).
- Graph 'Explore Connections' now carries the selected memory; Explore seeds the
  walk from THAT memory instead of re-seeding from the newest.
Verified live: /→palace, graph?memory=X&cinema=1 centers + auto-opens Cinema (0
errors), explore?memory=X seeds a walk. check 0/0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 11:31:26 +07:00
Sam Valladares
3200f04de2 Merge remote-tracking branch 'origin/main' into feat/dashboard-live-max
# Conflicts:
#	apps/dashboard/build/_app/immutable/assets/14.Bjd0S47S.css
#	apps/dashboard/build/_app/immutable/assets/14.Bjd0S47S.css.br
#	apps/dashboard/build/_app/immutable/assets/14.Bjd0S47S.css.gz
#	apps/dashboard/build/_app/immutable/assets/17.ChjqzJHo.css
#	apps/dashboard/build/_app/immutable/assets/17.ChjqzJHo.css.br
#	apps/dashboard/build/_app/immutable/assets/17.ChjqzJHo.css.gz
#	apps/dashboard/build/_app/immutable/assets/18.BnHgRQtR.css
#	apps/dashboard/build/_app/immutable/assets/18.BnHgRQtR.css.br
#	apps/dashboard/build/_app/immutable/assets/18.BnHgRQtR.css.gz
#	apps/dashboard/build/_app/immutable/assets/20.DKhUrxcR.css
#	apps/dashboard/build/_app/immutable/assets/20.DKhUrxcR.css.br
#	apps/dashboard/build/_app/immutable/assets/20.DKhUrxcR.css.gz
#	apps/dashboard/build/_app/immutable/assets/22.DKhUrxcR.css
#	apps/dashboard/build/_app/immutable/assets/22.DKhUrxcR.css.br
#	apps/dashboard/build/_app/immutable/assets/22.DKhUrxcR.css.gz
#	apps/dashboard/build/_app/immutable/assets/25.DKhUrxcR.css
#	apps/dashboard/build/_app/immutable/assets/25.DKhUrxcR.css.br
#	apps/dashboard/build/_app/immutable/assets/25.DKhUrxcR.css.gz
#	apps/dashboard/build/_app/immutable/assets/5.DQ_AfUnN.css
#	apps/dashboard/build/_app/immutable/assets/5.DQ_AfUnN.css.br
#	apps/dashboard/build/_app/immutable/assets/5.DQ_AfUnN.css.gz
#	apps/dashboard/build/_app/immutable/assets/6.DQ_AfUnN.css
#	apps/dashboard/build/_app/immutable/assets/6.DQ_AfUnN.css.br
#	apps/dashboard/build/_app/immutable/assets/6.DQ_AfUnN.css.gz
#	apps/dashboard/build/_app/immutable/assets/7.DQ_AfUnN.css
#	apps/dashboard/build/_app/immutable/assets/7.DQ_AfUnN.css.br
#	apps/dashboard/build/_app/immutable/assets/7.DQ_AfUnN.css.gz
#	apps/dashboard/build/_app/immutable/assets/7.F0TwMZ5M.css
#	apps/dashboard/build/_app/immutable/chunks/BLadwbF7.js
#	apps/dashboard/build/_app/immutable/chunks/C4h_mRt2.js
#	apps/dashboard/build/_app/immutable/chunks/CqMQEF-F.js
#	apps/dashboard/build/_app/immutable/chunks/De_e6MzK.js
#	apps/dashboard/build/_app/immutable/chunks/DzesjbbJ.js
#	apps/dashboard/build/_app/immutable/nodes/20.DENLzARE.js
#	apps/dashboard/build/_app/immutable/nodes/22.C719k-1W.js
#	apps/dashboard/build/_app/immutable/nodes/25.CpxKI_0Q.js
#	apps/dashboard/build/_app/version.json
#	apps/dashboard/build/_app/version.json.br
#	apps/dashboard/build/_app/version.json.gz
#	apps/dashboard/build/index.html
#	apps/dashboard/build/index.html.br
#	apps/dashboard/build/index.html.gz
2026-07-13 11:15:50 +07:00
Sam Valladares
b0b69a1edf fix(os): close 4 shell launch blockers — dup nav, capture leak, palette a11y, Cinema keyboard collision
Audit BLOCK: (1) DUPLICATE MOBILE NAV — removed the legacy MobileNav (mounted in
(app)/+layout); the registry-driven os-mobilebar is now the ONE mobile nav.
(2) CAPTURE LEAK — showShell now also hides on ?frame=N (was capture only), and
removing MobileNav kills its un-gated leak; ?frame=1 and ?capture=1 both show 0
chrome. (3) PALETTE A11Y — role=dialog + aria-modal + a paletteDialog action that
traps Tab focus, marks [data-app-root] inert while open, and restores focus to
the opener on close. (4) CINEMA KEYBOARD COLLISION (most serious) — the shell's
⌘K/Escape now no-op while a full-screen takeover owns the keyboard, detected via
a READ-ONLY .cinema-overlay DOM probe (Cinema stays protected/untouched) plus a
new shell.svelte store for non-DOM takeovers. Verified live: mobileBars=1,
frame/capture chrome=0, dialog role+inert set/cleared, palette blocked during
Cinema. check 0/0, 980 files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 10:58:36 +07:00
Sam Valladares
4168925099 feat(os): the VestigeOS nervous system — canonical registry + persistent shell + mutation safety
THE nervous system (audit P0): one os-routes.ts registry (all 20 organs w/ group/
shortcut/icon/purpose) + base-aware os-nav.ts (osHref/osGoto + URL cognitive
context: memory/run/receipt/q/focus/cinema/days/filter). The root shell is now a
FLOATING dock + grouped ⌘K palette that overlays every full-bleed canvas organ,
so no page is a navigation island (Palace is in the nav for the first time).
Hideable via ?capture=1 for clean hero footage. Verified live: dock renders +
⌘K palette opens over the canvas, 0 console errors.

MUTATION SAFETY (audit dangerous-interactions, via M3 worker): a plain click now
SELECTS, never silently mutates. Feed no longer wipes on click (clearEvents gone);
Stats no longer runs consolidate() on a vital click (explicit button only);
Memories plain-click selects instead of promoting, with a visible affordance hint
for shift/alt. check 0/0, 979 files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 10:42:37 +07:00
Sam Valladares
65595b9ffc checkpoint(dashboard): mobile reflow + field richness + fake-data fixes + predict FSRS urgency
Verified-green pre-OS-shell checkpoint. Mobile portrait reflow (portraitAdapt +
MobileNav), desktop field-richness on 7 text organs, 4 fake-data fixes (settings
version, TRIGGER BIRTH removed, predict real per-memory urgency, palace DIAG),
timeline dim-backdrop, stats depth-floor, em-dash cleanup, per-tier launch-gate
fill floors. check 0/0, 977 files. Cinema WIP isolated to stash.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 10:32:22 +07:00
Sam Valladares
0b16709fbe test(dashboard): organ-graph clears the renderer pref for a deterministic default
Graph persists its renderer choice ('field'|'classic') in localStorage. In a
full-suite run a prior test could leave 'classic', so this test — which asserts
the WebGPU Field is the active/default renderer — intermittently failed. Clear
the pref via addInitScript before navigating so it deterministically gets the
field-mode default. Passes now even when ordered right after the graph-using
birth-ritual suite.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 07:28:00 +07:00
Sam Valladares
5a8d7bc1b7 test(dashboard): birth-ritual drives the zero-DOM settings birth control
Settings is a zero-DOM WebGPU console — '[ TRIGGER BIRTH ]' is an in-canvas MSDF
pick, not a DOM button. injectBirthViaSettings clicked getByRole('button', …)
which timed out. Click the canvas at the birth control's NDC (0.06, -0.5) instead
(with a small sweep for the MSDF hit box), and route the triple-birth test through
the same helper. All 3 birth-ritual visual-proof tests pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 07:20:39 +07:00
Sam Valladares
62984b74e6 fix(dashboard): reasoning stays honest-empty; update stale zero-DOM specs
Reasoning: replace the mount-time auto-run of a deep_reference (which violated
the honest-empty "ask a question to trace" contract) with a passive real
memory-pool substrate. The stage is alive at rest (55% fill) without claiming a
trace; a real query swaps the pool for the actual evidence galaxy. Align the ask
placeholder with the specs.

Specs: the Reasoning Theater is zero-DOM (sr-only input, everything in-canvas) as
of the living-field conversion, but organ-reasoning + reasoning-flow still drove
a visible input and asserted DOM response panels (Primary Source / Cognitive
Pipeline / EvidenceCards) that no longer exist. Rewrite them to fill the sr-only
input by id, wait on the real /api/deep_reference 200, and assert the canvas
re-lights (fill + non-black + animates) — proving the flow on pixels + the API
round-trip. organ-explore asserted a dead /memories/{id} navigation; the row
click is an in-place semantic walk (?q= re-centers), so assert that instead.

All three reasoning specs + explore now pass against the real brain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 07:12:45 +07:00
Sam Valladares
fa74224266 test(dashboard): patterns organ spec tolerates the empty-pattern state
The cross-project pattern set is recomputed and legitimately empty at times.
The spec hard-required patterns.length > 0 and 500+ lit row pixels, so it
false-failed whenever the brain had zero standing transfers. Branch on the
real count: assert the pattern rows when patterns exist, and assert the
memory-pool substrate still fills the field (fillPct > 20) when they don't —
matching the organ's real behavior. Also refresh the stale docstring
(LivingFieldPass galaxy + pool fallback, not just an MSDF text field).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 07:00:10 +07:00
Sam Valladares
e60e568160 fix(dashboard): audit pass — clickable field cells, empty-data substrate, reduced-motion
Full multi-team audit of the living-field work (adversarial fleet + fresh-eyes
pass + foundation deep-dive). 11 real bugs found and fixed; 7 false positives
adversarially refuted. All re-verified live on the real brain.

Pick contract: field cells were unclickable in intentions/schedule/memory-prs/
importance — the click handlers read the old text-item id off a node payload.
Read the id from either shape; importance now also picks the field pass;
intentions gets a dedicated filter toggle instead of flipping the filter on every
click. RouteStage now picks passes top-down (front-rendered text before
back-rendered field) so a background cell can't steal a foreground control's
click. Proven live: cell clicks fire real promote/act with real memory ids.

Empty data: /patterns went black when the cross-project set is empty (it is
recomputed). Seeded a real memory-pool substrate it falls back to, like
contradictions — alive at zero patterns.

Correctness: memories unsuppress now honors UnsuppressResult.stillSuppressed
(compounded suppression stays scarred). LivingFieldPass no longer writes the
shared params[2] node_count lane (was corrupting the co-resident scene renderer
on graph/observatory/memories). Finite-guard every value reaching the GPU buffer
so a bad mapper can't NaN-out the field. blackbox selected-cell highlight tracks
selectedRunId. graph nulls its field handle when leaving field mode.

Accessibility: /memories and /importance (direct ObservatoryCanvas mounts) now
honor prefers-reduced-motion via engine.setPaused — the field freezes for
reduce-motion users. Gate pins reducedMotion:'no-preference' so the motion
assertion is stable.

Gates green: check 0/0, build ok, palace-launch-gate 22/22 + curated tour,
all-routes-smoke 20/20, ChangelogResponse gains totalEvents.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 06:57:19 +07:00
Sam Valladares
844b91a804 feat(dashboard): every organ is a living WebGPU field (LivingFieldPass)
Turn all 17 sparse organs from text-on-black voids into full-bleed, moving,
bioluminescent WebGPU fields. Each cell maps to a real backend fact; verified
live on the real brain with a decoded fill% + motion + zero-error probe.

Foundation: one reusable LivingFieldPass (src/lib/observatory/field/) does
splat -> separable-blur (render passes) -> membrane base coat -> HDR cells with
orbital drift and a CPU pick-mirror. Each organ writes a ~20-line data->cells
mapper (cell-layout.ts: layoutGalaxy / layoutRings / FIELD_HUE).

Organs brought alive (fill% before -> after, all zero WebGPU errors):
stats 0.8->80.9, observatory 10.8->81.4, graph 12.3->82.4, memories ->78.4,
blackbox 18.2->83.3, contradictions 1.6->69.6, dreams 0.3->64.5,
settings 2.7->76.4, reasoning 2.7->39.2, patterns 7.1->45.6,
activation 10->64.9, feed ->89, explore ->83.3, intentions ->66.6,
importance ->73.7, memory-prs ->74.4, schedule ->37.1.

Backend surfaces: add api.memoryChangelog() + ChangelogResponse; surface
suppress/unsuppress on the memories field (shift/alt-click -> scar).

Tests: palace-launch-gate now asserts fillPct>30 + isAnimating (not just
non-black), with a longer settle for reasoning's deep_reference and a raised
timeout for the curated tour. all-routes-smoke treats settings as the WebGPU
field it now is. Gates green: check 0/0, build ok, palace-launch-gate 22/22 +
tour, all-routes-smoke 20/20.

Protected work untouched: MemoryCinema, graph/cinema, observatory scene
shaders, node-renderer, palace-map.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-12 06:20:35 +07:00
Sam Valladares
b65721c2f0 feat(dashboard): /memories is now a real-data Parallax MSDF field
Every line is a REAL memory from api.memories.list, rendered as glowing MSDF:
content snippet | id[:8] | retention%. Depth=retrievalStrength, stroke
weight=retentionStrength — a memory near the forgetting horizon renders
dimmer and thinner. Cursor-reactive (inherits the Parallax field). ASCII-
sanitized (real content has em-dashes/curly quotes the atlas can't draw).
Zero DOM, zero hardcoded text. check 0 errors.

Verified live: renders real memory ids (8bf0bb5a, 9070cece, 6d54f085) and
real retention (100%, 100%, 89% — the 89% line visibly dimmer).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 13:56:40 -07:00
Sam Valladares
c12b21ae45 feat(dashboard): crank the Parallax cursor effect so it's unmistakable
v1 magnitudes were imperceptible (verified live: cursor reached the shader but
R=0.45/lift=0.20/glow=0.6 gave ~16% influence at the text = invisible). Cranked
for the signature 'alive' read: influence radius 0.45→0.75 (reacts when the
cursor is anywhere near, not dead-on), z-lift 0.20→0.42, glow 0.6→1.4, added a
per-glyph scale-up (×1.55 near cursor) so glyphs visibly swell toward the
pointer, lean 0.015→0.04, warp tuned to 0.007 (liquid ripple, still readable).

Verified live on the real dashboard: glyphs near the cursor swell, flare bright,
and ripple like liquid mercury. check 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 13:44:35 -07:00
Sam Valladares
0d50eac624 feat(dashboard): Parallax Engram Field — cursor-reactive 3D/4D text
The dashboard text is now a volumetric field: each glyph floats at a depth
set by its trust, stroke weight set by FSRS retention, blur by confidence,
glow by salience. Move the cursor and nearby glyphs lift toward the camera,
lean, and ripple (SDF domain-warp); the field parallaxes like a diorama.
Every motion is a real memory fact — Math.random would visibly break it.

v1: PARAMS 16→20 cursor uniform (pre-divide NDC + velocity + off-canvas
sentinel), depth/weight packed into the free info.zw glyph lanes, vertex
depth→clip.z + Gaussian cursor lift + lean + pulse parallax, fragment SDF
warp + retention weight bias + depth-of-field + depth glow. Zero new render
passes. Deterministic (params.time/frame, never wall clock).

Built by GPT-5.5 against a source-verified scour spec (8-agent frontier
research combining W-perspective depth, cursor Gaussian fields, SDF warp,
and weight-as-data-gauge). Conductor live-GPU audit caught + fixed two
visual bugs: z clamped positive so cursor-lift never clips glyphs behind the
near plane; resting depth-of-field and glow floor raised so the field is
readable and lit at rest, sharpening toward the cursor. Verified live: text
glows at rest, brightens and lifts toward the pointer. check 0 errors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 13:32:15 -07:00
Sam Valladares
a4a36ee220 feat(dashboard): zero-DOM RouteStage + in-canvas WebGPU nav
RouteStage.svelte rebuilt: no slot chrome, no pause button, no telemetry/
loading/error/empty divs. One transparent pointer host + the canvas. Pause,
telemetry, and all lifecycle states now render as MSDF glyphs via TextLayerPass;
the sidebar nav is now an in-canvas WebGPU rail (nav-layer.ts) with all 19
routes, active route glowing cyan, hover ignition, click-to-navigate.

check 0 errors 0 warnings (the slot-deprecation warning is gone), build green.
The 5 organ routes still compile. Their own page DOM headers convert in Day-2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 13:05:52 -07:00
Sam Valladares
b85740d0e7 feat(dashboard): bypass DOM app shell for all organs (zero-DOM step 1)
Every dashboard route except marketing/waitlist now renders bare children:
no sidebar nav, no websocket toasts, no ambient orbs, no command palette.
Extends the existing /observatory immersive bypass to the whole app.

Verified live: the MSDF test route drops from ~304 DOM elements to 3 empty
structural divs, no <nav>, just the WebGPU canvas. The nav itself will be
rebuilt as an in-canvas WebGPU layer. check green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 12:47:50 -07:00
Sam Valladares
389ddfa294 feat(dashboard): MSDF text engine — the all-WebGPU text linchpin
Day-1 linchpin of the zero-DOM Cognitive OS. Every label, receipt id, and
number in the dashboard now renders as glowing in-canvas MSDF glyphs instead
of DOM text. Checked-in JetBrains Mono mtsdf atlas (512x512, 95 glyphs) +
loader + pure layout helper + FramePass + trap-checked WGSL.

Built by a GPT-5.5 swarm against an adversarially-verified spec (5 verifiers
+ 3 skeptics caught 6 silent-fail traps before a line was written: V-flip,
release-binary atlas embed, base-path fetch, linear rgba8unorm, premultiplied
blend, ASCII-only charset). Conductor live-GPU audit on the real dashboard
found one more at runtime: the aspect transform pushed text off-screen in
portrait; fixed to keep glyphs square in both orientations.

Renders cyan, crisp, upright, glowing, glyph-by-glyph, landscape + portrait.
check 0 errors, build green, golden V-flip test 2/2.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 12:43:58 -07:00
Sam Valladares
f167be2663 feat(dashboard): Organ Blackbox — Agent Flight Recorder Nerve Trace
Built by GPT-5.5 swarm worker, audited + fixed live by Opus 4.8. An agent
run rendered as a living nervous system: tool calls / retrievals / writes /
suppressions / vetoes as impulses, receipts as beads, real TraceEvent order.

- blackbox/blackbox-scene.ts + blackbox-pass.ts (metaball nerve field, all
  render passes, no storage textures) + wired route.
- Live-GPU audit caught a WGSL 'meta' reserved-keyword struct field
  (invalid module, 600 pipeline errors/frame, gates green) — renamed to
  'beat'. Added meta to the brief's reserved-word list.

Verified live vs the real brain: real agent runs list, real event log
(Tool Call smart_ingest, Wrote <memory-id>), real event producers
(mcp.call/memory.write/retrieve/suppress), honest empty states (no
contradiction/dream/veto this run), 115fps. check+build+1043 tests green.
Cinema + Graph field untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 09:21:11 -07:00
Sam Valladares
722d0f8738 feat(dashboard): Organ 3 — Contradictions "Immune Synapse Arena"
The second Cognitive OS flagship, built by GPT-5.5 in the council,
audited + verified live by Opus 4.8.

- contradictions/contradictions-scene.ts: /api/contradictions →
  RouteSceneModel. Real backend {stronger:{id},weaker:{id},topic_overlap}
  shape + DeepReferenceCompleted.contradiction_pairs. Provenance enforced.
- contradictions/contradictions-pass.ts: dual-channel signed metaball
  field — side A (stronger) splats red, side B (weaker) green; the seam
  (min(r,g) + opposing gradient) renders as a scarlet immune synapse.
  Trust thickens the membrane. Unresolved pairs spark scarlet arcs.
  All render passes (splat→render-pass blur→membrane), no storage
  textures, scarlet not magenta (magenta stays RSB-only).
- contradictions/+page.svelte: RouteStage full-bleed, replaced the
  AmbientField base coat. Seam-pick → DOM receipt drawer. Honest
  "CALM IMMUNE FIELD" empty state.

A WGSL struct-field mismatch (PairCell.meta vs p.signals) made the splat
pipeline invalid at runtime — caught by the live-GPU audit (invisible to
check/build), root-caused with getCompilationInfo + a web-verified spec
research pass, fixed by renaming the field.

Verified live vs the real 1241-memory brain: 104fps, valid pipelines,
zero GPU errors, honest empty state (brain has 0 standing contradictions).
check + build + 1043 tests green. Cinema + Graph field untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 08:46:56 -07:00
Sam Valladares
b5150f0b90 feat(dashboard): Organ 1 — Reasoning Theater (Cognitive OS de-risk prototype)
The first full-bleed WebGPU organ of the Cognitive Bioluminescent Cortex,
built by GPT-5.5 in the design council, audited + fixed live by Opus 4.8.

- RouteStage.svelte: reusable organ shell (engine/canvas lifecycle, WebGPU
  fallback, reduced-motion auto-pause, persistent pause control) — the
  lifecycle-only reuse of ObservatoryStage, NOT its Graph data path.
- reasoning/reasoning-scene.ts: /deep_reference → RouteSceneModel adapter.
  Honest 8-stage derivation from real fields (label unexposed internals),
  real backend contradiction {stronger/weaker} + superseded {superseded_by}
  shapes, provenance enforced.
- reasoning/reasoning-theater-pass.ts: the 8-chamber organ. Metaball field
  (additive splat -> render-pass separable blur -> membrane, all render
  passes, no storage textures), compute Bezier spline packet advection,
  labeled deterministic replay of the one-shot receipt. Palette-driven;
  magenta stays RSB-only; contradictions scarlet.
- reasoning/+page.svelte: query -> /deep_reference -> scene -> full-bleed
  organ behind the DOM answer/evidence panels.

Three WebGPU runtime traps caught by the live-GPU audit (invisible to
check/build) and fixed: (T6) no read_write storage in a shared compute+
render module; (T3) no rgba16float write-storage blur -> use render-pass
blur; and the 'active' reserved-keyword WGSL parse error.

Verified LIVE vs the real 1241-memory brain: query "How does FSRS-6 trust
scoring work?" lit the chambers with a REAL memory (trust 51%), 84%
confidence, 26 analyzed, contradiction stage correctly dark (none real),
120fps. check + build + 1043 tests green. Cinema + Graph field untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-09 00:10:29 -07:00
Sam Valladares
0f242231d4 feat(observatory): Cognitive Cortex foundation — palette + scene model
Shared foundation for the Cognitive OS dashboard (design council Opus 4.8
× GPT-5.5). Both locked, zero-risk, no engine changes yet.

- cognitive-palette.ts: the invented "Causal Bioluminescent Cortex" color
  language. Blackwater base (never purple), retention oxygen ramp
  (sediment→amber→green→luciferin), magenta reserved ONLY for RSB
  retrograde causality, indigo ONLY for bitemporal parallax, scarlet for
  the immune system. Event→impulse map, trust→membrane width, retention
  →color. One source of truth to prevent per-route accent drift.
- route-scene.ts: RouteSceneModel — the adapter↔RouteStage contract with
  the discipline test enforced in the type system (every primitive carries
  real Provenance: memory/event/receipt/pair/trace/pr/pattern/scalar).
  assertProvenance() trips a screensaver primitive in dev before it ships.

check green. Foundation only — RouteStage waits on the council's
buffer-layout decision.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 23:18:36 -07:00
Sam Valladares
435d3f4098 feat(observatory): reduced-motion + persistent pause control for the field
Closes the launch guardrail: the field's ambient orbit + force-sim drift
run >5s, so WCAG needs a persistent pause control and prefers-reduced-
motion must be honored.

- engine.setPaused(): freezes the deterministic clock so the orbit + sim
  drift hold still, while the frame still renders and the live preFrameHook
  still runs — discrete event pulses (firewall, decay, dream) are
  information, not decoration, so they land even when motion is reduced.
- ObservatoryStage: a persistent ❚❚ PAUSE / ▶ RESUME control on the live
  field; auto-pauses under prefers-reduced-motion (user can override).

Verified live: the pause button toggles engine.isPaused (frozen drift,
pulses still land); check 0 err, 1043 tests, build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:34:31 -07:00
Sam Valladares
da3bc5e5d7 feat(dashboard): metric-bound ambient base coat for the quiet routes (Phase 5)
The dead routes were flat purple. This adds ONE cheap WebGPU substrate
behind them whose drive is REAL backend metrics, so it legibly READS the
data instead of being decoration — a store with 129 endangered memories
storms; 0 contradictions is a calm field (the discipline test still holds).

- AmbientField.svelte + ambient-field.wgsl: a metric-bound mote field.
  Each mote's vertical drift IS its retention (low sinks to the forgetting
  floor, high floats up); the real endangered fraction storms turbulence +
  the sink split; contradiction fraction tears rifts; due-for-review
  pulses it. Deterministic per mote (no Math.random in the loop).
- Guardrails: no WebGPU / null adapter / context throw -> renders nothing
  (page background shows, never a black canvas). prefers-reduced-motion
  freezes drift but keeps the metric snapshot. Page-Visibility +
  IntersectionObserver gate the rAF loop. DPR clamped, mobile-first budget.
- Wired to the two highest-signal routes: /stats (endangered + due) and
  /contradictions (fracture). Reusable — any remaining route adopts it with
  one import + real metric props.

Verified live: /stats renders the field reading the retention distribution
(dense healthy top, endangered embers); /contradictions shows a calm
crimson field at 0 contradictions (fracture=0). check 0 err, 1043 tests,
build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:29:07 -07:00
Sam Valladares
07921cfd52 feat(observatory): RSB causal recall wavefront on the live field (Phase 4)
A real recall lights the backward CAUSE chain through the graph — every
hop after the origin follows a real ConnectionType::Causal edge, not mere
co-occurrence. This is the conjunction no competitor has: RSB's directed
causation + the causal edge type + per-memory FSRS + the raw-WebGPU engine.

- pathfinder: isCausalEdge() + a preferCausal walk option (defaults false,
  so Memory Cinema is byte-identical). When set, the greedy walk prefers
  real causal edges every step, tracing true causation.
- path-builder: buildRecallPath gains preferCausal + centerId; causal hops
  (detected on viaEdge.type, keeping the shared Cinema beat-kind union and
  the protected narrator untouched) map to PATH_KIND.backwardCause — the
  magenta backward rim in render-path.wgsl.
- live-bridge: a real DeepReferenceCompleted (or BackfillFired) whose
  primary is in-field rebuilds the PathStep buffer centered on the real
  recalled memory, preferring causal edges, and rides the proven recall
  wavefront machinery. Honest scope: only lights when the recalled memory
  is actually on screen (never invents a path).
- 2 new tests: the pathfinder picks the real cause over the strongest
  co-occurrence; a live DeepReferenceCompleted arms the causal wavefront.

Verified live: injected a real in-field DeepReferenceCompleted → the
bridge armed causalRecall for the real primary + set an 8-step path whose
7 post-origin hops are ALL kind-1 (backward-cause) following real causal
edges. 1043 tests, check + build green. Cinema untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:19:25 -07:00
Sam Valladares
1b23516579 feat(observatory): dream consolidation storm on the live field (Phase 3)
When the real dream pipeline runs, the field enters a metabolic storm:
damping loosens, the newly-discovered edges are appended live, and their
springs pull the clusters into their new shape.

- node-renderer: setEdges() — a setPathSteps clone that regrows the edge
  index buffer, updates the CPU graph, bumps edge_count, rebuilds the sim
  pipeline so new springs act immediately.
- simulate.wgsl: while live_kind==dreamStorm, damping loosens with
  live_energy + a deterministic turbulence rides the envelope (pure of
  node index + live_frame, so no wall clock).
- live-bridge: real ConnectionDiscovered pairs append to a deduped edge
  accumulator, coalesced to ONE setEdges per frame (a 1000-edge burst is
  one regrow, not a thousand). Storm fires on DreamStarted OR
  DreamCompleted (a real dream floods the 200-event ring and evicts
  DreamStarted, so Completed must also arm it), holds ~6s, settles.
- ingest rewrite: timestamp watermark instead of object-identity dedup —
  robust to ring eviction AND browser/backend clock skew (seeds from the
  backend clock, never the browser wall clock). This fixed a real bug
  where a 36s clock skew silently dropped every event.
- 8 new LiveBridge unit tests machine-prove decay/firewall/storm/edges
  (the multi-second storm can't be screenshotted in a frozen-rAF preview).

Verified: firewall re-fired live post-rewrite naming the real memory;
1041 tests (8 new), check + build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 22:07:32 -07:00
Sam Valladares
d7f5657bc7 feat(observatory): contradiction firewall fires on real events (Phase 2)
The crimson quarantine firewall was hard-locked to the deterministic demo
clock. Now it fires on real cognitive events — a MemorySuppressed or a
DeepReferenceCompleted contradiction pair — targeting the REAL memory and
its REAL graph neighbors, on camera.

- firewall-plan: buildLiveFirewallPlan(graph, seed, intruderIndex) reuses
  all the deterministic machinery (real-layout shock delays, real severed
  neighbors, spine, verdict) but takes the intruder from the live event.
- firewall.wgsl + render-nodes.wgsl: dual-gate on demo_id==4 OR
  live_kind==1, driven by live_frame (frames since the event) so the
  720-frame beat map plays once from the event, not the loop clock.
- firewall-renderer: rearm(plan) rebuilds the fire buffer for a live
  target; compute() gates on demo OR live.
- live-bridge: lazily builds + rearms a live FirewallRenderer on a
  firewall event; onFirewall callback surfaces the verdict.
- ObservatoryStage: crimson "threat quarantined" verdict card naming the
  real memory, auto-clears after the choreography.
- live lane [13] repurposed liveStartFrame -> liveFrame (event-relative).

Verified live: fired 3 real suppressions on the 1241-memory brain — each
raised the crimson verdict naming the real memory ("ProtocolGate Lane 4
design decision", cascade ~54), the field ran the quarantine, the forget
counter incremented 129->132, then all 3 reversed cleanly. check 0 err,
1033 tests, build green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:49:22 -07:00
Sam Valladares
addbf260f1 feat(observatory): live event bridge + live FSRS decay field (Phase 0+1)
The raw-WebGPU field was inert — it ran the deterministic DemoClock and
never heard the backend. This wires it to the real event stream and makes
every memory visibly forget on its true FSRS curve.

- LiveBridge (new): lock-free per-frame drain via engine.preFrameHook,
  ingests $eventFeed oldest-first, decodes real events into live lanes.
- fsrs.ts (new): exact TS port of retrievability_with_decay (w20=0.1542).
- params 12→16 floats (capture_mode + 4 live lanes); all 8 WGSL Params
  structs updated in lockstep. _pad renamed to its real meaning.
- node-renderer: live-retention GPU buffer (binding 4); simulate.wgsl
  overwrites vel_retention.w so render-nodes dims on the real curve.
- ObservatoryStage: `live` prop, $eventFeed subscription, persistent
  FORGETTING HORIZON scrubber (project the curve forward N days, honest).
- backend: get_graph node json now carries stability + lastAccessed.

Verified live vs the real 1241-memory brain: +300d scrub visibly decays
low-stability nodes while high-stability survive; per-node FSRS math
confirmed. svelte-check 0 err, 1033 tests, build, cargo check all green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-08 21:41:18 -07:00
Sam Valladares
f58cbd3f1e Merge branch 'main' into feat/dashboard-live-max 2026-07-08 19:33:15 -07:00
Sam Valladares
9f5a1fde4a feat(observatory): GPU picking — click a memory in the field to inspect it
The living field is now interactive, killing Classic's main reason to
exist. Clicking a node in the WebGPU field opens the same Memory Detail
inspector (content, FSRS bars, retention forecast, promote/demote,
explore) that Classic's Three.js picking drove.

How: NodeRenderer.pickAt(ndcX, ndcY) — the one sanctioned GPU readback,
input-driven and click-frequency only, so the render loop's determinism
contract (spec §6) holds. It copies the live NodeState buffer (post
force-sim positions) to a MAP_READ staging buffer, reprojects every node
on the CPU through the SAME deterministic orbit camera the frame used
(engine params phase + canvas aspect, column-major viewProj), and picks
the nearest node whose projected disc (r·f/w with a floor for faint
nodes, 1.6x halo slop) contains the click. NodeState gains COPY_SRC for
the copy; a fresh staging buffer per click is created and destroyed.

ObservatoryStage gains an onpick prop wired to the canvas layer
(crosshair cursor when interactive); the graph page passes onNodeSelect
so field picks open the existing panel.

Verified live: click at field center hit a real memory, panel opened
with real FSRS data (retention 65.4%, forecast 65%->37% @30d), zero
console errors. svelte-check 940 files 0/0; 96 observatory tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 19:22:07 -07:00
Sam Valladares
c920f93b10 feat(graph): raw-WebGPU living field is now the main dashboard renderer
The main graph page defaults to the Observatory engine — GPU force sim,
HDR bloom, and the recall wavefront sweeping the REAL memory graph on a
12s loop — instead of the flat Three.js view. Visuals to the max, per
the locked ALIVE-field direction.

- ObservatoryStage gains embedded (fills parent, not viewport) and
  chrome ('full' | 'none') props; chrome='none' is a pure living canvas
  plus loading/error text, so the page's own DOM chrome stays in charge.
- New Field | Classic renderer toggle in the control bar. Field is the
  default wherever WebGPU exists; no WebGPU forces classic. Choice
  persists in localStorage.
- Classic (Three.js) remains one click away and untouched: node picking,
  colour modes, node count, brightness, temporal scrubbing and legends
  are classic-renderer features and now only render there. Dream,
  Observatory takeover, Memory Cinema (protected) and Reload work in
  both modes.

Verified live: fresh load defaults to Field (148 real nodes, 2865 real
edges, recall ribbon igniting on camera, zero console errors); Classic
toggle restores search/colour/brightness with a single canvas; the
choice round-trips through localStorage. svelte-check 940 files 0
errors 0 warnings.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 12:06:01 -07:00
Sam Valladares
7da5f4aa97 feat(observatory): integrate into the main dashboard graph
The Observatory is no longer a separate URL you have to know about. It
is now a first-class part of the main graph page, following the proven
Memory Cinema pattern (which remains untouched per the protected-block
rule):

- The full experience is factored into a reusable ObservatoryStage
  component (engine, plans, overlays moved verbatim from the route).
- The graph control bar gains an Observatory button beside Dream and
  Memory Cinema; clicking it takes over the screen full-bleed (z-50).
- Inside the stage: an on-screen switcher for the 5 cognitive moments
  (RECALL / BIRTH / RESCUE / HORIZON / FIREWALL) and an EXIT control
  (Esc works too) that returns to the graph exactly as it was. Both are
  hidden in capture mode so recordings stay chrome-free.
- {#key demo} remounts the stage per moment: fresh engine, plans, and
  clock, deterministic from frame 0.
- The /observatory route stays as a thin wrapper so deep links and the
  ?frame=N / ?capture=1 recording contract are unchanged; switching a
  moment there rewrites the URL so links stay shareable.

Verified live in the running dashboard: button renders between Dream
and Cinema, click boots the WebGPU takeover (148 real nodes, 2865
edges), RESCUE chip switches the moment (telemetry: SALIENCE-RESCUE),
EXIT unmounts cleanly back to the graph (canvas count 2 -> 1).
svelte-check 940 files 0 errors 0 warnings; 96 observatory tests green.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 11:54:03 -07:00
Sam Valladares
e886d4e5e7 fix(observatory): dense real memory field + hold the verdict card
Two demo-readiness fixes so the Observatory reads as a living brain
doing real work, not a sparse placeholder:

1. Graph query switched from sort=recent to sort=connected (max_nodes
   200). 'recent' centered on the newest memory, a lonely node whose
   depth-3 neighborhood is only ~12 nodes, so the field looked empty.
   'connected' surfaces the populous hotspot: ~148 real memories and
   ~2865 real edges, laid out as two dense clusters. Verified live on
   recall-path and salience-rescue: 148 nodes / 2865 edges at 110-119fps.

2. Verdict card now holds. The 'root cause found' card faded fully out
   by frame 660 in a 720-frame (12s) loop, so it flashed for ~1s then
   vanished. Widened the default fade window to [600,620,705,719]: it
   fades in, holds fully readable through the field's decay to rest, and
   only fades out just before the seamless loop wrap. ~1.75s of readable
   verdict instead of a blink. GPU envelopes and the seam-zero loop test
   are unaffected (DOM overlay window is independent of the sim).

Verified live against the real brain: 96 observatory tests green, zero
console errors, verdict readable at frames 660 and 695 (both blank before).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 11:07:14 -07:00
Sam Valladares
a046c620c8 feat(observatory): raw-WebGPU living cognitive field with 5 deterministic demos
The Observatory is a full-bleed, zero-library WebGPU surface that renders
the memory graph as a living cognitive field. Five deterministic demo
moments driven by a URL contract (?demo=<name>&seed=...&frame=N):
recall-path, engram-birth, salience-rescue, forgetting-horizon, firewall.
Capture mode (?frame=N) freezes the sim deterministically so the same URL
produces identical pixels, the viral-clip primitive.

Architecture: bare-metal WebGPU engine (no Three.js), seeded demo clock,
per-demo plan + renderer modules, WGSL shaders (simulate, nodes, edges,
path, birth particles, rescue, forgetting, firewall) plus a post-processing
chain (tone mapping, MIP). DOM is instrument overlays only (telemetry strip,
timeline spine, rescue verdict); the layout gives /observatory the same
full-bleed bypass as marketing routes so recordings stay clean.

Reads the real memory graph. Verified live: svelte-check 939 files 0 errors,
96 observatory unit tests green, all 5 demos load at 108-119fps with zero
console errors against the live brain.

Known follow-up: engram-birth capture-mode particle cluster needs a render
fix pass before it is camera-ready; the other 4 demos are camera-ready.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 10:49:18 -07:00
Sam Valladares
905933b0af fix(backend): resolve 10 bugs from the final full-codebase audit (#141)
A second adversarial audit of shipped main (post the 29+3 earlier fixes) found
10 more real bugs in areas the first pass under-covered (FTS sanitizer,
protocol/HTTP, connectors, frontend). None regressions — all pre-existing, and
several are "twin sites" of a class fixed elsewhere but missed here.

Majors:
- FTS5: sanitize_fts5_terms leaked bare operators on doubled input ("foo AND AND
  AND"), aborting MATCH with a syntax error or silently flipping AND->OR. Now
  filters operator tokens (repetition-proof).
- Server crash (DoS): unbounded MCP `hours_back`/`hours_forward` panicked via
  Duration::minutes in CaptureWindow; unclamped `limit` in match_context
  panicked via negative Vec::with_capacity / limit*2 overflow. Both now
  bounded/checked.
- Connectors: the source idempotency key omitted source_project, so two repos
  (or two Redmine instances) with overlapping ids clobbered each other's memory.
  Key + unique index (migration V19) now include source_project.

Minors/nits:
- list_memories now honors node_type/tag on the search path (were dropped).
- HTTP Accept honors */* and type wildcards (was hard 406 for curl et al.).
- Bearer scheme matched case-insensitively (RFC 7235).
- Dream insight time-span no longer seeds from now/-365d sentinels (fabricated a
  TemporalTrend for old clusters).
- WebSocket disconnect() detaches onclose before close() so it can't resurrect
  the socket via scheduleReconnect.
- Redmine thread truncation keeps the NEWEST journals (was keeping oldest, so
  new activity never re-indexed).

Tests: FTS operator-leak regression added. Full workspace green (1559 tests,
clippy -D warnings clean); dashboard check + 937 tests green.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 16:05:40 -05:00
Sam Valladares
898bd336cc fix(dashboard): wire duplicates/contradictions/patterns to real APIs, remove mock data
The /duplicates, /contradictions, and /patterns routes shipped hardcoded mock
data — and /duplicates rendered a "Live" badge over it. That is a launch
credibility risk: a visitor who spots the canned data distrusts every real
claim (including the CauseBench benchmark).

Replaces the three mocks (mockFetchDuplicates, MOCK_CONTRADICTIONS,
mockFetchCrossProject) with real dashboard HTTP endpoints backed by the existing
core capabilities:
- GET /api/duplicates            -> dedup cluster detection
- GET /api/contradictions        -> trust-weighted contradiction analysis
- GET /api/patterns/cross-project-> cross-project pattern transfer

Adds the handlers (dashboard/handlers.rs), route registrations (dashboard/mod.rs),
frontend api client methods + response types, and rewrites the three routes to
fetch live. The "Live" badge is now truthful.

Verified this session:
- cargo build -p vestige-mcp: compiles
- pnpm --filter @vestige/dashboard check: 905 files, 0 errors, 0 warnings
- live backend on a 1073-memory DB returns real rows from all three endpoints

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 15:44:46 -05:00
Sam Valladares
b380e36f1f release: v2.2.1 — Windows embeddings fix + backfill safety + first-run guide (#105)
* patch(backfill-safety): VESTIGE_BACKFILL_AUTOFIRE gate (default OFF) + bounded promote_memory_backfill

Off-by-default env gate around step-8.5 auto-fire in run_consolidation (decouples
backfill from consolidation cadence). New promote_memory_backfill caps stability at
MIN(stability*1.5, stability+365.0) (the bound retroactive_backfill.rs:300 already
computes but discarded); both backfill entry points use it. Fixes the false 'capped'
comment. Cloud-sync excluded at build (--no-default-features). Pending upstream PR to
samvallad33/vestige. omega-backfill-safety-v2.2.0 off tag v2.2.0 (3bcd4667).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* release: v2.2.1 — Windows embeddings fix + backfill safety + first-run guide

Board-clearing patch release.

Fixes:
- #101 Windows embeddings: release.yml already restores vector-search on the
  x86_64-pc-windows-msvc target (merged in #102); this release rebuilds the
  Windows binary so users actually get working embeddings.
- #103 Retroactive Salience Backfill safety (from community PR #104, adjusted):
  * promote_memory_backfill bounds the stability multiply to
    MIN(stability*1.5, stability+365.0) on both auto-fire and manual paths.
  * VESTIGE_BACKFILL_AUTOFIRE gate — default ON (preserves the shipped/documented
    v2.2.0 behavior), disable with 0/false/off/no. Env value is trimmed.
  * Corrected the false "capped" comment and the promote_memory_backfill doc.
  * Added 3 tests: +365 cap binds, *1.5 multiply below crossover, gate parsing.

Docs:
- #83 First-Run: new docs/GETTING-STARTED.md + README pointer.
- Consolidated roadmap issues #82,#84-#92 into docs/ROADMAP.md (Tracked Issues).
- Documented VESTIGE_BACKFILL_AUTOFIRE in docs/CONFIGURATION.md.
- CHANGELOG v2.2.1 entry.

Version bumped to 2.2.1 across all manifests + Cargo.lock + dashboard build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Peter Lauzon <inbijiburu@protonmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 12:02:42 -05:00
Sam Valladares
d4477976cb chore(release): v2.2.0 — Retroactive Salience + Tool Consolidation
Version bump 2.1.27 -> 2.2.0 across workspace crates + npm packages.

v2.2.0 = three coherent value streams:
- Retroactive Salience Backfill (Cai 2024 Nature) — memory with hindsight
- MCP Tool Consolidation (34 -> 13 advertised tools)
- deep_reference engine upgrades (F32 / RRF / claim-contradiction / band-gate)
  + recall/compose CLI
- security & correctness audit-swarm fixes

The Black Box / trace-receipt / cloud-sync / launch-UI bundle (PR #98) is a
separate coupled feature stream and ships as its own follow-up release.

Gates: 1550 tests pass, clippy -D warnings clean, dashboard check + build clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 15:15:54 -05:00
Sam Valladares
8f7bed0463 fix(blackbox): address review blockers B1–B7 + re-capture proof bundle
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>
2026-06-22 18:46:14 -05:00
Sam Valladares
b89beeeb63 proof(blackbox): Proof Lock — full-spine test, honest UI states, proof pack
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>
2026-06-22 17:41:02 -05:00
Sam Valladares
80c823a3ca feat(blackbox): Agent Black Box + Receipts + risk-gated Memory PRs
Watch the agent think. Watch memory change. Watch the receipt prove why.

Make Vestige the first memory server where you can replay an agent run,
audit every retrieval, and review changes to the agent's brain like code.

Phase 0 — the trace-correlation spine. One runId threads, unbroken, through
every layer: MCP tool output (runId + traceUri) -> SQLite agent_traces rows ->
WebSocket TraceEvent -> dashboard pulse -> /api/traces/:runId ->
vestige://trace/{runId} -> .vestige-trace.json export -> Cinema replay input.
Proven end to end by a real JSON-RPC round-trip integration test.

Core (vestige-core):
- trace/ module: MemoryTraceEvent (7 variants incl. contradiction.detected),
  Receipt, and classify_write — the pure, DB-free immune-system logic.
- Risk taxonomy: contradiction-vs-high-trust, supersede/forget/merge/protect,
  identity/preference/workflow/positioning, auth/security/money/legal,
  dream consolidation, decay resurrection, low-confidence batch, weak-provenance
  connector. Fast / Risk-Gated (default) / Paranoid modes.
- V18 migration: agent_traces, agent_runs, memory_receipts, memory_prs.
- trace_store.rs: CRUD following the established store idiom.

MCP (vestige-mcp):
- trace_recorder.rs: records mcp.call + downstream retrieve/suppress/write/
  contradiction/veto/dream events; builds + persists receipts; risk-gates
  writes into Memory PRs. Args are hashed, never stored raw.
- server.rs dispatch stamps runId/traceUri/receipt onto every tool result and
  routes risky writes to the PR queue; trace events broadcast over WebSocket.
- vestige://trace/{runId} resource; /api/traces, /api/receipts, /api/memory-prs.

Dashboard:
- Black Box tab: live spine header + Proof Mode, run picker, timeline scrubber,
  per-event detail, memory pulse, full event log, .vestige-trace.json export.
- Memory PRs tab: GitHub-style cognition diff, self-explaining risk signals,
  Promote/Merge/Supersede/Quarantine/Forget/Ask-Agent-Why, mode toggle.
- ReceiptCard with "Open receipt in Cinema" (deep-links graph; Cinema untouched).

Gates: 987 lib tests pass, clippy -D warnings clean, dashboard check + build
clean. Live proof in blackbox-proof-2026-06-22/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22 17:06:35 -05:00
Sam Valladares
9e92a5999a fix(cinema): back-pressure the frame loop — kill parallax lag
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>
2026-06-22 15:12:28 -05:00
Sam Valladares
5e948320a9 fix(cinema): lift brightness so the 4 depth systems don't stack to black
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>
2026-06-22 14:39:07 -05:00
Sam Valladares
4e3542eecb feat(cinema): flythrough streaks + interactive parallax (immersion steps 5+6/6)
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>
2026-06-22 14:35:32 -05:00
Sam Valladares
4a238a4893 feat(cinema): INFINITE DROSTE ZOOM (immersion step 4/6) — the spine
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>
2026-06-22 14:27:21 -05:00
Sam Valladares
85dacfad2b feat(cinema): depth-of-field defocus (immersion step 3b/6)
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>
2026-06-22 14:20:37 -05:00
Sam Valladares
3b342da9ea feat(cinema): volumetric fog depth (immersion step 3a/6)
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>
2026-06-22 14:12:05 -05:00
Sam Valladares
dad74d5aeb feat(cinema): near-plane fade (immersion step 2/6)
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>
2026-06-22 13:58:14 -05:00
Sam Valladares
d9fb791af6 refactor(cinema): canonical sprite center (positionNode = instancePos)
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>
2026-06-22 13:53:52 -05:00
Sam Valladares
12678596d5 feat(cinema): jarring inner/outer color clash — opposing palettes that fight
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>
2026-06-22 12:18:25 -05:00
Sam Valladares
4bdc5955f0 feat(cinema): impossible-geometry forms + 3D-within-3D nesting + demo capture
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>
2026-06-22 11:15:37 -05:00