Skip to content

feat(perps): decouple agentic cache fingerprint from project EAS fingerprint#30569

Merged
abretonc7s merged 5 commits into
mainfrom
feat/perps/agentic-cache-fp-overrides
May 22, 2026
Merged

feat(perps): decouple agentic cache fingerprint from project EAS fingerprint#30569
abretonc7s merged 5 commits into
mainfrom
feat/perps/agentic-cache-fp-overrides

Conversation

@abretonc7s

@abretonc7s abretonc7s commented May 22, 2026

Copy link
Copy Markdown
Contributor

Description

Adds scripts/perps/agentic/lib/compute-cache-fp.js, an agentic-local native-build fingerprint, and switches the build cache in bc_fingerprint to use it instead of scripts/generate-fingerprint.js. The project-wide fingerprint script and fingerprint.config.js are untouched, so EAS Build, EAS Update, and the OTA fingerprint guard in nightly-ota-updates.md keep their existing semantics.

Why: --mode auto's shared cache (#30565) was keyed off the same fingerprint EAS/OTA depend on, which conservatively hashes build outputs (ios/build/, .gradle/, IDE xcuserdata, env-populated xcconfig/google-services.json). Those paths diverge per worktree, so two slots on the same commit hashed to different keys and never shared a cached .app — the cross-worktree benefit the cache was designed for never landed. The new fingerprint uses the same extraSources (so anything that genuinely affects the binary still participates) but ignores the per-worktree noise paths.

Verified across three worktrees on the same commit (c06187a24c, all on main):

mm-1: c7fe9e2161109d4ff2e092e068821a2e9984aac5
mm-5: c7fe9e2161109d4ff2e092e068821a2e9984aac5
mm-6: c7fe9e2161109d4ff2e092e068821a2e9984aac5

Identical → next --mode auto dispatch on any of these slots will install the cached artifact from whichever slot built first.

Changelog

CHANGELOG entry: null

Related issues

Follows #30565.

Manual testing steps

Feature: Agentic cache fingerprint decoupled from project fingerprint

  Scenario: Project fingerprint unchanged
    When I run "node scripts/generate-fingerprint.js"
    Then the hash is the same as on `main` before this PR
    And EAS / OTA tools that depend on it are unaffected

  Scenario: Agentic cache fingerprint ignores build artifacts
    Given a worktree at any state
    When I capture the agentic fingerprint
    And I write a poison file under `ios/build/`
    And I capture the agentic fingerprint again
    Then the two fingerprints are identical

  Scenario: Cross-worktree fingerprint match on same commit
    Given two worktrees (mm-5, mm-6) at the same git commit
    When I compute the agentic fingerprint in each
    Then they match
    And `--mode auto` on the second slot installs from the cached artifact stored by the first

Programmatic check the test suite runs:

bash scripts/perps/agentic/lib/test-build-cache.sh

New section "agentic fp ignores build artifacts" verifies the ignorePaths actually take effect.

Screenshots/Recordings

N/A — script-only change, no UI surface.

Before

N/A

After

N/A

Pre-merge author checklist

  • I've followed MetaMask Contributor Docs and MetaMask Mobile Coding Standards.
  • I've completed the PR template to the best of my ability
  • I've included tests if applicable (new "agentic fp ignores build artifacts" assertion in test-build-cache.sh)
  • I've documented my code using JSDoc format if applicable (file-level rationale in compute-cache-fp.js)
  • I've applied the right labels on the PR

Performance checks (if applicable)

  • I've tested on Android — N/A (script-only)
  • I've tested with a power user scenario — N/A
  • I've instrumented key operations with Sentry traces — N/A (developer tooling)

Pre-merge reviewer checklist

  • I've manually tested the PR.
  • I confirm that this PR addresses all acceptance criteria.

Note

Medium Risk
Changes the cache key used for agentic preflight native build reuse; incorrect ignore/hashing boundaries could cause stale or mismatched cached binaries across worktrees.

Overview
Decouples the agentic shared native build cache fingerprint from the repo-wide EAS/OTA fingerprint by introducing scripts/perps/agentic/lib/compute-cache-fp.js and switching bc_fingerprint to use it.

The new fingerprint inherits fingerprint.config.js extraSources (plus explicitly hashes app/core/InpageBridgeWeb3.js) while adding ignorePaths for per-worktree build outputs (e.g., ios/build, Xcode xcuserdata, .gradle, NDK .cxx) so cache artifacts can be shared across parallel worktrees.

Updates agentic docs to describe the new keying behavior and extends test-build-cache.sh with boundary tests ensuring ignored paths don’t shift the fingerprint while binary-affecting sources still do (and adjusts the fast-mode failure test to reference the new script).

Reviewed by Cursor Bugbot for commit 32aa686. Bugbot is set up for automated code reviews on this repo. Configure here.

…erprint

The shared build cache that backs `--mode auto` was keyed by the same
fingerprint EAS Build and EAS Update use (`scripts/generate-fingerprint.js`
via `fingerprint.config.js`). That fingerprint conservatively hashes
build outputs (`ios/build/`, `.gradle/`, IDE state, env-populated
`xcconfig`/`google-services.json`) on the theory that they could
conceivably influence the produced binary. For EAS / OTA that is the
right call: never reuse a build whose inputs you cannot vouch for.

For the agentic cache it is the wrong call. Build outputs are
non-deterministic across worktrees, so two parallel slots on the same
commit produce different keys and never share a cached `.app` — the
cross-worktree win the cache was designed for never lands. Re-running
on the same slot, even on the same branch, can also drift the key as
the build itself mutates hashed inputs.

Add `scripts/perps/agentic/lib/compute-cache-fp.js`, an agentic-local
fingerprint that uses the same `extraSources` (so anything that genuinely
affects the binary still participates) but `ignorePaths` the per-worktree
build artifacts. `bc_fingerprint` now invokes this instead of the
repo-wide script. EAS / OTA pipelines continue to use
`scripts/generate-fingerprint.js` and `fingerprint.config.js` unchanged.

Verified against three worktrees on the same commit
(c06187a, branch=main):

  mm-1: c7fe9e2161109d4ff2e092e068821a2e9984aac5
  mm-5: c7fe9e2161109d4ff2e092e068821a2e9984aac5
  mm-6: c7fe9e2161109d4ff2e092e068821a2e9984aac5

A new unit test asserts the fingerprint is unaffected by poisoning an
ignored path (`ios/build/`).
@github-actions

Copy link
Copy Markdown
Contributor

CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes.

@github-actions github-actions Bot added the pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. label May 22, 2026
@metamaskbotv2 metamaskbotv2 Bot added the team-perps Perps team label May 22, 2026
@abretonc7s abretonc7s added the no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed label May 22, 2026
@abretonc7s abretonc7s marked this pull request as ready for review May 22, 2026 14:28
@abretonc7s abretonc7s requested a review from a team as a code owner May 22, 2026 14:28
@abretonc7s abretonc7s added skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. skip-e2e skip E2E test jobs and removed pr-not-ready-for-e2e Skip E2E and block merging. Remove this label once the PR is ready to run the E2E tests. labels May 22, 2026
@abretonc7s abretonc7s enabled auto-merge May 22, 2026 14:30
Comment thread scripts/perps/agentic/lib/compute-cache-fp.js
…ss claim

R1 caught two issues with the initial decoupled-fp design:

B1. `ios/*.xcconfig`, `android/app/google-services.json`, and
    `android/app/src/main/assets/InpageBridgeWeb3.js` were on the
    ignorePaths list. All three are read at build time and embedded in
    the produced binary — ignoring them means the cache could serve a
    binary built against different secrets / Firebase config / runtime
    JS bridge. Remove them.

B2. `createFingerprintAsync` always loads `fingerprint.config.js` and
    merges the project config with caller options. The script's claim
    of "bypassing" the config was wrong — we extend it. Update the
    source comment, README, and bc_fingerprint comment to describe the
    actual relationship.

Add `app/core/InpageBridgeWeb3.js` to extraSources so JS-only changes
to the bridge source still invalidate the cache after we ignore the
generated android-asset mirror.

Tests now assert both halves of the boundary:
- poisoning an ignored path (`ios/build/`) must NOT shift the fp
- poisoning a hashed binary-affecting input (`InpageBridgeWeb3.js`)
  MUST shift the fp

Verified mm-1 and mm-6 (aligned env state) still converge to the same
fp; mm-5 (different `.ios.env` + missing `google-services.json`)
correctly diverges — the cache only reuses across worktrees when the
actual build inputs match.
@github-actions github-actions Bot added size-M and removed size-S labels May 22, 2026
…poison

R2 found that `createFingerprintAsync(projectRoot, options)` OVERRIDES
the config's `extraSources` rather than merging them — passing only the
bridge source dropped the six project extraSources from
`fingerprint.config.js` (`.yarn/patches`, `.github/workflows`,
`.github/scripts`, `react-native.config.js`, `scripts/build.sh`,
`scripts/setup.mjs`), regressing coverage relative to the project
fingerprint.

Mirror the project's extraSources verbatim in `compute-cache-fp.js` and
append the bridge source. Update the file header comment to describe
the actual override-vs-merge semantics.

R2 nits:
- Test that mutates `app/core/InpageBridgeWeb3.js` now uses a trap-based
  restore helper so a fingerprint failure cannot leave the worktree
  poisoned.
- Add a regression test that poisoning a project extraSource (e.g.
  `scripts/setup.mjs`) shifts the agentic fp, proving the inherited
  extraSources actually participate.

Cross-worktree convergence still works for aligned-env slots (mm-1 ≡ mm-6
on the same env state hash to identical fp); mm-5 correctly diverges
because its `.ios.env` differs.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 303aa11. Configure here.

Comment thread scripts/perps/agentic/lib/test-build-cache.sh Outdated
… merge semantics

R3 left two non-blocking nits, both addressed:

- `_poison_must_shift_fp` no longer clobbers the suite-level EXIT trap.
  Capture the previous trap via `trap -p EXIT` before layering the
  temporary restore trap, then re-install the original via `eval`. An
  early abort inside the helper still triggers `.agent/build-cache`
  cleanup.
- File header comment in `compute-cache-fp.js` was inaccurate: only
  `extraSources` is overridden by caller options; `ignorePaths` is
  merged with the config's list. Comment now matches `@expo/fingerprint`
  0.15.x behaviour.
…cating extraSources

Bugbot caught that manually duplicating the project's extraSources is
brittle: future edits to fingerprint.config.js would silently fail to
flow into the agentic fingerprint because the explicit options array
overrides the config's.

`require()` the project config directly and spread its `extraSources`
and `ignorePaths` into our options. The agentic fingerprint now stays
in sync with `fingerprint.config.js` by construction; we just append
the bridge source + per-worktree-artifact ignore paths.
@sonarqubecloud

Copy link
Copy Markdown

@abretonc7s abretonc7s added this pull request to the merge queue May 22, 2026
Merged via the queue into main with commit 65cbeec May 22, 2026
160 checks passed
@abretonc7s abretonc7s deleted the feat/perps/agentic-cache-fp-overrides branch May 22, 2026 16:17
@github-actions github-actions Bot locked and limited conversation to collaborators May 22, 2026
@metamaskbotv2 metamaskbotv2 Bot added the release-7.80.0 Issue or pull request that will be included in release 7.80.0 label May 22, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

no-changelog no-changelog Indicates no external facing user changes, therefore no changelog documentation needed release-7.80.0 Issue or pull request that will be included in release 7.80.0 size-M skip-e2e skip E2E test jobs skip-sonar-cloud Only used for bypassing sonar cloud when failures are not relevant to the changes. team-perps Perps team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants