@1aboveio/skills 1.0.6 → 1.0.8

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 (78) hide show
  1. package/package.json +2 -2
  2. package/skills/app-dev/airflow/SKILL.md +1 -1
  3. package/skills/app-dev/android-foundation/SKILL.md +92 -34
  4. package/skills/app-dev/android-foundation/assets/android-ci-job.yml +13 -7
  5. package/skills/app-dev/android-foundation/references/ci.md +23 -13
  6. package/skills/app-dev/android-foundation/references/delivery-focus.md +29 -0
  7. package/skills/app-dev/android-foundation/references/diagnosis.md +136 -0
  8. package/skills/app-dev/android-foundation/references/gotchas.md +20 -11
  9. package/skills/app-dev/android-foundation/references/setup.md +15 -6
  10. package/skills/app-dev/android-foundation/scripts/device-run.sh +148 -42
  11. package/skills/app-dev/android-foundation/scripts/device-run.test.mjs +322 -58
  12. package/skills/app-dev/app-debug/SKILL.md +1 -1
  13. package/skills/app-dev/better-auth/SKILL.md +1 -1
  14. package/skills/app-dev/data-catalog/SKILL.md +1 -1
  15. package/skills/app-dev/data-quality/SKILL.md +1 -1
  16. package/skills/app-dev/ios-foundation/SKILL.md +1 -1
  17. package/skills/app-dev/monorepo/SKILL.md +1 -1
  18. package/skills/app-dev/nextjs-fullstack/SKILL.md +1 -1
  19. package/skills/app-dev/prisma-setup/SKILL.md +1 -1
  20. package/skills/app-dev/pyspark/SKILL.md +1 -1
  21. package/skills/app-dev/python-backend/SKILL.md +1 -1
  22. package/skills/app-dev/shadcn/SKILL.md +1 -1
  23. package/skills/app-dev/zod-v4/SKILL.md +1 -1
  24. package/skills/cicd/cloud-build/SKILL.md +1 -1
  25. package/skills/cicd/cloud-debug/SKILL.md +1 -1
  26. package/skills/cicd/cloud-deploy/SKILL.md +1 -1
  27. package/skills/cicd/docker/SKILL.md +1 -1
  28. package/skills/cicd/github-actions/SKILL.md +1 -1
  29. package/skills/cicd/github-flow/SKILL.md +1 -1
  30. package/skills/cicd/google-cloud/SKILL.md +1 -1
  31. package/skills/cicd/mergify/SKILL.md +1 -1
  32. package/skills/cicd/podman/SKILL.md +1 -1
  33. package/skills/content/article-review/SKILL.md +1 -1
  34. package/skills/content/article-to-image/SKILL.md +1 -1
  35. package/skills/content/flowchart-svg/SKILL.md +1 -1
  36. package/skills/content/image-gen/SKILL.md +1 -1
  37. package/skills/content/mermaid/SKILL.md +1 -1
  38. package/skills/content/wechat-article-writer/SKILL.md +1 -1
  39. package/skills/content/wechat-publisher/SKILL.md +1 -1
  40. package/skills/content/wechat-search/SKILL.md +1 -1
  41. package/skills/content/xai-search/SKILL.md +1 -1
  42. package/skills/core/distill-writing/SKILL.md +22 -4
  43. package/skills/core/distill-writing/references/extraction.md +19 -3
  44. package/skills/core/doc-to-md/SKILL.md +1 -1
  45. package/skills/core/editorial-review/SKILL.md +1 -1
  46. package/skills/core/house-style/SKILL.md +2 -1
  47. package/skills/core/house-style/references/persistence.md +93 -0
  48. package/skills/core/house-style/references/rules.md +15 -6
  49. package/skills/core/plain-language/SKILL.md +40 -4
  50. package/skills/core/polish-cn/SKILL.md +1 -1
  51. package/skills/core/reg-parser/SKILL.md +1 -1
  52. package/skills/core/terminology/SKILL.md +1 -1
  53. package/skills/core/write-doc/SKILL.md +14 -6
  54. package/skills/engineering/better-review/SKILL.md +1 -1
  55. package/skills/engineering/contributing/SKILL.md +1 -1
  56. package/skills/engineering/e2e-test/SKILL.md +1 -1
  57. package/skills/engineering/engineering-runtime/SKILL.md +1 -1
  58. package/skills/engineering/engineering-runtime/coherence/workflow.json +13 -13
  59. package/skills/engineering/ensure-coverage/SKILL.md +1 -1
  60. package/skills/engineering/golden-path/SKILL.md +1 -1
  61. package/skills/engineering/harness-runtime/SKILL.md +1 -1
  62. package/skills/engineering/resolve-issues/SKILL.md +11 -20
  63. package/skills/engineering/resolve-issues/references/delivery-progress.md +63 -0
  64. package/skills/engineering/resolve-issues/references/expire.md +24 -11
  65. package/skills/engineering/resolve-issues/references/implementation.md +9 -1
  66. package/skills/engineering/resolve-issues/references/task-plan.md +7 -4
  67. package/skills/engineering/resolve-release/SKILL.md +1 -1
  68. package/skills/engineering/rush-issues/SKILL.md +5 -2
  69. package/skills/engineering/rush-release/SKILL.md +1 -1
  70. package/skills/engineering/test-quality/SKILL.md +1 -1
  71. package/skills/risk-compliance/compliance-audit/SKILL.md +1 -1
  72. package/skills/risk-compliance/contract-compare/SKILL.md +1 -1
  73. package/skills/risk-compliance/contract-review/SKILL.md +1 -1
  74. package/skills/risk-compliance/doc-authenticity/SKILL.md +1 -1
  75. package/skills/risk-compliance/fraud-analysis/SKILL.md +1 -1
  76. package/skills/risk-compliance/payment-analysis/SKILL.md +1 -1
  77. package/skills/risk-compliance/similar-domain/SKILL.md +1 -1
  78. package/skills/risk-compliance/tld-detection/SKILL.md +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@1aboveio/skills",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "Every 1aboveio skill package in one: install once, then choose which packages Pi loads with npx @1aboveio/skills select.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -251,7 +251,7 @@
251
251
  ]
252
252
  }
253
253
  ],
254
- "digest": "efb93166fdfdb1405f9a596f79d068c34b10a09ff176dc8f51021d64bd80e83d"
254
+ "digest": "bfce7befa948e2bb4167e5820bbebe316e25ea580c6126246d5516944520bbe0"
255
255
  },
256
256
  "publishConfig": {
257
257
  "registry": "https://registry.npmjs.org/",
@@ -2,7 +2,7 @@
2
2
  name: airflow
3
3
  description: Airflow DAG architecture and conventions. Use when designing, writing, reviewing, testing, or debugging Airflow DAGs and tasks, including TaskGroups, data intervals, timezone-aware date parameters, CLI validation, environment-based scheduling, and pytest integrity tests.
4
4
  user-invocable: true
5
- release-version: 0.42.1
5
+ release-version: 0.43.1
6
6
  ---
7
7
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
8
8
  # Airflow DAG Development Patterns
@@ -1,20 +1,22 @@
1
1
  ---
2
2
  name: android-foundation
3
- description: "Prove an Expo / React Native app on a native Android emulator, and fix it when that proof fails. Use before you fix and re-run or re-dispatch a failed Android CI job (`gh workflow run android.yml`, `gh run rerun`): a re-run is not a debugger, so reproduce the failing journey checkpoint off CI first. Also use when a UiAutomator journey or its Python harness tests fail (a CHECK/FAIL line, a wait that timed out, a control not found, adb offline, a lost Metro bridge, a fixture failing on the runner), to build the debug APK and run the device journey, to set up a fresh Android workspace (SDK/NDK/JDK, Gradle caches, private AVD, disposable PostgreSQL), or to add the emulator job to CI. NOT for workflow YAML, CI speed or runner design (github-actions), browser tests (e2e-test), iOS (ios-foundation), plain Jest component tests, or signing and store release."
4
- release-version: 0.42.1
3
+ description: "Prove and debug Expo / React Native apps on an owned Android emulator. Use for stuck Android debugging, post-deploy startup or rendering failures, Metro answering while the app does not render, UiAutomator failures, missing controls, ADB drops, harness-test failures, APK builds, fresh SDK/NDK/JDK workspaces, and native journey validation. Before fixing and rerunning or redispatching a failed Android CI job, reproduce its failing checkpoint off CI: a rerun is not a debugger. Diagnose existing setups without rebuilding the whole environment. NOT for workflow YAML, CI speed or runner design (github-actions), browser tests (e2e-test), iOS (ios-foundation), plain Jest component tests, or signing and store release."
4
+ release-version: 0.43.1
5
5
  ---
6
6
  **Updates:** Once/session run `node <skill-base-dir>/release-check.mjs`.
7
7
  # Android foundation
8
8
 
9
- Take a native Expo / React Native Android workspace from a fresh checkout to a passing
10
- device journey, then record the evidence. Use the repo's existing build scripts, native
11
- project, device harness and journey wrapper. For CI, add one job to the repo's `ci.yml`
12
- from the template; do not write a separate release runbook.
9
+ Prove or debug a native Expo / React Native device journey using the repo's existing
10
+ build scripts, native project, harness and wrapper. Use `github-actions` for CI YAML
11
+ and runner integration. The CI template is a starting point; preserve existing workflows.
13
12
 
14
13
  Pick the mode first:
15
14
 
16
- - **Setup proof:** a new workspace or CI job, a toolchain, dependency, native or harness
17
- change, or a broken build-to-device path. Run every stage and write the
15
+ - **Diagnosis:** an existing workspace or CI run fails or stalls. Follow
16
+ [Diagnosis](#diagnosis) first; a harness change does not automatically require a cold
17
+ setup. Re-run only the setup stages whose assumptions changed.
18
+ - **Setup proof:** a new workspace or CI job, or a toolchain, dependency or native
19
+ change that invalidates setup. Run every stage and write the
18
20
  [evidence record](#evidence-record).
19
21
  - **Feature work:** proving a product change on the emulator in a workspace already set
20
22
  up. Follow [Feature work](#feature-work) and report only the journey result.
@@ -27,18 +29,24 @@ Pick the mode first:
27
29
  | Stages 6–8 in one command | [scripts/device-run.sh](scripts/device-run.sh) |
28
30
  | Adding the Android job to CI | [references/ci.md](references/ci.md), template [assets/android-ci-job.yml](assets/android-ci-job.yml) |
29
31
  | Proving a product change on the emulator | [Feature work](#feature-work) |
30
- | A stage failed | [Triage](#triage), then [references/gotchas.md](references/gotchas.md) |
32
+ | A stage failed or a worker appears stuck | [Diagnosis](#diagnosis), then [references/diagnosis.md](references/diagnosis.md) and [Triage](#triage) |
31
33
  | Writing up setup proof | [Evidence record](#evidence-record) |
32
34
 
33
35
  ## Rules
34
36
 
35
- - Work in a dedicated worktree on a new branch from `origin/main`. Never overwrite or reuse
36
- another checkout, and never symlink another worktree's `node_modules`.
37
+ - Use an isolated checkout. For new work, branch from `origin/main`; for diagnosis,
38
+ pin the failed source SHA or the reviewed correction. Confirm the checkout actually
39
+ contains the failing code: the repo root may lag active workspaces. Never mutate a
40
+ peer's checkout or symlink its writable `node_modules`.
37
41
  - Tool shells keep no variables, functions or traps between calls. Write the environment
38
- to `.cache/android-env.sh` once and source it at the start of every command. Run stages
39
- 6–8 as one `scripts/device-run.sh` command, never as separate calls.
40
- - Keep every cache private to the worktree under `.cache/`: Gradle home, Android user home,
41
- AVD home, `TMPDIR`, npm, node-gyp and pnpm store. Keep them between runs.
42
+ to `.cache/android-env.sh` once and source it at the start of every command. Use the
43
+ repo's existing owned-resource launcher. For a new local setup without one, use
44
+ `scripts/device-run.sh` for stages 6–8 in one command. Do not wrap an existing owner
45
+ with a second emulator/database lifecycle.
46
+ - Keep local writable caches private under `.cache/`: Gradle home, Android user/AVD
47
+ homes, temporary files, npm, node-gyp and pnpm. In CI, an already isolated runner slot
48
+ may provide those paths; verify its ownership contract rather than layering another
49
+ cache system on top. Never share writable state across concurrent owners.
42
50
  - Read toolchain versions from the repo: the root `packageManager` and `engines`, the
43
51
  native Gradle config, and the CI preflight. The repo is the source of truth, not this skill.
44
52
  - Check that every required SDK component (platform, build-tools, NDK, CMake,
@@ -51,8 +59,10 @@ Pick the mode first:
51
59
  - Build every configured ABI for setup proof and release acceptance. An x86_64-only CI
52
60
  APK only proves the emulator ABI. For feature work, the emulator ABI is enough unless the
53
61
  change touches native code or ABI configuration.
54
- - A debug APK needs Metro. A successful export or build does not prove the app works on
55
- a device. Only the device journey does.
62
+ - Determine how the selected build loads code and assets. A typical debug build needs
63
+ Metro; a release build normally embeds its bundle. Do not introduce Metro or debug
64
+ preferences into a release failure without evidence that the build uses them.
65
+ A successful build does not prove execution on a device.
56
66
 
57
67
  ## Stages
58
68
 
@@ -106,21 +116,64 @@ Run them in this order. Stop at the first failure and triage it.
106
116
  CID file, and the named database. Signal the PID with `TERM`, wait up to 10 seconds, then
107
117
  `KILL`. Then `wait` for it and confirm nothing is left. Count wait status 0 or 143 (ended
108
118
  by your `TERM`) as a clean stop; count a needed `KILL` or any other status as a failure.
109
- - Never use `adb kill-server`, `adb -s <serial> emu kill`, broad `pkill`, or
110
- `docker system prune`. An ADB serial can be reused by another process; a PID you own
111
- cannot.
119
+ - Never use broad `pkill`, `docker system prune` or a shared `adb kill-server` for cleanup.
120
+ Use the live child's process owner, not an ADB serial that may be reused. A numeric
121
+ PID can also be reused after exit; it is not durable ownership evidence.
112
122
  - Give every startup, readiness and cleanup command a 30-second limit that kills the
113
123
  command's whole process group. Treat exit 124 (timeout) as a terminal failure, not as
114
124
  "not ready yet".
115
125
  - Preserve the stage's original non-zero exit status even when cleanup succeeds. Print
116
126
  `original_stage_exit=<n> cleanup_exit=<n>`.
117
- - After a `SIGKILL` or a host crash, the trap cannot run. Remove only this run's recorded
118
- PID and container ID by hand, and keep the failure logs.
119
- - Point the database URL only at the disposable loopback container. Never at development,
120
- production or another worker's database.
127
+ - After SIGKILL or a host crash, verify recorded resources before recovery: process
128
+ start identity, command/run scope and boot identity where available, or container ID
129
+ and ownership labels. Never signal a numeric PID solely because an old record names
130
+ it. If ownership cannot be verified, leave it alone and report the gap. Keep logs.
131
+ - For the local setup flow, point the database URL only at its disposable loopback
132
+ container. An existing isolated remote test flow must use its own disposable data and
133
+ ownership checks. Never use development, production or another worker's database for
134
+ fixture writes or cleanup. A public render-only smoke needs no database.
121
135
  - Expo may rewrite `android/tsconfig.json` or delete `android/expo-env.d.ts` while it runs.
122
136
  Inspect those changes and restore them before you commit.
123
137
 
138
+ ## Delivery focus
139
+
140
+ Read [references/delivery-focus.md](references/delivery-focus.md) before starting or
141
+ continuing work. Keep an existing acceptance checkpoint, reuse available evidence,
142
+ justify new infrastructure and carry failure history across workers. Required CI and
143
+ the full acceptance criteria still apply; report delivered behavior before activity.
144
+
145
+ ## Diagnosis
146
+
147
+ Follow the procedure below and [references/diagnosis.md](references/diagnosis.md).
148
+ `diagnosing-bugs`, when available, can help with deeper hypothesis testing; it is not
149
+ required to use this skill.
150
+
151
+ 1. Record the failed SHA, actual checkout, build variant, device type and retained
152
+ evidence. Locate the earliest failing stage: build/install → launch → load code/assets
153
+ → initialize → render → interact. Distinguish host/CI, harness, transport and product
154
+ failures; an absent screen alone does not identify which one failed.
155
+ 2. Choose the smallest test that can expose the suspected defect: a host test for logic,
156
+ real producer/consumer composition for a contract, or a device test for native/runtime
157
+ behavior. Collect evidence appropriate to that stage. A service probe proves only the
158
+ probe, not that the application used the same path.
159
+ 3. State competing explanations and a distinguishing observation. Change one variable.
160
+ For reversible defects, a failure → correction → failure comparison can strengthen
161
+ the finding; it is optional, not a gate. For intermittent failures, use a bounded,
162
+ repeatable trigger and compare failure rates. Do not replay Authentication or financial
163
+ actions merely to obtain a comparison.
164
+ 4. Keep the first exception and its evidence separate from cleanup errors. Bound the
165
+ full command and each subprocess wait, allowing the resource owner time to clean up.
166
+ A live worker or an outstanding tool call is not evidence of progress.
167
+ 5. Verify the fix at the failing checkpoint, then run the applicable acceptance once.
168
+ Report local reproduction, source CI and post-deploy acceptance separately. A local
169
+ result on another API/ABI or a copied APK is not proof of the original CI artifact.
170
+
171
+ Continue when the next attempt tests a new prediction, collects a missing observation,
172
+ reduces the reproduction, or adds a justified sample for an intermittent failure. Name
173
+ that purpose and bound its cost. Changing workers or repeating an unchanged run without
174
+ such a purpose is not progress. When no available experiment distinguishes the remaining
175
+ explanations, report the missing evidence or access instead of restarting the campaign.
176
+
124
177
  ## Triage
125
178
 
126
179
  Name the earliest stage that failed. In CI, that is the first failed step. If the same
@@ -135,6 +188,7 @@ the product.
135
188
  | Gradle network | Maven download or TLS-handshake errors on a cold build: fix routing, not code |
136
189
  | Emulator boot / ADB | `sys.boot_completed` never reaches 1, device offline, exit 124 |
137
190
  | Device to Metro | red box, "unable to load script", missing `adb reverse` mapping |
191
+ | Bridge passes, debug app fails to load | possible app/probe endpoint mismatch; inspect the actual request before choosing a cause ([React Native example](references/diagnosis.md#example-react-native-debug-app-uses-another-metro)) |
138
192
  | Device to Metro, mid-journey | a screen's first Metro asset fails (`Unable to download asset from url: http://127.0.0.1:8081/assets/…`) while API calls still succeed |
139
193
  | Backend / Login | backend log errors, verification code not found in the database |
140
194
  | Backend tool, CI only | a Backend-backed step gets a 5xx in CI only; the log names a missing program (`Browser was not found at the configured executablePath`) |
@@ -156,16 +210,20 @@ build is reliable.
156
210
 
157
211
  - Reuse the workspace's caches, venv and AVD configuration. Rerun a setup stage only when
158
212
  the change touches what it proves (toolchain, dependencies, native code, harness).
159
- - Build the emulator ABI and run `scripts/device-run.sh` once per candidate HEAD.
160
- - After a failed journey, local or a CI dispatch, reproduce the failing checkpoint off CI
161
- before you run it again: in the harness unit tests with the fake UI scripted to the
162
- failing screen, or on the owned emulator. Show the fix passes there, then run the journey
163
- once to confirm. Never send a guessed fix to CI to see whether it passes; a failure you
164
- cannot reproduce earns one more run, with added diagnostics, then goes in the report as
165
- unreproduced.
166
- - Report the source SHA, the journey command, its `PASS` markers or the failing stage,
167
- and the cleanup exit. Nothing else: no APK hash, version inventory, screenshots, copied
168
- logs or earlier attempts.
213
+ - Build the emulator ABI when its inputs changed and run the repo's owned journey
214
+ command once per candidate HEAD. A reused APK needs the source/configuration checks
215
+ the repo requires; record its hash and any provenance gap during diagnosis.
216
+ - After a failed journey, local or a CI dispatch, enter Diagnosis mode and reproduce the
217
+ failing checkpoint off CI before running it again. A fake UI can reproduce a harness
218
+ navigation/scrolling bug; it cannot prove that the app loaded a bundle or rendered.
219
+ Show the fix passes at the appropriate seam, then run the journey once to confirm.
220
+ Never send a guessed fix to CI to see whether it passes. Use the Diagnosis continuation
221
+ rule for unreproduced or intermittent failures; report uncertainty until evidence
222
+ supports the cause.
223
+ - For a passing feature run, report the source SHA, journey command, `PASS` markers and
224
+ cleanup exit. For a failure, also name the earliest failing checkpoint, link retained
225
+ evidence and state what remains unproved; use the diagnosis report instead of hiding
226
+ the failed attempts.
169
227
  - Integrated device acceptance (all ABIs, tablet, TalkBack, physical devices, a release
170
228
  device campaign) runs at the release or campaign gate the spec or repo assigns it. Do
171
229
  not recreate it per feature. Record it once, as pending, in its owning issue, never as
@@ -107,6 +107,12 @@ jobs:
107
107
  ' "$props" "$mirror"
108
108
  grep '^distributionUrl=' "$props"
109
109
 
110
+ # Prerequisite: runner slots own their writable caches and Android homes.
111
+ # Otherwise export job-private paths to GITHUB_ENV before install so every
112
+ # subsequent step (including the emulator action) inherits the same paths.
113
+ - name: Verify writable runner isolation
114
+ run: <runner-cache-and-home-isolation-preflight-command>
115
+
110
116
  - name: Install dependencies
111
117
  timeout-minutes: 12
112
118
  run: pnpm install --frozen-lockfile
@@ -116,6 +122,7 @@ jobs:
116
122
  pnpm --filter <android-workspace-package> test
117
123
  pnpm --filter <android-workspace-package> typecheck
118
124
 
125
+ # Optional: only after measurement, and never for persistence/recovery tests.
119
126
  - name: Relax durability on the disposable Postgres
120
127
  env:
121
128
  PG_CONTAINER: ${{ job.services.postgres.id }}
@@ -138,9 +145,7 @@ jobs:
138
145
  timeout-minutes: 30
139
146
  env:
140
147
  EXPO_PUBLIC_API_URL: https://app.invalid
141
- ANDROID_USER_HOME: ${{ github.workspace }}/.cache/android-user
142
148
  run: |
143
- mkdir -p "$ANDROID_USER_HOME"
144
149
  cpus="$(nproc)"
145
150
  if [ -r /sys/fs/cgroup/cpu.max ]; then
146
151
  read -r quota period < /sys/fs/cgroup/cpu.max
@@ -148,7 +153,7 @@ jobs:
148
153
  fi
149
154
  echo "gradle max-workers=$cpus (nproc=$(nproc))"
150
155
  <android-project>/gradlew --project-dir <android-project> :app:assembleDebug --no-daemon \
151
- -PreactNativeArchitectures=x86_64 --max-workers="$cpus"
156
+ -PreactNativeArchitectures=x86_64 -Pandroid.builder.sdkDownload=false --max-workers="$cpus"
152
157
 
153
158
  - uses: actions/setup-python@v5
154
159
  with:
@@ -172,8 +177,9 @@ jobs:
172
177
  - name: Device journey
173
178
  uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2.38.0
174
179
  env:
175
- SHARD_ADMIN_URL: postgresql://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/postgres
176
- SHARD_DB_NAME: <ci-db-name>
180
+ # Replace these keys too; the harness owns their names and database prefix.
181
+ <harness-admin-url-variable>: postgresql://postgres:postgres@127.0.0.1:${{ job.services.postgres.ports['5432'] }}/postgres
182
+ <harness-db-name-variable>: <ci-db-name>
177
183
  with:
178
184
  api-level: <emulator-api>
179
185
  arch: x86_64
@@ -182,8 +188,8 @@ jobs:
182
188
  enable-hw-keyboard: true
183
189
  emulator-port: ${{ env.ANDROID_EMULATOR_PORT }}
184
190
  cores: 4
185
- # At 2 GB (the usual AVD value) the guest kernel's vsock allocations fail and adb drops
186
- # mid-journey, taking every adb reverse with it (references/gotchas.md).
191
+ # Default for this sample. The documented guest-memory ADB failure occurred
192
+ # on specific images; a transport drop alone does not establish that cause.
187
193
  ram-size: 4096M
188
194
  disable-linux-hw-accel: false
189
195
  script: bash <path/to/foundation-journey-wrapper.sh>
@@ -1,13 +1,16 @@
1
1
  # Android CI
2
2
 
3
- Add an Android job to the repo's one `ci.yml`: build the debug APK and run the foundation
4
- journey on an emulator. Copy [assets/android-ci-job.yml](../assets/android-ci-job.yml) and
5
- fill every `<placeholder>`. Follow the `github-actions` skill for the `changes` job, the
6
- `gate` job, runner labels, pinning and hardening; this file covers only what is Android-
7
- specific.
3
+ Integrate the Android build and journey into the repo's existing CI. For a new
4
+ `changes` → area jobs → `gate` design, adapt
5
+ [assets/android-ci-job.yml](../assets/android-ci-job.yml) and fill every placeholder.
6
+ Use `github-actions` for workflow structure, required checks, runner labels, pinning and
7
+ hardening. Do not replace existing required checks or workflows just to match this example.
8
8
 
9
9
  ## Wire it in
10
10
 
11
+ The following is an example for a new gate-based workflow; retain an established repo's
12
+ trigger and required-check contract unless changing it is part of the task.
13
+
11
14
  1. Add an `android` filter to the `changes` job: the app workspace, the native project,
12
15
  the backend code the journey drives, the device harness and journey scripts, the
13
16
  lockfile, and `ci.yml`. Leave docs out.
@@ -34,13 +37,18 @@ specific.
34
37
  `$GITHUB_ENV` and start the ADB server on its own port.
35
38
  - Size Gradle from the cgroup CPU quota (`/sys/fs/cgroup/cpu.max`), not `nproc`. `nproc`
36
39
  reports every host core and thrashes the native build.
40
+ - Verify each runner slot owns its writable Gradle, Android user/AVD, temporary, npm,
41
+ node-gyp and pnpm state. If the runner image already isolates these, keep that contract.
42
+ Otherwise configure private job paths before install and export them to every later
43
+ step, including the emulator. A step-local Android home is insufficient.
37
44
  - Route the Gradle wrapper distribution and Maven repositories through the runner's
38
45
  dependency proxy when it has one. Fail when the proxy variable is missing; never fall
39
46
  back to direct downloads.
40
47
 
41
48
  ## Build
42
49
 
43
- - Build `x86_64` only (`-PreactNativeArchitectures=x86_64`), with `--no-daemon`. Report
50
+ - Build `x86_64` only (`-PreactNativeArchitectures=x86_64`), with `--no-daemon` and
51
+ `-Pandroid.builder.sdkDownload=false`. Report
44
52
  this APK as emulator evidence only. The all-ABI build stays a local or release step.
45
53
  - Bundle the JavaScript with `expo export --platform android` before the native build so
46
54
  bundling errors fail fast.
@@ -49,8 +57,10 @@ specific.
49
57
 
50
58
  ## Database and journey
51
59
 
52
- - Run PostgreSQL as a job service on a random host port, with a health check. Turn off
53
- `fsync` and `synchronous_commit` on it: the database is disposable.
60
+ - Run PostgreSQL only when the journey needs it, as an isolated service with a random
61
+ host port and health check. Disable durability only when measured and when the tests
62
+ do not exercise recovery/persistence semantics. Discover the harness's database variable
63
+ names and required database prefix; map the service explicitly without shared fallbacks.
54
64
  - Run the native auth/integration tests against that service before the device journey.
55
65
  - Unit-test the device orchestration scripts (journey wrapper, slot allocator, code
56
66
  lookup) before booting the emulator.
@@ -75,11 +85,11 @@ specific.
75
85
  and whether it scrolls, and the runner's free disk at preflight. A repo that uploads no
76
86
  capture needs these in the log.
77
87
  - Upload the APK with `if-no-files-found: error`.
78
- - Treat one green run as one run. Fix flaky device failures at their cause instead of
79
- rerunning, and do not change product code for them. An adb drop after boot means guest
80
- RAM ([gotchas](gotchas.md#the-adb-transport-drops-mid-journey)). A `RemoteDisconnected`
81
- with the adb transport still up means the uiautomator2 server was relaunched
82
- ([gotchas](gotchas.md#remotedisconnected-right-after-a-new-process-connects)).
88
+ - Treat one green run as one run. Investigate intermittent device failures rather than
89
+ retrying without a purpose. An ADB drop may match the documented guest-memory issue;
90
+ confirm its transport/kernel evidence before choosing that fix. `RemoteDisconnected`
91
+ with transport still up may match a server restart; verify server/process evidence.
92
+ These are hypotheses, not universal diagnoses; see [gotchas](gotchas.md).
83
93
 
84
94
  ## Traps
85
95
 
@@ -0,0 +1,29 @@
1
+ # Delivery focus
2
+
3
+ Name one immediate checkpoint from the task's existing acceptance criteria: for example,
4
+ open the app and render the expected screen. Keep that target visible while diagnosing;
5
+ passing setup or adding helper code is not a substitute. Each independent work unit has
6
+ its own checkpoint, so this does not serialize unrelated work.
7
+
8
+ - Preserve a known-working source/artifact and relevant environment as a comparison when
9
+ one already exists. Do not start a baseline campaign or count that old artifact as proof
10
+ of the candidate. Reuse caches and valid results under the repo's ownership rules.
11
+ - Run the smallest test that reaches the failing behavior. After it supports the fix,
12
+ run affected acceptance and required CI; do not repeatedly rebuild the full campaign
13
+ to discover the next local defect.
14
+ - Before adding a service, transport or test abstraction, state which existing criterion
15
+ needs it, why the current path cannot answer the question and the smallest alternative.
16
+ Make routine choices within authorization; preserve shared-resource and acceptance
17
+ approval boundaries. Do not expand infrastructure merely because a screen failed.
18
+ - Every continuation states the current checkpoint, new evidence or concrete blocker,
19
+ and the next distinguishing test. Carry prior failures across worker changes. If
20
+ successive attempts leave the same checkpoint unproved, reassess and reduce the case
21
+ or change the approach before assigning another similar attempt. Diagnostics can guide
22
+ that decision but do not count as delivered functionality or reset coordinator limits.
23
+ - Report behavior delivered and criteria still unproved first. Reuse existing results for
24
+ time to reproduce, time to verified fix and full CI runs when available; never invent
25
+ those measurements or create a reporting project to obtain them.
26
+
27
+ When a coordinator owns the run, keep this context in its existing plan note and worker
28
+ result. Follow its retry/replan rules; add no separate ledger, check or acceptance gate.
29
+
@@ -0,0 +1,136 @@
1
+ # Diagnose an existing Android failure
2
+
3
+ Use the smallest investigation that can distinguish the remaining explanations. Reuse
4
+ established resources and caches; do not build a second test platform to explain one
5
+ failure. This procedure works without another diagnosis skill.
6
+
7
+ ## Locate the failing stage
8
+
9
+ First identify the failed source, actual checkout, build variant, artifact provenance,
10
+ device/API/ABI and last successful checkpoint. Do not diagnose an old repo checkout
11
+ as though it were the running candidate. Determine whether code/assets are embedded,
12
+ served by a development server, or delivered through another mechanism.
13
+
14
+ | Stage | Useful evidence and smallest starting point |
15
+ | --- | --- |
16
+ | Build/install | First failing compiler, linker, dependency or package-manager operation; reproduce the affected task before booting a device |
17
+ | Launch | Package and Activity, process start/exit, exception or crash record; use the affected device/runtime when necessary |
18
+ | Load code/assets | Actual resource source and load result; for embedded assets inspect packaging/runtime errors, for remote assets inspect the app's actual request and response |
19
+ | Initialize | Startup exception, configuration, service calls or producer/consumer contract; use a focused host/integration test where it reaches the defect |
20
+ | Render | Foreground Activity, screenshot or hierarchy, runtime errors; distinguish missing rendering from a wrong selector |
21
+ | Interact | State transitions and event ordering around the action; use a deterministic trigger or a bounded repeated lifecycle sequence |
22
+
23
+ Select evidence by stage. A failed compiler does not need a screenshot. A release APK
24
+ with embedded JavaScript does not need Metro. A physical device does not inherit the
25
+ stock emulator's host alias. Preserve the actual failure environment when those
26
+ properties may affect the cause.
27
+
28
+ ## Choose a test that can expose the defect
29
+
30
+ - Use a host test when it executes the real defective logic or process lifecycle.
31
+ - Compose the actual producer and consumer for serialization/protocol defects. Separate
32
+ tests with handwritten fixtures can pass while the integrated path fails.
33
+ - Use the real app/device for native networking, rendering, Activity lifecycle, keyboard
34
+ or runtime behavior that a host double cannot exercise.
35
+
36
+ A fake hierarchy containing the expected screen can prove selector handling, ordering
37
+ or error classification; it cannot prove that the app loaded code and rendered that
38
+ screen. Likewise, a service readiness probe does not establish that the app used the
39
+ same endpoint. Observe the relevant application operation, not just its prerequisite.
40
+
41
+ State competing explanations and what each predicts. Change one relevant variable
42
+ while keeping the others fixed. A failing regression test followed by a passing
43
+ correction may be sufficient. For a safe reversible defect, an optional A/B/A comparison
44
+ can strengthen causal evidence: reproduce, apply one correction, restore that setting
45
+ and see whether the failure returns. Do not make A/B/A a gate for every bug, and do not
46
+ replay authentication, financial or other non-idempotent actions merely to obtain it.
47
+
48
+ For intermittent failures, preserve the trigger conditions, record failures/attempts and
49
+ use a bounded repeated sequence. Fix randomness or timing inputs where appropriate;
50
+ compare baseline and corrected behavior under equivalent conditions. One passing run
51
+ cannot establish reliability, and another sample is justified only when it answers a
52
+ stated question. Do not claim certainty from a small sample.
53
+
54
+ ## Preserve evidence and resource ownership
55
+
56
+ Capture the evidence needed for the failing stage before cleanup deletes it. Preserve
57
+ the earliest exception separately from cleanup status; a cleanup timeout must not
58
+ replace the original error. Keep raw logs private under the repo's retention rules and
59
+ outside a checkout the next job deletes. Publish only sanitized findings. If original
60
+ logs are gone, state that limitation rather than treating a new reproduction as the
61
+ historical recording.
62
+
63
+ Use the repository's established launcher and resource owner. Keep peers' devices,
64
+ ports, databases and writable caches untouched. A borrowed physical device is not a
65
+ disposable AVD: do not reset it or clear its data without task authorization. Reuse a
66
+ shared preparation helper when callers have the same contract, while preserving
67
+ caller-specific behavior that is actually required.
68
+
69
+ A report needs the failed/tested sources, relevant artifact and environment differences,
70
+ reproduction command, controlled change, observations, evidence locations, primary and
71
+ cleanup outcomes, and remaining uncertainty. Do not require an APK hash for a compiler
72
+ failure that produced no APK.
73
+
74
+ ## Bound work and distinguish progress from waiting
75
+
76
+ Give commands and child waits explicit deadlines appropriate to their purpose. Reserve
77
+ cleanup time and terminate only owned process groups. A force-exit option, heartbeat or
78
+ worker's "running" status does not impose a timeout or demonstrate progress. The generic
79
+ `device-run.sh` bounds startup/cleanup probes and supports `JOURNEY_SECONDS` for the
80
+ whole journey. Set a positive value for unattended runs; its backward-compatible
81
+ zero default disables that deadline. Allow time for the owner to finish cleanup.
82
+
83
+ For a hung test, identify the actual outstanding command and last completed assertion.
84
+ If the test waits for a child to exit, check whether its input actually requires exit.
85
+ Reduce that question to a bounded host test before launching another emulator.
86
+
87
+ Continue when an attempt tests a new prediction, collects a missing observation, shrinks
88
+ the reproduction or adds a justified sample for an intermittent failure. State the
89
+ purpose and cost bound first. When no available experiment distinguishes the remaining
90
+ explanations, report the missing evidence/access. Do not restart an unchanged campaign
91
+ or impose an arbitrary fixed number of retries on every kind of failure.
92
+
93
+ Choose the environment the assertion requires: local test resources for ordinary
94
+ functional diagnosis, isolated deployed HTTPS when that behavior requires it, or an
95
+ existing shared deployment for explicitly non-destructive smoke checks. Create only the
96
+ services needed by the test. Do not use shared dev data for destructive fixtures or
97
+ cleanup. A request that never reaches its gateway calls for a transport investigation,
98
+ not an assumed product fix.
99
+
100
+ ## Example: React Native debug app uses another Metro
101
+
102
+ This example applies to a debug build that uses Metro. It is not a prescription for
103
+ release builds, other runtimes or physical-device addressing.
104
+
105
+ Record the host port, device port, reverse mapping, package and effective app settings.
106
+ Select the private ADB endpoint before importing clients that cache it. Prove readiness,
107
+ then observe an actual bundle request, response and screen.
108
+
109
+ For RN 0.81.5, `debug_http_host` takes precedence; otherwise `metro.host` or emulator
110
+ detection chooses the host and a compiled resource supplies the port. A stock emulator
111
+ normally selects `10.0.2.2`. Check the pinned library and build before applying that
112
+ explanation elsewhere. With device `tcp:8081` mapped to host `tcp:8158`, the agreed app
113
+ endpoint might be `127.0.0.1:8081`; copying the host port into the app is not equivalent.
114
+ Do not kill another worker's server if the app accidentally connects to it.
115
+
116
+ - No owned bundle request: inspect selected address, mapping and Activity launch.
117
+ - Request fails: inspect its response or bundling error.
118
+ - Bundle succeeds, expected screen absent: inspect runtime exceptions, actual screen
119
+ and selector.
120
+
121
+ In fmm-express #2001, a local API36 ARM64 comparison failed without the preference,
122
+ rendered Login after setting it, and failed again after removing it. The original API35
123
+ x86_64 CI response was not retained; the local HTTP 500 was not claimed as that response.
124
+ The corrected post-deploy CI subsequently passed on its deployed SHA. Ports, package,
125
+ cloud infrastructure and issue identifiers are case-study details, not requirements.
126
+
127
+ Another repo-specific example was a Node first-login fixture with an empty Organization
128
+ list consumed by Python. Passing the actual producer output through the real reader
129
+ and journey seed selection exposed the mismatch before another cloud/device run. The
130
+ general lesson is to test the composed contract, regardless of language or domain.
131
+
132
+ - [Case study: issue #2001](https://github.com/1aboveio/fmm-express/issues/2001)
133
+ - [Correction PR #2010](https://github.com/1aboveio/fmm-express/pull/2010)
134
+ - [Passing post-deploy run](https://github.com/1aboveio/fmm-express/actions/runs/40329312705)
135
+ - [RN 0.81.5 preference handling](https://raw.githubusercontent.com/facebook/react-native/v0.81.5/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/packagerconnection/PackagerConnectionSettings.kt)
136
+ - [RN 0.81.5 host selection](https://raw.githubusercontent.com/facebook/react-native/v0.81.5/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/AndroidInfoHelpers.kt)
@@ -177,8 +177,10 @@ matches, [confirm the suspected cause](#confirm-a-suspected-cause) before changi
177
177
 
178
178
  ### Postgres setup hooks time out
179
179
 
180
- - **Cause:** durability is on.
181
- - **Fix:** disable `fsync` and `synchronous_commit` on the disposable service.
180
+ - **Possible cause:** durability overhead, if timing or database logs establish it.
181
+ - **Fix:** investigate the slow hook first. Disable `fsync` and `synchronous_commit`
182
+ only on a disposable service when measured and when tests do not require persistence
183
+ or recovery semantics. A timeout by itself does not establish this cause.
182
184
 
183
185
  ### The job never starts
184
186
 
@@ -200,11 +202,13 @@ matches, [confirm the suspected cause](#confirm-a-suspected-cause) before changi
200
202
  - **Cause:** the journey's Backend runs on the runner itself, and the self-hosted runner
201
203
  image has no browser (or other app-launched tool). A developer machine does, so it only
202
204
  fails in CI.
203
- - **Fix:** don't install it on the runner, and don't treat it as a product bug. Point the
204
- app's browser variable (`CHROMIUM_PATH`) at a wrapper that runs the pinned Playwright
205
- image's browser: `github-actions` → `references/runners.md`, "A host process that needs
206
- a browser binary". Prove it in CI; Docker Desktop on macOS cannot reach the wrapper's
207
- host-network port.
205
+ - **Fix:** inspect the runner's supported browser packaging first. One option is the
206
+ pinned Playwright-image wrapper described by `github-actions` →
207
+ `references/runners.md`, "A host process that needs a browser binary". Reproduce the
208
+ failing command and verify the wrapper on a compatible isolated Linux environment
209
+ before CI acceptance; Docker Desktop on macOS cannot prove that host-network path.
210
+ If no compatible diagnostic environment is available, report that gap and collect
211
+ targeted evidence rather than sending an unverified configuration fix to CI.
208
212
 
209
213
  ### A failed run's Metro log is gone
210
214
 
@@ -215,7 +219,12 @@ matches, [confirm the suspected cause](#confirm-a-suspected-cause) before changi
215
219
 
216
220
  ## Confirm a suspected cause
217
221
 
218
- Inject the suspected cause on purpose, for example `adb reverse --remove tcp:8081` right
219
- before the failing step, and check that it reproduces the exact failure signature: the same
220
- step, error and error count. Then show that the fix passes the same injection. A cause that
221
- does not reproduce its signature is a guess, and a fix for a guess is not proof.
222
+ Choose a test that can distinguish the suspected cause from its alternatives, as described
223
+ in [diagnosis.md](diagnosis.md#choose-a-test-that-can-expose-the-defect). A regression test
224
+ that reproduces the defect and passes with the correction may suffice. When safe and
225
+ relevant, deliberate fault injection can strengthen the evidence: for example, remove a
226
+ reverse mapping on an owned test device and compare the failure signature before and
227
+ after the correction. Injection and A/B/A are optional techniques, not universal gates.
228
+ For intermittent failures, compare bounded samples under equivalent conditions rather
229
+ than requiring an identical error count. Report a cause as unconfirmed when the evidence
230
+ does not distinguish it; do not manufacture certainty from a passing run.
@@ -50,6 +50,8 @@ export SETUP_AVD=<new-unique-avd-name>
50
50
  export EMULATOR_PORT=<even-port-5554-5584>
51
51
  export ANDROID_BACKEND_PORT=<free-port>
52
52
  export ANDROID_METRO_PORT=<free-port>
53
+ # Choose the whole-journey deadline; zero disables it and is not suitable for unattended runs.
54
+ export JOURNEY_SECONDS=<positive-journey-timeout-seconds>
53
55
  ENV
54
56
  source .cache/android-env.sh
55
57
  mkdir -p "$TMPDIR" "$npm_config_cache" "$npm_config_devdir" \
@@ -63,8 +65,10 @@ for component in platforms/android-<api> build-tools/<build-tools> ndk/<ndk> cma
63
65
  done
64
66
  ```
65
67
 
66
- If the wrapper reads its port or Python variables under other names, export those names in
67
- `android-env.sh` instead.
68
+ If the wrapper reads ports or Python under other names, export aliases in
69
+ `android-env.sh` **as well as** the bundled runner's required names. For example,
70
+ `export APP_METRO_PORT="$ANDROID_METRO_PORT"`; both must select the same port. Adapt
71
+ `DB_URL_VAR` and `DB_NAME_VAR` to the actual harness, not its fallback defaults.
68
72
 
69
73
  ## 2. Install and check
70
74
 
@@ -152,13 +156,18 @@ Pass each command as separate words, not as one quoted string. The script:
152
156
  2. Refuses an emulator port outside 5554–5584 and any busy port.
153
157
  3. Starts the ADB server, then the emulator (its PID recorded), then `postgres` with
154
158
  `--cidfile` on a random loopback port. Override the image with `POSTGRES_IMAGE`.
155
- 4. Waits for `sys.boot_completed=1` and `pg_isready`. Every command has a 30-second limit
156
- (`BOUNDED_SECONDS`) that kills the command's whole process group; exit 124 is terminal.
159
+ 4. Waits for `sys.boot_completed=1` and `pg_isready`. Startup/readiness and cleanup
160
+ commands have a 30-second limit (`BOUNDED_SECONDS`); exit 124 is terminal. The journey
161
+ uses the separate `JOURNEY_SECONDS` deadline. Leave time for cleanup after that deadline.
157
162
  5. Exports `$DB_URL_VAR`, `$DB_NAME_VAR` (`$DB_NAME_PREFIX` plus a unique suffix) and
158
163
  `ANDROID_EMULATOR_SERIAL`, then runs the journey.
159
164
  6. Drops the database, stops the emulator PID (`TERM`, then `KILL` after 10 seconds),
160
165
  removes the container by its CID, and prints `original_stage_exit=<n> cleanup_exit=<n>`.
161
166
  It exits with the journey's status if the journey failed, else the cleanup status.
162
167
 
163
- The journey stops its own backend and Metro children. Capture the command's exit status and
164
- the last output line for the evidence record.
168
+ The runner supervises the journey's process group. Journey children must stay in that
169
+ group; a wrapper that deliberately creates detached services must stop those services
170
+ through its own owner. Send TERM to the launcher and allow its cleanup to finish rather
171
+ than killing it immediately. The generic runner inherits the caller's ADB endpoint and
172
+ does not stop that server: use a verified private endpoint on a shared host and close it
173
+ through the caller's owner. Capture the command's exit status and final summary line.