mcp-accessibility-scanner 3.0.1 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +265 -12
  2. package/index.d.ts +1 -1
  3. package/lib/browserContextFactory.js +1161 -94
  4. package/lib/browserContextFactory.js.map +1 -1
  5. package/lib/browserServerBackend.js +199 -22
  6. package/lib/browserServerBackend.js.map +1 -1
  7. package/lib/browserSessions.js +172 -0
  8. package/lib/browserSessions.js.map +1 -0
  9. package/lib/config.js +48 -7
  10. package/lib/config.js.map +1 -1
  11. package/lib/context.js +321 -71
  12. package/lib/context.js.map +1 -1
  13. package/lib/extension/cdpRelay.js +5 -0
  14. package/lib/extension/cdpRelay.js.map +1 -1
  15. package/lib/extension/extensionContextFactory.js +12 -1
  16. package/lib/extension/extensionContextFactory.js.map +1 -1
  17. package/lib/index.js +5 -1
  18. package/lib/index.js.map +1 -1
  19. package/lib/mcp/http.js +194 -44
  20. package/lib/mcp/http.js.map +1 -1
  21. package/lib/mcp/inProcessTransport.js.map +1 -1
  22. package/lib/mcp/mdb.js +7 -9
  23. package/lib/mcp/mdb.js.map +1 -1
  24. package/lib/mcp/proxyBackend.js +76 -18
  25. package/lib/mcp/proxyBackend.js.map +1 -1
  26. package/lib/mcp/server.js +70 -41
  27. package/lib/mcp/server.js.map +1 -1
  28. package/lib/mcp/sharedClientSlot.js +134 -0
  29. package/lib/mcp/sharedClientSlot.js.map +1 -0
  30. package/lib/mcp/tool.js +3 -0
  31. package/lib/mcp/tool.js.map +1 -1
  32. package/lib/networkPolicy.js +73 -0
  33. package/lib/networkPolicy.js.map +1 -0
  34. package/lib/program.js +91 -12
  35. package/lib/program.js.map +1 -1
  36. package/lib/response.js +16 -3
  37. package/lib/response.js.map +1 -1
  38. package/lib/sessionLog.js +36 -6
  39. package/lib/sessionLog.js.map +1 -1
  40. package/lib/tab.js +149 -18
  41. package/lib/tab.js.map +1 -1
  42. package/lib/tools/auditKeyboard.js +204 -4
  43. package/lib/tools/auditKeyboard.js.map +1 -1
  44. package/lib/tools/auditScreenReader.js +823 -0
  45. package/lib/tools/auditScreenReader.js.map +1 -0
  46. package/lib/tools/auditSite.js +268 -90
  47. package/lib/tools/auditSite.js.map +1 -1
  48. package/lib/tools/axe.js +479 -21
  49. package/lib/tools/axe.js.map +1 -1
  50. package/lib/tools/dialogs.js +18 -4
  51. package/lib/tools/dialogs.js.map +1 -1
  52. package/lib/tools/evaluate.js +34 -5
  53. package/lib/tools/evaluate.js.map +1 -1
  54. package/lib/tools/network.js +136 -8
  55. package/lib/tools/network.js.map +1 -1
  56. package/lib/tools/pdf.js +5 -2
  57. package/lib/tools/pdf.js.map +1 -1
  58. package/lib/tools/scanPageMatrix.js +135 -47
  59. package/lib/tools/scanPageMatrix.js.map +1 -1
  60. package/lib/tools/screenshot.js +8 -4
  61. package/lib/tools/screenshot.js.map +1 -1
  62. package/lib/tools/session.js +53 -0
  63. package/lib/tools/session.js.map +1 -0
  64. package/lib/tools/snapshot.js +266 -8
  65. package/lib/tools/snapshot.js.map +1 -1
  66. package/lib/tools/tool.js.map +1 -1
  67. package/lib/tools/utils.js +62 -6
  68. package/lib/tools/utils.js.map +1 -1
  69. package/lib/tools.js +11 -2
  70. package/lib/tools.js.map +1 -1
  71. package/lib/utils/dataUrl.js +58 -35
  72. package/lib/utils/dataUrl.js.map +1 -1
  73. package/lib/utils/fileUtils.js +35 -0
  74. package/lib/utils/fileUtils.js.map +1 -1
  75. package/lib/utils/guid.js +8 -0
  76. package/lib/utils/guid.js.map +1 -1
  77. package/lib/utils/jsSource.js +187 -0
  78. package/lib/utils/jsSource.js.map +1 -0
  79. package/lib/vscode/browserContextFactory.js +87 -0
  80. package/lib/vscode/browserContextFactory.js.map +1 -0
  81. package/lib/vscode/host.js +189 -33
  82. package/lib/vscode/host.js.map +1 -1
  83. package/lib/vscode/main.js +3 -35
  84. package/lib/vscode/main.js.map +1 -1
  85. package/package.json +13 -9
package/lib/tab.js CHANGED
@@ -18,9 +18,12 @@ import { callOnPageNoTrace, waitForCompletion } from './tools/utils.js';
18
18
  import { logUnhandledError } from './utils/log.js';
19
19
  import { ManualPromise } from './mcp/manualPromise.js';
20
20
  import { truncateDataUrls } from './utils/dataUrl.js';
21
+ import { safeIsoTimestampForFileName, truncateToUtf8Bytes } from './utils/fileUtils.js';
21
22
  export const TabEvents = {
22
23
  modalState: 'modalState'
23
24
  };
25
+ class StaleAriaSnapshotError extends Error {
26
+ }
24
27
  export class Tab extends EventEmitter {
25
28
  context;
26
29
  page;
@@ -33,34 +36,72 @@ export class Tab extends EventEmitter {
33
36
  _modalStates = [];
34
37
  _downloads = [];
35
38
  _defaultTimeout;
39
+ // The aria snapshot last handed to the caller; the refs in it are the refs the
40
+ // next tool call will name. Cleared whenever the page it described is gone.
41
+ _lastAriaSnapshot;
42
+ _ariaSnapshotGeneration = 0;
43
+ _pageGeneration = 0;
44
+ _pageListeners = [];
36
45
  constructor(context, page, onPageClose) {
37
46
  super();
38
47
  this.context = context;
39
48
  this.page = page;
40
49
  this._onPageClose = onPageClose;
41
50
  this._defaultTimeout = context.config.timeouts.defaultTimeout ?? 6000;
42
- page.on('console', event => this._handleConsoleMessage(messageToConsoleMessage(event)));
43
- page.on('pageerror', error => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));
44
- page.on('request', request => this._requests.set(request, null));
45
- page.on('response', response => this._handleResponse(response));
46
- page.on('close', () => this._onClose());
47
- page.on('filechooser', chooser => {
51
+ // Registered through a tracked list so dispose() can take them off again:
52
+ // on a shared (non-isolated CDP) context the page outlives the session,
53
+ // and listeners left behind would pile up with session churn.
54
+ const listen = (event, listener) => {
55
+ page.on(event, listener);
56
+ this._pageListeners.push({ event, listener });
57
+ };
58
+ // Every document swap invalidates the cached snapshot, whoever caused it:
59
+ // goBack(), page.reload() from scan_page_matrix, a meta refresh, or the page
60
+ // assigning location itself. Tab.navigate() is only one of those routes, and
61
+ // a ref resolved against the page the user has left would target the wrong
62
+ // document.
63
+ listen('framenavigated', (frame) => {
64
+ if (!frame.parentFrame()) {
65
+ ++this._pageGeneration;
66
+ this._invalidateAriaSnapshot();
67
+ }
68
+ });
69
+ listen('console', event => this._handleConsoleMessage(messageToConsoleMessage(event)));
70
+ listen('pageerror', error => this._handleConsoleMessage(pageErrorToConsoleMessage(error)));
71
+ listen('request', request => this._requests.set(request, null));
72
+ listen('response', response => this._handleResponse(response));
73
+ listen('close', () => this._onClose());
74
+ listen('filechooser', chooser => {
48
75
  this.setModalState({
49
76
  type: 'fileChooser',
50
77
  description: 'File chooser',
51
78
  fileChooser: chooser,
52
79
  });
53
80
  });
54
- page.on('dialog', dialog => this._dialogShown(dialog));
55
- page.on('download', download => {
56
- void this._downloadStarted(download);
81
+ listen('dialog', dialog => this._dialogShown(dialog));
82
+ // Fires on Playwright >= 1.63 when a dialog is closed out of band (e.g.
83
+ // dismissed manually in headed mode or via a CDP side-channel); inert on
84
+ // the pinned 1.62.0, which never emits it. Until then a stale dialog
85
+ // modal state blocks every snapshot-bearing tool until the user re-issues
86
+ // browser_handle_dialog, whose already-closed fallback (tools/dialogs.ts)
87
+ // recovers the session on the pinned version.
88
+ listen('dialogclosed', dialog => this._dialogClosed(dialog));
89
+ listen('download', download => {
90
+ // Tracked on the Context: the save outlives this tool call (and can
91
+ // outlive the tab), and context disposal must wait for it instead of
92
+ // closing the browser mid-stream. The context also owns the promise's
93
+ // rejection handling.
94
+ this.context.trackPendingDownload(this._downloadStarted(download));
57
95
  });
58
96
  page.setDefaultNavigationTimeout(context.config.timeouts.navigationTimeout ?? 30000);
59
97
  page.setDefaultTimeout(this._defaultTimeout);
60
- _pageTabMap.set(page, this);
61
98
  }
62
- static forPage(page) {
63
- return _pageTabMap.get(page);
99
+ // Detaches this wrapper from its page without closing the page: the page
100
+ // can belong to a shared context that outlives the session.
101
+ dispose() {
102
+ for (const { event, listener } of this._pageListeners)
103
+ this.page.off(event, listener);
104
+ this._pageListeners = [];
64
105
  }
65
106
  modalStates() {
66
107
  return this._modalStates;
@@ -82,11 +123,41 @@ export class Tab extends EventEmitter {
82
123
  dialog,
83
124
  });
84
125
  }
126
+ _dialogClosed(dialog) {
127
+ const state = this._modalStates.find(state => state.type === 'dialog' && state.dialog === dialog);
128
+ if (state)
129
+ this.clearModalState(state);
130
+ }
85
131
  async _downloadStarted(download) {
132
+ // The suggested name alone is not collision-safe: sessions share one
133
+ // output directory, and two downloads suggesting "report.pdf" would
134
+ // overwrite each other. The same {timestamp}-{token} fragment the other
135
+ // default artifact names carry goes in before the extension, keeping the
136
+ // suggested name as the recognizable part; responses print the suggested
137
+ // name next to the saved path, so the file stays attributable.
138
+ const suggested = download.suggestedFilename() || 'download';
139
+ const separator = suggested.lastIndexOf('.');
140
+ let base = separator > 0 ? suggested.slice(0, separator) : suggested;
141
+ let extension = separator > 0 ? suggested.slice(separator) : '';
142
+ const uniqueSuffix = `-${safeIsoTimestampForFileName()}`;
143
+ // Filesystems cap a single name component at 255 bytes, and a long but
144
+ // valid Content-Disposition name plus the ~35-byte suffix used to fail
145
+ // saveAs() with ENAMETOOLONG. The recognizable part is truncated by BYTE
146
+ // length (UTF-8, whole code points) so extension and uniqueness suffix
147
+ // survive intact; a pathological "extension" too long to leave any base
148
+ // is just part of one long name and is truncated with it.
149
+ const maxNameBytes = 255;
150
+ let baseBudget = maxNameBytes - Buffer.byteLength(uniqueSuffix, 'utf8') - Buffer.byteLength(extension, 'utf8');
151
+ if (baseBudget < 1) {
152
+ base = suggested;
153
+ extension = '';
154
+ baseBudget = maxNameBytes - Buffer.byteLength(uniqueSuffix, 'utf8');
155
+ }
156
+ const uniqueName = `${truncateToUtf8Bytes(base, baseBudget)}${uniqueSuffix}${extension}`;
86
157
  const entry = {
87
158
  download,
88
159
  finished: false,
89
- outputFile: await this.context.outputFile(download.suggestedFilename())
160
+ outputFile: await this.context.outputFile(uniqueName)
90
161
  };
91
162
  this._downloads.push(entry);
92
163
  await download.saveAs(entry.outputFile);
@@ -97,6 +168,12 @@ export class Tab extends EventEmitter {
97
168
  this._recentConsoleMessages.length = 0;
98
169
  this._requests.clear();
99
170
  this._mainDocumentStatus = undefined;
171
+ ++this._pageGeneration;
172
+ this._invalidateAriaSnapshot();
173
+ }
174
+ _invalidateAriaSnapshot() {
175
+ ++this._ariaSnapshotGeneration;
176
+ this._lastAriaSnapshot = undefined;
100
177
  }
101
178
  _handleConsoleMessage(message) {
102
179
  this._consoleMessages.push(message);
@@ -172,12 +249,28 @@ export class Tab extends EventEmitter {
172
249
  requests() {
173
250
  return this._requests;
174
251
  }
252
+ // Playwright resolves `Request.allHeaders()` and `Response.body()` with no
253
+ // timeout of their own, so a still-streaming response would hang a tool call
254
+ // until the page closed. Callers outside this class need the same bound the
255
+ // page-state reads above use.
256
+ async withPageStateTimeout(promise, description) {
257
+ return this._withPageStateTimeout(promise, description);
258
+ }
175
259
  async captureSnapshot() {
176
260
  let tabSnapshot;
261
+ const capture = { valid: true };
262
+ const snapshotGeneration = this._ariaSnapshotGeneration;
177
263
  const modalStates = await this._raceAgainstModalStates(async () => {
178
264
  const [snapshot, title] = await Promise.all([
179
- this._withPageStateTimeout(this.page.ariaSnapshot({ mode: 'ai' }), 'capturing page accessibility snapshot').catch(error => {
180
- logUnhandledError(error);
265
+ this._withPageStateTimeout(this._captureAriaSnapshot(capture), 'capturing page accessibility snapshot').catch(error => {
266
+ // Nothing describes the page any more, and the refs of an older
267
+ // snapshot must not be trusted against it.
268
+ if (!(error instanceof StaleAriaSnapshotError)) {
269
+ capture.valid = false;
270
+ logUnhandledError(error);
271
+ if (snapshotGeneration === this._ariaSnapshotGeneration)
272
+ this._invalidateAriaSnapshot();
273
+ }
181
274
  return `# Page snapshot unavailable: ${formatPageStateError(error)}`;
182
275
  }),
183
276
  this._withPageStateTimeout(this.page.title(), 'reading page title').catch(error => {
@@ -201,6 +294,10 @@ export class Tab extends EventEmitter {
201
294
  tabSnapshot.consoleMessages = this._recentConsoleMessages;
202
295
  this._recentConsoleMessages = [];
203
296
  }
297
+ if (!tabSnapshot) {
298
+ capture.valid = false;
299
+ this._invalidateAriaSnapshot();
300
+ }
204
301
  return tabSnapshot ?? {
205
302
  url: this.page.url(),
206
303
  title: '',
@@ -255,13 +352,48 @@ export class Tab extends EventEmitter {
255
352
  return (await this.refLocators([params]))[0];
256
353
  }
257
354
  async refLocators(params) {
258
- const snapshot = await this.page.ariaSnapshot({ mode: 'ai' });
355
+ // The refs a caller passes come from the snapshot the last tool call
356
+ // returned, which is the one cached here, so the common case needs no fresh
357
+ // capture. Playwright keeps a ref bound to the element it was issued for,
358
+ // but that element can change its accessible role or name while staying
359
+ // connected. Re-checking only the referenced nodes is still cheaper than a
360
+ // full-page snapshot and prevents an old ref from targeting repurposed UI.
361
+ const cached = this._lastAriaSnapshot;
362
+ const snapshot = cached && await this._refsMatchSnapshot(params, cached)
363
+ ? cached
364
+ : await this._captureAriaSnapshot();
259
365
  return params.map(param => {
260
366
  if (!snapshot.includes(`[ref=${param.ref}]`))
261
367
  throw new Error(`Ref ${param.ref} not found in the current page snapshot. Try capturing new snapshot.`);
262
368
  return this.page.locator(`aria-ref=${param.ref}`).describe(param.element);
263
369
  });
264
370
  }
371
+ async _refsMatchSnapshot(params, snapshot) {
372
+ const pageGeneration = this._pageGeneration;
373
+ const lines = snapshot.split('\n');
374
+ const timeout = Math.min(this._pageStateTimeoutMs(), 1000);
375
+ const matches = await Promise.all(params.map(async (param) => {
376
+ const cached = lines.find(line => line.includes(`[ref=${param.ref}]`));
377
+ if (!cached)
378
+ return false;
379
+ const current = await this.page.locator(`aria-ref=${param.ref}`)
380
+ .ariaSnapshot({ mode: 'ai', depth: 1, timeout })
381
+ .catch(() => '');
382
+ // Refs are assigned from the full role and name before long names are
383
+ // omitted from rendering, so a semantic change still changes this line.
384
+ return current.split('\n', 1)[0]?.trim() === cached.trim();
385
+ }));
386
+ return pageGeneration === this._pageGeneration && matches.every(Boolean);
387
+ }
388
+ async _captureAriaSnapshot(capture = { valid: true }) {
389
+ const pageGeneration = this._pageGeneration;
390
+ const snapshot = await this.page.ariaSnapshot({ mode: 'ai' });
391
+ if (!capture.valid || pageGeneration !== this._pageGeneration)
392
+ throw new StaleAriaSnapshotError('Page changed while capturing accessibility snapshot.');
393
+ ++this._ariaSnapshotGeneration;
394
+ this._lastAriaSnapshot = snapshot;
395
+ return snapshot;
396
+ }
265
397
  async waitForTimeout(time) {
266
398
  if (this._javaScriptBlocked()) {
267
399
  await new Promise(f => setTimeout(f, time));
@@ -301,10 +433,9 @@ export function renderModalStates(context, modalStates) {
301
433
  if (modalStates.length === 0)
302
434
  result.push('- There is no modal state present');
303
435
  for (const state of modalStates) {
304
- const tool = context.tools.filter(tool => 'clearsModalState' in tool).find(tool => tool.clearsModalState === state.type);
436
+ const tool = context.tools.find(tool => tool.clearsModalState === state.type);
305
437
  result.push(`- [${truncateDataUrls(state.description)}]: can be handled by the "${tool?.schema.name}" tool`);
306
438
  }
307
439
  return result;
308
440
  }
309
- const _pageTabMap = new WeakMap();
310
441
  //# sourceMappingURL=tab.js.map
package/lib/tab.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"tab.js","sourceRoot":"","sources":["../src/tab.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tab.js","sourceRoot":"","sources":["../src/tab.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import { z } from 'zod';
3
3
  import { defineTabTool } from './tool.js';
4
- import { sanitizeForFilePath } from '../utils/fileUtils.js';
4
+ import { safeIsoTimestampForFileName, sanitizeForFilePath } from '../utils/fileUtils.js';
5
5
  function buildFingerprint(point) {
6
6
  return [
7
7
  point.role ?? '',
@@ -29,6 +29,60 @@ function isLikelySkipLink(point) {
29
29
  return false;
30
30
  }
31
31
  }
32
+ // WCAG 2.2 SC 2.5.8 Target Size (Minimum), in CSS pixels.
33
+ const MIN_TARGET_SIZE_PX = 24;
34
+ function rectCenter(rect) {
35
+ return { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
36
+ }
37
+ function isUndersizedTarget(rect) {
38
+ return rect.width < MIN_TARGET_SIZE_PX || rect.height < MIN_TARGET_SIZE_PX;
39
+ }
40
+ /**
41
+ * SC 2.5.8 spacing exception: an undersized target passes when a 24px-diameter
42
+ * circle centered on its bounding box intersects neither another target's box nor
43
+ * the equivalent circle of another undersized target.
44
+ */
45
+ function meetsSpacingException(rect, neighbors) {
46
+ const center = rectCenter(rect);
47
+ const radius = MIN_TARGET_SIZE_PX / 2;
48
+ return neighbors.every(neighbor => {
49
+ // Every neighbor is "another target", so its box is tested first; an
50
+ // undersized one additionally owns a circle, and both must be cleared.
51
+ const nearestX = Math.min(Math.max(center.x, neighbor.x), neighbor.x + neighbor.width);
52
+ const nearestY = Math.min(Math.max(center.y, neighbor.y), neighbor.y + neighbor.height);
53
+ if (Math.hypot(center.x - nearestX, center.y - nearestY) < radius)
54
+ return false;
55
+ if (!isUndersizedTarget(neighbor))
56
+ return true;
57
+ const neighborCenter = rectCenter(neighbor);
58
+ return Math.hypot(center.x - neighborCenter.x, center.y - neighborCenter.y) >= MIN_TARGET_SIZE_PX;
59
+ });
60
+ }
61
+ export function meetsTargetSizeMinimum(point) {
62
+ const rect = point.boundingBox;
63
+ // Document root / non-interactive focus stops are not pointer targets at all.
64
+ if (!point.isPointerTarget || !rect)
65
+ return true;
66
+ if (!isUndersizedTarget(rect))
67
+ return true;
68
+ // ponytail: only the spacing and inline exceptions are evaluated. The
69
+ // user-agent-control, essential and equivalent-alternative exceptions need
70
+ // author intent that is not observable from the DOM, so undersized targets
71
+ // relying on them are reported and must be triaged by hand. Upgrade path:
72
+ // compare against a default-stylesheet baseline for user-agent control, and
73
+ // accept an allowlist of selectors for essential/equivalent.
74
+ if (point.inlineTarget)
75
+ return true;
76
+ return meetsSpacingException(rect, point.neighborTargets);
77
+ }
78
+ /**
79
+ * SC 2.4.11 Focus Not Obscured (Minimum) is only violated when the focused
80
+ * component is *entirely* hidden, so a partially covered target passes here.
81
+ */
82
+ export function isFocusEntirelyObscured(point) {
83
+ const obstruction = point.obstruction;
84
+ return obstruction !== null && obstruction.sampled > 0 && obstruction.blocked === obstruction.sampled;
85
+ }
32
86
  function didUrlHashChange(urlBefore, urlAfter) {
33
87
  if (!urlBefore || !urlAfter)
34
88
  return false;
@@ -39,9 +93,6 @@ function didUrlHashChange(urlBefore, urlAfter) {
39
93
  return false;
40
94
  }
41
95
  }
42
- function safeIsoTimestampForFileName() {
43
- return sanitizeForFilePath(new Date().toISOString());
44
- }
45
96
  async function maybeCaptureIssueScreenshot(options, callbacks, screenshots, issueName) {
46
97
  if (!options.screenshotOnIssue || !callbacks.captureScreenshot)
47
98
  return;
@@ -91,6 +142,14 @@ export async function runKeyboardFocusAudit(options, callbacks) {
91
142
  await maybeCaptureIssueScreenshot(options, callbacks, screenshots, `focus-jump-${step}`);
92
143
  }
93
144
  }
145
+ if (options.checkTargetSize && !meetsTargetSizeMinimum(stop)) {
146
+ stop.issues.push('target-size-below-minimum');
147
+ await maybeCaptureIssueScreenshot(options, callbacks, screenshots, `target-size-${step}`);
148
+ }
149
+ if (options.checkFocusObscured && isFocusEntirelyObscured(stop)) {
150
+ stop.issues.push('focus-entirely-obscured');
151
+ await maybeCaptureIssueScreenshot(options, callbacks, screenshots, `focus-obscured-${step}`);
152
+ }
94
153
  if (options.checkSkipLink && step <= options.skipLinkMaxTabs && isLikelySkipLink(stop) && skipLinkStep === null) {
95
154
  skipLinkStep = step;
96
155
  if (options.activateSkipLink && !skipLinkActivated) {
@@ -151,6 +210,8 @@ export async function runKeyboardFocusAudit(options, callbacks) {
151
210
  },
152
211
  focusVisibilityIssues: stops.filter(stop => stop.issues.includes('no-visible-focus-indicator')),
153
212
  focusJumpIssues: stops.filter(stop => stop.issues.includes('focus-jump-or-not-visible')),
213
+ targetSizeIssues: stops.filter(stop => stop.issues.includes('target-size-below-minimum')),
214
+ focusObscuredIssues: stops.filter(stop => stop.issues.includes('focus-entirely-obscured')),
154
215
  focusTrap: {
155
216
  detected: focusTrapDetectedAt !== null,
156
217
  step: focusTrapDetectedAt,
@@ -171,6 +232,8 @@ const auditKeyboardSchema = z.object({
171
232
  checkFocusTrap: z.boolean().default(true).describe('Detect likely focus trap/cycle.'),
172
233
  checkFocusVisibility: z.boolean().default(true).describe('Check focus ring visibility heuristic.'),
173
234
  checkFocusJumps: z.boolean().default(true).describe('Detect large scroll jumps and invisible focus.'),
235
+ checkTargetSize: z.boolean().default(true).describe('Check target size against WCAG 2.2 SC 2.5.8 (24x24 CSS px, spacing/inline exceptions applied).'),
236
+ checkFocusObscured: z.boolean().default(true).describe('Check that the focused element is not entirely hidden behind other content (WCAG 2.2 SC 2.4.11).'),
174
237
  jumpScrollThresholdPx: z.number().int().min(1).default(800).describe('Scroll delta threshold for jump detection.'),
175
238
  screenshotOnIssue: z.boolean().default(false).describe('Capture screenshots for detected issues.'),
176
239
  maxIssueScreenshots: z.number().int().min(1).max(20).default(3).describe('Maximum screenshots saved when screenshotOnIssue=true.'),
@@ -202,6 +265,10 @@ const auditKeyboard = defineTabTool({
202
265
  boundingBox: null,
203
266
  inViewport: false,
204
267
  hasVisibleIndicator: false,
268
+ isPointerTarget: false,
269
+ inlineTarget: false,
270
+ neighborTargets: [],
271
+ obstruction: null,
205
272
  scrollX,
206
273
  scrollY,
207
274
  };
@@ -225,6 +292,125 @@ const auditKeyboard = defineTabTool({
225
292
  && rect.right >= 0
226
293
  && rect.top <= window.innerHeight
227
294
  && rect.left <= window.innerWidth;
295
+ // Kept in sync with MIN_TARGET_SIZE_PX; page.evaluate cannot close over it.
296
+ const minTargetSize = 24;
297
+ // ponytail: target size comes from the layout box, so a target whose visible
298
+ // area is cut down by an overflow or clip-path ancestor is under-reported.
299
+ // Intersecting with clipping ancestors was measured against ordinary markup and
300
+ // cost four false positives (carousel slides parked off-track, rows of a plain
301
+ // overflow: auto list) per true positive, and clip-path shapes are not derivable
302
+ // from a rect at all. Upgrade path: clip only against ancestors that cannot be
303
+ // scrolled or animated to reveal the rest of the target.
304
+ const targetSelector = 'a[href], button, input:not([type="hidden"]), select, textarea, summary, [contenteditable]:not([contenteditable="false"]), [tabindex]:not([tabindex^="-"]), [role="button"], [role="link"], [role="checkbox"], [role="radio"], [role="switch"], [role="tab"], [role="menuitem"], [role="option"]';
305
+ // Shared by the focused element and its spacing neighbors so a disabled or
306
+ // unrendered control is never counted as a pointer target on either side.
307
+ const isPointerTargetElement = (element, box) => box.width > 0
308
+ && box.height > 0
309
+ && element.matches(targetSelector)
310
+ && !element.matches(':disabled');
311
+ const isPointerTarget = isPointerTargetElement(current, rect);
312
+ // "Target is in a sentence": approximated as an inline-level target that sits
313
+ // directly next to running text.
314
+ // ponytail: ceiling is that targets merely constrained by the line-height of
315
+ // nearby non-target text are missed. Upgrade path: compare the target height
316
+ // against the parent's computed line-height.
317
+ // The target may sit inside inline formatting (<strong>, <span>, ...), so walk
318
+ // up through inline-level wrappers to the containing block before concluding
319
+ // there is no running text beside it.
320
+ let hasSentenceText = false;
321
+ for (let scope = current; scope.parentElement && !hasSentenceText; scope = scope.parentElement) {
322
+ hasSentenceText = Array.from(scope.parentElement.childNodes).some(node => (node.nodeType === Node.TEXT_NODE && (node.textContent ?? '').trim().length > 0));
323
+ if (!window.getComputedStyle(scope.parentElement).display.startsWith('inline'))
324
+ break;
325
+ }
326
+ // Any inline-level display (inline, inline-block, inline-flex, ...) can sit in a
327
+ // sentence; SC 2.5.8's exception is about the sentence, not the display keyword.
328
+ const inlineTarget = isPointerTarget && style.display.startsWith('inline') && hasSentenceText;
329
+ const neighborTargets = [];
330
+ if (isPointerTarget && (rect.width < minTargetSize || rect.height < minTargetSize)) {
331
+ for (const candidate of document.querySelectorAll(targetSelector)) {
332
+ if (candidate === current)
333
+ continue;
334
+ const other = candidate.getBoundingClientRect();
335
+ if (!isPointerTargetElement(candidate, other))
336
+ continue;
337
+ // Only targets close enough for either 24px circle to reach can matter;
338
+ // the margin overshoots deliberately so the spacing test never misses one.
339
+ const outOfRange = other.right < rect.left - 2 * minTargetSize
340
+ || other.left > rect.right + 2 * minTargetSize
341
+ || other.bottom < rect.top - 2 * minTargetSize
342
+ || other.top > rect.bottom + 2 * minTargetSize;
343
+ if (outOfRange)
344
+ continue;
345
+ neighborTargets.push({ x: other.x, y: other.y, width: other.width, height: other.height });
346
+ // ponytail: payload cap. A cluster denser than 32 neighbors within 48px
347
+ // would under-report rather than over-report; raise the cap if that appears.
348
+ if (neighborTargets.length >= 32)
349
+ break;
350
+ }
351
+ }
352
+ let obstruction = null;
353
+ const clipLeft = Math.max(rect.left, 0);
354
+ const clipTop = Math.max(rect.top, 0);
355
+ const clipRight = Math.min(rect.right, window.innerWidth - 1);
356
+ const clipBottom = Math.min(rect.bottom, window.innerHeight - 1);
357
+ // SC 2.4.11 applies to anything that receives focus, so this is deliberately not
358
+ // gated on isPointerTarget: contenteditable, iframes and tabindex-only widgets
359
+ // are sampled too.
360
+ if (rect.width > 0 && rect.height > 0 && clipRight >= clipLeft && clipBottom >= clipTop) {
361
+ const inset = (low, high, value) => Math.min(Math.max(value, low), high);
362
+ const samples = [
363
+ [inset(clipLeft, clipRight, clipLeft + 1), inset(clipTop, clipBottom, clipTop + 1)],
364
+ [inset(clipLeft, clipRight, clipRight - 1), inset(clipTop, clipBottom, clipTop + 1)],
365
+ [inset(clipLeft, clipRight, clipLeft + 1), inset(clipTop, clipBottom, clipBottom - 1)],
366
+ [inset(clipLeft, clipRight, clipRight - 1), inset(clipTop, clipBottom, clipBottom - 1)],
367
+ [(clipLeft + clipRight) / 2, (clipTop + clipBottom) / 2],
368
+ ];
369
+ const labels = current instanceof HTMLInputElement || current instanceof HTMLTextAreaElement || current instanceof HTMLSelectElement
370
+ ? Array.from(current.labels ?? [])
371
+ : [];
372
+ // SC 2.4.11 is about visual coverage, not hit-test order, so a hit only counts
373
+ // when it (or a wrapper of it that is not also around the target) actually
374
+ // paints: visible, non-zero opacity and a non-transparent background.
375
+ // ponytail: the remaining ceiling is that a covering layer with
376
+ // `pointer-events: none` is never returned by hit testing, so it is missed
377
+ // (under-report, never a false alarm). Upgrade path: intersect the focused box
378
+ // against the boxes of positioned/stacking-context layers painted above it.
379
+ const paintsOver = (element) => {
380
+ let paints = false;
381
+ // Painted evidence never short-circuits the walk: an ancestor that renders
382
+ // nothing (opacity: 0, visibility: hidden) hides its painted children too.
383
+ for (let node = element; node && !node.contains(current); node = node.parentElement) {
384
+ const nodeStyle = window.getComputedStyle(node);
385
+ if (nodeStyle.visibility === 'hidden' || Number.parseFloat(nodeStyle.opacity || '1') === 0)
386
+ return false;
387
+ if (paints)
388
+ continue;
389
+ const alpha = /^rgba\(.*,\s*([\d.]+)\)$/.exec(nodeStyle.backgroundColor);
390
+ paints = nodeStyle.backgroundImage !== 'none'
391
+ || (alpha ? Number.parseFloat(alpha[1]) > 0 : nodeStyle.backgroundColor !== 'transparent');
392
+ }
393
+ return paints;
394
+ };
395
+ let blocked = 0;
396
+ let blockedBy = null;
397
+ for (const [x, y] of samples) {
398
+ const hit = document.elementFromPoint(x, y);
399
+ // Descendants paint the target itself; ancestors and associated labels
400
+ // wrap it (the common visually-hidden custom control pattern).
401
+ const covers = hit !== null
402
+ && !current.contains(hit)
403
+ && !hit.contains(current)
404
+ && !labels.some(label => label.contains(hit))
405
+ && paintsOver(hit);
406
+ if (!covers)
407
+ continue;
408
+ blocked++;
409
+ const className = typeof hit.className === 'string' ? hit.className.trim().split(/\s+/)[0] : '';
410
+ blockedBy = blockedBy ?? `${hit.tagName.toLowerCase()}${hit.id ? `#${hit.id}` : ''}${className ? `.${className}` : ''}`;
411
+ }
412
+ obstruction = { sampled: samples.length, blocked, blockedBy };
413
+ }
228
414
  return {
229
415
  role,
230
416
  name: name ? name.slice(0, 200) : null,
@@ -240,6 +426,10 @@ const auditKeyboard = defineTabTool({
240
426
  } : null,
241
427
  inViewport,
242
428
  hasVisibleIndicator: hasOutline || hasBoxShadow,
429
+ isPointerTarget,
430
+ inlineTarget,
431
+ neighborTargets,
432
+ obstruction,
243
433
  scrollX,
244
434
  scrollY,
245
435
  };
@@ -323,6 +513,8 @@ const auditKeyboard = defineTabTool({
323
513
  skipLinkActivated: result.skipLink.activated,
324
514
  focusVisibilityIssueCount: result.focusVisibilityIssues.length,
325
515
  focusJumpIssueCount: result.focusJumpIssues.length,
516
+ targetSizeIssueCount: result.targetSizeIssues.length,
517
+ focusObscuredIssueCount: result.focusObscuredIssues.length,
326
518
  focusTrapDetected: result.focusTrap.detected,
327
519
  focusTrapStep: result.focusTrap.step,
328
520
  screenshotCount: result.screenshots.length,
@@ -332,6 +524,8 @@ const auditKeyboard = defineTabTool({
332
524
  });
333
525
  const focusVisibilityPreview = result.focusVisibilityIssues.slice(0, 10).map(stop => (`- Step ${stop.step} (${stop.key}): ${stop.role ?? 'unknown-role'} ${stop.name ?? ''}`.trim()));
334
526
  const focusJumpPreview = result.focusJumpIssues.slice(0, 10).map(stop => (`- Step ${stop.step}: deltaY=${stop.scrollDeltaY}, inViewport=${stop.inViewport}`));
527
+ const targetSizePreview = result.targetSizeIssues.slice(0, 10).map(stop => (`- Step ${stop.step}: ${stop.role ?? 'unknown-role'} ${stop.name ?? ''} is ${Math.round(stop.boundingBox?.width ?? 0)}x${Math.round(stop.boundingBox?.height ?? 0)} CSS px`.replace(/\s+/g, ' ')));
528
+ const focusObscuredPreview = result.focusObscuredIssues.slice(0, 10).map(stop => (`- Step ${stop.step}: ${stop.role ?? 'unknown-role'} ${stop.name ?? ''} hidden behind ${stop.obstruction?.blockedBy ?? 'other content'}`.replace(/\s+/g, ' ')));
335
529
  const skipLinkResult = result.skipLink.found
336
530
  ? `found at step ${result.skipLink.step}${result.skipLink.activated ? ', activated' : ''}`
337
531
  : 'not found';
@@ -345,6 +539,12 @@ const auditKeyboard = defineTabTool({
345
539
  `Focus trap detected: ${result.focusTrap.detected ? `yes (step ${result.focusTrap.step})` : 'no'}`,
346
540
  `Focus jumps: ${result.focusJumpIssues.length}`,
347
541
  ...(focusJumpPreview.length ? focusJumpPreview : ['- None']),
542
+ '',
543
+ `Target size below 24x24 CSS px (WCAG 2.2 SC 2.5.8, spacing and inline exceptions applied): ${result.targetSizeIssues.length}`,
544
+ ...(targetSizePreview.length ? targetSizePreview : ['- None']),
545
+ '',
546
+ `Focus entirely obscured (WCAG 2.2 SC 2.4.11): ${result.focusObscuredIssues.length}`,
547
+ ...(focusObscuredPreview.length ? focusObscuredPreview : ['- None']),
348
548
  ...(result.screenshots.length ? ['', 'Issue screenshots:', ...result.screenshots.map(path => `- ${path}`)] : []),
349
549
  '',
350
550
  `JSON report: ${reportPath}`,