| 1 | # Dot-whale habitat and Watch |
| 2 | |
| 3 | The underwater transcript uses the portable 980-point whale for its completion |
| 4 | visitor. The whale is the home form of a persistent field of dots. Version 2 |
| 5 | reorganizes those dots into reasoning knots, woven code, filesystem branches, |
| 6 | browser layers, circulating traffic and open decision junctions. Original |
| 7 | recordings retain version 1 behavior; new habitats use version 2. This slice |
| 8 | replaces the old `≈≈>` / spray / fluke glyph sequence. The explicit Watch panel |
| 9 | adds foreground telemetry through the same world and score used by native and |
| 10 | web hosts, with opt-in stereo PCM output through FFmpeg's `ffplay`. |
| 11 | |
| 12 | ## Ownership |
| 13 | |
| 14 | - `crates/tui/src/tui/ambient_life/pet_sim.rs` owns the dependency-free Rust port |
| 15 | of the TypeScript reference core, with typed `ChannelId` and `Archetype`. |
| 16 | - `whale-points.tsv` is the embedded authored body. `PetSim::whale()` constructs |
| 17 | it using the existing `mulberry32(0xC0FFEE)` particle stream. |
| 18 | - `pet_widget.rs` owns particle-to-braille rendering. The portable Rust runner |
| 19 | and ratatui demo use these same product files, rather than maintaining copies. |
| 20 | - `pet_cameo.rs` is the completion presentation inside the existing habitat. |
| 21 | It consumes `WhaleCameo` and `AmbientActivity`; it never reads a wall clock, |
| 22 | schedules a frame, or classifies model/tool text. |
| 23 | |
| 24 | ## Completion is a bounded observation |
| 25 | |
| 26 | A completion does not identify which Whalesong category was last active. The |
| 27 | single visitor therefore uses `other · drift`, with observed coverage. Existing |
| 28 | `AmbientActivity::Subagents` presents three fixed, staggered peer slots, each |
| 29 | labelled `agent · pod`. At rest the three peers remain three animals; the core's |
| 30 | six-satellite working gait is not multiplied into eighteen animals. |
| 31 | |
| 32 | The complete creature and its caption are preflighted against `is_open_water`. |
| 33 | A text collision with either withholds the entire creature. Off-screen peers |
| 34 | are withheld instead of clamping them into an overlapping stack. On a 40-column |
| 35 | surface the middle peer remains visible. Content always owns its cells. |
| 36 | |
| 37 | The core is stepped at fixed 30 Hz into two bounded raster caches. A frame is |
| 38 | selected solely from the supplied completion age, so skipped draws, rewind, |
| 39 | resizes, and rendering another session do not alter its pose. There are no new |
| 40 | random choices. The existing theme supplies the habitat ink; the cameo adds no |
| 41 | status-bar colour meaning and never spends Failure red. |
| 42 | |
| 43 | The shell already owns an 800 ms completion light pulse and a 600 ms life fade. |
| 44 | It now passes the motion-gated clock through that full 1.4-second interval. The |
| 45 | ocean still clips its light pulse at 800 ms. The low-level cameo retains the |
| 46 | 2.4-second safety limit from its predecessor; the shell's life fade ends first. |
| 47 | Reduced motion exits before constructing marks or initializing the caches. |
| 48 | |
| 49 | The generic widget retains the core's unknown rendering and the literal |
| 50 | `· unobserved` cue. If the whole cue cannot fit, it withholds the whole widget. |
| 51 | Sleep dimming does not set unknown coverage. |
| 52 | |
| 53 | ## Evidence boundaries |
| 54 | |
| 55 | ### `/pet` habitat |
| 56 | |
| 57 | `/pet` (or `/pet on`) opens the full habitat over the existing shell. The pet |
| 58 | has no workbar panel: no dock cycling, tab, placement or dismissal applies. The |
| 59 | tank uses the whole content viewport and never overlays transcript cells; narrow |
| 60 | views keep the text cue. Opening it starts a read-only observer; it does not start an Engine |
| 61 | turn or silently substitute demonstration data. It begins with unknown coverage |
| 62 | and does not backfill events from before attachment. |
| 63 | |
| 64 | `ui/event_loop.rs` passes accepted foreground Engine events through the existing |
| 65 | `core::protocol_parity::event_to_protocol` projection. The pet allowlist keeps |
| 66 | only lifecycle kind, stable ids, tool names, channel and outcome. Prompt text, |
| 67 | reasoning, arguments, results, paths and routing credentials never enter the |
| 68 | worker queue or pet tape. No session context or KV-cache prefix is changed. |
| 69 | |
| 70 | The generated `pet_watch/pet-native.js` comes from the canonical source in `pet/src/core`: |
| 71 | |
| 72 | ```sh |
| 73 | npm --prefix pet ci --ignore-scripts |
| 74 | npm --prefix pet run sync |
| 75 | ``` |
| 76 | |
| 77 | The Engine adapter emits normalized event-v1 observations, then uses the existing |
| 78 | `compilePetTelemetry` function. A sealed 400 ms observation bucket appears at |
| 79 | the next world boundary; the world's accepted tape remains the replay authority. |
| 80 | Liveness pulses do not count as repeated tool calls. Silence does not stretch |
| 81 | occupancy across gaps. Error receipts create a current onset, rather than moving |
| 82 | a failure back to the operation's start. Typed `ShellPhase::Waiting/Approval` |
| 83 | can extend an already witnessed human request, preserving the outstanding request without approach-to-owner steering. |
| 84 | |
| 85 | The presentation companion now owns the one persistent world. Terminal Watch, |
| 86 | full-screen habitat, browser, macOS window, Apple Shared and Android Shared |
| 87 | attach to its authenticated loopback snapshots. View interpolation and stillness |
| 88 | never advance or modify the world. The existing Ratatui draw loop owns pixel |
| 89 | placement and cleanup; a successful Kitty query selects pixels, otherwise the |
| 90 | view uses braille. Full habitat focus uses the existing modal stack. |
| 91 | |
| 92 | The complete ownership, source selection, storage/reconnect, graphics, audio, |
| 93 | legacy habitat and mobile contracts live in [pet/SHARED.md](../../pet/SHARED.md). |
| 94 | That document supersedes the former per-session Watch worker and app-local |
| 95 | live-world ownership. Completion cameos remain bounded transcript decorations. |
| 96 | |
| 97 | The live Runtime SSE adapter and this foreground protocol adapter consume |
| 98 | different existing input contracts; they share event-v1 projection semantics, |
| 99 | the bucketer, world and score. The Runtime stream now has opt-in progress frames |
| 100 | at its own journal cursor. The standalone file recorder waits for durable replay and queued |
| 101 | live delivery to finish before extending any request as current. These frames |
| 102 | are transport metadata; they do not enter the event journal or pet tape. |
| 103 | The Runtime importer separately pairs request |
| 104 | lifecycles and preserves failure receipt times. Its local SSE/CLI and browser |
| 105 | fixtures pass. Typed synthetic Engine events have also passed through the actual |
| 106 | Runtime journal/SSE endpoint, recorder process and Apple file watcher/PetHost: |
| 107 | a fresh request appeared at 1,233 ms and cleared after its answer at 2,000 ms. |
| 108 | That provider-free fixture proves active native file delivery; physical-phone |
| 109 | transport and visual popover inspection are separate evidence. The source and |
| 110 | liveness contracts are documented in `pet/README.md`. |
| 111 | |
| 112 | Earlier phase evidence: the full TUI binary built offline, its foreground metadata projection test |
| 113 | passes, and the real PTY walkthrough covers Watch selection, keyboard, mouse |
| 114 | and resizing down to 40x12. Receipts and source hashes are in |
| 115 | `CW/artifacts/pet-review-20260912/`. Hosted macOS testing on the initial branch ran 15,418 tests with one Watch-tab |
| 116 | golden mismatch; its header is corrected in the transformation update. The |
| 117 | subsequent `e69e99b` passed the applicable Linux, macOS and Windows product tests, |
| 118 | lint and security checks. Later changes require their own hosted verdict. |
| 119 | |
| 120 | Local render fixtures exercise the actual ocean, glyph and ambient-life modules |
| 121 | with literal shell enums extracted from `underwater.rs`; they do not run an |
| 122 | Engine session. The portable conformance runner compares TypeScript, Rust and |
| 123 | Swift across the original tape and an additional all-channel/error-burst/sleep |
| 124 | tape, each with motion enabled and disabled. A missing tool or failed widget |
| 125 | build now fails that runner instead of printing a false success. |
| 126 | |
| 127 | Full product builds, real session acceptance, packaged applications, audio, |
| 128 | mobile builds and hosted CI remain separate proof requirements. The local |
| 129 | fixture and conformance checks do not establish those outcomes. |
| 130 |