Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .changeset/expo-verify-port-sessions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
4 changes: 2 additions & 2 deletions .claude/skills/verify-clerk-expo/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ A Mac has four iOS lanes and two Android lanes, shared by every worktree on it.

### Borrow a device on a CI runner

A machine that is not a Mac cannot run the simulator, and a machine with no hardware virtualization cannot run the emulator. There the CLI leases a device on a GitHub Actions runner and drives it through a tunnel. That machine needs Node 24.8.0 or newer on 24, the Platform API key, and access to GitHub, and `doctor` checks each. In the worktree it needs `npm ci --prefix integration/expo-native` and no `pnpm install`, because the runner builds the app. The session builds a pushed commit, never your working tree, so commit and push before `up` or `run`.
A machine that is not a Mac cannot run the simulator, and a machine with no hardware virtualization cannot run the emulator. There the CLI leases a device on a GitHub Actions runner and drives it through a tunnel. That machine needs Node 24.8.0 or newer on 24, the Platform API key, and access to GitHub, and `doctor` checks each. In the worktree it needs `npm ci --prefix integration/expo-native` and no `pnpm install`, because the runner builds the app. The session builds a pushed commit. When the app sources differ from it, `up` and `run` send the difference with it, and the session builds the commit with your changes on top.

```console
$ git push
Expand Down Expand Up @@ -225,7 +225,7 @@ On a machine whose `gh` can attach, `attach` edits the description itself and pr

When this machine cannot attach and there is no session to hand the files to, or the hand-off fails, `attach` fails and says which. Then name the run id in the PR and say that the evidence was not attached. A run on a local device has no session, so its fix is a newer `gh`. [Remote devices](references/remote.md) has what the repository needs before a hand-off can be published, and its limits.

`attach` writes only to an open pull request, and fails on one that is closed or merged. It refuses a run that is tainted, that has a failing spec or no passing one, or whose `app.log` names a user that the run did not create. A before run can have failing specs. `attach` refuses a before run that is tainted, that was never sealed, or whose `app.log` names a user that the run did not create.
`attach` writes only to an open pull request, and fails on one that is closed or merged. It refuses a run that is tainted, that ran on a session build with uncommitted changes, that has a failing spec or no passing one, or whose `app.log` names a user that the run did not create. A before run can have failing specs. `attach` refuses a before run that is tainted, that ran on a session build with uncommitted changes, that was never sealed, or whose `app.log` names a user that the run did not create.

Work in this order, with one `up` for both runs: make the branch and `git push` it, `up`, `run` the spec without your change when it changes something that exists, make the change, commit, `git push`, `run` the spec again, open the pull request, `attach` with the before run as `--before <run-id>`, `down`. Open the pull request after the last run, so that it is not left open without its evidence. Commit before the second `run`, so that the line `attach` writes names a commit the pull request holds. In the pull request, name the run id and the specs you ran, and say what you did not run.

Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/verify-clerk-expo/references/freshness.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,4 @@ A JS edit does not change it, and a new version of a JS-only package does not ch

A later standalone build with the same fingerprint runs no `expo prebuild`, `xcodebuild`, or Gradle. It builds the workspace packages, exports the bundle from the working tree with `expo export:embed`, compiles it with the test app's `hermesc`, and puts it in a copy of the kept app. The build fails unless the app then holds exactly the bundle it compiled. It builds natively instead, and prints `not reused:` with the reason, when the kept app holds no Hermes bundle, when it runs another Hermes bytecode version, when an Android bundle has image assets, or when the Android SDK has no build-tools 35 or newer to align the APK again. On Android the app is signed with the generated project's debug keystore when the working tree has one and with a new key otherwise, so a device that already holds the app under another key needs it uninstalled first.

A job of the workflow that had to build natively stores the app as a run artifact named `verify-expo-native-<platform>-<fingerprint>` for seven days, and a later job takes it only from a run of the same branch of this repository. When there is none, the job builds natively. Unset, nothing is kept and every standalone build is a native build. A remote session does not set it.
A job of the workflow that had to build natively stores the app as a run artifact named `verify-expo-native-<platform>-<fingerprint>` for seven days, and a later job takes it only from a run of the same branch of this repository. When there is none, the job builds natively. Unset, nothing is kept and every standalone build is a native build. A remote session sets it. Before its agent starts, the session downloads the native builds of its platform that the newest runs of the workflow on the same branch kept, at most three, each under its fingerprint. `up` then builds natively only when none of them has the fingerprint of the tree it builds. A session stores no native build, because the artifacts of a run are public. It stores no DerivedData or Pods either. It saves the pnpm store on Android and on a Blacksmith runner, and the Gradle cache on a Blacksmith runner.
32 changes: 16 additions & 16 deletions .claude/skills/verify-clerk-expo/references/output.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,19 @@ On an error the object is `{ "ok": false, "error": { "code", "message", "fix", "

`retryable` is true for `POOL_FULL`, `DEVICE_BUSY`, `LEASE_LOST`, and `RATE_LIMITED`. For those, the same command can succeed later with no other change.

| Code | Meaning |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `USAGE` | The command line, a spec's declaration, or an environment variable is malformed |
| `NOT_READY` | A precondition is missing, such as Metro that does not serve the current code. The fix names it |
| `POOL_FULL` | All four iOS lanes, or both Android lanes, on this machine are in use |
| `DEVICE_BUSY` | Another command in this worktree is driving the device, or a run on the other platform is using this worktree's application |
| `LEASE_LOST` | The leased device or the remote session is gone |
| `BUILD_FAILED` | A step of the test app's build failed, such as `turbo build`, `expo prebuild`, `xcodebuild`, or `gradlew`. The message names the step and has the last 15 lines of its output. With the remote backend, also that the app sources have uncommitted changes, that GitHub does not have HEAD, or that the session could not build the commit |
| `KEYS_MISSING` | No Platform API credential works on this machine, or `AI_GATEWAY_API_KEY_FILE` names a file that is missing, empty, or readable by other users |
| `INSTANCE_MISCONFIGURED` | The Clerk instance does not show the settings a spec needs |
| `NOT_TEST_IDENTITY` | Reserved. No command raises it. A run whose `app.log` names a user that the run did not create fails `attach` with `EVIDENCE_UNSAFE` |
| `NO_SPECS` | The selection matched no spec, or no selected spec ran |
| `E2E_CRASHED` | e2e exited without a readable report. Read `e2e.log` in the run directory |
| `EVIDENCE_UNSAFE` | The run cannot be attached, or a path is not safe to delete |
| `UNSUPPORTED` | This machine cannot do what the command asked, such as `--backend local` for a device it cannot run |
| `RATE_LIMITED` | Clerk's Platform API kept answering 429 |
| Code | Meaning |
| ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `USAGE` | The command line, a spec's declaration, or an environment variable is malformed |
| `NOT_READY` | A precondition is missing, such as Metro that does not serve the current code. The fix names it |
| `POOL_FULL` | All four iOS lanes, or both Android lanes, on this machine are in use |
| `DEVICE_BUSY` | Another command in this worktree is driving the device, or a run on the other platform is using this worktree's application |
| `LEASE_LOST` | The leased device or the remote session is gone |
| `BUILD_FAILED` | A step of the test app's build failed, such as `turbo build`, `expo prebuild`, `xcodebuild`, or `gradlew`. The message names the step and has the last 15 lines of its output. With the remote backend, also that GitHub does not have HEAD, that the session could not build the commit, or that the uncommitted changes to the app sources do not apply to it, change a file outside the app sources, or are larger than 16 MiB. A session on `main` refuses uncommitted changes |
| `KEYS_MISSING` | No Platform API credential works on this machine, or `AI_GATEWAY_API_KEY_FILE` names a file that is missing, empty, or readable by other users |
| `INSTANCE_MISCONFIGURED` | The Clerk instance does not show the settings a spec needs |
| `NOT_TEST_IDENTITY` | Reserved. No command raises it. A run whose `app.log` names a user that the run did not create fails `attach` with `EVIDENCE_UNSAFE` |
| `NO_SPECS` | The selection matched no spec, or no selected spec ran |
| `E2E_CRASHED` | e2e exited without a readable report. Read `e2e.log` in the run directory |
| `EVIDENCE_UNSAFE` | The run cannot be attached, or a path is not safe to delete |
| `UNSUPPORTED` | This machine cannot do what the command asked, such as `--backend local` for a device it cannot run |
| `RATE_LIMITED` | Clerk's Platform API kept answering 429 |
Loading
Loading