skeptic-cli 0.2.1 → 1.0.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.
- package/AGENTS.md +20 -53
- package/LICENSE +24 -0
- package/LICENSES.md +92 -3
- package/README.md +25 -49
- package/agent-skills/skeptic/SKILL.md +150 -38
- package/dist/adb-DUGGW3FV.mjs +2 -0
- package/dist/adb-driver-TBOCCKEO.mjs +3 -0
- package/dist/adb-session-AVVXL3QQ.mjs +2 -0
- package/dist/add-G7JFXU4S.mjs +67 -0
- package/dist/audit-ID2BSVYC.mjs +7 -0
- package/dist/auto-spawn-4TO4DBO6.mjs +2 -0
- package/dist/browser-verbs-U54BZACP.mjs +21 -0
- package/dist/browsers-install-F2ZWEBOX.mjs +3 -0
- package/dist/chokidar-KB6GLGX4.mjs +7 -0
- package/dist/chunk-2N64R5DC.mjs +457 -0
- package/dist/chunk-2VSGDT7T.mjs +7 -0
- package/dist/chunk-2YKSIUIN.mjs +3 -0
- package/dist/chunk-2ZORFJJP.mjs +11 -0
- package/dist/chunk-42J77CYA.mjs +3 -0
- package/dist/chunk-6TLKI7UN.mjs +4 -0
- package/dist/chunk-6U6H22OR.mjs +3 -0
- package/dist/chunk-7BFRKEFV.mjs +160 -0
- package/dist/chunk-7ZUWKIDM.mjs +3 -0
- package/dist/chunk-AH75LR2T.mjs +3 -0
- package/dist/chunk-B26AZRXU.mjs +41 -0
- package/dist/chunk-BIGNULF6.mjs +12 -0
- package/dist/chunk-COVGJJ47.mjs +3 -0
- package/dist/chunk-CWNYWHJ2.mjs +143 -0
- package/dist/chunk-EU3OXJX4.mjs +3 -0
- package/dist/chunk-EYVJTUBL.mjs +3 -0
- package/dist/chunk-G22LGRZ4.mjs +4 -0
- package/dist/chunk-I4JX25Y5.mjs +13 -0
- package/dist/chunk-IXBYLSGB.mjs +5 -0
- package/dist/chunk-IYLF56WL.mjs +3 -0
- package/dist/chunk-K65JNLTT.mjs +3 -0
- package/dist/chunk-LPJF33QP.mjs +3 -0
- package/dist/chunk-MHNEFL35.mjs +3 -0
- package/dist/chunk-N3533BCE.mjs +3 -0
- package/dist/chunk-NXTEMSUR.mjs +4 -0
- package/dist/chunk-OHVNABCL.mjs +10 -0
- package/dist/chunk-QICYK6XT.mjs +10 -0
- package/dist/chunk-RU7M6UGM.mjs +5 -0
- package/dist/chunk-S3M2RTHJ.mjs +7 -0
- package/dist/chunk-U3KRIAEU.mjs +3 -0
- package/dist/chunk-WBPZGXOC.mjs +8 -0
- package/dist/chunk-YB25SMQ2.mjs +141 -0
- package/dist/chunk-ZN6MI2TU.mjs +4 -0
- package/dist/client-UR65IKYX.mjs +2 -0
- package/dist/comment-F734YE5S.mjs +6 -0
- package/dist/cookies-X7W5U3VE.mjs +3 -0
- package/dist/daemon-M2J3L6JW.mjs +7 -0
- package/dist/device-fixture-MJSDIP75.mjs +2 -0
- package/dist/devices-NG4P5UPS.mjs +4 -0
- package/dist/devtools-N5AYAR54.mjs +12 -0
- package/dist/doctor-WRKNAK3W.mjs +4 -0
- package/dist/extractor-Y477MBN6.mjs +2 -0
- package/dist/html-reporter-7QHIRHEY.mjs +2 -0
- package/dist/index.d.ts +87 -120
- package/dist/index.mjs +26 -1741
- package/dist/init-4PXSHPNW.mjs +15 -0
- package/dist/ink-reporter-4EN7CRMK.mjs +3 -0
- package/dist/inspect-3XFCCSUL.mjs +19 -0
- package/dist/ios-tools-WK66CQ7Q.mjs +2 -0
- package/dist/json-reporter-SXWPAXRY.mjs +2 -0
- package/dist/junit-reporter-5AT3OFWV.mjs +12 -0
- package/dist/mail-GTOZFXJ5.mjs +14 -0
- package/dist/observe-MHEV7OVP.mjs +3 -0
- package/dist/render-MHOBDOSP.mjs +383 -0
- package/dist/run-GW3X5ANC.mjs +2 -0
- package/dist/scaffold-6ZF6K6Y5.mjs +38 -0
- package/dist/screenshot-GUJSIRQB.mjs +2 -0
- package/dist/session-daemon-cmd-23UUK6TD.mjs +4 -0
- package/dist/simctl-driver-PNUN7W7G.mjs +5 -0
- package/dist/skeptic.mjs +3 -1754
- package/dist/slack-reporter-EEFO66V6.mjs +8 -0
- package/dist/watch-A7ZLUYR2.mjs +3 -0
- package/dist/webhook-reporter-BXJGZS2I.mjs +3 -0
- package/dist/worker.mjs +3 -724
- package/package.json +13 -11
package/AGENTS.md
CHANGED
|
@@ -27,8 +27,8 @@ spec.
|
|
|
27
27
|
|
|
28
28
|
The npm package installs a managed `skeptic` skill for Claude Code, Codex,
|
|
29
29
|
Cursor, and OpenCode into user-level skill directories when `npm install` runs.
|
|
30
|
-
Use that skill when an agent needs browser QA, spec authoring, or
|
|
31
|
-
|
|
30
|
+
Use that skill when an agent needs browser QA, spec authoring, or interactive
|
|
31
|
+
browser-session driving.
|
|
32
32
|
|
|
33
33
|
Manual install commands:
|
|
34
34
|
|
|
@@ -78,7 +78,6 @@ Rules for generated or hand-written specs:
|
|
|
78
78
|
| `screenshot(name, opts?)` | PNG capture with optional ref annotations |
|
|
79
79
|
| `settle()` | Best-effort network-idle settle |
|
|
80
80
|
| `observability` | Performance, network, console, and accessibility assertions |
|
|
81
|
-
| `ai` | Vision-backed assertions, defect checks, and text extraction |
|
|
82
81
|
| `ctx` | Per-test execution context |
|
|
83
82
|
|
|
84
83
|
### Snapshot Helpers
|
|
@@ -185,60 +184,28 @@ Annotated screenshots add numbered labels over interactive refs and return an
|
|
|
185
184
|
annotation map without accessible names, so structured metadata does not repeat
|
|
186
185
|
potentially sensitive page text.
|
|
187
186
|
|
|
188
|
-
##
|
|
187
|
+
## Browser Session Verbs
|
|
189
188
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
ai:
|
|
194
|
-
provider: openai
|
|
195
|
-
model: gpt-4o
|
|
196
|
-
```
|
|
197
|
-
|
|
198
|
-
```ts
|
|
199
|
-
await ai.assert("the success toast is visible");
|
|
200
|
-
await ai.assertNoDefects();
|
|
201
|
-
const total = await ai.extract("invoice total");
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
Use:
|
|
189
|
+
Skeptic is agent-native — you drive a persistent browser from the shell, no MCP
|
|
190
|
+
server and no built-in AI/keys. A daemon holds the session so `@eN` refs persist
|
|
191
|
+
between commands:
|
|
205
192
|
|
|
206
193
|
```bash
|
|
207
|
-
skeptic
|
|
208
|
-
skeptic
|
|
209
|
-
skeptic
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
When Skeptic is exposed through MCP, prefer its browser tools for page QA:
|
|
217
|
-
|
|
218
|
-
| Tool | Use |
|
|
219
|
-
|---|---|
|
|
220
|
-
| `browser_open` | Navigate using project browser/auth/safety config |
|
|
221
|
-
| `browser_snapshot` | Capture refs and snapshot text |
|
|
222
|
-
| `browser_playwright` | Run focused Playwright code with `page`, `context`, `browser`, `ref` |
|
|
223
|
-
| `browser_screenshot` | Capture PNG, annotated PNG, or snapshot-only output |
|
|
224
|
-
| `browser_console_logs` | Read captured console messages |
|
|
225
|
-
| `browser_network_requests` | Read requests and computed issues |
|
|
226
|
-
| `browser_performance_metrics` | Capture Web Vitals, LoAF, resources, and `perf-trace.md` |
|
|
227
|
-
| `browser_accessibility_audit` | Run axe-core plus IBM Equal Access when available |
|
|
228
|
-
| `browser_close` | Close the session |
|
|
229
|
-
|
|
230
|
-
MCP browser tools honor:
|
|
231
|
-
|
|
232
|
-
```yaml
|
|
233
|
-
safety:
|
|
234
|
-
allowedDomains: ["example.com", "*.example.org"]
|
|
235
|
-
actionPolicy: .skeptic/action-policy.json
|
|
236
|
-
confirmActions: ["browser_playwright"]
|
|
237
|
-
maxOutputChars: 120000
|
|
238
|
-
contentBoundaries: true
|
|
194
|
+
skeptic open https://app.example.com # opens a session
|
|
195
|
+
skeptic snapshot -i # mints @e1.. refs + selectorHints
|
|
196
|
+
skeptic click @e3
|
|
197
|
+
skeptic fill @e5 "user@test.com"
|
|
198
|
+
skeptic snapshot -i # re-snapshot after the DOM changed
|
|
199
|
+
skeptic console --errors
|
|
200
|
+
skeptic screenshot --full # returns a file path
|
|
201
|
+
skeptic close
|
|
239
202
|
```
|
|
240
203
|
|
|
241
|
-
`
|
|
204
|
+
Verbs: `open`, `snapshot` (`-i`/`-c`), `click`, `fill`, `type`, `press`, `hover`,
|
|
205
|
+
`check`, `uncheck`, `select`, `get`, `screenshot`, `console`, `wait`, `list`,
|
|
206
|
+
`close`. Add `--json` to any verb; `--session <name>` for isolated sessions;
|
|
207
|
+
`--headless` on `open` for CI. Re-snapshot after navigation — refs invalidate on
|
|
208
|
+
DOM change and acting on a stale ref returns a clear `[ariaRef:stale]` error.
|
|
242
209
|
|
|
243
210
|
## Evidence
|
|
244
211
|
|
|
@@ -284,7 +251,7 @@ output:
|
|
|
284
251
|
|
|
285
252
|
```bash
|
|
286
253
|
skeptic add github-action
|
|
287
|
-
skeptic add github-action --
|
|
254
|
+
skeptic add github-action --dev-command "npm run dev" --dev-url http://localhost:3000
|
|
288
255
|
skeptic comment --results ./skeptic-output/results.json
|
|
289
256
|
```
|
|
290
257
|
|
package/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 iamjr15
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
|
22
|
+
|
|
23
|
+
Third-party components redistributed inside the published bundle are listed,
|
|
24
|
+
with their own license terms and attributions, in LICENSES.md.
|
package/LICENSES.md
CHANGED
|
@@ -1,9 +1,98 @@
|
|
|
1
1
|
# Third-party licenses and attributions
|
|
2
2
|
|
|
3
3
|
skeptic-cli is distributed under the [MIT License](#mit-license-skeptic-cli)
|
|
4
|
-
(see `package.json:license`).
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
(see `package.json:license`). Two kinds of third-party material are covered
|
|
5
|
+
below: (1) npm dependencies that are **inlined into the published bundle**
|
|
6
|
+
(`dist/skeptic.mjs`) at build time, and (2) source code **derived from upstream
|
|
7
|
+
projects**. Their terms and the corresponding NOTICE attributions follow.
|
|
8
|
+
|
|
9
|
+
## Bundled npm dependencies
|
|
10
|
+
|
|
11
|
+
The published `skeptic-cli` bundle inlines several pure-JS dependencies at build
|
|
12
|
+
time — the `noExternal` list in `tsup.config.ts` — instead of resolving them
|
|
13
|
+
from `node_modules` at runtime. Their license terms are reproduced or pointed to
|
|
14
|
+
here. Runtime-external dependencies (`playwright`, `playwright-core`, and the
|
|
15
|
+
optional `better-sqlite3` and `accessibility-checker-engine`) are installed
|
|
16
|
+
separately and keep their own license files in your `node_modules`.
|
|
17
|
+
|
|
18
|
+
### Mozilla Public License 2.0 — axe-core, @axe-core/playwright
|
|
19
|
+
|
|
20
|
+
The accessibility audit inlines **axe-core** (via its Playwright wrapper
|
|
21
|
+
**@axe-core/playwright**), © Deque Systems, Inc., licensed under the
|
|
22
|
+
**Mozilla Public License, Version 2.0 (MPL-2.0)**.
|
|
23
|
+
|
|
24
|
+
MPL-2.0 is a file-level copyleft: because skeptic distributes these files in
|
|
25
|
+
executable (bundled) form, the corresponding **source is made available** to
|
|
26
|
+
recipients at:
|
|
27
|
+
|
|
28
|
+
- `axe-core` — https://github.com/dequelabs/axe-core (npm: `axe-core@4.11.x`)
|
|
29
|
+
- `@axe-core/playwright` — https://github.com/dequelabs/axe-core-npm
|
|
30
|
+
(npm: `@axe-core/playwright@4.11.x`)
|
|
31
|
+
|
|
32
|
+
The full MPL-2.0 text is available at https://www.mozilla.org/en-US/MPL/2.0/.
|
|
33
|
+
Per MPL-2.0 Exhibit A, the covered source is governed by this notice:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
This Source Code Form is subject to the terms of the Mozilla Public
|
|
37
|
+
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
38
|
+
file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Apache License 2.0 — web-vitals
|
|
42
|
+
|
|
43
|
+
**web-vitals** © Google LLC is licensed under the Apache License 2.0 and is
|
|
44
|
+
shipped both inlined and as the standalone `dist/web-vitals.iife.js` asset.
|
|
45
|
+
Source: https://github.com/GoogleChrome/web-vitals. The full Apache 2.0 text is
|
|
46
|
+
reproduced in the [agent-browser section below](#apache-license-20-full-text).
|
|
47
|
+
|
|
48
|
+
### Apache License 2.0 — accessibility-checker-engine
|
|
49
|
+
|
|
50
|
+
**accessibility-checker-engine** (IBM Equal Access Accessibility Checker)
|
|
51
|
+
© IBM, Inc. is an **optional, runtime-external** dependency — resolved from
|
|
52
|
+
`node_modules` by `src/observability/collectors/accessibility-collector.ts`
|
|
53
|
+
when present (the audit falls back to axe-core only when it is absent), not
|
|
54
|
+
inlined into the bundle — licensed under the **Apache License 2.0**. Source:
|
|
55
|
+
https://github.com/IBMa/equal-access. The full Apache 2.0 text is reproduced in
|
|
56
|
+
the [agent-browser section below](#apache-license-20-full-text).
|
|
57
|
+
|
|
58
|
+
### Blue Oak Model License 1.0.0 — glob, minimatch
|
|
59
|
+
|
|
60
|
+
**glob** and **minimatch** © Isaac Z. Schlueter and contributors are licensed
|
|
61
|
+
under the **Blue Oak Model License 1.0.0**. Full text:
|
|
62
|
+
https://blueoakcouncil.org/license/1.0.0.
|
|
63
|
+
|
|
64
|
+
### ISC License — yaml, pixelmatch
|
|
65
|
+
|
|
66
|
+
**yaml** © Eemeli Aro and **pixelmatch** © Mapbox are licensed under the ISC
|
|
67
|
+
license (a permissive, functionally-MIT-equivalent license). Full texts ship in
|
|
68
|
+
each package's `node_modules` distribution.
|
|
69
|
+
|
|
70
|
+
### MIT License — commander, zod, chokidar, chalk, figures, cli-truncate, string-width, pretty-ms, pngjs, react, ink, ink-spinner
|
|
71
|
+
|
|
72
|
+
The following bundled dependencies are licensed under the MIT License and carry
|
|
73
|
+
their own copyright notices in their respective packages:
|
|
74
|
+
|
|
75
|
+
| Package | Copyright holder |
|
|
76
|
+
|---|---|
|
|
77
|
+
| commander | TJ Holowaychuk and contributors |
|
|
78
|
+
| zod | Colin McDonnell |
|
|
79
|
+
| chokidar | Paul Miller |
|
|
80
|
+
| chalk | Sindre Sorhus |
|
|
81
|
+
| figures | Sindre Sorhus |
|
|
82
|
+
| cli-truncate | Sindre Sorhus |
|
|
83
|
+
| string-width | Sindre Sorhus |
|
|
84
|
+
| pretty-ms | Sindre Sorhus |
|
|
85
|
+
| pngjs | the pngjs contributors |
|
|
86
|
+
| react | Meta Platforms, Inc. and affiliates |
|
|
87
|
+
| ink | Vadim Demedes |
|
|
88
|
+
| ink-spinner | Vadim Demedes |
|
|
89
|
+
|
|
90
|
+
Each MIT/ISC/BlueOak license is permissive and grants redistribution provided
|
|
91
|
+
the copyright notice and permission text are preserved; those texts are
|
|
92
|
+
distributed inside each package and reproduced under the canonical license URLs
|
|
93
|
+
cited above. (skeptic carries no bundled AI/MCP/ACP SDKs — those dependencies
|
|
94
|
+
and their attributions were removed when the AI, MCP, and ACP subsystems were
|
|
95
|
+
deleted.)
|
|
7
96
|
|
|
8
97
|
## NOTICE — agent-browser (Apache License 2.0)
|
|
9
98
|
|
package/README.md
CHANGED
|
@@ -43,8 +43,8 @@ skeptic observe https://example.com
|
|
|
43
43
|
# Run TypeScript specs with full QA evidence
|
|
44
44
|
skeptic run tests/homepage.spec.ts --observability --video --trace
|
|
45
45
|
|
|
46
|
-
#
|
|
47
|
-
skeptic
|
|
46
|
+
# Drive a browser interactively from the shell (persistent session)
|
|
47
|
+
skeptic open https://example.com && skeptic snapshot -i
|
|
48
48
|
|
|
49
49
|
# Check local setup
|
|
50
50
|
skeptic doctor
|
|
@@ -121,7 +121,6 @@ The fixture exposes:
|
|
|
121
121
|
| `screenshot` | PNG screenshots, including annotated numbered-ref captures |
|
|
122
122
|
| `settle` | Network-idle settle helper |
|
|
123
123
|
| `observability` | Performance, network, console, and accessibility assertions |
|
|
124
|
-
| `ai` | Vision-backed assertions, defect checks, and text extraction |
|
|
125
124
|
| `ctx` | Per-test execution context and artifact paths |
|
|
126
125
|
|
|
127
126
|
`expect` is re-exported from Playwright Test, so matchers like
|
|
@@ -249,53 +248,31 @@ It writes an output directory containing an HTML report, JSON report,
|
|
|
249
248
|
screenshots, annotated screenshots, snapshot text/JSON, console/network data,
|
|
250
249
|
performance summary, accessibility JSON, and an accessibility markdown audit.
|
|
251
250
|
|
|
252
|
-
##
|
|
251
|
+
## Browser Session Verbs
|
|
253
252
|
|
|
254
|
-
Skeptic
|
|
253
|
+
Skeptic is agent-native: a coding agent drives a persistent browser entirely from
|
|
254
|
+
the shell. A daemon holds the session, so `@eN` refs from one `skeptic snapshot`
|
|
255
|
+
stay valid for the next `skeptic click @eN` — across separate commands. There is
|
|
256
|
+
no MCP/ACP server and no built-in AI: the host agent is the intelligence.
|
|
255
257
|
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
258
|
+
```bash
|
|
259
|
+
skeptic open https://app.example.com # opens a session (default name "default")
|
|
260
|
+
skeptic snapshot -i # mints @e1.. refs + stable selectorHints
|
|
261
|
+
skeptic click @e3 # act on a ref from the last snapshot
|
|
262
|
+
skeptic fill @e5 "user@test.com"
|
|
263
|
+
skeptic snapshot -i # re-snapshot after the DOM changed
|
|
264
|
+
skeptic console --errors # check for uncaught errors
|
|
265
|
+
skeptic screenshot --full # returns a file path
|
|
266
|
+
skeptic close
|
|
260
267
|
```
|
|
261
268
|
|
|
262
|
-
|
|
263
|
-
`
|
|
264
|
-
`
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
- `ai.assertNoDefects()`
|
|
270
|
-
- `ai.extract("the invoice total")`
|
|
271
|
-
- `skeptic generate --message "test checkout"`
|
|
272
|
-
- `skeptic generate --diff`
|
|
273
|
-
- `skeptic run --analyze`
|
|
274
|
-
|
|
275
|
-
Generated specs are typechecked and imported before being written.
|
|
276
|
-
|
|
277
|
-
## MCP And ACP
|
|
278
|
-
|
|
279
|
-
`skeptic mcp` exposes testing and browser QA tools over stdio:
|
|
280
|
-
|
|
281
|
-
| Tool | Purpose |
|
|
282
|
-
|---|---|
|
|
283
|
-
| `list_tests` | Discover specs |
|
|
284
|
-
| `validate_tests` | Typecheck and import-check specs |
|
|
285
|
-
| `generate_test` | Generate a validated TypeScript spec |
|
|
286
|
-
| `run_test` | Run specs and stream progress |
|
|
287
|
-
| `browser_open` | Open a page with config-driven browser/auth/safety |
|
|
288
|
-
| `browser_snapshot` | Capture ARIA/cursor refs |
|
|
289
|
-
| `browser_playwright` | Run focused Playwright code |
|
|
290
|
-
| `browser_screenshot` | Capture PNG, annotated PNG, or snapshot-only output |
|
|
291
|
-
| `browser_console_logs` | Read console messages |
|
|
292
|
-
| `browser_network_requests` | Read requests and computed issues |
|
|
293
|
-
| `browser_performance_metrics` | Capture Web Vitals, LoAF, resources, and `perf-trace.md` |
|
|
294
|
-
| `browser_accessibility_audit` | Run axe-core plus IBM Equal Access when available |
|
|
295
|
-
| `browser_close` | Close the browser session |
|
|
296
|
-
|
|
297
|
-
`skeptic acp` exposes a testing-focused agent server for editors that support
|
|
298
|
-
Agent Client Protocol.
|
|
269
|
+
Verbs: `open`, `snapshot` (`-i`/`-c`), `click`, `fill`, `type`, `press`, `hover`,
|
|
270
|
+
`check`, `uncheck`, `select`, `get <text|box|url|title> [@ref]`, `screenshot`
|
|
271
|
+
(`--full`/`--annotate`), `console` (`--errors`), `wait`, `list`, `close`
|
|
272
|
+
(`--all`). Add `--json` to any verb. Use `--session <name>` for isolated parallel
|
|
273
|
+
sessions; the session browser defaults to headed (`--headless` for CI/containers).
|
|
274
|
+
Refs are minted per snapshot and invalidated by navigation — re-snapshot after any
|
|
275
|
+
navigation or DOM change.
|
|
299
276
|
|
|
300
277
|
## Configuration
|
|
301
278
|
|
|
@@ -354,7 +331,7 @@ contexts and are not sent to Skeptic services.
|
|
|
354
331
|
|
|
355
332
|
```bash
|
|
356
333
|
skeptic add github-action
|
|
357
|
-
skeptic add github-action --
|
|
334
|
+
skeptic add github-action --dev-command "npm run dev" --dev-url http://localhost:3000
|
|
358
335
|
```
|
|
359
336
|
|
|
360
337
|
The generated workflow installs dependencies, installs Chromium, starts your dev
|
|
@@ -393,8 +370,7 @@ skeptic daemon stop
|
|
|
393
370
|
```
|
|
394
371
|
|
|
395
372
|
`skeptic doctor` checks config, output directories, browser installs, optional
|
|
396
|
-
accessibility/cookie engines, daemon state, cookie profiles
|
|
397
|
-
setup.
|
|
373
|
+
accessibility/cookie engines, daemon state, and cookie profiles.
|
|
398
374
|
|
|
399
375
|
## License
|
|
400
376
|
|
|
@@ -1,44 +1,138 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skeptic
|
|
3
|
-
description: Use Skeptic for CLI-first browser QA and TypeScript E2E tests. Use when asked to inspect pages, write or run skeptic-cli specs, validate UI changes, capture observability evidence
|
|
3
|
+
description: Use Skeptic for CLI-first browser QA and TypeScript E2E tests. Use when asked to inspect pages, drive a browser interactively, write or run skeptic-cli specs, validate UI changes, or capture observability evidence. Not for unit-only logic with no browser behavior.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
<!-- skeptic-agent-skill: managed by skeptic-cli -->
|
|
7
7
|
|
|
8
8
|
# Skeptic
|
|
9
9
|
|
|
10
|
-
Use Skeptic when
|
|
10
|
+
Use Skeptic when you need browser evidence: interactive page-driving, page inspection, TypeScript E2E specs, one-off QA captures, or observability evidence. Do not claim a UI/browser change works until you have run a relevant Skeptic command and checked the evidence.
|
|
11
|
+
|
|
12
|
+
Skeptic is **agent-native**: it has no model of its own, makes no LLM calls, and needs no API keys. You (the coding agent) are the intelligence; Skeptic is the deterministic hands and eyes. Everything is driven from the shell — there is no MCP server.
|
|
11
13
|
|
|
12
14
|
## Choose The Surface
|
|
13
15
|
|
|
14
|
-
-
|
|
15
|
-
- One-off
|
|
16
|
-
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
16
|
+
- **Drive a browser interactively** (click through a flow, check a fix): use the persistent session verbs — `skeptic open <url>`, `skeptic snapshot -i`, `skeptic click @e3`, etc. Refs persist between commands.
|
|
17
|
+
- **One-off discovery** (get stable selectors to write a spec): `skeptic inspect <url> --interactive --compact --with-playwright-hints`.
|
|
18
|
+
- **One-off QA / bug hunt** (full evidence bundle for one page): `skeptic observe <url> --full-page --video --trace`.
|
|
19
|
+
- **Persistent regression coverage**: inspect, write a `tests/*.spec.ts`, then `skeptic run`.
|
|
20
|
+
- **Changed-code verification**: run existing specs with `skeptic run`.
|
|
19
21
|
|
|
20
22
|
If the `skeptic` binary is not on PATH, try `npx skeptic-cli` or `npx --yes skeptic-cli@latest`.
|
|
21
23
|
|
|
22
|
-
Specs import
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
Specs import the project dependency `skeptic-cli`. A normal `skeptic init` writes that dependency to `package.json`. If specs fail with `Cannot find package 'skeptic-cli'`: in an initialized project run `npm install`; in a project that never ran `skeptic init`, run `skeptic init` first, then `npm install`.
|
|
25
|
+
|
|
26
|
+
## Persistent Browser Session
|
|
27
|
+
|
|
28
|
+
A daemon holds the browser, so `@eN` refs from one `skeptic snapshot` stay valid for the next `skeptic click @eN` — across separate commands. The loop:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
skeptic open https://app.example.com # opens a session (default name "default")
|
|
32
|
+
skeptic snapshot -i # mints @e1.. refs + stable selectorHints
|
|
33
|
+
skeptic click @e3 # act on a ref from the last snapshot
|
|
34
|
+
skeptic fill @e5 "user@test.com"
|
|
35
|
+
skeptic snapshot -i # RE-SNAPSHOT after the DOM changed
|
|
36
|
+
skeptic console --errors # check for uncaught errors
|
|
37
|
+
skeptic screenshot --full # returns a file path
|
|
38
|
+
skeptic close # end the session
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Verbs: `open`, `snapshot` (`-i` interactive, `-c` compact), `click`, `fill`, `type`, `press`, `hover`, `check`, `uncheck`, `select`, `get <text|box|url|title> [@ref]`, `screenshot` (`--full`, `--annotate`), `console` (`--errors`), `wait` (`--ms` or `--selector`), `list`, `close` (`--all`). Add `--json` to any verb for machine-readable output.
|
|
26
42
|
|
|
27
|
-
|
|
43
|
+
Rules:
|
|
44
|
+
|
|
45
|
+
- **Re-snapshot after any navigation, route change, modal open/close, or DOM mutation.** Refs are minted per snapshot and invalidated by navigation; acting on a stale ref returns a clear `[ariaRef:stale]` error — re-run `skeptic snapshot`.
|
|
46
|
+
- Prefer `@eN` refs from the latest snapshot; for selectors, use the `selectorHint` grammar (`role=button:Save`, `text=...`, `css=...`, `testid=...`).
|
|
47
|
+
- Use `--session <name>` for parallel isolated sessions.
|
|
48
|
+
- The session browser defaults to headed for local debugging; pass `--headless` on the first `open` for headless environments (CI/containers).
|
|
49
|
+
- Binary outputs (screenshots) come back as file paths, not inline data.
|
|
50
|
+
|
|
51
|
+
## Mobile (Android + iOS simulator)
|
|
52
|
+
|
|
53
|
+
The same verbs drive a native app on a device. **Android** (`--platform android`)
|
|
54
|
+
via `adb`; **iOS simulator** (`--platform ios-sim`) via `simctl` + `axe` (the idb
|
|
55
|
+
accessibility-framework redistribution). Both are driver-less — no Appium, no
|
|
56
|
+
WebDriverAgent, no in-app test bundle. `open` takes an app id (Android package /
|
|
57
|
+
iOS bundle id) or a deep link instead of a URL.
|
|
58
|
+
|
|
59
|
+
### Android (`--platform android`)
|
|
28
60
|
|
|
29
61
|
```bash
|
|
30
|
-
skeptic
|
|
31
|
-
skeptic
|
|
32
|
-
skeptic
|
|
62
|
+
skeptic open com.example.app --platform android # launches the app (am start -W)
|
|
63
|
+
skeptic snapshot -i # uiautomator tree → @eN refs
|
|
64
|
+
skeptic click @e5 # taps the node's center
|
|
65
|
+
skeptic fill @e3 "user@test.com" # ASCII input
|
|
66
|
+
skeptic is enabled @e5 # element state (visible|enabled)
|
|
67
|
+
skeptic screenshot # device screencap → file path
|
|
68
|
+
skeptic record --duration 5 # screenrecord → .mp4
|
|
69
|
+
skeptic perf # gfxinfo jank + meminfo PSS + launch ms
|
|
70
|
+
skeptic a11y # uiautomator a11y heuristics
|
|
71
|
+
skeptic network # per-uid byte totals (degraded)
|
|
72
|
+
skeptic console --errors # logcat (app-filtered)
|
|
73
|
+
skeptic close
|
|
33
74
|
```
|
|
34
75
|
|
|
35
|
-
|
|
76
|
+
Device evidence (parallels the web collectors; read via the verbs above):
|
|
77
|
+
|
|
78
|
+
- **perf** — `dumpsys gfxinfo` (total/janky frames, frame-time percentiles, missed
|
|
79
|
+
vsync) + `meminfo` (PSS/RSS) + `am start -W` launch timings. A distinct shape from
|
|
80
|
+
web vitals (`platform: "android"`).
|
|
81
|
+
- **a11y** — STRUCTURAL uiautomator heuristics only (unlabeled clickables, sub-48dp
|
|
82
|
+
touch targets, NAF nodes). No color-contrast check — the dump has no pixels.
|
|
83
|
+
- **network** — `degraded: true` by default: Android exposes only per-uid byte totals,
|
|
84
|
+
never per-request URLs/status. Per-request capture needs an opt-in proxy.
|
|
85
|
+
- `is checked` / `get value` aren't available on Android (the node doesn't retain them)
|
|
86
|
+
— they return a structured `[adbQuery:*_unsupported]` error; re-`snapshot` to read state.
|
|
87
|
+
|
|
88
|
+
### iOS simulator (`--platform ios-sim`)
|
|
89
|
+
|
|
90
|
+
Same verbs, against a **booted** simulator (`skeptic devices` lists them; boot with
|
|
91
|
+
`xcrun simctl boot <udid>`). Requires a full **Xcode** (not just Command Line Tools)
|
|
92
|
+
and **`axe`** (`brew install cameroncooke/axe/axe`) — skeptic finds Xcode itself, so
|
|
93
|
+
no `sudo xcode-select` needed.
|
|
36
94
|
|
|
37
95
|
```bash
|
|
38
|
-
skeptic
|
|
96
|
+
skeptic open com.apple.Preferences --platform ios-sim # bundle id or scheme:// link
|
|
97
|
+
skeptic snapshot -i # AXe accessibility tree → @eN refs
|
|
98
|
+
skeptic click @e4 # taps the element's center
|
|
99
|
+
skeptic fill @e14 "search text" # focuses + types (Cmd+A clear)
|
|
100
|
+
skeptic screenshot
|
|
101
|
+
skeptic console # bounded unified-log (best-effort)
|
|
102
|
+
skeptic close
|
|
39
103
|
```
|
|
40
104
|
|
|
41
|
-
|
|
105
|
+
- Refs come from `axe describe-ui` (the accessibility tree). selectorHints prefer the
|
|
106
|
+
stable `id=<accessibility identifier>` › `label=` › `type=`. `snapshot()` auto-settles
|
|
107
|
+
(re-dumps until the layout stops animating) so taps land where the element *is* — iOS
|
|
108
|
+
launch / large-title animations move elements for ~1–2s.
|
|
109
|
+
- iOS evidence is deliberately thin: `console` from the unified log only. perf/a11y/network
|
|
110
|
+
parity is a follow-up (the simulator exposes far less to an unprivileged host than Android).
|
|
111
|
+
- Real iOS devices are out of scope (`axe`/`idb` UI automation is simulator-only).
|
|
112
|
+
|
|
113
|
+
Mobile-specific guidance:
|
|
114
|
+
|
|
115
|
+
- **Emulator GPU mode matters for visual evidence.** A headless emulator launched
|
|
116
|
+
with `-no-window` and the wrong `-gpu` mode returns BLANK screencaps/recordings.
|
|
117
|
+
skeptic detects this (a near-uniform frame) and attaches a `blank-screenshot`
|
|
118
|
+
diagnostic. Fix: relaunch with software rendering —
|
|
119
|
+
`emulator -avd <name> -gpu swiftshader_indirect` (drop `-no-window` if it persists).
|
|
120
|
+
uiautomator dumps and `dumpsys` evidence are unaffected (no GPU needed).
|
|
121
|
+
- Refs come from a `uiautomator` accessibility dump (~1–3s each on a healthy
|
|
122
|
+
device). Re-snapshot after every screen change; prefer `res=` (resource-id)
|
|
123
|
+
and `desc=` (content-description) selectorHints over `text=`/`class=`.
|
|
124
|
+
- **React Native:** `testID` surfaces as `resource-id` on RN ≥ 0.64 → use `res=`.
|
|
125
|
+
**Compose:** needs `Modifier.semantics { testTagsAsResourceId = true }`, else
|
|
126
|
+
nodes are generic `View`s (rely on `desc=`/`text=`). **Flutter:** needs the
|
|
127
|
+
semantics tree enabled, else the app is one opaque node — fall back to a
|
|
128
|
+
screenshot and tap by coordinates.
|
|
129
|
+
- `adb` text input is ASCII-only; non-ASCII `fill`/`type` returns a structured
|
|
130
|
+
`[adbInput:unicode_unsupported]` error — set the value via a deep link or test
|
|
131
|
+
seam instead.
|
|
132
|
+
- WebView contents are invisible to uiautomator; for in-WebView assertions, drive
|
|
133
|
+
the web surface separately.
|
|
134
|
+
- iOS simulator support (`--platform ios-sim`, via `simctl` + `idb`) is planned;
|
|
135
|
+
real iOS devices are out of scope.
|
|
42
136
|
|
|
43
137
|
## Writing Specs
|
|
44
138
|
|
|
@@ -52,7 +146,7 @@ test("homepage smoke", async ({ page, snapshot, screenshot, observability }) =>
|
|
|
52
146
|
await expect(page).toHaveTitle(/Example Domain/);
|
|
53
147
|
|
|
54
148
|
const tree = await snapshot(page, { interactive: true, compact: true });
|
|
55
|
-
await tree.
|
|
149
|
+
await (await tree.byRef("e1")).click();
|
|
56
150
|
|
|
57
151
|
await screenshot("homepage", { fullPage: true });
|
|
58
152
|
await observability.expectNoConsoleErrors();
|
|
@@ -63,11 +157,42 @@ Rules:
|
|
|
63
157
|
|
|
64
158
|
- Put browser side effects inside `test(...)`, hooks, or helper functions called from tests.
|
|
65
159
|
- Prefer role, label, text, and test-id locators over CSS.
|
|
66
|
-
-
|
|
160
|
+
- `await snapshot(page)` before interacting through refs; `tree.byRef("eN")` is async — always `await` it.
|
|
67
161
|
- Re-snapshot after navigation, route changes, modal open/close, or major DOM mutation.
|
|
68
|
-
- Do not paste CLI `@eN` refs
|
|
162
|
+
- Do not paste CLI `@eN` refs into specs. Use `selectorHint` from `inspect`, or `tree.byRef("eN")` only for refs from the same in-test `snapshot(page)` call.
|
|
69
163
|
- Add `screenshot("name")` for states that would help debug a failure.
|
|
70
164
|
|
|
165
|
+
### Android specs
|
|
166
|
+
|
|
167
|
+
The same `test`/`expect`, runner, and `results.json` drive Android — run with
|
|
168
|
+
`skeptic run <spec> --platform android` (`--target <serial>` to pick a device).
|
|
169
|
+
Scaffold a starting spec with `skeptic scaffold <package> --platform android`.
|
|
170
|
+
Specs get a **`device`** fixture instead of `page` (uiautomator refs, not
|
|
171
|
+
Playwright locators):
|
|
172
|
+
|
|
173
|
+
```ts
|
|
174
|
+
import { test, expect } from "skeptic-cli";
|
|
175
|
+
|
|
176
|
+
test("sessions screen loads", async ({ device }) => {
|
|
177
|
+
await device.open("app.fieldwork.android"); // package or scheme:// deep link
|
|
178
|
+
let snap = await device.snapshot(); // refs + selectorHints
|
|
179
|
+
if (snap.has("text=OK")) { // dismiss a dialog if present
|
|
180
|
+
await device.click("text=OK");
|
|
181
|
+
snap = await device.snapshot(); // re-snapshot after the change
|
|
182
|
+
}
|
|
183
|
+
expect(snap.has("Search sessions")).toBe(true); // match selectorHint / name / role:name
|
|
184
|
+
await device.screenshot("sessions");
|
|
185
|
+
});
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
- Targets accept an `@eN` ref from the **last** `device.snapshot()` or a
|
|
189
|
+
selectorHint (`res=`/`desc=`/`text=`). Re-`snapshot()` after every screen change.
|
|
190
|
+
- `device.is("visible"|"enabled"|"checked", target)` and `device.get("text"|"value", target)`
|
|
191
|
+
read state; `device.scroll("@e5")` (into view) or `device.scroll({ dy: 600 })` (pan).
|
|
192
|
+
- The run auto-attaches mobile evidence to `results.json`: `console` (logcat),
|
|
193
|
+
`mobilePerformance` (gfxinfo/meminfo/launch), `mobileAccessibility`, `mobileNetwork`.
|
|
194
|
+
- Using `page` in an android spec (or `device` in a web spec) throws a clear error.
|
|
195
|
+
|
|
71
196
|
## Observability Checks
|
|
72
197
|
|
|
73
198
|
Use `--observability` for real QA evidence. In specs, assert the signals that match the risk:
|
|
@@ -79,27 +204,14 @@ await observability.expectPerformance({ lcp: "<2500ms", cls: "<0.1" });
|
|
|
79
204
|
await observability.expectAccessible({ standard: "WCAG21AA" });
|
|
80
205
|
```
|
|
81
206
|
|
|
82
|
-
If an observability artifact reports a failure, fix the product or the test and re-run the same flow immediately.
|
|
83
|
-
|
|
84
|
-
## MCP Workflow
|
|
85
|
-
|
|
86
|
-
When Skeptic is exposed through MCP:
|
|
87
|
-
|
|
88
|
-
1. `browser_open` the target URL.
|
|
89
|
-
2. `browser_snapshot` or `browser_screenshot` with snapshot mode to get refs.
|
|
90
|
-
3. Use one `browser_playwright` call for actions that share the same DOM state. Use the `ref` helper for snapshot refs and `return` structured evidence.
|
|
91
|
-
4. After DOM-changing actions, request a fresh snapshot.
|
|
92
|
-
5. Check `browser_console_logs`, `browser_network_requests`, `browser_accessibility_audit`, and `browser_performance_metrics`.
|
|
93
|
-
6. `browser_close` when done so video and trace artifacts flush.
|
|
94
|
-
|
|
95
|
-
Batch fills, clicks, and data collection when the DOM is stable. Do not take a new snapshot between plain text fills unless the page structure changed.
|
|
207
|
+
`skeptic run` always writes `results.json` to the output dir (default `./skeptic-output`). Use it plus screenshots, videos, traces, `network.json`, `console.json`, `accessibility.json`, and `perf-trace.md` as the evidence source. Reference artifact paths from `results.json` instead of guessing filenames. If an observability artifact reports a failure, fix the product or the test and re-run the same flow immediately.
|
|
96
208
|
|
|
97
209
|
## Verification Standard
|
|
98
210
|
|
|
99
211
|
Before reporting completion for browser-facing work:
|
|
100
212
|
|
|
101
|
-
- Run the smallest Skeptic command or
|
|
213
|
+
- Run the smallest Skeptic command (session verbs or a spec) that actually exercises the changed behavior.
|
|
102
214
|
- Test at least one adjacent or negative path when forms, routing, validation, auth, persistence, or shared components changed.
|
|
103
|
-
- Read the full command
|
|
215
|
+
- Read the full command output. Passing navigation alone is not enough.
|
|
104
216
|
- If there are console errors, network failures, serious accessibility issues, poor Web Vitals, or visible regressions, fix and re-run.
|
|
105
|
-
- State the exact command
|
|
217
|
+
- State the exact command run and the main artifact path in the final report.
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {createRequire}from'node:module';export{a as createAdb,c as escapeInputText,b as isAsciiInput,d as listDevices}from'./chunk-G22LGRZ4.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
|
|
2
|
+
createRequire(import.meta.url);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import {createRequire}from'node:module';import {a as a$1}from'./chunk-BIGNULF6.mjs';import {d,a}from'./chunk-G22LGRZ4.mjs';import'./chunk-N3533BCE.mjs';import'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
|
|
2
|
+
createRequire(import.meta.url);
|
|
3
|
+
var n=class i{constructor(e,r){this.serial=e;this.adb=r;}serial;adb;static async create(e={}){let r=e.serial;if(!r){let t=(await d(e.adbPath)).filter(b=>b.state==="device");if(t.length===0)throw new Error("no Android device/emulator attached (adb devices is empty); boot one first");r=t[0].serial;}let d$1=e.adb??a({serial:r,...e.adbPath?{adbPath:e.adbPath}:{}});return new i(r,d$1)}static fromAdb(e,r){return new i(e,r)}newSession(e){let r=e?.artifactDir??process.cwd();return Promise.resolve(new a$1(this.adb,this.serial,r))}close(){return Promise.resolve()}};export{n as AdbDriver};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {createRequire}from'node:module';export{a as AndroidAdbDriverSession,b as detectBlankCapture}from'./chunk-BIGNULF6.mjs';import'./chunk-G22LGRZ4.mjs';import'./chunk-N3533BCE.mjs';import'./chunk-ZN6MI2TU.mjs';import'./chunk-MHNEFL35.mjs';import'./chunk-S3M2RTHJ.mjs';import'./chunk-2YKSIUIN.mjs';/*! @license skeptic-cli — see LICENSES.md for third-party attributions */
|
|
2
|
+
createRequire(import.meta.url);
|