Drop the hexagon symbol-count tripwire from the payload gate - #902
Merged
Conversation
The count asserted no capability. Against the regression it was built for -- Android release builds shipping without the Hexagon backend, issue #858 -- mustExport fails on its own: PR #859's own A/B shows both named symbols absent in the no-SDK run, with all 12 libraries and all 4 DSP assets present. Every other layer is independent of it: the SDK tarball and consumed-subset digests, the build-mode assertion, the variant-allowlist log check, required libraries, and the DSP assets verified as EM_QDSP6 objects. What it detected was change, not brokenness, and its only remedy was re-declaring the number -- so an upgrade that legitimately grew the symbol surface was indistinguishable from one that shrank it, and both were resolved by editing the number. It first came due on the llama.rn 0.13.0-rc.3 bump, where the hexagon surface grew from 16 to 28 because upstream added multi-device allreduce, async tensor copy and events. Nothing was wrong. mustExport now carries the rule alone, and the manifest validator requires it to be present and non-empty rather than accepting a count as an alternative demand, so the weakening shape the validator exists to refuse has one fewer way to pass. The report keeps the llama.rn version stamp, moved onto the .dynsym entries line, so the evidence still says which build it read.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Removes
expectedMatchCount— thehexagon.dynsymcount — from the Android payload gate.mustExportcarries the symbol rule alone.Why
The count asserted no capability. Against the regression it exists for (#858, Android release builds shipping without the Hexagon backend), #859's own A/B experiment shows
mustExportfailing on its own:lm_ggml_backend_hexagon_reglm_ggml_backend_is_hexagon.dynsymmatchesThe broken APK satisfied every library and asset rule — that is why a symbol rule is needed at all — but
mustExportalone rejects it. The count reported0, which is the same fact stated twice. Every other layer is independent of it: the SDK tarball and consumed-subset digests, the build-mode assertion, the variant-allowlist log check, required libraries, and the DSP assets verified asEM_QDSP6objects.What the count detected was change, not brokenness, and its only remedy was re-declaring the number. So an upgrade that legitimately grew the symbol surface and one that gutted it were resolved the same way — by editing the number until CI was green. A gate whose documented remedy is to silence it does not merely cost a CI round-trip; it launders the change as reviewed.
It first came due on #901 (llama.rn
0.13.0-rc.1→0.13.0-rc.3), where the count moved 16 → 28 and nothing was wrong:ggml-hexagon.his byte-identical across the two versions, and the growth is upstream adding multi-device allreduce, async tensor copy and events, and a host buffer type — hexagon-named identifiers in the vendored tree go 139 → 187.16 was never an invariant. It was the measurement that proved #858, promoted to a permanent expectation on the strength of reading the same number twice. That promotion is the defect being removed.
What changes
scripts/android-payload-manifest.json— the rule and itscountRulenote are gone.scripts/verify-android-payload.js— enforcement removed. The manifest validator is stricter, not looser:mustExportmust now be present, a list, and non-empty, rather than being satisfiable by a count. The weakening shape the validator exists to refuse — emptyingmustExportduring a dependency bump — has one fewer way to pass.llama.rnversion stamp, moved onto the.dynsymentries line, so the evidence still names the build it read.What is unchanged
Every layer that asserts a capability: SDK provisioning digests,
rnllamaBuildFromSource, the allowlist reaching gradle, required libraries, DSP assets and their ELF machine, and bothmustExportsymbols being defined. The incident this gate was built for is still caught, by the rule that caught it.Verification
npx jest scripts/— 11 suites, 205 tests, all passing. ESLint and Prettier clean on the changed files.The negative tests are the point, so they were kept honest rather than trimmed: a build with neither named symbol defined still fails, as an APK and as an AAB; a symbol present only as an undefined import still fails; and the manifest-weakening matrix still refuses a rule that asserts nothing, one whose
mustExportwas emptied, and one naming no library. The three cases that existed only to policeexpectedMatchCount's own shape are gone with it.Not covered by CI: no built artifact was checked locally. The claim rests on #859's calibration of the reader against
llvm-nm -Don two real artifacts, which this change does not touch.Generated by PocketPal Dev Team