| … | … | @@ -36,7 +36,7 @@ import { SwarmTransport } from 'favela-peer/lib/transport.js' |
| 36 | 36 | import { createUtf8Decoder } from './host/utf8.js' |
| 37 | 37 | import { safeStringify } from './host/safe-json.js' |
| 38 | 38 | // Stamped at build time by scripts/gen-version.mjs — the bundle carries no readable package.json. |
| 39 | import { VERSION, BUILT_AT } from './version.js' | |
| 39 | import { VERSION, BUILT_AT, DEPS } from './version.js' | |
| 40 | 40 | |
| 41 | 41 | /* global BareKit, Bare */ |
| 42 | 42 | |
| … | … | @@ -243,6 +243,13 @@ export async function boot (storage) { |
| 243 | 243 | available: !!ota, |
| 244 | 244 | version: VERSION, |
| 245 | 245 | builtAt: BUILT_AT, |
| 246 | // ⛔ AND WHAT WENT INTO IT. Every sibling arrives as `file:../x`, so this bundle carries | |
| 247 | // whatever was in that tree at pack time while the DESKTOP runs whatever was last published. | |
| 248 | // The two drift silently: on 2026-09-15 they were identical only because of the order things | |
| 249 | // were published that afternoon, and nothing on either side could have said so. A version | |
| 250 | // number answers "which build"; this answers "the same code as my desktop?", which is the | |
| 251 | // question actually being asked when someone compares the two. | |
| 252 | deps: DEPS, | |
| 246 | 253 | stagedBuiltAt, |
| 247 | 254 | note: lastOtaNote |
| 248 | 255 | } |
| … | … | @@ -1,4 +1,15 @@ |
| 1 | 1 | // GENERATED by scripts/gen-version.mjs — do not edit. |
| 2 | export const VERSION = "0.0.41" | |
| 3 | export const BUILT_AT = 1789503080437 | |
| 4 | export default { VERSION, BUILT_AT } | |
| 2 | export const VERSION = "0.0.42" | |
| 3 | export const BUILT_AT = 1789510414467 | |
| 4 | // The sibling versions THIS bundle was packed from — what a desktop compares against to see drift. | |
| 5 | export const DEPS = { | |
| 6 | "anproto": "0.1.0", | |
| 7 | "favela-peer": "0.0.57", | |
| 8 | "favela-surface": "0.0.63", | |
| 9 | "hyper-overlay": "0.3.13", | |
| 10 | "pgh": "0.1.156", | |
| 11 | "pgh-runtime": "0.1.4", | |
| 12 | "hyper-proto-peer": "0.3.123", | |
| 13 | "favela-host": "0.0.1" | |
| 14 | } | |
| 15 | export default { VERSION, BUILT_AT, DEPS } |
| … | … | @@ -1,6 +1,6 @@ |
| 1 | 1 | { |
| 2 | 2 | "name": "favela-surface-android", |
| 3 | "version": "0.0.41", | |
| 3 | "version": "0.0.42", | |
| 4 | 4 | "description": "favela-surface-android \u2014 a React Native shell over a bare-kit worklet running a full favela-peer node (markdown records, no atproto) with favela-surface rendering its pages in a WebView.", |
| 5 | 5 | "type": "module", |
| 6 | 6 | "private": true, |
| … | … | @@ -14,10 +14,36 @@ import { fileURLToPath } from 'url' |
| 14 | 14 | |
| 15 | 15 | const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..') |
| 16 | 16 | const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf8')) |
| 17 | ||
| 18 | // ⛔ WHAT WENT IN, NOT JUST WHICH BUILD. Every sibling arrives as `file:../x`, so a bundle carries | |
| 19 | // whatever was in that working tree at pack time — while the DESKTOP runs whatever was last | |
| 20 | // published. Those two can drift by any amount and, until now, nothing recorded enough to notice: | |
| 21 | // the stamp said 0.0.41 and nothing about which favela-surface was inside it. | |
| 22 | // | |
| 23 | // Measured 2026-09-15: desktop and phone happened to be identical (favela-surface 0.0.63, favela-peer | |
| 24 | // 0.0.57) purely because of the order things were published that afternoon. A parity you cannot read | |
| 25 | // off the device is a parity you are guessing at. | |
| 26 | // | |
| 27 | // ⚠ RESOLVED FROM THE SIBLING'S OWN package.json, never from the dependency RANGE — `file:../x` says | |
| 28 | // nothing about the version and that is the whole problem. A sibling that cannot be read is recorded | |
| 29 | // as null rather than omitted: "we could not tell" and "it is not there" are different answers. | |
| 30 | const deps = {} | |
| 31 | for (const [name, spec] of Object.entries(pkg.dependencies || {})) { | |
| 32 | if (typeof spec !== 'string' || !spec.startsWith('file:')) continue | |
| 33 | try { | |
| 34 | const sib = JSON.parse(fs.readFileSync(path.join(root, spec.slice('file:'.length), 'package.json'), 'utf8')) | |
| 35 | deps[name] = sib.version || null | |
| 36 | } catch { | |
| 37 | deps[name] = null | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 17 | 41 | const out = `// GENERATED by scripts/gen-version.mjs — do not edit. |
| 18 | 42 | export const VERSION = ${JSON.stringify(pkg.version)} |
| 19 | 43 | export const BUILT_AT = ${Date.now()} |
| 20 | export default { VERSION, BUILT_AT } | |
| 44 | // The sibling versions THIS bundle was packed from — what a desktop compares against to see drift. | |
| 45 | export const DEPS = ${JSON.stringify(deps, null, 2)} | |
| 46 | export default { VERSION, BUILT_AT, DEPS } | |
| 21 | 47 | ` |
| 22 | 48 | fs.writeFileSync(path.join(root, 'lib', 'version.js'), out) |
| 23 | console.log('version ' + pkg.version) | |
| 49 | console.log('version ' + pkg.version + ' — ' + Object.entries(deps).map(([k, v]) => k + '@' + (v || '?')).join(' ')) |