Ambient system companions over one privacy-preserving signal daemon (aggregate-only, no keystroke content): a git-driven terminal garden and IOKit hardware collectors. ambient daemon macos privacy terminal

CHANGELOG.org

main
ambient-companions/CHANGELOG.org rendered · source · history · blame · raw

177 lines · 8100 bytes

  1#+TITLE: Changelog
  2#+OPTIONS: toc:nil
  3
  4Notable changes per release. Dates are release dates; the repository's own
  5history has the detail.
  6
  7=SCHEMA_VERSION= is the wire contract between the daemon, the Swift collector
  8and every renderer, so it is called out wherever it moves. From 1.0 onward
  9=SignalName= discriminants are append-only: names may be added, never
 10renumbered or removed.
 11
 12* Unreleased
 13
 14* 1.2.1 — 2026-09-04
 15
 16** Added
 17- =packaging/net.krz.ambient-companions.menubar-pet.plist=, a LaunchAgent for
 18  the menu-bar face. A Login Item stores a bookmark that macOS resolves to the
 19  versioned Cellar path at creation, so it breaks silently at the first
 20  =brew cleanup= after an upgrade; launchd stores a string and follows the
 21  =opt= symlink each time.
 22
 23* 1.2.0 — 2026-09-04
 24
 25** Added
 26- =menubar-pet=, the third face: a menu-bar pet with one life. It ages, neglect
 27  kills it over a week through visible stages, and death is permanent for that
 28  pet. A new one arrives when you come back, and the dead are kept in a
 29  cemetery that is never pruned.
 30- =pet-life=, the Rust crate behind it. Everything derives from timestamps
 31  rather than accumulating, so death happens at =last_activity + 7 days= and
 32  not when a program noticed — sleep, reboots, daemon restarts and the app not
 33  running change nothing. Birth requires activity, so a fortnight away leaves
 34  one grave rather than a chain of pets born, never fed and dead.
 35- =History::open_read_only= and =History::last_activity_ms=. Read-only because
 36  the ordinary open prunes, and a face polling every five seconds must not
 37  delete the daemon's history as a side effect of reading it.
 38
 39** Fixed
 40- The privacy ship-gate's forbidden-symbol scan missed =${BUFFER}=. The braced
 41  form is ordinary zsh and does not contain the substring =$BUFFER=, so the
 42  check enforcing the project's central claim was bypassable by two
 43  characters. =$RBUFFER= was absent entirely.
 44- That scan also asserted nothing about having scanned. If the directory walk
 45  returned empty the test passed having read no files, reporting success while
 46  checking nothing.
 47- The banned list widened by prefix where safe: =CGEvent=, =IOHID=, plus
 48  =addLocalMonitorForEvents=, =AXObserver= and =AXUIElement=. Bare =NSEvent=
 49  stays permitted — the keylogger-shaped API is the monitor, not the class, and
 50  a menu-bar face will need it to draw a UI.
 51
 52* 1.1.0 — 2026-09-04
 53
 54** Added
 55- =terminal-pet --oneline=: one line, then exit, for a shell prompt segment.
 56  About 2.7 ms per call including process start. With no daemon it prints
 57  nothing and exits non-zero, so a prompt segment hides itself rather than
 58  printing a diagnostic into the prompt.
 59- =signal_client::Frames::snapshot=, which reads the daemon's last-value cache
 60  and returns without waiting out a timeout.
 61
 62** Fixed
 63- The pet's mood ignored staleness, so a cached keystroke rate left it looking
 64  busy indefinitely. The terminal collector stops publishing once a session
 65  ages out of its active window, so the last rate sat in the cache with nothing
 66  to replace it. Mood now considers only current readings.
 67
 68* 1.0.0 — 2026-09-04
 69
 70The release that makes one claim: the daemon runs unattended, recovers from its
 71own failures, and says so when it cannot. Not feature completeness — two of the
 72five faces in the README exist, and the rest are explicitly post-1.0.
 73
 74=SCHEMA_VERSION= 4 → 5.
 75
 76** Added
 77- =SignalName::CollectorUp= (discriminant 11), the daemon's own health,
 78  published once per =Source= on state changes. A dead collector now reaches a
 79  face instead of a log file.
 80- =signald/src/supervisor.rs=: collector liveness in one place. The hardware
 81  child is respawned with backoff from 1 s doubling to a 60 s cap, reset after
 82  a run surviving 30 s, with no retry limit.
 83- =terminal-pet=, the second face: the shell, the machine, and collector
 84  health. Any collector down renders the pet sick, which outranks every other
 85  mood.
 86- =crates/signal-client=, one definition of the socket path and of frame
 87  iteration, shared by the daemon and both renderers.
 88
 89** Fixed
 90- A panic in the git or terminal collector killed the producer thread while the
 91  socket kept serving a frozen cache, so faces went on rendering numbers that
 92  had stopped being true. A panic now costs one tick.
 93- The hardware collector was spawned once and never again. If the child died,
 94  the daemon stayed up, so launchd's =KeepAlive= never fired and hardware
 95  signals stopped for good.
 96- =run_git= used =.output()= with no timeout, so a held index lock or a
 97  vanished network mount hung the producer thread forever while health still
 98  read up.
 99- =keys_per_min= had no floor on its sample window: two prompts a millisecond
100  apart extrapolated a handful of keys into a five-figure rate.
101- The zsh hook capped the spool at 1 MiB. Nothing consumes it while the daemon
102  is away, and the daemon read the whole file on recovery.
103
104** Changed
105- The hub's last-value cache keys by name, source and tag. It keyed by name and
106  tag, so two signals differing only by source overwrote each other.
107- =Signal.ts= no longer claims to be monotonic-corrected. It cannot be: it is
108  persisted, retention prunes on it, and =CommitsToday= means since local
109  midnight.
110
111* 0.6.1 — 2026-09-04
112
113** Fixed
114- =signald= had no =--help=, and any unrecognised argument became a repository
115  path — so =signald --help= started the daemon watching a directory named
116  =--help=. Both binaries now have =--help= and =--version=, and an unknown
117  option exits 2.
118
119* 0.6.0 — 2026-09-04
120
121** Added
122- An install path. =packaging/net.krz.signald.plist= runs the daemon at login;
123  a Homebrew formula in =krz/homebrew-tap= installs the binaries, the plist and
124  the zsh hook, with =brew services= support.
125- =~/.config/signald/repos=, read when no repository is given on the command
126  line. launchd starts an agent in =/=, so without it a service install
127  collected no git signals at all.
128- A README "Paths" table: the socket, history database and spool defaults in
129  one place.
130
131* 0.5.0 — 2026-09-04
132
133The contract freeze. =SCHEMA_VERSION= 3 → 4.
134
135** Changed
136- =SignalName= cut from 29 variants to the 11 with a producer, and its
137  discriminants renumbered from zero. The last release in which renumbering was
138  possible.
139- =Tag::bundle_id= and =Tag::ssh_host= removed: both were =todo!()= panics
140  whose only consumers were among the removed variants. =Tag::repo_path= is the
141  sole constructor, and =signald= confines a tag to the roots it was told to
142  watch.
143
144** Fixed
145- A frame the build could not decode ended the stream, so a renderer built
146  before a metric was appended died on the first one it met. Such frames are
147  now skipped; an error is reserved for a stream that cannot be framed at all.
148- Around 34 citations of a specification that was never committed, replaced by
149  the rules they referred to.
150
151* 0.4.0 — 2026-09-04
152
153One bus: every collector reaching every subscriber by the same path.
154
155** Added
156- Hardware ingest. =signald= spawns =macos-collector= and reads its frames, so
157  the five hardware signals reach the hub, the history store and every
158  subscriber like any other collector's.
159- A 0BSD =LICENSE=.
160
161** Changed
162- The terminal spool is consumed each tick rather than re-read in full forever,
163  and its records carry the shell's pid, so =keys_per_min= is each active
164  shell's rate summed rather than a mix of interleaved sessions.
165- History rows older than =--retention-days= (default 7) are pruned.
166- CI was added and then removed within this release. The forge's runner is
167  scoped to one repository, so builds queued here were never claimed;
168  =.githooks/pre-push= runs the whole suite instead and is the only gate.
169
170* 0.3.0 — 2026-08-10
171
172First tagged release: the signal daemon, the git, terminal and IOKit
173collectors, and the privacy-gated =f64=-only schema at =SCHEMA_VERSION= 3.
174
175The v0.1 and v0.2 milestones named in the README — the git collector and the
176garden, then the SQLite history store, live streaming and the terminal
177collector — were never tagged and are folded into this commit.