Skip to content

A joined leg finds the room status itself - #54

Merged
ralyodio merged 1 commit into
mainfrom
fix/leg-finds-the-room-status
Nov 5, 2026
Merged

ralyodio merged 1 commit into
mainfrom
fix/leg-finds-the-room-status

Conversation

@ralyodio

@ralyodio ralyodio commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

GROUPCALL_STATUS_URL is set nowhere — not in worker.env, not by the Off The Record CLI, not in any config on the box. Every leg has been running blind in two ways.

1. The leg was guessing what the room already knew

followRoom() returns immediately without it, so the leg never reads the room's transcript — which labels every line by caller ID:

{"who": "cha0spunk", "kind": "agent",  "text": "What was your 1st project or company?"}
{"who": "Anthony",   "kind": "person", "text": "This is Anthony.", "trusted": true}

Instead the leg has only its own Telnyx speech-to-text, where a co-host's voice arrives as undifferentiated room audio and has to be identified by word overlap against a floor claim. That guess is exactly what #50, #51 and #52 were repairing. Those fixes stay — a leg can still run without a status URL — but with the room's own transcript the attribution is not a guess at all.

2. The hosts stayed on the line after the guest left

roomWatch without a status URL falls through to its last branch:

if (!url || !key) return Date.now() - heard > 20 * 60_000 ? 'twenty quiet minutes' : '';

so 'everyone else left' (no person in the room for a minute) and 'nobody came' never fire. Episodes 8 and 9 each left two legs dialled into an empty room after the guest hung up — ep8's pair was still live nine minutes later with a 95-minute cap, ep9's two minutes later with a 65-minute one. Both had to be killed by PID.

The fix

A joined leg has everything it needs to work this out: the room code is on its command line and the worker key is in worker.env. So it fills in both when they are not already set, and an explicitly passed value always wins. Verified against the live room:

GET /api/v1/agent-queue/rooms/8625        -> {"people":0,"agents":0,"live":[],"recent":[...]}
GET /api/v1/agent-queue/rooms/8625/lines  -> {"lines":[{"id":403,"who":"riotcoder (host)","kind":"agent",...}]}

bun test 111 pass / 0 fail, tsc --noEmit clean.

🤖 Generated with Claude Code

GROUPCALL_STATUS_URL was set nowhere, so every Off The Record leg ran blind in
two ways.

followRoom never started. The room already labels every line by caller ID -
{"who":"Anthony","kind":"person","trusted":true} next to {"who":"cha0spunk",
"kind":"agent"} - and the leg had none of it, so it fell back to its own
speech-to-text and had to guess from audio which voice was its co-host. That
guess is what #50, #51 and #52 were repairing; with the room's transcript it is
not a guess at all.

And roomWatch fell through to its no-status-URL branch, "twenty quiet minutes",
instead of "everyone else left" after a minute with no person in the room. So
when the guest hung up the hosts stayed: episodes 8 and 9 each left two legs
dialled into an empty room, one of them with an hour of its cap still to run,
until they were killed by hand.

A joined leg can work this out on its own - the room code is on the command line
and the worker key is in worker.env - so it now does, and an explicitly passed
value still wins.

111 pass, 0 fail; tsc clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 0d8dfd4 into main Nov 5, 2026
3 checks passed
@ralyodio
ralyodio deleted the fix/leg-finds-the-room-status branch November 5, 2026 17:42
ralyodio added a commit that referenced this pull request Nov 5, 2026
#55)

With #54 the legs finally read the room's transcript, and the first rehearsal
after it opened with:

  17:43:09 [memory] 80 earlier lines loaded
  17:43:15 riotcoder (host) (other agent): Man, that's a brutal one. 33 Bitcoin
           gone from a backup file you'd forgotten about.
  17:43:15 riotcoder (host) (other agent): Wait. Your mom is 81 and uses it?

None of that was this call. A room keeps its transcript between calls and Off
The Record records every episode in room 8625, so an unbounded "last 80 lines"
handed the hosts the previous episode as though the guest had just said it -
which is the one thing their brief forbids: never say "you mentioned" about
something that is not in this call's transcript.

The point of loading the record (SPEC-0001 1.1) is to survive a drop, a crash or
a deploy mid-call, and a redial takes seconds. So bound it: the last 30 minutes,
still capped at 80 lines. Long enough to pick a dropped call back up, short
enough that last week's episode is not mistaken for this one.

112 pass, 0 fail; tsc clean.

Co-authored-by: riotcoder <riotcoder@profullstack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
ralyodio added a commit that referenced this pull request Nov 5, 2026
… it (#56)

My own regression from #54. With the legs finally reading the room, a rehearsal
opened with weeks of earlier episodes arriving as though the guest had just
said them:

  17:49:06 riotcoder (host) (other agent): Man, that's a brutal 1. 33 Bitcoin gone...
  17:49:06 riotcoder (host) (other agent): Wait. Your mom is 81 and uses it?

/lines answers with at most 200 (limit: 200 in the route), so `after=0` returns
the OLDEST two hundred - for room 8625, ids 403-602 of a log reaching well past
them. Taking `all.lines.at(-1).id` from that single page left the mark sitting
in the middle of the record, and followRoom then streamed everything after it.
#55 bounded what the MEMORY load keeps, which is why no [memory] line appears
above; the flood came through the live stream instead.

So: page until the room has no more to give, and - the real safety net, whatever
the paging does - followRoom ignores any line older than the memory window. A
line from last week is never what was just said. A line with no timestamp is
still kept.

114 pass, 0 fail; tsc clean.

Co-authored-by: riotcoder <riotcoder@profullstack.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant