@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 > request-id > accepts valid ULID [0.040ms]
isValidUlid > request-id > rejects wrong length [0.030ms]
isValidUlid > request-id > rejects invalid characters [0.020ms]
exact matches > Router > matches /healthz [0.180ms]
exact matches > Router > matches /readyz [0.040ms]
exact matches > Router > matches /api/v1/projects [0.020ms]
exact matches > Router > matches POST /api/v1/projects/load [0.030ms]
parameterized matches > Router > extracts single param :id [0.040ms]
parameterized matches > Router > extracts multiple params :id and :cid [0.080ms]
parameterized matches > Router > DELETE with param [0.070ms]
percent-encoded params > Router > decodes %3A to colon in :id (guest userId pattern) [0.030ms]
percent-encoded params > Router > decodes %20 to space [0.030ms]
percent-encoded params > Router > decodes multiple encoded params independently [0.030ms]
percent-encoded params > Router > returns null for malformed percent-encoding [0.100ms]
percent-encoded params > Router > leaves already-decoded path segments unchanged [0.040ms]
non-matches > Router > returns null for unknown path [0.020ms]
non-matches > Router > returns null for wrong method on known path [0.040ms]
non-matches > Router > returns null for too-short path [0.030ms]
non-matches > Router > returns null for too-long path [0.020ms]
non-matches > Router > returns null for empty path [0.020ms]
methodsForPath > Router > returns GET and DELETE for /api/v1/projects/:id [0.100ms]
methodsForPath > Router > returns empty for unknown path [0.020ms]
methodsForPath > Router > returns GET only for /healthz [0.020ms]
with full route table > 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 > server integration > GET /healthz returns 200 ok [2.72ms]
service endpoints > server integration > GET /readyz returns 200 ready when ready [0.380ms]
service endpoints > server integration > GET /readyz returns 503 when not ready [0.250ms]
service endpoints > server integration > GET /api/versions returns version manifest [0.280ms]
response headers > server integration > includes X-Kaged-Request-Id [0.270ms]
response headers > server integration > includes X-Kaged-Daemon-Version [0.230ms]
response headers > server integration > includes Cache-Control: no-store [0.190ms]
response headers > server integration > includes X-Kaged-Warning in insecure mode [0.190ms]
response headers > server integration > request IDs are unique across requests [0.390ms]
authenticated endpoints > server integration > GET /api/v1/me returns operator info in insecure mode [0.700ms]
authenticated endpoints > server integration > GET /api/v1/me sets CSRF cookie [0.350ms]
authenticated endpoints > server integration > GET /api/v1/dsl/schema returns schema [0.310ms]
stub endpoints > server integration > GET /api/v1/projects returns 200 with empty list [0.430ms]
stub endpoints > server integration > POST /api/v1/dsl/validate returns 422 for invalid DSL [2.73ms]
stub endpoints > server integration > GET /api/v1/sessions/01HXAB returns 503 without storage [0.390ms]
routing > server integration > unknown path returns 404 [0.280ms]
routing > server integration > wrong method returns 405 with Allow header [0.280ms]
routing > server integration > OPTIONS returns 204 with CORS headers [0.340ms]
with sandbox disabled > server integration > warning header includes both insecure-mode and no-sandbox [0.520ms]
secure mode auth rejection > server integration > unauthenticated endpoints still work without auth [1.64ms]
secure mode auth rejection > server integration > authenticated endpoint rejects without headers [0.290ms]
secure mode auth rejection > server integration > authenticated endpoint rejects wrong nonce [0.230ms]
secure mode auth rejection > server integration > authenticated endpoint accepts correct headers [0.340ms]
secure mode auth rejection > server integration > no warning header in secure+sandbox mode [0.220ms]
loopback launch flow > server integration > launch with correct token returns 302 redirect to / [0.660ms]
loopback launch flow > server integration > launch sets kaged_session cookie with HttpOnly and SameSite=Lax [3.60ms]
loopback launch flow > server integration > launch with wrong token returns 401 with invalid_launch_token reason [3.17ms]
loopback launch flow > server integration > launch with missing token returns 401 [5.07ms]
loopback launch flow > server integration > launch token is single-use — second request returns 401 [3.62ms]
loopback launch flow > server integration > launch returns 404 in insecure mode [3.88ms]
loopback launch flow > server integration > launch returns 404 in sidecar mode (system deployment) [2.74ms]
loopback launch flow > server integration > after launch, cookie authenticates subsequent requests [3.66ms]
loopback launch flow > server integration > without cookie, authenticated endpoints reject in loopback mode [2.80ms]
loopback launch flow > server integration > after token consumption, a new token is generated and works [3.64ms]
loopback launch flow > server integration > regenerated launch URL uses uiUrl when configured [2.99ms]
loopback launch flow > server integration > regenerated launch URL falls back to daemon bind when uiUrl is empty [3.42ms]
launch endpoint content negotiation > server integration > Accept: application/json returns 200 with JSON body on valid token [2.82ms]
launch endpoint content negotiation > server integration > Accept: application/json sets session and CSRF cookies on success [5.07ms]
launch endpoint content negotiation > server integration > Accept: application/json returns 401 JSON on invalid token [3.96ms]
launch endpoint content negotiation > server integration > Accept: application/json still regenerates token after consumption [3.21ms]
launch endpoint content negotiation > 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 > SystemPluginLoader > happy path: loads and activates a plugin [1.82ms]
loadAll > SystemPluginLoader > setup receives ctx with config, log, on, off [0.260ms]
loadAll > SystemPluginLoader > disabled plugin is not imported [0.150ms]
loadAll > SystemPluginLoader > loads plugins in alphabetical order [0.260ms]
loadAll > SystemPluginLoader > resolves default path from kagedHome when no path specified [0.160ms]
loadAll > SystemPluginLoader > failed import: nonexistent path → failed state, daemon continues [0.300ms]
loadAll > SystemPluginLoader > bad export: no default export → failed state [0.130ms]
loadAll > SystemPluginLoader > bad export: missing setup method → failed state [0.130ms]
loadAll > SystemPluginLoader > name mismatch → failed state [0.120ms]
loadAll > SystemPluginLoader > setup() throws → failed state, other plugins still load [0.240ms]
loadAll > SystemPluginLoader > setup() timeout → failed state [52.19ms]
fireHook > SystemPluginLoader > fires registered hook callback with correct args [0.630ms]
fireHook > SystemPluginLoader > fires multiple callbacks in registration order [0.420ms]
fireHook > SystemPluginLoader > hook callback error: logged, other callbacks still fire [0.390ms]
fireHook > SystemPluginLoader > hook callback timeout: logged, other callbacks still fire [53.60ms]
fireHook > SystemPluginLoader > no-op when no callbacks registered for hook [0.390ms]
fireHook > SystemPluginLoader > off() unregisters a callback [0.700ms]
fireHook > SystemPluginLoader > does not fire hooks for failed plugins [0.500ms]
teardownAll > SystemPluginLoader > calls teardown() on active plugins [1.11ms]
teardownAll > SystemPluginLoader > sets stopped state even for plugins without teardown() [0.390ms]
teardownAll > SystemPluginLoader > teardown() error logged but does not block other teardowns [0.870ms]
teardownAll > SystemPluginLoader > teardown() timeout logged as warning [55.09ms]
getStates > SystemPluginLoader > returns status for all configured plugins [0.720ms]
getStates > SystemPluginLoader > failed plugin includes error message [0.450ms]
plugin logger > 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 > project handlers > returns empty list when no local config path [0.560ms]
handleListProjects > project handlers > returns empty list when config has no projects [0.690ms]
handleListProjects > project handlers > returns projects from local config [1.22ms]
handleLoadProject > project handlers > returns 400 when no path in body [0.600ms]
handleLoadProject > project handlers > returns 400 when path is not a string [0.300ms]
handleLoadProject > project handlers > returns 400 when path directory does not exist [0.560ms]
handleLoadProject > project handlers > creates .kaged and loads project from empty directory [6.94ms]
handleLoadProject > project handlers > loads existing .kaged project [2.66ms]
handleLoadProject > project handlers > registers project in local config after load [2.89ms]
handleLoadProject > project handlers > returns 503 when no localConfigPath [0.290ms]
handleGetProject > project handlers > returns 404 when project not found [0.780ms]
handleGetProject > project handlers > returns project by id [0.810ms]
handleProjectUnresolved > project handlers > returns missing plugin registry entries that are not registered [4.06ms]
handleProjectUnresolved > project handlers > returns null source when missing plugin registry entry omits source [5.15ms]
handleDeleteProject > project handlers > removes project from registry [1.64ms]
handleDeleteProject > project handlers > returns 404 when project not found [0.890ms]
handleDeleteProject > project handlers > returns 503 when no localConfigPath [0.250ms]
handleReloadProject > project handlers > re-reads project.yaml and returns updated data [2.38ms]
handleReloadProject > project handlers > detects invalid DSL after disk edit [2.01ms]
handleReloadProject > project handlers > updates status in local config after reload [2.34ms]
handleReloadProject > project handlers > returns 404 when project not in registry [0.560ms]
handleReloadProject > project handlers > returns 503 when no localConfigPath [0.240ms]
handleReloadProject > project handlers > handles missing .kaged directory gracefully [4.75ms]
handleUpdateProject > project handlers > returns 503 when no localConfigPath [0.690ms]
handleUpdateProject > project handlers > returns 400 on invalid JSON body [0.590ms]
handleUpdateProject > project handlers > returns 400 when label field is missing [0.350ms]
handleUpdateProject > project handlers > returns 400 when label has wrong type [0.500ms]
handleUpdateProject > project handlers > returns 400 when label is longer than 80 characters [0.470ms]
handleUpdateProject > project handlers > returns 404 when project does not exist [0.450ms]
handleUpdateProject > project handlers > sets a label and persists it to local config [1.58ms]
handleUpdateProject > project handlers > trims whitespace from the label [0.910ms]
handleUpdateProject > project handlers > clears the label when given null [1.31ms]
handleUpdateProject > project handlers > clears the label when given empty string [1.14ms]
handleUpdateProject > project handlers > drops legacy nickname on update (manual re-entry only) [1.65ms]
handleUpdateProject > project handlers > preserves accent_color across update [1.40ms]
handleGetProjectDsl > project handlers > returns 404 when no localConfigPath [0.570ms]
handleGetProjectDsl > project handlers > returns 404 when project not in registry [0.510ms]
handleGetProjectDsl > project handlers > returns DSL text and valid status when project.yaml parses cleanly [4.79ms]
handleGetProjectDsl > project handlers > returns invalid status when project.yaml fails schema validation [1.81ms]
handleGetProjectDsl > project handlers > returns invalid status with empty dsl when project.yaml is missing [0.900ms]
handlePutProjectDsl > project handlers > returns 503 when no localConfigPath [0.700ms]
handlePutProjectDsl > project handlers > returns 404 when project not in registry [0.440ms]
handlePutProjectDsl > project handlers > returns 400 when dsl field is missing [1.06ms]
handlePutProjectDsl > project handlers > saves valid DSL to disk and returns saved=true [2.55ms]
handlePutProjectDsl > project handlers > rejects invalid DSL with 422 and does not save [2.41ms]
handlePutProjectDsl > project handlers > updates project status to ready after successful save [5.36ms]
handleValidateDsl > project handlers > returns valid=true for well-formed DSL [1.17ms]
handleValidateDsl > project handlers > returns valid=false with diagnostics for invalid DSL [0.950ms]
handleValidateDsl > project handlers > returns 400 when dsl field is missing [0.370ms]
handleValidateDsl > project handlers > returns 400 for invalid JSON body [0.270ms]
handleValidateDsl > project handlers > returns warnings for cage: disabled subagents [1.54ms]
handleGetProjectDslSynthesized > project handlers > returns 404 when project not found [0.820ms]
handleGetProjectDslSynthesized > project handlers > returns merged YAML without overlay [11.68ms]
handleGetProjectDslSynthesized > project handlers > returns merged YAML with overlay applied [4.41ms]
handleGetProjectDslSynthesized > project handlers > returns 422 when merged config is invalid [2.02ms]
handleGetProjectDslSynthesized > project handlers > compiles nested project references into _compiled subtrees [10.07ms]
handleGetProjectDslSynthesized > project handlers > applies parent overrides on top of nested DSL [6.51ms]
handleGetProjectDslSynthesized > project handlers > returns 422 when a nested project.yaml is missing [2.64ms]
handleGetProjectDslSynthesized > project handlers > has_project_references=false on a flat project [3.12ms]
handleGetProjectDslSynthesized > project handlers > operator default_tools enables disabled-by-default tools in resolved_tools [7.46ms]
handleGetProjectDslSynthesized > project handlers > operator default_tools null entry disables tool [2.69ms]
handleInitSubagent > project handlers > returns 503 when no localConfigPath [0.690ms]
handleInitSubagent > project handlers > returns 404 when project not found [0.530ms]
handleInitSubagent > project handlers > returns 400 when path is missing [1.12ms]
handleInitSubagent > project handlers > rejects path traversal outside project root [0.980ms]
handleInitSubagent > project handlers > creates subagent .kaged directory with default config [2.67ms]
handleInitSubagent > project handlers > does not overwrite existing subagent config [5.71ms]
handleAuditLog > status handlers > accepts project_id filter and returns empty paginated shape [0.620ms]
handleProjectCapabilities > status handlers > returns 404 when project is not registered [1.00ms]
handleProjectCapabilities > status handlers > returns disabled cage capabilities and canonical tool split [2.11ms]
handleProjectCapabilities > 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) > dispatchPrimary compaction integration > compaction triggers when token estimate exceeds threshold [429.92ms]
proactive compaction (drop strategy) > dispatchPrimary compaction integration > superseded messages are marked in storage [224.95ms]
proactive compaction (drop strategy) > dispatchPrimary compaction integration > run completes successfully after compaction [386.89ms]
no compaction when below threshold > dispatchPrimary compaction integration > messages pass through unchanged with default thresholds [9.25ms]
reactive retry (provider_overflow_retry) > dispatchPrimary compaction integration > retries once after context-length error in result [309.94ms]
reactive retry (provider_overflow_retry) > dispatchPrimary compaction integration > marks run as context_overflow when retry also fails [29.36ms]
reconstructCompactableMessages > dispatchPrimary compaction integration > preserves storage record IDs [16.43ms]
reconstructCompactableMessages > dispatchPrimary compaction integration > synthesizes tool result IDs with :tr: separator [10.53ms]
reconstructCompactableMessages > dispatchPrimary compaction integration > skips superseded messages [13.83ms]
reconstructCompactableMessages > dispatchPrimary compaction integration > includes system role messages (compaction summaries) [10.92ms]
summarize strategy wiring > dispatchPrimary compaction integration > dispatch completes with summarize strategy configured (summarizeFn injected) [18.24ms]
summarize strategy wiring > dispatchPrimary compaction integration > dispatch completes with delegate strategy and no plugin supervisor (graceful fallback) [20.56ms]
summarize strategy wiring > 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 > compaction handlers > returns 503 when storage is unavailable [6.22ms]
handleListCompactions > compaction handlers > returns empty list when session has no compactions [5.43ms]
handleListCompactions > compaction handlers > returns compaction summaries [7.72ms]
handleListCompactions > compaction handlers > filters by agent_path in memory [6.04ms]
handleListCompactions > compaction handlers > passes pagination to storage and returns next_cursor [5.57ms]
handleGetCompaction > compaction handlers > returns 503 when storage is unavailable [7.03ms]
handleGetCompaction > compaction handlers > returns full compaction detail [6.24ms]
handleGetCompaction > compaction handlers > returns 404 when compaction is not found [4.95ms]
handlePatchCompaction > compaction handlers > returns 503 when storage is unavailable [7.02ms]
handlePatchCompaction > compaction handlers > updates a valid operator flag [6.27ms]
handlePatchCompaction > compaction handlers > updates operator notes [5.32ms]
handlePatchCompaction > compaction handlers > clears operator flag when null is provided [7.51ms]
handlePatchCompaction > compaction handlers > returns 422 for an invalid flag [5.67ms]
handlePatchCompaction > compaction handlers > returns 422 when notes exceed the maximum length [4.83ms]
handlePatchCompaction > compaction handlers > returns 404 when compaction is not found [7.03ms]
handlePatchCompaction > compaction handlers > publishes compaction.flagged event [5.73ms]
handlePostCompact > compaction handlers > returns 503 when storage is unavailable [5.54ms]
handlePostCompact > compaction handlers > accepts manual compaction and persists the result [11.51ms]
handlePostCompact > compaction handlers > returns synchronous dry_run proposal without persisting [6.97ms]
handlePostCompact > compaction handlers > returns 404 when the session is not found [8.19ms]
handlePostCompact > compaction handlers > returns 422 for an invalid strategy [5.76ms]
handlePostCompact > compaction handlers > publishes compaction.triggered and compaction.completed events [13.22ms]
handlePostCompact > compaction handlers > uses requested agent_path in the response and events [7.86ms]
route registration > 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 > dispatchPrimary integration > run completes with state 'done' [8.51ms]
happy path > dispatchPrimary integration > assistant message persisted to storage [11.72ms]
happy path > dispatchPrimary integration > persisted message has provider metadata [6.73ms]
happy path > dispatchPrimary integration > session transitions back to idle [10.99ms]
happy path > dispatchPrimary integration > runPrimary receives correct provider route [6.71ms]
happy path > dispatchPrimary integration > runPrimary receives reconstructed operator message [11.44ms]
happy path > dispatchPrimary integration > runPrimary receives system prompt content [6.63ms]
happy path > 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 > dispatchPrimary integration > run marked failed when runPrimary returns error [7.68ms]
error mid-stream > dispatchPrimary integration > session still transitions to idle after error [11.44ms]
error mid-stream > 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 > dispatchPrimary integration > override bypasses alias resolution and routes directly [11.52ms]
model override > dispatchPrimary integration > override works even when alias is missing [11.09ms]
model override > dispatchPrimary integration > override with unknown provider fails [6.04ms]
model override > dispatchPrimary integration > override with invalid format fails [10.08ms]
model override > dispatchPrimary integration > override with no api key fails [6.26ms]
abort controller registry > dispatchPrimary integration > controller is registered while runPrimary is executing [10.10ms]
abort controller registry > dispatchPrimary integration > controller is deregistered after successful completion [6.53ms]
abort controller registry > dispatchPrimary integration > controller is deregistered after error result [10.59ms]
abort controller registry > dispatchPrimary integration > controller is deregistered after runPrimary throws [6.67ms]
abort controller registry > dispatchPrimary integration > abort signal is passed to runPrimaryFn [10.55ms]
abort controller registry > dispatchPrimary integration > getRunController returns undefined for unknown run [4.56ms]
run.started event > dispatchPrimary event publishing > published before runPrimary executes [9.35ms]
run.started event > dispatchPrimary event publishing > has correct payload [6.96ms]
run.ended event > dispatchPrimary event publishing > published after successful completion with outcome 'completed' [11.09ms]
run.ended event > dispatchPrimary event publishing > published after error result with outcome 'failed' [6.76ms]
run.ended event > dispatchPrimary event publishing > published after runPrimary throws with outcome 'failed' [11.35ms]
run.ended event > dispatchPrimary event publishing > published after config-missing failure with outcome 'failed' [4.88ms]
run.ended event > dispatchPrimary event publishing > run.started is NOT published on early dispatch failure [5.35ms]
event ordering > dispatchPrimary event publishing > run.started comes before run.ended on success [9.95ms]
event ordering > dispatchPrimary event publishing > run.started comes before run.ended on error result [10.27ms]
harness event relay > dispatchPrimary event publishing > publish callback relays events through publishHarnessEvent [6.81ms]
harness event relay > 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]

Mentioned in

Type Document
adr ADR-0004: Runtime is Bun + TypeScript
adr ADR-0010: kaged supports per-user and system-wide deployment, equally
adr ADR-0011: Projects are portable; operator-local concerns live in local config
adr ADR-0016: Streaming-first UI — live data and operator abort are non-negotiable
adr ADR-0017: Guests are first-class identities with daemon-managed credentials
adr ADR-0022: Agents are recursive; tools and cage are per-agent
adr ADR-0030: Log streaming via Server-Sent Events
adr ADR-0031: An assistant turn is an ordered transcript of parts, not a flattened bubble
adr ADR-0033: Tool dot-namespace convention
spec Spec: Agent Tooling
spec Spec: Agent Harness
spec Spec: Daemon
spec Spec: Guests and Project Grants
spec Spec: HTTP + WebSocket API
spec Spec: Issues
spec Spec: Local config
spec Spec: Operational Logging
spec Spec: Plugin Host
spec Spec: Project DSL
spec Spec: project.recipe
spec Spec: Project Terminals
spec Spec: Sandbox
spec Spec: Session Manager
spec Spec: Task Runner
spec Spec: Workflows