Skip to content
Merged
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
63 changes: 63 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# CLAUDE.md (`.claude/`)

Guidance specific to Claude Code sessions that open pull requests against this
repository (including automated/scheduled sessions). See the root `CLAUDE.md`
and `AGENTS.md` for everything else.

## Attach CI labels when you open a PR

`.github/workflows/check.yml`'s `pull_request` trigger only fires on
`opened`, `synchronize` and `reopened` β€” **not** `labeled`. Several of its
jobs are gated behind a label check evaluated against that triggering
event's payload, e.g.:

```yaml
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/next' || contains(github.event.pull_request.labels.*.name, 'Host 🏑')
```

A label added after the PR is already open does nothing on its own β€” there
is no new `opened`/`synchronize`/`reopened` event for the workflow to
re-evaluate against, so the gated job silently never runs, and that gap is
easy to miss since the Check run still shows green (the job wasn't
skipped-and-failed, it just never triggered).

The label name in the `if:` condition has to match a real, currently-existing
GitHub label exactly (name and emoji). `host-cpp-tests` checked for a label
literally named `host` for a while, when the repository's real label was
`Host 🏑` β€” the condition never matched anything anyone would actually apply,
so the job silently only ran on pushes to `main`/`next`. Confirm the label
exists (e.g. via the GitHub MCP `get_label` tool) before trusting a condition
or table like the one below.

The `create_pull_request` GitHub MCP tool has no `labels` parameter, so
labels can only be attached in a follow-up call after the PR exists β€” which
is exactly the case above. **Whenever you open a PR here:**

1. Decide which of the labels below apply, based on what the diff touches.
2. Attach them immediately after creating the PR (e.g. `issue_write` with
`method: "update"`, or the equivalent `gh pr edit --add-label`).
3. Push one more commit to the branch β€” even a trivial or `--allow-empty`
one β€” so a `synchronize` event fires and the gated jobs actually run with
the labels now present. Labeling without this step means the relevant CI
never runs before merge.

## Label β†’ job map

| Label | Gated job(s) | Attach when the diff touches |
| --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Host 🏑` | Host C++ tests | `packages/host/cpp/`, `packages/host/android/CMakeLists.txt`, the generated injector, or anything in `packages/weak-node-api` that the host links against |
| `Apple 🍎` | iOS test app build/run | iOS/macOS/tvOS/visionOS build config, XCFrameworks, Cocoapods, Xcode project files, or any change to Node-API behavior addons rely on (buffers, fatal-error handling, etc.) that device tests would catch |
| `Android πŸ€–` | Android test app build/run (self-hosted runner; currently label-gated even on `main`/`next`, see the `if:` comment in `check.yml` β€” check whether that's still true before relying on it) | Gradle, NDK, Android SDK, `.android.node` packaging, or the same cross-platform Node-API behavior changes as above |
| `MacOS πŸ’»` | macOS test app | `react-native-macos`-specific code paths |
| `Ferric πŸ¦€` | Ferric Apple triplets build | `packages/ferric`, `packages/ferric-example`, or anything napi-rs/Cargo related |
| `weak-node-api` | weak-node-api tests | `packages/weak-node-api` |

A PR can need more than one label β€” e.g. a change to `RuntimeNodeApi.cpp`
that alters buffer semantics warrants `Host 🏑` plus `Apple 🍎` and
`Android πŸ€–`, since the actual behavior change can only be verified on a
real device.

When in doubt, prefer attaching a label and letting the job run (mirroring
what the label's own description says on GitHub) over guessing it isn't
needed β€” a job that runs and passes costs a bit of CI time; a real device
regression that ships because the label was skipped costs much more.
Loading