返回 CodeWhale
DOT_WHALE_PET.md
根目录 / docs / design / DOT_WHALE_PET.md
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
130 lines MARKDOWN