Test Report – SDK Bridge
Generated: 2026-03-14T13:31:04.474Z | Exit code: 0 | Duration: 35 ms
Tests by file
gateway starts and GET /health returns 200
- gateway starts and GET /health returns 200
WebSocket ping returns ok
- WebSocket ping returns ok
WebSocket getCapabilities returns supportedMethods and capabilityRegistry
- WebSocket getCapabilities returns supportedMethods and capabilityRegistry
WebSocket executePlan dry-run returns results and success
- WebSocket executePlan dry-run returns results and success
WebSocket auditListRecent returns actions array
- WebSocket auditListRecent returns actions array
WebSocket automationList returns automations array
- WebSocket automationList returns automations array
WebSocket getDesktopState returns object
- WebSocket getDesktopState returns object
WebSocket emergencyStop and getDeniedPermissions
- WebSocket emergencyStop and getDeniedPermissions
WebSocket invalid method returns error
- WebSocket invalid method returns error
checkPlan with low-risk steps returns allowed
- checkPlan with low-risk steps returns allowed
checkPlan with high-risk steps sets requiresApproval
- checkPlan with high-risk steps sets requiresApproval
checkPlan with missing steps returns error
- checkPlan with missing steps returns error
setPermission deny then checkPlan denies plan
- setPermission deny then checkPlan denies plan
setPermission then getDeniedPermissions lists denied
- setPermission then getDeniedPermissions lists denied
executePlan with denied capability returns PERMISSION_DENIED
- executePlan with denied capability returns PERMISSION_DENIED
executePlan with empty steps returns success
- executePlan with empty steps returns success
executePlan without steps param returns error
- executePlan without steps param returns error
auditListRecent with limit 3 returns at most 3
- auditListRecent with limit 3 returns at most 3
auditRevert with non-existent id returns error
- auditRevert with non-existent id returns error
automationCreate returns id and automationList includes it
- automationCreate returns id and automationList includes it
automationUpdate then automationList reflects change
- automationUpdate then automationList reflects change
automationPause then automation has enabled false
- automationPause then automation has enabled false
automationDelete removes automation
- automationDelete removes automation
getDesktopState returns object with expected keys or empty
- getDesktopState returns object with expected keys or empty
emergencyStop then emergencyResume restores execution
- emergencyStop then emergencyResume restores execution
executePlan dry-run with multiple capabilities returns one result per step
- executePlan dry-run with multiple capabilities returns one result per step
getPlan without message returns error
- getPlan without message returns error
setPermission without capabilityId returns error
- setPermission without capabilityId returns error
auditRevert without actionId returns error
- auditRevert without actionId returns error
automationCreate without trigger returns error
- automationCreate without trigger returns error
getPlan with real message returns plan when E2E_GETPLAN=1
- getPlan with real message returns plan when E2E_GETPLAN=1
getDesktopState returns live desktop data (windows/panels when available)
- getDesktopState returns live desktop data (windows/panels when available)
logExecution returns action id and listRecent includes it
- logExecution returns action id and listRecent includes it
listRecent respects limit and returns newest first
- listRecent respects limit and returns newest first
revert returns error for unknown actionId
- revert returns error for unknown actionId
revert returns reverted true for known action (no snapshots to restore)
- revert returns reverted true for known action (no snapshots to restore)
listCapabilityIds returns non-empty array
- listCapabilityIds returns non-empty array
execute with unknown capabilityId returns ok false
- execute with unknown capabilityId returns ok false
notification.show dry-run returns ok true
- notification.show dry-run returns ok true
window.list dry-run returns ok true
- window.list dry-run returns ok true
power.lock_screen dry-run returns ok true
- power.lock_screen dry-run returns ok true
display.brightness.set dry-run returns ok true
- display.brightness.set dry-run returns ok true
audio.volume.set dry-run returns ok true
- audio.volume.set dry-run returns ok true
app.launch dry-run returns ok true
- app.launch dry-run returns ok true
panel.get_layout dry-run returns ok true
- panel.get_layout dry-run returns ok true
theme.preview dry-run returns ok true
- theme.preview dry-run returns ok true
getList returns array with expected capability ids
- getList returns array with expected capability ids
each entry has id and schema
- each entry has id and schema
register adds or updates capability
- register adds or updates capability
executePlan with dryRun returns success and results without running adapters
- executePlan with dryRun returns success and results without running adapters
executePlan with unknown capability returns ok false for that step
- executePlan with unknown capability returns ok false for that step
executePlan when emergency paused returns empty results and success false
- executePlan when emergency paused returns empty results and success false
executePlan with empty steps returns success true
- executePlan with empty steps returns success true
getRiskLevel returns high for settings.write and theme.apply
- getRiskLevel returns high for settings.write and theme.apply
getRiskLevel returns medium for window.move and app.launch
- getRiskLevel returns medium for window.move and app.launch
getRiskLevel returns low for notification.show and window.list
- getRiskLevel returns low for notification.show and window.list
checkPlan allows plan when no capability denied
- checkPlan allows plan when no capability denied
checkPlan denies when capability is denied
- checkPlan denies when capability is denied
checkPlan sets requiresApproval for high-risk steps
- checkPlan sets requiresApproval for high-risk steps
getDeniedList and setPermission
- getDeniedList and setPermission
SUPPORTED_METHODS includes expected methods
- SUPPORTED_METHODS includes expected methods
validateRequest rejects missing method
- validateRequest rejects missing method
validateRequest rejects unknown method
- validateRequest rejects unknown method
validateRequest accepts chat with message
- validateRequest accepts chat with message
validateRequest rejects chat without message
- validateRequest rejects chat without message
validateRequest accepts health and ping with no params
- validateRequest accepts health and ping with no params
validateRequest accepts executePlan with steps array
- validateRequest accepts executePlan with steps array
validateRequest rejects executePlan without steps
- validateRequest rejects executePlan without steps
validateRequest accepts getPlan with message
- validateRequest accepts getPlan with message
validateRequest accepts setPermission with capabilityId and allow
- validateRequest accepts setPermission with capabilityId and allow
validateRequest accepts auditRevert with actionId
- validateRequest accepts auditRevert with actionId
validateRequest accepts automationCreate with trigger and steps
- validateRequest accepts automationCreate with trigger and steps
validateRequest accepts getDesktopState, emergencyStop, emergencyResume, getDeniedPermissions with no params
- validateRequest accepts getDesktopState, emergencyStop, emergencyResume, getDeniedPermissions with no params
sendResponse and sendError produce valid envelope shape
- sendResponse and sendError produce valid envelope shape
sendEvent produces event envelope
- sendEvent produces event envelope
route returns provider opencode for any intent
- route returns provider opencode for any intent
route returns provider for short quick-desktop style intent
- route returns provider for short quick-desktop style intent
route returns provider for long intent
- route returns provider for long intent
route handles empty intent
- route handles empty intent
initScheduler with null dir and list returns array
- initScheduler with null dir and list returns array
create returns id and list includes new automation
- create returns id and list includes new automation
update changes steps and enabled
- update changes steps and enabled
setPaused pauses and resumes
- setPaused pauses and resumes
remove deletes automation
- remove deletes automation
remove throws for unknown id
- remove throws for unknown id
validateWithSchema accepts valid chat params
- validateWithSchema accepts valid chat params
validateWithSchema rejects chat without message
- validateWithSchema rejects chat without message
validateWithSchema accepts valid generateCode params
- validateWithSchema accepts valid generateCode params
validateWithSchema accepts valid editCode params
- validateWithSchema accepts valid editCode params
validateWithSchema accepts valid writeFile params
- validateWithSchema accepts valid writeFile params
validateWithSchema passes through unknown method with ok true
- validateWithSchema passes through unknown method with ok true
getDesktopState returns an object
- getDesktopState returns an object
getDesktopState may have windows, panels, theme keys
- getDesktopState may have windows, panels, theme keys
in-memory setSnapshot and getSnapshot
- in-memory setSnapshot and getSnapshot
getSnapshot returns null for missing key
- getSnapshot returns null for missing key
deleteSnapshot removes key
- deleteSnapshot removes key
restoreSnapshot returns error for non-restorable snapshot
- restoreSnapshot returns error for non-restorable snapshot
restoreSnapshot returns error for missing snapshot
- restoreSnapshot returns error for missing snapshot
file-backed persistence when stateDir is set
- file-backed persistence when stateDir is set
All tests
| Status | Test | File |
| passed |
gateway starts and GET /health returns 200 |
gateway starts and GET /health returns 200 |
| passed |
WebSocket ping returns ok |
WebSocket ping returns ok |
| passed |
WebSocket getCapabilities returns supportedMethods and capabilityRegistry |
WebSocket getCapabilities returns supportedMethods and capabilityRegistry |
| passed |
WebSocket executePlan dry-run returns results and success |
WebSocket executePlan dry-run returns results and success |
| passed |
WebSocket auditListRecent returns actions array |
WebSocket auditListRecent returns actions array |
| passed |
WebSocket automationList returns automations array |
WebSocket automationList returns automations array |
| passed |
WebSocket getDesktopState returns object |
WebSocket getDesktopState returns object |
| passed |
WebSocket emergencyStop and getDeniedPermissions |
WebSocket emergencyStop and getDeniedPermissions |
| passed |
WebSocket invalid method returns error |
WebSocket invalid method returns error |
| passed |
checkPlan with low-risk steps returns allowed |
checkPlan with low-risk steps returns allowed |
| passed |
checkPlan with high-risk steps sets requiresApproval |
checkPlan with high-risk steps sets requiresApproval |
| passed |
checkPlan with missing steps returns error |
checkPlan with missing steps returns error |
| passed |
setPermission deny then checkPlan denies plan |
setPermission deny then checkPlan denies plan |
| passed |
setPermission then getDeniedPermissions lists denied |
setPermission then getDeniedPermissions lists denied |
| passed |
executePlan with denied capability returns PERMISSION_DENIED |
executePlan with denied capability returns PERMISSION_DENIED |
| passed |
executePlan with empty steps returns success |
executePlan with empty steps returns success |
| passed |
executePlan without steps param returns error |
executePlan without steps param returns error |
| passed |
auditListRecent with limit 3 returns at most 3 |
auditListRecent with limit 3 returns at most 3 |
| passed |
auditRevert with non-existent id returns error |
auditRevert with non-existent id returns error |
| passed |
automationCreate returns id and automationList includes it |
automationCreate returns id and automationList includes it |
| passed |
automationUpdate then automationList reflects change |
automationUpdate then automationList reflects change |
| passed |
automationPause then automation has enabled false |
automationPause then automation has enabled false |
| passed |
automationDelete removes automation |
automationDelete removes automation |
| passed |
getDesktopState returns object with expected keys or empty |
getDesktopState returns object with expected keys or empty |
| passed |
emergencyStop then emergencyResume restores execution |
emergencyStop then emergencyResume restores execution |
| passed |
executePlan dry-run with multiple capabilities returns one result per step |
executePlan dry-run with multiple capabilities returns one result per step |
| passed |
getPlan without message returns error |
getPlan without message returns error |
| passed |
setPermission without capabilityId returns error |
setPermission without capabilityId returns error |
| passed |
auditRevert without actionId returns error |
auditRevert without actionId returns error |
| passed |
automationCreate without trigger returns error |
automationCreate without trigger returns error |
| passed |
getPlan with real message returns plan when E2E_GETPLAN=1 |
getPlan with real message returns plan when E2E_GETPLAN=1 |
| passed |
getDesktopState returns live desktop data (windows/panels when available) |
getDesktopState returns live desktop data (windows/panels when available) |
| passed |
logExecution returns action id and listRecent includes it |
logExecution returns action id and listRecent includes it |
| passed |
listRecent respects limit and returns newest first |
listRecent respects limit and returns newest first |
| passed |
revert returns error for unknown actionId |
revert returns error for unknown actionId |
| passed |
revert returns reverted true for known action (no snapshots to restore) |
revert returns reverted true for known action (no snapshots to restore) |
| passed |
listCapabilityIds returns non-empty array |
listCapabilityIds returns non-empty array |
| passed |
execute with unknown capabilityId returns ok false |
execute with unknown capabilityId returns ok false |
| passed |
notification.show dry-run returns ok true |
notification.show dry-run returns ok true |
| passed |
window.list dry-run returns ok true |
window.list dry-run returns ok true |
| passed |
power.lock_screen dry-run returns ok true |
power.lock_screen dry-run returns ok true |
| passed |
display.brightness.set dry-run returns ok true |
display.brightness.set dry-run returns ok true |
| passed |
audio.volume.set dry-run returns ok true |
audio.volume.set dry-run returns ok true |
| passed |
app.launch dry-run returns ok true |
app.launch dry-run returns ok true |
| passed |
panel.get_layout dry-run returns ok true |
panel.get_layout dry-run returns ok true |
| passed |
theme.preview dry-run returns ok true |
theme.preview dry-run returns ok true |
| passed |
getList returns array with expected capability ids |
getList returns array with expected capability ids |
| passed |
each entry has id and schema |
each entry has id and schema |
| passed |
register adds or updates capability |
register adds or updates capability |
| passed |
executePlan with dryRun returns success and results without running adapters |
executePlan with dryRun returns success and results without running adapters |
| passed |
executePlan with unknown capability returns ok false for that step |
executePlan with unknown capability returns ok false for that step |
| passed |
executePlan when emergency paused returns empty results and success false |
executePlan when emergency paused returns empty results and success false |
| passed |
executePlan with empty steps returns success true |
executePlan with empty steps returns success true |
| passed |
getRiskLevel returns high for settings.write and theme.apply |
getRiskLevel returns high for settings.write and theme.apply |
| passed |
getRiskLevel returns medium for window.move and app.launch |
getRiskLevel returns medium for window.move and app.launch |
| passed |
getRiskLevel returns low for notification.show and window.list |
getRiskLevel returns low for notification.show and window.list |
| passed |
checkPlan allows plan when no capability denied |
checkPlan allows plan when no capability denied |
| passed |
checkPlan denies when capability is denied |
checkPlan denies when capability is denied |
| passed |
checkPlan sets requiresApproval for high-risk steps |
checkPlan sets requiresApproval for high-risk steps |
| passed |
getDeniedList and setPermission |
getDeniedList and setPermission |
| passed |
emergency pause state |
emergency pause state |
| passed |
SUPPORTED_METHODS includes expected methods |
SUPPORTED_METHODS includes expected methods |
| passed |
validateRequest rejects missing method |
validateRequest rejects missing method |
| passed |
validateRequest rejects unknown method |
validateRequest rejects unknown method |
| passed |
validateRequest accepts chat with message |
validateRequest accepts chat with message |
| passed |
validateRequest rejects chat without message |
validateRequest rejects chat without message |
| passed |
validateRequest accepts health and ping with no params |
validateRequest accepts health and ping with no params |
| passed |
validateRequest accepts executePlan with steps array |
validateRequest accepts executePlan with steps array |
| passed |
validateRequest rejects executePlan without steps |
validateRequest rejects executePlan without steps |
| passed |
validateRequest accepts getPlan with message |
validateRequest accepts getPlan with message |
| passed |
validateRequest accepts setPermission with capabilityId and allow |
validateRequest accepts setPermission with capabilityId and allow |
| passed |
validateRequest accepts auditRevert with actionId |
validateRequest accepts auditRevert with actionId |
| passed |
validateRequest accepts automationCreate with trigger and steps |
validateRequest accepts automationCreate with trigger and steps |
| passed |
validateRequest accepts getDesktopState, emergencyStop, emergencyResume, getDeniedPermissions with no params |
validateRequest accepts getDesktopState, emergencyStop, emergencyResume, getDeniedPermissions with no params |
| passed |
sendResponse and sendError produce valid envelope shape |
sendResponse and sendError produce valid envelope shape |
| passed |
sendEvent produces event envelope |
sendEvent produces event envelope |
| passed |
route returns provider opencode for any intent |
route returns provider opencode for any intent |
| passed |
route returns provider for short quick-desktop style intent |
route returns provider for short quick-desktop style intent |
| passed |
route returns provider for long intent |
route returns provider for long intent |
| passed |
route handles empty intent |
route handles empty intent |
| passed |
initScheduler with null dir and list returns array |
initScheduler with null dir and list returns array |
| passed |
create returns id and list includes new automation |
create returns id and list includes new automation |
| passed |
update changes steps and enabled |
update changes steps and enabled |
| passed |
setPaused pauses and resumes |
setPaused pauses and resumes |
| passed |
remove deletes automation |
remove deletes automation |
| passed |
remove throws for unknown id |
remove throws for unknown id |
| passed |
validateWithSchema accepts valid chat params |
validateWithSchema accepts valid chat params |
| passed |
validateWithSchema rejects chat without message |
validateWithSchema rejects chat without message |
| passed |
validateWithSchema accepts valid generateCode params |
validateWithSchema accepts valid generateCode params |
| passed |
validateWithSchema accepts valid editCode params |
validateWithSchema accepts valid editCode params |
| passed |
validateWithSchema accepts valid writeFile params |
validateWithSchema accepts valid writeFile params |
| passed |
validateWithSchema passes through unknown method with ok true |
validateWithSchema passes through unknown method with ok true |
| passed |
getDesktopState returns an object |
getDesktopState returns an object |
| passed |
getDesktopState may have windows, panels, theme keys |
getDesktopState may have windows, panels, theme keys |
| passed |
in-memory setSnapshot and getSnapshot |
in-memory setSnapshot and getSnapshot |
| passed |
getSnapshot returns null for missing key |
getSnapshot returns null for missing key |
| passed |
deleteSnapshot removes key |
deleteSnapshot removes key |
| passed |
restoreSnapshot returns error for non-restorable snapshot |
restoreSnapshot returns error for non-restorable snapshot |
| passed |
restoreSnapshot returns error for missing snapshot |
restoreSnapshot returns error for missing snapshot |
| passed |
file-backed persistence when stateDir is set |
file-backed persistence when stateDir is set |
Raw output (TAP)
TAP version 13
# {"timestamp":1773495064310,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
# Subtest: gateway starts and GET /health returns 200
# {"timestamp":1773495064337,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 1 - gateway starts and GET /health returns 200
---
duration_ms: 35.262801
...
# {"timestamp":1773495064347,"level":"info","event":"ws.connected","sdkInitialized":false}
# Subtest: WebSocket ping returns ok
# {"timestamp":1773495064354,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 2 - WebSocket ping returns ok
---
duration_ms: 17.017428
...
# {"timestamp":1773495064356,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064358,"level":"info","event":"ws.closed"}
# Subtest: WebSocket getCapabilities returns supportedMethods and capabilityRegistry
# {"timestamp":1773495064360,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 3 - WebSocket getCapabilities returns supportedMethods and capabilityRegistry
---
duration_ms: 6.600831
...
# {"timestamp":1773495064363,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064364,"level":"info","event":"ws.closed"}
# {"timestamp":1773495064365,"level":"info","event":"executor.step","capabilityId":"notification.show","ok":true,"dryRun":true}
# Subtest: WebSocket executePlan dry-run returns results and success
# {"timestamp":1773495064366,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 4 - WebSocket executePlan dry-run returns results and success
---
duration_ms: 5.651215
...
# {"timestamp":1773495064368,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064369,"level":"info","event":"ws.closed"}
# Subtest: WebSocket auditListRecent returns actions array
# {"timestamp":1773495064370,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 5 - WebSocket auditListRecent returns actions array
---
duration_ms: 4.000918
...
# {"timestamp":1773495064372,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064373,"level":"info","event":"ws.closed"}
# Subtest: WebSocket automationList returns automations array
# {"timestamp":1773495064375,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 6 - WebSocket automationList returns automations array
---
duration_ms: 4.229713
...
# {"timestamp":1773495064376,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064377,"level":"info","event":"ws.closed"}
# Subtest: WebSocket getDesktopState returns object
# {"timestamp":1773495064385,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 7 - WebSocket getDesktopState returns object
---
duration_ms: 9.957598
...
# {"timestamp":1773495064387,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064388,"level":"info","event":"ws.closed"}
# Subtest: WebSocket emergencyStop and getDeniedPermissions
# {"timestamp":1773495064390,"level":"info","event":"server.listening","port":18770,"sdkInitialized":false}
ok 8 - WebSocket emergencyStop and getDeniedPermissions
---
duration_ms: 4.705925
...
# {"timestamp":1773495064392,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064393,"level":"info","event":"ws.closed"}
# Subtest: WebSocket invalid method returns error
ok 9 - WebSocket invalid method returns error
---
duration_ms: 3.990377
...
# {"timestamp":1773495064394,"level":"info","event":"ws.closed"}
# {"timestamp":1773495064306,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
# {"timestamp":1773495064313,"level":"info","event":"ws.connected","sdkInitialized":false}
# Subtest: checkPlan with low-risk steps returns allowed
# {"timestamp":1773495064320,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 10 - checkPlan with low-risk steps returns allowed
---
duration_ms: 23.079922
...
# {"timestamp":1773495064322,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064323,"level":"info","event":"ws.closed"}
# Subtest: checkPlan with high-risk steps sets requiresApproval
# {"timestamp":1773495064326,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 11 - checkPlan with high-risk steps sets requiresApproval
---
duration_ms: 5.921204
...
# {"timestamp":1773495064328,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064328,"level":"info","event":"ws.closed"}
# Subtest: checkPlan with missing steps returns error
# {"timestamp":1773495064330,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 12 - checkPlan with missing steps returns error
---
duration_ms: 4.217445
...
# {"timestamp":1773495064331,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064332,"level":"info","event":"ws.closed"}
# Subtest: setPermission deny then checkPlan denies plan
# {"timestamp":1773495064334,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 13 - setPermission deny then checkPlan denies plan
---
duration_ms: 4.129147
...
# {"timestamp":1773495064336,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064337,"level":"info","event":"ws.closed"}
# Subtest: setPermission then getDeniedPermissions lists denied
# {"timestamp":1773495064339,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 14 - setPermission then getDeniedPermissions lists denied
---
duration_ms: 4.829458
...
# {"timestamp":1773495064343,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064344,"level":"info","event":"ws.closed"}
# Subtest: executePlan with denied capability returns PERMISSION_DENIED
# {"timestamp":1773495064346,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 15 - executePlan with denied capability returns PERMISSION_DENIED
---
duration_ms: 6.209081
...
# {"timestamp":1773495064347,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064348,"level":"info","event":"ws.closed"}
# Subtest: executePlan with empty steps returns success
# {"timestamp":1773495064350,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 16 - executePlan with empty steps returns success
---
duration_ms: 3.928414
...
# {"timestamp":1773495064351,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064351,"level":"info","event":"ws.closed"}
# Subtest: executePlan without steps param returns error
# {"timestamp":1773495064353,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 17 - executePlan without steps param returns error
---
duration_ms: 2.749635
...
# {"timestamp":1773495064354,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064355,"level":"info","event":"ws.closed"}
# Subtest: auditListRecent with limit 3 returns at most 3
# {"timestamp":1773495064356,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 18 - auditListRecent with limit 3 returns at most 3
---
duration_ms: 3.497624
...
# {"timestamp":1773495064357,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064358,"level":"info","event":"ws.closed"}
# Subtest: auditRevert with non-existent id returns error
# {"timestamp":1773495064360,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 19 - auditRevert with non-existent id returns error
---
duration_ms: 3.644918
...
# {"timestamp":1773495064362,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064363,"level":"info","event":"ws.closed"}
# Subtest: automationCreate returns id and automationList includes it
# {"timestamp":1773495064365,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 20 - automationCreate returns id and automationList includes it
---
duration_ms: 4.873618
...
# {"timestamp":1773495064367,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064368,"level":"info","event":"ws.closed"}
# Subtest: automationUpdate then automationList reflects change
# {"timestamp":1773495064369,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 21 - automationUpdate then automationList reflects change
---
duration_ms: 4.140781
...
# {"timestamp":1773495064371,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064372,"level":"info","event":"ws.closed"}
# Subtest: automationPause then automation has enabled false
# {"timestamp":1773495064374,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 22 - automationPause then automation has enabled false
---
duration_ms: 4.301412
...
# {"timestamp":1773495064376,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064376,"level":"info","event":"ws.closed"}
# Subtest: automationDelete removes automation
# {"timestamp":1773495064378,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 23 - automationDelete removes automation
---
duration_ms: 3.951736
...
# {"timestamp":1773495064379,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064380,"level":"info","event":"ws.closed"}
# Subtest: getDesktopState returns object with expected keys or empty
# {"timestamp":1773495064386,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 24 - getDesktopState returns object with expected keys or empty
---
duration_ms: 7.281329
...
# {"timestamp":1773495064387,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064388,"level":"info","event":"ws.closed"}
# Subtest: emergencyStop then emergencyResume restores execution
# {"timestamp":1773495064390,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 25 - emergencyStop then emergencyResume restores execution
---
duration_ms: 3.81353
...
# {"timestamp":1773495064391,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064392,"level":"info","event":"ws.closed"}
# {"timestamp":1773495064396,"level":"info","event":"executor.step","capabilityId":"window.list","ok":true,"dryRun":true}
# {"timestamp":1773495064396,"level":"info","event":"executor.step","capabilityId":"notification.show","ok":true,"dryRun":true}
# Subtest: executePlan dry-run with multiple capabilities returns one result per step
# {"timestamp":1773495064397,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 26 - executePlan dry-run with multiple capabilities returns one result per step
---
duration_ms: 7.000131
...
# {"timestamp":1773495064398,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064399,"level":"info","event":"ws.closed"}
# Subtest: getPlan without message returns error
# {"timestamp":1773495064401,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 27 - getPlan without message returns error
---
duration_ms: 3.68112
...
# {"timestamp":1773495064403,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064404,"level":"info","event":"ws.closed"}
# Subtest: setPermission without capabilityId returns error
# {"timestamp":1773495064405,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 28 - setPermission without capabilityId returns error
---
duration_ms: 4.414768
...
# {"timestamp":1773495064406,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064407,"level":"info","event":"ws.closed"}
# Subtest: auditRevert without actionId returns error
# {"timestamp":1773495064408,"level":"info","event":"server.listening","port":18771,"sdkInitialized":false}
ok 29 - auditRevert without actionId returns error
---
duration_ms: 2.814115
...
# {"timestamp":1773495064410,"level":"info","event":"ws.connected","sdkInitialized":false}
# {"timestamp":1773495064411,"level":"info","event":"ws.closed"}
# Subtest: automationCreate without trigger returns error
ok 30 - automationCreate without trigger returns error
---
duration_ms: 3.371327
...
# {"timestamp":1773495064412,"level":"info","event":"ws.closed"}
# Subtest: getPlan with real message returns plan when E2E_GETPLAN=1
ok 31 - getPlan with real message returns plan when E2E_GETPLAN=1 # SKIP
---
duration_ms: 1.07672
...
# {"timestamp":1773495064321,"level":"info","event":"server.listening","port":18772,"sdkInitialized":false}
# {"timestamp":1773495064331,"level":"info","event":"ws.connected","sdkInitialized":false}
# Subtest: getDesktopState returns live desktop data (windows/panels when available)
ok 32 - getDesktopState returns live desktop data (windows/panels when available)
---
duration_ms: 31.184032
...
# {"timestamp":1773495064343,"level":"info","event":"ws.closed"}
# {"timestamp":1773495064180,"level":"info","event":"audit.logged","id":"action-1-1773495064180","steps":1}
# {"timestamp":1773495064187,"level":"info","event":"audit.logged","id":"action-2-1773495064187","steps":0}
# {"timestamp":1773495064188,"level":"info","event":"audit.reverted","actionId":"action-2-1773495064187"}
# Subtest: logExecution returns action id and listRecent includes it
ok 33 - logExecution returns action id and listRecent includes it
---
duration_ms: 4.989089
...
# Subtest: listRecent respects limit and returns newest first
ok 34 - listRecent respects limit and returns newest first
---
duration_ms: 0.19342
...
# Subtest: revert returns error for unknown actionId
ok 35 - revert returns error for unknown actionId
---
duration_ms: 0.282002
...
# Subtest: revert returns reverted true for known action (no snapshots to restore)
ok 36 - revert returns reverted true for known action (no snapshots to restore)
---
duration_ms: 0.779934
...
# Subtest: listCapabilityIds returns non-empty array
ok 37 - listCapabilityIds returns non-empty array
---
duration_ms: 2.20314
...
# Subtest: execute with unknown capabilityId returns ok false
ok 38 - execute with unknown capabilityId returns ok false
---
duration_ms: 0.287942
...
# Subtest: notification.show dry-run returns ok true
ok 39 - notification.show dry-run returns ok true
---
duration_ms: 0.323658
...
# Subtest: window.list dry-run returns ok true
ok 40 - window.list dry-run returns ok true
---
duration_ms: 7.745331
...
# Subtest: power.lock_screen dry-run returns ok true
ok 41 - power.lock_screen dry-run returns ok true
---
duration_ms: 0.362939
...
# Subtest: display.brightness.set dry-run returns ok true
ok 42 - display.brightness.set dry-run returns ok true
---
duration_ms: 0.301082
...
# Subtest: audio.volume.set dry-run returns ok true
ok 43 - audio.volume.set dry-run returns ok true
---
duration_ms: 0.248977
...
# Subtest: app.launch dry-run returns ok true
ok 44 - app.launch dry-run returns ok true
---
duration_ms: 0.271499
...
# Subtest: panel.get_layout dry-run returns ok true
ok 45 - panel.get_layout dry-run returns ok true
---
duration_ms: 0.340813
...
# Subtest: theme.preview dry-run returns ok true
ok 46 - theme.preview dry-run returns ok true
---
duration_ms: 0.446982
...
# Subtest: getList returns array with expected capability ids
ok 47 - getList returns array with expected capability ids
---
duration_ms: 3.662524
...
# Subtest: each entry has id and schema
ok 48 - each entry has id and schema
---
duration_ms: 0.228857
...
# Subtest: register adds or updates capability
ok 49 - register adds or updates capability
---
duration_ms: 0.286184
...
# {"timestamp":1773495064206,"level":"info","event":"executor.step","capabilityId":"notification.show","ok":true,"dryRun":true}
# {"timestamp":1773495064215,"level":"info","event":"executor.step","capabilityId":"window.list","ok":true,"dryRun":true}
# {"timestamp":1773495064222,"level":"info","event":"executor.step","capabilityId":"unknown.capability","ok":false,"dryRun":true}
# Subtest: executePlan with dryRun returns success and results without running adapters
ok 50 - executePlan with dryRun returns success and results without running adapters
---
duration_ms: 16.30432
...
# Subtest: executePlan with unknown capability returns ok false for that step
ok 51 - executePlan with unknown capability returns ok false for that step
---
duration_ms: 0.519796
...
# Subtest: executePlan when emergency paused returns empty results and success false
ok 52 - executePlan when emergency paused returns empty results and success false
---
duration_ms: 0.21024
...
# Subtest: executePlan with empty steps returns success true
ok 53 - executePlan with empty steps returns success true
---
duration_ms: 0.170262
...
# Subtest: getRiskLevel returns high for settings.write and theme.apply
ok 54 - getRiskLevel returns high for settings.write and theme.apply
---
duration_ms: 2.855703
...
# Subtest: getRiskLevel returns medium for window.move and app.launch
ok 55 - getRiskLevel returns medium for window.move and app.launch
---
duration_ms: 0.209329
...
# Subtest: getRiskLevel returns low for notification.show and window.list
ok 56 - getRiskLevel returns low for notification.show and window.list
---
duration_ms: 0.168686
...
# Subtest: checkPlan allows plan when no capability denied
ok 57 - checkPlan allows plan when no capability denied
---
duration_ms: 0.542366
...
# Subtest: checkPlan denies when capability is denied
ok 58 - checkPlan denies when capability is denied
---
duration_ms: 0.324301
...
# Subtest: checkPlan sets requiresApproval for high-risk steps
ok 59 - checkPlan sets requiresApproval for high-risk steps
---
duration_ms: 0.169279
...
# Subtest: getDeniedList and setPermission
ok 60 - getDeniedList and setPermission
---
duration_ms: 0.179424
...
# Subtest: emergency pause state
ok 61 - emergency pause state
---
duration_ms: 0.337992
...
# Subtest: SUPPORTED_METHODS includes expected methods
ok 62 - SUPPORTED_METHODS includes expected methods
---
duration_ms: 2.951497
...
# Subtest: validateRequest rejects missing method
ok 63 - validateRequest rejects missing method
---
duration_ms: 0.298851
...
# Subtest: validateRequest rejects unknown method
ok 64 - validateRequest rejects unknown method
---
duration_ms: 0.144912
...
# Subtest: validateRequest accepts chat with message
ok 65 - validateRequest accepts chat with message
---
duration_ms: 0.83139
...
# Subtest: validateRequest rejects chat without message
ok 66 - validateRequest rejects chat without message
---
duration_ms: 0.150713
...
# Subtest: validateRequest accepts health and ping with no params
ok 67 - validateRequest accepts health and ping with no params
---
duration_ms: 0.124677
...
# Subtest: validateRequest accepts executePlan with steps array
ok 68 - validateRequest accepts executePlan with steps array
---
duration_ms: 0.136428
...
# Subtest: validateRequest rejects executePlan without steps
ok 69 - validateRequest rejects executePlan without steps
---
duration_ms: 0.153538
...
# Subtest: validateRequest accepts getPlan with message
ok 70 - validateRequest accepts getPlan with message
---
duration_ms: 0.155742
...
# Subtest: validateRequest accepts setPermission with capabilityId and allow
ok 71 - validateRequest accepts setPermission with capabilityId and allow
---
duration_ms: 0.393757
...
# Subtest: validateRequest accepts auditRevert with actionId
ok 72 - validateRequest accepts auditRevert with actionId
---
duration_ms: 0.189929
...
# Subtest: validateRequest accepts automationCreate with trigger and steps
ok 73 - validateRequest accepts automationCreate with trigger and steps
---
duration_ms: 0.182084
...
# Subtest: validateRequest accepts getDesktopState, emergencyStop, emergencyResume, getDeniedPermissions with no params
ok 74 - validateRequest accepts getDesktopState, emergencyStop, emergencyResume, getDeniedPermissions with no params
---
duration_ms: 0.339719
...
# Subtest: sendResponse and sendError produce valid envelope shape
ok 75 - sendResponse and sendError produce valid envelope shape
---
duration_ms: 0.426361
...
# Subtest: sendEvent produces event envelope
ok 76 - sendEvent produces event envelope
---
duration_ms: 0.291482
...
# {"timestamp":1773495064205,"level":"info","event":"provider_router.routed","provider":"opencode","reason":"quick_desktop_fallback"}
# {"timestamp":1773495064211,"level":"info","event":"provider_router.routed","provider":"opencode","reason":"quick_desktop_fallback"}
# {"timestamp":1773495064212,"level":"info","event":"provider_router.routed","provider":"opencode"}
# {"timestamp":1773495064213,"level":"info","event":"provider_router.routed","provider":"opencode"}
# Subtest: route returns provider opencode for any intent
ok 77 - route returns provider opencode for any intent
---
duration_ms: 5.483607
...
# Subtest: route returns provider for short quick-desktop style intent
ok 78 - route returns provider for short quick-desktop style intent
---
duration_ms: 0.523157
...
# Subtest: route returns provider for long intent
ok 79 - route returns provider for long intent
---
duration_ms: 0.609656
...
# Subtest: route handles empty intent
ok 80 - route handles empty intent
---
duration_ms: 1.539466
...
# Subtest: initScheduler with null dir and list returns array
ok 81 - initScheduler with null dir and list returns array
---
duration_ms: 1.964995
...
# Subtest: create returns id and list includes new automation
ok 82 - create returns id and list includes new automation
---
duration_ms: 0.315259
...
# Subtest: update changes steps and enabled
ok 83 - update changes steps and enabled
---
duration_ms: 0.209924
...
# Subtest: setPaused pauses and resumes
ok 84 - setPaused pauses and resumes
---
duration_ms: 0.29249
...
# Subtest: remove deletes automation
ok 85 - remove deletes automation
---
duration_ms: 0.182173
...
# Subtest: remove throws for unknown id
ok 86 - remove throws for unknown id
---
duration_ms: 0.410789
...
# Subtest: validateWithSchema accepts valid chat params
ok 87 - validateWithSchema accepts valid chat params
---
duration_ms: 3.40644
...
# Subtest: validateWithSchema rejects chat without message
ok 88 - validateWithSchema rejects chat without message
---
duration_ms: 1.056674
...
# Subtest: validateWithSchema accepts valid generateCode params
ok 89 - validateWithSchema accepts valid generateCode params
---
duration_ms: 0.258408
...
# Subtest: validateWithSchema accepts valid editCode params
ok 90 - validateWithSchema accepts valid editCode params
---
duration_ms: 0.399495
...
# Subtest: validateWithSchema accepts valid writeFile params
ok 91 - validateWithSchema accepts valid writeFile params
---
duration_ms: 0.228806
...
# Subtest: validateWithSchema passes through unknown method with ok true
ok 92 - validateWithSchema passes through unknown method with ok true
---
duration_ms: 1.057124
...
# Subtest: getDesktopState returns an object
ok 93 - getDesktopState returns an object
---
duration_ms: 9.150338
...
# Subtest: getDesktopState may have windows, panels, theme keys
ok 94 - getDesktopState may have windows, panels, theme keys
---
duration_ms: 3.428324
...
# Subtest: in-memory setSnapshot and getSnapshot
ok 95 - in-memory setSnapshot and getSnapshot
---
duration_ms: 1.679295
...
# Subtest: getSnapshot returns null for missing key
ok 96 - getSnapshot returns null for missing key
---
duration_ms: 0.119843
...
# Subtest: deleteSnapshot removes key
ok 97 - deleteSnapshot removes key
---
duration_ms: 0.15862
...
# Subtest: restoreSnapshot returns error for non-restorable snapshot
ok 98 - restoreSnapshot returns error for non-restorable snapshot
---
duration_ms: 0.432374
...
# Subtest: restoreSnapshot returns error for missing snapshot
ok 99 - restoreSnapshot returns error for missing snapshot
---
duration_ms: 0.10687
...
# Subtest: file-backed persistence when stateDir is set
ok 100 - file-backed persistence when stateDir is set
---
duration_ms: 2.049011
...
1..100
# tests 100
# suites 0
# pass 99
# fail 0
# cancelled 0
# skipped 1
# todo 0
# duration_ms 443.358115