[GH-ISSUE #3368] [Bug] Package inspection rounds distinct Android version codes to the same value #1234

Closed
opened 2026-10-16 21:03:08 +00:00 by bsakaguchi · 0 comments
Owner

Originally created by @coygeek on GitHub (Oct 14, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/3368

Before submitting

  • I searched the open and closed issues for a related report.
  • I removed credentials, tokens, private paths, and sensitive target data.

Area

Evidence, artifacts, or reconstruction

Observed behavior

inspect-adb-package converts a positive 64-bit Android version code to an inexact JavaScript number and returns it with confidence: "observed" and coverage: "complete". Two distinct reported versions, 9007199254740992 and 9007199254740993, produce the same normalized version and Evidence ID. The original decimal spelling is absent from the returned Evidence, so callers cannot recover which version Package Manager reported.

Both CLI requests exited with status 0. The second request's versionCode=9007199254740993 became 9007199254740992, and the two observations shared an Evidence ID. A separate control with versionCode=9007199254740991 retained that exact value. These observations establish the production CLI's response normalization with a local producer fixture; no live Android device was exercised.

Reproduction

  1. Start from a clean checkout and prepare the runtime:
git clone https://github.com/morluto/rea.git
cd rea
git checkout 8dde6370d0809ad04cda3342d4e6f290f48aa063
npm ci
npm run build:cached
  1. From the repository root, run the following local CLI reproduction. The executable models only adb version and the Package Manager response consumed by this operation; it never contacts a device. Android can represent these positive values as long version codes, with versionCodeMajor=2097152 and low version codes 0 and 1.
work=$(mktemp -d)
mkdir -p "$work/home"
cat > "$work/adb" <<'JS'
#!/usr/bin/env node
let args = process.argv.slice(2);
if (args[0] === 'version') {
  console.log('Android Debug Bridge version 1.0.41\nVersion 34.0.5-fixture\nInstalled as ' + __filename);
  process.exit(0);
}
if (args[0] === '-s') args = args.slice(2);
if (args.join(' ') !== 'shell dumpsys package com.example.app') process.exit(90);
console.log('Packages:\n  Package [com.example.app] (123):\n    userId=10000\n    versionCode=' + process.env.VERSION_CODE + ' minSdk=28 targetSdk=34\n    versionName=1.0\n    requested permissions:\n      android.permission.INTERNET\n    install permissions:\n      android.permission.INTERNET: granted=true');
JS
chmod +x "$work/adb"
env HOME="$work/home" REA_ADB_PATH="$work/adb" VERSION_CODE=9007199254740992 \
  node scripts/rea.mjs inspect-adb-package probe-device com.example.app --format json > "$work/first.json"
env HOME="$work/home" REA_ADB_PATH="$work/adb" VERSION_CODE=9007199254740993 \
  node scripts/rea.mjs inspect-adb-package probe-device com.example.app --format json > "$work/second.json"
node - "$work" <<'JS'
const fs = require('node:fs');
const root = process.argv[2];
const first = JSON.parse(fs.readFileSync(root + '/first.json', 'utf8'));
const second = JSON.parse(fs.readFileSync(root + '/second.json', 'utf8'));
console.log(JSON.stringify({
  first_version_code: first.normalized_result.version_code,
  second_version_code: second.normalized_result.version_code,
  same_evidence_id: first.evidence_id === second.evidence_id,
  confidence: second.confidence,
  coverage: second.normalized_result.coverage,
  raw_result: second.raw_result
}, null, 2));
JS
rm -rf "$work"
  1. Compare the printed normalized version codes and Evidence identity with the two distinct VERSION_CODE inputs. Both returned values are 9007199254740992, same_evidence_id is true, and raw_result is null. The script removes its disposable fixture directory after the comparison.

Expected behavior

docs/adb-device-analysis.md:90, under Operations, documents inspect_adb_package as a dumpsys package projection of the device's version declarations. AGENTS.md:29 requires preserving source values and explicit unknowns when normalization loses information.

The observation must preserve the exact version Package Manager reported. A value that the numeric representation cannot retain exactly must keep its original spelling or an explicit unknown alongside recoverable source evidence. It must not become a different fully observed version. The two different version responses must remain distinguishable.

Impact and scope

P2, supported. Valid large Android version codes lose identity, can collide in Evidence, and remain labeled fully observed. The demonstrated reach is the CLI normalization path with the two producer responses above; device prevalence was not measured. Input applicability relies on Android's long version-code representation; the local run verifies REA's handling of that response, not a live device.

A workaround is available. Read the Package Manager response directly and retain its decimal version code separately. The reproduction supplies the exact input text, so this preserves the information that the REA result loses without changing device state.

REA version

6.4.0 (main at 8dde6370d0)

Runtime and platform

Node.js v26.10.0; macOS 27.0.1 arm64. The adb identity comes from the inline local fixture, not an installed Android platform-tools binary.

Target and artifact context

Synthetic Package Manager output for com.example.app on serial probe-device, supplied through an executable selected by REA_ADB_PATH. The fixture reports Android Debug Bridge 1.0.41 and version 34.0.5-fixture, with versionName 1.0, minSdk 28, targetSdk 34, userId 10000, and the INTERNET permission. No device is contacted. The primary evidence is the two executed Package Manager fixture responses and the CLI comparison below. Evidence provenance is observed, local verification reproduced the failure, and the reproduction is complete for this CLI normalization contract.

Interface

CLI

Earliest failure stage

Transport or result projection

Relevant output or evidence

{
  "first_version_code": 9007199254740992,
  "second_version_code": 9007199254740992,
  "same_evidence_id": true,
  "confidence": "observed",
  "coverage": "complete",
  "raw_result": null
}

Typed outcome or recovery expected

Repeat the two CLI calls above and confirm that their version observations remain distinguishable and retain the original exact values or recoverable raw spellings. Neither response may claim a rounded replacement is the observed version. Keep controls for ordinary version codes and 9007199254740991, which must retain their values without introducing uncertainty.

Analysis or suspected cause

Source-derived reasoning: src/adb/AdbShellOutput.ts:254 converts the reported decimal version with Number, and src/adb/AdbProvider.ts:928 returns that projection with complete coverage and no raw reply. This explains the observed loss of numeric identity. The executed CLI comparison establishes the returned values, matching Evidence IDs, confidence, coverage, and absent raw result.

Additional context

  • #1813 discusses Android split-set identity and effective manifest version agreement, while this report concerns preservation of the version returned by an existing package-inspection operation.
  • #3145 concerns documented safe-number HAR admission restrictions, while this operation accepts the input and silently returns a rounded observed value.
  • #2515, closed as completed, concerns unrelated Hermes YAML integer keys during configuration edits, while this report concerns the ADB decimal version-code parser and returned Evidence.
  • #3166 concerns fresh installs mislabeled as observed replacements, while this report concerns exact inspected version values and their Evidence identity.
  • #2175, closed as completed, concerns logcat byte quantities computed from string length, while this report concerns precision loss in decimal package version codes.
Originally created by @coygeek on GitHub (Oct 14, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/3368 ### Before submitting - [x] I searched the open and closed issues for a related report. - [x] I removed credentials, tokens, private paths, and sensitive target data. ### Area Evidence, artifacts, or reconstruction ### Observed behavior `inspect-adb-package` converts a positive 64-bit Android version code to an inexact JavaScript number and returns it with `confidence: "observed"` and `coverage: "complete"`. Two distinct reported versions, `9007199254740992` and `9007199254740993`, produce the same normalized version and Evidence ID. The original decimal spelling is absent from the returned Evidence, so callers cannot recover which version Package Manager reported. Both CLI requests exited with status 0. The second request's `versionCode=9007199254740993` became `9007199254740992`, and the two observations shared an Evidence ID. A separate control with `versionCode=9007199254740991` retained that exact value. These observations establish the production CLI's response normalization with a local producer fixture; no live Android device was exercised. ### Reproduction 1. Start from a clean checkout and prepare the runtime: ```sh git clone https://github.com/morluto/rea.git cd rea git checkout 8dde6370d0809ad04cda3342d4e6f290f48aa063 npm ci npm run build:cached ``` 2. From the repository root, run the following local CLI reproduction. The executable models only `adb version` and the Package Manager response consumed by this operation; it never contacts a device. Android can represent these positive values as long version codes, with `versionCodeMajor=2097152` and low version codes `0` and `1`. ```sh work=$(mktemp -d) mkdir -p "$work/home" cat > "$work/adb" <<'JS' #!/usr/bin/env node let args = process.argv.slice(2); if (args[0] === 'version') { console.log('Android Debug Bridge version 1.0.41\nVersion 34.0.5-fixture\nInstalled as ' + __filename); process.exit(0); } if (args[0] === '-s') args = args.slice(2); if (args.join(' ') !== 'shell dumpsys package com.example.app') process.exit(90); console.log('Packages:\n Package [com.example.app] (123):\n userId=10000\n versionCode=' + process.env.VERSION_CODE + ' minSdk=28 targetSdk=34\n versionName=1.0\n requested permissions:\n android.permission.INTERNET\n install permissions:\n android.permission.INTERNET: granted=true'); JS chmod +x "$work/adb" env HOME="$work/home" REA_ADB_PATH="$work/adb" VERSION_CODE=9007199254740992 \ node scripts/rea.mjs inspect-adb-package probe-device com.example.app --format json > "$work/first.json" env HOME="$work/home" REA_ADB_PATH="$work/adb" VERSION_CODE=9007199254740993 \ node scripts/rea.mjs inspect-adb-package probe-device com.example.app --format json > "$work/second.json" node - "$work" <<'JS' const fs = require('node:fs'); const root = process.argv[2]; const first = JSON.parse(fs.readFileSync(root + '/first.json', 'utf8')); const second = JSON.parse(fs.readFileSync(root + '/second.json', 'utf8')); console.log(JSON.stringify({ first_version_code: first.normalized_result.version_code, second_version_code: second.normalized_result.version_code, same_evidence_id: first.evidence_id === second.evidence_id, confidence: second.confidence, coverage: second.normalized_result.coverage, raw_result: second.raw_result }, null, 2)); JS rm -rf "$work" ``` 3. Compare the printed normalized version codes and Evidence identity with the two distinct `VERSION_CODE` inputs. Both returned values are `9007199254740992`, `same_evidence_id` is true, and `raw_result` is null. The script removes its disposable fixture directory after the comparison. ### Expected behavior `docs/adb-device-analysis.md:90`, under Operations, documents `inspect_adb_package` as a `dumpsys package` projection of the device's version declarations. `AGENTS.md:29` requires preserving source values and explicit unknowns when normalization loses information. The observation must preserve the exact version Package Manager reported. A value that the numeric representation cannot retain exactly must keep its original spelling or an explicit unknown alongside recoverable source evidence. It must not become a different fully observed version. The two different version responses must remain distinguishable. ### Impact and scope P2, supported. Valid large Android version codes lose identity, can collide in Evidence, and remain labeled fully observed. The demonstrated reach is the CLI normalization path with the two producer responses above; device prevalence was not measured. Input applicability relies on Android's long version-code representation; the local run verifies REA's handling of that response, not a live device. A workaround is available. Read the Package Manager response directly and retain its decimal version code separately. The reproduction supplies the exact input text, so this preserves the information that the REA result loses without changing device state. ### REA version 6.4.0 (main at 8dde6370d0809ad04cda3342d4e6f290f48aa063) ### Runtime and platform Node.js v26.10.0; macOS 27.0.1 arm64. The adb identity comes from the inline local fixture, not an installed Android platform-tools binary. ### Target and artifact context Synthetic Package Manager output for `com.example.app` on serial `probe-device`, supplied through an executable selected by `REA_ADB_PATH`. The fixture reports Android Debug Bridge 1.0.41 and version 34.0.5-fixture, with versionName 1.0, minSdk 28, targetSdk 34, userId 10000, and the INTERNET permission. No device is contacted. The primary evidence is the two executed Package Manager fixture responses and the CLI comparison below. Evidence provenance is observed, local verification reproduced the failure, and the reproduction is complete for this CLI normalization contract. ### Interface CLI ### Earliest failure stage Transport or result projection ### Relevant output or evidence ```text { "first_version_code": 9007199254740992, "second_version_code": 9007199254740992, "same_evidence_id": true, "confidence": "observed", "coverage": "complete", "raw_result": null } ``` ### Typed outcome or recovery expected Repeat the two CLI calls above and confirm that their version observations remain distinguishable and retain the original exact values or recoverable raw spellings. Neither response may claim a rounded replacement is the observed version. Keep controls for ordinary version codes and `9007199254740991`, which must retain their values without introducing uncertainty. ### Analysis or suspected cause Source-derived reasoning: `src/adb/AdbShellOutput.ts:254` converts the reported decimal version with `Number`, and `src/adb/AdbProvider.ts:928` returns that projection with complete coverage and no raw reply. This explains the observed loss of numeric identity. The executed CLI comparison establishes the returned values, matching Evidence IDs, confidence, coverage, and absent raw result. ### Additional context - [#1813](https://github.com/morluto/rea/issues/1813) discusses Android split-set identity and effective manifest version agreement, while this report concerns preservation of the version returned by an existing package-inspection operation. - [#3145](https://github.com/morluto/rea/issues/3145) concerns documented safe-number HAR admission restrictions, while this operation accepts the input and silently returns a rounded observed value. - [#2515](https://github.com/morluto/rea/issues/2515), closed as completed, concerns unrelated Hermes YAML integer keys during configuration edits, while this report concerns the ADB decimal version-code parser and returned Evidence. - [#3166](https://github.com/morluto/rea/issues/3166) concerns fresh installs mislabeled as observed replacements, while this report concerns exact inspected version values and their Evidence identity. - [#2175](https://github.com/morluto/rea/issues/2175), closed as completed, concerns logcat byte quantities computed from string length, while this report concerns precision loss in decimal package version codes.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#1234
No description provided.