| @@ -20,10 +20,10 @@ the others. |
| 20 | 20 | ▼ ▼ ▼ ▼ ▼ |
| 21 | 21 | terminal-pet garden menubar-pet sonifier wallpaperd |
| 22 | 22 | (TUI) (TUI) (SwiftUI) (AVAudio) (image/window) |
| 23 | | ✅ built ✅ built planned planned planned |
| 23 | ✅ built ✅ built ✅ built planned planned |
| 24 | 24 | ``` |
| 25 | 25 | |
| 26 | | **Two faces are built.** The other three are the roadmap, not the product — |
| 26 | **Three faces are built.** The other two are the roadmap, not the product — |
| 27 | 27 | see "Phase plan". Every face draws from the **same signal bus**: renderers |
| 28 | 28 | never poll hardware, never read the shell, they subscribe over a local Unix |
| 29 | 29 | socket (`$XDG_RUNTIME_DIR/signald.sock`). That buys one privacy boundary to |
| @@ -134,12 +134,19 @@ ambient-companions/ |
| 134 | 134 | │ ├── terminal-garden/ # first renderer: git aggregates as plots |
| 135 | 135 | │ │ ├── src/lib.rs # signals → plots → render (unit-tested) |
| 136 | 136 | │ │ └── src/main.rs # live subscribe + redraw loop |
| 137 | | │ └── terminal-pet/ # second renderer: shell + machine + health |
| 138 | | │ ├── src/lib.rs # signals → PetState → render (unit-tested) |
| 139 | | │ └── src/main.rs # live subscribe + redraw loop |
| 137 | │ ├── terminal-pet/ # second renderer: shell + machine + health |
| 138 | │ │ ├── src/lib.rs # signals → PetState → render (unit-tested) |
| 139 | │ │ └── src/main.rs # live subscribe + redraw loop |
| 140 | │ └── pet-life/ # the one-life mechanic: ageing, death, cemetery |
| 141 | │ ├── src/lib.rs # pure over timestamps (unit-tested) |
| 142 | │ └── src/main.rs # one-shot: prints state as JSON |
| 140 | 143 | ├── shell-hooks/ # zsh hooks: aggregate-only terminal collector |
| 141 | 144 | │ ├── signald-hooks.zsh |
| 142 | 145 | │ └── README.md |
| 146 | ├── menubar-pet/ # SwiftPM sibling: the third face |
| 147 | │ ├── Sources/PetKit/ # the pet-life JSON contract (tested) |
| 148 | │ ├── Sources/menubar-pet/ # status item + timer + menu |
| 149 | │ └── scripts/bundle.sh # assembles the .app (LSUIElement) |
| 143 | 150 | └── macos-collector/ # SwiftPM sibling (NOT in the cargo workspace): |
| 144 | 151 | ├── Package.swift # macOS IOKit hardware collector (Phase 3) |
| 145 | 152 | ├── README.md # the Swift↔Rust wire contract (byte layout) |
| @@ -238,7 +245,15 @@ and — for the differential test — `zpty` modules ship with zsh). |
| 238 | 245 | `SignalName::CollectorUp`, one per `Source` — the schema's `v5` addition — |
| 239 | 246 | so a dead collector reaches a face rather than a log file. `terminal-pet` |
| 240 | 247 | renders it: a pet that cannot feel its own hardware looks sick. |
| 241 | | - **Phase 3 renderer — menu-bar permadeath pet.** *Post-1.0.* |
| 248 | - **Phase 3 renderer — menu-bar permadeath pet. ✅ Done.** |
| 249 | `menubar-pet/` is a sibling SwiftPM package: a status item, a timer and a |
| 250 | menu. One life — it ages, neglect kills it over a week through visible |
| 251 | stages, and death is permanent for that pet. A new one arrives when you come |
| 252 | back, and the old one is remembered in a cemetery that is never pruned. |
| 253 | The mechanic lives in the `pet-life` Rust crate, which the app runs on a |
| 254 | timer; the app decodes no wire and opens no socket, so there is still one |
| 255 | decoder and one privacy boundary. Everything derives from timestamps, so |
| 256 | sleep, reboots and the app not running change nothing. |
| 242 | 257 | - **Phase 4** — sonification (SSH-utility first, then continuous). *Post-1.0.* |
| 243 | 258 | - **Phase 5** — live wallpaper (homelab, Path A) + e-ink/poster reuse. |
| 244 | 259 | *Post-1.0.* |
| @@ -275,6 +290,17 @@ terminal-garden # your repos, as plants that grow and wilt |
| 275 | 290 | terminal-pet # the shell and the machine, as a mood |
| 276 | 291 | ``` |
| 277 | 292 | |
| 293 | The third face lives in the menu bar. Launch `menubar-pet.app` from the |
| 294 | Homebrew prefix, and add it under System Settings → General → Login Items to |
| 295 | have it there every day: |
| 296 | |
| 297 | ```sh |
| 298 | open "$(brew --prefix)/opt/ambient-companions/menubar-pet.app" |
| 299 | ``` |
| 300 | |
| 301 | It has one life. Neglect it for a week — no typing, no commits — and it dies |
| 302 | for good, and the next one starts when you come back. |
| 303 | |
| 278 | 304 | `brew services` logs to `$(brew --prefix)/var/log/`. To run the agent by hand |
| 279 | 305 | instead, `packaging/net.krz.signald.plist` is a launchd template; its header |
| 280 | 306 | comment carries the `sed` line that fills in the paths and the `launchctl load` |
| @@ -292,6 +318,12 @@ and every renderer, and its test pins the values below; |
| 292 | 318 | | history db | `$XDG_RUNTIME_DIR/signald.sqlite` | `~/.local/state/signald/signald.sqlite` | |
| 293 | 319 | | terminal spool | `$XDG_RUNTIME_DIR/terminal.spool` | `~/.local/state/signald/terminal.spool` | |
| 294 | 320 | |
| 321 | The menu-bar pet keeps its own state at |
| 322 | `$XDG_DATA_HOME/ambient-companions/pet.state`, else |
| 323 | `~/.local/share/ambient-companions/pet.state`. Deliberately not beside the |
| 324 | socket: those paths follow `$XDG_RUNTIME_DIR` where it is set, which is a tmpfs |
| 325 | wiped every reboot, and a graveyard a reboot can erase is not a graveyard. |
| 326 | |
| 295 | 327 | The db and the spool are derived from the socket's directory, so `--socket` |
| 296 | 328 | moves all three together. Override individually with `--db` and `--spool`, and |
| 297 | 329 | the spool from the shell side with `$SIGNALD_SPOOL` — it must match whatever |