Conversation
Previously, action keys (silence, acknowledge, note, etc.) required pressing twice from table view because: 1. Duplicate getIncidentMsg calls in action handlers 2. waitForSelectedIncidentThenDoMsg aborting prematurely when no m.selectedIncident was set Changes: - Added getHighlightedIncident() helper to get incident from m.incidentList using the highlighted row's ID - Simplified action handlers to use highlighted incident directly (silence, ack, unack, note, open) - Updated action message handlers to try highlighted incident first, then fall back to selectedIncident - Fixed waitForSelectedIncidentThenDoMsg abort logic to check for highlighted row before aborting - Login action still fetches alerts separately as needed Actions now work on first keypress by using incident data already in memory rather than waiting for API fetch. Added comprehensive unit tests: - TestGetHighlightedIncident: Tests incident lookup from list - TestActionMessagesFallbackToSelectedIncident: Tests message handler fallback logic for ack/unack/silence 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Previously, every time the incident list was updated (initial load, after actions like acknowledge/silence), the code pre-fetched full details, alerts, and notes for ALL incidents. This resulted in O(3n) API calls per update. Why this was inefficient: - Most incidents are never viewed or acted upon by SREs - The incident list already contains sufficient data for most actions (ID, Title, Service, EscalationPolicy, Status, Assignments) - getHighlightedIncident() uses data from m.incidentList directly - Only specific actions need additional data: * Viewing incident details (needs alerts and notes) * Login action (needs alerts for cluster_id extraction) Changes: - Removed pre-fetch loop from updatedIncidentListMsg handler - Added explanatory comment documenting the optimization - Data now fetched on-demand when user actions require it: * Press Enter to view: fetches alerts and notes * Press 'l' to login: fetches alerts for cluster_id Impact: - Reduces API calls from O(3n) to O(1) per incident list update - For 10 incidents: 30 calls → 0 calls (unless viewing) - For 50 incidents: 150 calls → 0 calls (unless viewing) - Faster incident list refresh after actions - Lower PagerDuty API rate limit usage - Better user experience with less waiting Added test: - TestUpdatedIncidentListNoPrefetch: Verifies incident list updates no longer trigger pre-fetch commands 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add input mode triggered by 'i' or ':' keys - All keypresses become text input (except esc, enter, ctrl+q/ctrl+c) - Context-aware help display shows only relevant keys in input mode - Two-column help layout for input mode (esc/enter, quit) - Replace static '>' prompt with animated spinner during API operations - MiniDot spinner in pink (#205) appears when interacting with PagerDuty API - Spinner shows during: incident refresh, fetch details, acknowledge, re-escalate, silence - Status text maintains normal color to prevent spinner color bleed - Reorganize table view help display - Add Top (g) and Bottom (G) navigation keys to help - Regroup keys logically across 5 columns - Move auto-refresh/auto-ack to top of last column - Add comprehensive keymap completeness test - Validates all key.Matches calls have corresponding help entries - Parses Go AST to find key bindings in focus mode handlers - Prevents adding keybindings without updating help display 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Add bottom status bar at terminal bottom showing incident ID (left) and git SHA (right) - Create renderBottomStatus() function for status bar rendering - Add mutedStyle with dark gray color matching help text - Fix spacing calculation to handle variable help text height - Account for all UI chrome in incident viewer height calculation - Inject git SHA at build time via ldflags in Makefile and goreleaser - Create pkg/tui/version.go to hold build-time version information 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
- Fix viewport position: Always go to top when content loads to prevent blank window - Add progressive rendering: Re-render when notes, alerts, or incident details arrive - Add incident polling: Refresh viewed incident data during auto-refresh cycles - Progressive updates make the UI feel more responsive as data loads Now when viewing an incident: 1. Viewer opens immediately at top with cached/placeholder data 2. Three parallel API calls fetch incident, notes, and alerts 3. View updates progressively as each piece of data arrives 4. Incident data auto-refreshes every 15s to show new notes/alerts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…ve polling - Stop spinner when all incident data loads (incident, notes, alerts) - Remove auto-refresh of incident data during polling (was too aggressive) - Only GotoTop() on first render, not on progressive updates - Prevents viewport jumping and reduces render churn The apiInProgress flag was never being set back to false after loading incident data, causing the spinner to run forever and potentially contributing to UI sluggishness. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Changed debug.log from O_APPEND to O_TRUNC to prevent unbounded growth. The log file had grown to 1.1GB, causing massive I/O slowdown on every keypress since each key logs multiple debug messages. With a 1.1GB file, every log write was slow, making the UI feel sluggish especially during rapid navigation. Truncating on startup keeps the log fresh and performant. TODO: Implement proper log rotation for long-running sessions. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Skip logging for: - spinner.TickMsg (fires every ~80ms) - TickMsg (scheduled job ticks) - Arrow key navigation (up/down) - Redundant "priority key handling" logs These high-frequency events were generating 150+ log writes per second, and since logging is synchronous in Update(), each write blocked the UI thread. Even with a small log file, this I/O overhead degraded responsiveness. Now logging only actionable events (enter, esc, commands, API responses) which is more useful for debugging anyway. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Created asyncWriter that writes logs to a buffered channel (1000 messages) processed by a background goroutine. This prevents log I/O from blocking the Update() function. Key features: - Non-blocking writes via select statement - Drops messages if buffer is full (prevents backpressure) - Graceful shutdown waits for pending logs to flush - Eliminates I/O blocking that was causing UI sluggishness Combined with reduced logging volume and log truncation, this ensures logging never impacts UI responsiveness. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Major performance optimizations to eliminate 1-2 second render delays: - Cache glamour markdown renderer at initialization instead of creating new renderer on every incident view (was the primary performance bottleneck) - Remove excessive debug logging from focus mode handlers that logged every keypress including terminal escape sequences - Remove debug logging from frequently-called helper functions (getDetailFieldFromAlert, getEscalationPolicyKey) - Expand terminal escape sequence filtering to catch more color response fragments that were slipping through Before: Each incident view took 1-2 seconds to render due to expensive glamour.NewTermRenderer() calls, causing sluggish keypresses as users pressed keys before UI finished responding to previous input. After: Rendering is nearly instant by reusing cached renderer. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What type of PR is this?
(bug/feature/cleanup/documentation)
What this PR does / Why we need it?
Which Jira/Github issue(s) does this PR fix?
Resolves #
Special notes for your reviewer
Pre-checks (if applicable)