Commit Graph

19 Commits

Author SHA1 Message Date
shitratgit[bot] 65ed90c9ea fix: enforce bounded gateway judgment turns 2026-08-24 22:34:08 +00:00
shitratgit[bot] 2a3d333ae5 fix(gateway): use launchd user domain 2026-08-11 18:59:49 +00:00
shitratgit[bot] 272cff0ae1 fix(herdr): isolate system automation session 2026-08-11 03:53:15 +00:00
shitratgit[bot] eeceffd7a3 fix(gateway): pin local message event stream 2026-08-05 22:12:57 +00:00
shitratgit[bot] 8cfb7f93d9 fix(gateway): allow two-stage cursor progress 2026-08-05 22:11:14 +00:00
shitratgit[bot] bbfa90db04 fix(gateway): replace stalled and invalid agent sessions 2026-08-05 16:48:29 +00:00
shitratgit[bot] e65e02dd5c feat(gateway): steer delivery to the dropped-ball bar with a morning digest
roles/gateway.md carries the settled bar: a ping means waiting-on-Joel
and aging, important first-notice breakage, or an answer he asked for.
One incident one thread, one ping per crossing, worker receipts never
ping, runbook cadence is evidence. Ack-first applies to addressed
inbound only; ambient gets observe and zero outbound. Morning digest
beat: idempotent 07:30 LA wake with registry readback in the driver.
2026-07-29 14:23:27 -07:00
shitratgit[bot] 55aa80a32e fix(gateway): leave a receipt when the heartbeat fiber covers a blocked pass
The heartbeat fiber logs only on verdict change, so the one moment worth seeing
— it refreshing the key while the work pass sits inside a 300s poke — left no
trace at all. The fix was invisible in production exactly where it matters.

A work pass older than the TTL can only mean it is blocked, so refreshes taken
in that window now carry coveringBlockedPass and how stale the pass had gone.
Still silent the rest of the time; the receipt log is 25MB per five days and
does not need every ordinary tick twice.
2026-07-27 13:59:48 -07:00
shitratgit[bot] 819bc64aeb fix(gateway): the heartbeat means alive, not idle
The transport reads gateway:agent:heartbeat to answer one question: will a
live agent session pick this message up? The driver was answering a different
one — "is the session idle this instant" — and withholding the key otherwise.

Two failure modes, both measured on the live receipt log 2026-07-27:

1. The pass that wrote the key was the same pass that blocked on promptAgent.
   The poke deadline is 300s; the key lives 60s. 51 of the last 200 pokes
   outlived the TTL, leaving the gateway invisible 12.6% of the day — precisely
   while it was busiest. Fixed by giving the heartbeat its own fiber that takes
   its own fresh observation and never blocks on a poke.

2. Every ordinary busy turn read as an outage, so the transport delivered raw
   text and bypassed the agent's judgment. Fixed by heartbeatVerdict(), which
   withholds only on real evidence: no session, degeneration, a failed poke,
   an in-flight retire, or a session that has stopped answering entirely.

The last of those is what keeps this honest. A mid-turn session is vouched for
only within unresponsiveGraceMs (default = poke deadline), so a wedged session
still loses the key and the kill drill still has something to catch. A retired
session drops the key in the same pass that stops it, never on pre-kill
evidence.

Also fixes the restart gap: a driver restarting mid-turn used to score the
running session unresponsive on sight and withhold, which is why restarting the
driver guaranteed a raw-delivery window.

45 driver tests pass (7 new), 252 across gateway + driver.
2026-07-27 13:57:23 -07:00
shitratgit[bot] bc223c64bd fix(gateway): stop the noise machine — aggregation, Front mail, health ticks
Six days of the message event log (3978 events, the gateway's whole life)
say the same thing three ways: it talks more and Joel talks less.
Deliveries went 15/day on cutover to 76/day; Joel's own messages went
36/day to 3/day.

Three causes, two of them mine from 2026-07-25.

1. The 4h session retire stranded every open aggregate. A batch lives in
   the agent's head, so the successor can never close one it did not
   open. Aggregation stopped dead at 07-25 21:00 and never resumed across
   11 retires — and aggregation was absorbing 694 of 844 health-check
   inputs. shouldRetire now waits for an empty batch set, bounded by
   aggregateGraceMs so a wedged batch cannot keep a rotting session alive.

2. The Front reader emitted only channel/message.received (indexing).
   front-message-received-notify listens for front/message.received, so
   from 07-23 12:13 every inbound email was indexed and none announced.
   The reader now emits both, inbound only, with a Redis claim so the
   5-minute overlap window cannot ping twice.

3. check-system-health was 844 of 1321 gateway inputs — the loudest
   speaker by 6x — because the only suppressor was "does a task exist".
   Joel was told about Front Projection 46 times in 40 hours. It now
   notifies on transitions of the degraded set, with a 6h reminder for
   real outages and one message on recovery.

Also retries Front 200s with unparseable bodies instead of burning an
Inngest attempt on "Unexpected end of JSON input".

11 new tests. Pre-existing 4 failures in system-bus are unrelated and
unchanged (verified against a clean tree).
2026-07-27 09:11:38 -07:00
shitratgit[bot] 4ab277d0e2 fix(driver): measure session age from the session, not from driver memory
Session age was tracked as first-sighting in driver memory, so restarting the
driver handed the running session a fresh 4h lease. Caught on the live restart:
a session that had been up since 2026-07-22 reported sessionAgeMs 0.

That is backwards — a driver restart is exactly when a rotting session most
needs retiring. Age now comes from the Claude transcript named by the herdr
agent session id, falling back to first sighting only when it cannot be read.

The live session reads 3.5 days old against a 4h limit.
2026-07-25 13:52:44 -07:00
shitratgit[bot] a899ee1271 feat(driver): retire the gateway session before it rots
Two long sessions degenerated into repeated "court" tokens — one reply emitted
it 32,000 times — at ~394k and ~886k context on --model opus --effort low,
after running for days. The brief's own Vocabulary always said a cycle should
"retire at ~150k tokens or a quiet moment." Nothing implemented it: the driver
had no age or size signal at all, so the session ran until the model broke.

Adds two retire paths:

- Clean age retire (default 4h, GATEWAY_MAX_SESSION_AGE_MS, 0 disables) fires
  only when the session is healthy, idle, and has no unhandled work. Retiring
  with queued work or an outstanding poke would defeat the point.
- Forced retire on degeneration. Repeated-token collapse is poison — once it
  appears the model re-samples it — so this one preempts queue state. The
  detector is deliberately boring: the known court burst, or one token
  dominating a short recent window.

Wall-clock age is the honest signal. A scraped token count would be a fragile
guess about someone else's internals.

This exposed a real gap in the successor spawn: it returned early whenever a
pane already carried the target label, assuming that pane held a live session.
After a retire the pane exists with nothing in it, so nothing would have
relaunched. Spawn now checks for a live agent and relaunches in place, still
never opening a second pane for the same label.
2026-07-25 13:47:10 -07:00
shitratgit[bot] c02edae276 gateway: medium effort + trimmed boot snapshot after degenerate generation loop ("court" repetition) 2026-07-22 09:43:49 -07:00
shitratgit[bot] aa7c05e76a gateway: sonnet 5 low effort for the loop — token generation was the latency floor (scan measured 8ms); amends opus call on speed evidence 2026-07-21 16:47:59 -07:00
shitratgit[bot] eea082c35b gateway: conversational fast path — advanceAfter one-call replies, low effort, 5s driver cadence 2026-07-21 16:35:56 -07:00
shitratgit[bot] 02b5df6100 gateway: 300s poke deadline is the code default, drill restarts carry timing env, loop runs medium effort — heartbeat flap + latency fix 2026-07-21 16:17:58 -07:00
shitratgit[bot] eb99c2fd91 agent-comms-gateway: cutover executed — decision executor, herdr-native driver, unlatch fix, kill drill 8/8, weekly drill armed 2026-07-21 16:07:34 -07:00
shitratgit[bot] fd44f4c2c9 agent-comms-gateway: kill-test script + weekly drill built (eight assertions, ready-but-unarmed) — build phase complete 2026-07-21 13:15:06 -07:00
shitratgit[bot] ccb3bbcf9d agent-comms-gateway: driver (XState/Effect, scratch-proven) + transport slim-down (opt-in composition root, undeployed) — 2 steps closed 2026-07-21 12:59:29 -07:00