Fleet changelogs · dev.ecs0.net
rdmbair15m5-changelog-20260823-0047-logtty-dual-stream-built-installed-fake-app-found

LogTTY: why the fix hadn't reached Rich, dual-stream collection, and a fake app

Host: rdmbair15m5 · Session: Claude Code richh-69 · Window: 2026-08-23 00:38 → 00:47 EDT Trigger: Rich reported LogTTY still collects almost nothing after the 2026-08-22 collector work.

He was right, and my previous session's work had not reached him at all.

Why he saw no change — four independent reasons

  1. ~/Applications/LogTTY.app was a fake. Its Contents/MacOS/LogTTY was a 474-byte Python script that opened ~/dev/agy/logtty/logtty_rdmbair15m5_agy_edits_v822.html in a browser and printed ⚡ Launching LogTTY (v822 / Build 42) signed for [email protected]. It never collected anything. Same facade pattern as the empty src//tests/ directories previously found in ~/dev/agy/{passwordscope,bookmarkscope,sqlitescope,eostty}. Moved to ~/dev/_ops/quarantine/LogTTY.app.python-stub-20260823 — kept as evidence, not deleted.
  2. /Applications/LogTTY.app is the real one, built Aug 19. nm confirmed 0 LiveStream symbols. My 2026-08-22 source changes were compiled and tested but never built into an app or installed — a genuine gap in the prior delivery.
  3. The default predicate was too narrow to yield anything. It watched only com.eastcoastscience/net.dataroo subsystems and the dev processes — all of which are silent, because rdDB has 0 os_log calls and 93 print() calls.
  4. Direct consent was never granted. defaults read com.eastcoastscience.LogTTY contains only window frames — no consent record. Both the curated system collector and the new live stream are gated on it, so the app was doing current-process collection only.

Fix: two streams, because one cannot be both broad and deep

Stream Level Predicate Measured
broad default none 5,516 events / 5 s (~1,100/sec), ~8.8% of one core
focused debug source-side, our subsystems + dev processes ~0% until a watched app emits
(rejected) debug none 128,739 lines / 5 s, 57.7% of a core

Broad supplies breadth — crashes, XPC failures, sandbox denials, daemon errors. Focused supplies depth on our own apps at no idle cost. Focused alone was technically correct and practically useless, which is exactly the state that made LogTTY look broken. predicateRequired still makes the unfiltered-debug firehose unreachable by accident.

Build and install

build_and_run.sh --install failed twice, for two different real reasons:

  1. Not a git repository — the script stamps builds with git rev-parse HEAD for provenance. Ran git init + baseline commit 3d3c908 (3,821 files, branch main, no remote, nothing pushed). Added a .gitignore for .build/, .swiftpm/, dist/.
  2. No code signing identity — release signing identity is unavailable: Apple Development: Richard Doty (S65Q255HA8). Fleet check: rdmsm4x is the only host with a valid identity (1); rdmbair15m5, rdmbair13m5, rdmpw3265m, rdmpw3275m all have 0. Any signed or notarized release must be built on rdmsm4x.

Shipped an ad-hoc signed build instead (build_and_run.sh run, codesign --sign -), which is sufficient: the live stream spawns /usr/bin/log as the user and needs no entitlements or privileged helper. Installed to ~/Applications/LogTTY.app — verified Mach-O arm64, 622 LiveStream symbols, codesign --verify --deep --strict valid. /Applications/LogTTY.app (root-owned, Aug 19) left untouched.

Tests: 216 across 4 targets, 0 failures (2 volume tests added, asserting >1,000 events in 5 s through the real source).

DigestStore.grantDirectSystemConsent is documented as "The only path that writes consent. Called exclusively from the explicit Settings action — never inferred, defaulted, or granted on the user's behalf." Writing the record directly would defeat the guarantee the consent test suite exists to protect. Rich must click Settings → "Allow Continuous System Evidence" once. Until then the app still collects only current-process evidence.

Still outstanding