Skip to content

Add live agent session viewer and recorded context - #855

Open
baxen wants to merge 4 commits into
honey/agents2-all-communitiesfrom
baxen/session-debug
Open

baxen wants to merge 4 commits into
honey/agents2-all-communitiesfrom
baxen/session-debug

Conversation

@baxen

@baxen baxen commented Oct 11, 2026 •

Copy link
Copy Markdown
Collaborator

Merge stack, bottom to top: #838 → #855 → #856 → #858 → #859 → #860 → #865 → #867 → #871. Each PR targets the one before it. Earlier stack notes here are superseded.

Adds a local live viewer for Claude Code and Codex sessions: inference/tool timing, posted messages, recorded prompts, tools, and injected context. Run bin/node scripts/session-debug.mjs '<Buzz thread ID or link>' to follow a session in a loopback browser view. Recorded context is distinguished from fields the harness does not record.

Restacked from the existing session-debug and session-debug-context integration commits without source conflicts. The 54 tooling tests (including session viewer/context) and required model-tip push checks pass; native/human acceptance of the combined stack is pending. Kept draft for that testing. No raw session files are included.

baxen and others added 3 commits October 11, 2026 09:57
Codex agents each kept their own `codex app-server` (~300-400 MB with its
MCP children) until the agent stopped running. With agents now running
in every joined community, that cost grew with every Codex agent used.

Everything agent-specific already travels with the thread: cwd,
developer instructions and dynamic tools go in thread/start, and tool
calls carry their threadId. So the runtime now owns one server, opened
on first use in ~/.buzz, and finds a tool call's agent by thread and
turn across all agents. Entries keep their conversations and saved
bindings but no longer own a process.

A stopped agent can no longer take its process down with it, so it
interrupts its own turns, then cleans the background shells its threads
left (a dev server from a finished turn, say). Starting the same agent
again waits for that, so it never resumes a thread mid-teardown. The
server ends with the last Codex agent, on dispose, or on a crash (the
next mention reopens it).

live.mjs passed the relay as an object since the per-agent relay
change; it now passes a function, expands ~ like the desktop host, and
checks two agents on one real server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bradley Axen <baxen@squareup.com>
`bin/node scripts/session-debug.mjs '<thread>'` serves a loopback page that
follows a Codex or Claude Code transcript as it is written. The left rail is a
vertical wall-time chart: inference, tool waits and their overlap, gaps nobody
is accounted for, and idle time between runs, with each call's new tokens
marked beside it. A grey band shows which part of the session is on screen.
The conversation shows one harness/model/effort line, compact tool rows, and
messages posted to Buzz as cards, so text the agent never sent stands out.

Claude Code's zero-usage `<synthetic>` resume replies and queue bookkeeping no
longer count as activity, which had been inflating inference time. The
standalone exporters pick up the same tool rows and posted-message cards.

Started by codex00; chart and conversation design by claude00.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Squashed-from: baxen/session-debug
Squashed-head: 84d70727ddf9db15c352f070634ab47f7adb682f
Signed-off-by: Bradley Axen <baxen@squareup.com>
The session page hid every instructions entry, so even Codex's recorded base
instructions and dynamic tools never appeared. Model-visible context now shows
as quiet collapsed rows where it was recorded, without a proxy:

- Claude: the system prompt and tool schemas from Claude Code's
  `prompt_snapshot` records, one disclosure per tool. Each snapshot pair counts
  as one, and repeats only show when the prompt or tools change. Every injected
  reminder (environment, skills, CLAUDE.md, hook context) is shown with its
  rendered text and role.
- Codex: base instructions, dynamic tools per tool, run settings from
  `turn_context` whenever they change, and developer/AGENTS.md context named
  by its tag.

A one-line reminder also shows inline, such as the token count. Request
framing, Claude's deferred tool schemas and Codex's native tool schemas are
not recorded, and the page says so.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Squashed-from: baxen/session-debug
Squashed-head: d7e8a3c248cdbbb693fdba2ef4c9262e412f21d8
Signed-off-by: Bradley Axen <baxen@squareup.com>
…page

Browser fixtures scan every HTML file under the repo root, and
scripts/session-debug.html imported "client.js", which only the
inspector's own server maps to a real file. The scan failed, Vite
skipped pre-bundling and re-optimized mid-test, and the reloads broke
browser journeys across both engines. The page now names its files as
they are on disk and the server serves them under those names, so the
vite.config.ts exclusion (which fixture servers never read) goes away.

Co-authored-by: claude00 <fb8b76a01257932b8ca35060862c29bd09b2137638573731c2d5074fc02c5385@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Bradley Axen <baxen@squareup.com>
@baxen
baxen marked this pull request as ready for review October 11, 2026 23:56
@baxen
baxen requested a review from a team as a code owner October 11, 2026 23:56
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 11, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-12T00:02:31.323020Z 430392d Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 430392dd1e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +120 to +123
const calls = [
...text(input).matchAll(
/tools\.([A-Za-z0-9_]+)\(\s*(?:\{\s*"?text"?\s*:\s*("(?:[^"\\]|\\.)*"))?/g,
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive posted messages from completed tool records

This regex treats any tools.buzz__send(...) text in an exec program as a successfully posted message, even when it is in a comment, an untaken branch, or after an earlier statement that throws. It also misses non-Code-Mode calls where item.name === "buzz__send", which the Codex session documentation explicitly identifies as a supported call shape. As a result, the diagnostic can both invent and omit Buzz replies; derive these entries from recorded completed tool-call events/results rather than matching JavaScript source.

Useful? React with 👍 / 👎.

Comment thread scripts/session-debug.mjs
Comment on lines +60 to +63
return (
new RegExp(`^Thread root: ${id}\\s*$`, "m").test(body) ||
new RegExp(`^Event ID: ${id}\\s*$`, "m").test(body)
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restrict fallback matches to Buzz envelope sections

For Claude transcripts, these fallback regexes scan the entire user message rather than the <context> or current <buzz-event> section. If quoted history or the current request text contains a standalone Thread root: or Event ID: line for the requested ID, that unrelated session becomes a candidate and may be selected by default, contrary to the documented promise that discovery ignores quoted history. Parse the semantic prompt sections and match only the routing context or current event metadata.

Useful? React with 👍 / 👎.

Comment thread scripts/session-model.mjs
},
turns,
timing: wallTiming(records, turns, provider),
raw: records.map(publicRecord),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Stop returning unused raw transcripts on every poll

Every one-second /state poll includes a recursively copied version of the complete transcript here, although session-debug-client.js never reads state.raw; the browser still parses it and then stringifies the entire response again for change detection. For long-lived sessions this needlessly transfers and processes potentially tens of megabytes each second, making the live viewer increasingly unresponsive. Omit raw from the polling response or load it only through an explicit on-demand endpoint.

Useful? React with 👍 / 👎.

@wesbillman wesbillman left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Three new P2s inline: Claude sends displayed as posted without confirmation, live refresh dropping chart focus, and keyboard activation failing to jump from timing segments. I also corroborated the existing Codex send-parsing, thread-discovery, and stopped-agent cleanup findings; linked rather than duplicated.

Star Lord automated source review via Wes’s account. Head 430392dd1e5dcc23adaf5343e0cac8bb02a96ab4; base 10ddcc861ee20ab75c9537aacaac44ecde277a31. Source-only: no tests, viewer/app execution, or CI verification; rendered/browser and native acceptance remain unverified.

/(^|__)buzz__send$/.test(block.name) &&
typeof block.input?.text === "string"
) {
entries.push(entry.sent(timestamp, block.input.text));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Confirm Claude delivery before rendering a send as posted

This branch replaces every buzz__send invocation with a “posted to Buzz” card without consulting the results map. If publication is rejected, the recorded tool_result.is_error and its explanation are therefore discarded; a still-pending send is also shown as delivered. That makes the diagnostic viewer report success precisely when someone is investigating a missing reply. Preserve the pending/failed tool row and show a posted card only when the recorded result confirms success. The analogous Codex-side issue is already covered in this finding.

Comment on lines +229 to +231
if (force || chartHtml !== html) {
$("timeline").innerHTML = html;
chartHtml = html;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Preserve chart focus across live refreshes

While an explicit turn is running, wallTiming() extends its end to the current time on every poll. The resulting duration/geometry changes this HTML every second, so this assignment destroys all chart buttons, including the one a keyboard user has focused. The focus restoration in render() only handles descendants of details, not these buttons, so focus drops out of the chart during normal live use. Reconcile chart controls by stable activity identity, or restore the focused chart control without stealing focus, and cover a refresh while a chart button is focused.

Comment on lines +405 to +407
$("timeline").addEventListener("click", (event) => {
const target = targetAt(event);
if (target) jumpTo(target);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Use the activated chart button for keyboard clicks

Enter/Space activation of a focused segment button produces a click with no meaningful pointer coordinates (normally 0,0). targetAt() handles marks directly, but for segments it instead checks clientX against the bar position; at the normal positive left offset this returns closest(".idle-break"), which is null for a segment. Consequently keyboard users can focus a timing segment and see its details but cannot jump to its record. Prefer the clicked [data-seg]/[data-mark] button, using coordinate hit-testing only for the enlarged pointer target.

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.

2 participants