Autonomous Discovery
luotsi discover is the first autonomous layer over Luotsi’s existing inspect, run, and replay surfaces. It explores a real Android app through the same host-side device runtime, writes an auditable discovery trace, and keeps JSON scenarios as the stable artifact to review before CI.
luotsi discover --device <serial> --package <app.id> --budget 5mWhat it writes
Section titled “What it writes”Discovery writes into the normal Luotsi artifact root:
discovery-map.jsonwith observed screens, active tap policy, safe action candidates, policy-skipped candidates, transitions, stop reason, and scenario-candidate provenancediscovery-events.jsonlwith line-orientedluotsi-discovery-event.v1records for agents and CIsession-timeline.jsonlandsession-replay.jsonsoreplay open,replay timeline,replay graph, andreplay scenario-draftcan inspect the discovery run through the normal replay surfacescenario-candidates/discovery-candidate.jsonas a review-required starter scenario- the normal
index.mdandindex.htmlartifact browser entries
The scenario candidate is intentionally not a finished test. Review coordinates, waits, assertions, and safety before checking it in.
How it explores
Section titled “How it explores”Discovery starts the target package unless --no-start is supplied, reads screen state, applies built-in and configured tap policy, ranks visible clickable elements deterministically, skips obvious destructive labels, taps one safe action at a time, records the resulting transition, and follows changed screens up to --max-depth. When a branch is exhausted, reaches the depth limit, cycles to an already-active screen, or the run ends, discovery backtracks with KEYCODE_BACK and records that backtrack in the event log and generated scenario candidate.
Useful bounds:
luotsi discover --device <serial> --package <app.id> --activity .MainActivity --budget 10m --max-actions 40 --max-depth 2 --output-dir artifactsUseful policy guardrails:
luotsi discover --device <serial> --package <app.id> --budget 5m --allow-text "Home,Search,Settings" --deny-text "Sign out,Delete" --deny-resource-id destructive --deny-class android.widget.SwitchPolicy patterns are comma- or semicolon-separated substring matches. --allow-text limits tapping to candidates whose label, text, or content description matches at least one pattern. --deny-text, --deny-resource-id, and --deny-class remove matching candidates before ranking. Skips are preserved as action_skipped events and as skipped candidates on each screen in discovery-map.json.
Stop reasons include no_new_actions, budget_expired, action_limit_reached, depth_limit_reached, action_failed, screen_state_failed, and backtrack_failed.
Promotion flow
Section titled “Promotion flow”Use discovery to find and explain behavior, then promote only reviewed behavior into deterministic scenarios:
luotsi discover --device <serial> --package <app.id> --budget 5m --output-dir artifactsluotsi replay packet --last --artifacts artifactsluotsi replay packet --last --artifacts artifacts --checkluotsi replay open --last --artifacts artifacts --dry-runluotsi scenario-validate --file artifacts/<run>/scenario-candidates/discovery-candidate.jsonluotsi run --file artifacts/<run>/scenario-candidates/discovery-candidate.json --device <serial>luotsi replay timeline --artifacts artifacts/<run> --type command_resultluotsi artifacts open --last --artifacts artifactsStart with replay packet after discovery so Luotsi writes the durable run-summary.json and run-summary.md packet before any browser or broad artifact browsing. Use replay packet --check when that packet came from CI, support, or another agent, then replay open --dry-run when a human wants the replay front door response without launching a browser. Use artifacts open --last only when you specifically need to browse every captured file.