feat(stella-observatory): inspect a turn on its own page, not in a drawer - #2055
Conversation
…awer The execution drawer was the wrong container for what it held. A reconstructed prompt and a prompt diff are the widest text this product produces, and it gave them min(680px, 94vw) at 12px, reached by clicking an unmarked table row, with the diff two disclosures deep and no URL to reload or share. Inspecting a turn is now a route: `#transcript/<execution>`, a full-width page with a sticky section rail, the type one step up the scale, prev/next through the owning session's turns, and the newest call's prompt diff open on arrival. The diff itself is drawn the way a reviewer reads one — both line-number gutters, tinted rows rather than colored glyphs alone. The descent that led there is made visible too: the sessions and turn tables carried no cursor, no hover, and a `sel` class no stylesheet defined, while the panel a click revealed opened below the fold. Every payload is unchanged — the same four endpoints, the same lazy per-call reconstruction. `/api/execution` gains one field, `session_id`, without which a transcript reached by URL alone cannot name its session or step to the turns either side of it.
…date the docs Verified against this workspace's own store: a real turn records 202 receipts, so the picker scrolls in a fixed box with the lit row pulled into view, and the diff opens directly beneath it. Also drops a duplicated running badge, restores the address bar when a route is rejected, and repairs three stale claims in the docs the change touched: the tab count, the drawer, and the fixture's session_id divergence.
…ot just the tab A bare '#transcript' is not a route either, so restoring to state.tab alone left the address in a state that would not survive a reload.
There was a problem hiding this comment.
Sorry @macanderson, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
Reviewer's GuideReplaces the execution-detail drawer with a full-page transcript route (#transcript/) including a sticky section rail, context/diff tooling, keyboard navigation, and URL-based routing, updates styles and accessibility for sessions/turns tables, wires both Overview and Sessions to the new route, extends the /api/execution DB query and test schema to expose session_id for deep-linked transcripts, and updates docs/README plus adds tests to witness the new behavior and schema. Sequence diagram for navigating to the new transcript pagesequenceDiagram
actor User
participant Dashboard as BrowserDashboard
participant API
User->>Dashboard: click executions row
Dashboard->>Dashboard: goTranscript(id)
Dashboard->>Dashboard: location.hash = "transcript/" + id
Dashboard-->>Dashboard: hashchange
Dashboard->>Dashboard: routeTo(location.hash)
Dashboard->>Dashboard: switchTab("transcript", id)
Dashboard->>Dashboard: openTranscript(id)
Note over Dashboard,API: Initial execution + folds
Dashboard->>API: api(/api/execution?id=id)
API-->>Dashboard: execution { id, session_id, ... }
Dashboard->>API: api(/api/execution-journal?id=id[&full])
Dashboard->>API: api(/api/execution-context?id=id)
Dashboard->>API: api(/api/execution-tendencies?id=id)
API-->>Dashboard: journal entries / context / tendencies
Note over Dashboard,API: Load sibling turns for prev/next
Dashboard->>Dashboard: txLoadSiblings(execution.session_id)
Dashboard->>API: api(/api/session?id=session_id)
API-->>Dashboard: session.turns[]
Dashboard->>Dashboard: render transcript head, rail, sections
Dashboard->>Dashboard: loadContextDiff(id, turn, step, call_seq)
User->>Dashboard: press ← / →
Dashboard->>Dashboard: goTranscript(siblingId)
Dashboard-->>Dashboard: hashchange (repeat routeTo/openTranscript)
Entity-relationship diagram for executions.session_id additionerDiagram
SESSIONS {
string id
}
EXECUTIONS {
int id
string session_id "nullable"
}
SESSIONS ||--o{ EXECUTIONS : "has turns"
EXECUTIONS }o--|| SESSIONS : "execution.session_id"
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
What & why
Inspecting a turn in the Observatory happened in a right-hand drawer. That was the
wrong container for what it held. A reconstructed prompt and a prompt diff are the
widest text this product produces, and the drawer gave them
min(680px, 94vw)at12px, reached by clicking an unmarked table row, with the diff two disclosures deep
and no URL to reload or share. The path to it was invisible too: the sessions and
turn tables carried no cursor, no hover, and a
selclass no stylesheet defined,while the panel a click revealed opened below the fold — so a click read as a click
that did nothing.
Inspecting a turn is now a route:
#transcript/<execution>.12px to 13px with reading line-height, at page width instead of a third of it.
arrival — the newest, because a role's first call has no previous call to diff
against and renders the entire prompt as one wall of additions. The diff is drawn
the way a reviewer reads one: both line-number gutters, and tinted rows rather than
colored glyphs alone (hue is never the only signal — BRAND.md).
workspace records 202 receipts, so it scrolls in a fixed box with the picked row
lit and pulled into view, above the panel it drives.
tr.clickon both tables, a goldturns ↓/open ↗cell that names what a row does, a real selected-row style, and a scrollto the panel a click just revealed.
Every payload is unchanged — the same four endpoints, the same lazy per-call
reconstruction, the same
after_seqlive append. One field is added to/api/execution:session_id. Without it a transcript reached by URL alone can nameneither its session nor the turns either side of it.
Exemplar for the route grammar: none needed — it is
#<tab>/#<tab>/<arg>, thesame shape the page already used for tabs, extended by one argument. The diff view
follows git's own hunk presentation, which is what the served endpoint already emits.
The witness
main, passes here)Two, one per half:
execution_detail_carries_its_session_id— asserts/api/executionservessession_id, and that the key survives asnull(not as a missing key) for a runrecorded before schema v8 stamped it, because the page distinguishes "no session"
from "field not served". On
mainthe execution head selects nine columns andsession_idis not among them, so the first assertion fails.inspecting_a_turn_is_a_page_not_a_drawer— asserts the transcript panel and itsroute exist, that both drill paths navigate to it, and that the drawer is gone
rather than merely bypassed (a second, stale way in is how two renderings of the
same data drift apart). On
main,id="drawer"is present anddata-tab="transcript"is not.The second is a structural witness and does not claim the page renders right;
that is not decidable from Rust. It was verified by driving the served dashboard in
headless Chrome over CDP against this repository's own
.stella/private/store.db— real sessions, real receipts, real 202-call turns:#transcript/83cold, no session list in memory+48 −0#transcript/73cold (turn 3 of 4)session_idalone; ← and → both enabled; all 6 sections including Reflection#transcript/76(session_idNULL, no receipts)#transcript/999999#transcript/notanumber#transcript/83→#sessions, tab re-hidden, panel clearedScreenshots of the transcript page and the Sessions tab were reviewed.
The gate
cargo fmt --checkcargo clippy --workspace --all-targets -- -D warningscargo test --workspacemake gate CARGO_SCOPE="-p stella-observatory"exits 0.Docs:
website/content/docs/telemetry/dashboard.mdxloses its drawer paragraph andgains
sessionsandtranscriptcards; the crate README gains the route grammar.Three stale claims the change touched are repaired in the same PR — the doc's tab
count (said nine, was eleven before this PR), the README's
seeded_workspacelocation (
src/lib.rs→src/tests.rs), and its list of store columns the fixturediverges on, which named
session_idand no longer can.Nothing left behind
Filed: stella-cli: dead DiagnosticInvocation/DiagnosticRunner imports warn on every shipping-binary build, and no gate configuration can see them #2053, stella-observatory: the transcript page renders every journal entry eagerly — 3,289 nodes and 1.1MB of HTML on a real turn #2054
stella-observatory: the transcript page renders every journal entry eagerly — 3,289 nodes and 1.1MB of HTML on a real turn #2054 — the transcript page renders every journal entry eagerly: measured on a
real turn in this workspace, 3,289 nodes and 1.1MB of HTML. Inherited from the
drawer, which built the same list from the same payload, but the page makes it the
primary surface. Options and a definition of done are in the issue.
stella-cli: dead DiagnosticInvocation/DiagnosticRunner imports warn on every shipping-binary build, and no gate configuration can see them #2053 —
cargo build -p stella-cli --bin stellawarns on two dead imports inagent/tools.rs. Noticed while running the gate here; this branch touches nostella-clifile, so it is inherited frommain(6bc6a072). It is the fix(stella-cli): drop imports left unused when the diagnostic impl moved out #2045shape:
clippy --all-targetscompiles the tests, where the names are used, so nogate configuration can see it.
Ground-rule check
stella-core; no new deps(
dashboard_html_has_no_external_referencesstill passes)Anything reviewers should know?
Sessions turns) now navigate to the page, and the witness asserts no drawer
survives. If you would rather keep an overlay for the Overview table, say so — but
two renderings of the same four endpoints is exactly the drift this repo files
issues about.
leave. It is a child route of Sessions, not a section you visit; an always-present
tab with nothing in it is a dead end. The consequence is that the tab bar's
roving-tabindex arrow keys now walk
visibleTabs(), since focus must never park ona
hiddenbutton.call was given is the question the drawer buried deepest, and the rail makes both
one click away regardless.
markCtxRowscrolls the picker box by settingscrollToprather than callingscrollIntoView, which walks every scrollable ancestor — on arrival that wouldscroll the page to reach the list, which is the below-the-fold jump this page
exists to remove.
Summary by Sourcery
Replace the execution detail drawer with a dedicated transcript page route and update backend, UI, tests, and docs to support deep-linked turn inspection.
New Features:
#transcript/<execution>with sections for context, transcript, steps, tools, files, and reflection.Bug Fixes:
Enhancements:
Documentation:
Tests:
/api/executionincludessession_idand that the transcript page and its routes exist while the old drawer implementation is fully removed.Chores:
executions.session_idnow that the observatory reads it from the store.