@aarwitz/tapp 0.17.0-rc.9 → 0.17.1
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/.claude-plugin/marketplace.json +34 -0
- package/.claude-plugin/plugin.json +33 -0
- package/AGENTS.md +44 -15
- package/Harness/OCQAHarnessUITests/ExplorerTests.swift +65 -7
- package/README.md +141 -81
- package/bin/tapp.js +253 -64
- package/docs/BROWSER-PRODUCT.md +1 -1
- package/docs/application-model.md +12 -3
- package/docs/scenarios.md +1 -1
- package/mcp-server/src/android-driver.js +13 -2
- package/mcp-server/src/android-explorer.js +3 -1
- package/mcp-server/src/android-flow.js +18 -1
- package/mcp-server/src/application-model.js +83 -13
- package/mcp-server/src/ci-report.js +2 -2
- package/mcp-server/src/ci-setup.js +4 -4
- package/mcp-server/src/environment-preflight.js +43 -0
- package/mcp-server/src/focused-navigation.js +271 -0
- package/mcp-server/src/html-report.js +3 -2
- package/mcp-server/src/index.js +565 -134
- package/mcp-server/src/pr-selection.js +2 -2
- package/mcp-server/src/product-operations.js +111 -6
- package/mcp-server/src/report.js +17 -4
- package/mcp-server/src/ui-map.js +2 -2
- package/mcp-server/src/web-explorer.js +123 -10
- package/mcp-server/src/web-flow.js +17 -1
- package/package.json +6 -4
- package/scripts/ci-gate.sh +42 -0
- package/scripts/flow_lib.py +1 -1
- package/scripts/quick-capture.sh +44 -13
- package/scripts/run-flow.sh +12 -1
- package/skills/tapp/SKILL.md +95 -0
- package/skills/tapp/agents/openai.yaml +4 -0
- package/skills/tapp/references/commands.md +105 -0
package/scripts/quick-capture.sh
CHANGED
|
@@ -23,9 +23,9 @@ TAPP_RUNTIME_HOME="${TAPP_HOME:-}"
|
|
|
23
23
|
if [[ -n "${TAPP_CAPTURE_DIR:-}" ]]; then
|
|
24
24
|
CAPTURE_DIR="$TAPP_CAPTURE_DIR"
|
|
25
25
|
elif [[ -n "$TAPP_RUNTIME_HOME" ]]; then
|
|
26
|
-
CAPTURE_DIR="$TAPP_RUNTIME_HOME/captures
|
|
26
|
+
CAPTURE_DIR="$TAPP_RUNTIME_HOME/captures/ios-$(date +%Y%m%d-%H%M%S)"
|
|
27
27
|
else
|
|
28
|
-
CAPTURE_DIR="$PROJECT_ROOT/captures
|
|
28
|
+
CAPTURE_DIR="$PROJECT_ROOT/captures/ios-$(date +%Y%m%d-%H%M%S)"
|
|
29
29
|
fi
|
|
30
30
|
if [[ -n "$TAPP_RUNTIME_HOME" ]]; then
|
|
31
31
|
HARNESS_DERIVED="$TAPP_RUNTIME_HOME/harness-derived"
|
|
@@ -163,13 +163,28 @@ run_harness_test() {
|
|
|
163
163
|
\"OCQA_PR_TARGET\": ${OCQA_PR_TARGET_JSON}"
|
|
164
164
|
fi
|
|
165
165
|
|
|
166
|
+
# Visual evidence must begin at the first settled target-app frame, never while Xcode is
|
|
167
|
+
# installing/launching the test runner or SpringBoard is selecting the app. The harness writes
|
|
168
|
+
# the ready file after the target is foregrounded + stable, then briefly waits for the host's
|
|
169
|
+
# recording-start acknowledgement so the first autonomous action cannot race ahead of video.
|
|
170
|
+
local visual_ready_line=""
|
|
171
|
+
if [[ -n "${OCQA_VISUAL_READY_PATH:-}" ]]; then
|
|
172
|
+
visual_ready_line=",
|
|
173
|
+
\"OCQA_VISUAL_READY_PATH\": \"${OCQA_VISUAL_READY_PATH}\""
|
|
174
|
+
fi
|
|
175
|
+
local recording_started_line=""
|
|
176
|
+
if [[ -n "${OCQA_RECORDING_STARTED_PATH:-}" ]]; then
|
|
177
|
+
recording_started_line=",
|
|
178
|
+
\"OCQA_RECORDING_STARTED_PATH\": \"${OCQA_RECORDING_STARTED_PATH}\""
|
|
179
|
+
fi
|
|
180
|
+
|
|
166
181
|
cat > /tmp/ocqa-run-config.json << CONF
|
|
167
182
|
{
|
|
168
183
|
"OCQA_BUNDLE_ID": "$bundle_id",
|
|
169
184
|
"OCQA_MAX_ACTIONS": "$max_actions",
|
|
170
185
|
"OCQA_TIMEOUT_SECONDS": "$timeout_secs",
|
|
171
186
|
"OCQA_TEST_EMAIL": "${OCQA_TEST_EMAIL:-qa@example.com}",
|
|
172
|
-
"OCQA_TEST_PASSWORD": "${OCQA_TEST_PASSWORD:-Tapp123!}"$interactive_line$overrides_line$launch_args_line$launch_env_line$login_steps_line$pr_target_line
|
|
187
|
+
"OCQA_TEST_PASSWORD": "${OCQA_TEST_PASSWORD:-Tapp123!}"$interactive_line$overrides_line$launch_args_line$launch_env_line$login_steps_line$pr_target_line$visual_ready_line$recording_started_line
|
|
173
188
|
}
|
|
174
189
|
CONF
|
|
175
190
|
|
|
@@ -290,23 +305,38 @@ OCQA_COMPLETE:{\"actions\":0,\"states\":0,\"issues\":1,\"screens\":\"\",\"outcom
|
|
|
290
305
|
echo "WARNING: Target process exited during launch preflight; recorded a crash instead of waiting for the exploration timeout." >&2
|
|
291
306
|
else
|
|
292
307
|
|
|
293
|
-
#
|
|
308
|
+
# Prepare the foreground/settled handshake before starting the harness. Recording begins
|
|
309
|
+
# only after that handshake; this excludes build/install/SpringBoard footage without using a
|
|
310
|
+
# brittle fixed trim duration. A caller such as VS Code may provide its own ready path to
|
|
311
|
+
# reveal a preview at the same authoritative boundary.
|
|
294
312
|
cleanup_stale_recorders "$UDID"
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
echo "WARNING: Could not start simulator video recording. Continuing without video." >&2
|
|
301
|
-
RECORD_PID=""
|
|
302
|
-
fi
|
|
313
|
+
VISUAL_READY_PATH="${OCQA_VISUAL_READY_PATH:-$CAPTURE_DIR/visual-ready}"
|
|
314
|
+
RECORDING_STARTED_PATH="$CAPTURE_DIR/recording-started"
|
|
315
|
+
rm -f "$VISUAL_READY_PATH" "$RECORDING_STARTED_PATH"
|
|
316
|
+
export OCQA_VISUAL_READY_PATH="$VISUAL_READY_PATH"
|
|
317
|
+
export OCQA_RECORDING_STARTED_PATH="$RECORDING_STARTED_PATH"
|
|
303
318
|
|
|
304
319
|
# Run exploration with watchdog timeout to avoid silent hangs.
|
|
305
320
|
run_harness_test "testAutonomousExploration" "$SIM_NAME" "$APP_BUNDLE" "$MAX_ACTIONS" "$EXPLORE_TIMEOUT" > "$local_output_file" 2>&1 &
|
|
306
321
|
HARNESS_PID=$!
|
|
307
322
|
|
|
308
323
|
START_TS=$(date +%s)
|
|
324
|
+
RECORDING_ATTEMPTED=0
|
|
309
325
|
while kill -0 "$HARNESS_PID" 2>/dev/null; do
|
|
326
|
+
if [[ "$RECORDING_ATTEMPTED" -eq 0 && -f "$VISUAL_READY_PATH" ]]; then
|
|
327
|
+
RECORDING_ATTEMPTED=1
|
|
328
|
+
if xcrun simctl io "$UDID" recordVideo --codec=h264 "$CAPTURE_DIR/exploration.mov" & then
|
|
329
|
+
RECORD_PID=$!
|
|
330
|
+
fi
|
|
331
|
+
sleep 0.25
|
|
332
|
+
if [[ -z "$RECORD_PID" ]] || ! kill -0 "$RECORD_PID" 2>/dev/null; then
|
|
333
|
+
echo "WARNING: Could not start simulator video recording. Continuing without video." >&2
|
|
334
|
+
RECORD_PID=""
|
|
335
|
+
fi
|
|
336
|
+
# Always release the bounded harness wait. The missing video remains explicit in the
|
|
337
|
+
# report; exploration itself must not hang merely because recording was unavailable.
|
|
338
|
+
: > "$RECORDING_STARTED_PATH"
|
|
339
|
+
fi
|
|
310
340
|
NOW_TS=$(date +%s)
|
|
311
341
|
ELAPSED=$((NOW_TS - START_TS))
|
|
312
342
|
if [[ "$ELAPSED" -ge "$EXPLORE_TIMEOUT" ]]; then
|
|
@@ -316,7 +346,7 @@ OCQA_COMPLETE:{\"actions\":0,\"states\":0,\"issues\":1,\"screens\":\"\",\"outcom
|
|
|
316
346
|
kill -KILL "$HARNESS_PID" 2>/dev/null || true
|
|
317
347
|
break
|
|
318
348
|
fi
|
|
319
|
-
sleep
|
|
349
|
+
if [[ "$RECORDING_ATTEMPTED" -eq 0 ]]; then sleep 0.1; else sleep 1; fi
|
|
320
350
|
done
|
|
321
351
|
|
|
322
352
|
wait "$HARNESS_PID" 2>/dev/null || true
|
|
@@ -327,6 +357,7 @@ OCQA_COMPLETE:{\"actions\":0,\"states\":0,\"issues\":1,\"screens\":\"\",\"outcom
|
|
|
327
357
|
kill -INT "$RECORD_PID" 2>/dev/null || true
|
|
328
358
|
wait "$RECORD_PID" 2>/dev/null || true
|
|
329
359
|
fi
|
|
360
|
+
rm -f "$RECORDING_STARTED_PATH"
|
|
330
361
|
sleep 1
|
|
331
362
|
fi
|
|
332
363
|
|
package/scripts/run-flow.sh
CHANGED
|
@@ -40,6 +40,14 @@ TOKEN="$(date +%s)"
|
|
|
40
40
|
CFG="/tmp/ocqa-flow-$TOKEN.json"
|
|
41
41
|
AI_RESP="/tmp/ocqa-flow-ai-$TOKEN.json"
|
|
42
42
|
AI_DIR="/tmp/ocqa-flow-ai-$TOKEN"
|
|
43
|
+
EVIDENCE_DIR="${TAPP_FLOW_EVIDENCE_DIR:-/tmp/tapp-flow-ios-$TOKEN}"
|
|
44
|
+
RESULT_BUNDLE="$EVIDENCE_DIR/result.xcresult"
|
|
45
|
+
mkdir -p "$EVIDENCE_DIR"
|
|
46
|
+
case "$FLOW" in
|
|
47
|
+
*.json) FLOW_EVIDENCE_SOURCE="$EVIDENCE_DIR/flow-source.json" ;;
|
|
48
|
+
*) FLOW_EVIDENCE_SOURCE="$EVIDENCE_DIR/flow-source.yml" ;;
|
|
49
|
+
esac
|
|
50
|
+
cp "$FLOW" "$FLOW_EVIDENCE_SOURCE"
|
|
43
51
|
python3 - "$CFG" "$APP" "$FLOW_JSON" "$AI_RESP" "$AI_DIR" <<'PY'
|
|
44
52
|
import json, os, sys
|
|
45
53
|
cfg, app, flow_json, ai_resp, ai_dir = sys.argv[1:6]
|
|
@@ -82,9 +90,12 @@ fi
|
|
|
82
90
|
|
|
83
91
|
TEST_RUNNER_OCQA_CONFIG_PATH="$CFG" xcodebuild test-without-building \
|
|
84
92
|
-xctestrun "$XCTR" -destination "platform=iOS Simulator,id=$UDID" \
|
|
85
|
-
-only-testing:"OCQAHarnessUITests/ExplorerTests/testReplayFlow"
|
|
93
|
+
-only-testing:"OCQAHarnessUITests/ExplorerTests/testReplayFlow" \
|
|
94
|
+
-resultBundlePath "$RESULT_BUNDLE" > "$LOG" 2>&1
|
|
86
95
|
[ -n "$RESPONDER_PID" ] && { kill "$RESPONDER_PID" 2>/dev/null; wait "$RESPONDER_PID" 2>/dev/null; }
|
|
87
96
|
|
|
97
|
+
cp "$LOG" "$EVIDENCE_DIR/flow.log"
|
|
98
|
+
python3 "$ROOT/scripts/flow_lib.py" report --json "$LOG" > "$EVIDENCE_DIR/flow-report.json"
|
|
88
99
|
echo ""
|
|
89
100
|
python3 "$ROOT/scripts/flow_lib.py" report "$LOG"
|
|
90
101
|
exit $?
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tapp
|
|
3
|
+
description: Use Tapp to see, drive, explore, and verify real application surfaces on iOS simulators, Android emulators/devices, or the web. Use when a user asks an agent to test an app or UI change, find bugs, inspect or screenshot a screen, exercise a journey, create a replayable flow, gather release evidence, or run the deterministic Tapp gate. Also use when the user mentions Tapp, @aarwitz/tapp, tapp_* tools, .tapp artifacts, or asks whether agent-authored UI actually works.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Tapp
|
|
7
|
+
|
|
8
|
+
Use Tapp as the app's hands and eyes. Work on the real UI surface and show evidence; do not claim a
|
|
9
|
+
screen or journey works from source inspection alone.
|
|
10
|
+
|
|
11
|
+
## Choose the smallest operation
|
|
12
|
+
|
|
13
|
+
| Intent | Operation |
|
|
14
|
+
|---|---|
|
|
15
|
+
| See or screenshot one screen | `open` / `tapp_open_app` |
|
|
16
|
+
| Inspect controls on the current screen | `tree` / `tapp_ui_tree` |
|
|
17
|
+
| Reach a named screen/control | `focus` / `tapp_focus` (source + observed UI Map fast path) |
|
|
18
|
+
| Drive a specific journey | MCP session start → focus or act → end |
|
|
19
|
+
| Find bugs autonomously | `explore` / `tapp_explore` |
|
|
20
|
+
| Preserve a journey | record and save a Flow; replay it deterministically |
|
|
21
|
+
| Decide whether a merge passes policy | `ci`; exploration never decides this |
|
|
22
|
+
|
|
23
|
+
Prefer connected `tapp_*` MCP tools when available: they keep interactive sessions alive and return
|
|
24
|
+
screenshots inline. Otherwise run `npx -y @aarwitz/tapp@latest` from the app repository. Do not require MCP,
|
|
25
|
+
an account, an API key, or a global install for the core workflow.
|
|
26
|
+
|
|
27
|
+
## Start source-connected
|
|
28
|
+
|
|
29
|
+
When the user asks for a general first test of a repository:
|
|
30
|
+
|
|
31
|
+
1. If `.tapp/application-model.json` exists, run `npx -y @aarwitz/tapp@latest explore`.
|
|
32
|
+
2. Otherwise run `npx -y @aarwitz/tapp@latest init . --explore` or call `tapp_init` with
|
|
33
|
+
`{operation:"explore", projectDir:"."}`.
|
|
34
|
+
3. If Tapp returns `target-selection-required`, present its actual choices and ask the user to pick.
|
|
35
|
+
Never guess among multiple targets. Re-run with the selected platform/target exactly as Tapp
|
|
36
|
+
instructs.
|
|
37
|
+
4. If a prerequisite is missing, call `tapp_health` when MCP is connected or run
|
|
38
|
+
`npx -y @aarwitz/tapp@latest doctor`, apply only the stated remediation that is in scope, and
|
|
39
|
+
retry once.
|
|
40
|
+
|
|
41
|
+
For a focused request, use the requested target directly rather than forcing repository onboarding.
|
|
42
|
+
Targets may be a repository path, Xcode container, `.app`, iOS bundle id, APK plus Android app id,
|
|
43
|
+
or owned HTTP(S) URL. Never explore a third-party web property without authorization: exploration
|
|
44
|
+
clicks and types.
|
|
45
|
+
|
|
46
|
+
## Navigate like a source-connected expert
|
|
47
|
+
|
|
48
|
+
When the user names a screen, control, or UI condition, do not discover the app one screenshot at a
|
|
49
|
+
time. Start from the repository source, then use Tapp's observed navigation evidence:
|
|
50
|
+
|
|
51
|
+
1. With MCP, pass the exact request as `focus` to `tapp_session_start`, or call `tapp_focus` in an
|
|
52
|
+
active session. Without MCP, run `npx -y @aarwitz/tapp@latest focus "<exact request>" [target]`.
|
|
53
|
+
2. Tapp searches owned source, reconciles the likely surface with `.tapp/ui-map.json`, and executes
|
|
54
|
+
the shortest runtime-observed route in one call. Read its final tree before visual assertions.
|
|
55
|
+
3. If Tapp returns source evidence but no replayable route, inspect the cited file/line and relevant
|
|
56
|
+
router/navigation source. Do not wander blindly or invent a path; ground the map or drive only a
|
|
57
|
+
route supported by that source evidence.
|
|
58
|
+
|
|
59
|
+
A fresh repository needs one grounding exploration before `focus` can replay a route. Source can
|
|
60
|
+
locate an unobserved surface, but it never authorizes unobserved taps.
|
|
61
|
+
|
|
62
|
+
Source establishes intent and location; the real UI establishes behavior. A URL-only target has no
|
|
63
|
+
source advantage and correctly falls back to runtime observation.
|
|
64
|
+
|
|
65
|
+
## Observe honestly
|
|
66
|
+
|
|
67
|
+
Exploration returns findings, coverage, evidence, and `inconclusive`; it does not return a score or
|
|
68
|
+
ship verdict. Report:
|
|
69
|
+
|
|
70
|
+
- target and platform;
|
|
71
|
+
- screens/actions and whether coverage was conclusive;
|
|
72
|
+
- deterministic versus advisory finding counts;
|
|
73
|
+
- each important finding and its evidence/report path;
|
|
74
|
+
- what Tapp explicitly did not check.
|
|
75
|
+
|
|
76
|
+
If `inconclusive: true`, explain the blocker. A login wall or missing test data is not a pass. Ask for
|
|
77
|
+
credentials or launch configuration instead of rerunning blindly. Do not infer content accuracy,
|
|
78
|
+
privacy, brand consistency, or business guarantees from a generic crawl; those require a reviewed
|
|
79
|
+
Flow, Scenario, contract, verifier, or human review.
|
|
80
|
+
|
|
81
|
+
When a screenshot path is printed, open it with the client's image-reading tool before describing
|
|
82
|
+
the screen. For web, use `--watch` when the human wants to follow Tapp's controlled browser. For iOS,
|
|
83
|
+
point the human to the report's exploration recording when available.
|
|
84
|
+
|
|
85
|
+
## Drive safely
|
|
86
|
+
|
|
87
|
+
After the focused fast path, read returned `elements[]` before any remaining action, target accessibility
|
|
88
|
+
ids or visible labels, check `hittable`, tap a field before typing, and wait for navigation or async
|
|
89
|
+
content. Use coordinates only as a last resort. End the session when finished.
|
|
90
|
+
|
|
91
|
+
Do not edit the app merely because testing found a defect unless the user also asked for a fix. State
|
|
92
|
+
what the evidence proves and what remains untested.
|
|
93
|
+
|
|
94
|
+
Read [references/commands.md](references/commands.md) only when exact CLI/MCP syntax, Flow replay,
|
|
95
|
+
credentials, or platform prerequisites are needed.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Tapp command reference
|
|
2
|
+
|
|
3
|
+
## Plain CLI
|
|
4
|
+
|
|
5
|
+
Run from the application repository. `[target]` is optional when Tapp can read the repository model
|
|
6
|
+
or detect one unambiguous target.
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npx -y @aarwitz/tapp@latest init . --explore
|
|
10
|
+
npx -y @aarwitz/tapp@latest explore [target]
|
|
11
|
+
npx -y @aarwitz/tapp@latest focus "Save storefront settings visible above keyboard" [target]
|
|
12
|
+
npx -y @aarwitz/tapp@latest open [target]
|
|
13
|
+
npx -y @aarwitz/tapp@latest tree [target] --json
|
|
14
|
+
npx -y @aarwitz/tapp@latest shot
|
|
15
|
+
npx -y @aarwitz/tapp@latest report latest
|
|
16
|
+
npx -y @aarwitz/tapp@latest doctor
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Platform examples:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
# Web: Tapp may build/start/stop a source target; --watch is human-visible.
|
|
23
|
+
npx -y @aarwitz/tapp@latest explore --platform web --target website --watch
|
|
24
|
+
npx -y @aarwitz/tapp@latest explore https://staging.example.com
|
|
25
|
+
|
|
26
|
+
# iOS: source repo, .app, or bundle id.
|
|
27
|
+
npx -y @aarwitz/tapp@latest explore MyApp.xcodeproj --platform ios
|
|
28
|
+
npx -y @aarwitz/tapp@latest open com.example.MyApp --platform ios
|
|
29
|
+
|
|
30
|
+
# Android: app id is required; APK is optional if already installed.
|
|
31
|
+
npx -y @aarwitz/tapp@latest explore app-debug.apk --platform android --app-id com.example.app
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Focused web evidence can perform one semantic interaction and wait for async content:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx -y @aarwitz/tapp@latest open https://example.com --tap "Not now" --wait-for "Dashboard"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## MCP mapping
|
|
41
|
+
|
|
42
|
+
- `tapp_init`: inspect or initialize a source repository; `operation:"explore"` prepares and explores.
|
|
43
|
+
- `tapp_build`: build and install an iOS app without needing its bundle id first.
|
|
44
|
+
- `tapp_open_app`: launch and return a screen summary plus inline screenshot.
|
|
45
|
+
- `tapp_focus`: source-locate a named screen/control and execute the shortest observed route in the active session.
|
|
46
|
+
- `tapp_ui_tree` / `tapp_screenshot`: inspect the current real surface.
|
|
47
|
+
- `tapp_session_start` → `tapp_session_act` → `tapp_session_end`: drive one persistent journey.
|
|
48
|
+
- `tapp_explore`: autonomous iOS, Android, or web exploration; observation only.
|
|
49
|
+
- `tapp_flow_save` / `tapp_flow_run`: save a driven journey and replay it deterministically.
|
|
50
|
+
- `tapp_release_contract`: validate, compile, or run a reviewed business guarantee.
|
|
51
|
+
- `tapp_ci_setup`: create a target-scoped baseline or reviewable CI installation.
|
|
52
|
+
|
|
53
|
+
An iOS no-bundle-id MCP path is `tapp_build {projectDir:"."}` followed by `tapp_explore` with the
|
|
54
|
+
returned `bundleId`. Android uses `androidAppId` and optional `apkPath`; web uses `url` or
|
|
55
|
+
source-connected `tapp_init`.
|
|
56
|
+
|
|
57
|
+
## Interactive session loop
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
tapp_session_start {appBundleId:"com.example.app", focus:"Save storefront settings visible above keyboard", projectDir:"."}
|
|
61
|
+
tapp_focus {query:"Save storefront settings visible above keyboard"}
|
|
62
|
+
tapp_session_act {action:"tap", id:"Email"}
|
|
63
|
+
tapp_session_act {action:"type", text:"qa@example.com"}
|
|
64
|
+
tapp_session_act {action:"tap", id:"Password"}
|
|
65
|
+
tapp_session_act {action:"type", text:"..."}
|
|
66
|
+
tapp_session_act {action:"tap", id:"Sign In"}
|
|
67
|
+
tapp_session_act {action:"wait", text:"Home", timeoutMs:10000}
|
|
68
|
+
tapp_screenshot
|
|
69
|
+
tapp_session_end
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Android sessions use `androidAppId`, optional `apkPath`, and the same action loop.
|
|
73
|
+
|
|
74
|
+
## Credentials and test configuration
|
|
75
|
+
|
|
76
|
+
For autonomous exploration, pass test-only values when authorized:
|
|
77
|
+
|
|
78
|
+
- CLI: `--email`, `--password`, repeated `--launch-arg`, and JSON `--launch-env`.
|
|
79
|
+
- MCP: `testEmail`, `testPassword`, `inputOverrides`, `appLaunchArgs`, `appLaunchEnv`, or explicit
|
|
80
|
+
`loginSteps`.
|
|
81
|
+
|
|
82
|
+
Do not persist secrets in `.tapp/`. If the result reports input fields and no values were supplied,
|
|
83
|
+
ask the user rather than pretending the explored surface was complete.
|
|
84
|
+
|
|
85
|
+
## Replay and gating
|
|
86
|
+
|
|
87
|
+
Flow YAML belongs under `.tapp/flows/` and can replay without a model or API key:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npx -y @aarwitz/tapp@latest flow run .tapp/flows/smoke.yml
|
|
91
|
+
npx -y @aarwitz/tapp@latest ci
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`tapp explore` observes. `tapp ci` applies versioned deterministic policy to evidence, selected
|
|
95
|
+
Flows/Scenarios/contracts, coverage, and any target-scoped baseline. Its outcomes are `pass`, `fail`,
|
|
96
|
+
or `inconclusive`; both `fail` and `inconclusive` block a merge.
|
|
97
|
+
|
|
98
|
+
## Platform prerequisites
|
|
99
|
+
|
|
100
|
+
- iOS: macOS, Xcode, and a booted simulator. First use builds a cached harness under `~/.tapp`.
|
|
101
|
+
- Android: `adb` and a connected authorized emulator/device.
|
|
102
|
+
- Web: Playwright and Chromium. If Tapp reports the browser missing, run
|
|
103
|
+
`npx playwright install chromium` and retry.
|
|
104
|
+
|
|
105
|
+
Captures and screenshots are stored under `~/.tapp/captures/` and `~/.tapp/shots/`.
|