Skip to content

feat(observability): session context inventory — span attrs + context consumed banner#410

Open
dimakis wants to merge 5 commits into
mainfrom
feat/tool-input-span-attrs
Open

feat(observability): session context inventory — span attrs + context consumed banner#410
dimakis wants to merge 5 commits into
mainfrom
feat/tool-input-span-attrs

Conversation

@dimakis

@dimakis dimakis commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

Two independent workstreams for session context inventory:

WS1: Enriched Jaeger traces

  • New getToolInputSpanAttrs() extracts structured, searchable span attributes from tool inputs
  • Tool spans carry tool.input.file_path, tool.input.command, tool.input.pattern, tool.input.path, tool.input.query, tool.input.url, tool.input.description, tool.input.subagent_type, tool.input.skill
  • Values truncated to 256 chars, indexed by Jaeger for search/filter
  • Raw input event preserved for full detail in span view

WS2: Context consumed in session banner

  • Messages reducer accumulates context consumption from BLOCK_END events (files read, searches, web fetches)
  • Deduped by type+key, tracks repeat counts
  • Subagent tool calls included
  • Rebuilds on RESTORE (reconnect/session switch), resets on CLEAR
  • Renders as collapsible "Context Consumed" section in SessionBanner
  • Collapsed summary shows unique context count alongside boot context stats

Test plan

  • 15 new tool-summary-attrs tests (all tool types, edge cases, truncation)
  • 7 new messages-slice tests (accumulation, dedup, multi-type, subagents, RESTORE, CLEAR)
  • Deploy and verify span attrs appear in Jaeger UI
  • Verify context consumed section renders in session banner

🤖 Generated with Claude Code

@dimakis dimakis left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Centaur Review

Found 1 issue(s).

packages/protocol/src/tool-summary.ts

Clean, well-tested feature addition. The new function follows existing patterns in tool-summary.ts, tests are thorough (all tools, edge cases, truncation, unknowns), integration in query-loop.ts is correct, and exports are properly wired. Only a minor style nit on collapsible switch cases.

  • 🔵 style (L79): The Read, Write, Edit, and StrReplace cases all extract the same file_path field — they can be collapsed into a single fallthrough block (case 'Read': case 'Write': case 'Edit': case 'StrReplace':), matching how Edit/StrReplace are already grouped. Same applies to Glob/Grep (both extract pattern + optional path). [fixable]

};

switch (toolName) {
case 'Read':

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

🔵 style: The Read, Write, Edit, and StrReplace cases all extract the same file_path field — they can be collapsed into a single fallthrough block (case 'Read': case 'Write': case 'Edit': case 'StrReplace':), matching how Edit/StrReplace are already grouped. Same applies to Glob/Grep (both extract pattern + optional path). [fixable]

@dimakis dimakis changed the title feat(tracing): tool.input.* span attributes for Jaeger search feat(observability): session context inventory — span attrs + context consumed banner Jun 27, 2026
@dimakis

dimakis commented Jun 27, 2026

Copy link
Copy Markdown
Owner Author

Centaur Review

Found 5 issue(s) (1 warning).

frontend/src/pages/DesktopChatView.tsx

Solid feature — well-tested reducer logic and clean span attribute extraction, but DesktopChatView is missing the contextConsumed prop, leaving desktop users without the new UI section.

  • 🟡 regressions (L244): DesktopChatView renders ChatArea but does not extract or pass contextConsumed from the store, unlike ChatView (which does at line 56/286). Desktop users will never see the context consumed section in SessionBanner. Likely needs const contextConsumed = useMitzoStore((s) => s.messages.contextConsumed); and contextConsumed={contextConsumed} on the ChatArea call. [fixable]

packages/client/src/slices/messages.ts

Solid feature — well-tested reducer logic and clean span attribute extraction, but DesktopChatView is missing the contextConsumed prop, leaving desktop users without the new UI section.

  • 🔵 style (L535): CLEAR handler explicitly sets contextConsumed: [] but this is already the value in INITIAL_MESSAGES_STATE (which is spread on the same line). The override is redundant. [fixable]
  • 🔵 style (L37): In extractContextEntry, the input ? ternary checks on lines 37/40/41/42 are redundant — line 34 already returns null when !input. Each case can simply return the object directly. [fixable]

packages/protocol/src/tool-summary.ts

Solid feature — well-tested reducer logic and clean span attribute extraction, but DesktopChatView is missing the contextConsumed prop, leaving desktop users without the new UI section.

  • 🔵 style (L81): Read/Write cases can be merged with Edit/StrReplace since all three just set('file_path', input.file_path). This would reduce the switch from 5 case arms to 3 (e.g. case 'Read': case 'Write': case 'Edit': case 'StrReplace':). [fixable]
  • 🔵 bugs (L73): String(val || '') coerces falsy non-string values (0, false) to empty string, silently dropping them. In practice this is harmless since all currently extracted fields are strings, but String(val ?? '') would be more precise and future-proof. This matches the idiom used elsewhere in the codebase. [fixable]

dimakis and others added 3 commits July 1, 2026 09:18
Tool spans now carry structured, searchable attributes (file_path,
command, pattern, path, query, url, description, skill) alongside the
existing raw input event. This makes tool calls filterable in Jaeger UI
without expanding individual span events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Accumulate runtime context consumption (files read, searches, web
fetches) from BLOCK_END events in the messages reducer, deduped by
type+key. Renders as a collapsible section in SessionBanner with
grouped entries and repeat counts. Collapsed summary shows total
unique context items. Rebuilds on RESTORE, resets on CLEAR. Includes
subagent tool calls.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@dimakis
dimakis force-pushed the feat/tool-input-span-attrs branch from 6347865 to 8b1451d Compare July 1, 2026 08:19
dimakis and others added 2 commits July 2, 2026 00:22
Collapse Read/Write/Edit/StrReplace and Glob/Grep cases in
getToolInputSpanAttrs and summarizeToolInput where they perform
identical operations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Wire contextConsumed into DesktopChatView (desktop users now see
  context consumed banner)
- Remove redundant input? ternaries in extractContextEntry
- Remove redundant contextConsumed: [] in CLEAR handler
- Use val ?? '' instead of val || '' in span attr helper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@dimakis dimakis left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Centaur Review

LGTM — no issues found.

@dimakis

dimakis commented Jul 4, 2026

Copy link
Copy Markdown
Owner Author

Centaur Review

Found 4 issue(s) (1 warning).

server/query-loop.ts

Solid feature — well-tested reducer logic and clean span attribute extraction. Main gap: subagent tool spans in query-loop don't get the new getToolInputSpanAttrs attributes despite parsed input being available, creating an observability blind spot for subagent tool calls in Jaeger.

  • 🟡 bugs (L1071): Subagent tool spans don't get getToolInputSpanAttrs attributes, unlike main tool spans. The parsed toolInput is already available at line 1049 — the same getToolInputSpanAttrs call and attribute-setting loop should be added here for consistency. Without it, subagent tool calls in Jaeger are missing the searchable tool.input.* attributes and the tool.input event, making them harder to find and debug. [fixable]

packages/client/__tests__/messages-slice.test.ts

Solid feature — well-tested reducer logic and clean span attribute extraction. Main gap: subagent tool spans in query-loop don't get the new getToolInputSpanAttrs attributes despite parsed input being available, creating an observability blind spot for subagent tool calls in Jaeger.

  • 🔵 missing_tests: The contextConsumed tests cover Read, Grep, and WebFetch but never test WebSearch. The extractContextEntry function maps WebSearch → web_search, and ContextConsumedSection has a label for it, but there's no test confirming this mapping works end-to-end through the reducer. [fixable]

frontend/src/components/SessionBanner.tsx

Solid feature — well-tested reducer logic and clean span attribute extraction. Main gap: subagent tool spans in query-loop don't get the new getToolInputSpanAttrs attributes despite parsed input being available, creating an observability blind spot for subagent tool calls in Jaeger.

  • 🔵 style (L142): When bootContext and sessionContext are both null but contextConsumed has entries, the banner renders with the label "Session Context" and a warning-colored dot (session-banner-dot--warn). This is misleading — the user sees a yellow warning indicator for what is normal runtime context. Consider showing a neutral label like "Context Inventory" and a neutral dot style when only contextConsumed is present. [fixable]
  • 🔵 style (L97): In ContextConsumedSection, items use array index as the React key (key={idx}). Since each ContextEntry has a unique key field within its type group, using ${type}:${item.key} would be a more stable key — though the current approach is harmless since the list is append-only. [fixable]

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