Skip to content

Code Quality: PR #416 #1320

Code Quality: PR #416

Code Quality: PR #416 #1320

Triggered via dynamic May 19, 2026 00:34
Status Success
Total duration 1m 26s
Artifacts

codeql

on: dynamic
Matrix: analyze
Fit to window
Zoom out
Zoom in

Annotations

2 errors and 12 warnings
UI runtime-snapshot fixtures use obsolete pre-rs/1 schema and were not regenerated for the new envelope: src/snapshot-tests/__tests__/json-normalize.test.ts#L76
The new normalization in `src/snapshot-tests/__tests__/json-normalize.test.ts` validates the rs/1 capture envelope (`protocol`, `capturedAtMs`, `expiresAtMs`, `elements`, `actions`) but three stored JSON fixtures still serialize the old runtime-snapshot shape (`rs: "1"`, `targets`, `scroll`, `udid`, no `protocol`/`capturedAtMs`/`expiresAtMs`/`elements`/`actions`): `src/snapshot-tests/__fixtures__/mcp/json/ui-automation/snapshot-ui--success.json`, `…/mcp/json/ui-automation/wait-for-ui--success.json`, and `…/cli/json/ui-automation/wait-for-ui--success.json`. Because `snapshot_ui.ts:100-101` passes `snapshot.payload` (built by `createRuntimeSnapshotRecord` in `src/mcp/tools/ui-automation/shared/runtime-snapshot.ts:556–591`, which emits the new fields) directly into `createCaptureSuccessResult`, the normalized output cannot match the stored fixtures. This violates the skill guardrails 'Fixture updates map to intentional behavior changes' and 'Missing fixtures are generated through the snapshot update flow' — these fixtures appear to have been left behind by the rs/1 refactor. (Note: the CLI `snapshot-ui--success.json` is a different `type: ui-hierarchy` envelope and is not affected.)
Smoke test still passes removed `x`/`y` params to `long_press`, which will fail schema validation: src/mcp/tools/ui-automation/long_press.ts#L36
The e2e smoke test at `src/smoke-tests/__tests__/e2e-mcp-ui-automation.test.ts:226` calls `long_press` with `{ x: 150, y: 300, duration: 500 }`, but the schema no longer accepts `x` or `y` — it requires `elementRef`. The test will now fail with a validation error. Update it to call `long_press` with a valid `elementRef` (obtained after a `snapshot_ui` call).
Local `createBootedScreenshotMockExecutor` duplicates `createCommandMatchingMockExecutor` instead of using it: src/mcp/tools/ui-automation/__tests__/screenshot.test.ts#L18
Replace the inline `createBootedScreenshotMockExecutor` with the existing `createCommandMatchingMockExecutor` helper from `mock-executors.ts`, which already handles multi-command matching for exactly this kind of multi-step tool flow.
[5G8-DF3] Local `createBootedScreenshotMockExecutor` duplicates `createCommandMatchingMockExecutor` instead of using it (additional location): src/mcp/tools/ui-automation/__tests__/screenshot.test.ts#L298
Replace the inline `createBootedScreenshotMockExecutor` with the existing `createCommandMatchingMockExecutor` helper from `mock-executors.ts`, which already handles multi-command matching for exactly this kind of multi-step tool flow.
Swipe success snapshot contract silently removed; `swipe--success.json` fixture is now orphaned: src/snapshot-tests/suites/ui-automation-suite.ts#L124
The swipe `'success'` test case (previously asserting `isError: false` against `swipe--success`) is entirely replaced by an error-only test, removing all snapshot verification of the swipe success path; the pre-existing `swipe--success.json` fixture is now an unreferenced orphan.
`ctx.nextStepParams` silently dropped — no manifest `nextSteps` templates exist to consume it: src/mcp/tools/ui-automation/wait_for_ui.ts#L364
`wait_for_uiLogic` sets `ctx.nextStepParams` (lines 364–367) but never sets `ctx.nextSteps`, and `wait_for_ui.yaml` declares no `nextSteps` templates; `postProcessSession` only merges `nextStepParams` into template-based steps, so both suggested tools (`snapshot_ui`, `wait_for_ui`) will never surface to the model — set `ctx.nextSteps` directly (as `snapshot_ui.ts` does via `createRuntimeSnapshotNextSteps`) instead.
Misleading `ACTION_FAILED` error code returned when the action actually succeeded: src/mcp/tools/ui-automation/shared/post-action-snapshot.ts#L54
When `executeAxeCommand` throws (e.g. `AxeError` or `SystemError`) after a successful UI action, the returned `uiError.code` is `'ACTION_FAILED'`, but `message` states "UI action succeeded." Agents inspecting the error code will incorrectly conclude the UI action itself failed and may retry it, potentially double-applying the action.
`inferScrollableContainers` re-adds `swipeWithin` to off-screen containers whose actions were cleared by `applyViewportVisibility`: src/mcp/tools/ui-automation/shared/runtime-snapshot.ts#L416
After `applyViewportVisibility` sets `publicElement.actions = []` for elements that don't intersect the viewport, `inferScrollableContainers` runs next and can push `swipeWithin` back onto those same off-screen `scroll-view`, `list`, and `other` containers — because it only checks `isVisible(frame)` (frame dimensions) and `actions.includes('swipeWithin')`, neither of which reflect the cleared viewport state. This surfaces invalid swipe-action hints to agents for elements they cannot actually interact with.
Non-parse snapshot capture failure mapped to 'ACTION_FAILED' despite action succeeding: src/mcp/tools/ui-automation/shared/post-action-snapshot.ts#L53
When the post-action `describe-ui` call fails for any reason other than a parse error, the returned `uiError.code` is `'ACTION_FAILED'`, but the message explicitly says "UI action succeeded." An agent receiving `code: 'ACTION_FAILED'` will likely retry the action (e.g., a tap or text entry), causing duplicate/unintended interactions.
`deriveRole` misclassifies elements with 'text' as substring (e.g. AXContextMenu → 'text'): src/mcp/tools/ui-automation/shared/runtime-snapshot.ts#L120
The pattern `/statictext|text/` is a plain substring match, so any role/type whose lowercased concatenation contains "text" (e.g. "axcontextmenu" contains "con**text**") is incorrectly classified as `'text'` before the `/menu/` check is ever reached, suppressing correct menu-role action derivation for agents.
Nested ternary operators (with IIFE) computing `matched`: src/mcp/tools/ui-automation/wait_for_ui.ts#L245
Replace the four-level nested ternary (which includes an IIFE for the `gone` branch) with an `if/else` chain or a helper function — the skill explicitly prohibits nested ternaries and requires preferring switch/if-else chains for multiple conditions.
[5HS-QCL] Nested ternary operators (with IIFE) computing `matched` (additional location): src/mcp/tools/ui-automation/shared/runtime-snapshot.ts#L533
Replace the four-level nested ternary (which includes an IIFE for the `gone` branch) with an `if/else` chain or a helper function — the skill explicitly prohibits nested ternaries and requires preferring switch/if-else chains for multiple conditions.
[5HS-QCL] Nested ternary operators (with IIFE) computing `matched` (additional location): src/mcp/tools/ui-automation/shared/runtime-snapshot.ts#L725
Replace the four-level nested ternary (which includes an IIFE for the `gone` branch) with an `if/else` chain or a helper function — the skill explicitly prohibits nested ternaries and requires preferring switch/if-else chains for multiple conditions.
Runtime element helpers duplicated verbatim from structured-output-envelope.ts: src/utils/renderers/domain-result-text.ts#L1169
The ten constants and helper functions added here are identical copies of private symbols already in `src/utils/structured-output-envelope.ts`; extract them to a shared module and import from both files instead.