@kaged/daemon
Long-lived HTTP+WebSocket server that routes operator sessions, dispatches primary agents through the harness, and orchestrates plugins, providers, and project lifecycles
73
source files
51
test files
~42.9k
lines
✓ 1170 pass
tests
pass
typecheck
clean
lint
Test results 1170
statusForCode > bad_request → 400
[0.050ms]
statusForCode > validation_failed → 400
[0.010ms]
statusForCode > unauthenticated → 401
[0ms]
statusForCode > forbidden → 403
[0ms]
statusForCode > not_found → 404
[0ms]
statusForCode > conflict → 409
[0ms]
statusForCode > gone → 410
[0ms]
statusForCode > dsl_invalid → 422
[0ms]
statusForCode > rate_limited → 429
[0.010ms]
statusForCode > internal → 500
[0ms]
statusForCode > provider_unreachable → 502
[0ms]
statusForCode > unavailable → 503
[0ms]
buildApiError > builds error with required fields
[0.070ms]
buildApiError > includes details when provided
[0.030ms]
buildApiError > omits details key when not provided
[0.020ms]
isClientError / isServerError > 4xx codes are client errors
[0.070ms]
isClientError / isServerError > 5xx codes are server errors
[0.040ms]
getAllApiRoutes > returns a non-empty array
[0.030ms]
getAllApiRoutes > every route has method, path, authenticated, csrf, description
[0.180ms]
getAllApiRoutes > all paths start with /
[0.060ms]
getAllApiRoutes > no duplicate method+path combinations
[0.140ms]
findRoute > finds healthz
[0.070ms]
findRoute > finds POST projects/load
[0.020ms]
findRoute > finds GET project capabilities endpoint
[0.020ms]
findRoute > returns undefined for unknown route
[0.060ms]
getAuthenticatedRoutes / getUnauthenticatedRoutes > unauthenticated routes include healthz, readyz, versions, launch, dsl/schema
[0.090ms]
getAuthenticatedRoutes / getUnauthenticatedRoutes > authenticated + unauthenticated = all routes
[0.090ms]
getCsrfProtectedRoutes > state-changing methods or WS upgrade have CSRF
[0.130ms]
getCsrfProtectedRoutes > GET routes never have CSRF except WebSocket upgrade
[0.100ms]
isStateChangingMethod > POST, PUT, PATCH, DELETE are state-changing
[0.030ms]
isStateChangingMethod > GET is not state-changing
[0.010ms]
resolveWarnings > no flags → empty
[0.050ms]
resolveWarnings > insecure → [insecure-mode]
[0.020ms]
resolveWarnings > noSandbox → [no-sandbox]
[0.020ms]
resolveWarnings > both → [insecure-mode, no-sandbox] in order
[0.020ms]
formatWarningHeader > no warnings → null
[0.030ms]
formatWarningHeader > insecure only → 'insecure-mode'
[0.020ms]
formatWarningHeader > both → comma-separated
[0.010ms]
hasWarnings > no flags → false
[0.020ms]
hasWarnings > any flag → true
[0.020ms]
findRateLimit > POST messages → 30/min
[0.090ms]
findRateLimit > POST dsl/validate → 120/min
[0.020ms]
findRateLimit > PUT projects/:id/dsl → 10/min
[0.020ms]
findRateLimit > GET audit → 30/min
[0.020ms]
findRateLimit > unknown endpoint → default 600/min
[0.030ms]
getAllRateLimits > returns 9 specific limits
[0.020ms]
getDefaultRateLimit > default is 600/min with wildcard pattern
[0.020ms]
isValidChannel > control, output, pty, events are valid
[0.030ms]
isValidChannel > unknown channel is invalid
[0.010ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > pty:01HXAB is a pty channel
[0.020ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > control is not a pty channel
[0.010ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > parsePtyChannel extracts invocation id
[0.030ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > parsePtyChannel returns null for non-pty
[0.010ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > parsePtyChannel returns null for empty id
[0.010ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > buildPtyChannel creates correct string
[0.020ms]
isPtyChannel / parsePtyChannel / buildPtyChannel > roundtrip: build → parse
[0.010ms]
isValidCloseCode / getAllCloseCodes > all spec close codes are valid
[0.040ms]
isValidCloseCode / getAllCloseCodes > unknown code is invalid
[0.010ms]
isValidCloseCode / getAllCloseCodes > getAllCloseCodes returns 8 codes
[0.020ms]
bufferLimitForChannel > output → 4MB
[0.030ms]
bufferLimitForChannel > pty → 1MB
[0.010ms]
bufferLimitForChannel > events → 64KB
[0.010ms]
bufferLimitForChannel > control → 64KB (same as events)
[0.020ms]
clampLimit > undefined → default 50
[0.030ms]
clampLimit > 0 → default 50
[0.010ms]
clampLimit > negative → default 50
[0.010ms]
clampLimit > 25 → 25 (within bounds)
[0.030ms]
clampLimit > 200 → 200 (max)
[0.010ms]
clampLimit > 500 → 200 (clamped)
[0.010ms]
buildPaginatedResponse > items within limit → no next page
[0.090ms]
buildPaginatedResponse > items exceeding limit → truncated with cursor
[0.040ms]
buildPaginatedResponse > empty items → no cursor
[0.020ms]
buildPaginatedResponse > exactly limit+1 items → limit items returned with cursor
[0.060ms]
constants > WS_SUBPROTOCOL is kaged.v1
[0.010ms]
constants > PAGINATION_DEFAULTS
[0.020ms]
constants > RESPONSE_HEADERS has expected keys
[0.020ms]
constants > REQUEST_HEADERS has expected keys
[0.030ms]
constants > PTY_DISCRIMINATOR values
[0.020ms]
insecure mode > auth > accepts request with no headers, synthesizes identity
[0.240ms]
insecure mode > auth > uses provided user-id header
[0.070ms]
insecure mode > auth > uses provided email header
[0.050ms]
insecure mode > auth > parses groups header
[0.110ms]
sidecar mode (secure) > auth > rejects missing user-id
[0.110ms]
sidecar mode (secure) > auth > rejects missing nonce
[0.050ms]
sidecar mode (secure) > auth > rejects wrong nonce
[0.090ms]
sidecar mode (secure) > auth > accepts correct headers
[0.070ms]
sidecar mode (secure) > auth > accepts with email and groups
[0.090ms]
loopback mode > auth > rejects missing cookie
[0.140ms]
loopback mode > auth > rejects wrong cookie
[0.060ms]
loopback mode > auth > accepts correct cookie
[0.060ms]
loopback mode > auth > parses cookie among multiple cookies
[0.040ms]
token generation > auth > generateLaunchToken produces 64-char hex
[0.230ms]
token generation > auth > generateLaunchToken is unique
[0.130ms]
token generation > auth > generateSessionCookie produces hex hash
[0.100ms]
token generation > auth > generateSessionCookie is deterministic
[0.030ms]
token generation > auth > generateSessionCookie differs for different nonces
[0.030ms]
handleRefreshModels > returns 503 when localConfigPath is not configured
[3.16ms]
handleRefreshModels > returns 404 for unknown provider
[2.71ms]
handleRefreshModels > returns 400 when no API key is configured
[1.91ms]
handleRefreshModels > returns ok:false when listModels fails
[1.36ms]
handleRefreshModels > returns ok:false when listModels throws
[1.28ms]
handleRefreshModels > all models added when no persisted catalog
[1.25ms]
handleRefreshModels > full match returns all unchanged
[1.26ms]
handleRefreshModels > mixed diff: added, retired, and unchanged
[1.26ms]
handleRefreshModels > affected_aliases populated for retired models
[1.79ms]
handleRefreshModels > affected_aliases empty when retired models have no aliases
[1.06ms]
handleRefreshModels > uses humanizeModelId for models without explicit name
[3.23ms]
handleRefreshModels > resolves api_key_env from environment
[1.22ms]
handleRefreshModels > driver fallback uses provider name when driver field absent
[0.980ms]
handleListAliases > config handlers > returns empty aliases when no config path
[0.760ms]
handleListAliases > config handlers > returns empty aliases when config has none
[0.900ms]
handleListAliases > config handlers > returns aliases from config
[0.890ms]
handleSetAlias > config handlers > sets a new alias
[1.67ms]
handleSetAlias > config handlers > overwrites existing alias
[1.36ms]
handleSetAlias > config handlers > rejects invalid alias name
[2.32ms]
handleSetAlias > config handlers > rejects reserved alias name
[0.580ms]
handleSetAlias > config handlers > rejects invalid alias target (no colon)
[0.460ms]
handleSetAlias > config handlers > rejects missing target field
[0.540ms]
handleSetAlias > config handlers > returns 503 when no config path
[0.330ms]
handleSetAlias > config handlers > preserves other config sections when setting alias
[2.02ms]
handleDeleteAlias > config handlers > deletes existing alias
[1.60ms]
handleDeleteAlias > config handlers > returns 404 when alias not found
[0.780ms]
handleDeleteAlias > config handlers > returns 503 when no config path
[0.480ms]
handleListProviders > config handlers > returns empty when no config path
[0.810ms]
handleListProviders > config handlers > returns empty when config has no providers
[1.03ms]
handleListProviders > config handlers > returns providers with api_key_status, driver, and api_key_env
[1.35ms]
handleListProviders > config handlers > uses explicit driver field when set
[1.05ms]
handleListProviders > config handlers > does not expose raw api_key value
[0.950ms]
handleConfigureProvider > config handlers > creates new provider with driver in response
[1.82ms]
handleConfigureProvider > config handlers > creates provider with explicit driver different from key
[3.46ms]
handleConfigureProvider > config handlers > updates existing provider base_url without losing api_key
[1.82ms]
handleConfigureProvider > config handlers > updates api_key for existing provider
[1.70ms]
handleConfigureProvider > config handlers > setting api_key clears api_key_env
[1.45ms]
handleConfigureProvider > config handlers > setting api_key_env clears api_key
[1.26ms]
handleConfigureProvider > config handlers > returns 503 when no config path
[0.390ms]
handleDeleteProvider > config handlers > deletes existing provider
[1.62ms]
handleDeleteProvider > config handlers > returns 404 when provider not found
[0.820ms]
handleDeleteProvider > config handlers > returns 503 when no config path
[0.370ms]
handleDeleteProvider > config handlers > preserves other config sections
[1.25ms]
handleGetPreferences > config handlers > returns defaults when no config path
[0.380ms]
handleGetPreferences > config handlers > returns defaults when config has no ui section
[0.770ms]
handleGetPreferences > config handlers > returns preferences from config
[2.63ms]
handleGetPreferences > config handlers > fills defaults for missing fields
[1.00ms]
handleSetPreferences > config handlers > updates preferences
[1.75ms]
handleSetPreferences > config handlers > partial update preserves other fields
[0.960ms]
handleSetPreferences > config handlers > returns 503 when no config path
[0.340ms]
handleSetPreferences > config handlers > preserves other config sections
[1.43ms]
handleListModels > config handlers > returns 503 when no config path
[0.530ms]
handleListModels > config handlers > returns 404 for unknown provider
[0.750ms]
handleListModels > config handlers > returns empty models when provider has no models field
[0.850ms]
handleListModels > config handlers > returns persisted models with auto-generated names
[0.990ms]
handleSaveModels > config handlers > returns 503 when no config path
[0.760ms]
handleSaveModels > config handlers > returns 404 for unknown provider
[0.660ms]
handleSaveModels > config handlers > returns 400 for missing models array
[0.490ms]
handleSaveModels > config handlers > saves models and persists to config
[1.55ms]
handleSaveModels > config handlers > replaces existing models
[1.23ms]
handleSaveModels > config handlers > skips entries with missing or empty id
[3.83ms]
handleSaveModels > config handlers > preserves other provider fields
[2.03ms]
handleListProviders model_count > config handlers > includes model_count in provider listing
[0.980ms]
parseConfig: empty/minimal TOML > empty string returns all defaults
[0.520ms]
parseConfig: empty/minimal TOML > parseConfigWithDefaults returns same as parseConfig with empty string
[0.320ms]
parseConfig: partial overrides > overriding daemon.bind preserves other defaults
[0.170ms]
parseConfig: partial overrides > overriding auth.mode to insecure
[0.130ms]
parseConfig: partial overrides > setting auth.nonce_file maps to nonceFile
[0.170ms]
parseConfig: partial overrides > overriding sandbox.mode to disabled
[0.150ms]
parseConfig: partial overrides > overriding sandbox.default_seccomp to relaxed maps to defaultSeccomp
[0.130ms]
parseConfig: partial overrides > overriding logging level
[0.100ms]
parseConfig: partial overrides > setting logging.audit_sync maps to auditSync
[0.080ms]
parseConfig: partial overrides > overriding plugins.enabled with array
[0.270ms]
parseConfig: partial overrides > overriding ui.serve to false
[0.350ms]
parseConfig: partial overrides > overriding ui.url
[0.100ms]
parseConfig: partial overrides > overriding ui.url with tunnel domain
[0.090ms]
parseConfig: full config > all sections populated
[0.240ms]
parseConfig: snake_case → camelCase mapping > nonce_file → nonceFile
[0.090ms]
parseConfig: snake_case → camelCase mapping > default_seccomp → defaultSeccomp
[0.110ms]
parseConfig: snake_case → camelCase mapping > audit_sync → auditSync
[0.090ms]
parseConfig: invalid TOML > malformed TOML throws ConfigValidationError
[0.400ms]
parseConfig: invalid TOML > ConfigValidationError has issues array
[0.120ms]
parseConfig: invalid TOML > ConfigValidationError name is ConfigValidationError
[0.030ms]
parseConfig: invalid values > invalid auth.mode throws ConfigValidationError
[0.310ms]
parseConfig: invalid values > invalid sandbox.mode throws ConfigValidationError
[0.190ms]
parseConfig: invalid values > invalid sandbox.default_seccomp throws ConfigValidationError
[0.120ms]
parseConfig: invalid values > invalid logging.level throws ConfigValidationError
[0.120ms]
parseConfig: invalid values > plugins.enabled as string instead of array throws ConfigValidationError
[0.130ms]
parseConfig: invalid values > ui.serve as string instead of boolean throws ConfigValidationError
[0.110ms]
parseConfig: ConfigValidationError shape > issues contain path and message
[0.170ms]
parseConfig: ConfigValidationError shape > message summarizes validation failures
[0.120ms]
parseConfig: return type matches DaemonConfig interface > returned object has all top-level keys
[0.110ms]
parseConfig: return type matches DaemonConfig interface > daemon section has bind and home
[0.080ms]
parseConfig: return type matches DaemonConfig interface > logging section has operational, audit, level
[0.060ms]
resolveConfigPaths > fills empty storage.url relative to home
[0.090ms]
resolveConfigPaths > fills empty logging.audit relative to home
[0.090ms]
resolveConfigPaths > fills empty plugins.dir relative to home
[0.070ms]
resolveConfigPaths > does not overwrite explicitly set storage.url
[0.090ms]
resolveConfigPaths > does not overwrite explicitly set logging.audit
[0.080ms]
resolveConfigPaths > does not overwrite explicitly set plugins.dir
[0.120ms]
generateDefaultToml > produces parseable TOML
[0.400ms]
generateDefaultToml > contains home-relative paths
[0.060ms]
generateDefaultToml > starts with header comment
[0.070ms]
generateDefaultToml > round-trips through parseConfig without loss
[0.200ms]
generateCsrfToken > csrf > produces 64-char hex string
[2.34ms]
generateCsrfToken > csrf > produces unique tokens
[0.140ms]
validateCsrf > csrf > returns true when header matches cookie
[0.220ms]
validateCsrf > csrf > returns false when header missing
[0.040ms]
validateCsrf > csrf > returns false when cookie missing
[0.030ms]
validateCsrf > csrf > returns false when token mismatch
[0.080ms]
cookie headers > csrf > csrfCookieHeader format
[0.040ms]
cookie headers > csrf > csrfCookieHeader with custom path
[0.020ms]
cookie headers > csrf > sessionCookieHeader format
[0.030ms]
generateTitle > empty string returns Untitled Session
[0.100ms]
generateTitle > whitespace-only returns Untitled Session
[0.030ms]
generateTitle > extracts noun phrase and title-cases it
[32.74ms]
generateTitle > fallback to first 3 words when no noun phrase detected
[3.19ms]
generateTitle > detects noun phrase containing acronym
[3.50ms]
generateTitle > extracts first noun from sentence with proper nouns
[2.98ms]
generateTitle > detects noun phrase with adjectives
[3.12ms]
generateTitle > handles single word
[1.56ms]
generateTitle > extracts noun from two-word input
[1.75ms]
generateTitle > extracts noun phrase from imperative sentence
[2.00ms]
generateTitle > detects noun phrase with acronym
[2.81ms]
interpretTaskEffects: allocate_pty > calls broker.spawn for allocate_pty effect
[5.63ms]
interpretTaskEffects: allocate_pty > stops processing on allocate_pty failure
[0.430ms]
interpretTaskEffects: create_tmux_window > stops processing on create_tmux_window failure
[0.150ms]
interpretTaskEffects: emit effects > emit_task_launched publishes task.launched event
[0.130ms]
interpretTaskEffects: emit effects > emit_task_exited publishes task.exited with exit code
[0.120ms]
interpretTaskEffects: emit effects > emit_task_stopped publishes task.stopped
[0.110ms]
interpretTaskEffects: emit effects > emit_task_state publishes task.state with from/to
[0.140ms]
interpretTaskEffects: destroy_pty > calls handle.dispose()
[0.120ms]
interpretTaskEffects: send_sigterm > calls handle.kill()
[0.120ms]
interpretTaskEffects: effect ordering > effects execute in array order
[0.180ms]
interpretTaskEffects: effect ordering > non-spawn effect failure does not stop remaining effects
[0.120ms]
interpretTaskEffects: full lifecycle sequences > create → spawn → exit produces correct effect sequence
[0.330ms]
interpretTaskEffects: persist_transcript > persists scrollback from handle to storage
[0.490ms]
interpretTaskEffects: persist_transcript > skips when no storage adapter
[0.100ms]
interpretTaskEffects: persist_transcript > skips when handle not found
[0.100ms]
interpretTaskEffects: persist_transcript > skips when scrollback is empty
[0.110ms]
interpretTaskEffects: persist_transcript > generates unique transcript id
[0.200ms]
interpretTaskEffects: persist_transcript > merges multiple scrollback chunks into single blob
[0.230ms]
GATE_ORDER > contains exactly 6 gates in spec order
[0.030ms]
GATE_ORDER > every gate has a corresponding exit code
[0.050ms]
bootstrap_complete > bootstrapping + bootstrap_complete → self_check
[0.160ms]
bootstrap_complete > emits emit_bootstrap then run_gate for all 6 gates in order
[0.070ms]
bootstrap_complete > run_gate side effects carry correct gate names in spec order
[0.050ms]
bootstrap_complete > total side effects = 1 emit_bootstrap + 6 run_gate
[0.020ms]
bootstrap_complete > self_check + bootstrap_complete → DaemonLifecycleError
[0.110ms]
bootstrap_complete > running + bootstrap_complete → DaemonLifecycleError
[0.010ms]
bootstrap_complete > draining + bootstrap_complete → DaemonLifecycleError
[0.010ms]
bootstrap_complete > stopped + bootstrap_complete → DaemonLifecycleError
[0.010ms]
self_check_passed > self_check + self_check_passed → running
[0.050ms]
self_check_passed > emits open_listener, spawn_plugins, load_projects, emit_ready
[0.030ms]
self_check_passed > bootstrapping + self_check_passed → DaemonLifecycleError
[0.040ms]
self_check_passed > running + self_check_passed → DaemonLifecycleError
[0.010ms]
self_check_passed > draining + self_check_passed → DaemonLifecycleError
[0.010ms]
self_check_passed > stopped + self_check_passed → DaemonLifecycleError
[0.010ms]
self_check_failed > self_check + self_check_failed → stopped
[0.070ms]
self_check_failed > gate auth → correct exit code
[0.050ms]
self_check_failed > gate bind → correct exit code
[0.010ms]
self_check_failed > gate sandbox → correct exit code
[0.010ms]
self_check_failed > gate storage → correct exit code
[0.010ms]
self_check_failed > gate plugins → correct exit code
[0.010ms]
self_check_failed > gate filesystem → correct exit code
[0.010ms]
self_check_failed > exit codes are 10-15 for auth through filesystem
[0.030ms]
self_check_failed > emits emit_shutdown with gate_failed reason containing gate name and message
[0.050ms]
self_check_failed > side effects are [emit_shutdown, exit]
[0.030ms]
self_check_failed > bootstrapping + self_check_failed → DaemonLifecycleError
[0.060ms]
self_check_failed > running + self_check_failed → DaemonLifecycleError
[0.010ms]
self_check_failed > draining + self_check_failed → DaemonLifecycleError
[0.020ms]
self_check_failed > stopped + self_check_failed → DaemonLifecycleError
[0.010ms]
sigterm > bootstrapping + sigterm → draining
[0.070ms]
sigterm > self_check + sigterm → draining
[0.030ms]
sigterm > running + sigterm → draining
[0.020ms]
sigterm > draining side effects include full shutdown sequence
[0.030ms]
sigterm > emit_shutdown reason is sigterm
[0.040ms]
sigterm > double sigterm (draining + sigterm) → stopped (force_stop)
[0.100ms]
sigterm > double sigterm emits force_stop shutdown reason and exit 0
[0.130ms]
sigterm > stopped + sigterm → DaemonLifecycleError
[0.050ms]
drain_complete > draining + drain_complete → stopped
[0.050ms]
drain_complete > emits exit code 0
[0.030ms]
drain_complete > bootstrapping + drain_complete → DaemonLifecycleError
[0.040ms]
drain_complete > self_check + drain_complete → DaemonLifecycleError
[0.020ms]
drain_complete > running + drain_complete → DaemonLifecycleError
[0.010ms]
drain_complete > stopped + drain_complete → DaemonLifecycleError
[0.010ms]
force_stop > draining + force_stop → stopped
[0.030ms]
force_stop > running + force_stop → stopped
[0.030ms]
force_stop > emits emit_shutdown with force_stop reason and exit 0
[0.030ms]
force_stop > bootstrapping + force_stop → DaemonLifecycleError
[0.040ms]
force_stop > self_check + force_stop → DaemonLifecycleError
[0.010ms]
force_stop > stopped + force_stop → DaemonLifecycleError
[0.020ms]
DaemonLifecycleError > exposes phase and event
[0.090ms]
DaemonLifecycleError > name is DaemonLifecycleError
[0.020ms]
DaemonLifecycleError > default message includes phase and event
[0.030ms]
DaemonLifecycleError > custom message overrides default
[0.050ms]
full lifecycle walkthrough > happy path: bootstrapping → self_check → running → draining → stopped
[0.050ms]
full lifecycle walkthrough > failed gate path: bootstrapping → self_check → stopped
[0.070ms]
full lifecycle walkthrough > double sigterm path: running → draining → stopped (force)
[0.050ms]
log streaming > subscriber registry filters by project, minimum level, and source
[1.34ms]
log streaming > SSE handler returns 404 for missing projects
[1.25ms]
log streaming > SSE handler returns 400 for invalid level and source filters
[1.29ms]
log streaming > route handler map wires project log stream endpoint
[0.740ms]
serializeMessage > produces Content-Length header with correct byte length
[0.170ms]
serializeMessage > handles multibyte UTF-8 correctly
[0.080ms]
serializeMessage > body is valid JSON
[0.060ms]
JsonRpcParser > parses a single complete message
[0.300ms]
JsonRpcParser > parses multiple messages fed at once
[0.250ms]
JsonRpcParser > handles chunked delivery across feeds
[0.130ms]
JsonRpcParser > handles partial header delivery
[0.080ms]
JsonRpcParser > handles byte-at-a-time delivery
[0.420ms]
JsonRpcParser > parses notifications (no id)
[0.110ms]
JsonRpcParser > parses error responses
[0.090ms]
JsonRpcParser > roundtrips through serialize then parse
[0.100ms]
type guards > isResponse identifies responses
[0.050ms]
type guards > isNotification identifies notifications
[0.030ms]
type guards > request has both id and method — neither guard matches
[0.020ms]
reconstructMessageParts > returns empty parts and empty thinking for null metadata
[0.230ms]
reconstructMessageParts > returns empty parts when metadata lacks contentBlocks
[0.030ms]
reconstructMessageParts > returns empty parts when contentBlocks is not an array
[0.030ms]
reconstructMessageParts > emits a single text part for a text-only assistant message
[0.060ms]
reconstructMessageParts > thinking appears as a positioned part in parts, and in the thinking string
[0.050ms]
reconstructMessageParts > multiple thinking blocks each appear as positioned parts, concatenated in thinking string
[0.040ms]
reconstructMessageParts > emits a tool_call part with no paired tool_result when toolResults is absent
[0.050ms]
reconstructMessageParts > pairs tool_call with tool_result when toolResults has the matching id
[0.100ms]
reconstructMessageParts > string outputs pass through tool_result.output verbatim
[0.070ms]
reconstructMessageParts > error tool_result sets is_error: true
[0.060ms]
reconstructMessageParts > interleaves text and tool_call+tool_result in original order
[0.070ms]
reconstructMessageParts > thinking is positioned within the interleaved sequence
[0.090ms]
reconstructMessageParts > multi-step loop: thinking→text→tool→thinking→text preserved in order
[0.130ms]
reconstructMessageParts > multiple tool calls each get paired with their own result
[0.070ms]
reconstructMessageParts > skips malformed toolCall blocks (missing id or name)
[0.050ms]
reconstructMessageParts > ignores non-object entries in contentBlocks
[0.030ms]
reconstructMessageParts > toolCall with non-object arguments defaults to empty input object
[0.030ms]
resolveMode: step 1 — explicit override > explicit user → user regardless of other signals
[1.63ms]
resolveMode: step 1 — explicit override > explicit system → system regardless of other signals
[0.030ms]
resolveMode: step 2 — KAGED_HOME path inference > /var/lib/kaged → system
[0.050ms]
resolveMode: step 2 — KAGED_HOME path inference > /opt/kaged → system
[0.020ms]
resolveMode: step 2 — KAGED_HOME path inference > /etc/kaged → system
[0.020ms]
resolveMode: step 2 — KAGED_HOME path inference > path under homeDir → user
[0.030ms]
resolveMode: step 2 — KAGED_HOME path inference > path under XDG_DATA_HOME → user
[0.020ms]
resolveMode: step 2 — KAGED_HOME path inference > unrecognized KAGED_HOME falls through to step 3+
[0.020ms]
resolveMode: step 3 — UID / dedicated-user check > uid 0 → system
[0.020ms]
resolveMode: step 3 — UID / dedicated-user check > dedicated user → system
[0.020ms]
resolveMode: step 3 — UID / dedicated-user check > non-root non-dedicated → falls through
[0.020ms]
resolveMode: step 4 — XDG / var/lib probe > xdgDataExists → user
[0.020ms]
resolveMode: step 4 — XDG / var/lib probe > varLibExists → system
[0.020ms]
resolveMode: step 4 — XDG / var/lib probe > both exist → user wins (XDG checked first)
[0.020ms]
resolveMode: step 5 — default > no signals → user
[0.020ms]
resolveMode: priority order > explicit beats KAGED_HOME
[0.020ms]
resolveMode: priority order > KAGED_HOME beats UID
[0.020ms]
resolveMode: priority order > UID beats XDG probe
[0.020ms]
resolveMode: priority order > XDG probe beats varLib probe
[0.020ms]
defaultHome > system → /var/lib/kaged
[0.030ms]
defaultHome > user without XDG → ~/.local/share/kaged
[0.020ms]
defaultHome > user with XDG_DATA_HOME → $XDG_DATA_HOME/kaged
[0.020ms]
defaultHome > system ignores XDG_DATA_HOME
[0.020ms]
defaultConfigPath > system → /etc/kaged/config.toml
[0.030ms]
defaultConfigPath > user without XDG → ~/.config/kaged/config.toml
[0.020ms]
defaultConfigPath > user with XDG_CONFIG_HOME → $XDG_CONFIG_HOME/kaged/config.toml
[0.020ms]
defaultConfigPath > system ignores XDG_CONFIG_HOME
[0.010ms]
defaultBind > system → 127.0.0.1:7777
[0.020ms]
defaultBind > user → 127.0.0.1:0 (OS-assigned port)
[0.020ms]
defaultAuthMode > system → secure
[0.020ms]
defaultAuthMode > user → secure
[0.010ms]
defaultRuntimeDir > user without XDG_RUNTIME_DIR → /tmp/kaged-<uid>
[0.030ms]
defaultRuntimeDir > user with XDG_RUNTIME_DIR → $XDG_RUNTIME_DIR/kaged
[0.020ms]
defaultRuntimeDir > system → $KAGED_HOME (uses home param)
[0.010ms]
defaultRuntimeDir > system ignores XDG_RUNTIME_DIR
[0.010ms]
defaultNoncePath > user → $runtimeDir/auth-cookie
[0.020ms]
defaultNoncePath > system → $runtimeDir/auth-nonce
[0.010ms]
defaultLaunchUrlPath > user → $runtimeDir/launch-url
[0.020ms]
defaultLaunchUrlPath > system → $runtimeDir/launch-url
[0.010ms]
slugifyDirName > simple directory name passes through
[0.170ms]
slugifyDirName > uppercased name lowered
[0.040ms]
slugifyDirName > spaces replaced with hyphens
[0.020ms]
slugifyDirName > underscores replaced with hyphens
[0.020ms]
slugifyDirName > consecutive hyphens collapsed
[0.020ms]
slugifyDirName > leading/trailing hyphens stripped
[0.020ms]
slugifyDirName > non-alphanumeric chars removed
[0.020ms]
slugifyDirName > truncated to 64 chars
[0.040ms]
slugifyDirName > single char padded to valid slug
[0.030ms]
slugifyDirName > empty string falls back to default
[0.100ms]
slugifyDirName > dot-prefixed name cleaned
[0.020ms]
slugifyDirName > result always valid per ProjectSlugSchema
[0.120ms]
generateDefaultProjectYaml > produces valid YAML
[11.13ms]
generateDefaultProjectYaml > passes DSL schema validation
[2.24ms]
generateDefaultProjectYaml > uses provided slug
[0.790ms]
generateDefaultProjectYaml > uses smart-generalist as default model
[0.830ms]
generateDefaultProjectYaml > system_prompt uses config:/ prefix by default
[0.830ms]
initProjectDir > creates .kaged directory
[7.19ms]
initProjectDir > creates project.yaml in .kaged
[2.50ms]
initProjectDir > project.yaml is valid DSL
[3.33ms]
initProjectDir > slug derived from directory name
[2.73ms]
initProjectDir > creates prompts directory with placeholder in .kaged
[5.39ms]
initProjectDir > prompt placeholder is non-empty
[2.15ms]
initProjectDir > skips if .kaged/project.yaml already exists
[1.62ms]
initProjectDir > returns parsed DSL data
[2.04ms]
initProjectDir > returns parsed DSL for existing project
[1.56ms]
initProjectDir > creates compaction-summary.md in prompts directory
[2.40ms]
initProjectDir > compaction-summary.md is non-empty
[5.68ms]
initProjectDir > does not overwrite existing compaction-summary.md
[2.05ms]
PtyBroker: construction > creates with default options
[0.140ms]
PtyBroker: construction > creates with custom maxPerProject
[0.030ms]
PtyBroker: construction > empty broker returns undefined for unknown taskId
[0.050ms]
PtyBroker: construction > empty broker returns empty list for any project
[0.140ms]
PtyBroker: spawn (raw PTY) > spawn returns a PtyHandle
[3.41ms]
PtyBroker: spawn (raw PTY) > spawned handle is retrievable via get()
[1.35ms]
PtyBroker: spawn (raw PTY) > spawned handle appears in listByProject()
[0.870ms]
PtyBroker: spawn (raw PTY) > count increments after spawn
[1.03ms]
PtyBroker: spawn (raw PTY) > multiple spawns for different projects are independent
[1.93ms]
PtyBroker: concurrency limit > throws PtyLimitError when project limit reached
[1.67ms]
PtyBroker: concurrency limit > PtyLimitError has correct properties
[0.990ms]
PtyBroker: concurrency limit > different projects have independent limits
[1.54ms]
PtyBroker: output and scrollback > onData callback receives process output
[501.41ms]
PtyBroker: output and scrollback > getScrollback returns buffered output
[505.89ms]
PtyBroker: output and scrollback > scrollback ring buffer respects capacity
[1.01s]
PtyBroker: write (stdin) > write sends data to process stdin
[504.43ms]
PtyBroker: resize > resize updates handle dimensions
[1.86ms]
PtyBroker: resize > default dimensions when not specified
[1.55ms]
PtyBroker: resize > tmux spawn threads initial dimensions into session and window creation
[1.09ms]
PtyBroker: resize > tmux handle resize uses window resize authority and pane resize
[0.380ms]
PtyBroker: kill and exit > kill() terminates the process
[2.57ms]
PtyBroker: kill and exit > onExit fires with exit code on natural exit
[2.72ms]
PtyBroker: kill and exit > onExit fires with non-zero for failing command
[2.59ms]
PtyBroker: dispose > dispose removes handle from registry
[1.20ms]
PtyBroker: dispose > disposeAll clears all handles
[2.54ms]
PtyBroker: dispose > spawn succeeds after dispose frees a slot
[1.81ms]
RateLimiter > allows requests under limit
[0.430ms]
RateLimiter > blocks requests over limit
[0.350ms]
RateLimiter > allows after window expires
[0.260ms]
RateLimiter > isolates users
[0.230ms]
RateLimiter > uses default limit for unknown routes
[0.120ms]
RateLimiter > uses specific limit for messages route
[0.070ms]
RateLimiter > reset clears user's windows
[0.270ms]
RateLimiter > remaining decreases
[0.100ms]
reconstructMessages > converts operator messages to user role
[1.85ms]
reconstructMessages > converts primary messages to assistant role
[0.040ms]
reconstructMessages > skips superseded messages
[0.050ms]
reconstructMessages > includes tool calls from contentBlocks when includeToolResults is true
[0.120ms]
reconstructMessages > omits tool calls when includeToolResults is false
[0.050ms]
reconstructMessages > defaults includeToolResults to true
[0.050ms]
reconstructMessages > handles multiple tool calls with separate results
[0.090ms]
reconstructMessages > handles assistant message with no metadata gracefully
[0.030ms]
reconstructMessages > handles tool call with missing result
[0.040ms]
reconstructMessages > interleaves user and assistant messages with tool calls in order
[0.070ms]
reconstructMessages > skips malformed toolCall blocks without id or name
[0.050ms]
request-id > generates 26-character ULID
[0.080ms]
request-id > generates valid ULID characters
[0.160ms]
request-id > generates unique IDs
[2.89ms]
request-id > generates sortable IDs (later calls produce lexicographically greater values)
[0.080ms]
isValidUlid &gt; request-id > accepts valid ULID
[0.040ms]
isValidUlid &gt; request-id > rejects wrong length
[0.030ms]
isValidUlid &gt; request-id > rejects invalid characters
[0.020ms]
exact matches &gt; Router > matches /healthz
[0.180ms]
exact matches &gt; Router > matches /readyz
[0.040ms]
exact matches &gt; Router > matches /api/v1/projects
[0.020ms]
exact matches &gt; Router > matches POST /api/v1/projects/load
[0.030ms]
parameterized matches &gt; Router > extracts single param :id
[0.040ms]
parameterized matches &gt; Router > extracts multiple params :id and :cid
[0.080ms]
parameterized matches &gt; Router > DELETE with param
[0.070ms]
percent-encoded params &gt; Router > decodes %3A to colon in :id (guest userId pattern)
[0.030ms]
percent-encoded params &gt; Router > decodes %20 to space
[0.030ms]
percent-encoded params &gt; Router > decodes multiple encoded params independently
[0.030ms]
percent-encoded params &gt; Router > returns null for malformed percent-encoding
[0.100ms]
percent-encoded params &gt; Router > leaves already-decoded path segments unchanged
[0.040ms]
non-matches &gt; Router > returns null for unknown path
[0.020ms]
non-matches &gt; Router > returns null for wrong method on known path
[0.040ms]
non-matches &gt; Router > returns null for too-short path
[0.030ms]
non-matches &gt; Router > returns null for too-long path
[0.020ms]
non-matches &gt; Router > returns null for empty path
[0.020ms]
methodsForPath &gt; Router > returns GET and DELETE for /api/v1/projects/:id
[0.100ms]
methodsForPath &gt; Router > returns empty for unknown path
[0.020ms]
methodsForPath &gt; Router > returns GET only for /healthz
[0.020ms]
with full route table &gt; Router > matches all routes from route registry
[1.62ms]
writeNonceFile > creates file with nonce content
[2.41ms]
writeNonceFile > creates file with mode 0600
[0.220ms]
writeNonceFile > creates parent directories
[0.240ms]
writeNonceFile > overwrites existing file
[0.180ms]
writeLaunchUrlFile > creates file with URL content
[0.190ms]
writeLaunchUrlFile > creates file with mode 0600
[0.170ms]
writeLaunchUrlFile > overwrites on regeneration
[0.240ms]
readNonceFile > reads existing nonce
[0.190ms]
readNonceFile > returns null for missing file
[0.130ms]
readLaunchUrlFile > reads existing launch URL
[0.200ms]
readLaunchUrlFile > returns null for missing file
[0.110ms]
cleanupRuntimeFiles > removes nonce and launch-url files
[0.440ms]
cleanupRuntimeFiles > does not throw if files do not exist
[0.220ms]
handleAuthNonce > prints nonce from file to stdout
[0.300ms]
handleAuthNonce > exits non-zero in insecure mode
[0.230ms]
handleAuthNonce > exits non-zero when nonce file missing
[0.180ms]
handleAuthOpen > reads launch URL and returns it for opening
[0.320ms]
handleAuthOpen > exits non-zero in insecure mode
[0.140ms]
handleAuthOpen > exits non-zero when launch-url file missing
[0.180ms]
detectBrowserOpener > returns a string on linux/mac
[6.76ms]
search.grep handler > rejects absolute paths
[2.78ms]
search.grep handler > rejects path traversal
[0.430ms]
search.grep handler > searches project root when no path given
[9.10ms]
search.grep handler > respects head_limit
[2.99ms]
search.grep handler > searches subdirectory when path given
[4.76ms]
search.grep handler > returns relative file paths
[2.09ms]
search.grep handler > returns empty matches for no-hit pattern
[1.97ms]
search.grep handler > include filter limits to matching files
[2.20ms]
search.glob handler > rejects absolute paths
[0.620ms]
search.glob handler > rejects path traversal
[0.420ms]
search.glob handler > finds files matching glob pattern
[2.74ms]
search.glob handler > returns relative paths
[3.83ms]
search.glob handler > returns empty for no matches
[2.08ms]
search.ast handler > rejects absolute paths in paths array
[0.580ms]
search.ast handler > rejects path traversal in paths array
[0.310ms]
search.ast handler > finds AST pattern in typescript file
[2.28ms]
search.ast handler > returns empty for no AST matches
[1.97ms]
search.ast handler > searches subdirectory via paths param
[2.24ms]
service endpoints &gt; server integration > GET /healthz returns 200 ok
[2.72ms]
service endpoints &gt; server integration > GET /readyz returns 200 ready when ready
[0.380ms]
service endpoints &gt; server integration > GET /readyz returns 503 when not ready
[0.250ms]
service endpoints &gt; server integration > GET /api/versions returns version manifest
[0.280ms]
response headers &gt; server integration > includes X-Kaged-Request-Id
[0.270ms]
response headers &gt; server integration > includes X-Kaged-Daemon-Version
[0.230ms]
response headers &gt; server integration > includes Cache-Control: no-store
[0.190ms]
response headers &gt; server integration > includes X-Kaged-Warning in insecure mode
[0.190ms]
response headers &gt; server integration > request IDs are unique across requests
[0.390ms]
authenticated endpoints &gt; server integration > GET /api/v1/me returns operator info in insecure mode
[0.700ms]
authenticated endpoints &gt; server integration > GET /api/v1/me sets CSRF cookie
[0.350ms]
authenticated endpoints &gt; server integration > GET /api/v1/dsl/schema returns schema
[0.310ms]
stub endpoints &gt; server integration > GET /api/v1/projects returns 200 with empty list
[0.430ms]
stub endpoints &gt; server integration > POST /api/v1/dsl/validate returns 422 for invalid DSL
[2.73ms]
stub endpoints &gt; server integration > GET /api/v1/sessions/01HXAB returns 503 without storage
[0.390ms]
routing &gt; server integration > unknown path returns 404
[0.280ms]
routing &gt; server integration > wrong method returns 405 with Allow header
[0.280ms]
routing &gt; server integration > OPTIONS returns 204 with CORS headers
[0.340ms]
with sandbox disabled &gt; server integration > warning header includes both insecure-mode and no-sandbox
[0.520ms]
secure mode auth rejection &gt; server integration > unauthenticated endpoints still work without auth
[1.64ms]
secure mode auth rejection &gt; server integration > authenticated endpoint rejects without headers
[0.290ms]
secure mode auth rejection &gt; server integration > authenticated endpoint rejects wrong nonce
[0.230ms]
secure mode auth rejection &gt; server integration > authenticated endpoint accepts correct headers
[0.340ms]
secure mode auth rejection &gt; server integration > no warning header in secure+sandbox mode
[0.220ms]
loopback launch flow &gt; server integration > launch with correct token returns 302 redirect to /
[0.660ms]
loopback launch flow &gt; server integration > launch sets kaged_session cookie with HttpOnly and SameSite=Lax
[3.60ms]
loopback launch flow &gt; server integration > launch with wrong token returns 401 with invalid_launch_token reason
[3.17ms]
loopback launch flow &gt; server integration > launch with missing token returns 401
[5.07ms]
loopback launch flow &gt; server integration > launch token is single-use — second request returns 401
[3.62ms]
loopback launch flow &gt; server integration > launch returns 404 in insecure mode
[3.88ms]
loopback launch flow &gt; server integration > launch returns 404 in sidecar mode (system deployment)
[2.74ms]
loopback launch flow &gt; server integration > after launch, cookie authenticates subsequent requests
[3.66ms]
loopback launch flow &gt; server integration > without cookie, authenticated endpoints reject in loopback mode
[2.80ms]
loopback launch flow &gt; server integration > after token consumption, a new token is generated and works
[3.64ms]
loopback launch flow &gt; server integration > regenerated launch URL uses uiUrl when configured
[2.99ms]
loopback launch flow &gt; server integration > regenerated launch URL falls back to daemon bind when uiUrl is empty
[3.42ms]
launch endpoint content negotiation &gt; server integration > Accept: application/json returns 200 with JSON body on valid token
[2.82ms]
launch endpoint content negotiation &gt; server integration > Accept: application/json sets session and CSRF cookies on success
[5.07ms]
launch endpoint content negotiation &gt; server integration > Accept: application/json returns 401 JSON on invalid token
[3.96ms]
launch endpoint content negotiation &gt; server integration > Accept: application/json still regenerates token after consumption
[3.21ms]
launch endpoint content negotiation &gt; server integration > without Accept header, launch still returns 302 redirect
[3.42ms]
session title auto-generation > posting first message auto-generates title from message content
[19.74ms]
session title auto-generation > posting message does not overwrite existing title
[8.55ms]
session title auto-generation > auto-generated title from acronym in message
[11.55ms]
session title auto-generation > auto-generated title from noun phrase in message
[8.82ms]
handleUpdateSession > renames session with valid label
[6.78ms]
handleUpdateSession > clears session name with empty label
[4.73ms]
handleUpdateSession > trims whitespace from label
[6.78ms]
handleUpdateSession > returns 400 for missing label field
[5.44ms]
handleUpdateSession > returns 400 for non-string label
[4.61ms]
handleUpdateSession > returns 400 for label exceeding 120 chars
[6.26ms]
handleUpdateSession > returns 400 for invalid JSON body
[5.69ms]
handleUpdateSession > returns 404 for non-existent session
[4.46ms]
handleUpdateSession > returns 503 when storage is unavailable
[6.16ms]
handleUpdateSession > label at exactly 120 chars is accepted
[5.63ms]
handleUpdateSession > renamed session persists across get
[4.58ms]
loadAll &gt; SystemPluginLoader > happy path: loads and activates a plugin
[1.82ms]
loadAll &gt; SystemPluginLoader > setup receives ctx with config, log, on, off
[0.260ms]
loadAll &gt; SystemPluginLoader > disabled plugin is not imported
[0.150ms]
loadAll &gt; SystemPluginLoader > loads plugins in alphabetical order
[0.260ms]
loadAll &gt; SystemPluginLoader > resolves default path from kagedHome when no path specified
[0.160ms]
loadAll &gt; SystemPluginLoader > failed import: nonexistent path → failed state, daemon continues
[0.300ms]
loadAll &gt; SystemPluginLoader > bad export: no default export → failed state
[0.130ms]
loadAll &gt; SystemPluginLoader > bad export: missing setup method → failed state
[0.130ms]
loadAll &gt; SystemPluginLoader > name mismatch → failed state
[0.120ms]
loadAll &gt; SystemPluginLoader > setup() throws → failed state, other plugins still load
[0.240ms]
loadAll &gt; SystemPluginLoader > setup() timeout → failed state
[52.19ms]
fireHook &gt; SystemPluginLoader > fires registered hook callback with correct args
[0.630ms]
fireHook &gt; SystemPluginLoader > fires multiple callbacks in registration order
[0.420ms]
fireHook &gt; SystemPluginLoader > hook callback error: logged, other callbacks still fire
[0.390ms]
fireHook &gt; SystemPluginLoader > hook callback timeout: logged, other callbacks still fire
[53.60ms]
fireHook &gt; SystemPluginLoader > no-op when no callbacks registered for hook
[0.390ms]
fireHook &gt; SystemPluginLoader > off() unregisters a callback
[0.700ms]
fireHook &gt; SystemPluginLoader > does not fire hooks for failed plugins
[0.500ms]
teardownAll &gt; SystemPluginLoader > calls teardown() on active plugins
[1.11ms]
teardownAll &gt; SystemPluginLoader > sets stopped state even for plugins without teardown()
[0.390ms]
teardownAll &gt; SystemPluginLoader > teardown() error logged but does not block other teardowns
[0.870ms]
teardownAll &gt; SystemPluginLoader > teardown() timeout logged as warning
[55.09ms]
getStates &gt; SystemPluginLoader > returns status for all configured plugins
[0.720ms]
getStates &gt; SystemPluginLoader > failed plugin includes error message
[0.450ms]
plugin logger &gt; SystemPluginLoader > log methods include plugin name prefix
[0.720ms]
task handlers E2E: real broker + real storage > run ad-hoc command: spawns, persists, exits cleanly
[1.03s]
task handlers E2E: real broker + real storage > run named task from DSL: resolves command from project.yaml
[1.03s]
task handlers E2E: real broker + real storage > run named task not found: returns 404
[19.00ms]
task handlers E2E: real broker + real storage > stop running task: terminates process, updates state
[223.57ms]
task handlers E2E: real broker + real storage > restart task: stops old, spawns new instance
[223.29ms]
task handlers E2E: real broker + real storage > list tasks returns instances for project
[1.04s]
task handlers E2E: real broker + real storage > list task instances via paginated endpoint
[519.03ms]
task handlers E2E: real broker + real storage > get task instance by ID
[7.72ms]
task handlers E2E: real broker + real storage > get nonexistent task instance returns 404
[4.99ms]
task handlers E2E: real broker + real storage > delete completed task instance
[1.01s]
task handlers E2E: real broker + real storage > delete running task instance returns 409 conflict
[208.53ms]
task handlers E2E: real broker + real storage > process output captured in scrollback buffer
[1.02s]
task handlers E2E: real broker + real storage > concurrency limit rejects with 429
[23.77ms]
task handlers E2E: real broker + real storage > rejects missing command and task
[13.31ms]
task handlers E2E: real broker + real storage > rejects command exceeding 4096 chars
[13.80ms]
task handlers E2E: real broker + real storage > rejects absolute cwd
[12.82ms]
task handlers E2E: real broker + real storage > rejects cwd with .. escape
[17.89ms]
task handlers E2E: real broker + real storage > passes requested terminal dimensions into the spawned handle
[20.05ms]
task handlers E2E: real broker + real storage > invalid dimensions fall back to defaults per field
[16.40ms]
task handlers E2E: real broker + real storage > oversized dimensions are clamped before spawn
[15.69ms]
task handlers E2E: real broker + real storage > no broker returns 503
[8.19ms]
task handlers E2E: real broker + real storage > cleanupProjectTasks stops running tasks and removes handles
[221.98ms]
task handlers E2E: real broker + real storage > cleanupProjectTasks returns 0 when no running tasks
[1.01s]
task handlers E2E: real broker + real storage > cleanupProjectTasks is a no-op for unknown project
[4.96ms]
task handlers E2E: real broker + real storage > PTY limit excludes exited handles
[1.02s]
task handlers E2E: real broker + real storage > cleanup task instances deletes non-running tasks for project
[1.04s]
task handlers E2E: real broker + real storage > cleanup task instances is a no-op when no deletable tasks
[26.61ms]
resolveNamedTask: lookup > returns task when name matches
[5.06ms]
resolveNamedTask: lookup > returns null when name not found
[2.49ms]
resolveNamedTask: lookup > returns null when no tasks block
[1.81ms]
resolveNamedTask: lookup > returns null when project.yaml missing
[0.600ms]
resolveNamedTask: lookup > returns null when YAML is invalid
[5.91ms]
resolveNamedTask: lookup > returns null when DSL schema validation fails
[7.25ms]
resolveNamedTask: task fields > resolves cwd from task definition
[2.25ms]
resolveNamedTask: task fields > resolves env from task definition
[3.25ms]
resolveNamedTask: task fields > task without cwd/env returns undefined for those fields
[2.11ms]
resolveNamedTask: task fields > long_running defaults to false
[9.40ms]
recoverTasksOnStartup: no sessions > returns zeroed result when no tmux sessions exist
[1.97ms]
recoverTasksOnStartup: no sessions > returns zeroed result when sessions exist but no stored tasks
[0.570ms]
recoverTasksOnStartup: tmux reattach (spec step 3) > reattaches running task whose tmux window still exists
[0.890ms]
recoverTasksOnStartup: tmux reattach (spec step 3) > updates storage with running state and new PID after reattach
[0.450ms]
recoverTasksOnStartup: tmux reattach (spec step 3) > reattaches multiple tasks across sessions
[0.530ms]
recoverTasksOnStartup: tmux reconcile (spec step 4) > marks task failed when tmux window is gone
[0.440ms]
recoverTasksOnStartup: tmux reconcile (spec step 4) > marks task failed when tmux session itself is gone
[0.170ms]
recoverTasksOnStartup: tmux reconcile (spec step 4) > gracefully handles reattach failure by marking task failed
[0.780ms]
recoverTasksOnStartup: orphaned sessions (spec step 5) > reports orphaned sessions with no matching tasks
[0.400ms]
recoverTasksOnStartup: orphaned sessions (spec step 5) > session with reattached tasks is not orphaned
[0.390ms]
recoverTasksOnStartup: raw PTY orphans (spec §Startup raw PTY) > marks running raw PTY tasks as failed
[0.330ms]
recoverTasksOnStartup: raw PTY orphans (spec §Startup raw PTY) > handles mixed tmux and pty tasks
[0.540ms]
recoverTasksOnStartup: starting state tasks > treats 'starting' tmux tasks same as 'running'
[0.430ms]
recoverTasksOnStartup: starting state tasks > treats 'starting' raw PTY tasks as orphaned
[0.240ms]
recoverTasksOnStartup: listWindows failure > treats listWindows error as empty windows (reconciles tasks)
[0.320ms]
recoverTasksOnStartup: ignores non-running tasks > does not touch done/failed/stopped tasks
[0.210ms]
parseControlModeLine > parses %window-add event
[0.200ms]
parseControlModeLine > parses %window-close event
[0.060ms]
parseControlModeLine > parses %pane-exited event with exit code
[0.050ms]
parseControlModeLine > parses %pane-exited with non-zero exit code
[0.040ms]
parseControlModeLine > parses %session-closed event
[0.030ms]
parseControlModeLine > returns null for non-event lines
[0.020ms]
parseControlModeLine > returns null for empty string
[0.020ms]
parseControlModeLine > returns null for lines without % prefix
[0.020ms]
parseControlModeLine > handles %begin and %end blocks (no event emitted)
[0.030ms]
decodeTmuxOctalEscapes > passes through plain ASCII
[0.480ms]
decodeTmuxOctalEscapes > decodes newline octal
[0.080ms]
decodeTmuxOctalEscapes > decodes tab octal
[0.080ms]
decodeTmuxOctalEscapes > decodes ESC sequences
[0.110ms]
decodeTmuxOctalEscapes > decodes literal backslash escaped as \134 (tmux never emits \\)
[0.120ms]
decodeTmuxOctalEscapes > preserves raw high bytes (Nerd Font glyph EF 81 BB) unchanged
[0.060ms]
decodeTmuxOctalEscapes > decodes octal escape at end of input (no off-by-one)
[0.040ms]
decodeTmuxOctalEscapes > handles empty input
[0.030ms]
parsePaneOutput > parses %output line with pane id and plain text data
[0.240ms]
parsePaneOutput > returns null for non-output lines
[0.120ms]
parsePaneOutput > returns null for empty input
[0.040ms]
parsePaneOutput > handles output with spaces in data
[0.130ms]
parsePaneOutput > handles multi-pane output routing
[0.090ms]
parsePaneOutput > decodes octal escapes for newline
[0.080ms]
parsePaneOutput > decodes carriage return + newline
[0.090ms]
parsePaneOutput > preserves raw high-byte payload (glyph) end-to-end
[0.120ms]
parseSessionListLine > parses valid session line
[0.150ms]
parseSessionListLine > parses session with single window
[0.050ms]
parseSessionListLine > returns null for empty string
[0.030ms]
parseSessionListLine > returns null for whitespace-only string
[0.020ms]
parseSessionListLine > returns null for too few fields
[0.030ms]
parseSessionListLine > returns null for non-numeric window count
[0.020ms]
parseSessionListLine > returns null for non-numeric created timestamp
[0.030ms]
parseSessionListLine > trims leading/trailing whitespace
[0.040ms]
parseSessionListLine > handles extra tab-separated fields gracefully
[0.050ms]
parseWindowListLine > parses active window
[0.120ms]
parseWindowListLine > parses inactive window
[0.040ms]
parseWindowListLine > returns null for empty string
[0.020ms]
parseWindowListLine > returns null for too few fields
[0.020ms]
parseWindowListLine > returns null for non-numeric pid
[0.020ms]
parseWindowListLine > treats any non-'1' active field as inactive
[0.030ms]
parsePaneListLine > parses valid pane line
[0.100ms]
parsePaneListLine > returns null for empty string
[0.030ms]
parsePaneListLine > returns null for too few fields
[0.030ms]
parsePaneListLine > returns null for non-numeric pid
[0.030ms]
parsePaneListLine > handles extra fields gracefully
[0.040ms]
TmuxCommandError > has correct name
[0.130ms]
TmuxCommandError > is instanceof Error
[0.040ms]
TmuxCommandError > stores command, exitCode, and stderr
[0.060ms]
TmuxCommandError > message includes exit code and command
[0.050ms]
BunTmuxDriver command orchestration > ensureSession creates sized session and forces manual window-size per-session
[0.760ms]
BunTmuxDriver command orchestration > ensureSession still enforces manual window-size for existing sessions
[0.270ms]
BunTmuxDriver command orchestration > createWindow disables aggressive-resize and sizes the window authoritatively
[0.890ms]
BunTmuxDriver command orchestration > resizeWindow targets the tmux window
[0.200ms]
BunTmuxDriver command orchestration > all direct tmux commands are socket-prefixed
[503.35ms]
BunTmuxDriver command orchestration > destructive operations keep the kaged session-name guard
[0.390ms]
tmux socket helpers > tmuxSocketName is deterministic and instance-specific
[0.340ms]
BunTmuxDriver control-mode attach > buildControlAttachArgs includes socket selection and both -f flags
[0.170ms]
BunTmuxDriver control-mode attach > sendKeys escapes semicolons before tmux send-keys
[0.630ms]
BunTmuxDriver control-mode attach > attachControlMode uses ignore-size flag
[2.12ms]
shell.bash handler > executes a simple command and returns stdout
[11.53ms]
shell.bash handler > returns non-zero exit code as data, not error
[4.91ms]
shell.bash handler > rejects empty command
[0.870ms]
shell.bash handler > rejects whitespace-only command
[0.600ms]
shell.bash handler > rejects missing command
[0.690ms]
shell.bash handler > uses custom cwd
[7.57ms]
shell.bash handler > rejects absolute cwd
[0.680ms]
shell.bash handler > rejects cwd that escapes project root
[0.530ms]
shell.bash handler > passes env vars to the process
[4.78ms]
shell.bash handler > rejects env with empty key
[0.970ms]
shell.bash handler > rejects env with non-string value
[0.530ms]
shell.bash handler > times out long-running command
[1.00s]
shell.bash handler > clamps timeout below minimum to 1000ms
[1.01s]
debug handler: launch action > throws when bridge is null
[2.35ms]
debug handler: launch action > rejects absolute script path
[0.440ms]
debug handler: launch action > rejects path traversal in script
[0.420ms]
debug handler: launch action > returns session info on success
[0.560ms]
debug handler: launch action > validates cwd path traversal
[0.310ms]
debug handler: attach action > throws when bridge is null
[0.400ms]
debug handler: attach action > returns session info on success
[0.460ms]
debug handler: breakpoint actions > throws when bridge is null
[0.300ms]
debug handler: breakpoint actions > lists breakpoints
[0.550ms]
debug handler: breakpoint actions > sets breakpoint with conditions
[0.400ms]
debug handler: breakpoint actions > removes breakpoint
[2.97ms]
debug handler: breakpoint actions > rejects set_breakpoint without path and line
[0.310ms]
debug handler: breakpoint actions > rejects path traversal on set_breakpoint
[0.270ms]
debug handler: step actions > throws when bridge is null
[0.340ms]
debug handler: step actions > returns step result with relative path
[0.430ms]
debug handler: continue action > throws when bridge is null
[0.290ms]
debug handler: continue action > returns stopped result with location
[0.520ms]
debug handler: continue action > returns exited result with exit code
[0.390ms]
debug handler: stack_trace action > throws when bridge is null
[0.310ms]
debug handler: stack_trace action > returns stack frames with relative paths
[0.430ms]
debug handler: stack_trace action > defaults levels to 20
[0.460ms]
debug handler: variables action > throws when bridge is null
[0.350ms]
debug handler: variables action > returns variables from bridge
[0.450ms]
debug handler: evaluate action > throws when bridge is null
[0.390ms]
debug handler: evaluate action > returns evaluation result
[0.330ms]
debug handler: evaluate action > defaults context to watch
[0.420ms]
debug handler: disconnect action > throws when bridge is null
[0.240ms]
debug handler: disconnect action > returns disconnect result
[0.310ms]
debug handler: disconnect action > defaults terminate_debuggee to true
[0.520ms]
debug handler: advanced actions > pause sends pause command
[0.320ms]
debug handler: advanced actions > threads returns thread list
[0.480ms]
debug handler: advanced actions > scopes returns scope list
[0.500ms]
debug handler: advanced actions > disassemble returns instructions
[0.410ms]
debug handler: advanced actions > read_memory returns memory data
[0.520ms]
debug handler: advanced actions > write_memory returns bytes written
[0.430ms]
debug handler: advanced actions > modules returns module list
[0.460ms]
debug handler: advanced actions > loaded_sources returns sources
[0.340ms]
debug handler: advanced actions > custom_request sends arbitrary command
[0.490ms]
debug handler: advanced actions > custom_request requires command
[0.290ms]
debug handler: advanced actions > set_instruction_breakpoint sets breakpoint
[0.410ms]
debug handler: advanced actions > set_instruction_breakpoint requires instruction_reference
[0.370ms]
debug handler: advanced actions > remove_instruction_breakpoint removes breakpoint
[0.450ms]
debug handler: advanced actions > data_breakpoint_info returns info
[0.430ms]
debug handler: advanced actions > data_breakpoint_info requires name
[2.62ms]
debug handler: advanced actions > set_data_breakpoint sets breakpoint
[0.430ms]
debug handler: advanced actions > set_data_breakpoint requires data_id
[0.300ms]
debug handler: advanced actions > remove_data_breakpoint removes breakpoint
[0.340ms]
debug handler: advanced actions > remove_data_breakpoint requires data_id
[0.390ms]
debug handler: unknown action > rejects unknown action
[0.270ms]
kaged.issue action=create > creates an issue and returns number + status
[10.12ms]
kaged.issue action=create > records agent:primary as author
[7.35ms]
kaged.issue action=create > records agent:<caller> for subagents
[5.12ms]
kaged.issue action=create > rejects empty title
[4.60ms]
kaged.issue action=create > rejects title exceeding 200 chars
[6.82ms]
kaged.issue action=create > rejects body exceeding 16 KB
[4.52ms]
kaged.issue action=create > assigns sequential numbers per project
[4.76ms]
kaged.issue action=list > returns empty list for new project
[8.02ms]
kaged.issue action=list > lists created issues
[4.70ms]
kaged.issue action=list > filters by status
[4.58ms]
kaged.issue action=list > rejects invalid status filter
[7.53ms]
kaged.issue action=list > respects limit
[4.97ms]
kaged.issue action=list > clamps limit to 100
[4.46ms]
kaged.issue action=get > returns issue with updates
[8.25ms]
kaged.issue action=get > returns issue_not_found for missing issue
[4.33ms]
kaged.issue action=get > rejects non-positive number
[4.30ms]
kaged.issue action=comment > adds a comment to an existing issue
[8.01ms]
kaged.issue action=comment > defaults visibility to all
[4.65ms]
kaged.issue action=comment > respects operator_only visibility
[4.62ms]
kaged.issue action=comment > rejects comment on missing issue
[6.63ms]
kaged.issue action=comment > rejects empty body
[4.39ms]
kaged.issue action=comment > rejects invalid visibility
[4.44ms]
kaged.issue action=transition > transitions open → in_progress
[5.32ms]
kaged.issue action=transition > transitions in_progress → resolved with required comment
[7.50ms]
kaged.issue action=transition > rejects resolved without comment
[4.52ms]
kaged.issue action=transition > rejects rejected without comment
[4.43ms]
kaged.issue action=transition > rejects invalid transition (open → reopened)
[7.70ms]
kaged.issue action=transition > rejects transition on missing issue
[4.24ms]
kaged.issue action=transition > records status_change update with metadata
[4.76ms]
kaged.issue action=transition > reopened clears resolvedAt and resolvedBy
[6.77ms]
kaged.issue action=transition > rejects invalid target status
[4.43ms]
kaged.issue unknown action > rejects unknown action
[4.19ms]
code.lsp handler: diagnostics action > returns error when bridge is null
[1.44ms]
code.lsp handler: diagnostics action > rejects absolute paths
[0.460ms]
code.lsp handler: diagnostics action > rejects path traversal
[0.370ms]
code.lsp handler: diagnostics action > returns diagnostics from bridge
[0.540ms]
code.lsp handler: diagnostics action > passes severity filter to bridge
[0.380ms]
code.lsp handler: definition action > returns error when bridge is null
[0.400ms]
code.lsp handler: definition action > rejects absolute paths
[0.340ms]
code.lsp handler: definition action > returns definitions with relative paths
[0.410ms]
code.lsp handler: references action > returns error when bridge is null
[0.450ms]
code.lsp handler: references action > passes include_declaration to bridge
[0.350ms]
code.lsp handler: references action > defaults include_declaration to false
[0.460ms]
code.lsp handler: references action > returns references with relative paths and outside_cage
[0.540ms]
code.lsp handler: symbols action > returns error when bridge is null
[0.230ms]
code.lsp handler: symbols action > rejects workspace scope without query
[0.510ms]
code.lsp handler: symbols action > calls getDocumentSymbols for document scope
[0.480ms]
code.lsp handler: symbols action > calls getWorkspaceSymbols for workspace scope
[0.340ms]
code.lsp handler: symbols action > respects limit parameter
[0.320ms]
code.lsp handler: symbols action > defaults limit to 50
[0.470ms]
code.lsp handler: rename action > returns error when bridge is null
[0.250ms]
code.lsp handler: rename action > returns rename results with relative paths
[0.490ms]
code.lsp handler: code_actions action > returns error when bridge is null
[0.240ms]
code.lsp handler: code_actions action > returns code actions with relative edit paths
[0.450ms]
code.lsp handler: code_actions action > defaults diagnostics to true
[0.430ms]
code.lsp handler: hover action > returns error when bridge is null
[0.320ms]
code.lsp handler: hover action > returns empty content when bridge returns null
[0.540ms]
code.lsp handler: hover action > returns hover content with range
[0.520ms]
code.lsp handler: type_definition action > returns type definitions with relative paths
[0.390ms]
code.lsp handler: type_definition action > rejects absolute paths
[0.380ms]
code.lsp handler: implementation action > returns implementations with relative paths
[0.400ms]
code.lsp handler: rename_file action > sends workspace/willRenameFiles request
[0.520ms]
code.lsp handler: rename_file action > rejects rename_file without path
[2.22ms]
code.lsp handler: rename_file action > rejects path traversal on rename_file
[0.410ms]
code.lsp handler: status action > sends status request
[0.280ms]
code.lsp handler: reload action > sends reload request
[0.350ms]
code.lsp handler: capabilities action > sends capabilities request
[0.330ms]
code.lsp handler: request action > sends custom LSP request
[0.450ms]
code.lsp handler: request action > rejects request without payload
[0.300ms]
code.lsp handler: unknown action > rejects unknown action
[0.300ms]
handleListProjects &gt; project handlers > returns empty list when no local config path
[0.560ms]
handleListProjects &gt; project handlers > returns empty list when config has no projects
[0.690ms]
handleListProjects &gt; project handlers > returns projects from local config
[1.22ms]
handleLoadProject &gt; project handlers > returns 400 when no path in body
[0.600ms]
handleLoadProject &gt; project handlers > returns 400 when path is not a string
[0.300ms]
handleLoadProject &gt; project handlers > returns 400 when path directory does not exist
[0.560ms]
handleLoadProject &gt; project handlers > creates .kaged and loads project from empty directory
[6.94ms]
handleLoadProject &gt; project handlers > loads existing .kaged project
[2.66ms]
handleLoadProject &gt; project handlers > registers project in local config after load
[2.89ms]
handleLoadProject &gt; project handlers > returns 503 when no localConfigPath
[0.290ms]
handleGetProject &gt; project handlers > returns 404 when project not found
[0.780ms]
handleGetProject &gt; project handlers > returns project by id
[0.810ms]
handleProjectUnresolved &gt; project handlers > returns missing plugin registry entries that are not registered
[4.06ms]
handleProjectUnresolved &gt; project handlers > returns null source when missing plugin registry entry omits source
[5.15ms]
handleDeleteProject &gt; project handlers > removes project from registry
[1.64ms]
handleDeleteProject &gt; project handlers > returns 404 when project not found
[0.890ms]
handleDeleteProject &gt; project handlers > returns 503 when no localConfigPath
[0.250ms]
handleReloadProject &gt; project handlers > re-reads project.yaml and returns updated data
[2.38ms]
handleReloadProject &gt; project handlers > detects invalid DSL after disk edit
[2.01ms]
handleReloadProject &gt; project handlers > updates status in local config after reload
[2.34ms]
handleReloadProject &gt; project handlers > returns 404 when project not in registry
[0.560ms]
handleReloadProject &gt; project handlers > returns 503 when no localConfigPath
[0.240ms]
handleReloadProject &gt; project handlers > handles missing .kaged directory gracefully
[4.75ms]
handleUpdateProject &gt; project handlers > returns 503 when no localConfigPath
[0.690ms]
handleUpdateProject &gt; project handlers > returns 400 on invalid JSON body
[0.590ms]
handleUpdateProject &gt; project handlers > returns 400 when label field is missing
[0.350ms]
handleUpdateProject &gt; project handlers > returns 400 when label has wrong type
[0.500ms]
handleUpdateProject &gt; project handlers > returns 400 when label is longer than 80 characters
[0.470ms]
handleUpdateProject &gt; project handlers > returns 404 when project does not exist
[0.450ms]
handleUpdateProject &gt; project handlers > sets a label and persists it to local config
[1.58ms]
handleUpdateProject &gt; project handlers > trims whitespace from the label
[0.910ms]
handleUpdateProject &gt; project handlers > clears the label when given null
[1.31ms]
handleUpdateProject &gt; project handlers > clears the label when given empty string
[1.14ms]
handleUpdateProject &gt; project handlers > drops legacy nickname on update (manual re-entry only)
[1.65ms]
handleUpdateProject &gt; project handlers > preserves accent_color across update
[1.40ms]
handleGetProjectDsl &gt; project handlers > returns 404 when no localConfigPath
[0.570ms]
handleGetProjectDsl &gt; project handlers > returns 404 when project not in registry
[0.510ms]
handleGetProjectDsl &gt; project handlers > returns DSL text and valid status when project.yaml parses cleanly
[4.79ms]
handleGetProjectDsl &gt; project handlers > returns invalid status when project.yaml fails schema validation
[1.81ms]
handleGetProjectDsl &gt; project handlers > returns invalid status with empty dsl when project.yaml is missing
[0.900ms]
handlePutProjectDsl &gt; project handlers > returns 503 when no localConfigPath
[0.700ms]
handlePutProjectDsl &gt; project handlers > returns 404 when project not in registry
[0.440ms]
handlePutProjectDsl &gt; project handlers > returns 400 when dsl field is missing
[1.06ms]
handlePutProjectDsl &gt; project handlers > saves valid DSL to disk and returns saved=true
[2.55ms]
handlePutProjectDsl &gt; project handlers > rejects invalid DSL with 422 and does not save
[2.41ms]
handlePutProjectDsl &gt; project handlers > updates project status to ready after successful save
[5.36ms]
handleValidateDsl &gt; project handlers > returns valid=true for well-formed DSL
[1.17ms]
handleValidateDsl &gt; project handlers > returns valid=false with diagnostics for invalid DSL
[0.950ms]
handleValidateDsl &gt; project handlers > returns 400 when dsl field is missing
[0.370ms]
handleValidateDsl &gt; project handlers > returns 400 for invalid JSON body
[0.270ms]
handleValidateDsl &gt; project handlers > returns warnings for cage: disabled subagents
[1.54ms]
handleGetProjectDslSynthesized &gt; project handlers > returns 404 when project not found
[0.820ms]
handleGetProjectDslSynthesized &gt; project handlers > returns merged YAML without overlay
[11.68ms]
handleGetProjectDslSynthesized &gt; project handlers > returns merged YAML with overlay applied
[4.41ms]
handleGetProjectDslSynthesized &gt; project handlers > returns 422 when merged config is invalid
[2.02ms]
handleGetProjectDslSynthesized &gt; project handlers > compiles nested project references into _compiled subtrees
[10.07ms]
handleGetProjectDslSynthesized &gt; project handlers > applies parent overrides on top of nested DSL
[6.51ms]
handleGetProjectDslSynthesized &gt; project handlers > returns 422 when a nested project.yaml is missing
[2.64ms]
handleGetProjectDslSynthesized &gt; project handlers > has_project_references=false on a flat project
[3.12ms]
handleGetProjectDslSynthesized &gt; project handlers > operator default_tools enables disabled-by-default tools in resolved_tools
[7.46ms]
handleGetProjectDslSynthesized &gt; project handlers > operator default_tools null entry disables tool
[2.69ms]
handleInitSubagent &gt; project handlers > returns 503 when no localConfigPath
[0.690ms]
handleInitSubagent &gt; project handlers > returns 404 when project not found
[0.530ms]
handleInitSubagent &gt; project handlers > returns 400 when path is missing
[1.12ms]
handleInitSubagent &gt; project handlers > rejects path traversal outside project root
[0.980ms]
handleInitSubagent &gt; project handlers > creates subagent .kaged directory with default config
[2.67ms]
handleInitSubagent &gt; project handlers > does not overwrite existing subagent config
[5.71ms]
handleAuditLog &gt; status handlers > accepts project_id filter and returns empty paginated shape
[0.620ms]
handleProjectCapabilities &gt; status handlers > returns 404 when project is not registered
[1.00ms]
handleProjectCapabilities &gt; status handlers > returns disabled cage capabilities and canonical tool split
[2.11ms]
handleProjectCapabilities &gt; status handlers > returns filesystem, network, and tool capabilities from compiled DSL
[6.72ms]
status handlers > buildRouteHandlerMap wires project capabilities route
[2.01ms]
compute.calc handler > evaluates a simple addition
[0.750ms]
compute.calc handler > evaluates multiple calculations in order
[0.250ms]
compute.calc handler > formats output with prefix and suffix
[0.120ms]
compute.calc handler > prefix and suffix default to empty string
[0.080ms]
compute.calc operator precedence > multiplication before addition
[0.160ms]
compute.calc operator precedence > division before subtraction
[0.080ms]
compute.calc operator precedence > parentheses override precedence
[0.110ms]
compute.calc operator precedence > exponentiation is right-associative: 2**3**2 = 512
[0.070ms]
compute.calc operator precedence > unary minus
[0.100ms]
compute.calc operator precedence > double unary minus
[0.070ms]
compute.calc operator precedence > unary plus is no-op
[0.070ms]
compute.calc operator precedence > mixed unary and binary operators
[0.080ms]
compute.calc operator precedence > modulo operator
[0.060ms]
compute.calc operator precedence > left-associative subtraction: 10 - 3 - 2 = 5
[0.060ms]
compute.calc operator precedence > left-associative division: 100 / 4 / 5 = 5
[0.060ms]
compute.calc number formats > decimal integer
[0.050ms]
compute.calc number formats > decimal with fractional part
[0.060ms]
compute.calc number formats > decimal starting with dot
[0.060ms]
compute.calc number formats > hexadecimal 0xFF = 255
[0.090ms]
compute.calc number formats > hexadecimal lowercase
[0.080ms]
compute.calc number formats > binary 0b1010 = 10
[0.100ms]
compute.calc number formats > octal 0o755 = 493
[0.100ms]
compute.calc number formats > scientific notation 1e10
[0.060ms]
compute.calc number formats > scientific notation with negative exponent
[0.060ms]
compute.calc number formats > scientific notation with positive exponent sign
[0.050ms]
compute.calc error handling > rejects missing calculations param
[0.120ms]
compute.calc error handling > rejects empty calculations array
[0.090ms]
compute.calc error handling > throws on invalid expression (trailing operator)
[0.220ms]
compute.calc error handling > throws on invalid character
[0.150ms]
compute.calc error handling > throws on unclosed parenthesis
[0.200ms]
compute.calc error handling > throws on extra closing parenthesis
[0.130ms]
compute.calc error handling > preserves expression in error message
[0.100ms]
compute.calc edge cases > whitespace is ignored
[0.080ms]
compute.calc edge cases > nested parentheses
[0.090ms]
compute.calc edge cases > deeply nested expression
[0.080ms]
compute.calc edge cases > normalizes negative zero to zero
[0.140ms]
compute.calc edge cases > division producing decimal
[0.080ms]
compute.calc edge cases > large exponentiation
[0.120ms]
compute.calc edge cases > hex in expression with operator
[0.090ms]
compute.calc edge cases > binary in expression with operator
[0.090ms]
proactive compaction (drop strategy) &gt; dispatchPrimary compaction integration > compaction triggers when token estimate exceeds threshold
[429.92ms]
proactive compaction (drop strategy) &gt; dispatchPrimary compaction integration > superseded messages are marked in storage
[224.95ms]
proactive compaction (drop strategy) &gt; dispatchPrimary compaction integration > run completes successfully after compaction
[386.89ms]
no compaction when below threshold &gt; dispatchPrimary compaction integration > messages pass through unchanged with default thresholds
[9.25ms]
reactive retry (provider_overflow_retry) &gt; dispatchPrimary compaction integration > retries once after context-length error in result
[309.94ms]
reactive retry (provider_overflow_retry) &gt; dispatchPrimary compaction integration > marks run as context_overflow when retry also fails
[29.36ms]
reconstructCompactableMessages &gt; dispatchPrimary compaction integration > preserves storage record IDs
[16.43ms]
reconstructCompactableMessages &gt; dispatchPrimary compaction integration > synthesizes tool result IDs with :tr: separator
[10.53ms]
reconstructCompactableMessages &gt; dispatchPrimary compaction integration > skips superseded messages
[13.83ms]
reconstructCompactableMessages &gt; dispatchPrimary compaction integration > includes system role messages (compaction summaries)
[10.92ms]
summarize strategy wiring &gt; dispatchPrimary compaction integration > dispatch completes with summarize strategy configured (summarizeFn injected)
[18.24ms]
summarize strategy wiring &gt; dispatchPrimary compaction integration > dispatch completes with delegate strategy and no plugin supervisor (graceful fallback)
[20.56ms]
summarize strategy wiring &gt; dispatchPrimary compaction integration > dispatch completes with delegate strategy and plugin supervisor (delegateFn injected)
[17.90ms]
dispatchPrimary — model-initiated checkpoint > session transitions to paused (not idle) when checkpointRequested is set
[14.52ms]
dispatchPrimary — model-initiated checkpoint > checkpoint record created with createdBy 'model'
[15.34ms]
dispatchPrimary — model-initiated checkpoint > checkpoint record has correct sessionId and runId
[9.31ms]
dispatchPrimary — model-initiated checkpoint > checkpoint messageCursor points to the persisted assistant message
[13.07ms]
dispatchPrimary — model-initiated checkpoint > checkpoint reason is populated from checkpointRequested.detail
[12.96ms]
dispatchPrimary — model-initiated checkpoint > checkpoint reason is null when detail is undefined
[7.66ms]
dispatchPrimary — model-initiated checkpoint > assistant message is still persisted when checkpoint is requested
[12.60ms]
dispatchPrimary — model-initiated checkpoint > run is marked done (not failed) when checkpoint is requested
[7.39ms]
dispatchPrimary — model-initiated checkpoint > checkpoint resumedAt is null (not yet resumed)
[12.29ms]
dispatchPrimary — model-initiated checkpoint > session transitions to idle when no checkpoint requested (regression)
[6.91ms]
context estimate handler > returns 503 when storage is unavailable
[6.24ms]
context estimate handler > returns 404 when session is not found
[4.57ms]
context estimate handler > returns the context estimate payload
[11.08ms]
context estimate handler > registers GET /api/v1/sessions/:id/context-estimate
[4.59ms]
handleProjectStatus > returns project telemetry from storage
[8.10ms]
handleProjectStatus > returns 404 when project is not registered
[4.46ms]
handleProjectStatus > route handler map wires the project status endpoint
[4.13ms]
handleListCompactions &gt; compaction handlers > returns 503 when storage is unavailable
[6.22ms]
handleListCompactions &gt; compaction handlers > returns empty list when session has no compactions
[5.43ms]
handleListCompactions &gt; compaction handlers > returns compaction summaries
[7.72ms]
handleListCompactions &gt; compaction handlers > filters by agent_path in memory
[6.04ms]
handleListCompactions &gt; compaction handlers > passes pagination to storage and returns next_cursor
[5.57ms]
handleGetCompaction &gt; compaction handlers > returns 503 when storage is unavailable
[7.03ms]
handleGetCompaction &gt; compaction handlers > returns full compaction detail
[6.24ms]
handleGetCompaction &gt; compaction handlers > returns 404 when compaction is not found
[4.95ms]
handlePatchCompaction &gt; compaction handlers > returns 503 when storage is unavailable
[7.02ms]
handlePatchCompaction &gt; compaction handlers > updates a valid operator flag
[6.27ms]
handlePatchCompaction &gt; compaction handlers > updates operator notes
[5.32ms]
handlePatchCompaction &gt; compaction handlers > clears operator flag when null is provided
[7.51ms]
handlePatchCompaction &gt; compaction handlers > returns 422 for an invalid flag
[5.67ms]
handlePatchCompaction &gt; compaction handlers > returns 422 when notes exceed the maximum length
[4.83ms]
handlePatchCompaction &gt; compaction handlers > returns 404 when compaction is not found
[7.03ms]
handlePatchCompaction &gt; compaction handlers > publishes compaction.flagged event
[5.73ms]
handlePostCompact &gt; compaction handlers > returns 503 when storage is unavailable
[5.54ms]
handlePostCompact &gt; compaction handlers > accepts manual compaction and persists the result
[11.51ms]
handlePostCompact &gt; compaction handlers > returns synchronous dry_run proposal without persisting
[6.97ms]
handlePostCompact &gt; compaction handlers > returns 404 when the session is not found
[8.19ms]
handlePostCompact &gt; compaction handlers > returns 422 for an invalid strategy
[5.76ms]
handlePostCompact &gt; compaction handlers > publishes compaction.triggered and compaction.completed events
[13.22ms]
handlePostCompact &gt; compaction handlers > uses requested agent_path in the response and events
[7.86ms]
route registration &gt; compaction handlers > registers all compaction routes
[7.96ms]
handleResumeCheckpoint > returns 200 with status resumed and run_id
[6.68ms]
handleResumeCheckpoint > session transitions to running
[7.54ms]
handleResumeCheckpoint > new run is created with pending state
[4.94ms]
handleResumeCheckpoint > checkpoint resumedAt is updated
[4.69ms]
handleResumeCheckpoint > returns 404 for non-existent session
[8.23ms]
handleResumeCheckpoint > returns 404 for non-existent checkpoint
[4.45ms]
handleResumeCheckpoint > returns 409 for non-paused session
[4.63ms]
handleRollbackCheckpoint > returns 200 with status rolled_back
[7.36ms]
handleRollbackCheckpoint > session transitions to idle
[5.67ms]
handleRollbackCheckpoint > checkpoint rolledBack is set to true
[4.51ms]
handleRollbackCheckpoint > messages after checkpoint messageCursor are superseded
[6.86ms]
handleRollbackCheckpoint > checkpoint is preserved (not deleted)
[5.34ms]
handleRollbackCheckpoint > returns 404 for non-existent session
[4.13ms]
handleRollbackCheckpoint > returns 409 for non-paused session
[7.14ms]
handleCreateCheckpoint — operator-initiated pause > returns 201 with checkpoint summary
[6.27ms]
handleCreateCheckpoint — operator-initiated pause > session transitions to paused
[6.86ms]
handleCreateCheckpoint — operator-initiated pause > checkpoint record has createdBy operator
[5.06ms]
handleCreateCheckpoint — operator-initiated pause > checkpoint messageCursor points to last message
[4.74ms]
handleCreateCheckpoint — operator-initiated pause > checkpoint has correct runId
[6.84ms]
handleCreateCheckpoint — operator-initiated pause > checkpoint reason is null when body is empty
[5.30ms]
handleCreateCheckpoint — operator-initiated pause > checkpoint resumedAt starts as null
[4.56ms]
handleCreateCheckpoint — operator-initiated pause > returns 404 for non-existent session
[6.34ms]
handleCreateCheckpoint — operator-initiated pause > returns 409 for non-running session
[7.13ms]
dispatchPrimary — on_session_start hooks > appends plugin inject to system prompt on first dispatch
[11.92ms]
dispatchPrimary — on_session_start hooks > wraps inject in <plugin:SLOT> tags with newlines
[7.74ms]
dispatchPrimary — on_session_start hooks > sets recalledAt on session after hook firing
[13.35ms]
dispatchPrimary — on_session_start hooks > sets recalledAt even when no plugin returns inject
[8.58ms]
dispatchPrimary — on_session_start hooks > does not modify system prompt when no inject returned
[12.01ms]
dispatchPrimary — on_session_start hooks > empty inject string is treated as no-inject
[12.24ms]
dispatchPrimary — on_session_start hooks > skips hooks when recalledAt is already set
[7.76ms]
dispatchPrimary — on_session_start hooks > skips hooks when no pluginSupervisor provided
[12.81ms]
dispatchPrimary — on_session_start hooks > skips hooks when pluginSupervisor is null
[7.64ms]
dispatchPrimary — on_session_start hooks > skips hooks when no plugins declared on primary
[12.59ms]
dispatchPrimary — on_session_start hooks > skips hooks when plugins exist but none declare on_session_start
[14.24ms]
dispatchPrimary — on_session_start hooks > multiple plugins fire in declaration order
[9.64ms]
dispatchPrimary — on_session_start hooks > multi-plugin inject blocks joined with newlines
[12.97ms]
dispatchPrimary — on_session_start hooks > failed hook produces no inject, other plugins still fire
[13.93ms]
dispatchPrimary — on_session_start hooks > not_found hook status produces no inject
[14.11ms]
dispatchPrimary — on_session_start hooks > all hooks failing still sets recalledAt
[8.74ms]
dispatchPrimary — on_session_start hooks > passes correct hook name and plugin names to fireHook
[11.73ms]
dispatchPrimary — on_session_start hooks > passes PluginCallContext with project, agent, and session
[11.57ms]
dispatchPrimary — on_session_start hooks > second dispatch on same session does not re-fire hooks
[9.94ms]
dispatchPrimary — on_session_start hooks > uses slot name when plugin has no package field
[10.44ms]
dispatchPrimary — on_session_start hooks > run completes with state done when hooks fire successfully
[12.18ms]
dispatchPrimary — on_session_start hooks > run completes with state done even when all hooks fail
[7.27ms]
happy path &gt; dispatchPrimary integration > run completes with state 'done'
[8.51ms]
happy path &gt; dispatchPrimary integration > assistant message persisted to storage
[11.72ms]
happy path &gt; dispatchPrimary integration > persisted message has provider metadata
[6.73ms]
happy path &gt; dispatchPrimary integration > session transitions back to idle
[10.99ms]
happy path &gt; dispatchPrimary integration > runPrimary receives correct provider route
[6.71ms]
happy path &gt; dispatchPrimary integration > runPrimary receives reconstructed operator message
[11.44ms]
happy path &gt; dispatchPrimary integration > runPrimary receives system prompt content
[6.63ms]
happy path &gt; dispatchPrimary integration > run state transitions through 'running' before 'done'
[11.30ms]
dispatchPrimary integration > config-missing: run fails when localConfigPath is null
[4.98ms]
dispatchPrimary integration > project-not-loaded: run fails when project not in config
[9.27ms]
dispatchPrimary integration > alias-not-found: run fails when model alias missing
[7.04ms]
dispatchPrimary integration > invalid-alias-target: run fails when target missing colon
[10.50ms]
dispatchPrimary integration > provider-not-configured: run fails when provider entry missing
[6.12ms]
dispatchPrimary integration > api-key-unresolved: run fails when provider has no key
[9.44ms]
dispatchPrimary integration > prompt-unreadable: run fails when prompt file doesn't exist
[6.30ms]
dispatchPrimary integration > dsl-invalid: run fails when project.yaml is malformed
[9.18ms]
error mid-stream &gt; dispatchPrimary integration > run marked failed when runPrimary returns error
[7.68ms]
error mid-stream &gt; dispatchPrimary integration > session still transitions to idle after error
[11.44ms]
error mid-stream &gt; dispatchPrimary integration > error assistant message is still persisted
[6.81ms]
dispatchPrimary integration > runPrimary-throws: run fails gracefully
[11.24ms]
dispatchPrimary integration > runPrimary-throws: session transitions to idle
[6.69ms]
dispatchPrimary integration > driver-fallback: uses provider key as driver when driver absent
[11.91ms]
dispatchPrimary integration > api-key-env: resolves key from environment variable
[7.10ms]
dispatchPrimary integration > reconstructs full message history
[11.76ms]
dispatchPrimary integration > skips superseded messages in history
[6.82ms]
dispatchPrimary integration > all dispatch errors leave session in idle state
[5.52ms]
model override &gt; dispatchPrimary integration > override bypasses alias resolution and routes directly
[11.52ms]
model override &gt; dispatchPrimary integration > override works even when alias is missing
[11.09ms]
model override &gt; dispatchPrimary integration > override with unknown provider fails
[6.04ms]
model override &gt; dispatchPrimary integration > override with invalid format fails
[10.08ms]
model override &gt; dispatchPrimary integration > override with no api key fails
[6.26ms]
abort controller registry &gt; dispatchPrimary integration > controller is registered while runPrimary is executing
[10.10ms]
abort controller registry &gt; dispatchPrimary integration > controller is deregistered after successful completion
[6.53ms]
abort controller registry &gt; dispatchPrimary integration > controller is deregistered after error result
[10.59ms]
abort controller registry &gt; dispatchPrimary integration > controller is deregistered after runPrimary throws
[6.67ms]
abort controller registry &gt; dispatchPrimary integration > abort signal is passed to runPrimaryFn
[10.55ms]
abort controller registry &gt; dispatchPrimary integration > getRunController returns undefined for unknown run
[4.56ms]
run.started event &gt; dispatchPrimary event publishing > published before runPrimary executes
[9.35ms]
run.started event &gt; dispatchPrimary event publishing > has correct payload
[6.96ms]
run.ended event &gt; dispatchPrimary event publishing > published after successful completion with outcome 'completed'
[11.09ms]
run.ended event &gt; dispatchPrimary event publishing > published after error result with outcome 'failed'
[6.76ms]
run.ended event &gt; dispatchPrimary event publishing > published after runPrimary throws with outcome 'failed'
[11.35ms]
run.ended event &gt; dispatchPrimary event publishing > published after config-missing failure with outcome 'failed'
[4.88ms]
run.ended event &gt; dispatchPrimary event publishing > run.started is NOT published on early dispatch failure
[5.35ms]
event ordering &gt; dispatchPrimary event publishing > run.started comes before run.ended on success
[9.95ms]
event ordering &gt; dispatchPrimary event publishing > run.started comes before run.ended on error result
[10.27ms]
harness event relay &gt; dispatchPrimary event publishing > publish callback relays events through publishHarnessEvent
[6.81ms]
harness event relay &gt; dispatchPrimary event publishing > dispatch failure publishes message.end error event via harness channel
[7.76ms]
kaged.todo action=view > returns an empty list for a newly bound issue
[5.24ms]
kaged.todo action=view > returns todos and markdown markers for all statuses
[4.73ms]
kaged.todo action=view > includes notes inline for the in_progress task only
[4.36ms]
kaged.todo action=set > abandons existing todos and creates a replacement list
[5.79ms]
kaged.todo action=set > records the caller as origin agent
[4.70ms]
kaged.todo action=set > rejects missing items
[4.35ms]
kaged.todo action=set > rejects more than 50 items
[4.44ms]
kaged.todo action=add > appends todos after the existing highest position
[5.12ms]
kaged.todo action=add > skips invalid items and reports only added count
[4.66ms]
kaged.todo action=add > rejects missing items
[4.30ms]
kaged.todo action=start > starts a pending todo by content-addressed lookup
[5.13ms]
kaged.todo action=start > auto-demotes the previous in_progress todo
[5.11ms]
kaged.todo action=start > rejects missing content
[4.34ms]
kaged.todo action=start > returns todo_not_found when content does not match
[4.63ms]
kaged.todo action=start > rejects starting a completed todo
[4.54ms]
kaged.todo action=start > rejects starting an abandoned todo
[4.51ms]
kaged.todo action=done > marks a todo completed and sets completedAt
[4.81ms]
kaged.todo action=done > rejects already completed todos
[4.64ms]
kaged.todo action=done > returns todo_not_found for missing todo
[4.45ms]
kaged.todo action=done > rejects missing content
[4.29ms]
kaged.todo action=drop > marks a todo abandoned
[4.76ms]
kaged.todo action=drop > rejects already abandoned todos
[4.49ms]
kaged.todo action=drop > returns todo_not_found for missing todo
[4.44ms]
kaged.todo action=drop > rejects missing content
[4.30ms]
kaged.todo action=note > appends a note to the notes array
[4.81ms]
kaged.todo action=note > returns todo_not_found for missing todo
[4.50ms]
kaged.todo action=note > rejects missing content
[4.25ms]
kaged.todo action=note > rejects empty text
[4.40ms]
kaged.todo shared errors > returns no_bound_issue when the session is not bound
[4.30ms]
kaged.todo shared errors > returns invalid_params for an unknown action
[4.28ms]
kaged.todo content-addressing coaching > returns coaching error when content looks like an ID token
[4.47ms]
kaged.todo content-addressing coaching > returns coaching error with empty-list hint when list is empty and content not found
[4.40ms]
kaged.todo content-addressing coaching > does not include empty-list hint when todos exist but content doesn't match
[4.55ms]
kaged.todo content-addressing coaching > returns coaching error for ID-like patterns in drop action
[4.47ms]
kaged.todo content-addressing coaching > returns coaching error for ID-like patterns in note action
[4.53ms]
project.recipe handler — no runners > returns error when no project runners detected
[3.76ms]
project.recipe handler — npm > detects npm from package.json and runs a script
[124.96ms]
project.recipe handler — npm > matches build script by first word
[109.21ms]
project.recipe handler — npm > returns available_tasks for all detected runners
[103.31ms]
project.recipe handler — npm > rejects empty op
[1.00ms]
project.recipe handler — npm > rejects missing op
[0.580ms]
project.recipe handler — npm > rejects whitespace-only op
[0.420ms]
project.recipe handler — bun > detects bun when bun.lock exists
[21.29ms]
project.recipe handler — cargo > detects cargo and runs cargo check
[17.68ms]
project.recipe handler — cargo > returns cargo task list in available_tasks
[21.45ms]
project.recipe handler — make > detects make and runs a target
[7.61ms]
project.recipe handler — make > returns make targets in available_tasks
[7.37ms]
project.recipe handler — cwd > uses project root as default cwd
[109.04ms]
project.recipe handler — cwd > resolves cwd relative to project root
[107.87ms]
project.recipe handler — cwd > rejects cwd that escapes project root
[0.770ms]
project.recipe handler — multiple runners > detects both npm and make
[106.33ms]
project.recipe handler — multiple runners > falls back to first runner when op does not match any task
[111.23ms]
buildStickyTodoReminder > returns null when no open todos
[0.610ms]
buildStickyTodoReminder > returns null when todo list is empty
[0.080ms]
buildStickyTodoReminder > returns system message with open items
[0.410ms]
buildStickyTodoReminder > caps at 5 items with +N more hint
[0.280ms]
buildStickyTodoReminder > always includes the in_progress task in the window
[0.260ms]
buildStickyTodoReminder > suppresses when preceding turn has kaged.todo tool result
[0.160ms]
buildStickyTodoReminder > does not suppress when kaged.todo result is from an older turn
[0.150ms]
buildStickyTodoReminder > regenerated from fresh data on each call
[0.160ms]
buildStickyTodoReminder > omits completed and abandoned from the window
[0.160ms]
edit.ast handler > rejects absolute paths
[5.37ms]
edit.ast handler > rejects path traversal
[0.620ms]
edit.ast handler > requires rewrites object
[0.430ms]
edit.ast handler > requires rewrites param at all
[0.430ms]
edit.ast handler > dry-run by default does not modify files
[3.42ms]
edit.ast handler > dry_run: false applies changes to file
[2.44ms]
edit.ast handler > targets a single file when path is a file
[1.33ms]
edit.ast handler > glob filter limits to matching files
[5.42ms]
edit.ast handler > returns relative file paths
[2.67ms]
edit.ast handler > returns empty for no pattern matches
[2.60ms]
edit.ast handler > max_replacements caps total replacements
[2.80ms]
edit.ast handler > max_files caps distinct files modified
[3.37ms]
route ↔ handler sync > every route definition has a handler (or is a known exception)
[0.230ms]
route ↔ handler sync > every handler has a route definition
[0.150ms]
route ↔ handler sync > known exceptions actually exist in route definitions
[0.090ms]
route ↔ handler sync > known exceptions do NOT have handlers (or remove them from exceptions)
[0.100ms]