Skip to content

Claude/review work allocation f32 sl#11

Merged
hyperpolymath merged 4 commits into
mainfrom
claude/review-work-allocation-F32Sl
Apr 19, 2026
Merged

Claude/review work allocation f32 sl#11
hyperpolymath merged 4 commits into
mainfrom
claude/review-work-allocation-F32Sl

Conversation

@hyperpolymath
Copy link
Copy Markdown
Owner

Summary

Changes

RSR Quality Checklist

Required

  • Tests pass (just test or equivalent)
  • Code is formatted (just fmt or equivalent)
  • Linter is clean (no new warnings or errors)
  • No banned language patterns (no TypeScript, no npm/bun, no Go/Python)
  • No unsafe blocks without // SAFETY: comments
  • No banned functions (believe_me, unsafeCoerce, Obj.magic, Admitted, sorry)
  • SPDX license headers present on all new/modified source files
  • No secrets, credentials, or .env files included

As Applicable

  • .machine_readable/STATE.a2ml updated (if project state changed)
  • .machine_readable/ECOSYSTEM.a2ml updated (if integrations changed)
  • .machine_readable/META.a2ml updated (if architectural decisions changed)
  • Documentation updated for user-facing changes
  • TOPOLOGY.md updated (if architecture changed)
  • CHANGELOG or release notes updated
  • New dependencies reviewed for license compatibility (PMPL-1.0-or-later / MPL-2.0)
  • ABI/FFI changes validated (src/interface/abi/ and src/interface/ffi/ consistent)

Testing

Screenshots

claude and others added 4 commits April 16, 2026 13:43
…cate Relay.res

Prerequisite cleanup for the audio-first phased plan
(see STATE.a2ml [route-to-mvp]). Every change in this commit is either
a deletion of already-broken/duplicate/orphan files, a doc
realignment to match actual code, or a test-assertion flip toward
safety behaviour that the source code already provides.

Removed
  api/v/                          V-lang REST client (language banned estate-wide)
  api/zig/                        broken merge-conflict-ridden half-migration
                                  duplicate of ffi/zig/ (8 =======  markers in burble.zig,
                                  Zig 0.13 API in build.zig — did not compile)
  signaling/Relay.res             ReScript duplicate of authoritative relay.js
  alloyiser.toml                  orphaned Alloy spec pointing at deleted api/v/burble.v
  generated/alloyiser/            generated output of the above

  (15 files, -4,314 LOC)

Contractile + manifest updates
  .machine_readable/MUST.contractile
    project-invariants populated (previously a *REMINDER placeholder):
      - ban new .v files (V-lang)
      - ban new .res/.resi files (ReScript)
      - no api/ directory — FFI lives at ffi/zig/
      - single signaling relay (signaling/relay.js)
      - stub NIFs must return {:error, :not_implemented}
      - Burble.LLM.process_query must not return simulated strings in prod
      - STATE.a2ml test count must match reality within ±5
      - ROADMAP.adoc completion claims must match STATE.a2ml
  0-AI-MANIFEST.a2ml
    abstract + invariants reflect Zig-FFI / AffineScript-target reality;
    old `rescript-web-client = "NOT TypeScript"` invariant replaced with
    `affinescript-client` (migration-in-progress) and explicit `no-v-lang`.
  .machine_readable/6a2/STATE.a2ml
    completion-percentage 85 → 72 with rationale (LLM, PTP HW,
    Avow attestation, Opus server NIF are stubs contradicting earlier
    "done" claims). Added [migration] section tracking V-removal (done)
    and ReScript-removal (pending Phase 3/5). Added phased roadmap
    (Phase 0 complete; Phases 1–5 enumerated) and honest
    [blockers-and-issues] listing doc/reality drift.
  BURBLE-PROOF-STATUS.md
    collapsed from 315 lines to ~40 — removed stale "Compilation
    Needs Attention / module name mismatches" section (src/ABI.idr
    compiles). Points at PROOF-NEEDS.md + STATE.a2ml and honestly
    flags the runtime-enforcement gaps (Avow stub, no LLM.idr,
    no Timing.idr).
  TOPOLOGY.md
    module-map rewritten: removed api/ and signaling/Relay.res;
    annotated which subtrees are stubs vs production; noted client/
    web/lib migration target. Added explicit "Removed 2026-04-16"
    block at the bottom.

Tests
  server/test/burble/e2e/signaling_test.exs
    RoomChannel catch-all handle_in + handle_info for
    :participant_joined/:left landed 2026-04-09 (commit 167d46d),
    but the test suite still had two @tag :known_gap tests asserting
    the OLD crash behaviour. Flipped them to safety-contract
    regression guards: 6 tests in a new "Channel safety contract"
    describe block verify structured-error replies, no EXIT signals,
    and channel liveness after malformed input. Removed the stale
    "Known channel gaps" comment block at top of file.

Build / test verification
  not run in this session — no toolchain (just/mix/zig) available in
  the execution sandbox. All edits are syntactically conservative:
  doc/a2ml/scheme text, test-assertion flips, and git rm of files
  already dead. Please run `just test` locally to confirm.

Refs Phase 0 of the review plan in STATE.a2ml [route-to-mvp].
https://claude.ai/code/session_01VqoQXyDhJfFUGepiKr6P8H
…, not transcoding

Phase 1 item 1 of the audio-first plan.

The Backend behaviour's audio_encode/4 + audio_decode/3 docstrings claimed
Opus encode/decode. The actual implementation is a length-prefixed i16 LE
frame packer — no compression, bitrate parameter ignored. Burble is an
E2EE-opaque SFU (clients Opus-encode in the browser's WebRTC stack; the
server forwards ciphertext without decoding), so server-side real Opus
was never going to happen in this layer. But the mislabelling meant
callers who asked for real Opus got a silent round-trip of raw PCM
instead of a loud failure.

Changes in this commit make the contract honest and enforceable:

Backend behaviour (server/lib/burble/coprocessor/backend.ex)
  - audio_encode/4 docstring rewritten: 'Pack raw PCM samples into a
    length-prefixed binary frame. THIS IS NOT OPUS ENCODING.' Explains
    the SFU-opaque rationale and that bitrate is ignored.
  - audio_decode/3 docstring rewritten to match.
  - Kernel-domain comment updated: 'Audio — PCM frame pack/unpack (NOT
    Opus transcoding)'.
  - New callback opus_transcode/4 — explicit entry point for real Opus.
    All backends return {:error, :not_implemented}. Callers wanting real
    Opus must either use the browser's WebRTC Opus encoder or request
    libopus integration (deferred — STATE.a2ml [migration]).
  - New callback opus_available?/0 — always false until libopus is linked.

Backend implementations
  - ElixirBackend: opus_transcode returns :not_implemented; audio_encode
    inline comment clarifies it's framing, not compression.
  - ZigBackend: opus_transcode returns :not_implemented.
  - SmartBackend: delegates opus_transcode to the underlying backend.
  - SNIFBackend: delegates to ZigBackend.

Zig kernel (ffi/zig/src/coprocessor/audio.zig)
  - File header comment expanded: 'PCM frame pack/unpack — NOT Opus
    compression. Real Opus transcoding requires linking libopus and is
    deferred'. Cross-references STATE.a2ml [migration] + the
    opus_transcode/4 callback.

Regression test (server/test/burble/coprocessor/opus_contract_test.exs)
  - Six tests pinning the contract:
    * opus_transcode returns :not_implemented on all 3 backends
    * opus_available? is false on all 3 backends
    * audio_encode -> audio_decode round-trips raw PCM within i16
      quantisation error (proves no lossy Opus is running)
    * bitrate parameter is provably ignored (low/high-bitrate frames
      are byte-identical)
    * frame format is stable (1-byte channels + 4-byte LE len + i16 LE
      PCM body)

STATE.a2ml
  - Moved the 'nif_audio_encode/decode are not real Opus (misleadingly
    named)' entry from [blockers-and-issues] to [resolved-2026-04-16].

Build / test verification: not run in this sandbox (no mix/zig).
Please run `just test` locally.

Refs Phase 1 item 1 in STATE.a2ml [route-to-mvp]. Next: decide on
client-side noise gate strategy (Phase 1 item 7) before committing it.

https://claude.ai/code/session_01VqoQXyDhJfFUGepiKr6P8H
…ude-to-Claude

This repairs the critical-path channel for the family/pair-programming use
case: two people running p2p-voice.html with a local Deno bridge each, and
Claude Code instances on both sides exchanging JSON over the WebRTC
DataChannel. The send direction already worked; the receive direction was
silently broken.

Root cause (the receive-leg bug)
--------------------------------
client/web/p2p-voice.html defined two AI-channel setup functions:
  setupAIChannel(ch)            — wires UI log + window.burble.onMessage
  setupAIChannelWithBridge(ch)  — was meant to do the above PLUS forward
                                  received DataChannel messages to the
                                  local Deno bridge via the bridge WS.
The wrapper was defined but NEVER CALLED. Both the pc.ondatachannel
handler (joiner side) and createAIDataChannel() (creator side) invoked
setupAIChannel — so remote DataChannel messages updated the on-page log
but were never forwarded to the bridge. Result:
  curl http://localhost:6474/recv  →  always empty
The send direction (curl POST /send → bridge → WS → page → DataChannel)
was unaffected.

Fix: inline the bridge-forward into setupAIChannel; delete the dead wrapper
and originalSetupAIChannel reference. No caller can pick the wrong variant
now because there is only one.

Other hardening
---------------
burble-ai-bridge.js
  * BURBLE_AI_BRIDGE_PORT env var — allows two bridges on one host for
    tests (HTTP + WS ports shift together: 6474/6475 default).
  * wsClient is assigned IMMEDIATELY after Deno.upgradeWebSocket rather
    than inside socket.onopen. Under Deno 2.x upgraded sockets are often
    already in readyState=1 by the time you return the Response, so
    `open` may never fire and wsClient would stay null indefinitely.
  * Heartbeat: bridge sends {type:"ping"} every 15 s and closes the
    socket if no pong arrives within 5 s. This detects silent drops
    (laptop sleep, wifi change) that otherwise leave a stale readyState.
  * Proper teardown: onclose clears the heartbeat and pong timers, and
    only nulls wsClient if the closing socket is still the active one.

p2p-voice.html
  * Bridge status indicator in the AI Channel card header: green dot
    "bridge online", amber "bridge connecting…", grey "bridge offline".
    No more guessing whether the local Claude is reachable.
  * setBridgeStatus() is called on WS open / close / error.
  * Respond to bridge heartbeat pings with {type:"pong", ts:Date.now()}.
  * window.burble exposes new helper: bridgeConnected() → boolean.

Tests
-----
client/web/tests/ai_bridge_roundtrip_test.js — new file, three tests:
  1. A → B round-trip: POST /send on bridge A → GET /recv on bridge B,
     via two mock pages cross-wired to simulate the DataChannel.
     Assertion fails if the receive-leg bug returns.
  2. B → A (reverse direction) same assertion.
  3. Heartbeat: page replies to ping, socket stays connected over 2 s.

Uses BURBLE_AI_BRIDGE_PORT=7474/7484 so the suite coexists with a normal
bridge on 6474. Each test spawns fresh Deno subprocesses so the ports
don't leak between tests.

Docs / state
------------
CLAUDE.md
  * Start-order clarified: bridge FIRST, then page (so the page's
    auto-retry picks up the WS relay immediately).
  * New troubleshooting section covering `/send` 503, empty `/recv`,
    grey bridge dot, and the BURBLE_AI_BRIDGE_PORT trick.

STATE.a2ml
  * Split the phased plan: Phase 2 is now the P2P AI bridge (CRITICAL
    path for the family use case); Phase 2b is the server-side
    Burble.LLM provider work (secondary, not required for
    father/son pair-programming).
  * [critical-next-actions]: five bridge items marked DONE this commit;
    NEXT items sharpen to ordering/reconnect tests and protocol docs.
  * phase-1-audio: Opus item marked DONE (from commit 179fa34).

Verification: not run in this sandbox (no deno/mix/zig available).
Please run:
  deno test --allow-net --allow-env --allow-run client/web/tests/

https://claude.ai/code/session_01VqoQXyDhJfFUGepiKr6P8H
@hyperpolymath hyperpolymath merged commit 7d1b5bb into main Apr 19, 2026
15 of 18 checks passed
@hyperpolymath hyperpolymath deleted the claude/review-work-allocation-F32Sl branch April 19, 2026 22:22
hyperpolymath added a commit that referenced this pull request May 13, 2026
Implements task #11 in the ADR-0003 roadmap (NAPTR + SRV at jewell.nexus
for Burble Bolt discovery).

- scripts/cf-bolt-dns.sh — idempotent Cloudflare API provisioner for the
  two records  looks for. Looks up the zone,
  upserts records (no duplicates on re-run), supports DRY_RUN=1 for safe
  preview without an API token.
- docs/developer/bolt-dns-records.adoc — developer reference: the record
  shapes, why CNAME  indirection, dashboard fallback
  instructions, verification steps (dig + Resolve-DnsName).

Records published by the script:

  jewell.nexus.                   IN NAPTR 10 1 "U" "BURBLE+bolt" \
                                    "!.*!bolt://bolt.jewell.nexus:7373!" .
  _burble._bolt._udp.jewell.nexus. IN SRV 10 1 7373 bolt.jewell.nexus.

Deployment is gated on a Cloudflare API token with Zone:Zone:Read +
Zone:DNS:Edit on jewell.nexus; script exits cleanly without it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants