返回 CodeWhale
SHARED.md
根目录 / pet / SHARED.md
1 # One pet, attached views
2
3 `codewhale-tui pet serve` owns the local pet independently of every window.
4 Watch starts it when needed. The native macOS package can start its bundled
5 owner as well. Closing a view releases its connection; the companion keeps the
6 identity, clock, particle field and recording. It contains no agent turn loop,
7 prompts, provider calls or second telemetry classifier.
8
9 ```mermaid
10 flowchart LR
11 E[Existing Engine: accepted metadata] --> T[Terminal projection]
12 T --> O[Local companion: one PetNative world]
13 O --> S[Private checkpoint and immutable archives]
14 O --> W[Ratatui Watch / full habitat]
15 O --> B[Browser view]
16 O --> N[Native companion / mobile view]
17 O --> A[One optional audio device]
18 W & B & N -->|ordered interactions| O
19 ```
20
21 ## Try it
22
23 From the repository root, build the existing product binary and native view:
24
25 ```sh
26 npm --prefix pet ci --ignore-scripts
27 npm --prefix pet run sync
28 cargo build --locked -p codewhale-tui
29 PET_OWNER_BINARY="$PWD/target/debug/codewhale-tui" ./pet/macos/build.sh
30 ./target/debug/codewhale-tui
31 ```
32
33 In the running application:
34
35 | Command | Result |
36 | --- | --- |
37 | `/pet` | Toggle pet mode for this terminal: the habitat takes the whole content viewport now and on every accepted turn |
38 | `/pet on` / `/pet off` | Enable or disable explicitly; `off` closes the view and stops automatic entry while the companion keeps the pet alive |
39 | `/pet appearance` | Configure the shared palette in the authenticated local browser studio |
40 | `/pet window` | Open the independently closable native macOS window |
41 | `/pet source` | Explicitly select this terminal session as the source |
42 | `/pet sound on\|off` | Request/release the companion's audio device |
43 | `/pet export` | Save a replay to this saved session's artifacts |
44 | `/pet status` | Mode, view, identity and measured terminal output counters |
45
46 The pet has no workbar panel; the habitat is its only terminal view. Escape
47 leaves it without cancelling the turn or touching the composer draft. F6
48 toggles sound, F8 opens the appearance studio, and F9 opens the native window;
49 reduced motion follows the shell's existing motion setting. Hints and key
50 admission use the existing shell binding table. The habitat uses the modal
51 stack; composer contents, transcript, selection and active Engine state stay
52 underneath it. Consent and approval views retain their existing priority.
53
54 `CODEWHALE_PET_APP` can identify a locally built `.app`. `CODEWHALE_PET_HOME`
55 selects an isolated companion directory; its default is
56 `~/.codewhale/pet-shared`. `CODEWHALE_PET_PORT` chooses the initial loopback port
57 (default 4633; zero allocates an unused port for tests). A saved world retains
58 its selected port. `CODEWHALE_PET_GRAPHICS=braille` forces the text fallback.
59 None of these commands replace an installed global CLI.
60
61 ## Appearance and work-to-result preview
62
63 The habitat studio provides Ocean, Chalk, Graphite, Linen, Forest, Plum, Ember
64 and Cobalt presets. Background, upper light, particle color, activity colors,
65 brightness, dot size, glow and environment are independently configurable.
66 Export/import a versioned appearance JSON. Live appearance changes use the same
67 ordered, durable action contract and reach every attached view; they never enter
68 the simulation's interaction journal or change its replay digest. Native and
69 terminal hosts consume the shared background, material, dot size and glow.
70
71 For an isolated, provider-free review, serve `pet/dist` and open
72 `shared.html?preview=1`. Compare all eight looks, toggle Still, and choose
73 **Preview work → result**. The canonical world drives the animation; the answer
74 is explicitly illustrative and no task or provider is run. The live studio's
75 preview detaches into an isolated world and offers **Return to live pet**.
76
77 `/pet on` is opt-in for the current TUI
78 instance. The existing Engine's accepted turn-start event opens the full habitat
79 when no consent or other modal owns focus. Completion gives space to the actual
80 last assistant/error cell through the existing transcript renderer, with arrows
81 and page keys for scrolling. The terminal implementation composes the whale above
82 the answer for legibility; the browser preview demonstrates an overlaid fade.
83 Escape does not cancel the turn, replace the composer or remove the transcript.
84 Conversation text stays in the shell, never in the pet transport or recording.
85
86 ## Legible work and spontaneous motion
87
88 The shared frame adds a bounded, read-only `activity` projection. It reports
89 reading, searching, editing, command execution, tests, browser use, context
90 retrieval, response writing, coordination, errors and witnessed human waiting.
91 The exact printable tool identifier accompanies its label. An `exec_command`
92 receipt says **Running a command**: without inspecting its private arguments,
93 the pet cannot honestly call that a test, a build or a successful result.
94 At most four concurrent foreground cues and a fresh active-agent count are
95 projected. Tool/agent IDs, paths, arguments, prompts and outputs are omitted.
96 Cues expire after 800 ms without an appropriate heartbeat and clear on source
97 change, disconnect and restoration. A connected transport alone is not work.
98
99 The preview selector demonstrates thirteen action/unknown states. A complete
100 44-second work preview walks through eleven phases and then reveals the example
101 answer. Search sweeps, file marks, editing brackets, test activity rings and
102 parallel-agent marks use the canonical frame time, freeze under Still, and make
103 no claim about progress percentages, test counts or successful outcomes. These
104 extra drawn marks are currently a browser presentation treatment; terminal and
105 native prepared views share the exact action caption and canonical work forms.
106
107 Determinism and variety live at different boundaries:
108
109 * Physics, seven autonomous behaviors, persistent pod phases and sound use
110 fixed ticks and named seeded streams. Rendering never consumes those streams.
111 * Engine observations and human interactions arrive from outside the pet.
112 Accepted categories and ordered interactions are recorded. The same starting
113 checkpoint and input history reproduce the motion and score.
114 * Changing the input history changes the visit. Focus and Pulse therefore
115 influence a living trajectory while remaining replayable. Fresh worlds
116 currently use the same initial seed; per-pet random birth seeds are not added.
117 * Live action captions are ephemeral receipts, intentionally absent from replay
118 files to avoid persisting tool names. Replay proves the world and score, not a
119 historical transcript of exact actions. It cannot revive a stale request.
120
121 The pet is a presentation of observed activity. It never chooses tools, invents
122 work, runs another agent loop, or blocks completion to finish an animation.
123
124 ## Ownership and reconnects
125
126 A process-lifetime OS lock excludes a competing owner. Private, anchored file
127 I/O rejects symbolic/hard links, replaced locks and external revisions. The
128 saved envelope holds one UUID, connection credential, selected source and
129 revision, ordered cursor, retained interaction receipts and canonical recording.
130 The first attached saved terminal selects its session only when the source is
131 `unattached`. Later terminals are views until explicitly selected. Session IDs
132 are represented by a short SHA-256 identifier. Multiple sessions are never mixed.
133
134 Interactions require a client UUID, consecutive sequence and current source
135 revision. The world and receipt are saved before acknowledgement. Repeating the
136 same packet returns its receipt; changing a duplicate, skipping a sequence or
137 using a stale source fails. Storage failure refuses the action and preserves
138 the prior file. Receipts are retained for up to 4,096 interacting clients; they
139 are never silently evicted or re-applied after an owner restart.
140
141 Engine metadata uses a separate ordered producer lease and the existing
142 `PetEngineTelemetry` bucketer. A fresh lease starts with sequence zero and no
143 historical events. Unknown fields, content payloads, oversized batches and
144 partial invalid batches are rejected. Gaps reset observation, and old epochs
145 cannot feed a restarted owner. A heartbeat proves transport availability; it
146 cannot invent observed work. A witnessed waiting request still requires the
147 existing typed shell's current waiting state.
148
149 The world advances at fixed 30 Hz even with no views. Its periodic checkpoint
150 is once a second. Producer replies explicitly say `durable: false`: a crash
151 may lose the uncheckpointed observation interval. Acknowledged interactions
152 are durable. Recovery restores the last checkpoint and resumes at the first
153 unrecorded interval, clears producer/audio leases, and does not replay stale
154 sound or claim historical requests as current. Suspended-machine catch-up is
155 bounded to three ticks and marks a gap. Frame receivers independently reject
156 stale presentation after 800 ms.
157
158 At 1,024 consumed buckets or 4,096 applied interactions, completed history is
159 published immutably before the active segment advances. Active storage is
160 bounded to 8 MiB; recovery exports stream out of QuickJS in chunks, up to
161 64 MiB. Archives remain on disk and require explicit storage management.
162
163 ## Graphics and audio
164
165 The Rust view worker polls immutable snapshots, interpolates display positions,
166 rasterizes and compresses pixels outside the input thread. It overwrites one
167 latest frame slot; it does not queue movies. The maximum raster is 960×560 RGB.
168 Stillness uses a separate stable projection and cannot change the authoritative
169 simulation, score, journal or digest. Missing coverage remains hollow and
170 labeled; sleep dims it separately.
171
172 Pixels require a successful Kitty graphics query and synchronized output.
173 Inline RGB uses zlib and base64 chunks of at most 4,096 bytes. One image ID per
174 process is replaced inside the existing Ratatui synchronized frame, with cursor
175 save/restore and deletion on layout changes, covered views and exit. The
176 transport follows the [Kitty graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/).
177
178 60 fps is a presentation target, not a universal guarantee. `/pet
179 status` reports actual frames, elapsed output time, bytes/second, raster time
180 and write time for that visit. Slow encoding drops intermediate presentations.
181 The 30 Hz world does not depend on display rate. Unsupported terminals, tmux,
182 Sixel-only terminals and disabled synchronized output use braille. SSH can use
183 inline Kitty bytes if the remote terminal answers the probe, but bandwidth and
184 end-to-end SSH compatibility require separate measurement. No tmux passthrough
185 or Sixel pixel renderer is claimed.
186
187 Sound is off by default. One view leases the companion's single `ffplay`
188 output, renewed every 500 ms and expired after two seconds. PCM comes from the
189 existing deterministic score at 48 kHz. Closing, hiding, quiet mode and stale
190 frames release or expire the lease. Late output is dropped through the bounded
191 PCM queue. FFmpeg is optional and never downloaded automatically. On mobile,
192 “Companion sound” controls the owner's speaker; it does not start a second
193 phone player.
194
195 ## Existing habitats and mobile
196
197 Wild, Event demo, imported replay and File study remain explicitly isolated.
198 Old browser IndexedDB recordings and per-session TUI
199 `artifacts/pet/habitat.json` files are retained. Apple File study continues to
200 use the former `live.json`; Android's File study keeps its `live` storage key.
201 Shared views never overwrite or merge those worlds. Import their recordings in
202 the standalone viewer to recover them.
203
204 The local browser can join using its “Join shared pet” file control and the
205 private `connection.json`, or the terminal's browser command. The URL fragment
206 is removed immediately; the owner exchanges the bearer for an HttpOnly,
207 SameSite cookie. Host and Origin checks reject foreign origins. The listener is
208 only `127.0.0.1`; no CORS, LAN listener or unauthenticated remote route is added.
209
210 Apple and Android Shared modes consume the same immutable frame contract.
211 They do not run their native simulation or native audio in this mode. Import
212 `connection.json` with “Join shared pet”; it is retained privately. On an Android
213 emulator or explicitly connected device, `adb reverse tcp:4633 tcp:4633` carries
214 its loopback traffic to the desktop owner. iOS Simulator shares host loopback.
215 Physical-device/cross-network use needs an explicitly established authenticated
216 loopback tunnel. The existing Runtime's authenticated transport and progress
217 contract are unchanged; no new remote deployment or compatibility claim is made.
218
219 ## Verification
220
221 `python3 pet/scripts/check-shared.py /absolute/path/to/codewhale-tui` creates a
222 unique fixture directory and checks owner exclusion, two attachments, metadata
223 validation, source changes, interaction ordering, view independence, audio
224 exclusion, crash recovery and storage conflicts. Fixtures are retained for
225 inspection. `npm --prefix pet run check` covers unchanged replay/score semantics
226 and presentation immutability. The product's `pet_watch` tests exercise real
227 transport encoding, braille, focus restoration, storage and PCM boundaries.
228
229 Build/test receipts, actual native/browser screenshots, terminal visual
230 qualification and independent exact-SHA review are separate evidence. See
231 `QA.md` for the current measured results and outstanding limitations.
232
232 lines MARKDOWN