@kaged/ui
React 19 SPA — mobile-first web dashboard with TanStack Router/Query, Zustand state, guest routes, project config editing, and terminal viewer
154
source files
51
test files
~20.2k
lines
✓ 727 pass
tests
pass
typecheck
clean
lint
Test results 727
resolveAuthGate > pending status → loading
[0.970ms]
resolveAuthGate > success status → authenticated
[0.040ms]
resolveAuthGate > error with status 401 → auth_required
[0.030ms]
resolveAuthGate > error with status 403 → auth_required
[0.020ms]
resolveAuthGate > error with non-auth status → connection_error
[0.020ms]
resolveAuthGate > error with no status (network failure) → connection_error
[0.020ms]
resolveAuthGate > error with null error object → connection_error
[0.020ms]
resolveRoleHome > guest -> /g
[0.030ms]
resolveRoleHome > member -> /
[0.030ms]
resolveRoleHome > operator -> /
[0.010ms]
shouldRedirectForRole > guest hitting non-guest route redirects to /g
[0.060ms]
shouldRedirectForRole > guest hitting guest route does not redirect
[0.030ms]
shouldRedirectForRole > guest hitting /launch or /auth/sso/callback does not redirect
[0.020ms]
shouldRedirectForRole > member hitting guest route redirects to /
[0.020ms]
shouldRedirectForRole > member hitting system route redirects to /
[0.020ms]
shouldRedirectForRole > member hitting normal route does not redirect
[0.020ms]
shouldRedirectForRole > operator hitting guest route redirects to /
[0.010ms]
shouldRedirectForRole > operator hitting system route does not redirect
[0.020ms]
shouldRedirectForRole > operator hitting normal route does not redirect
[0.020ms]
resolveAuthFlow > sidecar → authenticated regardless of cookie
[0.040ms]
resolveAuthFlow > loopback with cookie → authenticated
[0.010ms]
resolveAuthFlow > loopback without cookie → launch_url_required
[0.010ms]
resolveAuthFlow > insecure → no_auth regardless of cookie
[0.020ms]
requiresLaunchUrl > loopback → true
[0.020ms]
requiresLaunchUrl > sidecar → false
[0.010ms]
requiresLaunchUrl > insecure → false
[0.010ms]
isInsecure > insecure → true
[0.020ms]
isInsecure > sidecar → false
[0.010ms]
isInsecure > loopback → false
[0.020ms]
projectBadge > ready → [LIVE] amber, no pulse
[0.060ms]
projectBadge > pending → [DRAFT] text-secondary with pulse
[0.030ms]
projectBadge > invalid → [CRASHED] magenta
[0.020ms]
projectBadge > all project states return a badge
[1.28ms]
projectBadge > all project badges have uppercase bracket-lock labels
[0.210ms]
sessionBadge > idle → [IDLE] dim
[0.040ms]
sessionBadge > running → [LIVE] amber
[0.020ms]
sessionBadge > paused → [PAUSED] amber-dim
[0.020ms]
sessionBadge > ended → [ENDED] magenta-dim
[0.020ms]
sessionBadge > all session states return a badge
[0.040ms]
sessionBadge > all session badges have uppercase bracket-lock labels
[0.050ms]
subagentBadge > caged → [CAGED] magenta with magenta-faint bg
[0.030ms]
subagentBadge > uncaged → [UNCAGED] magenta with magenta-dim bg
[0.020ms]
subagentBadge > idle → [IDLE] dim, no bg
[0.020ms]
subagentBadge > running → [LIVE] amber
[0.020ms]
subagentBadge > paused → [PAUSED] amber-dim
[0.020ms]
subagentBadge > blocked → [BLOCKED] magenta
[0.020ms]
subagentBadge > failed → [CRASHED] magenta
[0.020ms]
subagentBadge > all subagent badges have uppercase bracket-lock labels
[0.060ms]
resolveBanners > no flags → empty array
[0.080ms]
resolveBanners > insecure only → one banner
[0.040ms]
resolveBanners > noSandbox only → one banner
[0.020ms]
resolveBanners > both flags → two banners, insecure first
[0.030ms]
resolveBanners > insecure banner has correct text
[0.040ms]
resolveBanners > insecure banner has abbreviated mobile text
[0.020ms]
resolveBanners > no_sandbox banner has correct text
[0.020ms]
resolveBanners > no_sandbox banner has abbreviated mobile text
[0.020ms]
hasBanners > no flags → false
[0.030ms]
hasBanners > insecure → true
[0.020ms]
hasBanners > noSandbox → true
[0.020ms]
hasBanners > both → true
[0.020ms]
resolveBreakpoint > 0px → xs
[0.060ms]
resolveBreakpoint > 375px (iPhone SE / Mini) → xs
[0.020ms]
resolveBreakpoint > 390px (iPhone 12–15 standard) → xs
[0.010ms]
resolveBreakpoint > 411px (Pixel 6/7/8, Galaxy S20+, OnePlus 9) → xs
[0.010ms]
resolveBreakpoint > 412px (Pixel 6 Pro variant) → xs
[0.010ms]
resolveBreakpoint > 414px (iPhone Plus legacy) → xs
[0.020ms]
resolveBreakpoint > 428px (iPhone Pro Max / Plus) → xs
[0.010ms]
resolveBreakpoint > 479px (xs upper bound) → xs
[0.010ms]
resolveBreakpoint > 480px → sm
[0.020ms]
resolveBreakpoint > 767px (sm upper bound) → sm
[0.010ms]
resolveBreakpoint > 768px → md
[0.010ms]
resolveBreakpoint > 1023px (md upper bound) → md
[0.010ms]
resolveBreakpoint > 1024px → lg
[0.020ms]
resolveBreakpoint > 1439px (lg upper bound) → lg
[0.010ms]
resolveBreakpoint > 1440px → xl
[0.020ms]
resolveBreakpoint > 2560px (ultrawide) → xl
[0.010ms]
isMobile > 375px → true
[0.030ms]
isMobile > 480px → true (sm is still mobile)
[0.010ms]
isMobile > 767px → true
[0.020ms]
isMobile > 768px → false (tablet)
[0.010ms]
isMobile > 1024px → false (desktop)
[0.010ms]
isTablet > 767px → false (mobile)
[0.020ms]
isTablet > 768px → true
[0.010ms]
isTablet > 1023px → true
[0.010ms]
isTablet > 1024px → false (desktop)
[0.010ms]
isDesktop > 1023px → false (tablet)
[0.020ms]
isDesktop > 1024px → true
[0.020ms]
isDesktop > 1440px → true (xl)
[0.010ms]
isDesktop > 375px → false (mobile)
[0.020ms]
getBreakpoint > xs starts at 0, ends at 479
[0.130ms]
getBreakpoint > sm starts at 480, ends at 767
[0.020ms]
getBreakpoint > md starts at 768, ends at 1023
[0.020ms]
getBreakpoint > lg starts at 1024, ends at 1439
[0.020ms]
getBreakpoint > xl starts at 1440, no upper bound
[0.020ms]
getAllBreakpoints > returns 5 breakpoints
[0.020ms]
getAllBreakpoints > breakpoints are in ascending order by minWidth
[0.050ms]
getAllBreakpoints > breakpoints form contiguous ranges (no gaps)
[0.030ms]
compactor routes > session_compactor → /projects/:id/sessions/:sid/compactor
[0.070ms]
compactor routes > session_compaction_detail → /projects/:id/sessions/:sid/compactor/:compactionId
[0.010ms]
compactor routes > project_compactor → /projects/:id/compactor
[0ms]
compactor routes > buildPath resolves session compactor
[0.300ms]
compactor routes > buildPath resolves session compaction detail
[0.060ms]
compactor routes > buildPath resolves project compactor
[0.030ms]
compaction query keys > session compactions key is stable
[0.030ms]
compaction query keys > single compaction key is stable
[0.030ms]
compaction api types > request and response shapes compile
[0.130ms]
compactionStatusBadge > success badge contract
[0.030ms]
compactionStatusBadge > fallback badge contract
[0.010ms]
compactionStatusBadge > failed badge contract
[0ms]
compactionStatusBadge > in_progress badge contract
[0ms]
compaction indicator color thresholds > below 60% is green
[0.030ms]
compaction indicator color thresholds > 60-84% is amber
[0.010ms]
compaction indicator color thresholds > 85%+ is magenta
[0.010ms]
context indicator route > session compactor route remains stable
[0.040ms]
context estimate query keys > context estimate key is stable
[0.040ms]
context estimate api types > response shape compiles
[0.040ms]
context indicator color thresholds > below 60% is green
[0.050ms]
context indicator color thresholds > 60-84% is amber
[0.020ms]
context indicator color thresholds > 85%+ is magenta
[0.020ms]
CornerBrackets types > three tones are valid
[0.030ms]
CornerBrackets types > two weights are valid
[0.020ms]
CornerBrackets tone mapping > amber tone uses --color-amber CSS var
[0.010ms]
CornerBrackets tone mapping > dim tone uses --color-text-dim CSS var
[0.030ms]
CornerBrackets tone mapping > magenta tone uses magenta accent
[0.010ms]
CornerBrackets weight mapping > hairline is 50% opacity
[0.010ms]
CornerBrackets weight mapping > visible is 100% opacity
[0.010ms]
EmptyState types > message-only props are valid
[0.030ms]
EmptyState types > message + action props are valid
[0.050ms]
getRoutePattern (guest routes) > guest_login → /g/login
[0.030ms]
getRoutePattern (guest routes) > guest_setup → /g/setup
[0.010ms]
getRoutePattern (guest routes) > guest_logout → /g/logout
[0.010ms]
getRoutePattern (guest routes) > guest_projects → /g
[0.010ms]
getRoutePattern (guest routes) > guest_project → /g/:project_id
[0.010ms]
getRoutePattern (guest routes) > guest_project_workflows → /g/:project_id/workflows
[0.010ms]
getRoutePattern (guest routes) > guest_project_workflow → /g/:project_id/workflows/:name
[0.010ms]
getRoutePattern (guest routes) > guest_project_runs → /g/:project_id/runs
[0.010ms]
getRoutePattern (guest routes) > guest_project_run → /g/:project_id/runs/:run_id
[0.010ms]
getRoutePattern (guest routes) > guest_project_issues → /g/:project_id/issues
[0.010ms]
getRoutePattern (guest routes) > guest_project_issue_new → /g/:project_id/issues/new
[0.010ms]
getRoutePattern (guest routes) > guest_project_issue → /g/:project_id/issues/:number
[0.010ms]
getRoutePattern (guest routes) > guest_account → /g/account
[0.010ms]
getRoutePattern (guest routes) > guest_account_sessions → /g/account/sessions
[0.010ms]
buildPath (guest routes) > guest_login (no params)
[0.040ms]
buildPath (guest routes) > guest_setup (no params)
[0.030ms]
buildPath (guest routes) > guest_logout (no params)
[0.040ms]
buildPath (guest routes) > guest_projects (no params)
[0.020ms]
buildPath (guest routes) > guest_project with project_id
[0.030ms]
buildPath (guest routes) > guest_project_workflows with project_id
[0.020ms]
buildPath (guest routes) > guest_project_workflow with project_id and name
[0.030ms]
buildPath (guest routes) > guest_project_runs with project_id
[0.020ms]
buildPath (guest routes) > guest_project_run with project_id and run_id
[0.020ms]
buildPath (guest routes) > guest_project_issues with project_id
[0.030ms]
buildPath (guest routes) > guest_project_issue_new with project_id
[0.020ms]
buildPath (guest routes) > guest_project_issue with project_id and number
[0.020ms]
buildPath (guest routes) > guest_account (no params)
[0.030ms]
buildPath (guest routes) > guest_account_sessions (no params)
[0.020ms]
buildPath (guest routes) > encodes special characters in guest params
[0.020ms]
buildPath (guest routes) > throws on missing project_id for guest_project
[0.060ms]
buildPath (guest routes) > throws on missing name for guest_project_workflow
[0.050ms]
getAllRoutes (guest inclusion) > includes 14 guest routes
[0.010ms]
getAllRoutes (guest inclusion) > all guest route patterns start with /g
[0.040ms]
getAllRoutes (guest inclusion) > no duplicate guest route ids
[0.090ms]
getAllRoutes (guest inclusion) > no duplicate guest route patterns
[0.040ms]
KanjiGlyph types > three sizes are valid
[0.030ms]
KanjiGlyph types > three glow modes are valid
[0.020ms]
KanjiGlyph size mapping > sm maps to text-base
[0.020ms]
KanjiGlyph size mapping > md maps to text-2xl
[0.010ms]
KanjiGlyph size mapping > lg maps to text-6xl
[0.010ms]
KanjiGlyph size mapping > all sizes include leading-none
[0.030ms]
KanjiGlyph glow spec > glow amber radial opacity is 12%
[0.010ms]
KanjiGlyph glow spec > glow transition duration is 200ms
[0.010ms]
KanjiGlyph pulse spec > pulse animation class follows naming convention
[0.010ms]
launch route > launch route pattern is /launch
[0.020ms]
launch route > buildPath for launch needs no params
[0.030ms]
getApiBase > returns /api/v1 by default (no KAGED_UI_API_BASE set)
[0.510ms]
getApiBase > returns a string
[0.020ms]
getApiBase > does not have trailing slash
[0.020ms]
avatarLetter > extracts first letter uppercased from normal name
[0.050ms]
avatarLetter > extracts first letter from single-char name
[0.020ms]
avatarLetter > handles already-uppercase name
[0.010ms]
avatarLetter > returns ? for empty string
[0.010ms]
avatarLetter > returns ? for whitespace-only string
[0.010ms]
avatarLetter > trims leading whitespace before extracting
[0.010ms]
avatarLetter > handles numeric first character
[0.010ms]
avatarLetter > handles unicode first character
[0.020ms]
avatarColor > returns a value from AVATAR_PALETTE
[0.210ms]
avatarColor > is deterministic — same id returns same color
[0.040ms]
avatarColor > different ids can produce different colors
[0.320ms]
avatarColor > handles empty string without throwing
[0.030ms]
avatarColor > handles very long id
[0.110ms]
avatarColor > single-char ids produce valid palette entries
[0.060ms]
AVATAR_PALETTE > has exactly 8 entries
[0.020ms]
AVATAR_PALETTE > includes brand colors
[0.020ms]
AVATAR_PALETTE > all entries are non-empty strings
[0.030ms]
StateDot types > all four colours are valid StateDotColor values
[0.050ms]
StateDot types > both sizes are valid
[0.020ms]
StateDot colour mapping > each colour maps to a bg- class
[0.060ms]
StateDot colour mapping > amber maps to bg-amber
[0.020ms]
StateDot colour mapping > cyan maps to bg-cyan
[0.010ms]
StateDot colour mapping > magenta maps to bg-magenta
[0.010ms]
StateDot colour mapping > dim maps to bg-text-dim
[0.010ms]
StateDot pulse spec > pulse animation class name follows naming convention
[0.010ms]
StatusBadge types > all variants have bracket-lock labels
[0.080ms]
StatusBadge types > all variants have required class fields
[0.050ms]
StatusBadge types > only PENDING and DRAFT pulse
[0.040ms]
StatusBadge types > danger variants use magenta text
[0.030ms]
StatusBadge types > CAGED uses magenta-faint bg, UNCAGED uses magenta-dim bg
[0.020ms]
StatusBadge types > amber signal variants use amber text
[0.030ms]
StatusBadge types > dim variants use text-dim
[0.030ms]
StatusBadge types > EXIT label format for display with value
[0.010ms]
KAGED_TERMINAL_THEME > background matches spec --bg-inset
[0.020ms]
KAGED_TERMINAL_THEME > foreground matches spec --text-primary
[0.010ms]
KAGED_TERMINAL_THEME > cursor matches spec --amber
[0.010ms]
KAGED_TERMINAL_THEME > red matches spec --magenta
[0.010ms]
KAGED_TERMINAL_THEME > cyan matches spec --cyan
[0.010ms]
KAGED_TERMINAL_THEME > has all 21 color properties
[0.030ms]
KAGED_TERMINAL_THEME > all values are hex color strings
[0.070ms]
DEFAULT_TERMINAL_CONFIG > fontFamily uses literal font stack for xterm.js renderer
[0.020ms]
DEFAULT_TERMINAL_CONFIG > fontSize is 14
[0.010ms]
DEFAULT_TERMINAL_CONFIG > lineHeight is 1.0 so TUI box-drawing stays aligned
[0.020ms]
DEFAULT_TERMINAL_CONFIG > scrollback is 10000
[0.010ms]
DEFAULT_TERMINAL_CONFIG > theme is the KAGED_TERMINAL_THEME
[0.010ms]
resolveGuestAuthGate > pending → loading
[0.050ms]
resolveGuestAuthGate > success → authenticated
[0.020ms]
resolveGuestAuthGate > error with 401 → auth_required
[0.030ms]
resolveGuestAuthGate > error with 403 → auth_required
[0.020ms]
resolveGuestAuthGate > error with 500 → connection_error
[0.020ms]
resolveGuestAuthGate > error with null error object → connection_error
[0.020ms]
isGuestRoute > /g → true
[0.010ms]
isGuestRoute > /g/ → true
[0.020ms]
isGuestRoute > /g/login → true
[0.010ms]
isGuestRoute > /g/setup → true
[0.010ms]
isGuestRoute > /g/proj-1/issues → true
[0.010ms]
isGuestRoute > /g/proj-1/workflows/deploy → true
[0.020ms]
isGuestRoute > / → false
[0.010ms]
isGuestRoute > /launch → false
[0.010ms]
isGuestRoute > /projects/foo → false
[0.010ms]
isGuestRoute > /system → false
[0.010ms]
isGuestRoute > /global → false (prefix match only)
[0.020ms]
isGuestUnauthRoute > /g/login → true
[0.020ms]
isGuestUnauthRoute > /g/setup → true
[0.020ms]
isGuestUnauthRoute > /g/setup/validate → true (startsWith)
[0.020ms]
isGuestUnauthRoute > /g → false
[0.010ms]
isGuestUnauthRoute > /g/account → false
[0.010ms]
isGuestUnauthRoute > /g/proj-1/issues → false
[0.010ms]
isGuestUnauthRoute > /launch → false
[0.010ms]
resolveIdentityType > operator session → operator
[0.030ms]
resolveIdentityType > guest session → guest
[0.010ms]
resolveIdentityType > no session → none
[0.010ms]
resolveIdentityType > both sessions → operator wins
[0.020ms]
getRoutePattern > dashboard → /
[0.020ms]
getRoutePattern > launch → /launch
[0.010ms]
getRoutePattern > project → /projects/:id
[0ms]
getRoutePattern > session → /projects/:id/sessions/:sid
[0ms]
getRoutePattern > project_settings → /projects/:id/settings
[0ms]
getRoutePattern > system → /system
[0ms]
getRoutePattern > system_aliases → /system/aliases
[0ms]
getRoutePattern > system_providers → /system/providers
[0.020ms]
getRoutePattern > system_plugins → /system/plugins
[0ms]
getRoutePattern > system_guests → /system/guests
[0ms]
getRoutePattern > system_status → /system/status
[0ms]
getRoutePattern > system_audit → /system/audit
[0ms]
getRoutePattern > system_operator_config_web → /system/operator-config/web
[0ms]
getRoutePattern > system_operator_config_tools → /system/operator-config/tools
[0ms]
getRoutePattern > system_operator_config_observability → /system/operator-config/observability
[0ms]
getRoutePattern > system_operator_config_audit → /system/operator-config/audit
[0ms]
getRoutePattern > system_operator_config_daemon → /system/operator-config/daemon
[0ms]
buildPath > dashboard (no params)
[0.030ms]
buildPath > project with id param
[0.030ms]
buildPath > session with id and sid params
[0.030ms]
buildPath > project_settings with id
[0.020ms]
buildPath > system routes need no params
[0.040ms]
buildPath > system status and audit need no params
[0.070ms]
buildPath > encodes special characters in params
[0.030ms]
buildPath > throws on missing required param
[0.050ms]
buildPath > throws on missing all params for parameterized route
[0.030ms]
getAllRoutes > every route has id and pattern
[0.060ms]
getAllRoutes > no duplicate route ids
[0.060ms]
getAllRoutes > no duplicate patterns
[0.040ms]
shouldShowTodoTab > returns false when todos is undefined
[0.040ms]
shouldShowTodoTab > returns false when todos is empty array
[0.020ms]
shouldShowTodoTab > returns true when todos has at least one item
[0.050ms]
shouldShowTodoTab > returns true even when all todos are completed
[0.020ms]
resolveDefaultSidePanelTab > returns fallback when todos is undefined
[0.030ms]
resolveDefaultSidePanelTab > returns fallback when todos is empty
[0.020ms]
resolveDefaultSidePanelTab > returns fallback when all todos are terminal (completed/abandoned)
[0.080ms]
resolveDefaultSidePanelTab > returns 'todo' when there is a pending todo
[0.030ms]
resolveDefaultSidePanelTab > returns 'todo' when there is an in_progress todo
[0.020ms]
resolveDefaultSidePanelTab > returns 'todo' when mixed active and terminal todos
[0.020ms]
buildSidePanelTabs > without todo tab, returns 3 base tabs
[0.050ms]
buildSidePanelTabs > with todo tab, returns 4 tabs
[0.030ms]
buildSidePanelTabs > todo tab is first when present
[0.020ms]
buildSidePanelTabs > todo tab has label 'Todos'
[0.040ms]
buildSidePanelTabs > base tab order is preserved after todo tab
[0.030ms]
isProjectContext > returns false for dashboard
[0.110ms]
isProjectContext > returns false for system
[0.030ms]
isProjectContext > returns false for system status
[0.010ms]
isProjectContext > returns false for system audit
[0.010ms]
isProjectContext > returns false for launch
[0.010ms]
isProjectContext > returns true for project overview
[0.020ms]
isProjectContext > returns true for project settings
[0.010ms]
isProjectContext > returns true for session view
[0.010ms]
isProjectContext > returns true for session history
[0.010ms]
isProjectContext > returns false for bare /projects without id
[0.020ms]
extractProjectId > extracts id from project overview path
[0.040ms]
extractProjectId > extracts id from project settings path
[0.020ms]
extractProjectId > extracts id from session view path
[0.020ms]
extractProjectId > returns null for non-project paths
[0.020ms]
extractProjectId > returns null for bare /projects
[0.020ms]
extractProjectId > handles url-encoded project ids
[0.010ms]
GLOBAL_NAV_ITEMS > contains exactly 2 items (Dashboard,profile)
[0.020ms]
BOTTOM_NAV_ITEMS > contains a single System entry
[0.020ms]
PROJECT_NAV_ITEMS > Overview points at /sessions (not the project root) so /projects/:id stays a redirect surface and active-match doesn't bleed into siblings
[0.060ms]
PROJECT_NAV_ITEMS > encodes project id in paths
[0.020ms]
PROJECT_NAV_ITEMS > Overview uses exact-match active state so it does not stay highlighted on /sessions/:sid descendants
[0.020ms]
PROJECT_BOTTOM_NAV_ITEMS > generates Tasks, Guests, Issues, Settings, Status, Audit (project-scoped) replacing global bottom nav
[0.120ms]
PROJECT_BOTTOM_NAV_ITEMS > encodes project id in paths
[0.040ms]
PROJECT_BOTTOM_NAV_ITEMS > targets include Tasks, Guests, Issues, Settings, Status, Audit in order
[0.040ms]
PROJECT_BOTTOM_NAV_ITEMS > bottom items default to descendant-match (no exact flag) so any future child routes inherit the parent highlight
[0.040ms]
truncateSessionId > truncates long ids to 10 chars + ellipsis
[0.050ms]
truncateSessionId > does not truncate ids <= 10 chars
[0.020ms]
truncateSessionId > handles empty string
[0.010ms]
sessionDisplayName > returns label when present
[0.030ms]
sessionDisplayName > returns truncated id when label is null
[0.020ms]
sessionDisplayName > returns truncated id when label is undefined
[0.020ms]
sessionDisplayName > returns truncated id when label is empty string
[0.020ms]
sessionDisplayName > returns truncated id when label is whitespace-only
[0.020ms]
Sidebar types > two modes exist
[0.030ms]
SidebarHeader props > global mode requires no projectName
[0.030ms]
SidebarHeader props > project mode accepts projectName (no back-chevron per ADR-0035 §10.6)
[0.030ms]
SidebarSection props > label is required
[0.020ms]
SidebarItem props > minimal item requires label and to
[0.030ms]
SidebarItem props > active item has active=true
[0.020ms]
SidebarItem props > session item has dotColor and dotPulse
[0.020ms]
SidebarItem props > all StateDotColor values are valid for dotColor
[0.050ms]
SidebarItem props > onClick prevents default navigation
[0.040ms]
Tasks section > tasks section uses Terminal icon and is a SidebarSection
[0.030ms]
Tasks section > tasks section auto-hides when empty
[0.020ms]
Tasks section > task items can have confirm badge
[0.020ms]
SidebarFooter props > version defaults accepted when undefined
[0.010ms]
SidebarFooter props > explicit version is passed through
[0.020ms]
Sidebar composition contract > Sidebar accepts children (slot-based composition)
[0.010ms]
Sidebar composition contract > global mode sidebar structure: header + section + footer
[0.040ms]
Sidebar composition contract > project mode sidebar structure: header + sessions + issues + tasks + archive + footer
[0.050ms]
position and range conversion > toLspPosition converts 1-based to 0-based
[0.050ms]
position and range conversion > toMonacoRange and toLspRange are inverses
[0.050ms]
markerFromDiagnostic > maps LSP severities to Monaco MarkerSeverity values
[0.080ms]
markerFromDiagnostic > converts range, code, and tags
[0.050ms]
hoverContentsToMarkdown > handles MarkupContent
[0.090ms]
hoverContentsToMarkdown > wraps language-tagged MarkedString in a fence
[0.030ms]
hoverContentsToMarkdown > drops empty parts and keeps plain strings
[0.020ms]
normalizeLocations > handles a single Location
[0.060ms]
normalizeLocations > prefers targetSelectionRange for LocationLinks
[0.020ms]
normalizeLocations > returns empty for null
[0.010ms]
extractTokenFromHash > extracts token correctly
[0.090ms]
extractTokenFromHash > returns null if no token
[0.040ms]
extractTokenFromHash > extracts token with other params
[0.030ms]
isUlid > valid ULID
[0.050ms]
isUlid > invalid ULID
[0.020ms]
getInitials > single word
[0.310ms]
getInitials > multiple words
[0.040ms]
classifyAuthor > ulid
[0.050ms]
classifyAuthor > ambient
[0.020ms]
provider model wire schemas (manual model support) > ProviderModelInfoSchema accepts manual flag
[1.18ms]
provider model wire schemas (manual model support) > SaveModelsRequestSchema accepts manual flag
[0.340ms]
provider model wire schemas (manual model support) > DiscoverModelsResponseSchema carries manual flag in merged
[0.170ms]
provider model manual management helpers > buildModelsFromDiscover combines merged and existing manual models
[0.120ms]
provider model manual management helpers > addManualModel appends a new manual model
[0.070ms]
provider model manual management helpers > addManualModel drops optional name when empty
[0.030ms]
provider model manual management helpers > addManualModel trims id and name
[0.020ms]
provider model manual management helpers > addManualModel returns current list unchanged when id is empty
[0.020ms]
provider model manual management helpers > addManualModel returns current list unchanged when id already exists
[0.020ms]
provider model manual management helpers > removeModel filters out the target model
[0.040ms]
provider model manual management helpers > isManualModel returns true only when manual flag is set
[0.040ms]
load-project-dialog dirname > returns / for root
[0.050ms]
load-project-dialog dirname > returns / for empty string
[0.010ms]
load-project-dialog dirname > returns / for single-level path
[0.030ms]
load-project-dialog dirname > returns parent directory
[0.020ms]
load-project-dialog dirname > ignores trailing slash
[0.010ms]
parseCageLimit > returns undefined for empty string
[0.060ms]
parseCageLimit > returns integer for valid value
[0.050ms]
parseCageLimit > enforces minimum
[0.020ms]
parseCageLimit > rejects non-integers
[0.020ms]
wikiGitPushValid > valid when auto_push is not true
[0.030ms]
wikiGitPushValid > valid when auto_push and auto_commit are true
[0.020ms]
wikiGitPushValid > invalid when auto_push is true but auto_commit is not
[0.020ms]
parseCommandString > splits on whitespace and drops empties
[0.100ms]
parseCommandString > returns empty array for blank string
[0.030ms]
serializeCommandArray > joins with spaces
[0.040ms]
serializeCommandArray > returns empty string for undefined
[0.020ms]
parseKeyValuePairs > parses line-separated KEY=value
[0.110ms]
parseKeyValuePairs > skips lines without equals
[0.030ms]
serializeKeyValuePairs > joins as KEY=value
[0.060ms]
parseCommaList > splits, trims, and drops empties
[0.050ms]
serializeCommaList > joins with comma and space
[0.030ms]
validateMcpServerKey > accepts valid keys
[0.090ms]
validateMcpServerKey > rejects invalid keys
[0.080ms]
buildMcpServer > builds stdio server with command and env
[0.270ms]
buildMcpServer > builds sse server with url and headers
[0.060ms]
buildMcpServer > omits empty optional fields
[0.040ms]
buildMcpServerUpdate > returns update for valid draft
[0.110ms]
buildMcpServerUpdate > returns null for invalid key
[0.030ms]
buildMcpServerUpdate > returns null for empty server
[0.020ms]
BottomBar types > BottomBarProps accepts children
[0.030ms]
BottomBarSidebarZone props > expanded defaults to undefined (component defaults to true)
[0.020ms]
BottomBarSidebarZone props > expanded=true shows sidebar zone
[0.020ms]
BottomBarSidebarZone props > expanded=false hides sidebar zone
[0.020ms]
BottomBarMainZone props > accepts children
[0.020ms]
BottomBarStatus props > dotColor accepts all StateDotColor values
[0.050ms]
BottomBarStatus props > dotPulse is optional
[0.020ms]
BottomBarStatus props > dotPulse=true for degraded daemon
[0.020ms]
BottomBarStatus props > items are middot-separated status text segments
[0.040ms]
BottomBarStatus props > empty items array is valid
[0.020ms]
BottomBarIconButton props > icon and ariaLabel are required
[0.030ms]
BottomBarIconButton props > active=true highlights button amber
[0.020ms]
BottomBarIconButton props > label adds text beside icon
[0.020ms]
BottomBarIconButton props > onClick callback fires
[0.040ms]
BottomBar composition contract > global mode: sidebar zone + main zone with System + status block
[0.060ms]
BottomBar composition contract > project mode: sidebar zone + main zone with Settings/Status/Audit + log toggle + status block
[0.050ms]
BottomBar composition contract > sidebar zone disappears when sidebar is collapsed
[0.020ms]
BottomBar composition contract > global mode has no log toggle
[0.010ms]
BottomBar composition contract > project mode has log toggle
[0.010ms]
BottomBarIconButton active states per spec > collapse icon is amber when sidebar expanded
[0.020ms]
BottomBarIconButton active states per spec > expand icon is amber when sidebar collapsed
[0.020ms]
BottomBarIconButton active states per spec > filter icon has no active state by default
[0.020ms]
root path special-case &gt; isNavActive > root item (to='/') active on exact '/'
[0.050ms]
root path special-case &gt; isNavActive > root item inactive on any descendant
[0.030ms]
exact flag &gt; isNavActive > exact=true matches only the exact path
[0.020ms]
exact flag &gt; isNavActive > exact=true rejects descendants
[0.030ms]
exact flag &gt; isNavActive > exact=true on non-root item
[0.020ms]
descendant matching (default) &gt; isNavActive > matches exact path
[0.010ms]
descendant matching (default) &gt; isNavActive > matches child paths
[0.020ms]
descendant matching (default) &gt; isNavActive > matches deeply nested descendants
[0.020ms]
descendant matching (default) &gt; isNavActive > rejects unrelated paths
[0.020ms]
descendant matching (default) &gt; isNavActive > rejects path-prefix collision (no trailing slash guard bypass)
[0.020ms]
project session paths &gt; isNavActive > active on exact session path
[0.010ms]
project session paths &gt; isNavActive > active on session sub-route
[0.020ms]
project session paths &gt; isNavActive > inactive on different session
[0.020ms]
project session paths &gt; isNavActive > inactive on parent sessions list
[0.010ms]
works with real nav items &gt; isNavActive > global dashboard item active on '/'
[0.030ms]
works with real nav items &gt; isNavActive > bottom nav System active on /system and /system/*
[0.030ms]
works with real nav items &gt; isNavActive > project Overview (exact) active only on sessions list
[0.040ms]
works with real nav items &gt; isNavActive > project bottom items use descendant matching
[0.040ms]
ShellMode > global and project are the two valid modes
[0.030ms]
ShellMode > modes are string literals (not enums)
[0.020ms]
useShellStore > exposes sidebarExpanded as boolean
[0.060ms]
useShellStore > exposes setSidebarExpanded function
[0.020ms]
useShellStore > exposes toggleSidebar function
[0.020ms]
useShellStore > setSidebarExpanded(false) collapses
[0.080ms]
useShellStore > setSidebarExpanded(true) expands
[0.030ms]
useShellStore > toggleSidebar flips expanded → collapsed
[0.060ms]
useShellStore > toggleSidebar flips collapsed → expanded
[0.030ms]
useShellStore > toggle round-trips: true → false → true
[0.030ms]
useShellStore > toggle round-trips: false → true → false
[0.030ms]
useShellStore > setSidebarExpanded is idempotent
[0.040ms]
MobileBottomNav items > project context returns 5 items (sessions, issues, files, status, settings)
[0.100ms]
MobileBottomNav items > global context returns only Dashboard and profile (no System on mobile)
[0.030ms]
Desktop sidebar item composition > global mode: Dashboard + System = 2 total
[0.030ms]
Desktop sidebar item composition > project mode: Overview + 6 project bottom items = 7 total
[0.050ms]
Desktop sidebar item composition > project items include encoded project id in paths
[0.050ms]
Desktop sidebar item composition > project mode retains more items than global mode
[0.030ms]
Shell structural contracts > sidebar width constants: 140px desktop, 280px mobile drawer
[0.020ms]
Shell structural contracts > shell localStorage key is 'kaged.ui.sidebar.expanded'
[0.010ms]
Shell structural contracts > all nav items have required icon property
[0.040ms]
Shell structural contracts > shell mode is determined by isProjectContext, not stored state
[0.050ms]
makeTabId > produces kind:sourceId format
[0.040ms]
makeTabId > different kinds produce different IDs for the same sourceId
[0.030ms]
makeTabId > same kind+sourceId always returns the same string
[0.020ms]
openSession &gt; useTabStore > creates a single session tab
[0.330ms]
openSession &gt; useTabStore > sets activeTabId to the session tab
[0.100ms]
openSession &gt; useTabStore > session tab uses the provided label
[0.040ms]
openSession &gt; useTabStore > session tab is closeable
[0.040ms]
openSession &gt; useTabStore > opening a different session adds a new tab alongside the old one
[0.130ms]
openSession &gt; useTabStore > opening same session again is a no-op when the tab already exists
[0.050ms]
openSession &gt; useTabStore > re-opening same session after closing it restores the tab
[0.170ms]
openSession &gt; useTabStore > non-session tabs are preserved when a new session opens
[0.060ms]
openSession &gt; useTabStore > different projects are independent
[0.060ms]
openIssue &gt; useTabStore > creates a single issue tab with kind 'issue'
[0.150ms]
openIssue &gt; useTabStore > sets activeTabId to the issue tab
[0.070ms]
openIssue &gt; useTabStore > issue tab uses the provided label
[0.030ms]
openIssue &gt; useTabStore > issue tab is closeable
[0.030ms]
openIssue &gt; useTabStore > sourceId is the string representation of the issue number
[0.030ms]
openIssue &gt; useTabStore > opening same issue again is a no-op
[0.050ms]
openIssue &gt; useTabStore > different projects are independent
[0.060ms]
openIssue &gt; useTabStore > non-issue tabs are preserved when opening an issue
[0.060ms]
openFile &gt; useTabStore > creates a single file tab with kind 'file'
[0.140ms]
openFile &gt; useTabStore > sets activeTabId to the file tab
[0.050ms]
openFile &gt; useTabStore > sourceId is the file path
[0.030ms]
openFile &gt; useTabStore > file tab is closeable
[0.030ms]
openFile &gt; useTabStore > opening same file path again is a no-op
[0.050ms]
openFile &gt; useTabStore > different file paths create different tabs
[0.090ms]
useTabStore > mixed heterogeneous tabs preserve order and fallback activation on close
[0.150ms]
closeTab &gt; useTabStore > removes the targeted tab
[0.120ms]
closeTab &gt; useTabStore > closing the active tab falls back to adjacent tab
[0.070ms]
closeTab &gt; useTabStore > closing a non-active tab does not change activeTabId
[0.070ms]
closeTab &gt; useTabStore > closing the last tab results in null activeTabId
[0.050ms]
activateTab &gt; useTabStore > sets activeTabId to the given tab
[0.130ms]
activateTab &gt; useTabStore > no-op when tabId does not exist in the project
[0.050ms]
clearProject &gt; useTabStore > removes all tabs and sets activeTabId to null
[0.080ms]
clearProject &gt; useTabStore > does not affect other projects
[0.060ms]
getProjectTabs selector > returns empty default for unknown project
[0.040ms]
getProjectTabs selector > returns stored tabs for known project
[0.060ms]
getActiveTab selector > returns null when project has no tabs
[0.040ms]
getActiveTab selector > returns the active StoreTab
[0.060ms]
getActiveTab selector > returns null when activeTabId references a removed tab
[0.040ms]
hydrateProject > no-op when project is already loaded in state
[0.120ms]
hydrateProject > no-op when localStorage has no persisted tabs
[0.040ms]
hydrateProject > loads persisted tabs from localStorage into state
[0.060ms]
hydrateProject > hydrated tabs are visible via getProjectTabs selector
[0.090ms]
hydrateProject > idempotent — second call is a no-op
[0.060ms]
resolveSubagentDot > returns null for empty array
[0.070ms]
resolveSubagentDot > returns null when all subagents are idle
[0.040ms]
resolveSubagentDot > returns null when all subagents are paused
[0.020ms]
resolveSubagentDot > returns null when mix of idle and paused (all quiet)
[0.020ms]
resolveSubagentDot > returns cyan pulse for running subagent
[0.030ms]
resolveSubagentDot > returns magenta no-pulse for failed subagent
[0.030ms]
resolveSubagentDot > returns magenta no-pulse for blocked subagent
[0.030ms]
resolveSubagentDot > running takes priority over failed
[0.020ms]
resolveSubagentDot > running takes priority over blocked
[0.020ms]
resolveSubagentDot > failed takes priority over blocked
[0.020ms]
resolveSubagentDot > running takes priority over all others combined
[0.030ms]
useShellStore — log state > logOpen defaults to false
[0.040ms]
useShellStore — log state > logHeight defaults to LOG_HEIGHT_DEFAULT (240)
[0.020ms]
useShellStore — log state > setLogOpen(true) opens log
[0.040ms]
useShellStore — log state > setLogOpen(false) closes log
[0.030ms]
useShellStore — log state > toggleLog flips false → true
[0.060ms]
useShellStore — log state > toggleLog flips true → false
[0.030ms]
useShellStore — log state > toggleLog round-trips: false → true → false
[0.040ms]
useShellStore — log state > setLogHeight sets height within bounds
[0.040ms]
useShellStore — log state > setLogHeight clamps below LOG_HEIGHT_MIN
[0.030ms]
useShellStore — log state > setLogHeight clamps above LOG_HEIGHT_MAX
[0.030ms]
useShellStore — log state > setLogHeight rounds fractional values
[0.020ms]
useShellStore — log state > LOG_HEIGHT_MIN < LOG_HEIGHT_DEFAULT < LOG_HEIGHT_MAX
[0.020ms]
useShellStore — log state > LOG_HEIGHT_MIN is 120, LOG_HEIGHT_MAX is 600
[0.020ms]
STORAGE_KEYS > sidebarExpanded key
[0.010ms]
STORAGE_KEYS > logOpen key
[0.010ms]
STORAGE_KEYS > logHeight key
[0.010ms]
STORAGE_KEYS > all keys share the kaged.ui prefix
[0.040ms]
Shell store — ADR-35 §5.4 keys > storage keys match ADR-35
[0.070ms]
Shell store — ADR-35 §5.4 keys > lastProjectId defaults to null and round-trips
[0.070ms]
Shell store — ADR-35 §5.4 keys > rightPanelUserToggled defaults to false and can be set
[0.050ms]
Shell store — ADR-35 §5.4 keys > getActivity defaults to sessions and setActivity updates reactive state
[0.120ms]
Shell store — ADR-35 §5.4 keys > loadActivity hydrates from localStorage once and is idempotent
[0.090ms]
Shell store — ADR-35 §5.4 keys > systemActivity defaults to config and round-trips
[0.050ms]
Shell store — ADR-35 §5.4 keys > setSystemActivity persists and updates state
[0.040ms]
Shell store — ADR-35 §5.4 keys > activity state is isolated per project
[0.050ms]
Shell store — ADR-35 §5.4 keys > all ActivityItem values are covered
[0.050ms]
LogFilterState helpers > DEFAULT_LOG_FILTERS has all kinds enabled
[0.030ms]
LogFilterState helpers > LOG_FILTER_KINDS lists all filter kinds
[0.030ms]
LogFilterState helpers > isLogFilterActive reads from filter state
[0.040ms]
LogFilterState helpers > toggleLogFilter flips a single kind
[0.030ms]
LogFilterState helpers > toggleLogFilter is immutable (returns new object)
[0.030ms]
LogFilterState helpers > double-toggle round-trips
[0.020ms]
filterEntries > returns all entries when all filters are enabled and query is empty
[0.070ms]
filterEntries > filters out daemon entries when daemon filter is off
[0.080ms]
filterEntries > filters out multiple kinds
[0.040ms]
filterEntries > all filters off returns empty
[0.030ms]
filterEntries > search query filters by message (case-insensitive)
[0.040ms]
filterEntries > search query combined with kind filter
[0.030ms]
filterEntries > empty entries returns empty
[0.020ms]
filterEntries > no-match search query returns empty
[0.020ms]
PROJECT_LOG_NAV_ITEM > returns a NavItem with label 'Log'
[0.040ms]
PROJECT_LOG_NAV_ITEM > routes to /projects/:id/log
[0.020ms]
PROJECT_LOG_NAV_ITEM > encodes projectId in path
[0.020ms]
PROJECT_LOG_NAV_ITEM > has icon property (ScrollText)
[0.020ms]
PROJECT_LOG_NAV_ITEM > isNavActive works for log route
[0.040ms]
Desktop sidebar item composition (Phase 6a) > project mode: Overview + 6 bottom + Log = 8 total
[0.060ms]
Desktop sidebar item composition (Phase 6a) > global mode still has 2 items (no Log)
[0.020ms]
Desktop sidebar item composition (Phase 6a) > all project mode items include encoded project id
[0.050ms]
Desktop sidebar item composition (Phase 6a) > all 5 project items have icon property
[0.030ms]
IconButton types > tone list is exhaustive
[0.050ms]
IconButton types > default size is 26
[6.10ms]
ActionBarItem types > tone list is exhaustive
[0.030ms]
ActionBarItem types > exports as a function
[0.020ms]
RailItem types and rendering > count is optional at the type level
[0.020ms]
RailItem types and rendering > count > 0 renders the badge span
[0.440ms]
RailItem types and rendering > count 0 or undefined renders no badge
[0.160ms]
PanelToggle types > side list is exhaustive
[0.030ms]
PanelToggle types > open is required and boolean
[0.030ms]
PanelToggle types > exports as a function
[0.020ms]
TextInput types > size list is exhaustive
[0.020ms]
TextInput types > borderless and mono flags are supported
[0.030ms]
TextInput types > default type contracts stay callable
[0.360ms]
Dropdown types > option shape uses string value and label
[0.050ms]
Dropdown types > size list is exhaustive
[0.020ms]
RightPaneIcon types > pane list is exhaustive
[0.030ms]
RightPaneIcon types > files pane is not allowed
[0.010ms]
DockRow types > label list is exhaustive
[0.020ms]
DockRow types > DockRow stays callable for both edit modes
[0.350ms]
api-client path convention > no api-client call passes a path that starts with /api/v1 (the client prepends it)
[16.17ms]
api-client path convention > body-bearing routes use apiCall (not apiPost/apiPut/apiPatch) for contract type safety
[12.25ms]
buildWorkflowFlowchart > generates correct mermaid string for a basic workflow
[0.510ms]
fromDsl > omitted on_success on a non-last step becomes an explicit edge to the next step
[0.430ms]
fromDsl > omitted on_success on the last step becomes the `end` fallback verb (no edge)
[0.100ms]
fromDsl > omitted on_fail defaults to the abort fallback verb (no edge)
[0.050ms]
fromDsl > explicit step-id routes become edges
[0.130ms]
fromDsl > explicit end/abort become fallback verbs, not edges
[0.070ms]
fromDsl > legacy `continue` normalizes to the next step edge
[0.050ms]
fromDsl > max_runs is carried onto the node
[0.040ms]
fromDsl > kind-specific config is preserved, routing/identity stripped
[0.070ms]
toDslSteps > preserves order[] and omits default routes
[0.320ms]
toDslSteps > default continue success route is omitted
[0.060ms]
toDslSteps > emits max_runs only for supported kinds
[0.060ms]
toDslSteps > throws when order references an unknown step
[0.080ms]
round-trip > fromDsl -> toDslSteps is stable for explicit graphs
[0.090ms]
detectLoopTargets > back-edge to earlier step is a loop target
[0.150ms]
detectLoopTargets > self-edge is a loop target
[0.050ms]
detectLoopTargets > forward edge is not a loop
[0.030ms]
validateDraft > loop target without max_runs is a blocking error
[0.350ms]
validateDraft > loop target with max_runs is allowed
[0.050ms]
validateDraft > compare step cannot be a loop target
[0.060ms]
validateDraft > duplicate ids are an error
[0.040ms]
validateDraft > reserved id is an error
[0.050ms]
validateDraft > invalid id format is an error
[0.040ms]
validateDraft > dangling edge target is an error
[0.040ms]
validateDraft > two edges on the same handle is an error
[0.090ms]
validateDraft > empty workflow is an error
[0.030ms]
validateDraft > continue on last step is a non-blocking warning
[0.040ms]
buildHelloPayload > omits resume_from_seq on fresh connect ({0,0})
[0.060ms]
buildHelloPayload > omits resume_from_seq when resume_failed cleared the store
[0.030ms]
buildHelloPayload > includes resume_from_seq when output seq > 0
[0.020ms]
buildHelloPayload > includes resume_from_seq when events seq > 0
[0.020ms]
buildHelloPayload > includes resume_from_seq when both seqs > 0
[0.020ms]
Daemon Registry Store > seedIfEmpty adds a seed daemon if empty
[0.200ms]
Daemon Registry Store > seedIfEmpty does nothing if not empty
[0.060ms]
Daemon Registry Store > registerDaemon normalizes apiBase and adds new entry
[0.050ms]
Daemon Registry Store > registerDaemon normalizes relative apiBase
[0.040ms]
Daemon Registry Store > registerDaemon dedupes and updates existing entry
[0.120ms]
Daemon Registry Store > setActive changes activeId
[0.120ms]
Daemon Registry Store > relabel updates label
[0.110ms]
Daemon Registry Store > remove deletes entry and updates activeId if needed
[0.140ms]
Daemon Registry Store > setSessionToken updates token
[0.090ms]
Daemon Registry Store > persists to localStorage
[0.070ms]
api-client > getApiBase seeds if empty and returns default
[0.110ms]
api-client > getApiBase returns active daemon base
[0.050ms]
api-client > headers uses CSRF token if no session token
[0.100ms]
api-client > headers uses Bearer token if session token present, and no CSRF
[0.060ms]
api-client > headers uses Bearer token for GET requests too
[0.050ms]
api-client > switchDaemon clears cache and sets active
[0.150ms]
api-client > wsUrlFor derives from relative apiBase
[0.090ms]
api-client > wsUrlFor derives from absolute http apiBase
[0.050ms]
api-client > wsUrlFor derives from absolute https apiBase
[0.040ms]
expandDaemonUrl > shorthand expands to https://<name>.kaged.dev/api/v1
[0.110ms]
expandDaemonUrl > shorthand trims whitespace
[0.030ms]
expandDaemonUrl > full https URL appends /api/v1
[0.030ms]
expandDaemonUrl > full http URL appends /api/v1
[0.020ms]
expandDaemonUrl > URL already ending in /api/v1 is not doubled
[0.020ms]
expandDaemonUrl > URL with trailing slash appends /api/v1
[0.020ms]
expandDaemonUrl > dotted hostname without scheme gets https and /api/v1
[0.020ms]
expandDaemonUrl > hostname with port gets https and /api/v1
[0.020ms]
expandDaemonUrl > empty string throws
[0.040ms]
expandDaemonUrl > whitespace-only throws
[0.030ms]
firstWord > returns the leading whitespace-delimited token
[0.060ms]
firstWord > trims leading whitespace before splitting
[0.030ms]
firstWord > collapses inner runs of whitespace
[0.020ms]
firstWord > returns empty string for an all-whitespace input
[0.010ms]
firstWord > returns the input intact when it is a single token
[0.020ms]
getTaskInstanceLabel > prefers the DSL task description when the task is reachable
[0.120ms]
getTaskInstanceLabel > falls back to instance.task_name when description is null
[0.030ms]
getTaskInstanceLabel > falls back to instance.task_name when the DSL task is missing
[0.020ms]
getTaskInstanceLabel > falls back to first word of command when task_name is null
[0.030ms]
getTaskInstanceLabel > uses "bash" for an ad-hoc bash invocation with no task_name
[0.020ms]
getTaskInstanceLabel > does not match a DSL task whose name differs from task_name
[0.040ms]
getTaskInstanceLabel > matches the worked example from the operator report
[0.020ms]
resolveTier > same session + visible -> 1
[0.050ms]
resolveTier > different session + visible -> 2
[0.020ms]
resolveTier > no active session + visible -> 2
[0.020ms]
resolveTier > same session + hidden -> 2.5
[0.020ms]
resolveTier > different session + hidden -> 2.5
[0.010ms]
resolveTier > no active session + hidden -> 2.5
[0.020ms]
resolveSubscriptionAffordance > !pushManagerSupported -> hidden:unsupported
[0.060ms]
resolveSubscriptionAffordance > !isSecureContext -> hidden:insecure
[0.030ms]
resolveSubscriptionAffordance > !swRegistered -> hidden:no_sw
[0.020ms]
resolveSubscriptionAffordance > alreadySubscribed && permissionGranted -> manage
[0.020ms]
resolveSubscriptionAffordance > alreadySubscribed && !permissionGranted -> done
[0.020ms]
resolveSubscriptionAffordance > !alreadySubscribed && permissionGranted -> offer
[0.020ms]
resolveSubscriptionAffordance > !alreadySubscribed && !permissionGranted -> offer
[0.020ms]
resolveBellVisualState > attentionCount > 0 -> active
[0.050ms]
resolveBellVisualState > attentionCount === 0 && bellValue === silent -> muted
[0.020ms]
resolveBellVisualState > attentionCount === 0 && bellValue === attention-only && eventClass === run.completed -> muted
[0.020ms]
resolveBellVisualState > attentionCount === 0 && bellValue === attention-only && eventClass !== run.completed -> idle
[0.020ms]
resolveBellVisualState > attentionCount === 0 && bellValue === default -> idle
[0.020ms]
shouldCoalesceToast > same session + within 2 seconds -> true
[0.040ms]
shouldCoalesceToast > same session + exactly 2 seconds -> true
[0.020ms]
shouldCoalesceToast > same session + more than 2 seconds -> false
[0.020ms]
shouldCoalesceToast > different session + within 2 seconds -> false
[0.020ms]
createNotificationReducer > attention.required: increments attentionBySession
[0.180ms]
createNotificationReducer > attention.required: idempotent on duplicate event.id
[0.050ms]
createNotificationReducer > run.completed: appends to recentCompletions
[0.040ms]
createNotificationReducer > run.completed: respects bell=silent (skips)
[0.050ms]
createNotificationReducer > run.completed: respects bell=attention-only (skips)
[0.030ms]
createNotificationReducer > attention.required: respects bell=silent (skips)
[0.040ms]
sw-notify > renderTitle: attention.required
[0.070ms]
sw-notify > renderTitle: run.completed
[0.030ms]
sw-notify > renderBody: attention.required
[0.030ms]
sw-notify > renderBody: run.completed
[0.020ms]
shouldProbe &gt; version-probe > throttled when elapsed < 60s
[0.070ms]
shouldProbe &gt; version-probe > interval when elapsed >= intervalMs
[0.030ms]
shouldProbe &gt; version-probe > visibility when visible and elapsed >= 60s
[0.020ms]
shouldProbe &gt; version-probe > throttled when visible but elapsed < 60s
[0.020ms]
shouldProbe &gt; version-probe > dev mode short-circuits
[0.020ms]
compareVersions &gt; version-probe > current when versions match
[0.040ms]
compareVersions &gt; version-probe > update-available when versions differ and fetch is ok
[0.020ms]
compareVersions &gt; version-probe > no-remote when fetch is ok but version is null
[0.020ms]
compareVersions &gt; version-probe > fetch-failed when fetch is not ok
[0.020ms]
compareVersions &gt; version-probe > fetch-failed when fetch is not ok and version is null
[0.020ms]
UpdateBanner predicate > disabled when dismissed
[0.060ms]
UpdateBanner predicate > disabled when activeRuns > 0
[0.060ms]
UpdateBanner predicate > enabled when activeRuns === 0 and not dismissed
[0.030ms]
PWA Configuration Invariants > navigateFallbackDenylist excludes /api/
[0.030ms]
PWA Configuration Invariants > runtimeCaching is empty
[0.020ms]
PWA Configuration Invariants > globIgnores excludes version.json
[0.010ms]
PWA Configuration Invariants > globPatterns includes assets but not raw /api/
[0.010ms]
useRegenerate > builds correct URL and method
[0.190ms]
useRegenerate > surfaces queued receipt distinctly
[0.070ms]
retry-controller > nextDelay sequence
[0.080ms]
retry-controller > resolveSchedule countdown vs scheduled
[0.080ms]
retry-controller > reducer transitions
[0.170ms]
retry-controller > getSecondsRemaining
[0.070ms]
resolveAnchorOperatorId > single operator to reply
[0.090ms]
resolveAnchorOperatorId > multiple operators, picks nearest preceding
[0.040ms]
resolveAnchorOperatorId > skips superseded messages
[0.030ms]
resolveAnchorOperatorId > returns null if no preceding operator
[0.020ms]
shouldArmRetry > returns true when failed and retryable is true
[0.040ms]
shouldArmRetry > returns false when not failed
[0.020ms]
shouldArmRetry > returns false when retryable is false or null
[0.030ms]
shouldArmRetry > returns false for non-primary roles
[0.020ms]