Skip to content

feat(agent,web): Trajectory pane with complete context capture and request inspection - #1157

Draft
ChrAlpha wants to merge 94 commits into
felinics:mainfrom
ChrAlpha:feat/trajectory-view
Draft

feat(agent,web): Trajectory pane with complete context capture and request inspection#1157
ChrAlpha wants to merge 94 commits into
felinics:mainfrom
ChrAlpha:feat/trajectory-view

Conversation

@ChrAlpha

@ChrAlpha ChrAlpha commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

Adds a Trajectory dock pane for inspecting how a conversation reaches the model: collected and selected context, prepared provider input, captured HTTP request bodies, model request timing and usage, tool execution, and compaction history. It replaces the Context Lifecycle Inspector with Open Trajectory in the session info panel.

#1118 has merged. This PR targets main with only the Trajectory history: all 93 original Trajectory commits retain their order, authorship and messages, followed by one migration/test compatibility commit. The former context-usage commits and stack merge commits have been removed from the PR range.

Changes

  • Persist per-request step traces, tool timing, and bounded run rollups; expose completed requests through the live runtime view and retain them in conversation history. Include spawned runs and requests without text output.
  • Record immutable context stages across trigger/history/memory/prompt assembly, fragment collection and selection, prepared/dispatched provider input, retries, tool transformations, hooks, media, steering, background results, and child-context provenance. Continuations have distinct capture identities even when they reuse a run ID.
  • Capture supported providers' generation HTTP request bodies before dispatch, with transport outcomes linked to the request. Capture failures are surfaced explicitly; the bounded writer flushes before terminal delivery. Full captured bodies are deduplicated within session ownership and cleared with session history, including concurrent-reset protection.
  • Add paged context-stage and detail endpoints alongside lifecycle decisions, injected fragments, and compaction pagination. Full capture content and injected text require workspace_read; content reads verify the stored hashes and report completeness.
  • Extend the virtualized ledger and inspector with stage navigation, filters, full-text search, comparison, copy/export, and visible loading/access/capture failures. Keep request boundaries and fragment occurrence labels intact. The pane supports keyboard navigation, stable scrolling, a fixed inspector header, and an inspector that covers narrow panes.
  • Retain shared transcript pagination, on-demand detail reads, hidden-pane gating, and a bounded overview strip.

Database

0148_context_fragment_texts adds per-bot injected text storage; 0149_context_trajectory adds session-owned capture events and content. These follow main's 0147_context_lifecycle_selection_decisions. The canonical schema and generated SQL/API/SDK contracts are updated.

Validation

The checks below ran on the previous head. The history rewrite preserves its exact Git tree; git range-diff, commit metadata checks, and tree equality were verified after rebasing:

  • Focused Vitest run: 185 tests passed across 13 files, covering trajectory rows/components, capture paging/text, lifecycle views, query-cache persistence, and turn-end invalidation. The runner uses inline configuration with config: false and envDir: false.
  • go test passed for the affected context, application, native runtime, tools, contextview, models, handlers, and database packages.
  • Independent merge review confirmed preservation of both branches' API/SDK contracts and the recent capture/UI changes. The lifecycle migration test now anchors to versions 146/147 instead of assuming it is the latest migration.
  • go test -tags integration ./internal/db -run '^TestContext(Trajectory|Fragment|Lifecycle)' -count=1: 7 top-level tests passed on an isolated PostgreSQL 18 instance, including eight capture/reset race orderings. The race-test deadline starts after database migration setup.
  • SDK regeneration, sqlc diff, focused ESLint, migration-version uniqueness, and git diff --check passed.

Authenticated live-provider E2E and browser QA were not rerun for this update. Earlier smoke runs do not validate the newly added capture paths.

Known limits

  • Continued runs can restart their persisted step_index; the pane separates requests by their run/capture identity.
  • Tools executed after an approval decision do not yet have execution timing.
  • Capture persistence is best effort with explicit failure/completeness reporting; a recorded stage does not by itself prove every stage was captured.

QA

  1. Open a session and choose Open Trajectory. Check overview selection, ledger keyboard navigation, narrow-pane inspection, and older-history loading.
  2. Send a message with tools. Inspect context stages, prepared input and wire request bodies, request timing, tool results, and capture completeness.
  3. Search a long captured body, compare stages, and copy/export its content.
  4. Resume an approval or question, trigger a compaction, and inspect the corresponding continuation and compaction rows.
  5. Verify restricted users cannot read full captured content; clear session history and confirm old captures disappear.

⚠️ No human QA — this PR has not been verified by a human yet. Remove this line once a human confirms the happy path.

@ChrAlpha
ChrAlpha requested review from a team as code owners September 5, 2026 06:44
@ChrAlpha
ChrAlpha marked this pull request as draft September 5, 2026 06:54
@chen-ran
chen-ran force-pushed the feat/context-usage-viz branch 3 times, most recently from 9cb6824 to b7b4408 Compare September 7, 2026 20:19
@ChrAlpha ChrAlpha changed the title feat(agent,web): Trajectory pane with per-request traces, injected context texts, and compaction rows [stack 2/2] feat(agent,web): Trajectory pane with complete context capture and request inspection Sep 8, 2026
@ChrAlpha
ChrAlpha changed the base branch from feat/context-usage-viz to main September 8, 2026 18:57
Provider attempts are clocked at the provider seam (dispatch, first content
part, finish-step) and published as step_start/step_end events carrying the
request's usage and timing. The observer forwards parts like Twilight ranges
them so a cancelled provider still completes its blocked send.
Each native tool execution records started/ended wall clock under its call
ID; the timing rides tool_call_end events and the persisted tool-call part
through the existing execution metadata registry.
A step trace tracker takes finished provider steps inside the commit barrier
and stores them as step_trace metadata on each assistant row, mirroring the
reasoning timing path. Tool execution timing and terminal usage are observed
on the public event wire, which every runtime shares, and the lifecycle
snapshot gains a fixed-size run_trace rollup read at terminal time.
Persisted assistant rows expose their step_trace as UITurn.step_traces
anchored to the row's first block, tool blocks carry execution_timing, and
the live run view appends the same UIStepTrace per finished request so a
subscriber sees timing and usage while the turn is still running.
Steering interleaved at the terminal snapshot and context prepared before a
later step both persist a context_injection marker, and the history
projection surfaces it so readers can tell injected context from the
person's request.
The lifecycle list accepts an opaque before cursor bound to (created_at,
run_id) and returns next_cursor while older run-keyed rows remain, so a long
session pages in fixed-size summaries instead of widening one request. The
spec and SDK pick up the cursor together with the run trace, step trace,
execution timing, and context injection fields.
The runtime projection appends step_trace_appends onto the live run view and
drops them on reset; normalized turns keep step traces, tool execution
timing, and the context injection marker so any view can read them.
The lifecycle list joins the run ledger so each summary names the turn it
wrote into, giving readers an exact join to history turns instead of
guessing from assistant message ids.
Older lifecycle pages follow the server's next_cursor and accumulate beside
the refreshable first page, replacing the 50-to-200 limit jump.
A dockview Trajectory tab reads the session's shared transcript window and
lifecycle summaries: an overview strip with input, model, and tool lanes
(duration or sequence scale, model bars split at first token), a
virtualized ledger of system, user, context, assistant, reasoning, and
tool rows in transcript order, a local inspector for the selected record,
and a window-scoped stats line that omits anything never sampled.
… filtering

- release the observed stream when the consumer leaves after cancel
- discard finished steps a retry regenerates; fold the run rollup at commit
- stamp injected user messages at the source so steering survives filtering
- align step traces by assistant ordinal across empty-row filtering
- bound each trace by its last block id; keep run_trace off per-row copies
- clock external tool calls from their arrival at the transcript boundary
The first page keeps the plain session scan; only continuations carry the (created_at, run_id) predicate, so the planner never sees a nullable cursor.
- page lifecycle summaries only when the older page joins the loaded anchor
- keep the ledger anchored while older rows prepend; memoize row building
- continue turn numbering into the live turn; TTFT from the earliest sampled step
- rem-based virtual rows, load-older gating, error toasts, aria selection
- keep the pane alive across tab switches; close it with its deleted session
A wall-clock step between two readings produced a first token 305ms before its request in a live run. Every mark after the anchor now adds the clock's monotonic elapsed time instead of re-reading the wall clock.
isPanelAllowed had no trajectory case, so every layout restore closed the panel on reload.
The lifecycle page keeps only rolled-up counts; the trajectory inspector reads the content-light audit of one run on demand, after confirming the run belongs to the authorized session.
- the strip is DSH's row map: one segment per ledger record on its lane over the whole loaded window, duration or equal width, click focuses the row
- every turn leads with its system prompt and the context the manifest injected: rules, tool usage, skills, memory recall, history with its selection, tool definitions, mutations, and per-step reselection
- the inspector explains system and history rows with the run's per-fragment audit
- the context inspector dialog folds into the trajectory
@ChrAlpha
ChrAlpha force-pushed the feat/trajectory-view branch from d5ee3ee to 2f69352 Compare September 9, 2026 01:27
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