@aarwitz/tapp 0.16.5 → 0.17.0-rc.2
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 +26 -21
- package/Harness/OCQAHarnessUITests/ExplorerTests.swift +62 -22
- package/README.md +64 -67
- package/bin/tapp.js +168 -45
- 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 +271 -0
- package/docs/scenarios.md +95 -0
- package/mcp-server/src/android-driver.js +15 -2
- package/mcp-server/src/android-explorer.js +54 -12
- package/mcp-server/src/application-model.js +9 -8
- 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 +20 -6
- package/mcp-server/src/index.js +182 -67
- 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 +2 -2
- 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 +9 -8
- package/scripts/platform-gate.js +11 -5
- package/scripts/quick-capture.sh +72 -38
- package/scripts/run-flow.sh +1 -1
package/scripts/quick-capture.sh
CHANGED
|
@@ -19,7 +19,7 @@ PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
|
|
19
19
|
# accidentally reuse stale markers). TAPP_HOME redirects all writable output otherwise —
|
|
20
20
|
# set by the `tapp` CLI when running as an installed npm package, where the package dir
|
|
21
21
|
# must stay read-only. Unset (repo dev flow), everything lands in the repo as before.
|
|
22
|
-
TAPP_RUNTIME_HOME="${TAPP_HOME
|
|
22
|
+
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
|
|
@@ -262,58 +262,92 @@ case "$MODE" in
|
|
|
262
262
|
echo "Running autonomous exploration ($MAX_ACTIONS actions, timeout: ${EXPLORE_TIMEOUT}s, app: $APP_BUNDLE)..."
|
|
263
263
|
ensure_harness_built "$SIM_NAME"
|
|
264
264
|
|
|
265
|
-
#
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
if
|
|
273
|
-
|
|
274
|
-
|
|
265
|
+
# XCUITest can block inside `app.launch()` until the outer watchdog when the target dies in its
|
|
266
|
+
# initializer, producing a misleading timeout after minutes. For an ordinary unconfigured
|
|
267
|
+
# launch, probe the target directly first and verify that the returned PID survives a short
|
|
268
|
+
# settle window. (Configured launch args/env skip this probe because simctl would not reproduce
|
|
269
|
+
# that launch contract.) The harness still performs its own fresh launch for healthy apps.
|
|
270
|
+
PREFLIGHT_CRASH=0
|
|
271
|
+
PREFLIGHT_OUTPUT=""
|
|
272
|
+
if [[ -z "${OCQA_APP_LAUNCH_ARGS_JSON:-}" && -z "${OCQA_APP_LAUNCH_ENV_JSON:-}" ]]; then
|
|
273
|
+
xcrun simctl terminate "$UDID" "$APP_BUNDLE" >/dev/null 2>&1 || true
|
|
274
|
+
PREFLIGHT_OUTPUT="$(xcrun simctl launch "$UDID" "$APP_BUNDLE" 2>&1 || true)"
|
|
275
|
+
PREFLIGHT_PID="$(echo "$PREFLIGHT_OUTPUT" | sed -n 's/.*: \([0-9][0-9]*\)$/\1/p' | tail -1)"
|
|
276
|
+
if [[ -n "$PREFLIGHT_PID" ]]; then
|
|
277
|
+
sleep 2
|
|
278
|
+
if ! kill -0 "$PREFLIGHT_PID" 2>/dev/null; then PREFLIGHT_CRASH=1; fi
|
|
279
|
+
fi
|
|
280
|
+
xcrun simctl terminate "$UDID" "$APP_BUNDLE" >/dev/null 2>&1 || true
|
|
275
281
|
fi
|
|
276
282
|
|
|
277
|
-
# Run exploration with watchdog timeout to avoid silent hangs.
|
|
278
283
|
local_output_file="$CAPTURE_DIR/harness-output.txt"
|
|
279
|
-
run_harness_test "testAutonomousExploration" "$SIM_NAME" "$APP_BUNDLE" "$MAX_ACTIONS" "$EXPLORE_TIMEOUT" > "$local_output_file" 2>&1 &
|
|
280
|
-
HARNESS_PID=$!
|
|
281
|
-
|
|
282
|
-
START_TS=$(date +%s)
|
|
283
284
|
TIMED_OUT=0
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
285
|
+
RECORD_PID=""
|
|
286
|
+
if [[ "$PREFLIGHT_CRASH" -eq 1 ]]; then
|
|
287
|
+
OUTPUT="OCQA_ISSUE:{\"type\":\"crash\",\"severity\":\"critical\",\"title\":\"App crashed during launch preflight\",\"screen\":\"Launch\",\"step\":0}
|
|
288
|
+
OCQA_COMPLETE:{\"actions\":0,\"states\":0,\"issues\":1,\"screens\":\"\",\"outcome\":\"launch_crash\"}"
|
|
289
|
+
printf '%s\n%s\n' "$PREFLIGHT_OUTPUT" "$OUTPUT" > "$local_output_file"
|
|
290
|
+
echo "WARNING: Target process exited during launch preflight; recorded a crash instead of waiting for the exploration timeout." >&2
|
|
291
|
+
else
|
|
292
|
+
|
|
293
|
+
# Start video recording in background
|
|
294
|
+
cleanup_stale_recorders "$UDID"
|
|
295
|
+
if xcrun simctl io "$UDID" recordVideo --codec=h264 "$CAPTURE_DIR/exploration.mov" & then
|
|
296
|
+
RECORD_PID=$!
|
|
297
|
+
fi
|
|
298
|
+
sleep 0.5
|
|
299
|
+
if ! kill -0 "$RECORD_PID" 2>/dev/null; then
|
|
300
|
+
echo "WARNING: Could not start simulator video recording. Continuing without video." >&2
|
|
301
|
+
RECORD_PID=""
|
|
293
302
|
fi
|
|
294
|
-
sleep 2
|
|
295
|
-
done
|
|
296
303
|
|
|
297
|
-
|
|
298
|
-
|
|
304
|
+
# Run exploration with watchdog timeout to avoid silent hangs.
|
|
305
|
+
run_harness_test "testAutonomousExploration" "$SIM_NAME" "$APP_BUNDLE" "$MAX_ACTIONS" "$EXPLORE_TIMEOUT" > "$local_output_file" 2>&1 &
|
|
306
|
+
HARNESS_PID=$!
|
|
307
|
+
|
|
308
|
+
START_TS=$(date +%s)
|
|
309
|
+
while kill -0 "$HARNESS_PID" 2>/dev/null; do
|
|
310
|
+
NOW_TS=$(date +%s)
|
|
311
|
+
ELAPSED=$((NOW_TS - START_TS))
|
|
312
|
+
if [[ "$ELAPSED" -ge "$EXPLORE_TIMEOUT" ]]; then
|
|
313
|
+
TIMED_OUT=1
|
|
314
|
+
kill -TERM "$HARNESS_PID" 2>/dev/null || true
|
|
315
|
+
sleep 2
|
|
316
|
+
kill -KILL "$HARNESS_PID" 2>/dev/null || true
|
|
317
|
+
break
|
|
318
|
+
fi
|
|
319
|
+
sleep 2
|
|
320
|
+
done
|
|
321
|
+
|
|
322
|
+
wait "$HARNESS_PID" 2>/dev/null || true
|
|
323
|
+
OUTPUT="$(cat "$local_output_file" 2>/dev/null || true)"
|
|
299
324
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
325
|
+
# Stop recording
|
|
326
|
+
if [[ -n "$RECORD_PID" ]]; then
|
|
327
|
+
kill -INT "$RECORD_PID" 2>/dev/null || true
|
|
328
|
+
wait "$RECORD_PID" 2>/dev/null || true
|
|
329
|
+
fi
|
|
330
|
+
sleep 1
|
|
304
331
|
fi
|
|
305
|
-
sleep 1
|
|
306
332
|
|
|
307
333
|
# Parse OCQA_ markers
|
|
308
334
|
echo "$OUTPUT" | grep "^OCQA_" > "$CAPTURE_DIR/ocqa-markers.txt" || true
|
|
309
335
|
if [[ "$TIMED_OUT" -eq 1 ]]; then
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
336
|
+
# The caller's wall-clock budget expiring means the evidence is partial; it is not proof that
|
|
337
|
+
# the app itself is slow or hung. Preserve observed coverage in the terminal marker and let
|
|
338
|
+
# report.js classify the run as inconclusive instead of inventing an app finding.
|
|
339
|
+
TIMED_ACTIONS="$(echo "$OUTPUT" | sed -n 's/^OCQA_PROGRESS:{"action":\([0-9][0-9]*\).*/\1/p' | tail -1)"
|
|
340
|
+
TIMED_STATES="$(echo "$OUTPUT" | sed -n 's/^OCQA_PROGRESS:.*"states":\([0-9][0-9]*\).*/\1/p' | tail -1)"
|
|
341
|
+
TIMED_ISSUES="$(echo "$OUTPUT" | grep -c '^OCQA_ISSUE:' || true)"
|
|
342
|
+
TIMED_ACTIONS="${TIMED_ACTIONS:-0}"
|
|
343
|
+
TIMED_STATES="${TIMED_STATES:-0}"
|
|
344
|
+
TIMED_ISSUES="${TIMED_ISSUES:-0}"
|
|
345
|
+
echo "OCQA_COMPLETE:{\"actions\":$TIMED_ACTIONS,\"states\":$TIMED_STATES,\"issues\":$TIMED_ISSUES,\"screens\":\"\",\"timedOut\":true,\"timeoutSeconds\":$EXPLORE_TIMEOUT}" >> "$CAPTURE_DIR/ocqa-markers.txt"
|
|
346
|
+
echo "WARNING: Exploration reached its ${EXPLORE_TIMEOUT}s time budget; evidence is partial" >&2
|
|
313
347
|
fi
|
|
314
348
|
echo "$OUTPUT" > "$CAPTURE_DIR/full-output.txt"
|
|
315
349
|
|
|
316
|
-
COMPLETE_LINE=$(
|
|
350
|
+
COMPLETE_LINE=$(grep "OCQA_COMPLETE" "$CAPTURE_DIR/ocqa-markers.txt" | tail -1 || true)
|
|
317
351
|
if [[ -n "$COMPLETE_LINE" ]]; then
|
|
318
352
|
echo ""
|
|
319
353
|
echo "Exploration complete: $COMPLETE_LINE"
|
package/scripts/run-flow.sh
CHANGED
|
@@ -26,7 +26,7 @@ UDID="$(xcrun simctl list devices booted -j 2>/dev/null | python3 -c 'import sys
|
|
|
26
26
|
[ -z "$UDID" ] && { echo "❌ No booted simulator."; exit 2; }
|
|
27
27
|
# When run through the installed `tapp` CLI, the harness cache lives under TAPP_HOME.
|
|
28
28
|
XCTR=""
|
|
29
|
-
TAPP_RUNTIME_HOME="${TAPP_HOME
|
|
29
|
+
TAPP_RUNTIME_HOME="${TAPP_HOME:-}"
|
|
30
30
|
[ -n "$TAPP_RUNTIME_HOME" ] && XCTR="$(find "$TAPP_RUNTIME_HOME/harness-derived/Build/Products" -name '*.xctestrun' 2>/dev/null | head -1)"
|
|
31
31
|
[ -z "$XCTR" ] && XCTR="$(find "$HOME/Library/Developer/Xcode/DerivedData/OCQAHarness-"*/Build/Products -name '*.xctestrun' 2>/dev/null | head -1)"
|
|
32
32
|
[ -z "$XCTR" ] && XCTR="$(find /tmp/tapp-harness-derived/Build/Products -name '*.xctestrun' 2>/dev/null | head -1)"
|