@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/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 **judgment**: did it actually work? tapp explores your app like a user —
16
- no test code, no app changes — detects what's broken, and commits to a verdict your merge queue
17
- can trust: `ready`, `caution`, or `blocked`, with evidence.
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 judgment layer:
22
+ Three platforms, one observe-and-gate engine:
20
23
 
21
- - **iOS** — the missing Playwright for iOS. tapp is hands *and* judgment: a generic XCUITest
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 QA, committed Flows, evidence, and regression gate. The app
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 verdict.
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 ask for a release verdict:
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 qa # explores the real app; prints verdict, findings, and evidence report
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, preserve Tapp's exact
52
- `ready`/`caution`/`blocked` verdict, and link the HTML evidence report. No server, account, config
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
- The baseline command writes only after autonomous QA and every selected deterministic suite pass
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 qa http://localhost:3000` *(one-time setup:
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 qa path/to/app-debug.apk --platform android --app-id com.acme.app
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`/`qa` workflow.
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
- > "Run tapp qa on my app is it ship-ready?"
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
- | 🧪 | `tapp_run_qa` | **Autonomous QA** — explores with no authored test, returns `{verdict, releaseScore, findings[]}` (`releaseScore` is `null` for exploratory web). Takes `appBundleId` (iOS), `androidAppId` (Android), or `url` (web). |
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
- ## The verdict you can trust
193
-
194
- **Adaptive exploration, deterministic judgment.** Exploration is adaptive — two runs may
195
- traverse different paths through your app. Judgment is deterministic: the same evidence
196
- trace always produces the same findings and verdict no LLM variability
197
- in the decision loop. PR gating keys on the **regression diff**
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 CI
200
- suite: reusable semantic actions, exact assertions, condition-based waits, fresh launch state, bounded timeouts,
201
- and evidence on failure. We call this *flake-resistant*, not magically flake-free—backend outages,
202
- unstable test data, and poorly identified controls can still make any E2E test fail.
203
-
204
- **Native has a heuristic release score; exploratory web does not.** The native 0–100 number comes
205
- from fixed deductions and is not calibrated probability. Web reports deterministic findings,
206
- advisory budget-capped control probes, and concrete coverage instead of compressing those unlike
207
- signals into a scalar. Committed Flows, Tasks, contracts, and baseline regressions provide the web
208
- merge decision.
209
-
210
- `tapp_run_qa` explores like a user accessibility surfaces on iOS/Android and a real browser on web —
211
- and detects crashes, failed sign-ins, dead buttons, stuck loading screens, error surfaces,
212
- navigation loops, and dead ends (plus, on web: uncaught JS exceptions, failed/5xx requests,
213
- broken links and assets, and visible placeholder links with no destination). The verdict is
214
- **deterministic** (no LLM in the run loop) and **honest**:
215
-
216
- - `blocked` a release-blocking issue was found.
217
- - `caution` issues to review, or the run couldn't see enough.
218
- - `ready` genuinely explored with no detected blockers in the checks that ran. **A shallow run
219
- is never `ready`**if the
220
- app crashed on launch or a login wall blocked exploration, you get `inconclusive: true`,
221
- not a false pass. Absence of findings is not a pass.
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 autonomous QA inferred the guarantee.
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 qa` (or `qa <url>` for web) and
354
- report the ship/no-ship verdict. A change is not "done" until it has been seen working.
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 tapp_run_qa.)
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 judgment layer parses into trees, screenshots, findings, and the verdict.
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 verdict. Core exploration, evidence collection, and
368
- verdict calculation run entirely locally — no telemetry, nothing phones home. Optional AI
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`. Existing
374
- `.autotap/`, `.autotap.yml`, and `AUTOTAP_*` inputs remain readable as migration fallbacks; when
375
- both names exist, Tapp uses the canonical one. Rename the old directory/config in your next
376
- reviewed repository change—no secrets or evidence formats need to be rewritten.
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