@1aboveio/skills 1.0.17 → 1.0.19

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.
Files changed (99) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/.codex-plugin/resources.json +175 -141
  3. package/README.md +1 -1
  4. package/package.json +5 -4
  5. package/skills/app-dev/airflow/SKILL.md +1 -1
  6. package/skills/app-dev/android-development/SKILL.md +14 -12
  7. package/skills/app-dev/android-development/references/diagnosis.md +4 -6
  8. package/skills/app-dev/android-development/references/gotchas.md +3 -9
  9. package/skills/app-dev/android-development/references/init.md +5 -2
  10. package/skills/app-dev/android-development/references/setup.md +2 -1
  11. package/skills/app-dev/android-development/references/ui-journeys.md +12 -127
  12. package/skills/app-dev/android-development/scripts/failure_capture.py +23 -84
  13. package/skills/app-dev/android-development/scripts/init.mjs +2 -1
  14. package/skills/app-dev/android-development/scripts/maestro_failure.py +43 -387
  15. package/skills/app-dev/android-development/scripts/test_maestro_failure.py +113 -424
  16. package/skills/app-dev/app-debug/SKILL.md +1 -1
  17. package/skills/app-dev/better-auth/SKILL.md +1 -1
  18. package/skills/app-dev/data-catalog/SKILL.md +1 -1
  19. package/skills/app-dev/data-quality/SKILL.md +1 -1
  20. package/skills/app-dev/ios-foundation/SKILL.md +1 -1
  21. package/skills/app-dev/maestro/LICENSE +3 -0
  22. package/skills/app-dev/maestro/SKILL.md +112 -0
  23. package/skills/app-dev/maestro/references/android-connection.md +54 -0
  24. package/skills/app-dev/maestro/references/authoring.md +113 -0
  25. package/skills/app-dev/maestro/references/diagnosis.md +50 -0
  26. package/skills/app-dev/maestro/references/evidence.md +74 -0
  27. package/skills/app-dev/maestro/references/journeys.md +100 -0
  28. package/skills/app-dev/maestro/references/migration.md +35 -0
  29. package/skills/app-dev/maestro/release-check.mjs +95 -0
  30. package/skills/app-dev/maestro/scripts/failure_record.py +110 -0
  31. package/skills/app-dev/maestro/scripts/maestro_failure.py +481 -0
  32. package/skills/app-dev/maestro/scripts/test_maestro_failure.py +710 -0
  33. package/skills/app-dev/monorepo/SKILL.md +1 -1
  34. package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
  35. package/skills/app-dev/prisma-setup/SKILL.md +1 -1
  36. package/skills/app-dev/pyspark/SKILL.md +1 -1
  37. package/skills/app-dev/python-backend/SKILL.md +1 -1
  38. package/skills/app-dev/shadcn/SKILL.md +1 -1
  39. package/skills/app-dev/zod-v4/SKILL.md +1 -1
  40. package/skills/cicd/cloud-build/SKILL.md +1 -1
  41. package/skills/cicd/cloud-debug/SKILL.md +1 -1
  42. package/skills/cicd/cloud-deploy/SKILL.md +1 -1
  43. package/skills/cicd/docker/SKILL.md +1 -1
  44. package/skills/cicd/github-actions/SKILL.md +1 -1
  45. package/skills/cicd/github-flow/SKILL.md +1 -1
  46. package/skills/cicd/google-cloud/SKILL.md +1 -1
  47. package/skills/cicd/mergify/SKILL.md +1 -1
  48. package/skills/cicd/podman/SKILL.md +1 -1
  49. package/skills/content/article-review/SKILL.md +1 -1
  50. package/skills/content/article-to-image/SKILL.md +1 -1
  51. package/skills/content/flowchart-svg/SKILL.md +1 -1
  52. package/skills/content/image-gen/SKILL.md +1 -1
  53. package/skills/content/mermaid/SKILL.md +1 -1
  54. package/skills/content/wechat-article-writer/SKILL.md +1 -1
  55. package/skills/content/wechat-publisher/SKILL.md +1 -1
  56. package/skills/content/wechat-search/SKILL.md +1 -1
  57. package/skills/content/xai-search/SKILL.md +1 -1
  58. package/skills/core/distill-writing/SKILL.md +1 -1
  59. package/skills/core/doc-to-md/SKILL.md +1 -1
  60. package/skills/core/editorial-review/SKILL.md +1 -1
  61. package/skills/core/house-style/SKILL.md +1 -1
  62. package/skills/core/plain-language/SKILL.md +1 -1
  63. package/skills/core/polish-cn/SKILL.md +1 -1
  64. package/skills/core/reg-parser/SKILL.md +1 -1
  65. package/skills/core/terminology/SKILL.md +1 -1
  66. package/skills/core/write-doc/SKILL.md +1 -1
  67. package/skills/core/write-report/SKILL.md +1 -1
  68. package/skills/engineering/better-review/SKILL.md +1 -1
  69. package/skills/engineering/e2e-test/SKILL.md +1 -1
  70. package/skills/engineering/engineering/SKILL.md +1 -1
  71. package/skills/engineering/engineering-runtime/SKILL.md +1 -1
  72. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  73. package/skills/engineering/ensure-coverage/SKILL.md +1 -1
  74. package/skills/engineering/golden-path/SKILL.md +1 -1
  75. package/skills/engineering/harness-runtime/SKILL.md +1 -1
  76. package/skills/engineering/harness-runtime/agent-catalog.mjs +44 -11
  77. package/skills/engineering/harness-runtime/contracts.md +1 -1
  78. package/skills/engineering/resolve-issues/SKILL.md +4 -2
  79. package/skills/engineering/resolve-issues/references/preflight.md +17 -3
  80. package/skills/engineering/resolve-issues/references/retention.md +162 -0
  81. package/skills/engineering/resolve-issues/references/workspaces.md +40 -10
  82. package/skills/engineering/resolve-issues/scripts/daily-cleanup.mjs +169 -0
  83. package/skills/engineering/resolve-issues/scripts/resource-formats.mjs +625 -0
  84. package/skills/engineering/resolve-issues/scripts/retention-lock.mjs +548 -0
  85. package/skills/engineering/resolve-issues/scripts/retention-plans.mjs +57 -0
  86. package/skills/engineering/resolve-issues/scripts/retention.mjs +2314 -0
  87. package/skills/engineering/resolve-release/SKILL.md +1 -1
  88. package/skills/engineering/rush-issues/SKILL.md +1 -1
  89. package/skills/engineering/rush-release/SKILL.md +1 -1
  90. package/skills/engineering/test-quality/SKILL.md +1 -1
  91. package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
  92. package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
  93. package/skills/risk-compliance/contract-review/SKILL.md +1 -1
  94. package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
  95. package/skills/risk-compliance/fraud-detection/SKILL.md +1 -1
  96. package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
  97. package/skills/risk-compliance/portfolio-payment-analysis/SKILL.md +1 -1
  98. package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
  99. package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
@@ -0,0 +1,112 @@
1
+ ---
2
+ name: maestro
3
+ description: "Design, run, debug and migrate mobile E2E journeys with Maestro: complete flows and subflows, selectors, parameters, exclusive UI-driver ownership, non-UI authentication/backend helpers and failure evidence. Use for Maestro YAML/CLI/MCP work, slow fragmented mobile journeys, UiAutomation driver collisions, or replacing a hybrid Python/uiautomator2 UI harness. Android-first; use platform-neutral flow guidance for iOS only with its verified device/runtime contract. NOT for Android provisioning/builds (android-development), iOS setup (ios-foundation), browser Playwright tests (e2e-test), or CI workflow YAML (github-actions)."
4
+ release-version: 0.49.1
5
+ ---
6
+ **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
7
+ # Maestro
8
+
9
+ Make the journey, not each tap, the unit of UI execution. Maestro owns ordinary app UI;
10
+ the existing runner owns resources and cleanup; existing non-UI helpers establish backend
11
+ and platform facts. Preserve the repository's acceptance criteria and selected checkpoint.
12
+
13
+ ## Read the assignment
14
+
15
+ Read applicable `AGENTS.md`, `CONTRIBUTING.md`, test guidance and relevant ADRs from the
16
+ assigned workspace. Resolve the actual case, caller, source, app artifact, served code,
17
+ device identifier and runtime owner before execution. Follow nested guidance for touched
18
+ paths. Existing policy wins; missing guidance uses the defaults here, while unreadable
19
+ guidance or an unresolved ownership conflict is reported before affected operations.
20
+
21
+ This skill writes requested flows, helpers and tests, not project conventions or agent
22
+ settings on discovery. It has no `init` command and installs no tools automatically.
23
+ For missing Android workflow conventions, offer `android-development init` once without
24
+ blocking the task; that skill owns its authorized writes. A task override lasts only for
25
+ the assignment and survives context reload, not as a saved policy change.
26
+
27
+ ## Work loop
28
+
29
+ 1. **Select proof.** Name the user journey and its required observations. Map each to a
30
+ UI assertion, non-UI helper or specifically justified native case using
31
+ [the test split](references/journeys.md#split-by-responsibility). Reuse sufficient
32
+ existing proof; do not add a matrix or gate because Maestro is being used.
33
+ 2. **Use the owned runtime.** Consume the existing runner's device assignment, app/code
34
+ identity, private endpoints and disposable fixture contract. For Android environment
35
+ work use `android-development`; for iOS setup use `ios-foundation`. Neither a new flow
36
+ nor this skill authorizes another emulator, dependency install or fixture lifecycle.
37
+ 3. **Compose the journey.** Prefer one top-level flow invoking reusable `runFlow` subflows
38
+ within one Maestro invocation. Group contiguous UI work; split only for a real external
39
+ or native checkpoint. Read [journeys](references/journeys.md) before authoring or running.
40
+ 4. **Verify the real path.** Test actual case dispatch, caller parameters, production
41
+ selectors and fixture composition before allocating a device when host checks suffice.
42
+ Then run the selected case through the maintained local/CI caller on the identified app.
43
+ Syntax checks, mocks, a readiness probe or YAML files alone are not execution proof.
44
+ 5. **Diagnose and correct.** At failure, identify the earliest failed stage and retain its
45
+ evidence before teardown. Use [diagnosis](references/diagnosis.md); confirm the original
46
+ reproduction after the correction and repeat only invalidated checks.
47
+ 6. **Report and finish.** Name executed cases/assertions, source/app identities, results,
48
+ remaining requirements and cleanup or explicit runtime handoff. Follow
49
+ [evidence](references/evidence.md); a converter's success is not a journey pass.
50
+
51
+ For an authorized existing-harness conversion, read [migration](references/migration.md).
52
+ An installed Maestro CLI or a broken harness alone does not authorize a migration.
53
+
54
+ ## One UI driver
55
+
56
+ A Maestro-only case starts no uiautomator2 client in its parent, child, observer or failure
57
+ capture. A reader that acquires Android UI automation is still a competing driver.
58
+ Use Maestro's hierarchy/artifacts and suitable non-conflicting platform probes instead.
59
+
60
+ During migration, a necessary handoff goes through the process that actually launched the
61
+ old server: verify ownership, stop and confirm release, run Maestro to completion, then
62
+ reclaim only if the next native phase needs it. A joined child client cannot necessarily
63
+ stop the parent's server. Keep the existing security/currentness checks and never stop a
64
+ peer. Treat this as transitional, not the default around every action.
65
+
66
+ ## Framework responsibilities
67
+
68
+ | Responsibility | Owner | Rule |
69
+ | --- | --- | --- |
70
+ | Setup, source/app identity, timeouts and cleanup | Existing runner | One authoritative resource owner per device; retain its emulator/ADB/Metro/backend and fixture lifecycle |
71
+ | Ordinary app interactions and UI assertions | Maestro | No uiautomator2 server starts in this case's parent, child, observer or failure capture |
72
+ | Financial and backend verification | Existing backend test code | Verify real records, amounts, request counts and isolation, not just success text; preserve required checkpoint order |
73
+ | Specialized native assertions requiring another UI driver | Existing native test code | Separate exclusive case/phase; Maestro is stopped and its registration released before the native driver starts |
74
+ | Logic and module tests | Existing host/JVM tests | Run without an emulator where sufficient; do not convert these tests to UI journeys |
75
+
76
+ The runner may use Python or another existing language. It orchestrates resources and
77
+ case/checkpoint boundaries, not individual taps. Backend helpers remain non-UI; a reader
78
+ that acquires UI automation belongs in the exclusive native path. Suitable non-conflicting
79
+ platform probes may run during a Maestro case, but do not silently substitute them for
80
+ required native proof. Grouping UI actions never moves a financial guard past its action.
81
+
82
+ This skill owns the Maestro side of that split. `android-development` owns Android runtime
83
+ and build work; `ios-foundation` owns iOS setup without Android addressing assumptions.
84
+ Use `test-quality` for test honesty, `e2e-test` for browser journeys and `github-actions`
85
+ for workflow implementation. This is a test-framework contract, not an agent-role policy.
86
+
87
+ Maestro supports focused-element assertions; focus alone is not a reason to keep another
88
+ driver. App stop/relaunch does not automatically prove OS process death, reboot, continuous
89
+ focus retention, physical hardware or payment-provider acceptance. Match each claim to its
90
+ observation. A multi-device coordinator may orchestrate separate Maestro journeys, but
91
+ independent shards do not establish an ordered cross-device interaction.
92
+
93
+ The skill ships no Maestro binary and no resource runner. Reuse the repo-pinned CLI and
94
+ check its actual `--help`/version for flags and artifact shape. Shared flow guidance can
95
+ apply to iOS, but this extraction does not certify iOS provisioning, transport or native
96
+ assertions. Keep that evidence gap explicit.
97
+
98
+ ## References
99
+
100
+ - [Journeys and helpers](references/journeys.md): test split, state, selectors and invocation.
101
+ - [Flow authoring](references/authoring.md): a complete flow/subflow example and parameter checks.
102
+ - [Diagnosis](references/diagnosis.md): driver startup, action failures and useful comparisons.
103
+ - [Android connection](references/android-connection.md): direct adbd versus ADB-server routing and JVM key lookup.
104
+ - [Evidence](references/evidence.md): reports, converter and original-status preservation.
105
+ - [Migration](references/migration.md): replace hybrid UI paths without losing assertions.
106
+
107
+ ## Sources
108
+
109
+ - [Nested flows](https://docs.maestro.dev/maestro-flows/flow-control-and-logic/nested-flows)
110
+ - [State selectors](https://docs.maestro.dev/reference/selectors/state-selectors)
111
+ - [JavaScript HTTP requests](https://docs.maestro.dev/advanced/javascript/make-http-requests)
112
+ - [Launch behavior](https://docs.maestro.dev/reference/commands-available/launchapp)
@@ -0,0 +1,54 @@
1
+ # Android connection and driver startup
2
+
3
+ Read this when ADB sees the device but Maestro cannot find/authenticate it, or when the
4
+ driver never reaches its first flow command. The runtime owner supplies the assigned
5
+ serial, server/guest endpoints and authorized credentials. This reference does not
6
+ provision devices or change global ADB state.
7
+
8
+ ## Distinguish the endpoints
9
+
10
+ The Maestro 2.12.0 connection implementation has separate direct-adbd and ADB-server
11
+ factories. Discovery/by-ID paths and explicit endpoint paths are not interchangeable.
12
+ Do not assume `ADB_SERVER_SOCKET`, `ANDROID_ADB_SERVER_PORT`, `ADB_VENDOR_KEYS` or the
13
+ fact that the host `adb` works means the JVM followed the same route.
14
+
15
+ Inspect the actual pinned CLI `--help`, launcher and bundled connection implementation
16
+ to establish which route the invocation selects. Use supported flags through the existing
17
+ adapter. For a conventional Android emulator the console and adbd transport ports differ;
18
+ the console port is not an adbd endpoint. Read the owner's actual mapping instead of
19
+ guessing from another session's serial. Keep peer/default-server endpoints untouched.
20
+
21
+ ## Check the effective JVM credentials
22
+
23
+ The Dadb `AdbKeyPair.readDefault()` implementation reads `.android/adbkey` and
24
+ `.android/adbkey.pub` under Java's `user.home`. If the private key is absent it generates
25
+ a new pair there. A private shell HOME, `ADB_VENDOR_KEYS`, or a successful host ADB
26
+ connection does not by itself establish that Java used the guest-authorized pair.
27
+
28
+ Verify that behavior in the pinned dependency before applying it to another version.
29
+ Compare the launcher's effective JVM home and public-key identity with the runtime
30
+ owner's authorized key. Use the owner's supported JVM-home/credential configuration;
31
+ do not copy another owner's key, print private key material, approve an unexpected USB
32
+ dialog or alter a shared server to work around failed authentication. Bound the probe
33
+ and record missing credential authority rather than retrying the whole journey.
34
+
35
+ ## Separate authentication from instrumentation
36
+
37
+ On Android, a session installs/starts Maestro's `dev.mobile.maestro` and
38
+ `dev.mobile.maestro.test` driver packages and launches instrumentation. A working adbd
39
+ connection does not prove this succeeded. Retain installation output, instrumentation
40
+ errors and the guest log interval covering startup before cleanup.
41
+
42
+ If instrumentation reports an existing UiAutomation registration, inspect its real
43
+ owner as described in [diagnosis](diagnosis.md). If no commands ran, do not debug a UI
44
+ selector yet. Once startup is corrected, the selected case still owes its UI/backend
45
+ assertions; driver readiness alone is not acceptance.
46
+
47
+ ## Sources and version limits
48
+
49
+ - [Maestro 2.12.0 AndroidDeviceConnection](https://github.com/mobile-dev-inc/Maestro/blob/cli-2.12.0/maestro-client/src/main/java/maestro/android/AndroidDeviceConnection.kt)
50
+ - [Dadb default key lookup](https://github.com/mobile-dev-inc/dadb/blob/master/dadb/src/main/kotlin/dadb/AdbKeyPair.kt)
51
+
52
+ The Dadb source link follows its branch and is explanatory evidence, not a dependency pin.
53
+ Recheck the installed implementation; these sources do not certify every consumer's CLI,
54
+ transport or launcher configuration.
@@ -0,0 +1,113 @@
1
+ # Author a flow, not a CLI loop
2
+
3
+ Start from the repo's existing selectors, copies and fixtures. The following is a structural
4
+ example for a warm History filter case, not runnable proof against an arbitrary app.
5
+ Replace the IDs and assertion with the actual production controls and required result;
6
+ keep its existing caller and `APP_ID`/`FILTER_DATE` input validation.
7
+
8
+ ```yaml
9
+ # maestro/flows/history-filter.yaml
10
+ appId: ${APP_ID}
11
+ name: History filter
12
+ ---
13
+ - launchApp:
14
+ stopApp: false
15
+ - runFlow:
16
+ file: ../shared/open-history.yaml
17
+ - tapOn:
18
+ id: history_filters
19
+ - tapOn:
20
+ id: history_filter_from
21
+ - assertVisible:
22
+ id: history_filter_from
23
+ focused: true
24
+ - inputText: ${FILTER_DATE}
25
+ - tapOn:
26
+ id: history_filter_apply
27
+ - assertNotVisible:
28
+ id: history_filter_apply
29
+ - assertVisible:
30
+ id: history_filter_active
31
+ text: ${FILTER_DATE}
32
+ ```
33
+
34
+ ```yaml
35
+ # maestro/shared/open-history.yaml
36
+ appId: ${APP_ID}
37
+ ---
38
+ - tapOn:
39
+ id: navigation_history
40
+ - assertVisible:
41
+ id: history_list
42
+ ```
43
+
44
+ One CLI invocation executes the top-level flow and its subflow. The subflow does not
45
+ restart, clear state or grant permissions behind the caller's back. An ordinary focused
46
+ selector is useful at a checkpoint, not a replacement for a required continuous hold.
47
+
48
+ Bind the expected value to the intended control, as `id` plus `text` above. Separate
49
+ assertions for a badge and a date anywhere on screen can pass when another row contains
50
+ that date. If the real renderer puts the value on a child, use a verified parent/descendant
51
+ relationship (for example `containsDescendants`) instead of dropping that binding.
52
+
53
+ ## Parameters and input
54
+
55
+ Pass required values through the existing caller and `-e NAME=value`/subflow `env` route
56
+ supported by the pinned version. Prefer required inputs over hidden defaults. If a default
57
+ is actually needed, preserve undefined versus empty/false/zero and verify its expansion
58
+ with the real CLI before adopting it. Do not put the caller's input name in a competing
59
+ flow-level default block and assume CLI precedence.
60
+
61
+ Assert the exact resulting value when text entry is part of the requirement. A successful
62
+ `inputText` command does not prove the entire string reached the intended field. Current
63
+ Maestro docs flag Android Unicode input limitations: verify the selected CLI/input route
64
+ for non-ASCII data, and use an existing supported alternative if required. Do not claim
65
+ Chinese input proof from ASCII-only data, silently change locale, or add sleeps/retries
66
+ without identifying the failed operation.
67
+
68
+ Use existing syntax/admission checks before allocating the device, then run the actual
69
+ selected journey. Syntax validation does not check that an ID is in the real app, that
70
+ the caller supplied the right parameter, or that the destination rendered.
71
+
72
+ ## Consume an existing helper result
73
+
74
+ When the case requires real Login-code delivery and an authorized helper interface already
75
+ exists, a flow can retrieve that result without restarting Maestro. The following fragments
76
+ assume the existing helper returns JSON with a string `code` scoped to this invocation and
77
+ the exact preceding Login request. They are not permission to build an endpoint.
78
+
79
+ ```yaml
80
+ - runScript:
81
+ file: ../scripts/read-auth-code.js
82
+ - tapOn:
83
+ id: authentication_code
84
+ - inputText: ${output.authCode}
85
+ - tapOn:
86
+ id: authentication_verify
87
+ ```
88
+
89
+ ```javascript
90
+ // maestro/scripts/read-auth-code.js; use the existing helper's real contract.
91
+ var response = http.get(AUTH_HELPER_URL, {
92
+ headers: { Authorization: 'Bearer ' + AUTH_HELPER_TOKEN }
93
+ });
94
+ if (response.status !== 200) throw new Error('Authentication helper failed');
95
+ var body = json(response.body);
96
+ if (typeof body.code !== 'string' || body.code.length === 0) {
97
+ throw new Error('Authentication code unavailable');
98
+ }
99
+ output.authCode = body.code;
100
+ ```
101
+
102
+ The caller supplies the already-authorized URL/token without logging them, and the existing
103
+ owner bounds helper waits and closes any owned endpoint. Scope/authorization belong to the
104
+ helper, not a guessed query parameter. Sanitize code-entry artifacts before publishing. For
105
+ an approved non-Login fixture, keep that fixture rather than adding a code-delivery step.
106
+
107
+ ## Sources
108
+
109
+ - [runFlow](https://docs.maestro.dev/reference/commands-available/runFlow)
110
+ - [State selectors](https://docs.maestro.dev/reference/selectors/state-selectors)
111
+ - [inputText](https://docs.maestro.dev/reference/commands-available/inputText)
112
+ - [runScript output](https://docs.maestro.dev/reference/commands-available/runScript)
113
+ - [Relational selectors](https://docs.maestro.dev/reference/selectors/relational-selectors)
@@ -0,0 +1,50 @@
1
+ # Diagnose the failing stage
2
+
3
+ Preserve the first failure and inspect the actual operation before another device run.
4
+ Use the assigned source and runtime; do not substitute a newer checkout or relabel an old
5
+ APK. Keep uncertainty when the retained evidence cannot distinguish causes.
6
+
7
+ | Earliest failed stage | Smallest useful evidence/question |
8
+ | --- | --- |
9
+ | CLI/flow admission | Real arguments, supported selector, syntax and selected flow count |
10
+ | Device discovery/authentication | Actual endpoint, owned serial, authorized key and JVM home; did a command reach the intended guest? |
11
+ | Driver startup | Installation/instrumentation output and guest startup log interval before teardown; which process owns UI automation? |
12
+ | UI action/selector | Failing command, hierarchy, screenshot, actual foreground state and caller parameters |
13
+ | Business assertion | Real record IDs, fixture and backend/provider readback at the required checkpoint |
14
+ | Teardown | Cleanup status separately from the original failed stage |
15
+
16
+ For `UiAutomationService ... already registered!`, identify the registration holder. In a
17
+ parent/child harness, a child's uiautomator2 client may have joined the parent's server;
18
+ stopping that client releases nothing. Ask the verified owner to stop and confirm exit for
19
+ a necessary transitional handoff. For a migrated Maestro-only path, remove competing setup
20
+ and observers once equivalent observations are in place. Never use broad kills, another
21
+ namespace or longer timeouts as a substitute for correct ownership.
22
+
23
+ A correct transport and key do not prove driver readiness. Capture installation,
24
+ instrumentation and crash logs covering startup, not only a tail after the driver failed.
25
+ For endpoint modes, JVM `user.home` key lookup and driver packages, read
26
+ [Android connection](android-connection.md) before changing private transport settings.
27
+ A ready driver does not prove the app used the expected Metro/backend endpoint. Compare
28
+ with an existing known-working caller on the same relevant contract before inventing a
29
+ new transport or collector; explain differences instead of claiming all callers are alike.
30
+
31
+ For UI failures, test the actual producer/consumer where a host reproduction suffices:
32
+ localized labels with country suffixes, undefined-versus-empty parameters, exact selected
33
+ case, fixture prerequisites and executable path. Preserve original gesture coverage such
34
+ as a deliberate double tap; a single successful submit does not replace it.
35
+
36
+ When comparing scroll adapters, content DOWN requires an upward finger swipe; content UP
37
+ requires a downward swipe. A regression fixture must keep the target offscreen until the
38
+ correct gesture, rather than reveal it after an arbitrary gesture count. Prefer Maestro's
39
+ existing scroll command over adding a comparison adapter.
40
+
41
+ Use bounded searches over named files and installed module paths. An unbounded recursive
42
+ search through workspaces/caches can outlast the journey being debugged. Every experiment
43
+ answers a stated question and has an execution/cleanup bound. Correct the supported cause,
44
+ confirm the original reproduction, then rerun invalidated checks; neither a full unchanged
45
+ campaign nor a new worker is required for each small correction.
46
+
47
+ Measure case wall time, invocation count and time inside Maestro separately. Invocation
48
+ time includes UI execution and is not all removable startup cost. Use existing logs;
49
+ do not promise a speedup, increase sensitive assertion windows or build a metrics system
50
+ solely to explain one slow case.
@@ -0,0 +1,74 @@
1
+ # Journey results and failure evidence
2
+
3
+ Record selected cases and executed assertions, source/native artifact/served code identity,
4
+ device/OS and relevant configuration, original status, evidence paths and cleanup outcome.
5
+ The existing runner owns deadlines and cleanup. Successful rendering is not a packaged-app
6
+ or release claim unless that checkpoint's artifact/source requirements were satisfied.
7
+
8
+ Use the pinned Maestro's per-flow results/JUnit report or the existing runner's honest PASS
9
+ markers. A zero exit with no selected flows is not a pass. Capture passing checkpoints with
10
+ `takeScreenshot` when required; ordinary passing flows have no automatic screenshots.
11
+
12
+ The bundled `scripts/maestro_failure.py` maps retained Maestro artifacts to `failure.json`:
13
+ `case`, `step`, `error`, `screenshot`, `uiDump`, `logcatTail`, `evidenceDir`, `cleanupErrors`.
14
+ It prints one `NATIVE_FAILURE` JSON line with `case`, `step`, `error`, `evidenceDir`. The
15
+ first existing failure wins; later capture or cleanup failures never replace its cause.
16
+ Artifact fields are paths relative to the evidence directory or null with a capture reason.
17
+ The converter reads retained files and writes only under the selected evidence directory;
18
+ it starts no device or UI-automation client. Absolute/escaping artifact paths and symlinks
19
+ outside the Flow or destination are rejected as capture gaps, preserving the original error.
20
+
21
+ Confirm the pinned CLI's actual output layout first. The converter understands session/flow
22
+ folders with `commands.json`, failing-step screenshots/hierarchies and device logs. When a
23
+ version uses a different shape, retain its original output and adapt/test the real reader;
24
+ do not assume missing converter output means a passing case. iOS log-name fallbacks in the
25
+ reader are not an observed iOS-device certification.
26
+
27
+ Malformed command entries or unsupported statuses are conversion errors, not empty passing
28
+ flows. If part of a session is unreadable, the CLI retains an available failed record,
29
+ reports the omitted Flow(s) and returns 2 for incomplete conversion. Its selection is only
30
+ the earliest readable failure, not proof of the session's first failure. An explicitly
31
+ empty command list produces no record and still does not prove a selected journey ran.
32
+
33
+ Nested `runFlow` output may include a failed parent summary as well as a failed child.
34
+ The reader's timestamp/entry selection is mechanical; deepest-child/root-cause attribution
35
+ is not certified without a retained nested-output fixture from the pinned CLI. Keep the
36
+ raw command sequence and inspect it when that distinction matters.
37
+
38
+ Give every case/attempt a new owned `LOG_DIR`, shared with its launcher. Reusing a runtime
39
+ does not reuse its failure-record destination. After finalized CLI output, convert before
40
+ teardown with the original status preserved. Inside the existing owner's bounded command:
41
+
42
+ ```bash
43
+ maestro_status=0
44
+ maestro --device "$DEVICE_ID" test --test-output-dir "$LOG_DIR/maestro" \
45
+ --format junit --output "$LOG_DIR/report.xml" ./maestro/flows/checkout.yaml \
46
+ || maestro_status=$?
47
+ conversion_status=0
48
+ python3 <skill-base-dir>/scripts/maestro_failure.py \
49
+ --maestro-dir "$LOG_DIR/maestro" --evidence-dir "$LOG_DIR" --case "$DEVICE_CASE" \
50
+ || conversion_status=$?
51
+ printf 'maestro_exit=%s conversion_exit=%s\n' "$maestro_status" "$conversion_status"
52
+ if [ "$maestro_status" -ne 0 ]; then
53
+ exit "$maestro_status"
54
+ fi
55
+ exit "$conversion_status"
56
+ ```
57
+
58
+ Here `<skill-base-dir>` is the installed **maestro** directory. Retain the repo's actual
59
+ qualified invocation/transport in place of the example. Converter exit zero means evidence
60
+ processing succeeded, not that the journey passed: a recorded failure also returns zero.
61
+
62
+ If startup leaves no step report, retain CLI logs and the actual driver-start interval.
63
+ Have the existing owner write its partial failure record before teardown, preserving the
64
+ original exit/error. Capture with Maestro artifacts or non-conflicting probes; a fallback
65
+ `uiautomator dump` can itself acquire UI automation, so it must not run alongside Maestro.
66
+ Report missing capture as a gap, not permission to start a competing client.
67
+
68
+ Keep raw credentials, authentication codes and payment data private. Publish only sanitized
69
+ findings. Report build time, device time and total worker time separately; one cannot be
70
+ inferred from another.
71
+
72
+ ## Source
73
+
74
+ - [Reports and artifacts](https://docs.maestro.dev/maestro-flows/workspace-management/test-reports-and-artifacts)
@@ -0,0 +1,100 @@
1
+ # Complete journeys
2
+
3
+ ## Split by responsibility
4
+
5
+ | Required observation | Default location |
6
+ | --- | --- |
7
+ | Navigation, form entry, scrolling, visible results, enabled/selected/focused state | Maestro flow and assertions |
8
+ | Exact records, amounts, duplicate-call counts, authorization isolation and recovery identity | Existing backend/database helper |
9
+ | Authentication/fixtures required by this case | Existing approved helper; for real Login-code acceptance, the code produced by that request |
10
+ | Device setup, installation, Metro, fixture creation and cleanup | Existing runtime owner |
11
+ | OS/security/accessibility fact not exposed with equivalent fidelity by Maestro | Non-conflicting platform probe or named exclusive native case |
12
+
13
+ Use the cheapest observation that proves the requirement. An on-screen success is not an
14
+ exact Sale assertion; conversely, a database row does not prove the intended screen rendered.
15
+ Preserve the repository-approved authentication fixture: an unrelated authenticated-screen
16
+ test may use an approved seeded session or test-account service. When acceptance includes
17
+ Login or code delivery, exercise that real path and retrieve its actual code through the
18
+ approved helper (for example disposable PostgreSQL). Do not substitute a hardcoded OTP or
19
+ injected session for required authentication proof. Provider doubles remain only where
20
+ repo policy allows them; no production fixture endpoint or replay of an Unknown payment
21
+ to get a green journey.
22
+
23
+ Separate helpers from UI clients. Run before/after checks directly through the existing
24
+ runner. Where ordering needs a mid-flow result, first reuse an existing supported helper
25
+ interface. Maestro `runScript` can issue HTTP requests, but a new bridge is a scoped design
26
+ change, not required infrastructure: get authorization, reuse the same fixture/authority,
27
+ limit it to owned disposable resources and required operations, keep credentials private,
28
+ bound waits, and close it through the existing owner. It must not become arbitrary command
29
+ execution or a public production test route. Record a necessary split if no safe interface
30
+ exists instead of inventing one or omitting an assertion.
31
+
32
+ ## Starting state
33
+
34
+ Declare the required app state, permissions, locale, window and fixture in the existing
35
+ case setup. Inspect hooks and subflows for resets too.
36
+
37
+ - For a warm app, keep it running or use `launchApp: {stopApp: false}` to foreground it.
38
+ Plain `launchApp` stops and relaunches by default.
39
+ - `clearState` clears app data, not installs an APK or proves upgrade behavior. Clear only
40
+ owned disposable state and restore debug endpoint preferences when the reset removes them.
41
+ - Set permissions explicitly for denied/unset/prompt cases: `launchApp` grants all by default.
42
+ - Configure lifecycle-changing size/density settings before starting an observation whose
43
+ Activity must survive. Preserve real restart/process-death checks where assigned.
44
+
45
+ ## Flow structure and selectors
46
+
47
+ Read [flow authoring](authoring.md) for a complete top-level/subflow example and the
48
+ required-input/text-entry checks before writing a new journey.
49
+
50
+ Keep one top-level business case with subflows for reusable Login, context selection or
51
+ editor actions. A subflow call is not another CLI process. Host code should not decide every
52
+ tap or reacquire UI automation between subflows. Do not combine independent stateful cases
53
+ merely to reduce process count; each retains its starting state, result and failure record.
54
+
55
+ Prefer existing stable accessibility/resource IDs. Otherwise derive complete, unambiguous
56
+ labels from the real renderer and metadata, including localization and suffixes. Maestro
57
+ text selectors use regular expressions; escape literal dynamic values as appropriate.
58
+ Confirm destination-only state after navigation, and use bounded `scrollUntilVisible` for
59
+ offscreen controls. A fake exposing every control cannot prove scrolling works.
60
+ Bind a dynamic expected value to its intended field/row/container, using the verified
61
+ hierarchy when needed. A separate screen-wide text match may come from an unrelated row
62
+ and cannot establish that a filter, receipt or selected item has the expected value.
63
+
64
+ Verify parameter precedence against the pinned CLI and actual caller. Supply defaults only
65
+ when an input is undefined, preserving intentional empty/false/zero values. A YAML `env`
66
+ default can override a CLI value in some versions; a test of each side with handwritten
67
+ fixtures misses this. Exercise the real caller-to-flow parameter path.
68
+
69
+ ## Execute through the existing owner
70
+
71
+ Use the assigned device explicitly, with the owner's endpoint and credentials. For a
72
+ standard supported route the command shape is:
73
+
74
+ ```bash
75
+ maestro --device "$DEVICE_ID" test --test-output-dir "$LOG_DIR/maestro" \
76
+ --format junit --output "$LOG_DIR/report.xml" ./maestro/flows/checkout.yaml
77
+ ```
78
+
79
+ Check flags and selectors with the repo-pinned CLI. A private Android ADB server may need
80
+ an existing adapter's explicit transport/credential configuration; `--device` alone does
81
+ not prove that the CLI uses that endpoint. Keep the qualified route rather than replacing
82
+ it with this example. If no qualified route exists or ADB works while Maestro cannot
83
+ authenticate, read [Android connection](android-connection.md) and inspect the pinned
84
+ implementation before changing settings. The runner bounds the invocation and cleanup, captures the original
85
+ status, and follows [evidence](evidence.md).
86
+
87
+ Reuse valid development resources between fixes. New case evidence gets a new directory;
88
+ this does not require a fresh emulator. Fresh-install acceptance still uses its required
89
+ disposable app/data state. Keep one owner through the diagnosis/fix/recheck cycle where
90
+ possible; a bounded attempt is not automatically the end of the assignment.
91
+
92
+ Maestro MCP inspection can help choose selectors and author a flow. The executed assertions
93
+ on the identified candidate, not exploration or syntax validation, establish the result.
94
+
95
+ ## Sources
96
+
97
+ - [runFlow](https://docs.maestro.dev/reference/commands-available/runFlow)
98
+ - [launchApp](https://docs.maestro.dev/reference/commands-available/launchapp)
99
+ - [runScript](https://docs.maestro.dev/reference/commands-available/runScript)
100
+ - [HTTP requests](https://docs.maestro.dev/advanced/javascript/make-http-requests)
@@ -0,0 +1,35 @@
1
+ # Replace a hybrid UI driver
2
+
3
+ Start only with task/repo authorization. Existing working journeys are not migration scope
4
+ merely because Maestro is installed. Preserve required CI and every original criterion.
5
+
6
+ 1. **Map the real case.** Trace its local and CI commands to maintained callers, fixtures,
7
+ UI actions, observers and assertions. Include private/copied callers if they are actually
8
+ executed. Record which observations move to Maestro, stay in a non-UI helper or require
9
+ a named native exception. Reuse existing flows and applicable evidence.
10
+ 2. **Prove one complete path.** Choose a representative case with meaningful UI work,
11
+ required backend assertions, failure capture and owned cleanup. Genuine Login
12
+ is required when it is part of that case's acceptance; otherwise retain the approved
13
+ authentication fixture. Use the current runner, not a new emulator manager. Test actual dispatch and parameter/fixture composition
14
+ on the host before spending a device run where those defects can be exposed there.
15
+ 3. **Move sequencing.** Replace Python deciding each tap with a top-level Maestro journey
16
+ and subflows. Extract existing non-UI helpers from UI clients without duplicating financial
17
+ or authentication logic. Keep mid-flow assertions in their required order. Grouping is not
18
+ permission to move a safety check until after a financial action.
19
+ 4. **Remove competition.** After equivalent proof exists, stop creating uiautomator2 in the
20
+ ordinary case's setup, parent/child, observation and failure paths. During transition,
21
+ handoffs retain verified ownership, expiry/currentness and cleanup checks. Keep specialist
22
+ drivers exclusive and explicit; retain only assertions not yet equivalently proven.
23
+ 5. **Replace callers and retire code.** Put the working case in tracked source. Local and
24
+ CI use that same implementation with environment-specific configuration. Once it passes,
25
+ remove equivalent legacy UI helpers, private copied callers and silent driver fallbacks.
26
+ A public flow wired correctly does not establish that a private caller uses it.
27
+ 6. **Verify the replacement.** Real run artifacts must show selected cases, Maestro commands,
28
+ unchanged domain/native assertions and cleanup on the final candidate. Keep old failures
29
+ and still-valid proof. A zero-Maestro run may prove business behavior, not the migration.
30
+
31
+ Finish the assigned scope, not every possible device campaign. Report unmigrated paths and
32
+ unrun acceptance explicitly. Script extraction, host tests and successful driver startup
33
+ are useful intermediate results, not whole-issue acceptance. Do not duplicate a working
34
+ journey permanently as reassurance, weaken an oracle, or add gates and broad framework
35
+ work outside the authorized migration.
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import { spawnSync } from 'node:child_process';
3
+ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { homedir } from 'node:os';
5
+ import { dirname, join, resolve } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const DAY_MS = 24 * 60 * 60 * 1000;
9
+ const WEEK_MS = 7 * DAY_MS;
10
+ const here = dirname(fileURLToPath(import.meta.url));
11
+
12
+ function readJson(path, fallback = {}) {
13
+ try { return JSON.parse(readFileSync(path, 'utf8')); } catch { return fallback; }
14
+ }
15
+
16
+ function frontmatterValue(text, key) {
17
+ const frontmatter = /^---\n([\s\S]*?)\n---/.exec(text)?.[1] ?? '';
18
+ const match = new RegExp('^' + key + ':\\s*([^\\n]+)$', 'm').exec(frontmatter);
19
+ return match?.[1].trim().replace(/^['"]|['"]$/g, '') ?? null;
20
+ }
21
+
22
+ function repositoryOf(source) {
23
+ const value = String(source ?? '').trim();
24
+ const match = /^(?:git@github\.com:|https:\/\/github\.com\/)?([A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+?)(?:\.git)?$/.exec(value);
25
+ return match?.[1] ?? null;
26
+ }
27
+
28
+ function stableVersion(value) {
29
+ const match = /^v?(\d+)\.(\d+)\.(\d+)$/.exec(String(value ?? '').trim());
30
+ return match ? match.slice(1).map(Number) : null;
31
+ }
32
+
33
+ function newer(left, right) {
34
+ for (let index = 0; index < 3; index += 1) {
35
+ if (left[index] !== right[index]) return left[index] > right[index];
36
+ }
37
+ return false;
38
+ }
39
+
40
+ function writeCache(path, value) {
41
+ try {
42
+ mkdirSync(dirname(path), { recursive: true });
43
+ writeFileSync(path, JSON.stringify(value));
44
+ } catch { /* A read-only cache must not block skill use. */ }
45
+ }
46
+
47
+ function main(now = Date.now()) {
48
+ if (process.env.ONEABOVEIO_NO_UPDATE_CHECK) return;
49
+ const bundle = readJson(join(resolve(here, '../../..'), 'package.json'));
50
+ if (bundle.name === '@1aboveio/skills' && bundle.nativeCodex?.schemaVersion === 1) return;
51
+ const skill = readFileSync(join(here, 'SKILL.md'), 'utf8');
52
+ const name = frontmatterValue(skill, 'name');
53
+ const localVersion = stableVersion(frontmatterValue(skill, 'release-version'));
54
+ if (!name || !localVersion) return;
55
+
56
+ const lock = readJson(join(process.env.HOME || homedir(), '.agents', '.skill-lock.json'));
57
+ const entry = lock.skills?.[name];
58
+ const repository = repositoryOf(entry?.sourceUrl || entry?.source);
59
+ if (!repository) return;
60
+
61
+ const cacheRoot = process.env.XDG_CACHE_HOME || join(process.env.HOME || homedir(), '.cache');
62
+ const cachePath = join(cacheRoot, '1aboveio-skills', 'release-check.json');
63
+ const all = readJson(cachePath);
64
+ const cache = all[repository] && typeof all[repository] === 'object' ? all[repository] : {};
65
+
66
+ if (!cache.lastCheck || now - cache.lastCheck >= DAY_MS) {
67
+ const result = spawnSync('gh', ['api', 'repos/' + repository + '/releases/latest', '--jq', '.tag_name'], {
68
+ encoding: 'utf8',
69
+ stdio: ['ignore', 'pipe', 'ignore'],
70
+ timeout: 1500,
71
+ });
72
+ cache.lastCheck = now;
73
+ if (result.status === 0 && stableVersion(result.stdout)) cache.latestTag = result.stdout.trim();
74
+ else delete cache.latestTag;
75
+ all[repository] = cache;
76
+ writeCache(cachePath, all);
77
+ }
78
+
79
+ const latestVersion = stableVersion(cache.latestTag);
80
+ if (!latestVersion || !newer(latestVersion, localVersion)) return;
81
+ if (cache.notifiedTag === cache.latestTag && cache.notifiedAt && now - cache.notifiedAt < WEEK_MS) return;
82
+
83
+ cache.notifiedTag = cache.latestTag;
84
+ cache.notifiedAt = now;
85
+ all[repository] = cache;
86
+ writeCache(cachePath, all);
87
+ const command = `npx skills@1.5.23 add '${repository}#${cache.latestTag}' --global --agent universal claude-code --skill ${name} --yes`;
88
+ process.stdout.write(
89
+ `UPDATE_AVAILABLE: A newer 1AboveIO skills release (${cache.latestTag}) is available; this skill is `
90
+ + `v${localVersion.join('.')}. Ask once whether to refresh ${name}. On approval run \`${command}\`. `
91
+ + 'The refreshed instructions apply next session. Either way, continue the current task and do not ask again this session.\n',
92
+ );
93
+ }
94
+
95
+ try { main(); } catch { /* Update checks are advisory and always fail silent. */ }