Skip to content

Release: dev → main (inspector header redesign + feed bug fixes)#1138

Merged
cgcardona merged 63 commits into
mainfrom
release/dev-to-main-20260316
Mar 16, 2026
Merged

Release: dev → main (inspector header redesign + feed bug fixes)#1138
cgcardona merged 63 commits into
mainfrom
release/dev-to-main-20260316

Conversation

@cgcardona

Copy link
Copy Markdown
Owner

Summary

Merge conflicts resolved — dev improvements kept over main's older versions.

Inspector Header Redesign (PR #1134)

  • Zone A (Issue Identity): restructured toolbar — issue number + action cluster on top row, prominent title, label chips + colour-coded status badge row.
  • Zone B (Execution State): exec strip showing role chip, tier badge (engineer/vp/cto with distinct colours), step count, human-readable run duration (ran 8m 23s), branch name. Pulsing dot + "Currently: …" row for active runs.
  • Zone C (Agent Attribution): persona card as a compact horizontal strip — oversized emoji / name + archetype / skill chips / arrow link.
  • Extended AgentRun TS interface with steps_completed, spawned_at, last_activity_at, current_step, branch, cognitive_arch. Added formatRunDuration() helper with live clock for active runs.
  • 8 new unit tests for formatRunDuration.

Toolbar Simplification (PR #1135)

  • Removed transcript and cognitive-architecture icon links from the toolbar.
  • Persona card arrow links to /agents/{run_id} (agent transcript page). run_id passed to template server-side.
  • Deleted dead __icon-link SCSS block.

Activity Feed Clear on Card Switch (PR #1136)

  • Bug fix: switching issue cards left the previous run's feed rows visible. Added clearFeed() to activity_feed.ts and call it in onInspect() and clearInspect().
  • 3 regression tests.

Conflict resolution

All 6 conflicts were between dev's new inspector code and main's older versions of the same files. Accepted dev (HEAD) in every case. All checks pass: mypy clean, tsc clean, 291 tests pass, bundles build.

cgcardona and others added 30 commits March 15, 2026 23:03
chore: sync dev with main merge commit (fast-forward)
.build-issue__branch already had white-space: nowrap + overflow: hidden +
text-overflow: ellipsis + max-width: 100%, but the truncation never fired.
Root cause: .build-issue__pr-row had align-items: flex-start inherited from
its flex-column parent (.build-issue__footer), which shrinks the row to its
content width. max-width: 100% then resolves against that already-oversized
parent and does nothing.

Fix: add width: 100% to .build-issue__pr-row so the percentage resolves
against the card width, not the branch name's intrinsic length.
fix: branch name truncates to card width (not hardcoded length)
… local model name

Three cosmetic/correctness fixes to the llm_iter row in the activity feed:

1. Remove color-coded left borders from all non-error activity rows.
   The border-left-color rules by subtype added visual noise without meaning.
   Only error rows (border-left: #ef4444) and shell exit-nonzero rows keep a
   coloured border because those carry real signal.

2. Drop the 'Iteration N' second line from llm_iter rows.
   The step count already establishes position; the iteration number inside a
   step is redundant. buildIterSummary now renders a single .af__iter-model
   span. Matching SCSS removes the flex-direction: column layout and the
   now-unused .af__iter-num selector.

3. Fix 'Local: local' — show the actual Ollama model name.
   Two root causes:
   a) Backend (llm.py): local_llm_tool_call emitted llm_iter with 'model: model'
      (the default parameter 'local') instead of 'model: agent_model or model'
      (the resolved settings value, e.g. 'qwen2.5:7b').
   b) Frontend (format_utils.ts): parseModelInfo had no handling for Qwen,
      Llama, Mistral, Phi, DeepSeek, or Gemma model strings from Ollama.
   Now: 'qwen2.5:7b' → { network: 'Local', modelShort: 'Qwen 2.5' } →
   display 'Local: Qwen 2.5'. 'local' (fallback) → modelShort '' → display
   just 'Local' (no redundant ': local' suffix).
fix: activity feed — remove color borders, drop iteration count, fix local model name
…in Docker

Tool rows (tool_invoked, github_tool) now expand on click to show the full
parsed arguments inline below the row:
- 4-column grid adds a chevron (af__chevron) that rotates 90° when open
- Click (or Enter/Space) toggles aria-expanded and the hidden detail panel
- af__tool-detail shows each arg as key · value using af__detail-key /
  af__detail-val; falls back to raw preview if parsing fails
- Keyboard-accessible: role=button, tabindex=0
- Light and dark mode styled
- 5 new unit tests covering expand, collapse, key-value rendering, and
  non-expandable row types

Also fixes a long-standing Docker gap: vitest.config.ts was never copied into
the image (only package.json, tsconfig.json etc. were). Without the config
Vitest used default include patterns (**/*.spec.ts) which picked up the
Playwright E2E spec and poisoned the jsdom environment for all other tests.
Fix: add vitest.config.ts to the Dockerfile COPY step. The config also gains
an explicit exclude for agentception/tests/** to prevent future E2E spec
pickup regardless of Vitest version changes.
feat: expandable tool call rows in activity feed
- llm_iter rows are suppressed entirely; instead a single .af__model-header
  element is inserted once at the top of #activity-feed showing the run model
  (e.g. "Local: Qwen 3.5") so it is not repeated on every step
- llm_usage rows are suppressed; their token count is injected directly into
  the .event-card__tokens placeholder on the current step header, appearing
  right-aligned on the same line as "STEP N"
- Removed per-subtype indentation from tool/file/shell/git_push rows — they
  are now flush with the rest of the feed since llm_iter is no longer a
  visual parent
- step_context: track _currentStepHeader; export getCurrentStepHeader()
- event_card: add empty .event-card__tokens span to step_start cards
- SCSS: .af__model-header styles, .event-card__tokens styles, pruned dead
  llm_iter/llm_usage overrides, updated .af__tool-detail padding
- 250 tests passing, zero type errors
feat: model info in feed header; token count on step header; remove tool indent
fix: colon separator in tool summary rows
fix: sans-serif colon separator; 0:00 timestamp instead of 'now'
…e entry

- Add humanizeDetailKey() to format_utils with a 40-key label map
  (n_results→results, cmd_preview→command, old_string→find, etc.)
- buildToolDetail uses humanizeDetailKey for all rendered keys
- start_line + end_line are collapsed into a single "lines: N–M" entry
  instead of two separate rows
- 260 tests passing, zero type errors
feat: humanize detail panel key names; collapse line range
Backend:
- FileReadPayload gains content_preview: NotRequired[str]
- read_file_lines emits first 10 lines / 400 chars as content_preview

Frontend:
- file_read rows are now expandable (click chevron to reveal preview)
- buildFileReadDetail renders content_preview in a scrollable <pre> block
- Falls back to a "no preview" note for historical events without the field
- .af__content-preview SCSS: compact code block, max-height 10rem, scrollable
- 263 tests passing, zero mypy errors, zero tsc errors
feat: file content preview in file_read activity events
Backend:
- DirListedPayload TypedDict: path, entry_count, entries (newline-delimited)
- dir_listed added to ACTIVITY_SUBTYPES
- agent_loop: emit dir_listed after successful list_directory with
  proper isinstance narrowing for JsonValue typing

Frontend:
- folder SVG icon added to icons.ts
- dir_listed: expandable row (folder icon, "N entries" summary)
- buildDirListedDetail renders entries as a pre block via af__content-preview
  (same SCSS reused from file_read content preview)
- 267 tests passing, zero mypy errors, zero tsc errors
feat: dir_listed activity event — show list_directory results in inspector
- Increase arg_preview 120→500 chars and text_preview 200→1500 chars so
  full LLM reply text and complete tool args fit without truncation.
- Make llm_reply rows expandable: clicking reveals the full text_preview
  in a scrollable prose block (af__content-preview--reply).
- Suppress the internal `collection` key (Qdrant collection name) from
  all tool detail panels via HIDDEN_DETAIL_KEYS.
- Render old_string/new_string pairs as a colour-coded find/replace diff
  block (af__diff-block--old / --new) instead of raw key-value lines.
- SCSS: add diff block styles with red/green tints for find/replace, and
  a wrapping prose variant for LLM reply previews.
- Tests: 8 new assertions covering llm_reply expand, diff rendering, and
  collection suppression — 271 tests passing.
feat(feed): llm reply expandable, search humanisation, code diff display
Adds scripts/retrofit_activity_events.py — idempotent back-fill for two
event types added after existing runs were recorded:

- dir_listed: reconstructs 29 events across 3 runs from tool result rows
  in agent_messages (entries list stored in raw JSON).
- llm_reply text_preview: extends 2 events whose previews were truncated
  at 200 chars to the new 1 500-char limit using the matching assistant
  message in agent_messages.

Safe to re-run; no-ops when there is nothing left to do.
Usage: docker compose exec agentception python3 /app/scripts/retrofit_activity_events.py [--dry-run]
feat(scripts): retrofit historical activity events
dir_listed is a result, not a peer event. Instead of rendering a separate
folder-icon row, inject directory entries directly into the detail panel
of the preceding list_directory tool_invoked row:

- Remove dir_listed from EXPANDABLE_SUBTYPES.
- Add injectDirListedIntoPanel(): finds the nearest [data-list-dir-target]
  panel in the current step container and appends an 'entries' key row +
  pre block.
- Tag list_directory tool_invoked detail panels with data-list-dir-target
  so the injector can find them.
- Route dir_listed events to the injector then return (no standalone row).
- Tests: replaced 4 dir_listed-as-row tests with 3 nesting-behaviour tests.
  270 tests passing.
feat(feed): nest dir_listed entries inside list_directory row
Same pattern as dir_listed / list_directory:

Backend:
- Add SearchResultsPayload TypedDict and 'search_results' to ACTIVITY_SUBTYPES.
- After search_codebase: emit search_results with deduplicated relative file
  paths from match objects.
- After search_text: emit search_results by parsing rg --heading output to
  extract file path lines.

Frontend:
- Tag search_codebase / search_text tool_invoked detail panels with
  data-search-target.
- Route search_results events to injectSearchResultsIntoPanel(), which finds
  the nearest data-search-target panel and appends a 'files' label + pre block.
- No standalone row created — results live inside the search row chevron.
- Tests: 4 new assertions; 274 tests passing.
feat(feed): show search result files nested inside search rows
Adds _backfill_search_results() to retrofit_activity_events.py:
- Finds runs with search_codebase/search_text tool_invoked events but no
  search_results activity events.
- Reconstructs file lists from agent_messages tool results: structured
  matches array for search_codebase, rg --heading output parsing for
  search_text.
- Matches invocations to results sequentially (same strategy as dir_listed).

Ran live: 61 search_results events inserted across 3 historical runs.
Script remains fully idempotent.
feat(scripts): retrofit search_results for historical runs
Three fixes:

1. Injection scope: search the full feed element (not just the current
   step container) when injecting dir_listed and search_results. This
   makes injection resilient to step-boundary timing edge cases where
   the step context changes between the tool_invoked and result events.

2. Label: n_results → 'limit' in ARG_KEY_LABELS. The param is the
   request cap, not the count of matches found. Showing 'results: 10'
   implied 10 results were found rather than requested.

3. Retrofit timestamps: search_results events now anchor to
   invocation.recorded_at + 1 s (not the tool result timestamp) to
   guarantee they sort strictly after their tool_invoked event. The
   script purges and re-inserts to fix the previously stored events.

274 tests passing.
AgentCeption Bot and others added 28 commits March 16, 2026 01:09
Every tool call in the inspector feed now shows its output when expanded:

shell_done: stdout_preview (first 30 lines / 2 000 chars) + stderr_preview
are added to the shell_done payload and injected into the preceding
run_command tool_invoked detail panel (data-shell-output-target).

github_result: a new activity event type emitted after every GitHub MCP
call carries result_preview (first 30 lines / 2 000 chars of the MCP
response text) and is injected into the preceding github_tool detail panel
(data-github-result-target).

Retrofit inserts lorem-ipsum placeholders for both new event types on
historical runs so the UX can be validated immediately.

280 tests passing.
feat: output preview for every tool call (shell + GitHub MCP)
- Compute MD5 fingerprint of app.js at server startup and embed as ?v=
  query string on all CSS/JS asset URLs so the browser always loads the
  latest bundle after every npm run build without a manual cache clear.
- Add _backfill_missing_shell_done to retrofit script: inserts placeholder
  shell_done events (with lorem-ipsum stdout_preview) for run_command
  invocations that have no shell_done event at all (emitted by older code
  that skipped the event). Matched 3 unmatched invocations and inserted
  placeholders so the shell-output injection panel receives content.
feat: asset cache-busting + retrofit missing shell_done events
…ind_call_sites

All four tools now emit output events on success so the inspector shows
real content rather than just the arguments:

- read_file_lines → file_read event (content_preview, first 20 lines/1500 chars)
- read_symbol     → file_read event (symbol body, same limits)
- read_window     → file_read event (windowed content, same limits)
- find_call_sites → search_results event (unique file paths from rg output)

Frontend: extend data-file-read-target tagging to read_symbol and
read_window panels; add data-search-target to find_call_sites panels.
Add humanised labels "Read symbol", "Read window", "Find usages" to
TOOL_LABELS so the feed row summary reads naturally.
feat: output preview for read_file_lines, read_symbol, read_window, find_call_sites
…og arch

- Remove icon links from Kanban card; move them to inspector toolbar
- Add transcript and cognitive-arch icon links to the inspector header
- Add inline persona mini-card to inspector panel (HTMX lazy-loaded via
  new GET /ui/runs/{run_id}/persona-card endpoint + _persona_card.html)
- Replace raw Timeline section on agent detail page with the same rich
  activity-feed SSE stream already used in the inspector panel
- Add agentDetailFeed() Alpine component in build.ts; export from app.ts
- Polish cognitive_arch.html: wrap Prompt Prefix in a collapsible
  <details> element; improve hero panel, atom pills, section labels,
  skill chips and light-mode friendliness in _agent-detail.scss
- Add agent-feed-section / agent-feed__feed SCSS for the standalone feed
- Add persona-card SCSS in _inspector-layout.scss
…lish

feat: inspector + agent pages polish — persona card, activity feed, cog arch
The Timeline section in agent.html was replaced by the SSE-driven
activity feed in the previous commit, so get_agent_events_tail,
AgentEventRow, _event_detail_text, _event_icon, and processed_events
are now unreachable dead code. Remove them all.
fix: remove dead events fetching code from agent detail route
The chain of thought is already surfaced in the rich activity feed
(SSE stream) above.  The raw Conversation disclosure block — which
rendered every user/assistant message as a collapsible pre block —
is redundant and visually noisy.

- Remove the Conversation <details> section from agent.html
- Drop db_messages fetching from get_agent_run_detail in agent_detail()
- Remove the messages list build, the "messages" template context key,
  and the AgentMessageRow import from the main page route
- Leave the agent_transcript_partial endpoint untouched (it is a
  separate HTMX route with its own logic)
fix: remove Conversation section from agent detail page
fix: persona card profile link — same tab, stable hover colour in light mode
Move Presets and Launch buttons before the mode-toggle in the DOM.
od-header__title has flex:1 so the right-side cluster is packed against
the right edge. With Toggle and Close always the last two items in that
cluster, they stay at identical pixel positions regardless of whether
Presets/Launch are rendered. No SCSS change needed.
fix: stable org designer toolbar — Toggle and Close never shift position
Place Presets and Launch buttons before the flex:1 title spacer so they
expand leftward into the title gap. Everything to the right of the title
(initiative, save-as, toggle, close) stays at exactly the same pixel
positions in both Live and Design mode — no layout shift whatsoever.
…unch

fix: Presets + Launch on left side of org designer toolbar
fix: keep Agent Org anchored far-left in org designer toolbar
Co-authored-by: AgentCeption Bot <agent@agentception.io>
Zone A (Issue Identity): restructured toolbar to show a top row with issue
number + actions cluster, a prominent title, and a labels + status badge row.
Labels are filtered (no phase-* or initiative slugs, max 3) and displayed as
chips alongside the colour-coded status badge pushed to the right.

Zone B (Execution State): replaced the thin run-meta bar with a dedicated
exec strip showing role chip, tier badge (engineer/vp/cto with distinct
colours), step count, human-readable run duration (e.g. "ran 8m 23s"), and
the branch name. A pulsing dot + "Currently: …" row appears for active runs.

Zone C (Agent Attribution): persona card redesigned as a compact horizontal
strip — oversized emoji / name + archetype / skill chips / arrow icon link.

Data pipeline: extends AgentRun TS interface with steps_completed,
spawned_at, last_activity_at, current_step, branch, cognitive_arch (all
already carried by RunForIssueRow in the backend). Adds formatRunDuration()
helper with live setInterval clock for implementing/reviewing runs. Adds
filteredLabels getter using window._buildInitiative to strip noise labels.

Removes dead __run-meta, __run-since SCSS. Adds 8 unit tests for
formatRunDuration.
feat: redesign inspector header into three information-rich zones
…ranscript

Remove the transcript and cognitive-architecture icon links from the inspector
toolbar — they added visual noise and duplicated the persona card arrow.

The persona card arrow (→) now links to /agents/{run_id} (the agent
transcript page) instead of the cognitive architecture page. Pass run_id to
the _persona_card.html template context so the link can be rendered
server-side. Delete dead __icon-link SCSS block.
fix: remove icon links from toolbar; persona card arrow links to transcript
Switching cards called _closeStream() but never wiped the #activity-feed
element, so rows from the previous run bled into the newly selected card
(or remained visible when a card with no run was selected).

Add clearFeed() to activity_feed.ts — wipes #activity-feed innerHTML and
calls resetFeedSession() — then call it from onInspect() and clearInspect()
in buildPage(). Add 3 regression tests for clearFeed behaviour.
fix: clear activity feed DOM when switching between inspector cards
All conflicts were between dev's inspector header redesign / feed fixes and
main's older versions of the same files. Accepted dev (HEAD) in every case:

- build.html: three-zone inspector layout (no icon links)
- _inspector-layout.scss: new Zone A/B/C styles (no __icon-link / __run-meta)
- _persona_card.html: compact horizontal strip linking to transcript page
- build_ui.py: pass run_id to persona card template
- build.ts: include clearFeed import
- activity_feed.test.ts: include clearFeed regression tests
@cgcardona cgcardona merged commit e5649ae into main Mar 16, 2026
4 checks passed
@cgcardona cgcardona deleted the release/dev-to-main-20260316 branch March 16, 2026 15:52
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