@aarwitz/tapp 0.16.5 → 0.17.0-rc.10
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 +35 -21
- package/Harness/OCQAHarnessUITests/ExplorerTests.swift +100 -31
- package/README.md +70 -67
- package/bin/tapp.js +265 -74
- package/browser/app.js +12 -6
- package/docs/BROWSER-PRODUCT.md +75 -0
- package/docs/PRODUCT-ENGINE.md +107 -0
- package/docs/application-model.md +278 -0
- package/docs/scenarios.md +95 -0
- package/mcp-server/src/android-driver.js +88 -3
- package/mcp-server/src/android-explorer.js +83 -14
- package/mcp-server/src/application-model.js +13 -9
- package/mcp-server/src/browser-product.js +1 -1
- package/mcp-server/src/ci-report.js +84 -62
- package/mcp-server/src/ci-setup.js +35 -5
- package/mcp-server/src/enrich.js +1 -1
- package/mcp-server/src/html-report.js +41 -7
- package/mcp-server/src/index.js +198 -72
- package/mcp-server/src/pr-selection.js +4 -3
- package/mcp-server/src/product-execution.js +1 -1
- package/mcp-server/src/product-operations.js +96 -7
- package/mcp-server/src/project-config.js +1 -2
- package/mcp-server/src/project-paths.js +5 -17
- package/mcp-server/src/release-contract.js +3 -3
- package/mcp-server/src/report.js +185 -51
- package/mcp-server/src/task-runtime.js +1 -1
- package/mcp-server/src/web-explorer.js +1 -1
- package/package.json +2 -2
- package/scripts/ci-gate.sh +11 -9
- package/scripts/flow_ai_judge.py +1 -1
- package/scripts/platform-gate.js +11 -5
- package/scripts/quick-capture.sh +72 -38
- package/scripts/run-flow.sh +1 -1
package/README.md
CHANGED
|
@@ -12,21 +12,24 @@ It turns a repository and real product into an observed UI Map, a compact review
|
|
|
12
12
|
suite, and an inspectable merge decision.
|
|
13
13
|
|
|
14
14
|
Coding agents can write the code, and (with Playwright & friends) they can even drive the app.
|
|
15
|
-
What nobody gives them is **
|
|
16
|
-
no
|
|
17
|
-
|
|
15
|
+
What nobody gives them is **proof it works**. tapp explores your app like a user — no test code,
|
|
16
|
+
no app changes — and surfaces what's broken, with evidence. Then a deterministic gate applies
|
|
17
|
+
versioned policy to that evidence — the findings and coverage, any selected deterministic suites
|
|
18
|
+
(Flows/Scenarios/contracts), and, when available, a target-scoped baseline — and returns a merge
|
|
19
|
+
decision your queue can trust: `pass`, `fail`, or `inconclusive`. Exploration **observes**; the gate
|
|
20
|
+
**judges** — never a soft "ship-ready" guess.
|
|
18
21
|
|
|
19
|
-
Three platforms, one
|
|
22
|
+
Three platforms, one observe-and-gate engine:
|
|
20
23
|
|
|
21
|
-
- **iOS** — the missing Playwright for iOS. tapp is hands *and*
|
|
24
|
+
- **iOS** — the missing Playwright for iOS. tapp is hands *and* eyes: a generic XCUITest
|
|
22
25
|
harness drives any app on the simulator via the accessibility surface. Native — no Appium,
|
|
23
26
|
no WebDriverAgent.
|
|
24
27
|
- **Android** — black-box native driving through ADB + UIAutomator. Install an APK, target its
|
|
25
|
-
application id, and run the same
|
|
26
|
-
does not link a Tapp SDK.
|
|
28
|
+
application id, and run the same exploration, committed Flows, evidence, and regression gate. The
|
|
29
|
+
app does not link a Tapp SDK.
|
|
27
30
|
- **Web (beta)** — built *on* Playwright. Your agent already has browser hands; tapp adds the
|
|
28
31
|
autonomous exploration, the deterministic detectors (uncaught exceptions, failed requests,
|
|
29
|
-
dead buttons, broken links, placeholder `href="#"` links, error pages), and the same
|
|
32
|
+
dead buttons, broken links, placeholder `href="#"` links, error pages), and the same gate.
|
|
30
33
|
|
|
31
34
|
```
|
|
32
35
|
you: "Add a logout button to the settings screen"
|
|
@@ -40,17 +43,17 @@ agent: "Done — and here it is working on the simulator: [screenshot]"
|
|
|
40
43
|
Requirements: **Node ≥ 18**. iOS needs **macOS + Xcode**; Android needs `adb` plus a connected
|
|
41
44
|
emulator/device; web needs Playwright + Chromium.
|
|
42
45
|
|
|
43
|
-
From the app repository, let the agent see the current screen and then
|
|
46
|
+
From the app repository, let the agent see the current screen and then explore it:
|
|
44
47
|
|
|
45
48
|
```bash
|
|
46
49
|
npx -y @aarwitz/tapp open # builds/launches as needed; prints a screenshot path + screen summary
|
|
47
|
-
npx -y @aarwitz/tapp
|
|
50
|
+
npx -y @aarwitz/tapp explore # explores the real app; prints findings + evidence (an observation, not a gate)
|
|
48
51
|
```
|
|
49
52
|
|
|
50
53
|
Claude Code can read the saved image with its file-reading tool; Codex can open it with
|
|
51
|
-
`view_image`. The agent should report what the screenshot proves,
|
|
52
|
-
`
|
|
53
|
-
file, test code, API key, or bundle id is required for this loop.
|
|
54
|
+
`view_image`. The agent should report what the screenshot proves, relay the exploration findings
|
|
55
|
+
as-is (an observation, not a merge decision — `tapp ci` gates that), and link the HTML evidence
|
|
56
|
+
report. No server, account, config file, test code, API key, or bundle id is required for this loop.
|
|
54
57
|
|
|
55
58
|
The product, executable, and package leaf are all Tapp: npm distributes it as
|
|
56
59
|
`@aarwitz/tapp`, while the installed command remains `tapp`.
|
|
@@ -77,7 +80,13 @@ npx -y @aarwitz/tapp baseline create . --platform web
|
|
|
77
80
|
npx -y @aarwitz/tapp ci install .
|
|
78
81
|
```
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
On a fresh repository containing multiple apps (for example, iOS plus web), bare
|
|
84
|
+
`tapp init . --explore` does not guess from detection order. A human terminal gets a numbered
|
|
85
|
+
selector; a non-interactive CLI prints exact target-selection commands, while MCP also returns
|
|
86
|
+
structured choices. Neither builds or writes before the choice. After you choose one, the model
|
|
87
|
+
retains every detected target and records the choice as the default for the next bare `tapp explore`.
|
|
88
|
+
|
|
89
|
+
The baseline command writes only after exploration and every selected deterministic suite pass
|
|
81
90
|
conclusively. It stores `.tapp/baselines/<platform>/<target-id>.json`; the generated workflow
|
|
82
91
|
uses that exact target identity so two apps on the same platform never share a baseline. `ci
|
|
83
92
|
install` writes `.github/workflows/tapp.yml` plus `.tapp/ci.json`, refuses unresolved build
|
|
@@ -96,7 +105,7 @@ npx -y @aarwitz/tapp apps # what's installed on the simulator (names
|
|
|
96
105
|
npx -y @aarwitz/tapp build [dir] # just build + install (scheme auto-detected)
|
|
97
106
|
```
|
|
98
107
|
|
|
99
|
-
Web (beta): `npx -y @aarwitz/tapp
|
|
108
|
+
Web (beta): `npx -y @aarwitz/tapp explore http://localhost:3000` *(one-time setup:
|
|
100
109
|
`npm i -g playwright && npx playwright install chromium`)*
|
|
101
110
|
|
|
102
111
|
Focused web inspection waits briefly for loading states to settle. If a consent or location modal
|
|
@@ -110,7 +119,7 @@ npx -y @aarwitz/tapp tree https://example.com --tap "Not now" --wait-for "Dashbo
|
|
|
110
119
|
Android:
|
|
111
120
|
|
|
112
121
|
```bash
|
|
113
|
-
npx -y @aarwitz/tapp
|
|
122
|
+
npx -y @aarwitz/tapp explore path/to/app-debug.apk --platform android --app-id com.acme.app
|
|
114
123
|
npx -y @aarwitz/tapp open com.acme.app --platform android
|
|
115
124
|
```
|
|
116
125
|
|
|
@@ -124,7 +133,7 @@ npx -y @aarwitz/tapp doctor # verify Xcode / simulators / toolchain
|
|
|
124
133
|
|
|
125
134
|
`npx -y @aarwitz/tapp app .` opens a local Release Studio for people who want visual repository
|
|
126
135
|
onboarding, release-plan review, and CI preparation. It is not required for the coding-agent
|
|
127
|
-
`open`/`
|
|
136
|
+
`open`/`explore` workflow.
|
|
128
137
|
|
|
129
138
|
### MCP hookup (optional)
|
|
130
139
|
|
|
@@ -156,7 +165,7 @@ args = ["-y", "@aarwitz/tapp", "mcp"]
|
|
|
156
165
|
**Any other MCP client:** stdio command `npx -y @aarwitz/tapp mcp`.
|
|
157
166
|
|
|
158
167
|
Then ask your agent:
|
|
159
|
-
> "
|
|
168
|
+
> "Explore my app and show me what breaks."
|
|
160
169
|
> "Open com.mycompany.app on the simulator and screenshot the home screen."
|
|
161
170
|
> "Log in with test@example.com, drive to checkout, and record it as a replayable test."
|
|
162
171
|
|
|
@@ -168,7 +177,7 @@ Then ask your agent:
|
|
|
168
177
|
| 📸 | `tapp_screenshot` | Whatever's on the sim right now, as an inline image. |
|
|
169
178
|
| 🌳 | `tapp_ui_tree` | The accessibility tree of the current screen (ids, labels, hittability). |
|
|
170
179
|
| 🕹 | `tapp_session_start/act/end` | **Interactive driving** — the Playwright loop. App launches once; each act (tap/type/swipe/back/wait) returns the fresh tree. |
|
|
171
|
-
|
|
|
180
|
+
| 🔭 | `tapp_explore` | **Autonomous exploration** — explores with no authored test, returns an observation `{kind, headline, inconclusive, findingCounts, findings[]}` (no verdict/score — the deterministic gate judges). Takes `appBundleId` (iOS), `androidAppId` (Android), or `url` (web). |
|
|
172
181
|
| 🧭 | `tapp_init` | **Repository import** — detect targets; optionally explore a real surface; persist the shared UI Map; construct the evidence-classified model and grounded release plan. |
|
|
173
182
|
| 👤 | `tapp_actor_config` | **Actor/session setup** — store roles, isolation/provisioning, and environment-variable names without accepting or persisting credential values. |
|
|
174
183
|
| ✅ | `tapp_release_plan` | **Release-plan lifecycle** — inspect, approve/reject/defer, generate, real-target validate, and explicitly promote proposed guarantees without silent test edits. |
|
|
@@ -189,49 +198,43 @@ The desktop Coverage view reads the same `.tapp/application-model.json`,
|
|
|
189
198
|
does not maintain a separate product model. Map nodes identify both the real launch entry and the
|
|
190
199
|
deterministic per-platform navigation root used for bounded changed-surface replay.
|
|
191
200
|
|
|
192
|
-
##
|
|
193
|
-
|
|
194
|
-
**
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
in the decision loop. PR gating keys on the
|
|
198
|
-
(stable finding signatures vs. a baseline), so it reacts to what *changed*, not to
|
|
199
|
-
run-to-run path variance. For critical user journeys, committed **Tasks and Flows** provide the stable
|
|
200
|
-
suite: reusable semantic actions, exact assertions, condition-based waits, fresh launch state,
|
|
201
|
-
and evidence on failure. We call this *flake-resistant*, not magically flake-free—
|
|
202
|
-
unstable test data, and poorly identified controls can still make any E2E test fail.
|
|
203
|
-
|
|
204
|
-
**
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
Web beta presents a `ready` result as **AUTOMATED CHECKS COMPLETE**, not “ship-ready,” and displays
|
|
224
|
-
no scalar score. Exhaustive checks on each exercised page drive the verdict; sampled control probes
|
|
225
|
-
remain visible findings but are advisory. The report
|
|
226
|
-
explicitly excludes content/claim accuracy, privacy and API data minimization, brand/SEO
|
|
227
|
-
consistency, and subjective visual credibility. Those require reviewed contracts, privacy review,
|
|
228
|
-
or human/vision judgment; an exploratory crawl must not imply they were validated.
|
|
201
|
+
## Observation you can read, judgment you can trust
|
|
202
|
+
|
|
203
|
+
**Exploration observes; the gate judges.** Exploration is adaptive — two runs may traverse different
|
|
204
|
+
paths — and it produces an **observation**, never a ship verdict: findings + coverage + evidence. The
|
|
205
|
+
**gate** is deterministic: the same evidence trace, contracts, and baseline always produce the same
|
|
206
|
+
outcome — `pass`, `fail`, or `inconclusive` — with no LLM in the decision loop. PR gating keys on the
|
|
207
|
+
**regression diff** (stable finding signatures vs. a baseline), so it reacts to what *changed*, not to
|
|
208
|
+
run-to-run path variance. For critical user journeys, committed **Tasks and Flows** provide the stable
|
|
209
|
+
CI suite: reusable semantic actions, exact assertions, condition-based waits, fresh launch state,
|
|
210
|
+
bounded timeouts, and evidence on failure. We call this *flake-resistant*, not magically flake-free —
|
|
211
|
+
backend outages, unstable test data, and poorly identified controls can still make any E2E test fail.
|
|
212
|
+
|
|
213
|
+
**No scores, no soft verdicts.** Exploration reports deterministic findings, advisory budget-capped
|
|
214
|
+
control probes, and concrete coverage — never a 0–100 number or a "ready/ship" label a shallow crawl
|
|
215
|
+
can't honestly earn. The merge decision comes only from the gate: reviewed contracts, committed
|
|
216
|
+
Flows/Scenarios, and baseline regressions.
|
|
217
|
+
|
|
218
|
+
`tapp_explore` explores like a user — accessibility surfaces on iOS/Android and a real browser on web
|
|
219
|
+
— and detects crashes, failed sign-ins, dead buttons, stuck loading screens, error surfaces,
|
|
220
|
+
navigation loops, and dead ends (plus, on web: uncaught JS exceptions, failed/5xx requests, broken
|
|
221
|
+
links and assets, and visible placeholder links with no destination). The observation is honest about
|
|
222
|
+
its limits:
|
|
223
|
+
|
|
224
|
+
- It **surfaces findings**; it does not pronounce "ready." **A shallow run is never a pass** — if the
|
|
225
|
+
app crashed on launch or a login wall blocked exploration, you get `inconclusive: true`, not a false
|
|
226
|
+
green. Absence of findings is not a pass.
|
|
227
|
+
- The **gate** turns findings + coverage + your reviewed contracts + a baseline into `pass` / `fail` /
|
|
228
|
+
`inconclusive` (`inconclusive` fails closed). Deterministic — no LLM in the run loop.
|
|
229
|
+
- An exploratory crawl explicitly **excludes** content/claim accuracy, privacy and API data
|
|
230
|
+
minimization, brand/SEO consistency, and subjective visual credibility. Those require reviewed
|
|
231
|
+
contracts, privacy review, or human/vision judgment; a crawl must not imply they were validated.
|
|
229
232
|
|
|
230
233
|
For a business guarantee such as “every coach is insured,” use a deterministic app-owned verifier
|
|
231
234
|
endpoint that returns success only when the invariant holds, then require that status and the
|
|
232
235
|
customer-visible claim in a release contract. The current DSL does not yet read arbitrary JSON
|
|
233
236
|
response bodies or compare a cross-origin API payload directly with page copy; use a verifier or an
|
|
234
|
-
explicit CI preflight rather than assuming
|
|
237
|
+
explicit CI preflight rather than assuming exploration inferred the guarantee.
|
|
235
238
|
|
|
236
239
|
Apps behind a login? Pass `testEmail`/`testPassword` (typed into the login form automatically),
|
|
237
240
|
`appLaunchArgs` (e.g. `["--uitesting"]` if your app supports a bypass), or explicit `loginSteps`
|
|
@@ -350,30 +353,30 @@ your agent proves its UI work instead of claiming it:
|
|
|
350
353
|
This repo uses tapp (https://github.com/aarwitz/tapp) to verify UI work on a real app surface
|
|
351
354
|
(iOS simulator, Android emulator/device, or a browser for web). After any UI change, run `npx -y @aarwitz/tapp open` from the
|
|
352
355
|
repo root (it finds and builds the Xcode project itself) and look at the screenshot it saves as
|
|
353
|
-
proof. Before declaring a feature done, run `npx -y @aarwitz/tapp
|
|
354
|
-
report the
|
|
356
|
+
proof. Before declaring a feature done, run `npx -y @aarwitz/tapp explore` (or `explore <url>` for web)
|
|
357
|
+
and report the findings + evidence. A change is not "done" until it has been seen working.
|
|
355
358
|
(If the tapp MCP server is connected, the tapp_* tools do the same with inline screenshots —
|
|
356
|
-
tapp_build builds + installs the app and returns the bundle id for
|
|
359
|
+
tapp_build builds + installs the app and returns the bundle id for tapp_explore.)
|
|
357
360
|
```
|
|
358
361
|
|
|
359
362
|
## How it works
|
|
360
363
|
|
|
361
364
|
Every driver speaks one protocol: structured `OCQA_*` markers (state, actions, issues,
|
|
362
|
-
transitions) that the
|
|
365
|
+
transitions) that the engine parses into trees, screenshots, findings, coverage, and the gate outcome.
|
|
363
366
|
On **iOS**, a generic **XCUITest harness** attaches to any app by bundle id — no SDK or app code
|
|
364
367
|
changes — and acts through the accessibility tree. On **Android**, ADB + UIAutomator provide the
|
|
365
368
|
same black-box driver contract. On **web** (beta), a deterministic **Playwright crawler** does the
|
|
366
369
|
same in a real browser. Same detectors' spirit,
|
|
367
|
-
same dedup, same regression gate, same honest
|
|
368
|
-
|
|
370
|
+
same dedup, same regression gate, same honest `pass`/`fail`/`inconclusive` outcome. Core exploration,
|
|
371
|
+
evidence collection, and gate evaluation run entirely locally — no telemetry, nothing phones home. Optional AI
|
|
369
372
|
features are explicit: finding enrichment requires `TAPP_ENABLE_REMOTE_AI=1` (an ambient
|
|
370
373
|
API key alone never changes data handling), and AI flow generation / `assert_ai` only run
|
|
371
374
|
when you invoke them; these send selected metadata (screen names, finding titles) to your
|
|
372
375
|
configured model provider. Runtime configuration uses `TAPP_*` environment variables. Repository
|
|
373
|
-
artifacts live under `.tapp/`, and desktop run configuration uses `.tapp.yml`.
|
|
374
|
-
`.autotap/`, `.autotap.yml`, and `AUTOTAP_*` inputs
|
|
375
|
-
|
|
376
|
-
reviewed
|
|
376
|
+
artifacts live under `.tapp/`, and desktop run configuration uses `.tapp.yml`. These are the only
|
|
377
|
+
names Tapp reads: the pre-rename `.autotap/`, `.autotap.yml`, and `AUTOTAP_*` inputs are no longer
|
|
378
|
+
supported. If you still have an old directory or config, rename it to the `.tapp` names in a
|
|
379
|
+
reviewed change—no secrets or evidence formats need to be rewritten.
|
|
377
380
|
|
|
378
381
|
Committed Flow replay, recording a driven session, autonomous exploration, exact assertions,
|
|
379
382
|
regression comparison, and CI gating require **no API key and no coding agent at runtime**. AI is
|