@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 > isNavActive > root item (to='/') active on exact '/' [0.050ms]
root path special-case > isNavActive > root item inactive on any descendant [0.030ms]
exact flag > isNavActive > exact=true matches only the exact path [0.020ms]
exact flag > isNavActive > exact=true rejects descendants [0.030ms]
exact flag > isNavActive > exact=true on non-root item [0.020ms]
descendant matching (default) > isNavActive > matches exact path [0.010ms]
descendant matching (default) > isNavActive > matches child paths [0.020ms]
descendant matching (default) > isNavActive > matches deeply nested descendants [0.020ms]
descendant matching (default) > isNavActive > rejects unrelated paths [0.020ms]
descendant matching (default) > isNavActive > rejects path-prefix collision (no trailing slash guard bypass) [0.020ms]
project session paths > isNavActive > active on exact session path [0.010ms]
project session paths > isNavActive > active on session sub-route [0.020ms]
project session paths > isNavActive > inactive on different session [0.020ms]
project session paths > isNavActive > inactive on parent sessions list [0.010ms]
works with real nav items > isNavActive > global dashboard item active on '/' [0.030ms]
works with real nav items > isNavActive > bottom nav System active on /system and /system/* [0.030ms]
works with real nav items > isNavActive > project Overview (exact) active only on sessions list [0.040ms]
works with real nav items > 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 > useTabStore > creates a single session tab [0.330ms]
openSession > useTabStore > sets activeTabId to the session tab [0.100ms]
openSession > useTabStore > session tab uses the provided label [0.040ms]
openSession > useTabStore > session tab is closeable [0.040ms]
openSession > useTabStore > opening a different session adds a new tab alongside the old one [0.130ms]
openSession > useTabStore > opening same session again is a no-op when the tab already exists [0.050ms]
openSession > useTabStore > re-opening same session after closing it restores the tab [0.170ms]
openSession > useTabStore > non-session tabs are preserved when a new session opens [0.060ms]
openSession > useTabStore > different projects are independent [0.060ms]
openIssue > useTabStore > creates a single issue tab with kind 'issue' [0.150ms]
openIssue > useTabStore > sets activeTabId to the issue tab [0.070ms]
openIssue > useTabStore > issue tab uses the provided label [0.030ms]
openIssue > useTabStore > issue tab is closeable [0.030ms]
openIssue > useTabStore > sourceId is the string representation of the issue number [0.030ms]
openIssue > useTabStore > opening same issue again is a no-op [0.050ms]
openIssue > useTabStore > different projects are independent [0.060ms]
openIssue > useTabStore > non-issue tabs are preserved when opening an issue [0.060ms]
openFile > useTabStore > creates a single file tab with kind 'file' [0.140ms]
openFile > useTabStore > sets activeTabId to the file tab [0.050ms]
openFile > useTabStore > sourceId is the file path [0.030ms]
openFile > useTabStore > file tab is closeable [0.030ms]
openFile > useTabStore > opening same file path again is a no-op [0.050ms]
openFile > useTabStore > different file paths create different tabs [0.090ms]
useTabStore > mixed heterogeneous tabs preserve order and fallback activation on close [0.150ms]
closeTab > useTabStore > removes the targeted tab [0.120ms]
closeTab > useTabStore > closing the active tab falls back to adjacent tab [0.070ms]
closeTab > useTabStore > closing a non-active tab does not change activeTabId [0.070ms]
closeTab > useTabStore > closing the last tab results in null activeTabId [0.050ms]
activateTab > useTabStore > sets activeTabId to the given tab [0.130ms]
activateTab > useTabStore > no-op when tabId does not exist in the project [0.050ms]
clearProject > useTabStore > removes all tabs and sets activeTabId to null [0.080ms]
clearProject > 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 > version-probe > throttled when elapsed < 60s [0.070ms]
shouldProbe > version-probe > interval when elapsed >= intervalMs [0.030ms]
shouldProbe > version-probe > visibility when visible and elapsed >= 60s [0.020ms]
shouldProbe > version-probe > throttled when visible but elapsed < 60s [0.020ms]
shouldProbe > version-probe > dev mode short-circuits [0.020ms]
compareVersions > version-probe > current when versions match [0.040ms]
compareVersions > version-probe > update-available when versions differ and fetch is ok [0.020ms]
compareVersions > version-probe > no-remote when fetch is ok but version is null [0.020ms]
compareVersions > version-probe > fetch-failed when fetch is not ok [0.020ms]
compareVersions > 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]

Mentioned in

Type Document
adr ADR-0016: Streaming-first UI — live data and operator abort are non-negotiable
adr ADR-0019: Workflows are operator-authored, parameterised DSL artifacts agents invoke
adr ADR-0021: Guest UI lives at /g/* — segregated route tree, distinct app shell
adr ADR-0024: Context compaction is kaged-owned, layered, observable, and operator-tunable
adr ADR-0025: Typecheck orchestrates per-package; root tsc is a marker
adr ADR-0028: 3rd-party OAuth provider auth — token lifecycle and credential management
adr ADR-0030: Log streaming via Server-Sent Events
adr ADR-0031: An assistant turn is an ordered transcript of parts, not a flattened bubble
adr ADR-0035: Unified operator shell — scope tabs, activity rail, route-driven chrome, and enforced UI primitives
adr ADR-0039: @kaged/wire is the normative wire contract; daemon and UI must consume it
adr ADR-0040: Multi-daemon operator UI — runtime daemon registry, cross-origin hosting, bearer transport
adr ADR-0041: Containerised daemon — single-binary build, distribution image, Kubernetes operation
adr ADR-0042: Package distribution, CI, and the release pipeline
adr ADR-0049: Providers are dynamically-loaded modules from an operator-local store; catalog from a self-hosted models.dev mirror; @kaged/llm becomes resolver + loader + middleware
spec Spec: Agent Harness
spec Spec: Daemon
spec Spec: HTTP + WebSocket API
spec Spec: Operational Logging
spec Spec: Project Terminals
spec Spec: @kaged/wire
spec Spec: Workflows