Commit graph

75 commits

Author SHA1 Message Date
Admin
c042c06eba Arcade M5: multi-Claude co-editing — intent log, semantic rebase, soft leases
libs/game/coedit (zero deps, so merge logic is testable without a socket or
a VM). Not a CRDT: transactions are host-serialized into an append-only
generation history, and a conflict is answered by handing the author the new
base so THEY re-derive their intent.

- Transaction carries the author's whole intended file, not a patch: the
  diff against its declared base is derived host-side, so a stale or
  malformed patch can never be applied — and an AI writes whole files anyway
- diff3 over lines with LCS anchors. Merge::Conflict deliberately carries NO
  merged text: a half-merged game file that still parses is worse than an
  honest rejection. Conflict -> Rebase{new base + per-generation summary of
  what landed underneath}. An edit already present in the tip is refused as
  NoChange rather than appended as an empty generation
- Leases are advisory as designed: a test asserts a submit SUCCEEDS while
  another author holds the lease. They shape who chooses to edit; they never
  gate the log. TTL expiry means a crashed author cannot lock a region
- Wire: coedit is reliable-channel ONLY — a test signs a valid submission,
  sends it by datagram, and asserts it is ignored, so no datagram can
  rewrite the game. Every response is addressed, never broadcast
- Arcade bridge routes in exactly one place; local agent and remote authors
  share the queue and the rules, and a test asserts the local agent gets
  rebased identically when it loses a race. Remote players map to
  AuthorId(player+1) so a client holding player id 0 cannot impersonate the
  host's agent
- 200-round deterministic fuzz: 4 authors submit against deliberately stale
  bases, rebase, resubmit — asserting linear append-only numbering, no
  generation claiming a base from the future, and that replaying accepted
  diffs from generation 0 reproduces the head exactly

Two real bugs found building it: validate used `?` on the base lookup, so an
unknown base returned "no refusal" instead of UnknownBase; and
MAX_COEDIT_SOURCE (512 KiB) exceeded MAX_FRAME_BYTES (256 KiB), so the host
would have accepted a source it could never hand back inside a Rebase,
stranding the next author on an answer that never arrives. Both now 192 KiB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 02:45:31 +02:00
Admin
564c1b52dd Arcade M3 (part 1): MR/VR stage modes, XR input, settings panel, authoring inbox
Stage as presentation, never simulation. Stage{mode, origin, yaw, scale} is
applied as the scene draw list's view_transform uniform — one value per
frame, so sky/terrain/cubes/skinned characters all move together, cached
static slabs never invalidate (they hold stage-independent world transforms)
and per-instance cost is zero. The view matrix cannot carry this: in XR the
platform overwrites camera_view with the runtime's eye matrices every frame
(openxr_opengl.rs:20-25), discarding anything the app wrote.

- MrDiorama: world scaled onto an anchored slab, sky/fog/terrain-horizon
  suppressed (the room IS the environment), shadow-catcher quad so it looks
  planted. VrFullScale: 1:1, environment intact. Flat: unchanged
- stage_invariants.rs proves the design point: two worlds run 120 ticks, one
  switching flat->MR->VR->MR(new anchor)->flat mid-run, hashes bit-identical
  at every switch, with an assert_ne against a fresh world so the equality
  isn't vacuous. The stage has no API by which it could reach the world
- Stereo needed NO work, and rendering twice would have been wrong: XR uses
  single-pass GL_OVR_multiview2, so draw_pass.camera_view compiles to an
  indexed [VIEW_ID] lookup and the GPU rasterizes both eyes from one
  encoding. The existing draw path is already stereo-correct
- XR input maps controllers/pinch onto the same per-player InputState the
  net layer sends — an XR player is just another player to the sim
- Quest APK packages (arm64-v8a, passthrough/handtracking/anchor/colocation
  manifest bits) with no cargo_makepad changes
- Settings panel: provider/model pickers, masked key entry, pair button
  showing LAN URL + confirm code, active-tier status line
- Authoring inbox: keyless clients' Intent::Authoring queued for the host's
  agent, bounded and refusing with a reason — every entry eventually costs a
  paid call and it is filled by peers who hold the lobby key but are not
  trusted terminals

Pre-existing startup crash fixed: run_tick held a RefMut across
self.world.borrow() (`let _ = w` drops the reborrow, not the RefMut it came
from), aborting the demo path. Reproduced at HEAD with changes stashed.

Not wired, needs a device: passthrough is requested via
StageMode::wants_passthrough() but not handed to xr_passthrough (arcade has
no XR root widget yet); env-depth occlusion has a hook and no consumer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 02:32:22 +02:00
Admin
cec4f5b380 Arcade M4: voice + AI tiers, game library, /pair key flow, and libs/game/script
- libs/game/script (new): the table-driven game.* binding layer game.md
  called for — 71 verbs in a HashMap built once per isolate, replacing
  gamemaker's 84-arm linear chain. spawn_entity/spawn_terrain ported
  verbatim so fixture terrain matches bit-for-bit; generation-tagged
  callback slots; streaming eval + hot reload. Rollback snapshot is
  GameWorld::clone() — M1a made the world Clone, and a clone cannot forget
  a field, which is the exact bug class that put next_id in M0r's fix list.
  (Gamemaker still runs its own copy; migrating it is a follow-up.)
- Capability tiers: Voice (VAD + Whisper + local judge) -> VoiceUnfiltered
  (push-to-talk, every utterance costs a call) -> Chatbox (typing is the
  gate). Text box in every tier, mic only above Chatbox. The chain sits
  behind the local-llm feature so Quest/mobile never link a backend they
  don't have
- Librarian: the local model is an optional override (None = no opinion),
  never a gate — a flaky or absent model can only sharpen a decision.
  Beneath it, deterministic word-overlap matching for load-by-description,
  restart, and manifest-clamped knob writes. Creative requests deliberately
  do NOT match an existing game (tested). Locally-answerable utterances are
  dropped before they reach the cloud
- /pair: self-contained page (no external URLs, asserted), 4-digit confirm
  code so a room of headsets can't take the wrong key, 0600 config-dir
  storage documented as NOT a keystore — Android/iOS must move to the
  platform one before shipping. Key never enters a log, package, or error
- Racing fixture evals through the new dispatch (28 entities) and renders;
  hot-reload rollback verified live — a bad verb reports with a suggestion
  and keeps the last good world

Found (platform, unfixed — out of this task's scope):
HttpServerHeaders::from_tcp_stream buffers past the headers into a
BufReader, so a body arriving in the same TCP segment is swallowed and
handle_post blocks forever on a body that's already gone. Browsers split
the two, which is why nothing noticed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 02:05:50 +02:00
Admin
a8427cda75 Arcade M2b: multiplayer — players in the sim, tiered replication, host/join
A room of devices now plays one game: host simulates, clients send input
and render replicated truth.

- libs/game/sim/player.rs: Players roster on GameWorld, slot 0 is always
  this device. Player 0's input stays in the world's original held/pressed/
  pad/cam_yaw fields and is mirrored into the roster, which is what keeps
  single-player numerics bit-identical (tape gate confirms). Ids are never
  reused, so a stale reference resolves to None, never to somebody else
- The camera-movement knot resolved: world.player_move(p) rotates that
  player's axes by THEIR cam_yaw, carried in their input packet. Player 0's
  branch is the original expression character-for-character (the f32 cos
  widened to f64 kept deliberately — tidying it would move the numbers)
- libs/game/session/replication.rs: Shared = pos/vel/size/kind/tag;
  Derived = facing/anim/scale/glow/blob shadows, recomputed client-side and
  costing zero wire bytes; Local = camera/audio/effects. Statics never enter
  the per-tick stream
- Protocol (additive, version unchanged): EntityDesc + Descriptors message
  splits rare reliable construction data from volatile unreliable state —
  without it a joiner sees poses for entities it cannot build. EntityDesc
  carries pos because statics never appear in the state stream (the
  late-joiner test caught ground arriving at the origin)
- Script: game.players/player_name/player_entity/player_input/bot/on_join/
  on_leave; blocks gained owner: PlayerId so a car reads its own driver
- Arcade: ARCADE_HOST=1 / ARCADE_JOIN=<addr>; clients skip world
  construction and don't simulate
- Racing wire volume, 6 players x 60Hz x 200 entities: 2400 pps,
  20.9 Mbit/s up (audit projected 74 Mbit for the XR stack). Asserted in
  racing_scenario_wire_volume_fits_a_living_room

Two more not-a-playable-default bugs, same class as M1b's rng-at-zero:
Entity::default() leaves gravity_scale 0 (weightless wheels) and ground
without friction gives no traction — only the DSL path filled these in.

255 tests green; tape probe BYTE_IDENTICAL; xr/arcade/gamemaker build.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 01:21:44 +02:00
Admin
c13c867547 Arcade M1b: libs/game/blocks — car/character/plane, brains, race kit; racing game in 72 lines
The thesis proof: examples/gamemaker/resources/fixtures/racing.splash is a
complete playable racing game in 72 lines (12-corner oval from a waypoint
loop, 4 cars, gates, standings, restart) with no physics, no AI and no lap
bookkeeping in script. Blocks run engine-side at 60Hz: Blocks::pre_step
(intent -> motion) before step_world, post_step after; Blocks is Clone and
snapshots beside GameWorld so a failed eval rolls both back together.

- game.car (4 suspension raycasts on a box3d rigid chassis), game.character
  (drives the existing mover sweep + owns idle/walk/run blending),
  game.plane; game.drive/autodrive/speed
- Brains: game.wander/chase/patrol/caught — the fixture's hand-rolled AI,
  absorbed engine-side
- Race kit: spawnpoint, checkpoint, place, race, standings, lap/rank/
  finished, score/score_of (Shared-tier data, ready for replication)

raycast_vehicle audit (defects documented in car.rs, still live in xr):
libm sin/cos in steering (unreplicable), a wrong side-impulse denominator
(iaj.dot(iaj) where it should be (I^-1 aJ).aJ), and an unguarded division.
Kept the structure, replaced Bullet's friction solver with an arcade force
model: suspension acts at the contact point, grip and drive through the
centre of mass, steering as yaw torque — no lateral force can generate
roll, so it is stable by construction rather than by roll_influence fudge.

Engine bug fixed at the source: GameWorld::new() left rng at 0 and
xorshift64* is a fixed point at zero, so rand() returned 0 forever for any
world built through the sim API. reset_content seeds on every eval, which
hid it from gamemaker entirely; found by a wander brain that never left home.

Tape probe byte-identical; racing fixture evals clean and drives (AI follow
the line, gates bank in order).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 00:54:22 +02:00
Admin
17263b6666 Arcade M1a: box3d as the dynamics layer (hybrid — movers keep the parity sweep)
- libs/game/sim/dynamics.rs: box3d world inside GameWorld, body mirror
  RECONCILED against the sorted entity list per tick (merge-walk), so
  retain/rollback/reset are correct by construction. Statics + kinematics
  mirrored (kinematics via target transforms so resting rigids inherit
  platform velocity); smooth terrain as a box3d heightfield
- New BodyKind::Rigid + body:"rigid" with density/friction/restitution;
  game.push = mass-scaled impulse; set_pos/set_vel detected via bit-exact
  pose caches (no new dispatch arms). Sphere rigids roll on real spheres
- Entity.orient quat read back per tick; renderer builds quat instance
  transforms for rigids (no shader change). Step order: mover sweep
  verbatim -> reconcile -> world_step(dt, 4) -> readback; rigid-free
  worlds skip the solver
- GameWorld stays Clone via box3d snapshot round-trip (bit-identical
  continuation proven by test)
- Determinism: double-run equality + golden hash 0xa8a2baf71e4a564f
  (aarch64, debug and release). Perf: 0.038 ms/tick for 100 movers +
  50 rigids + 65x65 terrain (budget 2 ms)
- Tape probe BYTE_IDENTICAL; box3d crate untouched; arcade demo gains a
  kicked crate stack (captures verified: settles upright, then topples
  with rotated resting poses)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03 00:04:26 +02:00
Admin
ac5ed14285 Arcade M1c: skinned animated characters (glTF skins/clips, KayKit, CPU skinning)
- libs/game/render/skin.rs: GLB container + owned-JSON parser, dense
  accessors, multi-primitive skinned meshes, skin + inverse binds, full
  node-hierarchy palette, T/R/S clips (linear/step), nlerp blending.
  Hermetic tests via an in-code 2-joint GLB; real-asset test skips with a
  hint when the download hasn't run
- DrawGameSkinned shader (PbrVertex + albedo texture, terrain-style
  lighting); skinned batch draws between opaque and alpha passes.
  CPU skinning for now (sub-ms at 3716 verts): the uniform_buffer GPU path
  has zero in-tree runtime consumers — SkinnedModel::palette is the seam
  for the GPU swap
- apps/arcade: download_assets.sh (KayKit pinned commit + sha256,
  idempotent, dir gitignored, CC0 license note in-repo); Knight patrols
  the demo world with idle/walk blending, yaw follows path; captures
  verified (pose advances, depth-occludes correctly)
- renderer binary_search sites use the shared sorted-id helper from M0r

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 23:35:09 +02:00
Admin
7bb0c3be34 Arcade M0 stage B: rendering extracted to libs/game/render + arcade live viewport
- libs/game/render: the 5 game draw shaders (script_mod registration),
  shape geometry + winding test, terrain mesh, static-slab instancing,
  draw_scene pass (sky/terrain/opaque/alpha) as GameRenderer over GameDraws
  (draw structs stay #[live] on the host widget so script theming works),
  CameraRig + scene_state per-view (multi-view ready), HUD + billboard
  label drawing. game_view.rs 4640 -> 3599 lines
- apps/arcade: first engine-only viewport (arcade_view.rs) — GameWorld
  built via the sim API with no script VM, 60Hz tick, orbit camera,
  offscreen pass composite; ARCADE_CAPTURE=<png> GPU-capture test hook
- Verified: sandbox3d fixture evals clean headless; arcade demo frame
  GPU-captured and visually checked; suites green. Sim untouched — stage-A
  tape byte-parity (probe.txt identical vs pre-refactor binary) stands

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 22:56:22 +02:00
Admin
f2228a4654 Arcade M0 stage A: gamemaker sim extracted to libs/game/sim + deterministic math + apps/arcade shell
- libs/game/math: cross-arch bit-deterministic f32 kernel (f64-internal
  fdlibm-style polynomial kernels, exactly-rounded IEEE ops only, zero
  platform-libm transcendentals). Parity golden hashes recorded on aarch64;
  equal hashes on every other target IS the determinism test
- libs/game/sim: the gamemaker world moved verbatim (entity/terrain/world/
  queries/step — float expression order preserved so tapes replay
  bit-identically). No Cx, no draw types, no ScriptObjectRef: script
  callbacks are CallbackSlots resolved through a generation-tagged
  host-side CallbackTable in game_view.rs; sim reset no longer touches audio
- examples/gamemaker: game_view.rs 5545 -> 4640 lines (script boundary,
  rendering, input devices, host I/O remain); per-tick args/input objects
  built via unchecked pushes + release_transient (flat-heap tick path)
- apps/arcade: Makepad Arcade app shell + workspace membership
- Verified: headless sandbox3d fixture (90 entities) boots end-to-end;
  gamemaker/sim/math/script-test suites green

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 22:28:06 +02:00
Admin
f4af4db88d Map: growing-archive watcher — the app reloads as the world spiral weaves cells in
5s mtime watch on the active archive (root.mkidx for mkmap); on change,
Failed placeholders clear and the visible loop re-requests. Workers
already reopen per batch, so an atomic shard-set swap appears live —
apps/route now points at world.mkmap and starts empty until cell-001
(NL) lands.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:44 +02:00
Admin
c073c08596 Revert to known-good: pass batching opt-in (MAKEPAD_BATCH_PASSES=1), AI loading opt-in (MAKEPAD_AI=1)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:43 +02:00
Admin
c59fe0b0eb Metal: frame-batched command buffer for offscreen passes + big benchmark window
Texture-mode passes append to one retained command buffer flushed at the
window pass (safety flush at repaint start for texture-only frames) —
the 12-pass gauss pyramid paid ~1ms commit/schedule latency PER PASS.
Profiling mode (MAKEPAD_GPU_PROFILE) keeps per-pass buffers so spans
stay attributable. Startup window 3400x2050 for pixel-heavy iteration.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:43 +02:00
Admin
768fc340a7 route: NL-first iteration — app reads nl-kf-test 4-keyframe cut (15-18 + shadows)
Europe re-cut with these buckets happens on explicit go; the NL cut
lives in local/maps (untracked) for cross-session stability.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:43 +02:00
Admin
627f0bb04b Map: app reads .mkmap shards — MkmapReader + TileArchiveReader, varint-KV index v2
libs/mbtile_reader gains the .mkmap consumer: root.mkidx parse (Hilbert
tile ids, root ranges -> brotli leaf directories -> shard/offset/len),
positioned shard reads, same get_metadata/get_tile_decoded surface as
MbtilesReader; TileArchiveReader sniffs the path so mbtiles_path can
point at either. Index format v2 drops JSON: the metadata section is now
varint KV like the leaves (writer + reader; no serde in the container).
Loader, zoom-range probe and the headless harness go through the enum;
bridge-dz/overlay sidecars stay mbtiles. Harness parity via shards:
worst AMS rz16 164.7ms, z12 native 51.3ms — identical to mbtiles. App
repointed to local/maps/europe-base-br.mkmap (111 shards + root.mkidx,
the exact bytes a CDN would serve).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:42 +02:00
Admin
9b4d871075 Map: repoint app to europe-base-br-v2 (theme-independent final cut) + pipeline script
Final cut: 9.38M tiles, 133,431 baked (9.6GB streams, zooms 10-14,
threshold 100ms), 107 shards under cap, 253,525 sampled byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:42 +02:00
Admin
fce6c68835 Map: repoint app to europe-base-br-faces-mz (mid-zoom baked) + midzoom pipeline script
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:42 +02:00
Admin
80d5967198 Map: Europe single-origin archive shipped — 51.8GB base + faces bake + .mkmap shards
Overnight run 2026-08-01: 9,380,390 tiles z2-14 in 3.2h, faces bake 1h
(+8GB, worker-side brotli q10), transmux to 99 shards all <510MB.
App repointed to europe-base-br-faces.mbtiles. nl-bridge-dz verified
byte-identical against the new base (deterministic feature indices).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:42 +02:00
Admin
9bddc458b9 Map: painter-cascade per-bucket bake (v2-faces-1) + z14 streets merge
- The boolean union cascade (59-77% of heavy tile builds) is now baked
  per (tile, bucket 14/15/16) as additive field 101: cascade output made
  deterministic (1/64 grid snap, canonical ring order, sorted tiers) and
  bit-reproducible; renderer consumes guarded by structure signature +
  coordinate checksum with runtime fallback; MAKEPAD_NO_BAKED_FACES=1.
  Roundtrip bit-identical on all keys x buckets x dz configs. New
  tools/map_bake producer (worker-pool incl. worker-side brotli).
- z14 streets merging never ran (early-out at DETAIL_ZOOM): fixed —
  1957->1285 ways (-34%), payload -20MB, cascade input shrunk at source.
- Slow-tile log now prints per-stage ms + a ready-to-paste headless repro
  command; harness honors archive/detail/dz/overlay/rz/3D envs.
- Worst AMS tile: 2-3s cold -> 175ms rz16 (61ms native); NL bake data
  882MB at 60ms threshold; Europe needs threshold 150ms + 2 buckets to
  fit shard budget (+2-4GB est).
- App -> nl-base-br3-faces archive; bridge-dz rebake required (joins
  fail closed against br3 feature indices).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:42 +02:00
Admin
7ad23460ea Route: user override interrupts the dispatcher; break tool loops
- Voice override ("ok nevermind / stop / wait, do X") and ANY typed
  prompt now cancel the in-flight local turn (cancel_prompt -> per-token
  stop; worker closes the assistant turn and drops its pending tool
  calls). Bare "stop"/"nevermind" just halts + silences TTS; otherwise
  the new command is sent immediately. Queueing remains for non-override
  follow-ups.
- Greedy-decoding tool loops (identical geo_search spam): an identical
  repeated call or >10 tool rounds per prompt gets a corrective error
  result instead of execution ("answer with what you have").
- geo_search rejects degenerate queries (>64 chars / >8 words) that
  crawl the fuzzy index.
- Append-only context has no recovery once full: at >90% usage after a
  turn, the local session restarts fresh (cheap with mmap weights);
  transcript stays, conversational memory resets.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:41 +02:00
Admin
053b1a9d15 Audio: constant gentle ducking beats half-duplex unit swapping
The mid-stream VPIO<->plain unit swap glitched the start of the
assistant's own speech; keep the voice-processing unit armed for the
whole capture (standard+Min ducking) instead. set_echo_cancellation and
the options-rebuild plumbing stay for apps that want the trade.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:41 +02:00
Admin
419d77c652 Audio: half-duplex echo control — duck only while the assistant speaks
Idle listening now runs PLAIN capture (no VPIO, zero ducking — music
untouched); the app arms the voice-processing unit only while its own
TTS is audibly playing (+0.8s tail), which is the only window where echo
cancellation matters. Options changes rebuild running input units
(AudioUnitAccess.last_input_options); WindowVoiceInput/VoiceWave gain
set_echo_cancellation; route app polls speech playback at 4Hz.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-02 17:48:41 +02:00
Admin
1afcedd8f6 NL-wide bridge-dz overlay + mbtiles-merge; fix VoiceInput unit handling
- bridge-dz baked for the entire Netherlands (17026 tiles, 29MB):
  AHN-refined over the 8 Amsterdam sheet pairs, solver-only elsewhere.
  Baked as 4 north-south strips with 2-tile overlap — the full-bbox
  global solve peaked past 60GB RSS — merged with the new mbtiles-merge
  subcommand (later input wins on overlaps, block-major write order).
  Route app bridge_dz path ams -> nl.
- audio_unit: the new VoiceInput (VoiceProcessingIO) kind takes the input
  setup/handler paths (set_input_handler panicked and aborted the app);
  VPIO capture forced mono on every platform.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:38:48 +02:00
Admin
723b7928bb Route assistant: mmap LLM weights, fix batched-attention corruption, kokoro voice out
- ggml: read-only mmap module (unix-gated) + two-region Context (mapped
  weights / dirty caches) + segmented Metal buffer binding; llama loads
  GGUF weights as file-backed clean pages (jetsam-exempt) with owned-arena
  fallback (MAKEPAD_LLAMA_NO_MMAP=1). Route app dirty footprint 12GB -> 4-7GB;
  model load becomes lazy page-in; A/B byte-identical on 4B + 9B.
- llama: fix graph-cache keying corruption — a graph keyed wider than the
  KV cache corrupted attention for any prefill batch >= 2 (flash op reads
  permute-node dims baked at build; view reconfigure never reached the
  kernel; masks were written cache-narrow). Masks now always fill the full
  graph key width and graphs key by 1024-buckets; reconfigure path removed.
  Verified byte-exact vs per-length reference across batch 1/2/8/64/512,
  short+long prompts, mmap on/off, plus a two-session concurrency probe.
- voice: passive VoiceWaves no longer register the global audio-input
  callback (the invisible caption-bar wave stole mic audio — last
  registrant wins — and spawned duplicate whisper workers); whisper back
  to F16 default (voice Metal library has no quantized kernels; q5_0
  failed every GPU matmul); raw transcripts render immediately.
- route: kokoro TTS voice output (speaker toggle; streams reply sentences,
  announces nav maneuvers + arrival) with barge-in — voice activity on the
  mic stops playback instantly; dispatcher context 8k -> 32k (hybrid KV is
  12/48 layers, ~48KB/token); window caption bar suppressed under studio.
- llama-generate: --max-context/--prefill-batch-size + state fingerprints;
  new llama_concurrent_probe bin.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 12:13:31 +02:00
Admin
676255dfc2 Land route app + platform geo/permission APIs, map nav layer, geodata radar
apps/route: AI trip planner on MapView — tool broker + local/cloud agent
dispatch, nav session + simulated drive, layers/theme state, DDG image
search, trip history, tilt-shift DOF layer (linear circle-of-confusion:
level = log2 of radius, constant growth rate, tilt raises only the
ceiling; tilt-shift on by default).

Platform: Cx geo location API (macOS/iOS/Android/web) + permission
plumbing, memory watchdog, headless build cfg. Map: nav layer M0 API,
landcover drape, bridge dz. Geodata: 250m dual-radar compositor
(radar_volume) + KNMI sync. Docs for the route/glass/blur/shiny work.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 00:10:52 +02:00
Admin
ff4e3183c1 Add apps/route AI trip planner M0 skeleton to workspace
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-31 00:10:52 +02:00