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