diff --git a/docs/revised-api-acceptance-plan.md b/docs/revised-api-acceptance-plan.md index 2c458fc..b48dffc 100644 --- a/docs/revised-api-acceptance-plan.md +++ b/docs/revised-api-acceptance-plan.md @@ -4,7 +4,9 @@ **Android Mapbox API36 is complete within the declared retained-contract scope: camera passed attempt24, core passed attempt27 and all six retained scenarios passed attempt29.** The [completed outcome](../records/evidence/revised-api-u26-android-mapbox-api36-attempt-29.json) records all thirteen renderer checks, six current physical receipts, actual scale2.625, matching installed APK identities before and after,695 unchanged frozen files and successful owned cleanup. Accepted camera/core evidence retains its original limits. The [retained packet](../records/evidence/revised-api-u26-mapbox-android-api36-retained-preparation.json) is completed execution history and grants no further dispatch. -**Next: prepare the complete Android MapLibre unit.** Preparation must account for every retained requirement using applicable reused evidence, remaining camera/core/retained scenarios and owner exclusions, then supply one immutable packet for independent audit under the [complete batch protocol](testing-policy.md#complete-acceptance-units). This handoff authorizes no backend switch or native execution. Three native units and nine rows remain: Android MapLibre, iOS Mapbox and iOS MapLibre. +**Android MapLibre API36 is complete within the declared retained-contract scope: camera passed attempt30, core passed attempt31 and all six retained scenarios passed attempt32.** The [completed outcome](../records/evidence/revised-api-u26-android-maplibre-api36-attempt-32.json) records all thirteen renderer checks, six fresh physical receipts, actual scale2.625, matching installed APK identities before and after,695 unchanged frozen files and nine passed cleanup steps. Accepted camera/core evidence retains its original limits. Attempt30 schema failure and attempt31 quota-interrupted retained timeout remain unchanged history; neither was retroactively passed. The [retained-only packet](../records/evidence/revised-api-u26-maplibre-android-api36-retained-preparation.json) is completed execution history and grants no further dispatch. + +**Next: prepare the complete iOS Mapbox unit.** Both Android backend units are complete. Two iOS units and six rows remain, followed by offline density closeout requiring two distinct positive observed scales per engine. Preparation must follow the complete batch protocol and independent audit; this Android completion authorizes no iOS launch, build, installation, calibration or acceptance execution. The [attempt27 outcome](../records/evidence/revised-api-u26-android-mapbox-api36-attempt-27.json) preserves the accepted core pass and mistaken retained failure latch. The [attempt28 outcome](../records/evidence/revised-api-u26-android-mapbox-api36-attempt-28.json) remains an unverified retained row; missing initial-theme history and stale final child state were not retroactively repaired. Attempt29 supplied fresh initial/updated child history and final matching snapshots. The original application SIGKILL cause remains unresolved; the completed unit does not establish its cause or a fix. @@ -12,16 +14,16 @@ After all four native units, the offline density closeout still requires two dis ## Coverage matrix and order -The [fixed baseline matrix](../records/evidence/revised-api-u26-platform-batches-preparation.json) owns the twelve camera/core/retained row IDs, thirteen core recipes, six retained recipes, accepted evidence and scope dispositions. Its historical two-platform dispatch instructions are superseded by the four complete backend units below. The historical baseline remains twelve rows, with one accepted API37 camera row and eleven remaining rows. Selecting API36 reopened Android Mapbox camera for the new OS; attempt24 passed that row, leaving eleven unfinished rows across the selected targets. The old API37 pass remains accurate history. Attempt27 completed API36 core and attempt29 completed retained, leaving nine unfinished rows across three native units. +The [fixed baseline matrix](../records/evidence/revised-api-u26-platform-batches-preparation.json) owns the twelve camera/core/retained row IDs, thirteen core recipes, six retained recipes, accepted evidence and scope dispositions. Its historical two-platform dispatch instructions are superseded by the four complete backend units below. The historical baseline remains twelve rows, with one accepted API37 camera row and eleven remaining rows. Selecting API36 reopened Android Mapbox camera for the new OS; attempt24 passed that row, leaving eleven unfinished rows across the selected targets. The old API37 pass remains accurate history. Attempt27 completed API36 core and attempt29 completed retained, leaving nine unfinished rows across three native units. Attempt30 subsequently completed MapLibre Android camera; attempt31 completed its core and attempt32 its retained row, leaving six unfinished iOS rows. | Order | Immutable platform/backend unit | Camera | Core | Retained | Remaining rows | | ----- | ------------------------------- | ---------------- | ---------------- | ---------------- | -------------- | | 1 | Android Mapbox, API36 | Passed attempt24 | Passed attempt27 | Passed attempt29 | 0 | -| 2 | Android MapLibre | Pending | Pending | Pending | 3 | +| 2 | Android MapLibre, API36 | Passed attempt30 | Passed attempt31 | Passed attempt32 | 0 | | 3 | iOS Mapbox | Pending | Pending | Pending | 3 | | 4 | iOS MapLibre | Pending | Pending | Pending | 3 | -The [Android Mapbox camera outcome](../records/evidence/revised-api-u26-android-platform-batch-attempt-01.json) remains accepted. It does not establish an API36 camera pass; attempt24 independently supplied that pass. Partial core observations and calibration runs do not complete a row. Android Mapbox is complete within its recorded scope. Prepare Android MapLibre next; do not interleave features across the remaining units. +The [Android Mapbox camera outcome](../records/evidence/revised-api-u26-android-platform-batch-attempt-01.json) remains accepted. It does not establish an API36 camera pass; attempt24 independently supplied that pass. Partial core observations and calibration runs do not complete a row. Android Mapbox is complete within its recorded scope. MapLibre Android camera30, core31 and retained32 are accepted within their recorded scopes. Prepare iOS Mapbox next. Do not interleave features across the remaining units. All nine browser rows passed on unchanged f05 within the [recorded browser scope](../records/evidence/revised-api-u25-web-attempt-07.json); web has no pending row. The fixed matrix links the accepted four-environment minimal, lifetime, query/cluster, bounded source/image and targeted rendering evidence. Reuse those results where artifact and behavior remain applicable, retaining their original limits. The API36 packet reviews OS-change impact: reuse unchanged-contract evidence within its original limits, then obtain fresh camera/GL, query, style/replacement, live UI and density observations through the three selected rows. Any new OS-dependent gap blocks the unit; no general SDK certification is implied. @@ -29,7 +31,7 @@ The twelve rows are the remaining execution baseline, not a replacement for full ## Next complete-unit preparation -Prepare Android MapLibre under the [complete batch protocol](testing-policy.md#prepare-the-complete-batch). Reuse valid frozen-candidate evidence with its original limits; account for the complete retained contract before proposing execution. The packet must bind candidate, resolved dependencies, selected device/OS, all remaining camera/core/retained scenarios, exact commands, ownership, first-failure cleanup, storage and elapsed-time budgets. Independent audit precedes a separate execution decision. No Android MapLibre launch, build, installation or calibration is authorized here. +Prepare iOS Mapbox under the [complete batch protocol](testing-policy.md#prepare-the-complete-batch), accounting for every retained requirement through applicable reused evidence, remaining camera/core/retained rows and owner exclusions. Supply one immutable packet with candidate/dependency/device identities, exact commands, ownership, first-failure cleanup and resource budgets for independent audit before an iOS execution decision. The completed Android packets are history and must not be dispatched again. The [completed Android Mapbox outcome](../records/evidence/revised-api-u26-android-mapbox-api36-attempt-29.json) and [completed retained packet](../records/evidence/revised-api-u26-mapbox-android-api36-retained-preparation.json) preserve its executed inputs and accepted reuse. Historical commands must not be dispatched again from this handoff. diff --git a/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json b/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json new file mode 100644 index 0000000..d5c948e --- /dev/null +++ b/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json @@ -0,0 +1,151 @@ +{ + "result": "stopped-at-observation-writer-schema-error", + "candidateSha256": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "distSha256": "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + "inputApkSha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131", + "environment": "api36-google-apis-revision7-arm64-4k", + "deviceIdentity": { + "api": "36", + "abi": "arm64-v8a", + "pageBytes": "4096", + "gles": 196609 + }, + "completedRows": [ + { + "rowId": "maplibre-android-camera", + "status": "passed", + "scene": { + "observations": [ + { + "text": "TF04 fit=ok click=pending clickAt=pending stop=pending held=pending command=pending doubletap=pending center=-122.32000,47.64000 note=none phase=await-click done=0", + "fields": { + "fit": "ok", + "click": "pending", + "clickAt": "pending", + "stop": "pending", + "held": "pending", + "command": "pending", + "doubletap": "pending", + "center": "-122.32000,47.64000", + "note": "none", + "phase": "await-click", + "done": "0" + } + }, + { + "text": "TF04 fit=ok click=hit clickAt=-122.32001,47.63754 stop=rejected held=pending command=pending doubletap=pending center=-120.00000,45.00000 note=none phase=await-hold done=0", + "fields": { + "fit": "ok", + "click": "hit", + "clickAt": "-122.32001,47.63754", + "stop": "rejected", + "held": "pending", + "command": "pending", + "doubletap": "pending", + "center": "-120.00000,45.00000", + "note": "none", + "phase": "await-hold", + "done": "0" + } + }, + { + "text": "TF04 fit=ok click=hit clickAt=-122.32001,47.63754 stop=rejected held=0 command=applied doubletap=pending center=-120.00000,45.00000 note=none phase=await-double-tap done=0", + "fields": { + "fit": "ok", + "click": "hit", + "clickAt": "-122.32001,47.63754", + "stop": "rejected", + "held": "0", + "command": "applied", + "doubletap": "pending", + "center": "-120.00000,45.00000", + "note": "none", + "phase": "await-double-tap", + "done": "0" + } + }, + { + "text": "TF04 fit=ok click=hit clickAt=-122.32001,47.63754 stop=rejected held=0 command=applied doubletap=timeout center=-120.00000,45.00000 note=none phase=done done=1", + "fields": { + "fit": "ok", + "click": "hit", + "clickAt": "-122.32001,47.63754", + "stop": "rejected", + "held": "0", + "command": "applied", + "doubletap": "timeout", + "center": "-120.00000,45.00000", + "note": "none", + "phase": "done", + "done": "1" + } + } + ], + "display": { + "width": 1080, + "height": 2400 + }, + "tap": [ + "540", + "1488" + ] + } + } + ], + "core": { + "status": "unverified", + "acceptedPhysicalScenarios": [ + "live-child-button", + "nested-scroll", + "live-activation", + "annotation-activation", + "offset-touch-bounds", + "popup-follow-dismissal", + "map-feature-click", + "navigation-location", + "style-remount", + "host-accessibility", + "sdk-ornaments", + "camera-target-and-gesture" + ], + "remainingPhysicalScenarios": [ + "marker-prop-rejection" + ], + "markerRecoveryHelpers": "Four rejection-verified receipts exist; final observation not written; no completed core judge/result exists. Fresh four-case rejection remains required for continuation.", + "runId": "8ca84053-4355-45bc-8d81-0b213cd34adb" + }, + "retained": { + "status": "not-run" + }, + "firstFailure": { + "boundary": "operator observation input, not production library", + "message": "Unknown observation field.", + "cause": "Worker put receipts at top level; writer allows only action, seenResult, rendererData, screenshot and rejected input before mutation.", + "writerExitCode": 1, + "rawReportUnchanged": true + }, + "cleanup": { + "launcher": "Worker sent SIGTERM under erroneous packet instruction; exit143 without finally cleanup; checkpoint cleanup remains empty.", + "manualFallback": "Worker reported bounded owned cleanup: core PGID26486 and emulator PID/PGID25229 absent; ports5580/5581/8081/8797 absent; private AVD and ini removed.", + "limits": "Selected app force-stop/uninstall and reverse removal were not independently confirmed before emulator termination; device termination ended them. No automatic-cleanup pass claimed.", + "source": "Execution worker report relayed by coordinator; checkpoint binds acquired emulator identity.", + "rawRetention": "Preserve all attempt30 files unchanged for active investigation." + }, + "sourceSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/checkpoint.json": "441e0a77035ce5f7157e550b63dc38c0d244802965164ec1bc74534836efcecf", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json": "0b3c5b46c960edc3fa129996bbc794d104c211f1230134af57248d1b263915d1", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/marker-prop-rejection-observation.json": "818e84f6b230f04c08756893d4302f684d925ff58516e7ac7cbab1d91f458b93", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/toolbar-034.json": "34a98f0d8427f2659f8e6dc5799e5293313bf116614d7764cf5853f4022d5805", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/toolbar-038.json": "57a8069ee9f920d8263a0c5033c17e78d49b57002efbc7507dd8edaf8932cf8c", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/toolbar-042.json": "3911a8ce5d4352c99217a6c726283fc0f918dceb6294d39763d01f987e4afd1f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/toolbar-046.json": "c184ffb60be97afbfeaaf532cd6615f1293596cb3eab64800f35d71e630c88b5" + }, + "correctedInput": { + "path": "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json", + "sha256": "dfd9e2d4f9f95205c25fc38afcb16af646896dbeed643515229d0e1ea841c57d", + "change": "Only move receipts under rendererData; new copy, raw input/report untouched.", + "limit": "Offline schema reproduction; no core acceptance credit." + }, + "remainingUnit": "Android MapLibre API36 core+retained, reusing camera30 and twelve accepted core physical observations with exact provenance; fresh marker cases/current renderer read and all six retained required.", + "authorization": "No native retry authorized. Offline repair and independent audit precede one complete remaining-unit owner decision." +} diff --git a/records/evidence/revised-api-u26-android-maplibre-api36-attempt-31.json b/records/evidence/revised-api-u26-android-maplibre-api36-attempt-31.json new file mode 100644 index 0000000..4a1a122 --- /dev/null +++ b/records/evidence/revised-api-u26-android-maplibre-api36-attempt-31.json @@ -0,0 +1,113 @@ +{ + "result": "retained-observation-timeout-after-worker-usage-limit-interruption", + "candidateSha256": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "distSha256": "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + "inputApkSha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131", + "environment": "api36-google-apis-revision7-arm64-4k", + "reusedRows": [ + { + "rowId": "maplibre-android-camera", + "status": "passed", + "outcome": "revised-api-u26-android-maplibre-api36-attempt-30.json", + "outcomeSha256": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6" + } + ], + "completedRows": [ + { + "rowId": "maplibre-android-core", + "status": "passed", + "runId": "654a874e-519e-46c0-91f1-1055acaa877b", + "observed": true, + "manualComplete": true, + "remaining": [], + "scope": "Twelve exact prior physical observations30 plus four fresh marker rejection cases and fresh actual known-feature/finite-camera/load/no-error current read; complete core judgment passed." + } + ], + "coreManualScenarios": { + "live-child-button": "passed", + "nested-scroll": "passed", + "live-activation": "passed", + "annotation-activation": "passed", + "offset-touch-bounds": "passed", + "popup-follow-dismissal": "passed", + "map-feature-click": "passed", + "navigation-location": "passed", + "style-remount": "passed", + "host-accessibility": "passed", + "sdk-ornaments": "passed", + "camera-target-and-gesture": "passed", + "marker-prop-rejection": "passed" + }, + "retained": { + "status": "unverified", + "runId": "5fcdf81e-46c0-4f54-bff3-33c1701af453", + "scenarios": { + "simultaneous-named-maps": "passed", + "provider-child-state": "passed", + "annotation-image-refresh": "passed", + "resize-orientation": "passed", + "camera-target-isolation": "unverified", + "touch-density-bounds": "unverified" + }, + "finalJudgment": "Not completed; worker usage limit interrupted input, driver later observation timeout. Four partial passed receipts do not complete retained row and are not reused into a new row. All six scenarios and initial/updated/final history must be fresh.", + "lastActions": "Target A/Repeat A/Clear A, both children pressed and Read focus; camera-isolation/touch-density final receipts absent. Original user_rotation0 and accelerometer_rotation1 restored." + }, + "failure": { + "cause": "Worker usage-limit interruption followed by finite retained observation timeout; no production defect established", + "launcherError": "Error: /bin/sh exited: 1/null", + "retry": "No independent worker retry; owner Continue resumes same unchanged selected unit after offline preparation/audit." + }, + "cleanup": { + "status": "passed", + "steps": [ + { + "name": "selected app termination", + "result": "passed" + }, + { + "name": "owned process 60623", + "result": "passed" + }, + { + "name": "owned reverse 8081", + "result": "passed" + }, + { + "name": "owned emulator shutdown", + "result": "passed" + }, + { + "name": "owned emulator process exit", + "result": "passed" + }, + { + "name": "released port 5580", + "result": "passed" + }, + { + "name": "released port 5581", + "result": "passed" + }, + { + "name": "released port 8081", + "result": "passed" + }, + { + "name": "released port 8797", + "result": "passed" + }, + { + "name": "owned private AVD removal", + "result": "passed" + } + ], + "coordinatorVerification": "Owner coordinator independently checked assigned ports closed, private AVD absent and all695 frozen hashes unchanged." + }, + "sourceSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/receipt.json": "500b1914deb2152bdfbf3ed52fa9490bb10ea80f4354ffc6ece18f956240a190", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-result.json": "ae647e0a42819166357ca697dccb1f3ee82dd9f79574577aa1ab228f4987ae9b", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-manual.json": "a11dab67a1f7b2c294fdf8b07e7409f708e6a9a5273d983a1761c4ba0f601097", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json": "7adcfd6c7c05073988a2ce6cfcf36734a5238d5fffe923d7302bf2f217230b33" + }, + "remainingUnit": "MapLibre Android API36 retained only, all six fresh scenarios; camera30/core31 accepted and not rerun." +} diff --git a/records/evidence/revised-api-u26-android-maplibre-api36-attempt-32.json b/records/evidence/revised-api-u26-android-maplibre-api36-attempt-32.json new file mode 100644 index 0000000..d5e99a4 --- /dev/null +++ b/records/evidence/revised-api-u26-android-maplibre-api36-attempt-32.json @@ -0,0 +1,199 @@ +{ + "result": "passed", + "unitStatus": "Android MapLibre API36 complete within declared retained-contract coverage and reused evidence limits", + "candidateSha256": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "distSha256": "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + "inputApkSha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131", + "platform": "android", + "backend": "maplibre", + "environment": "api36-google-apis-revision7-arm64-4k", + "device": { + "serial": "emulator-5580", + "api": "36", + "abi": "arm64-v8a", + "pageBytes": "4096", + "gles": 196609 + }, + "execution": { + "row": "maplibre-android-retained", + "runId": "cfaeefdf-7430-4894-a54c-41fb9ab766eb", + "method": "manual-native-touch", + "worker": "Same exclusive GPT-6.1 Terra Medium worker", + "authorization": "Owner Continue after worker quota interruption resumed the same unchanged MapLibre batch; no new artifact or target.", + "privateHarnessRevision": "9eea9f1", + "observed": true, + "manualComplete": true, + "remaining": [] + }, + "checks": { + "focusedComplete": true, + "enoughValidReads": true, + "currentRead": true, + "initialTheme": true, + "updatedTheme": true, + "resized": true, + "rotated": true, + "isolated": true, + "imageLoad": true, + "imageRefresh": true, + "aFeatureTouch": true, + "bFeatureTouch": true, + "noErrors": true + }, + "physicalScenarios": { + "provider-child-state": { + "status": "passed", + "summary": "Both initial counts 1 and updated counts 2 matched named map cameras; exact live judge initialTheme, updatedTheme and currentRead true." + }, + "simultaneous-named-maps": { + "status": "passed", + "summary": "Both distinct map reads finite; each named feature-touch count reached 1. A bounds [0,90.667,411.429,548.952], B [0,639.619,411.429,274.667], scale 2.625." + }, + "annotation-image-refresh": { + "status": "passed", + "summary": "image-load and image-refresh each 1 with no image-error; waiting label changed to Image ready with blue square." + }, + "resize-orientation": { + "status": "passed", + "summary": "Short map heights both 411.81 logical; restored A 548.95 and B 274.67. Landscape 914.29x411.43, portrait 411.43x914.29; child counts 5 then 6 match named cameras. Restored user rotation 0 and auto-rotate 1." + }, + "camera-target-isolation": { + "status": "passed", + "summary": "A moved from [-122.34,47.61] to [-122.345,47.612] and stayed on repeat and clear; B remained [-122.33,47.615]. Final children count 9 each matched own camera." + }, + "touch-density-bounds": { + "status": "passed", + "summary": "Both feature touch counters reached 2, both child counters reached 9; scale 2.625. Original A and B viewport heights 548.95 and 274.67 logical; short heights both 411.81. Final child snapshots match respective cameras." + } + }, + "density": { + "observedScale": 2.625, + "source": "Actual current renderer window.scale; physical bounds and both layouts observed", + "aggregateGate": "Still open: offline closeout requires two distinct positive observed scales per engine across completed Android/iOS retained rows; scale2.625 alone does not satisfy it." + }, + "installedIdentity": { + "method": "Strict device-side SHA256 of sole installed APK path", + "reads": [ + { + "phase": "maplibre-installed", + "sha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131" + }, + { + "phase": "maplibre-android-retained-before", + "sha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131" + }, + { + "phase": "maplibre-android-retained-after", + "sha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131" + } + ] + }, + "frozenInputs": { + "verifiedFiles": 695, + "freezePath": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/mapbox-ios-sources-attempt-01/post-restoration-freeze.json", + "freezeSha256": "2ec3355e8e8de917f001abf7cf6d02fcaf3ab034b93dc76224f81106988a9b8f", + "coordinatorVerification": "All695 hashes unchanged after execution; ports5580/5581/8081/8797 closed and private AVD absent." + }, + "resolvedPackages": { + "react-native": { + "version": "0.87.1", + "sha256": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de" + }, + "react": { + "version": "19.2.3", + "sha256": "c383aced6a67c8d06f02996015c0a163e78532a330a96dff1ccfd107b00ab326" + }, + "@maplibre/maplibre-react-native": { + "version": "11.5.0", + "sha256": "13cad2ed700ffbc475cbf90050a7a1322add8fc2a8ba1c9ec958f89f771607e4" + }, + "react-native-teleport": { + "version": "1.2.1", + "sha256": "03175c80b89d81f0466656bc6bf54be52436804c30cb97ee06b255271abda0fa" + } + }, + "packagedSdk": { + "nativeLibraries": { + "lib/arm64-v8a/libmaplibre.so": "d3a1ab9b9d056d84b93f2aa5f676d20d2d76723952dfcd8bd8d203d6eca6980d" + }, + "configuredNativeSdk": "org.maplibre.gl:android-sdk-opengl:13.6.1", + "configurationSource": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/android/gradle.properties", + "limit": "Configured SDK/version source and exact packaged native library hash; not an independent runtime version readback or general SDK certification." + }, + "acceptedReuse": { + "camera": { + "row": "maplibre-android-camera", + "outcome": "revised-api-u26-android-maplibre-api36-attempt-30.json", + "sha256": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + "limits": "Original camera scope and installed before/after proof retained; not rerun." + }, + "core": { + "row": "maplibre-android-core", + "outcome": "revised-api-u26-android-maplibre-api36-attempt-31.json", + "sha256": "3317ec5e334434d33854b74a0bb6f51750e8565cb8259b48d96300f79b5390fc", + "receiptSha256": "500b1914deb2152bdfbf3ed52fa9490bb10ea80f4354ffc6ece18f956240a190", + "runId": "654a874e-519e-46c0-91f1-1055acaa877b", + "limits": "Passed actual core judgment with twelve pinned physical observations30 plus fresh marker rejection/current renderer evidence31; not rerun." + } + }, + "historicalFailures": { + "attempt30": "Unsupported top-level receipts caused writer schema rejection before mutation; core30 final judgment absent. Original failure/raw bytes remain unchanged; no retroactive pass.", + "attempt31": "Core passed, then worker quota interruption led to retained observation timeout. Partial retained receipts remain unverified history; no retroactive pass. All six retained scenarios32 were fresh.", + "originalSigkill": "Cause remains unresolved; completed unit does not establish its cause or a fix." + }, + "cleanup": { + "status": "passed", + "steps": [ + { + "name": "selected app termination", + "result": "passed" + }, + { + "name": "owned reverse 8081", + "result": "passed" + }, + { + "name": "owned emulator shutdown", + "result": "passed" + }, + { + "name": "owned emulator process exit", + "result": "passed" + }, + { + "name": "released port 5580", + "result": "passed" + }, + { + "name": "released port 5581", + "result": "passed" + }, + { + "name": "released port 8081", + "result": "passed" + }, + { + "name": "released port 8797", + "result": "passed" + }, + { + "name": "owned private AVD removal", + "result": "passed" + } + ] + }, + "sourceSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/receipt.json": "1d20b00d33858559f8f988f974d8e22bcc02dbfb3525582bebec03630df1b397", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-result.json": "277cf3e1dd68cb02911da01635755abb3735401fc012dfb96338f3120a9ded5a", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json": "850800199fbcbab28aabe319f47a2b54c7708c6d275b75637904dfcac539c655" + }, + "coverage": { + "fixedMatrix": "records/evidence/revised-api-u26-platform-batches-preparation.json", + "executedPacket": "records/evidence/revised-api-u26-maplibre-android-api36-retained-preparation.json", + "executedPacketSha256BeforeOutcome": "00dfbe720b01b2c16958fc9fc2b263166f9452a6e6b787fe48a4c9f4aed22184", + "limits": "Inherited accepted minimal/lifetime/query/bounded-source/targeted-rendering evidence retains its original artifact/OS/scope limits. This completes the declared facade contract unit, not general upstream SDK certification.", + "exclusions": "Physical devices, full VoiceOver/TalkBack certification, sensors and two owner-excluded RNMapbox cache operations retain existing boundaries; see fixed matrix and acceptance-plan verification boundaries.", + "visualEvidenceLimit": "Saved screenshot005 depicts short-layout child count3; final count9 is supported by fresh renderer readback/history, not that screenshot. Known nonmodal debugger notice visible; underlying warning content remains unclassified within prior scope." + }, + "next": "Prepare iOS Mapbox unit only; then iOS MapLibre. Two iOS units/six rows and offline density closeout remain. This Android completion authorizes no iOS execution." +} diff --git a/records/evidence/revised-api-u26-maplibre-android-api36-preparation.json b/records/evidence/revised-api-u26-maplibre-android-api36-preparation.json new file mode 100644 index 0000000..99488b7 --- /dev/null +++ b/records/evidence/revised-api-u26-maplibre-android-api36-preparation.json @@ -0,0 +1,763 @@ +{ + "candidate": { + "archive": "/Users/rob/code/mapbox-code/one-map/artifacts/revised-api-u25-f05/one-map-react-0.1.0-rc.2.tgz", + "sha256": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "members": 171, + "matchingPackageCopies": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/packages/one-map-react", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/one-map-react" + ], + "distSha256": "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + "runtimeDistProof": "Launcher verifies695 frozen files before acquisition and after each passed row, including selected MapLibre package/lock/SDK files. Preparation compares all171 archive members in both selected copies. Frozen fixtures and APKs remain unchanged." + }, + "freeze": { + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/mapbox-ios-sources-attempt-01/post-restoration-freeze.json", + "sha256": "2ec3355e8e8de917f001abf7cf6d02fcaf3ab034b93dc76224f81106988a9b8f", + "verifiedFiles": 695, + "mismatches": [] + }, + "stagedSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf09-rendering-smoke.mjs": "4f03fd882edb813891afaf48cf17ea8802d14f55dc7654093772786d415ba696", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf09-rendering-fixture.mjs": "50b90fa0b06d2b4cc3129084322bcfb232ab3113a003f134dc8c826bc9f7ad15", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/native-smoke-process.mjs": "09faef759e0fe9fdda9695b069a2eb1f105a56343143f20d6750c2f3b5bd712b", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/package.json": "85b17f2f852aece03e71edb4ed4d9fddf6a0a8f0b69ac75d7f00b6592d62d37c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/bitmapper.js": "3f2f720e3a2b4e41cdc03e9f58bb1794bec26dcd1b22568e41ce0b84ab20aeb5", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/bitpacker.js": "3f7bfabcbc82bedd0cc8551bc210b44dc1fb179fa2ce3b8b1d39fa307d8af204", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/chunkstream.js": "43c5507901554a29c5a29e555aaeb3c3987b84fb3aa8c681c1b30794a477aa85", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/constants.js": "9e3b4f994ac93751e9ccb4d453e85e4f25a0b086a9f24ec92c7dcb06995bdf6c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/crc.js": "57e2328cfa361fb54f1f4b3a59e071c1ccc864095e4f3759a957cd15aa2a8b65", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-pack.js": "500c1b3b34702c895e9e689143f44280687cac363447523679ec13d12bd564f6", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse-async.js": "328b6173f1a2a4d91425220a0fa421699552f254006a57ede9f4018ced50a7ee", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse-sync.js": "201a08dfab26a2903c0dabcbdfe0406b3fa33d60f59b591878329f590fac48ff", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse.js": "b8aad6f29371f5b13b232643781a7c49f7d36d565136ddda1ed7fbaca987ce2c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/format-normaliser.js": "c73989d85bef5d33ce571095bf0d96927261730d8b0f79c9d48f971fcbdd0be0", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/interlace.js": "3bb5d57153078ff586667e9a9d2c06db993c8ff1638e0521a9883cdeea6e1e3f", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer-async.js": "f50df0610749ce7b1a99abbe9e4596df7c16f96efd3848f12dd632b22cb02b45", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer-sync.js": "1b516238168a42704e62ba44528406188864a6ddda2ae92d1b91e5e078cdaa2d", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer.js": "b5f9956364c80d67c28d615ace639a5fb4d4d79d3acb235237f3050dca220e03", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/paeth-predictor.js": "48555b909af708593dade8e8df75d18ecdffdb6577e362eac01eae357ef1e0e9", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser-async.js": "a0299cad35220de62b7180b1f984b8f77b4c0f419a580fd3c86ea3b3e971ee30", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser-sync.js": "266c9fb230b90075022b3f54f5710a9cacb71ca565f83fce66e7cbd1b7e9b507", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser.js": "574e43fea28a28cc6feb7ab62a480a86bb75411ee4bfaba76a7e9d7310b6e94c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/png-sync.js": "867b1a78dcd3e45458eb4f0af01acd48f38d3a31225bd7cb8dd8ee3966ab54be", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/png.js": "e02cecbd36327829758386dc3f0ca4a36a2339ccb5d5e824ca3556e2c3f89726", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/sync-inflate.js": "08cb8afb79a4c0ab58e94601dab22261daf6638382b211d6a7f6bfbc16d27a0b", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/sync-reader.js": "437a99bf1bf739202ae85c3018cd9174d411597cf55e7064c36976de493368f1" + }, + "hostInputSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/with-android-env.sh": "c1edce14e259e16598218d9eb9a987587355ed3a6821da226c5c12897cf571b4", + "/private/tmp/one-map-android-restoration-review/scripts/launch-android-lifetime-emulator.py": "877dde6787b8463c740c916f24f54477f67365dd3b26d1a52bd2d4b5e7dcbb25", + "/private/tmp/one-map-android-restoration-review/scripts/setup-android-api36.py": "95b3de8a97f8fa2c3302cfc1c712383ad3e95ecb5c93456cbed5ef1b53101e4a", + "/private/tmp/one-map-approved-android-boot-poll.py": "f819d439aa4573070b858e80c7d3a61ca8f7a833f5ca857f3347ba5d39a35956", + "/Users/rob/Library/Android/sdk/emulator/source.properties": "ba13085f647fb8389a4d06a1de0e4104ac4e841733e50f67223ac230e1ce685a", + "/Users/rob/Library/Android/sdk/platform-tools/source.properties": "2dccd788c0234d8cf7f7457377e57f57527a86a629c6ed54feb8af0f549dac38", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/package.json": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/LogBoxInspectorContainer.js": "d8dbf80e71984e631b8d71e8f14c2f0bf7def9a78b05e641936530d9afd482a2", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/UI/LogBoxInspectorFooter.js": "81c1c99e0b0c376ef877b20391b6a442b499376368eadf388a36737be456ed4f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/Data/LogBoxData.js": "d9a60b7cb0a2025744fd56b90934a94ebbf9550aef11a8858dbfdc7773ba94ad", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-api36-image/.one-map-image.json": "e7be6e67a4aba4305918c4fa15a8b54bbe819c447eab4132e574a55af67c2b6c" + }, + "operatorHelperSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py": "a6b26eb1fe16c7c7f25dc79b88624b3099dd124f7d1d6074d151465ce0e3600f", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs": "26f2e069d5ce6f2578715442d4f192a0ce9f5dad4b3e3601cfeb95c6165d3715" + }, + "checkpoint": "Complete Android MapLibre API36 unit", + "status": "Independent coordinator audit passed; owner-authorized complete MapLibre execution ready", + "nativeExecution": false, + "unit": { + "platform": "android", + "backend": "maplibre", + "device": "OneMapF05MapboxApi36 on emulator-5580", + "os": "Stable Android16 API36 Google APIs revision7 arm64-v8a standard4K userdebug image", + "immutableCandidate": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "executionRows": [ + "maplibre-android-camera", + "maplibre-android-core", + "maplibre-android-retained" + ], + "scope": "One immutable MapLibre unit: fresh camera, all13core and all6retained scenarios; reuse applicable bounded prior evidence. No Mapbox rerun." + }, + "executionRows": [ + "maplibre-android-camera", + "maplibre-android-core", + "maplibre-android-retained" + ], + "worker": { + "model": "gpt-6.1-terra", + "reasoning": "medium", + "count": 1, + "ownership": "Exclusive selected emulator, Metro, installation, input, row reports and logs; coordinator owns diagnosis, pins and audit" + }, + "output": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30", + "command": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-acceptance.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30", + "proposedLauncherToolCall": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "cmd": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-acceptance.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30", + "max_output_tokens": 1500 + }, + "operatorToolParameters": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "max_output_tokens": 20000 + }, + "writerToolParameters": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "max_output_tokens": 1500 + }, + "operatorProtocol": { + "helper": "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py", + "writer": "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs", + "output": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30", + "rowOrder": [ + "maplibre-android-camera", + "maplibre-android-core", + "maplibre-android-retained" + ], + "readiness": "Camera is automatic, including its one MapLibre double-tap input. Wait for API36 core operator phase and driver-created core report, then execute all13core recipes. Wait for retained phase/report before six retained recipes. Use lower-interior fresh toolbar points, current hierarchy and live status. Initial BOTH-child press/read must precede Theme. Final fresh BOTH-child press/read must follow all camera/layout/image changes. No callback synthesis or historical receipts.", + "firstFailure": "Preserve first operator failure latch, close current scenario once, let driver diagnostics and owned cleanup run. No raw adb, reconstructed transport, or retry.", + "exactInitialCalls": { + "maplibre-android-core": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount status", + "readRenderer": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount toolbar \"Read renderer\"" + }, + "maplibre-android-retained": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps status", + "readRenderer": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"" + } + }, + "operationArgv": [ + "python3", + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30", + "ROW", + "SCENARIO", + "OPERATION", + "ARGUMENTS..." + ], + "writerArgv": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/ROW-manual.json", + "SCENARIO", + "passed|failed", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/SCENARIO-observation.json" + ], + "dynamicArguments": "ROW is maplibre-android-core or maplibre-android-retained; SCENARIO is the matching exact recipe key. Helper supports status, toolbar LABEL, dismiss-marker-rejection LABEL and bounded adb argument arrays. Use fresh measured coordinates; never reconstruct raw transport.", + "toolbarLabels": { + "core": [ + "remount", + "style", + "offset", + "popup", + "Target A", + "Target B", + "Repeat target", + "Clear target", + "Reject view draggable", + "Reject view callback", + "Reject annotation draggable", + "Reject annotation callback", + "Clear rejection", + "Read renderer" + ], + "retained": [ + "Read focus", + "Finish focus", + "Theme", + "Resize", + "Target A", + "Repeat A", + "Clear A", + "Image" + ] + }, + "hierarchyArgvTemplate": [ + "adb", + "shell", + "uiautomator", + "dump", + "/sdcard/one-map-attempt30-hierarchy-NNN.xml" + ], + "hierarchyReadTemplate": [ + "adb", + "shell", + "cat", + "/sdcard/one-map-attempt30-hierarchy-NNN.xml" + ], + "input": "Use fixed toolbar labels for retained controls and validated helper adb for fresh hierarchy/screenshots and actual measured feature/child bounds. No arbitrary warning dismissal or raw transport.", + "completion": "All13 core and all6 retained observations are individually recorded by validated writer with actual physical/rendered evidence. No bulk-pass assignments. Final core driver judge and retained Finish focus driver judge must pass. Camera/core/retained passed rows and installed identity reads are preserved." + }, + "coreOperatorRecipes": { + "live-child-button": "Physically tap the live child button; record its counter increment and unchanged map-click counter from fresh renderer reads.", + "nested-scroll": "Swipe inside the live child list; observe changed visible list content and unchanged map camera. Use genuine input and visual evidence.", + "live-activation": "Tap the non-child live marker body and observe marker-click. Native dragging is removed and is not a success criterion.", + "annotation-activation": "Tap the visible annotation and observe annotation-click; do not infer interactive child support from its bitmap.", + "offset-touch-bounds": "Toggle offset, activate the visibly displaced child, then reset and activate again. Record actual bounds, touches and scale; no native drag.", + "popup-follow-dismissal": "Pan/zoom and observe the bubble attachment; activate its child, dismiss once, reopen and verify teardown/remount adds no stale dismissal. Fresh hierarchy must show popup child. If zoom11 overlaps marker, use visible application Zoom out once and read actual zoom10 before measuring child bounds. Physically activate bubble child and dismiss/reopen. Record popup-close count before/after remount; stale callbacks must not add dismissal. No assumed Mapbox coordinates.", + "map-feature-click": "Physically tap projected point707 with interactiveLayerIds filtering, and repeat after remount. Record actual source-click/map callback data; no retired source bubbling or hitbox API. Fresh sourcePoint is renderer-projected screen logical coordinate: combine current map viewport origin and actual scale to physical input; verify hierarchy/bitmap bounds first. Observe source-click both before and after remount; final aggregate needs>=2.", + "navigation-location": "Use Zoom in/out and Reset north with renderer reads; tap Locate me using the fixture supplied constant coordinate [-122.33,47.62], observe camera and UserLocation. No sensor request.", + "style-remount": "Apply style, then remount; require generation>=1, load>=2, known feature and working child/source interactions afterward, with no error/stale callback. Run first: fresh source feature tap/read, style, read, remount, read, source feature tap/read. Afterward retain generation>=1 and load>=2. The scene retains observation counters across remount but subsequent physical tests establish current-generation events; do not restart scene.", + "host-accessibility": "Inspect host and child accessibility labels/roles using the native hierarchy and visible controls. Full VoiceOver/TalkBack audit is excluded.", + "sdk-ornaments": "Inspect SDK scale, logo/legal attribution and available attribution interaction; inspect application control placement and empty overlay touches. No deleted common units/width policy.", + "camera-target-and-gesture": "Request Target A, physically pan to B, Repeat target with equal values and verify B remains. Request changed Target B and verify camera movement; Clear target and confirm gestures remain usable.", + "marker-prop-rejection": "Run each of Reject view draggable, Reject view callback, Reject annotation draggable, Reject annotation callback through toolbar under marker-prop-rejection. Inspect exact native rejection/boundary, recover only via dismiss-marker-rejection LABEL for the same case, verify Clear rejection/current normal scene and No rejection requested after each. Match exact selected com.onemapmaplibre hierarchy and exact message. Record four distinct request receipts and no drag callback; wrong/unknown warning stops. Final Read renderer must remain valid." + }, + "retainedOperatorRecipes": { + "simultaneous-named-maps": "Read both actual map instances, touch each known feature and record independent named-map readbacks and finite measured viewports.", + "provider-child-state": "Before Theme press BOTH initial child buttons, then Read focus and status; require both initial/count>=1/current map-matching child snapshots. Only then Theme, press BOTH again, Read focus and verify both updated/count>=2 while initial checkpoint remains in history.", + "annotation-image-refresh": "Use Image, observe delayed image load and explicit annotation refresh, inspect resulting bitmap; require image-load/image-refresh and no image-error.", + "resize-orientation": "Use Resize both ways, then landscape and portrait on the owned device; find current controls from fresh hierarchy and record valid changed bounds and orientation readbacks. Refresh BOTH child snapshots and Read focus in each layout/orientation; use valid reads, not only screenshots.", + "camera-target-isolation": "Move only Map A and record its changed center while Map B stays fixed; repeat equal target without rollback, then clear. Verify named children read their own map. After every camera change refresh BOTH child snapshots by physically pressing both child buttons, then Read focus and verify matching centers/zoom before recording the read.", + "touch-density-bounds": "Physically activate children/features at their actual current bounds in both layouts; record actual window.scale and logical viewport measurements, with no synthetic callback invocation. After all camera/layout/image operations, physically press BOTH children again; Read focus must verify both snapshots against current maps before Finish focus." + }, + "coverageDispositions": [ + { + "group": "MapSetup/Map/useMap; selection and mixed aliases", + "disposition": "Existing frozen package/selection verification and four minimal native runs reused; simultaneous named-map/provider attachment remains in retained rows." + }, + { + "group": "Source/Layer/Images, styles and update lifetimes", + "disposition": "Four accepted bounded source/image scenes and four targeted rendering scenes reused. Both native adapter tests cover heatmap/fill-extrusion translation; representative real renderer evidence is sufficient under testing-policy.md. No new per-layer pixel suite and no claim of pixel certification for those types.", + "routineSources": [ + "packages/one-map-react/test/mapbox-native.native.test.tsx", + "packages/one-map-react/test/maplibre-native.native.test.tsx" + ], + "policy": "docs/testing-policy.md#select-checks-by-the-change and #test-behavior-at-the-owning-boundary" + }, + { + "group": "Queries/clusters/explicit feature state", + "disposition": "Four ordinary query/cluster and four lifetime scopes reused; no automatic clearing/replay guarantee is added." + }, + { + "group": "Camera, native unchanged targets and gestures", + "disposition": "Fresh MapLibre Android camera, core camera-target-and-gesture and retained camera-target-isolation cover changed camera behavior on API36. Native stop rejects; animation cancellation is not claimed. Other-engine/platform evidence retains original limits." + }, + { + "group": "Marker, portals, providers, offsets, refresh and failure handling", + "disposition": "Core and retained recipes own actual activation, nested scrolling, coordinates, host/layout, refresh and replacement. Common native drag success is excluded by contract; explicit rejection is required." + }, + { + "group": "UserLocation and migrated screen UI", + "disposition": "Core deterministic location action and supplied display, application-owned navigation/popups, SDK ornaments and legal attribution. No common acquisition, native units policy, source bubbling or removed controls are reintroduced." + }, + { + "group": "Selected wrapper and raw facilities", + "disposition": "Existing surface/peer/package and affected integration evidence reused. Raw SDK services are application-owned; no new general SDK certification, database/offline/capture/sensor campaign. SDK metadata/configuration limitations remain in original receipts." + }, + { + "group": "Density", + "disposition": "Retained rows record actual window.scale. Existing judgeNativeDensityMatrix requires two distinct positive observed scales per engine across Android+iOS. Android pinned source configuration420dpi corresponds to2.625; iOS expected3 must be actually observed, never inferred. No extra suite row is added. Identical/missing scales fail this explicit closeout gate." + }, + { + "group": "Excluded scope", + "disposition": "Physical devices, full VoiceOver/TalkBack certification, sensors, removed common services/controls/drag, RNMapbox invalidateAmbientCache/setMaximumAmbientCacheSize remain excluded; retained functionality is not relabeled unsupported." + } + ], + "fullContractMap": { + "source": "docs/requirements.md#purpose-and-scope, docs/revised-api-proposal.md and docs/api-coverage.md", + "fixedBaseline": "records/evidence/revised-api-u26-platform-batches-preparation.json", + "acceptedSelectedEvidence": { + "minimal": "revised-api-u25-f05-maplibre-android-minimal-attempt-01.json", + "lifetimes": "revised-api-u25-f05-maplibre-android-lifetimes-attempt-01.json", + "queries": "revised-api-u25-f05-maplibre-android-queries-attempt-05.json", + "sources": "revised-api-u25-f05-maplibre-android-sources-attempt-01.json", + "rendering": "revised-api-u25-f05-maplibre-android-rendering-attempt-01.json" + }, + "reuseLimits": "Only selected unchanged-f05 MapLibre Android minimal/lifetime/query/bounded-source/targeted-rendering evidence reused, within original scopes. Original OS evidence does not certify API36 camera/GL or UI. Fresh three-row unit supplies representative camera, query, style/replacement, live UI, density and attachment observations; any newly demonstrated gap blocks unit.", + "pendingRows": [ + "maplibre-android-camera", + "maplibre-android-core", + "maplibre-android-retained" + ], + "pendingScenarioCount": 20, + "coverageRule": "All retained requirements must be passed, covered by applicable accepted evidence, or explicitly owner-excluded; unknown/failed work is never passed. No new general SDK/service/sensor/pixel campaign.", + "density": "Retained result top-level density is the actual current.window.scale; preserve raw observation array and APK/library identities. U27 later reconciles two distinct positive observed scales per engine across four retained rows. No assumed scale or extra test/platform switch.", + "selectedMatrix": "Mapbox API36 complete and excluded from dispatch. MapLibre Android camera/core/retained pending. Six iOS rows remain after this unit." + }, + "verifiedBinaries": { + "android": { + "maplibre": { + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/android/app/build/outputs/apk/debug/app-debug.apk", + "sha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131" + } + } + }, + "resolvedPackageEvidence": { + "react-native": { + "version": "0.87.1", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/package.json", + "sha256": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de" + }, + "react": { + "version": "19.2.3", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react/package.json", + "sha256": "c383aced6a67c8d06f02996015c0a163e78532a330a96dff1ccfd107b00ab326" + }, + "@maplibre/maplibre-react-native": { + "version": "11.5.0", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/package.json", + "sha256": "13cad2ed700ffbc475cbf90050a7a1322add8fc2a8ba1c9ec958f89f771607e4" + }, + "react-native-teleport": { + "version": "1.2.1", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native-teleport/package.json", + "sha256": "03175c80b89d81f0466656bc6bf54be52436804c30cb97ee06b255271abda0fa" + } + }, + "packagedSdkEvidence": { + "nativeLibraries": { + "lib/arm64-v8a/libmaplibre.so": "d3a1ab9b9d056d84b93f2aa5f676d20d2d76723952dfcd8bd8d203d6eca6980d" + }, + "configuredNativeSdk": "org.maplibre.gl:android-sdk-opengl:13.6.1", + "configurationSource": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/android/gradle.properties", + "limit": "Configured SDK/version source and exact packaged native library hash; not an independent runtime version readback or general SDK certification." + }, + "batchInputSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/android-rendering.mjs": "18f5c6b427f33bec6528b511af6653a70f0ed3994868e81ac55038612121db4d", + "/private/tmp/one-map-android-restoration-review/scripts/android-camera-observer.mjs": "c1c589a6d74c1739e386af506f651a6c91b0c0a77e974a96b61c4a5ba2abae44", + "/private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-acceptance.mjs": "e66181da707b33b40823c49c69d42241d88ffbf0e053651fcb93d47442c01820", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-ui-smoke.mjs": "41464708656e27e250d29a5a9cac42c24080ad38f5fef908fad7f9dcca40779c", + "/private/tmp/one-map-android-restoration-review/scripts/native-smoke-process.mjs": "09faef759e0fe9fdda9695b069a2eb1f105a56343143f20d6750c2f3b5bd712b", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-smoke-contract.mjs": "fa4967297a3a0782d2aea89fe17b7d726a9b3052bac7437e0b47e1484cb3bf1b", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-retained-contract.mjs": "21dd6881cd052656ec1c3c63a173b62c817e5fe2c89dc156e529c606552f9695", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs": "26f2e069d5ce6f2578715442d4f192a0ce9f5dad4b3e3601cfeb95c6165d3715", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf04-camera-smoke.mjs": "13a9c48f32afc8118629f830f5d02c4c7e87d518f77e956a748f018194740e38", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-ui-smoke.mjs": "eee588dd20e8d712491045801a194f7d67a0a61f43791ef2df0f61eb2b944a11", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-smoke-contract.mjs": "74ca64dd2fb1c4a159e7f59edc213e9ca3d8893e433c61913c6f26682a062d2f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-retained-contract.mjs": "f4428fb5902170f57308738bfd44fa7a9a59d2a5aa957835ef199071a98b3852" + }, + "regressionSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/mapbox-android-rendering.test.mjs": "a87d75621e3916a88e5518c074e40a0534321c66aaedb7e151dd148ad194c908", + "/private/tmp/one-map-android-restoration-review/scripts/android-camera-observer.test.mjs": "7234012e787c0f4c835bdcea8ea56f3ffa0d20b1e0058ef2c3412c87eeac89ec", + "/private/tmp/one-map-android-restoration-review/scripts/android-installed-identity.test.mjs": "bd6b11bc709f7fd3ff95446179da2907224b1064d0e509f1ba9c78d54318008c", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-native-runner.test.mjs": "ccd7c36fd033a8be2e06937af21473e2724cf985e33493decb90beaf5a2cd45c", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.test.mjs": "b68b03d56d604b6352fa5153404c4da04baee95c08e94940ebb0c97460f89e38", + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.test.py": "07f013404f05dbe2e842251bfe599d551b0b952e1942ef08f9eb55d1e52b926f", + "/private/tmp/one-map-android-restoration-review/scripts/setup-android-api36.test.py": "18221ffa7dba7c5000e39e278928e2dfbb5e1f134520cc40d634620be021aab6", + "/private/tmp/one-map-android-restoration-review/scripts/launch-android-lifetime-emulator.test.py": "31c7caf00ecc75ad30f7833d6c0c6ad4fce472e811f3fa421496b6fc37c318d7", + "/private/tmp/one-map-android-restoration-review/scripts/api36-retained-observation.test.mjs": "4cd378d591cb982411431fc4ea0f458c650cc94edd22e4c777a21a43662dc634" + }, + "storage": { + "measuredWholeUnitPeakAvailable": false, + "measurementGap": "No empirical whole-unit peak is claimed. Reuse existing verified4.3GiB image and unchanged APK; configured private userdata/sdcard and install/cache allowance budget4GiB,6GiB headroom and2GiB cleanup reserve. No download/build.", + "requiredFreeBytes": 12884901888, + "planningBudget": { + "privateUserdataUpperBytes": 2147483648, + "sdcardUpperBytes": 134217728, + "apkInstallAndTaskCacheAllowanceBytes": 2013265920, + "hostHeadroomBytes": 6442450944, + "cleanupReserveBytes": 2147483648 + }, + "meaning": "Conservative12GiB planning capacity, not an empirical peak or a SIGKILL explanation. Configured userdata/sdcard bounds plus install/cache allowance total4GiB, with6GiB host headroom and2GiB cleanup reserve. Historical modes keep their8.2GiB gate.", + "currentFreeBytes": 19991937024, + "readiness": "Require fresh12GiB plus absent attempt30 output immediately before dispatch; image member/hash check remains mandatory.", + "shortfallBytes": 0, + "preDispatchReadOnlyCheck": { + "cmd": "python3 -c 'import pathlib, shutil; p=pathlib.Path(\"/Users/rob/code/mapbox-code/one-map-f05-android-recovery\"); free=shutil.disk_usage(p).free; print({\"freeBytes\":free,\"requiredBytes\":12*1024**3}); assert (p/\"android-api36-image\").is_dir(),\"Hold: verified image missing\"; assert free>=12*1024**3,\"Hold:12GiB storage gate\"; assert not (p/\"android-platform-batch-attempt-30\").exists(),\"Hold: output exists\"'", + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "max_output_tokens": 1000, + "purpose": "Coordinator only, under existing owner execution authorization and after audit/readiness decision; no emulator/adb/app starts and no file is created. Do not dispatch on a known capacity failure." + }, + "imageReuse": "Reuse retained API36 image only after setup helper checks all28members and hashes. No download when verification succeeds." + }, + "timing": { + "estimateMinutes": "40-90minutes estimated with retained image reuse, automated camera, all13core and all6retained; no build/download", + "manualPerRowMs": 1800000, + "driverPerRowMs": 2100000, + "bootMs": 180000, + "installMs": 120000, + "ordinaryCommandMs": 30000, + "workerAllocationMinutes": 150, + "limit": "Existing finite phase bounds retained;150minutes is coordinator supervision allocation, not a global launcher watchdog. Reserve cleanup; stop first failure without retry.", + "reuseEstimate": "40-90minutes estimated for complete camera/core/retained unit with verified retained image reuse;150minute worker allocation and finite stage timeouts preserve cleanup reserve." + }, + "resources": { + "serial": "emulator-5580", + "privateAvd": "OneMapF05MapboxApi36", + "ports": [ + 5580, + 5581, + 8081, + 8797 + ], + "ownedReverses": [ + "tcp:8081", + "tcp:8797" + ], + "lifetime": "Verified retained API36 image, one fresh private AVD with historical name OneMapF05MapboxApi36, one checked unchanged MapLibre APK installation. No Mapbox SDK/app execution. Camera then core then retained share owned emulator and reverse; per-row Metro/status sequential.", + "cleanup": "Stop on first unexpected failure; retain accepted prefix and original error. Launcher releases only acquired selected app, row drivers/Metro/process groups, reverses, emulator and private AVD after absence checks. Preserve foreign resources and verified image. Do not use adb outside helper or delete global API37 image. On interruption signal owned launcher for its finally cleanup; coordinator classifies uncertain ownership, no broad kill.", + "retention": "Compact outcome, provenance and row reports persist; essential raw logs/screenshots remain temporary. Existing kernel-console log is not byte-bounded; no new tracing campaign is added.", + "image": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-api36-image" + }, + "exclusions": [ + "No Mapbox rerun or interleaved backend", + "No build, dependency restore, peer/lock/version/fixture/APK/f05 change", + "No image download: retained image must exist and all28files match", + "No CUA, raw transport, Android Studio, signal calibration or speculative framework", + "No independent retry or changed artifact/environment", + "Physical devices, full VoiceOver/TalkBack, sensors and two owner-excluded RNMapbox cache operations remain outside scope" + ], + "routineVerification": { + "nativeExecuted": false, + "passed": [ + "All695 frozen identities, all171archive members in both selected copies, selected MapLibre APK identity, selected consumer lock and SDK package pins, direct APKmanifest and native library hashes, retained image28member/hash verification", + "Shared launcher actual-code mocks pass including selected MapLibre API36 successful3row flow, first failure/passed prefix, image/identity/environment/storage failures, cleanup, exclusive backend and fixed entrypoint", + "Camera observer, strict installed identity/command transport, TF07 runner and validated observation writer regressions pass", + "Exact packet Mapbox/MapLibre live-judge subprocess regressions pass; null/failure/wrong identity reject and synthetic preFinish requires all other checks and manualComplete; no acceptance credit", + "Python operator33tests, API36 setup10tests and emulator launcher4tests pass; no native tools launched", + "Vite+ formatting and lint pass on four changed JavaScript files; Python covered by AST/test execution, not formatter/linter" + ], + "pending": [ + "Actual MapLibre complete native unit remains unverified until execution" + ], + "commands": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/mapbox-android-rendering.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/android-camera-observer.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/android-installed-identity.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/tf07-native-runner.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/record-native-ui-observation.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/api36-retained-observation.test.mjs", + "python3 scripts/android-operator.test.py", + "python3 scripts/setup-android-api36.test.py", + "python3 scripts/launch-android-lifetime-emulator.test.py" + ] + }, + "authorization": "Owner explicitly requested complete MapLibre batch preparation then execution. Coordinator audits this exact packet before one exclusive Terra Medium worker executes the initial declared unit. No retries are implied. No runtime was launched during preparation.", + "exactOperatorCommands": [ + "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps status", + "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"" + ], + "compatibility": { + "source": "https://dl.google.com/android/repository/sys-img/google_apis/sys-img2-3.xml", + "repositorySha256": "b1261b4f645125367bc74d5e0881a55cb489cf13bae26a3c9d61bdef287d228e", + "package": "system-images;android-36;google_apis;arm64-v8a", + "revision": 7, + "channel": 0, + "url": "https://dl.google.com/android/repository/sys-img/google_apis/arm64-v8a-36_r07.zip", + "archiveBytes": 1872691175, + "archiveSha1": "5a99183b6d924da606260e45fd41a3eb8eca6eb7", + "uncompressedBytes": 4575096761, + "regularFiles": 28, + "zip64Resolved": true, + "sourcePropertiesSha256": "f53d5fbbb89420d911b9e5ed9243aff60caad24132a76e649efc8dfd96295731", + "buildPropSha256": "999e509f85b5edd5522e867842f27a10f4cb077082bbd70d8eea27fc073463af", + "kernelSha256": "9b300ef4ee5ea5ee21c0a1924991e92a740d93127b19edead1a9365e83df95ca", + "offlineKernelConfig": "CONFIG_ARM64_4K_PAGES=y;16K/64Knotset; official compressed kernel member inspected offline, not booted", + "image": "Android16 REL preview0 API36 google_apis arm64-v8a userdebug/debuggable1, Google Play services without Play Store, GPU support true", + "emulatorMinimum": "35.4.9", + "installedEmulator": "37.2.12", + "installedAdb": "37.0.1", + "retainedApkManifest": { + "minSdk": 24, + "targetSdk": 36, + "compileSdk": 37, + "method": "Direct offline binary AndroidManifest.xml parse of pinned MapLibre APK" + }, + "reason": "Retained MapLibre APK min24/target36 permits selected stable API36 arm64-v8a. Image requires emulator>=35.4.9; installed37.2.12 satisfies it. Pinned image standard4K kernel avoids API37/16K variant. Runtime API/ABI/page/GLES checks remain required; this is offline compatibility evidence.", + "runtimeGateBeforeInstall": "API36; arm64-v8a; getconf PAGE_SIZE=4096; ro.opengles.version>=196608. Skip API37-only ACCESS_LOCAL_NETWORK grant; old modes unchanged.", + "offlineImageVerification": { + "files": 28, + "manifestSha256": "e7be6e67a4aba4305918c4fa15a8b54bbe819c447eab4132e574a55af67c2b6c", + "mismatches": [], + "nativeExecuted": false + } + }, + "installedIdentityVerification": { + "method": "adb -s emulator-5580 shell /system/bin/toybox sha256sum EXACT_SOLE_BASE_APK_PATH", + "validation": "Unchanged input APK hash; exactly one pm path in safe shell alphabet; exact lower-case64hex digest and matching sole filename; digest equals pinned APK. Shared before/after checks remain. Nonzero/malformed output stops; no pull fallback/retry.", + "transportDiagnostics": "First8command failures retain redacted file/args, code, signal, killed, elapsedMs, timeoutMs and last4096characters of stdout/stderr. Timeout-compatible termination is not proven causation.", + "boundary": "Installed-byte digest replaces host readback hashing. Tool presence established offline in pinned image; runtime availability and native outcomes unverified.", + "samePatternReview": "Shared Android launcher identity and selected TF07 core/retained driver both use strict device-side SHA256. Historical standalone TF08 still pulls APKs outside this packet; no general transport cause is claimed." + }, + "retainedReadinessProtocol": { + "commands": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps status", + "readFocus": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"", + "dump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell uiautomator dump /sdcard/one-map-attempt30-retained-read.xml", + "hierarchy": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell cat /sdcard/one-map-attempt30-retained-read.xml", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell screencap -p /sdcard/one-map-attempt30-retained-read.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb pull /sdcard/one-map-attempt30-retained-read.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/retained-read.png", + "captureStatus": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps status > /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/retained-status.txt" + }, + "boundedReadback": "After Read focus, run fresh status then hierarchy/screenshot. If status remains null, observe status at most15times over30seconds without repeated input. A populated object is not a pass: inspect actual named-map readbacks and error events. Actual failed command/assertion/read-error stops immediately. After the bounded window with null only, present fresh post-read hierarchy/screenshot/status to coordinator before creating a failure latch, so the coordinator can classify obstruction evidence within this approved unit. No unilateral retry or null-only warning classification.", + "obstruction": "Existing helper computes a lower interior Y only for fresh retained top0 toolbar tap/swipe bounds. Inspect current hierarchy/screenshot if readback remains null; do not replay stale coordinates or assume a successful input proves a read.", + "notice": "Do not fail or dismiss solely for the known nonmodal synthetic debugger notice. Unknown visible errors/warnings require coordinator inspection; actual errors remain first failures." + }, + "liveJudgeCommand": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node --input-type=module -e 'import assert from \"node:assert/strict\"; import {readFileSync} from \"node:fs\"; import {judgeNativeRetained} from \"/private/tmp/one-map-android-restoration-review/scripts/tf07-retained-contract.mjs\"; const lines=readFileSync(process.argv[1],\"utf8\").trim().split(\"\\n\"); const start=lines.indexOf(\"START status http://127.0.0.1:8797/tf07\"); assert(start>=0 && lines.length===start+3 && lines.at(-1)===\"COMPLETE 0\",\"Expected successful operator status output\"); const body=JSON.parse(lines[start+1]); assert(body && typeof body===\"object\" && !Array.isArray(body),\"Await populated renderer status\"); const manual=JSON.parse(readFileSync(process.argv[2],\"utf8\")); console.log(JSON.stringify(judgeNativeRetained(body,manual,{installedBinarySha256:\"c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131\",libraryDistSha256:\"f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5\",environment:\"maplibre-android\",runId:manual.runId}),null,2));' /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/retained-status.txt /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json", + "retainedCheckpoints": [ + { + "step": "Initial context before Theme", + "actions": "Physically press BOTH initial child buttons using fresh bounds. Read focus, capture actual status and run liveJudgeCommand.", + "required": "checks.initialTheme and checks.currentRead true; both children initial/count>=1 and centers/zoom match their named maps. Do not press Theme until this actual read is in history." + }, + { + "step": "Updated context", + "actions": "Only after initial checkpoint: Theme, physically press BOTH child buttons again, Read focus, capture status and run liveJudgeCommand.", + "required": "checks.initialTheme, checks.updatedTheme and checks.currentRead true; both children updated/count>=2, with matching map centers/zoom." + }, + { + "step": "All six physical scenarios", + "actions": "Complete all six retained recipes as one row, observing actual known features/touches/image load-refresh, changed sizes, both orientations and isolated camera. After camera/layout/image changes physically press BOTH children and Read focus again.", + "required": "Preserve valid initial and updated history, actual window.scale positive. Errors remain first failures; all6 fresh physical receipts required." + }, + { + "step": "Final fresh snapshot before Finish", + "actions": "After ALL camera/resize/orientation/image changes, physically press BOTH child buttons, then Read focus, capture status and run liveJudgeCommand.", + "required": "EVERY checks entry except focusedComplete is true, especially currentRead/initialTheme/updatedTheme. Verify all6 current manual scenarios and meaningful action/seenResult receipts. focusedComplete=false is expected before Finish. Never synthesize or edit renderer history." + }, + { + "step": "Finish and verify", + "actions": "Only then Finish focus. Capture actual final status and run liveJudgeCommand if driver remains active; let driver judge the same unchanged contract and finish normally.", + "required": "Allchecks true, manualComplete true, status passed and final driver/launcher passed. Do not submit unverified output as completed acceptance." + } + ], + "coreExecutionOrder": [ + "style-remount", + "map-feature-click", + "live-child-button", + "nested-scroll", + "live-activation", + "annotation-activation", + "offset-touch-bounds", + "popup-follow-dismissal", + "navigation-location", + "host-accessibility", + "sdk-ornaments", + "camera-target-and-gesture", + "marker-prop-rejection" + ], + "completedEvidenceReused": { + "minimal": [ + "revised-api-u25-f05-maplibre-android-minimal-attempt-01.json" + ], + "lifetimes": [ + "revised-api-u25-f05-maplibre-android-lifetimes-attempt-01.json" + ], + "queries": [ + "revised-api-u25-f05-maplibre-android-queries-attempt-05.json" + ], + "sources": [ + "revised-api-u25-f05-maplibre-android-sources-attempt-01.json" + ], + "rendering": [ + "revised-api-u25-f05-maplibre-android-rendering-attempt-01.json" + ] + }, + "liveJudgeProtocol": "Capture exact actual helper START status / one JSON object / COMPLETE0 output to retained-status.txt. Live judge parses it strictly and binds pinned MapLibre APK/dist/environment plus current report runId. Before Finish focusedComplete=false is EXPECTED: Read focus calls read() with its defaultfalse; Finish focus calls read(true), which performs a fresh actual SDK read. Require EVERY other checks entry true and manualComplete=true before Finish. The running driver independently binds its runId and judges after that fresh finished read. Source: native-harness/examples/shared/native-tf07-retained-screen.tsx read default/SDK reads and Read focus/Finish focus bindings; scripts/tf07-ui-smoke.mjs nativeStatus completion gates.", + "unchangedInputVerification": { + "nativeExecuted": false, + "frozenFiles": 695, + "maplibreFrozenPaths": 297, + "frozenMismatches": [], + "archiveMembersPerCopy": 171, + "packageCopies": 2, + "selectedApkMatch": true, + "imageFiles": 28, + "freshOutputAbsent": true, + "apkManifest": { + "manifest": { + "versionCode": 1, + "versionName": "1.0", + "compileSdkVersion": 37, + "compileSdkVersionCodename": "17", + "package": "com.onemapmaplibre", + "platformBuildVersionCode": 37, + "platformBuildVersionName": 17 + }, + "uses-sdk": { + "minSdkVersion": 24, + "targetSdkVersion": 36 + } + } + }, + "scenarioCommands": { + "live-child-button": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core live-child-button status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json live-child-button passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/live-child-button-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json live-child-button failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/live-child-button-observation.json" + }, + "nested-scroll": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core nested-scroll status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json nested-scroll passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/nested-scroll-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json nested-scroll failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/nested-scroll-observation.json" + }, + "live-activation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core live-activation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json live-activation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/live-activation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json live-activation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/live-activation-observation.json" + }, + "annotation-activation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core annotation-activation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json annotation-activation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/annotation-activation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json annotation-activation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/annotation-activation-observation.json" + }, + "offset-touch-bounds": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core offset-touch-bounds status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json offset-touch-bounds passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/offset-touch-bounds-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json offset-touch-bounds failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/offset-touch-bounds-observation.json" + }, + "popup-follow-dismissal": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core popup-follow-dismissal status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json popup-follow-dismissal passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/popup-follow-dismissal-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json popup-follow-dismissal failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/popup-follow-dismissal-observation.json" + }, + "map-feature-click": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core map-feature-click status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json map-feature-click passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/map-feature-click-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json map-feature-click failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/map-feature-click-observation.json" + }, + "navigation-location": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core navigation-location status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json navigation-location passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/navigation-location-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json navigation-location failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/navigation-location-observation.json" + }, + "style-remount": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json style-remount passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/style-remount-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json style-remount failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/style-remount-observation.json" + }, + "host-accessibility": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core host-accessibility status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json host-accessibility passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/host-accessibility-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json host-accessibility failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/host-accessibility-observation.json" + }, + "sdk-ornaments": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core sdk-ornaments status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json sdk-ornaments passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/sdk-ornaments-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json sdk-ornaments failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/sdk-ornaments-observation.json" + }, + "camera-target-and-gesture": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core camera-target-and-gesture status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json camera-target-and-gesture passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/camera-target-and-gesture-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json camera-target-and-gesture failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/camera-target-and-gesture-observation.json" + }, + "marker-prop-rejection": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json marker-prop-rejection passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/marker-prop-rejection-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json marker-prop-rejection failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/marker-prop-rejection-observation.json" + }, + "simultaneous-named-maps": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json simultaneous-named-maps passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/simultaneous-named-maps-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json simultaneous-named-maps failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/simultaneous-named-maps-observation.json" + }, + "provider-child-state": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained provider-child-state status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json provider-child-state passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/provider-child-state-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json provider-child-state failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/provider-child-state-observation.json" + }, + "annotation-image-refresh": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained annotation-image-refresh status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json annotation-image-refresh passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/annotation-image-refresh-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json annotation-image-refresh failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/annotation-image-refresh-observation.json" + }, + "resize-orientation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json resize-orientation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/resize-orientation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json resize-orientation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/resize-orientation-observation.json" + }, + "camera-target-isolation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained camera-target-isolation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json camera-target-isolation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/camera-target-isolation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json camera-target-isolation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/camera-target-isolation-observation.json" + }, + "touch-density-bounds": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained touch-density-bounds status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json touch-density-bounds passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/touch-density-bounds-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-manual.json touch-density-bounds failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/touch-density-bounds-observation.json" + } + }, + "observationSchema": { + "action": "Actual nonempty physical action performed in this run", + "seenResult": "Actual nonempty visible and renderer result, not a request or assumption", + "rendererData": "Optional actual readback object", + "screenshot": "Optional actual saved screenshot path" + }, + "orientationCommands": { + "readOriginalAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings get system accelerometer_rotation", + "readOriginalRotation": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings get system user_rotation", + "disableAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings put system accelerometer_rotation 0", + "landscape": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings put system user_rotation 1", + "portrait": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings put system user_rotation 0", + "restoreOriginalRotation": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings put system user_rotation \"${ORIGINAL_USER_ROTATION:?Use actually observed validated0to3}\"", + "restoreOriginalAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained resize-orientation adb shell settings put system accelerometer_rotation \"${ORIGINAL_ACCELEROMETER_ROTATION:?Use actually observed validated0or1}\"" + }, + "coreRejectionCommands": { + "Reject view draggable": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Reject view draggable\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject view draggable\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection status" + }, + "Reject view callback": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Reject view callback\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject view callback\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection status" + }, + "Reject annotation draggable": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Reject annotation draggable\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject annotation draggable\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection status" + }, + "Reject annotation callback": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Reject annotation callback\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject annotation callback\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core marker-prop-rejection status" + } + }, + "coreCompletionProtocol": "Before recording the13th passed manual outcome, Read renderer and inspect actual generation>=1/load>=2, known feature707, finite center/zoom, child-click>=1, marker-click>=1, annotation-click>=1, source-click>=2, popup-close>=1, location>=1 and no error. After all13 genuine receipts are written, one final fresh Read renderer POST permits driver completion; do not send further input once driver completes or switch to retained until its own phase starts. A failed prerequisite remains a first failure, never a forged receipt.", + "orientationProtocol": "Read and retain original values before rotation; validate accelerometer_rotation is literal0or1 and user_rotation literal0..3 before using restoration templates. Do not substitute guessed values. Owned fresh private AVD only. If null/invalid values occur, stop for coordinator classification; no foreign settings changes. Record actual landscape and portrait renderer bounds, fresh BOTH-child reads in each orientation, restore observed originals before final fresh snapshot and Finish focus.", + "inputCommandTemplates": { + "maplibre-android-core": { + "hierarchyDump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount adb shell uiautomator dump /sdcard/one-map-attempt30-maplibre-android-core-NNN.xml", + "hierarchyRead": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount adb shell cat /sdcard/one-map-attempt30-maplibre-android-core-NNN.xml", + "tap": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount adb shell input tap \"${FRESH_X:?Set measured physicalX}\" \"${FRESH_Y:?Set measured physicalY}\"", + "swipe": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount adb shell input swipe \"${START_X:?Set measured physicalX}\" \"${START_Y:?Set measured physicalY}\" \"${END_X:?Set measured physicalX}\" \"${END_Y:?Set measured physicalY}\" 450", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount adb shell screencap -p /sdcard/one-map-attempt30-maplibre-android-core-NNN.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-core style-remount adb pull /sdcard/one-map-attempt30-maplibre-android-core-NNN.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-NNN.png" + }, + "maplibre-android-retained": { + "hierarchyDump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell uiautomator dump /sdcard/one-map-attempt30-maplibre-android-retained-NNN.xml", + "hierarchyRead": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell cat /sdcard/one-map-attempt30-maplibre-android-retained-NNN.xml", + "tap": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell input tap \"${FRESH_X:?Set measured physicalX}\" \"${FRESH_Y:?Set measured physicalY}\"", + "swipe": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell input swipe \"${START_X:?Set measured physicalX}\" \"${START_Y:?Set measured physicalY}\" \"${END_X:?Set measured physicalX}\" \"${END_Y:?Set measured physicalY}\" 450", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb shell screencap -p /sdcard/one-map-attempt30-maplibre-android-retained-NNN.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30 maplibre-android-retained simultaneous-named-maps adb pull /sdcard/one-map-attempt30-maplibre-android-retained-NNN.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-retained-NNN.png" + } + }, + "inputCommandProtocol": "Replace NNN with fresh monotonic capture names and select actual current scenario when using templates. Physical touch points come from fresh selected-package hierarchy/bitmap bounds. For projected source/map point, physicalX=(mapBoundsX+pointX)*actualScale; physicalY=(mapBoundsY+pointY)*actualScale, using actual logical layout bounds and sourcePoint from same current read; verify feature against bitmap and current bounds. No stale dimensions, hardcoded cross-engine point, direct callback or assumed scale.", + "coordinatorAudit": { + "status": "passed", + "nativeExecution": false, + "scope": "Fixed MapLibre-only camera/core/retained call chain, selected-package rejection recovery, unchanged renderer judges, exact command/live judge/rotation/writer paths, freeze and runtime input pins", + "checks": [ + "Launcher three-row/backend-isolation/failure/cleanup mocks", + "Camera observer and exact MapLibre live-judge subprocess regressions", + "Operator 33 tests with selected MapLibre four-case rejection and cross-package negatives", + "695 frozen files and 60 runtime/regression pin hashes matched", + "Direct min24/target36/compile37 APK metadata and retained API36 compatibility reviewed", + "18.61 GiB free; fresh output30 absent" + ], + "limits": "Native execution pending; no production/f05/dependency changes or runtime certification from routine checks" + } +} diff --git a/records/evidence/revised-api-u26-maplibre-android-api36-resume-preparation.json b/records/evidence/revised-api-u26-maplibre-android-api36-resume-preparation.json new file mode 100644 index 0000000..04caa13 --- /dev/null +++ b/records/evidence/revised-api-u26-maplibre-android-api36-resume-preparation.json @@ -0,0 +1,725 @@ +{ + "candidate": { + "archive": "/Users/rob/code/mapbox-code/one-map/artifacts/revised-api-u25-f05/one-map-react-0.1.0-rc.2.tgz", + "sha256": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "members": 171, + "matchingPackageCopies": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/packages/one-map-react", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/one-map-react" + ], + "distSha256": "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + "runtimeDistProof": "Launcher verifies695 frozen files before acquisition and after each passed row, including selected MapLibre package/lock/SDK files. Preparation compares all171 archive members in both selected copies. Frozen fixtures and APKs remain unchanged." + }, + "freeze": { + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/mapbox-ios-sources-attempt-01/post-restoration-freeze.json", + "sha256": "2ec3355e8e8de917f001abf7cf6d02fcaf3ab034b93dc76224f81106988a9b8f", + "verifiedFiles": 695, + "mismatches": [] + }, + "stagedSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf09-rendering-smoke.mjs": "4f03fd882edb813891afaf48cf17ea8802d14f55dc7654093772786d415ba696", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf09-rendering-fixture.mjs": "50b90fa0b06d2b4cc3129084322bcfb232ab3113a003f134dc8c826bc9f7ad15", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/native-smoke-process.mjs": "09faef759e0fe9fdda9695b069a2eb1f105a56343143f20d6750c2f3b5bd712b", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/package.json": "85b17f2f852aece03e71edb4ed4d9fddf6a0a8f0b69ac75d7f00b6592d62d37c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/bitmapper.js": "3f2f720e3a2b4e41cdc03e9f58bb1794bec26dcd1b22568e41ce0b84ab20aeb5", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/bitpacker.js": "3f7bfabcbc82bedd0cc8551bc210b44dc1fb179fa2ce3b8b1d39fa307d8af204", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/chunkstream.js": "43c5507901554a29c5a29e555aaeb3c3987b84fb3aa8c681c1b30794a477aa85", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/constants.js": "9e3b4f994ac93751e9ccb4d453e85e4f25a0b086a9f24ec92c7dcb06995bdf6c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/crc.js": "57e2328cfa361fb54f1f4b3a59e071c1ccc864095e4f3759a957cd15aa2a8b65", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-pack.js": "500c1b3b34702c895e9e689143f44280687cac363447523679ec13d12bd564f6", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse-async.js": "328b6173f1a2a4d91425220a0fa421699552f254006a57ede9f4018ced50a7ee", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse-sync.js": "201a08dfab26a2903c0dabcbdfe0406b3fa33d60f59b591878329f590fac48ff", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse.js": "b8aad6f29371f5b13b232643781a7c49f7d36d565136ddda1ed7fbaca987ce2c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/format-normaliser.js": "c73989d85bef5d33ce571095bf0d96927261730d8b0f79c9d48f971fcbdd0be0", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/interlace.js": "3bb5d57153078ff586667e9a9d2c06db993c8ff1638e0521a9883cdeea6e1e3f", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer-async.js": "f50df0610749ce7b1a99abbe9e4596df7c16f96efd3848f12dd632b22cb02b45", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer-sync.js": "1b516238168a42704e62ba44528406188864a6ddda2ae92d1b91e5e078cdaa2d", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer.js": "b5f9956364c80d67c28d615ace639a5fb4d4d79d3acb235237f3050dca220e03", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/paeth-predictor.js": "48555b909af708593dade8e8df75d18ecdffdb6577e362eac01eae357ef1e0e9", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser-async.js": "a0299cad35220de62b7180b1f984b8f77b4c0f419a580fd3c86ea3b3e971ee30", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser-sync.js": "266c9fb230b90075022b3f54f5710a9cacb71ca565f83fce66e7cbd1b7e9b507", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser.js": "574e43fea28a28cc6feb7ab62a480a86bb75411ee4bfaba76a7e9d7310b6e94c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/png-sync.js": "867b1a78dcd3e45458eb4f0af01acd48f38d3a31225bd7cb8dd8ee3966ab54be", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/png.js": "e02cecbd36327829758386dc3f0ca4a36a2339ccb5d5e824ca3556e2c3f89726", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/sync-inflate.js": "08cb8afb79a4c0ab58e94601dab22261daf6638382b211d6a7f6bfbc16d27a0b", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/sync-reader.js": "437a99bf1bf739202ae85c3018cd9174d411597cf55e7064c36976de493368f1" + }, + "hostInputSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/with-android-env.sh": "c1edce14e259e16598218d9eb9a987587355ed3a6821da226c5c12897cf571b4", + "/private/tmp/one-map-android-restoration-review/scripts/launch-android-lifetime-emulator.py": "877dde6787b8463c740c916f24f54477f67365dd3b26d1a52bd2d4b5e7dcbb25", + "/private/tmp/one-map-android-restoration-review/scripts/setup-android-api36.py": "95b3de8a97f8fa2c3302cfc1c712383ad3e95ecb5c93456cbed5ef1b53101e4a", + "/private/tmp/one-map-approved-android-boot-poll.py": "f819d439aa4573070b858e80c7d3a61ca8f7a833f5ca857f3347ba5d39a35956", + "/Users/rob/Library/Android/sdk/emulator/source.properties": "ba13085f647fb8389a4d06a1de0e4104ac4e841733e50f67223ac230e1ce685a", + "/Users/rob/Library/Android/sdk/platform-tools/source.properties": "2dccd788c0234d8cf7f7457377e57f57527a86a629c6ed54feb8af0f549dac38", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/package.json": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/LogBoxInspectorContainer.js": "d8dbf80e71984e631b8d71e8f14c2f0bf7def9a78b05e641936530d9afd482a2", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/UI/LogBoxInspectorFooter.js": "81c1c99e0b0c376ef877b20391b6a442b499376368eadf388a36737be456ed4f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/Data/LogBoxData.js": "d9a60b7cb0a2025744fd56b90934a94ebbf9550aef11a8858dbfdc7773ba94ad", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-api36-image/.one-map-image.json": "e7be6e67a4aba4305918c4fa15a8b54bbe819c447eab4132e574a55af67c2b6c", + "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json": "dfd9e2d4f9f95205c25fc38afcb16af646896dbeed643515229d0e1ea841c57d" + }, + "operatorHelperSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py": "a6b26eb1fe16c7c7f25dc79b88624b3099dd124f7d1d6074d151465ce0e3600f", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs": "26f2e069d5ce6f2578715442d4f192a0ce9f5dad4b3e3601cfeb95c6165d3715" + }, + "checkpoint": "Remaining Android MapLibre API36 core and retained continuation", + "status": "Offline repair and independent source audit passed; owner continuation approval pending", + "nativeExecution": false, + "unit": { + "platform": "android", + "backend": "maplibre", + "device": "OneMapF05MapboxApi36 on emulator-5580", + "os": "Stable Android16 API36 Google APIs revision7 arm64-v8a standard4K userdebug image", + "immutableCandidate": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "executionRows": [ + "maplibre-android-core", + "maplibre-android-retained" + ], + "scope": "Reuse accepted camera30 and twelve accepted physical core observations30 only; obtain fresh four marker rejection cases and current known-feature/finite-camera/load/no-error renderer judgment, then all six fresh retained scenarios. Core30 itself remains unverified." + }, + "executionRows": [ + "maplibre-android-core", + "maplibre-android-retained" + ], + "worker": { + "model": "gpt-6.1-terra", + "reasoning": "medium", + "count": 1, + "ownership": "Exclusive selected emulator, Metro, installation, input, row reports and logs; coordinator owns diagnosis, pins and audit" + }, + "output": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31", + "command": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-resume.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31", + "proposedLauncherToolCall": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "cmd": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-resume.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31", + "max_output_tokens": 1500 + }, + "operatorToolParameters": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "max_output_tokens": 20000 + }, + "writerToolParameters": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "max_output_tokens": 1500 + }, + "operatorProtocol": { + "helper": "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py", + "writer": "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs", + "output": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31", + "rowOrder": [ + "maplibre-android-core", + "maplibre-android-retained" + ], + "readiness": "Camera30 is reused, not dispatched. Wait for API36 core phase and fresh driver report with exactly12immutable reusedObservations/passed scenario entries plus marker-prop-rejection unverified. Run all four marker rejection cases fresh. Before publishing the final physical passed receipt, Read renderer and inspect current known feature707, finite center/zoom, generation>=0, load>=1 and no error. Validated writer then records one new receipt; final Read renderer POST lets unchanged driver judge. Wait for retained phase/report; all six retained scenarios fresh with initial BOTHchildren/read BEFORE Theme and updatedcounts, finalfresh BOTHchildren/read before Finish.", + "firstFailure": "Any unexpected input, assertion or writer failure stops the unit. Preserve original error and raw bytes. Create a NEW valid failure observation using only allowed fields and record the current scenario failed through existing validated writer; the driver readManual polling detects it and performs normal finallycleanup. Await launcher normal exit/owned cleanup. NEVER signal the parent launcher expecting finally: it has no signalhandler.", + "exactInitialCalls": { + "maplibre-android-core": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection status", + "readRenderer": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"" + }, + "maplibre-android-retained": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps status", + "readRenderer": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"" + } + }, + "operationArgv": [ + "python3", + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31", + "ROW", + "SCENARIO", + "OPERATION", + "ARGUMENTS..." + ], + "writerArgv": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/ROW-manual.json", + "SCENARIO", + "passed|failed", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/SCENARIO-observation.json" + ], + "dynamicArguments": "ROW is maplibre-android-core or maplibre-android-retained; SCENARIO is the matching exact recipe key. Helper supports status, toolbar LABEL, dismiss-marker-rejection LABEL and bounded adb argument arrays. Use fresh measured coordinates; never reconstruct raw transport.", + "toolbarLabels": { + "core": [ + "remount", + "style", + "offset", + "popup", + "Target A", + "Target B", + "Repeat target", + "Clear target", + "Reject view draggable", + "Reject view callback", + "Reject annotation draggable", + "Reject annotation callback", + "Clear rejection", + "Read renderer" + ], + "retained": [ + "Read focus", + "Finish focus", + "Theme", + "Resize", + "Target A", + "Repeat A", + "Clear A", + "Image" + ] + }, + "hierarchyArgvTemplate": [ + "adb", + "shell", + "uiautomator", + "dump", + "/sdcard/one-map-attempt31-hierarchy-NNN.xml" + ], + "hierarchyReadTemplate": [ + "adb", + "shell", + "cat", + "/sdcard/one-map-attempt31-hierarchy-NNN.xml" + ], + "input": "Use fixed toolbar labels for retained controls and validated helper adb for fresh hierarchy/screenshots and actual measured feature/child bounds. No arbitrary warning dismissal or raw transport.", + "completion": "All13 core and all6 retained observations are individually recorded by validated writer with actual physical/rendered evidence. No bulk-pass assignments. Final core driver judge and retained Finish focus driver judge must pass. Camera/core/retained passed rows and installed identity reads are preserved." + }, + "coreOperatorRecipes": { + "marker-prop-rejection": "Run each of Reject view draggable, Reject view callback, Reject annotation draggable, Reject annotation callback through toolbar under marker-prop-rejection. Inspect exact native rejection/boundary, recover only via dismiss-marker-rejection LABEL for the same case, verify Clear rejection/current normal scene and No rejection requested after each. Match exact selected com.onemapmaplibre hierarchy and exact message. Record four distinct request receipts and no drag callback; wrong/unknown warning stops. Final Read renderer must remain valid." + }, + "retainedOperatorRecipes": { + "simultaneous-named-maps": "Read both actual map instances, touch each known feature and record independent named-map readbacks and finite measured viewports.", + "provider-child-state": "Before Theme press BOTH initial child buttons, then Read focus and status; require both initial/count>=1/current map-matching child snapshots. Only then Theme, press BOTH again, Read focus and verify both updated/count>=2 while initial checkpoint remains in history.", + "annotation-image-refresh": "Use Image, observe delayed image load and explicit annotation refresh, inspect resulting bitmap; require image-load/image-refresh and no image-error.", + "resize-orientation": "Use Resize both ways, then landscape and portrait on the owned device; find current controls from fresh hierarchy and record valid changed bounds and orientation readbacks. Refresh BOTH child snapshots and Read focus in each layout/orientation; use valid reads, not only screenshots.", + "camera-target-isolation": "Move only Map A and record its changed center while Map B stays fixed; repeat equal target without rollback, then clear. Verify named children read their own map. After every camera change refresh BOTH child snapshots by physically pressing both child buttons, then Read focus and verify matching centers/zoom before recording the read.", + "touch-density-bounds": "Physically activate children/features at their actual current bounds in both layouts; record actual window.scale and logical viewport measurements, with no synthetic callback invocation. After all camera/layout/image operations, physically press BOTH children again; Read focus must verify both snapshots against current maps before Finish focus." + }, + "coverageDispositions": [ + { + "group": "MapSetup/Map/useMap; selection and mixed aliases", + "disposition": "Existing frozen package/selection verification and four minimal native runs reused; simultaneous named-map/provider attachment remains in retained rows." + }, + { + "group": "Source/Layer/Images, styles and update lifetimes", + "disposition": "Four accepted bounded source/image scenes and four targeted rendering scenes reused. Both native adapter tests cover heatmap/fill-extrusion translation; representative real renderer evidence is sufficient under testing-policy.md. No new per-layer pixel suite and no claim of pixel certification for those types.", + "routineSources": [ + "packages/one-map-react/test/mapbox-native.native.test.tsx", + "packages/one-map-react/test/maplibre-native.native.test.tsx" + ], + "policy": "docs/testing-policy.md#select-checks-by-the-change and #test-behavior-at-the-owning-boundary" + }, + { + "group": "Queries/clusters/explicit feature state", + "disposition": "Four ordinary query/cluster and four lifetime scopes reused; no automatic clearing/replay guarantee is added." + }, + { + "group": "Camera, native unchanged targets and gestures", + "disposition": "Fresh MapLibre Android camera, core camera-target-and-gesture and retained camera-target-isolation cover changed camera behavior on API36. Native stop rejects; animation cancellation is not claimed. Other-engine/platform evidence retains original limits." + }, + { + "group": "Marker, portals, providers, offsets, refresh and failure handling", + "disposition": "Core and retained recipes own actual activation, nested scrolling, coordinates, host/layout, refresh and replacement. Common native drag success is excluded by contract; explicit rejection is required." + }, + { + "group": "UserLocation and migrated screen UI", + "disposition": "Core deterministic location action and supplied display, application-owned navigation/popups, SDK ornaments and legal attribution. No common acquisition, native units policy, source bubbling or removed controls are reintroduced." + }, + { + "group": "Selected wrapper and raw facilities", + "disposition": "Existing surface/peer/package and affected integration evidence reused. Raw SDK services are application-owned; no new general SDK certification, database/offline/capture/sensor campaign. SDK metadata/configuration limitations remain in original receipts." + }, + { + "group": "Density", + "disposition": "Retained rows record actual window.scale. Existing judgeNativeDensityMatrix requires two distinct positive observed scales per engine across Android+iOS. Android pinned source configuration420dpi corresponds to2.625; iOS expected3 must be actually observed, never inferred. No extra suite row is added. Identical/missing scales fail this explicit closeout gate." + }, + { + "group": "Excluded scope", + "disposition": "Physical devices, full VoiceOver/TalkBack certification, sensors, removed common services/controls/drag, RNMapbox invalidateAmbientCache/setMaximumAmbientCacheSize remain excluded; retained functionality is not relabeled unsupported." + } + ], + "fullContractMap": { + "source": "docs/requirements.md#purpose-and-scope, docs/revised-api-proposal.md and docs/api-coverage.md", + "fixedBaseline": "records/evidence/revised-api-u26-platform-batches-preparation.json", + "acceptedSelectedEvidence": { + "minimal": "revised-api-u25-f05-maplibre-android-minimal-attempt-01.json", + "lifetimes": "revised-api-u25-f05-maplibre-android-lifetimes-attempt-01.json", + "queries": "revised-api-u25-f05-maplibre-android-queries-attempt-05.json", + "sources": "revised-api-u25-f05-maplibre-android-sources-attempt-01.json", + "rendering": "revised-api-u25-f05-maplibre-android-rendering-attempt-01.json", + "camera": "revised-api-u26-android-maplibre-api36-attempt-30.json" + }, + "reuseLimits": "Only selected unchanged-f05 MapLibre Android minimal/lifetime/query/bounded-source/targeted-rendering evidence reused, within original scopes. Original OS evidence does not certify API36 camera/GL or UI. Fresh three-row unit supplies representative camera, query, style/replacement, live UI, density and attachment observations; any newly demonstrated gap blocks unit. Camera30 accepted; twelve physical core observations30 are accepted individually with exact provenance, but core30 final judge absent and remains unverified. Fresh marker/current renderer plus all retained remain.", + "pendingRows": [ + "maplibre-android-core", + "maplibre-android-retained" + ], + "pendingScenarioCount": 7, + "coverageRule": "All retained requirements must be passed, covered by applicable accepted evidence, or explicitly owner-excluded; unknown/failed work is never passed. No new general SDK/service/sensor/pixel campaign.", + "density": "Retained result top-level density is the actual current.window.scale; preserve raw observation array and APK/library identities. U27 later reconciles two distinct positive observed scales per engine across four retained rows. No assumed scale or extra test/platform switch.", + "selectedMatrix": "Mapbox API36 complete. MapLibre API36 camera30 passed; core and retained pending. Six iOS rows remain after selected unit." + }, + "verifiedBinaries": { + "android": { + "maplibre": { + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/android/app/build/outputs/apk/debug/app-debug.apk", + "sha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131" + } + } + }, + "resolvedPackageEvidence": { + "react-native": { + "version": "0.87.1", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/package.json", + "sha256": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de" + }, + "react": { + "version": "19.2.3", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react/package.json", + "sha256": "c383aced6a67c8d06f02996015c0a163e78532a330a96dff1ccfd107b00ab326" + }, + "@maplibre/maplibre-react-native": { + "version": "11.5.0", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/package.json", + "sha256": "13cad2ed700ffbc475cbf90050a7a1322add8fc2a8ba1c9ec958f89f771607e4" + }, + "react-native-teleport": { + "version": "1.2.1", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native-teleport/package.json", + "sha256": "03175c80b89d81f0466656bc6bf54be52436804c30cb97ee06b255271abda0fa" + } + }, + "packagedSdkEvidence": { + "nativeLibraries": { + "lib/arm64-v8a/libmaplibre.so": "d3a1ab9b9d056d84b93f2aa5f676d20d2d76723952dfcd8bd8d203d6eca6980d" + }, + "configuredNativeSdk": "org.maplibre.gl:android-sdk-opengl:13.6.1", + "configurationSource": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/android/gradle.properties", + "limit": "Configured SDK/version source and exact packaged native library hash; not an independent runtime version readback or general SDK certification." + }, + "batchInputSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/android-rendering.mjs": "3997155131d0f4246d968879d47121aa776449715225a1ac34e14ea21e9bcfa0", + "/private/tmp/one-map-android-restoration-review/scripts/android-camera-observer.mjs": "c1c589a6d74c1739e386af506f651a6c91b0c0a77e974a96b61c4a5ba2abae44", + "/private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-acceptance.mjs": "e66181da707b33b40823c49c69d42241d88ffbf0e053651fcb93d47442c01820", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-ui-smoke.mjs": "54073dfbc34632cff8861c974426001ea2b5fbd96ae3997287b8aba1050cf666", + "/private/tmp/one-map-android-restoration-review/scripts/native-smoke-process.mjs": "09faef759e0fe9fdda9695b069a2eb1f105a56343143f20d6750c2f3b5bd712b", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-smoke-contract.mjs": "fa4967297a3a0782d2aea89fe17b7d726a9b3052bac7437e0b47e1484cb3bf1b", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-retained-contract.mjs": "21dd6881cd052656ec1c3c63a173b62c817e5fe2c89dc156e529c606552f9695", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs": "26f2e069d5ce6f2578715442d4f192a0ce9f5dad4b3e3601cfeb95c6165d3715", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf04-camera-smoke.mjs": "13a9c48f32afc8118629f830f5d02c4c7e87d518f77e956a748f018194740e38", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-ui-smoke.mjs": "eee588dd20e8d712491045801a194f7d67a0a61f43791ef2df0f61eb2b944a11", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-smoke-contract.mjs": "74ca64dd2fb1c4a159e7f59edc213e9ca3d8893e433c61913c6f26682a062d2f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-retained-contract.mjs": "f4428fb5902170f57308738bfd44fa7a9a59d2a5aa957835ef199071a98b3852", + "/private/tmp/one-map-android-restoration-review/scripts/api36-reused-observations.mjs": "65af733c0e4a1804c90c54108bf2806af806fa93b29135a1b5d9ef8bea997815", + "/private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-resume.mjs": "19fa3b322b1137b962525a061dfccf83c573af7713b0cd4bbd776108db504484" + }, + "regressionSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/mapbox-android-rendering.test.mjs": "01c8fac50786a3c61d20d4eeae2c5fdbcfd5606738bb6c7e0e4e31a69d1152e8", + "/private/tmp/one-map-android-restoration-review/scripts/android-camera-observer.test.mjs": "7234012e787c0f4c835bdcea8ea56f3ffa0d20b1e0058ef2c3412c87eeac89ec", + "/private/tmp/one-map-android-restoration-review/scripts/android-installed-identity.test.mjs": "bd6b11bc709f7fd3ff95446179da2907224b1064d0e509f1ba9c78d54318008c", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-native-runner.test.mjs": "49e1754c5ecdbfc762a294a0d518247489ee8e53bb84670a61391dd88b965989", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.test.mjs": "a4a0d9e05ec4a58e59fda03e254469465fbda4885c4e33489fc942c3e2430c2a", + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.test.py": "07f013404f05dbe2e842251bfe599d551b0b952e1942ef08f9eb55d1e52b926f", + "/private/tmp/one-map-android-restoration-review/scripts/setup-android-api36.test.py": "18221ffa7dba7c5000e39e278928e2dfbb5e1f134520cc40d634620be021aab6", + "/private/tmp/one-map-android-restoration-review/scripts/launch-android-lifetime-emulator.test.py": "31c7caf00ecc75ad30f7833d6c0c6ad4fce472e811f3fa421496b6fc37c318d7", + "/private/tmp/one-map-android-restoration-review/scripts/api36-retained-observation.test.mjs": "54e0991aa4005f15e6eec94401a5c097fc6d14db81a10fd24b210bba52cfc72c", + "/private/tmp/one-map-android-restoration-review/scripts/api36-reused-observations.test.mjs": "7c56262934a2f851cffa0aa3fe869ba48011063fd93ff8f97b16e7b32171ff52", + "/private/tmp/one-map-android-restoration-review/scripts/fixtures/api36-maplibre-attempt30-rejected-input.json": "818e84f6b230f04c08756893d4302f684d925ff58516e7ac7cbab1d91f458b93" + }, + "storage": { + "measuredWholeUnitPeakAvailable": false, + "measurementGap": "No empirical whole-unit peak is claimed. Reuse existing verified4.3GiB image and unchanged APK; configured private userdata/sdcard and install/cache allowance budget4GiB,6GiB headroom and2GiB cleanup reserve. No download/build.", + "requiredFreeBytes": 12884901888, + "planningBudget": { + "privateUserdataUpperBytes": 2147483648, + "sdcardUpperBytes": 134217728, + "apkInstallAndTaskCacheAllowanceBytes": 2013265920, + "hostHeadroomBytes": 6442450944, + "cleanupReserveBytes": 2147483648 + }, + "meaning": "Conservative12GiB planning capacity, not an empirical peak or a SIGKILL explanation. Configured userdata/sdcard bounds plus install/cache allowance total4GiB, with6GiB host headroom and2GiB cleanup reserve. Historical modes keep their8.2GiB gate.", + "currentFreeBytes": 19106897920, + "readiness": "Require fresh12GiB plus absent attempt30 output immediately before dispatch; image member/hash check remains mandatory.", + "shortfallBytes": 0, + "preDispatchReadOnlyCheck": { + "cmd": "python3 -c 'import pathlib, shutil; p=pathlib.Path(\"/Users/rob/code/mapbox-code/one-map-f05-android-recovery\"); free=shutil.disk_usage(p).free; print({\"freeBytes\":free,\"requiredBytes\":12*1024**3}); assert (p/\"android-api36-image\").is_dir(),\"Hold: verified image missing\"; assert free>=12*1024**3,\"Hold:12GiB storage gate\"; assert not (p/\"android-platform-batch-attempt-31\").exists(),\"Hold: output exists\"'", + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "max_output_tokens": 1000, + "purpose": "Coordinator only, under existing owner execution authorization and after audit/readiness decision; no emulator/adb/app starts and no file is created. Do not dispatch on a known capacity failure." + }, + "imageReuse": "Reuse retained API36 image only after setup helper checks all28members and hashes. No download when verification succeeds." + }, + "timing": { + "estimateMinutes": "40-75minutes estimated for remaining marker/current-renderer core and allsix retained with verifiedimage reuse; no build/download", + "manualPerRowMs": 1800000, + "driverPerRowMs": 2100000, + "bootMs": 180000, + "installMs": 120000, + "ordinaryCommandMs": 30000, + "workerAllocationMinutes": 150, + "limit": "Existing finite phase bounds retained;150minutes is coordinator supervision allocation, not a global launcher watchdog. Reserve cleanup; stop first failure without retry.", + "reuseEstimate": "40-75minutes estimated for remaining marker/current-renderer core and allsix retained with verifiedimage reuse; no build/download" + }, + "resources": { + "serial": "emulator-5580", + "privateAvd": "OneMapF05MapboxApi36", + "ports": [ + 5580, + 5581, + 8081, + 8797 + ], + "ownedReverses": [ + "tcp:8081", + "tcp:8797" + ], + "lifetime": "Verified retained API36 image, fresh private historical-name AVD and unchanged checked MapLibre APK. Camera30 remains accepted and unrun; core+retained share only owned emulator/reverse and sequential row Metro/status. No Mapbox execution.", + "cleanup": "Normal failure path: create a valid failure observation for the current manual scenario, use validated writer passed|failed CLI, and await driver readManual failure plus normal launcher finallycleanup. Preserve first failed report/latch; no upgrade. Interruption fallback only: independently verify acquired PID/PGID ownership from current checkpoint/diagnostics and exact private AVD, then bounded TERM/KILL only owned driver/emulator groups; verify processes/ports and private AVD+ini absence. Do not signal parent expecting finally; it has no handler. Preserve foreign resources, all raw30 evidence and verified image. Any uncertain ownership stops for coordinator review.", + "retention": "Compact outcome, provenance and row reports persist; essential raw logs/screenshots remain temporary. Existing kernel-console log is not byte-bounded; no new tracing campaign is added.", + "image": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-api36-image" + }, + "exclusions": [ + "No Mapbox rerun or interleaved backend", + "No build, dependency restore, peer/lock/version/fixture/APK/f05 change", + "No image download: retained image must exist and all28files match", + "No CUA, raw transport, Android Studio, signal calibration or speculative framework", + "No independent retry or changed artifact/environment", + "Physical devices, full VoiceOver/TalkBack, sensors and two owner-excluded RNMapbox cache operations remain outside scope" + ], + "routineVerification": { + "nativeExecuted": false, + "passed": [ + "Portable exact raw-input fixture reproduces unknown top-level receipts rejection before mutation on a temporary synthetic matching-identity report with12passed/markerunverified. Corrected repository JSON moves only receipts under rendererData and succeeds; report identities and inputfixturebytes preserved. No active S/attempt30 dependency and no acceptance credit.", + "Fixed MapLibre30 outcome/checkpoint/manual byte pins and freshidentity/backend/tamper rejection tests", + "Actual launcher mocks cover remainingcore+retained only, camera reuse, nointerleaving, envgate, first failure/passedprefix and ownedcleanup", + "TF07 runner MapLibre reuse provenance, immutable reused observations and failed-manual cleanup mocks", + "Final five focused regression suites passed after formatting: loader provenance, actual launcher selection/cleanup, TF07 runner, exact writer replay and all three exact packet livejudge commands", + "Vite+ format/lint passed on nine touched JavaScript files; no new native execution" + ], + "pending": [ + "Owner approval of complete remainingunit attempt31" + ], + "commands": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/api36-reused-observations.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/mapbox-android-rendering.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/tf07-native-runner.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/record-native-ui-observation.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/api36-retained-observation.test.mjs" + ] + }, + "authorization": "No execution or retry authorized. Owner must approve this complete remaining-unit proposal after independent audit: unchangedf05/APK/image, selected MapLibre core+retained, exact reuse/provenance, fresh four marker cases/current renderer and six retained scenarios, estimated40-75minutes,12GiB reserve and owned cleanup. No other backend, build, download, calibration or independent retry.", + "exactOperatorCommands": [ + "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps status", + "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"" + ], + "compatibility": { + "source": "https://dl.google.com/android/repository/sys-img/google_apis/sys-img2-3.xml", + "repositorySha256": "b1261b4f645125367bc74d5e0881a55cb489cf13bae26a3c9d61bdef287d228e", + "package": "system-images;android-36;google_apis;arm64-v8a", + "revision": 7, + "channel": 0, + "url": "https://dl.google.com/android/repository/sys-img/google_apis/arm64-v8a-36_r07.zip", + "archiveBytes": 1872691175, + "archiveSha1": "5a99183b6d924da606260e45fd41a3eb8eca6eb7", + "uncompressedBytes": 4575096761, + "regularFiles": 28, + "zip64Resolved": true, + "sourcePropertiesSha256": "f53d5fbbb89420d911b9e5ed9243aff60caad24132a76e649efc8dfd96295731", + "buildPropSha256": "999e509f85b5edd5522e867842f27a10f4cb077082bbd70d8eea27fc073463af", + "kernelSha256": "9b300ef4ee5ea5ee21c0a1924991e92a740d93127b19edead1a9365e83df95ca", + "offlineKernelConfig": "CONFIG_ARM64_4K_PAGES=y;16K/64Knotset; official compressed kernel member inspected offline, not booted", + "image": "Android16 REL preview0 API36 google_apis arm64-v8a userdebug/debuggable1, Google Play services without Play Store, GPU support true", + "emulatorMinimum": "35.4.9", + "installedEmulator": "37.2.12", + "installedAdb": "37.0.1", + "retainedApkManifest": { + "minSdk": 24, + "targetSdk": 36, + "compileSdk": 37, + "method": "Direct offline binary AndroidManifest.xml parse of pinned MapLibre APK" + }, + "reason": "Retained MapLibre APK min24/target36 permits selected stable API36 arm64-v8a. Image requires emulator>=35.4.9; installed37.2.12 satisfies it. Pinned image standard4K kernel avoids API37/16K variant. Runtime API/ABI/page/GLES checks remain required; this is offline compatibility evidence.", + "runtimeGateBeforeInstall": "API36; arm64-v8a; getconf PAGE_SIZE=4096; ro.opengles.version>=196608. Skip API37-only ACCESS_LOCAL_NETWORK grant; old modes unchanged.", + "offlineImageVerification": { + "files": 28, + "manifestSha256": "e7be6e67a4aba4305918c4fa15a8b54bbe819c447eab4132e574a55af67c2b6c", + "mismatches": [], + "nativeExecuted": false + } + }, + "installedIdentityVerification": { + "method": "adb -s emulator-5580 shell /system/bin/toybox sha256sum EXACT_SOLE_BASE_APK_PATH", + "validation": "Unchanged input APK hash; exactly one pm path in safe shell alphabet; exact lower-case64hex digest and matching sole filename; digest equals pinned APK. Shared before/after checks remain. Nonzero/malformed output stops; no pull fallback/retry.", + "transportDiagnostics": "First8command failures retain redacted file/args, code, signal, killed, elapsedMs, timeoutMs and last4096characters of stdout/stderr. Timeout-compatible termination is not proven causation.", + "boundary": "Installed-byte digest replaces host readback hashing. Tool presence established offline in pinned image; runtime availability and native outcomes unverified.", + "samePatternReview": "Shared Android launcher identity and selected TF07 core/retained driver both use strict device-side SHA256. Historical standalone TF08 still pulls APKs outside this packet; no general transport cause is claimed." + }, + "retainedReadinessProtocol": { + "commands": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps status", + "readFocus": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"", + "dump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell uiautomator dump /sdcard/one-map-attempt31-retained-read.xml", + "hierarchy": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell cat /sdcard/one-map-attempt31-retained-read.xml", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell screencap -p /sdcard/one-map-attempt31-retained-read.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb pull /sdcard/one-map-attempt31-retained-read.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/retained-read.png", + "captureStatus": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps status > /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/retained-status.txt" + }, + "boundedReadback": "After Read focus, run fresh status then hierarchy/screenshot. If status remains null, observe status at most15times over30seconds without repeated input. A populated object is not a pass: inspect actual named-map readbacks and error events. Actual failed command/assertion/read-error stops immediately. After the bounded window with null only, present fresh post-read hierarchy/screenshot/status to coordinator before creating a failure latch, so the coordinator can classify obstruction evidence within this approved unit. No unilateral retry or null-only warning classification.", + "obstruction": "Existing helper computes a lower interior Y only for fresh retained top0 toolbar tap/swipe bounds. Inspect current hierarchy/screenshot if readback remains null; do not replay stale coordinates or assume a successful input proves a read.", + "notice": "Do not fail or dismiss solely for the known nonmodal synthetic debugger notice. Unknown visible errors/warnings require coordinator inspection; actual errors remain first failures." + }, + "liveJudgeCommand": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node --input-type=module -e 'import assert from \"node:assert/strict\"; import {readFileSync} from \"node:fs\"; import {judgeNativeRetained} from \"/private/tmp/one-map-android-restoration-review/scripts/tf07-retained-contract.mjs\"; const lines=readFileSync(process.argv[1],\"utf8\").trim().split(\"\\n\"); const start=lines.indexOf(\"START status http://127.0.0.1:8797/tf07\"); assert(start>=0 && lines.length===start+3 && lines.at(-1)===\"COMPLETE 0\",\"Expected successful operator status output\"); const body=JSON.parse(lines[start+1]); assert(body && typeof body===\"object\" && !Array.isArray(body),\"Await populated renderer status\"); const manual=JSON.parse(readFileSync(process.argv[2],\"utf8\")); console.log(JSON.stringify(judgeNativeRetained(body,manual,{installedBinarySha256:\"c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131\",libraryDistSha256:\"f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5\",environment:\"maplibre-android\",runId:manual.runId}),null,2));' /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/retained-status.txt /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json", + "retainedCheckpoints": [ + { + "step": "Initial context before Theme", + "actions": "Physically press BOTH initial child buttons using fresh bounds. Read focus, capture actual status and run liveJudgeCommand.", + "required": "checks.initialTheme and checks.currentRead true; both children initial/count>=1 and centers/zoom match their named maps. Do not press Theme until this actual read is in history." + }, + { + "step": "Updated context", + "actions": "Only after initial checkpoint: Theme, physically press BOTH child buttons again, Read focus, capture status and run liveJudgeCommand.", + "required": "checks.initialTheme, checks.updatedTheme and checks.currentRead true; both children updated/count>=2, with matching map centers/zoom." + }, + { + "step": "All six physical scenarios", + "actions": "Complete all six retained recipes as one row, observing actual known features/touches/image load-refresh, changed sizes, both orientations and isolated camera. After camera/layout/image changes physically press BOTH children and Read focus again.", + "required": "Preserve valid initial and updated history, actual window.scale positive. Errors remain first failures; all6 fresh physical receipts required." + }, + { + "step": "Final fresh snapshot before Finish", + "actions": "After ALL camera/resize/orientation/image changes, physically press BOTH child buttons, then Read focus, capture status and run liveJudgeCommand.", + "required": "EVERY checks entry except focusedComplete is true, especially currentRead/initialTheme/updatedTheme. Verify all6 current manual scenarios and meaningful action/seenResult receipts. focusedComplete=false is expected before Finish. Never synthesize or edit renderer history." + }, + { + "step": "Finish and verify", + "actions": "Only then Finish focus. Capture actual final status and run liveJudgeCommand if driver remains active; let driver judge the same unchanged contract and finish normally.", + "required": "Allchecks true, manualComplete true, status passed and final driver/launcher passed. Do not submit unverified output as completed acceptance." + } + ], + "coreExecutionOrder": [ + "marker-prop-rejection" + ], + "completedEvidenceReused": { + "minimal": [ + "revised-api-u25-f05-maplibre-android-minimal-attempt-01.json" + ], + "lifetimes": [ + "revised-api-u25-f05-maplibre-android-lifetimes-attempt-01.json" + ], + "queries": [ + "revised-api-u25-f05-maplibre-android-queries-attempt-05.json" + ], + "sources": [ + "revised-api-u25-f05-maplibre-android-sources-attempt-01.json" + ], + "rendering": [ + "revised-api-u25-f05-maplibre-android-rendering-attempt-01.json" + ] + }, + "liveJudgeProtocol": "Capture exact actual helper START status / one JSON object / COMPLETE0 output to retained-status.txt. Live judge parses it strictly and binds pinned MapLibre APK/dist/environment plus current report runId. Before Finish focusedComplete=false is EXPECTED: Read focus calls read() with its defaultfalse; Finish focus calls read(true), which performs a fresh actual SDK read. Require EVERY other checks entry true and manualComplete=true before Finish. The running driver independently binds its runId and judges after that fresh finished read. Source: native-harness/examples/shared/native-tf07-retained-screen.tsx read default/SDK reads and Read focus/Finish focus bindings; scripts/tf07-ui-smoke.mjs nativeStatus completion gates.", + "unchangedInputVerification": { + "nativeExecuted": false, + "frozenFiles": 695, + "maplibreFrozenPaths": 297, + "frozenMismatches": [], + "archiveMembersPerCopy": 171, + "packageCopies": 2, + "selectedApkMatch": true, + "imageFiles": 28, + "freshOutputAbsent": true, + "apkManifest": { + "manifest": { + "versionCode": 1, + "versionName": "1.0", + "compileSdkVersion": 37, + "compileSdkVersionCodename": "17", + "package": "com.onemapmaplibre", + "platformBuildVersionCode": 37, + "platformBuildVersionName": 17 + }, + "uses-sdk": { + "minSdkVersion": 24, + "targetSdkVersion": 36 + } + } + }, + "scenarioCommands": { + "marker-prop-rejection": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-manual.json marker-prop-rejection passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/marker-prop-rejection-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-manual.json marker-prop-rejection failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/marker-prop-rejection-observation.json" + }, + "simultaneous-named-maps": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json simultaneous-named-maps passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/simultaneous-named-maps-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json simultaneous-named-maps failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/simultaneous-named-maps-observation.json" + }, + "provider-child-state": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained provider-child-state status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json provider-child-state passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/provider-child-state-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json provider-child-state failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/provider-child-state-observation.json" + }, + "annotation-image-refresh": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained annotation-image-refresh status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json annotation-image-refresh passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/annotation-image-refresh-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json annotation-image-refresh failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/annotation-image-refresh-observation.json" + }, + "resize-orientation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json resize-orientation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/resize-orientation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json resize-orientation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/resize-orientation-observation.json" + }, + "camera-target-isolation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained camera-target-isolation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json camera-target-isolation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/camera-target-isolation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json camera-target-isolation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/camera-target-isolation-observation.json" + }, + "touch-density-bounds": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained touch-density-bounds status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json touch-density-bounds passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/touch-density-bounds-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json touch-density-bounds failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/touch-density-bounds-observation.json" + } + }, + "observationSchema": { + "allowedTopLevelFields": [ + "action", + "seenResult", + "rendererData", + "screenshot" + ], + "action": "Required nonempty actual physical action", + "seenResult": "Required nonempty actual observed result", + "rendererData": "Optional actual object; put receipts array INSIDE this object", + "screenshot": "Optional actual screenshot path", + "forbidden": "No top-level receipts or other keys. No fabricated historical or new renderer observations." + }, + "orientationCommands": { + "readOriginalAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings get system accelerometer_rotation", + "readOriginalRotation": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings get system user_rotation", + "disableAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings put system accelerometer_rotation 0", + "landscape": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings put system user_rotation 1", + "portrait": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings put system user_rotation 0", + "restoreOriginalRotation": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings put system user_rotation \"${ORIGINAL_USER_ROTATION:?Use actually observed validated0to3}\"", + "restoreOriginalAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained resize-orientation adb shell settings put system accelerometer_rotation \"${ORIGINAL_ACCELEROMETER_ROTATION:?Use actually observed validated0or1}\"" + }, + "coreRejectionCommands": { + "Reject view draggable": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Reject view draggable\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject view draggable\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection status" + }, + "Reject view callback": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Reject view callback\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject view callback\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection status" + }, + "Reject annotation draggable": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Reject annotation draggable\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject annotation draggable\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection status" + }, + "Reject annotation callback": { + "request": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Reject annotation callback\"", + "recover": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection dismiss-marker-rejection \"Reject annotation callback\"", + "clear": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Clear rejection\"", + "read": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection toolbar \"Read renderer\"", + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection status" + } + }, + "coreCompletionProtocol": "Reused twelve physical receipts are immutable, no old events are imported. Fresh four marker cases need exact selected-package rejection receipts and clear/read between cases. Before final writer publication inspect actual current knownfeature707, finite center/zoom, generation>=0, load>=1/noerror; all other counters are governed by exact reusedScenarios in unchanged judge. Only after actual physical outcome and valid observation schema, write final passed marker receipt and request final fresh Read renderer. Wait for normal core driver pass and owned per-row cleanup before retained phase.", + "orientationProtocol": "Read and retain original values before rotation; validate accelerometer_rotation is literal0or1 and user_rotation literal0..3 before using restoration templates. Do not substitute guessed values. Owned fresh private AVD only. If null/invalid values occur, stop for coordinator classification; no foreign settings changes. Record actual landscape and portrait renderer bounds, fresh BOTH-child reads in each orientation, restore observed originals before final fresh snapshot and Finish focus.", + "inputCommandTemplates": { + "maplibre-android-core": { + "hierarchyDump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection adb shell uiautomator dump /sdcard/one-map-attempt31-maplibre-android-core-NNN.xml", + "hierarchyRead": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection adb shell cat /sdcard/one-map-attempt31-maplibre-android-core-NNN.xml", + "tap": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection adb shell input tap \"${FRESH_X:?Set measured physicalX}\" \"${FRESH_Y:?Set measured physicalY}\"", + "swipe": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection adb shell input swipe \"${START_X:?Set measured physicalX}\" \"${START_Y:?Set measured physicalY}\" \"${END_X:?Set measured physicalX}\" \"${END_Y:?Set measured physicalY}\" 450", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection adb shell screencap -p /sdcard/one-map-attempt31-maplibre-android-core-NNN.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-core marker-prop-rejection adb pull /sdcard/one-map-attempt31-maplibre-android-core-NNN.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-NNN.png" + }, + "maplibre-android-retained": { + "hierarchyDump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell uiautomator dump /sdcard/one-map-attempt31-maplibre-android-retained-NNN.xml", + "hierarchyRead": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell cat /sdcard/one-map-attempt31-maplibre-android-retained-NNN.xml", + "tap": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell input tap \"${FRESH_X:?Set measured physicalX}\" \"${FRESH_Y:?Set measured physicalY}\"", + "swipe": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell input swipe \"${START_X:?Set measured physicalX}\" \"${START_Y:?Set measured physicalY}\" \"${END_X:?Set measured physicalX}\" \"${END_Y:?Set measured physicalY}\" 450", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb shell screencap -p /sdcard/one-map-attempt31-maplibre-android-retained-NNN.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31 maplibre-android-retained simultaneous-named-maps adb pull /sdcard/one-map-attempt31-maplibre-android-retained-NNN.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-NNN.png" + } + }, + "inputCommandProtocol": "Replace NNN with fresh monotonic capture names and select actual current scenario when using templates. Physical touch points come from fresh selected-package hierarchy/bitmap bounds. For projected source/map point, physicalX=(mapBoundsX+pointX)*actualScale; physicalY=(mapBoundsY+pointY)*actualScale, using actual logical layout bounds and sourcePoint from same current read; verify feature against bitmap and current bounds. No stale dimensions, hardcoded cross-engine point, direct callback or assumed scale.", + "coordinatorAudit": { + "status": "passed", + "nativeExecution": false, + "scope": "Exact writer-schema failure, immutable failed outcome and camera/twelve-observation reuse, fresh marker/current renderer requirements, retained complete row, validated failure publication and owned cleanup", + "checks": [ + "Coordinator independently reviewed fixed loader/envgate/launcher resume, exact12provenance/freshmarker/currentSDKread/error checks", + "Coordinator independently reran reuse/orchestration/writer regressions", + "Portable schema replay subsequently passed exact writer CLI, targeted formatting/lint; immutable outcome30 unchanged" + ], + "limits": "No retry executed; core30 remains unverified and retained unrun; continuation awaits explicit owner approval" + }, + "reusedCamera": { + "outcomePath": "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json", + "outcomeSha256": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + "checkpointPath": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/checkpoint.json", + "checkpointSha256": "441e0a77035ce5f7157e550b63dc38c0d244802965164ec1bc74534836efcecf", + "row": "maplibre-android-camera", + "scope": "Immutable completed camera row and installed-byte identities before/after; not a completed core row." + }, + "reusedCorePhysicalObservations": { + "reportPath": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json", + "reportSha256": "0b3c5b46c960edc3fa129996bbc794d104c211f1230134af57248d1b263915d1", + "runId": "8ca84053-4355-45bc-8d81-0b213cd34adb", + "outcomePath": "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json", + "outcomeSha256": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + "scenarios": [ + "live-child-button", + "nested-scroll", + "live-activation", + "annotation-activation", + "offset-touch-bounds", + "popup-follow-dismissal", + "map-feature-click", + "navigation-location", + "style-remount", + "host-accessibility", + "sdk-ornaments", + "camera-target-and-gesture" + ], + "limits": "Only twelve passed physical receipts reused. No prior renderer counters are imported; freshrun identity, fresh known feature707, finitecenter/zoom, generation>=0/load>=1/noerror plus new marker physical receipt must satisfy unchanged judge. Marker raw input and synthetic schema-replay report earn no acceptance credit." + }, + "correctedOfflineInput": { + "path": "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json", + "sha256": "dfd9e2d4f9f95205c25fc38afcb16af646896dbeed643515229d0e1ea841c57d", + "change": "Only move receipts under rendererData; new copy, raw input/report untouched.", + "limit": "Offline schema reproduction; no core acceptance credit.", + "sourceRawSha256": "818e84f6b230f04c08756893d4302f684d925ff58516e7ac7cbab1d91f458b93", + "purpose": "Device-free exactwriter reproduction only; do not dispatch as a new physical observation or modify raw30 report." + }, + "failurePublication": { + "createInput": "Create a NEW output/SCENARIO-failure-observation.json with only action,seenResult and optional rendererData/screenshot. Preserve raw bad input. Describe the original failure; no synthetic passed output.", + "writerTemplate": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/ROW-manual.json SCENARIO failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/SCENARIO-failure-observation.json", + "after": "Allow driver polling to observe failed scenario and perform cleanup. Await launcher exit and read checkpoint/receipt. If publication is impossible, report coordinator immediately and use only verified-ownership interruption fallback; no broad kills or retries." + } +} diff --git a/records/evidence/revised-api-u26-maplibre-android-api36-retained-preparation.json b/records/evidence/revised-api-u26-maplibre-android-api36-retained-preparation.json new file mode 100644 index 0000000..83b3d0d --- /dev/null +++ b/records/evidence/revised-api-u26-maplibre-android-api36-retained-preparation.json @@ -0,0 +1,662 @@ +{ + "candidate": { + "archive": "/Users/rob/code/mapbox-code/one-map/artifacts/revised-api-u25-f05/one-map-react-0.1.0-rc.2.tgz", + "sha256": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "members": 171, + "matchingPackageCopies": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/packages/one-map-react", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/one-map-react" + ], + "distSha256": "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + "runtimeDistProof": "Launcher verifies695 frozen files before acquisition and after each passed row, including selected MapLibre package/lock/SDK files. Preparation compares all171 archive members in both selected copies. Frozen fixtures and APKs remain unchanged." + }, + "freeze": { + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/mapbox-ios-sources-attempt-01/post-restoration-freeze.json", + "sha256": "2ec3355e8e8de917f001abf7cf6d02fcaf3ab034b93dc76224f81106988a9b8f", + "verifiedFiles": 695, + "mismatches": [] + }, + "stagedSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf09-rendering-smoke.mjs": "4f03fd882edb813891afaf48cf17ea8802d14f55dc7654093772786d415ba696", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf09-rendering-fixture.mjs": "50b90fa0b06d2b4cc3129084322bcfb232ab3113a003f134dc8c826bc9f7ad15", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/native-smoke-process.mjs": "09faef759e0fe9fdda9695b069a2eb1f105a56343143f20d6750c2f3b5bd712b", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/package.json": "85b17f2f852aece03e71edb4ed4d9fddf6a0a8f0b69ac75d7f00b6592d62d37c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/bitmapper.js": "3f2f720e3a2b4e41cdc03e9f58bb1794bec26dcd1b22568e41ce0b84ab20aeb5", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/bitpacker.js": "3f7bfabcbc82bedd0cc8551bc210b44dc1fb179fa2ce3b8b1d39fa307d8af204", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/chunkstream.js": "43c5507901554a29c5a29e555aaeb3c3987b84fb3aa8c681c1b30794a477aa85", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/constants.js": "9e3b4f994ac93751e9ccb4d453e85e4f25a0b086a9f24ec92c7dcb06995bdf6c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/crc.js": "57e2328cfa361fb54f1f4b3a59e071c1ccc864095e4f3759a957cd15aa2a8b65", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-pack.js": "500c1b3b34702c895e9e689143f44280687cac363447523679ec13d12bd564f6", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse-async.js": "328b6173f1a2a4d91425220a0fa421699552f254006a57ede9f4018ced50a7ee", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse-sync.js": "201a08dfab26a2903c0dabcbdfe0406b3fa33d60f59b591878329f590fac48ff", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/filter-parse.js": "b8aad6f29371f5b13b232643781a7c49f7d36d565136ddda1ed7fbaca987ce2c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/format-normaliser.js": "c73989d85bef5d33ce571095bf0d96927261730d8b0f79c9d48f971fcbdd0be0", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/interlace.js": "3bb5d57153078ff586667e9a9d2c06db993c8ff1638e0521a9883cdeea6e1e3f", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer-async.js": "f50df0610749ce7b1a99abbe9e4596df7c16f96efd3848f12dd632b22cb02b45", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer-sync.js": "1b516238168a42704e62ba44528406188864a6ddda2ae92d1b91e5e078cdaa2d", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/packer.js": "b5f9956364c80d67c28d615ace639a5fb4d4d79d3acb235237f3050dca220e03", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/paeth-predictor.js": "48555b909af708593dade8e8df75d18ecdffdb6577e362eac01eae357ef1e0e9", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser-async.js": "a0299cad35220de62b7180b1f984b8f77b4c0f419a580fd3c86ea3b3e971ee30", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser-sync.js": "266c9fb230b90075022b3f54f5710a9cacb71ca565f83fce66e7cbd1b7e9b507", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/parser.js": "574e43fea28a28cc6feb7ab62a480a86bb75411ee4bfaba76a7e9d7310b6e94c", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/png-sync.js": "867b1a78dcd3e45458eb4f0af01acd48f38d3a31225bd7cb8dd8ee3966ab54be", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/png.js": "e02cecbd36327829758386dc3f0ca4a36a2339ccb5d5e824ca3556e2c3f89726", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/sync-inflate.js": "08cb8afb79a4c0ab58e94601dab22261daf6638382b211d6a7f6bfbc16d27a0b", + "/Users/rob/code/mapbox-code/one-map/node_modules/.bun/pngjs@7.0.0/node_modules/pngjs/lib/sync-reader.js": "437a99bf1bf739202ae85c3018cd9174d411597cf55e7064c36976de493368f1" + }, + "hostInputSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/with-android-env.sh": "c1edce14e259e16598218d9eb9a987587355ed3a6821da226c5c12897cf571b4", + "/private/tmp/one-map-android-restoration-review/scripts/launch-android-lifetime-emulator.py": "877dde6787b8463c740c916f24f54477f67365dd3b26d1a52bd2d4b5e7dcbb25", + "/private/tmp/one-map-android-restoration-review/scripts/setup-android-api36.py": "95b3de8a97f8fa2c3302cfc1c712383ad3e95ecb5c93456cbed5ef1b53101e4a", + "/private/tmp/one-map-approved-android-boot-poll.py": "f819d439aa4573070b858e80c7d3a61ca8f7a833f5ca857f3347ba5d39a35956", + "/Users/rob/Library/Android/sdk/emulator/source.properties": "ba13085f647fb8389a4d06a1de0e4104ac4e841733e50f67223ac230e1ce685a", + "/Users/rob/Library/Android/sdk/platform-tools/source.properties": "2dccd788c0234d8cf7f7457377e57f57527a86a629c6ed54feb8af0f549dac38", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/package.json": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/LogBoxInspectorContainer.js": "d8dbf80e71984e631b8d71e8f14c2f0bf7def9a78b05e641936530d9afd482a2", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/UI/LogBoxInspectorFooter.js": "81c1c99e0b0c376ef877b20391b6a442b499376368eadf388a36737be456ed4f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/Libraries/LogBox/Data/LogBoxData.js": "d9a60b7cb0a2025744fd56b90934a94ebbf9550aef11a8858dbfdc7773ba94ad", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-api36-image/.one-map-image.json": "e7be6e67a4aba4305918c4fa15a8b54bbe819c447eab4132e574a55af67c2b6c", + "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json": "dfd9e2d4f9f95205c25fc38afcb16af646896dbeed643515229d0e1ea841c57d", + "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-31.json": "3317ec5e334434d33854b74a0bb6f51750e8565cb8259b48d96300f79b5390fc", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/receipt.json": "500b1914deb2152bdfbf3ed52fa9490bb10ea80f4354ffc6ece18f956240a190", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-result.json": "ae647e0a42819166357ca697dccb1f3ee82dd9f79574577aa1ab228f4987ae9b", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-manual.json": "a11dab67a1f7b2c294fdf8b07e7409f708e6a9a5273d983a1761c4ba0f601097" + }, + "operatorHelperSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py": "a6b26eb1fe16c7c7f25dc79b88624b3099dd124f7d1d6074d151465ce0e3600f", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs": "26f2e069d5ce6f2578715442d4f192a0ce9f5dad4b3e3601cfeb95c6165d3715" + }, + "checkpoint": "Remaining Android MapLibre API36 retained-only continuation", + "status": "Executed passed: Android MapLibre API36 unit complete within declared scope", + "nativeExecution": true, + "unit": { + "platform": "android", + "backend": "maplibre", + "device": "OneMapF05MapboxApi36 on emulator-5580 (historical private AVD name, MapLibre APK only)", + "os": "Stable Android16 API36 Google APIs revision7 arm64-v8a standard4K userdebug image", + "immutableCandidate": "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276", + "executionRows": [ + "maplibre-android-retained" + ], + "scope": "Reuse immutable accepted camera30 and completed core31; execute all six retained scenarios fresh in one row, without reusing partial retained31 receipts/history." + }, + "executionRows": [ + "maplibre-android-retained" + ], + "worker": { + "model": "gpt-6.1-terra", + "reasoning": "medium", + "count": 1, + "ownership": "Exclusive selected emulator, Metro, installation, input, row reports and logs; coordinator owns diagnosis, pins and audit" + }, + "output": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32", + "command": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-retained-resume.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32", + "proposedLauncherToolCall": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "cmd": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-retained-resume.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32", + "max_output_tokens": 1500 + }, + "operatorToolParameters": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "max_output_tokens": 20000 + }, + "writerToolParameters": { + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "sandbox_permissions": "require_escalated", + "yield_time_ms": 1000, + "max_output_tokens": 1500 + }, + "operatorProtocol": { + "helper": "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py", + "writer": "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs", + "output": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32", + "rowOrder": [ + "maplibre-android-retained" + ], + "readiness": "Camera30 and completed core31 are reused and never rerun. Wait for retained phase/fresh report. Run all six retained recipes with fresh current history: BOTH initial children pressed/read BEFORE Theme, BOTH updated children pressed/read with counts>=2, current reads after all camera/layout/image/orientation changes and final fresh BOTH-child snapshots before Finish.", + "firstFailure": "Any unexpected input, assertion or writer failure stops the unit. Preserve original error and raw bytes. Create a NEW valid failure observation using only allowed fields and record the current scenario failed through existing validated writer; the driver readManual polling detects it and performs normal finallycleanup. Await launcher normal exit/owned cleanup. NEVER signal the parent launcher expecting finally: it has no signalhandler.", + "exactInitialCalls": { + "maplibre-android-retained": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps status", + "readRenderer": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"" + } + }, + "operationArgv": [ + "python3", + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.py", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32", + "ROW", + "SCENARIO", + "OPERATION", + "ARGUMENTS..." + ], + "writerArgv": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/ROW-manual.json", + "SCENARIO", + "passed|failed", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/SCENARIO-observation.json" + ], + "dynamicArguments": "ROW is maplibre-android-core or maplibre-android-retained; SCENARIO is the matching exact recipe key. Helper supports status, toolbar LABEL, dismiss-marker-rejection LABEL and bounded adb argument arrays. Use fresh measured coordinates; never reconstruct raw transport.", + "toolbarLabels": { + "core": [ + "remount", + "style", + "offset", + "popup", + "Target A", + "Target B", + "Repeat target", + "Clear target", + "Reject view draggable", + "Reject view callback", + "Reject annotation draggable", + "Reject annotation callback", + "Clear rejection", + "Read renderer" + ], + "retained": [ + "Read focus", + "Finish focus", + "Theme", + "Resize", + "Target A", + "Repeat A", + "Clear A", + "Image" + ] + }, + "hierarchyArgvTemplate": [ + "adb", + "shell", + "uiautomator", + "dump", + "/sdcard/one-map-attempt32-hierarchy-NNN.xml" + ], + "hierarchyReadTemplate": [ + "adb", + "shell", + "cat", + "/sdcard/one-map-attempt32-hierarchy-NNN.xml" + ], + "input": "Use fixed toolbar labels for retained controls and validated helper adb for fresh hierarchy/screenshots and actual measured feature/child bounds. No arbitrary warning dismissal or raw transport.", + "completion": "Allsix fresh individually verified retained physical receipts plus all13renderer checks and independent final driver judge required; preFinish focusedComplete=false expected, every other check and manualComplete true. Finishfocus makes a fresh actualSDKread. Partial retained31 receipt/history is not reusable." + }, + "coreOperatorRecipes": {}, + "retainedOperatorRecipes": { + "simultaneous-named-maps": "Read both actual map instances, touch each known feature and record independent named-map readbacks and finite measured viewports.", + "provider-child-state": "Before Theme press BOTH initial child buttons, then Read focus and status; require both initial/count>=1/current map-matching child snapshots. Only then Theme, press BOTH again, Read focus and verify both updated/count>=2 while initial checkpoint remains in history.", + "annotation-image-refresh": "Use Image, observe delayed image load and explicit annotation refresh, inspect resulting bitmap; require image-load/image-refresh and no image-error.", + "resize-orientation": "Use Resize both ways, then landscape and portrait on the owned device; find current controls from fresh hierarchy and record valid changed bounds and orientation readbacks. Refresh BOTH child snapshots and Read focus in each layout/orientation; use valid reads, not only screenshots.", + "camera-target-isolation": "Move only Map A and record its changed center while Map B stays fixed; repeat equal target without rollback, then clear. Verify named children read their own map. After every camera change refresh BOTH child snapshots by physically pressing both child buttons, then Read focus and verify matching centers/zoom before recording the read.", + "touch-density-bounds": "Physically activate children/features at their actual current bounds in both layouts; record actual window.scale and logical viewport measurements, with no synthetic callback invocation. After all camera/layout/image operations, physically press BOTH children again; Read focus must verify both snapshots against current maps before Finish focus." + }, + "coverageDispositions": [ + { + "group": "MapSetup/Map/useMap; selection and mixed aliases", + "disposition": "Existing frozen package/selection verification and four minimal native runs reused; simultaneous named-map/provider attachment remains in retained rows." + }, + { + "group": "Source/Layer/Images, styles and update lifetimes", + "disposition": "Four accepted bounded source/image scenes and four targeted rendering scenes reused. Both native adapter tests cover heatmap/fill-extrusion translation; representative real renderer evidence is sufficient under testing-policy.md. No new per-layer pixel suite and no claim of pixel certification for those types.", + "routineSources": [ + "packages/one-map-react/test/mapbox-native.native.test.tsx", + "packages/one-map-react/test/maplibre-native.native.test.tsx" + ], + "policy": "docs/testing-policy.md#select-checks-by-the-change and #test-behavior-at-the-owning-boundary" + }, + { + "group": "Queries/clusters/explicit feature state", + "disposition": "Four ordinary query/cluster and four lifetime scopes reused; no automatic clearing/replay guarantee is added." + }, + { + "group": "Camera, native unchanged targets and gestures", + "disposition": "Fresh MapLibre Android camera, core camera-target-and-gesture and retained camera-target-isolation cover changed camera behavior on API36. Native stop rejects; animation cancellation is not claimed. Other-engine/platform evidence retains original limits." + }, + { + "group": "Marker, portals, providers, offsets, refresh and failure handling", + "disposition": "Core and retained recipes own actual activation, nested scrolling, coordinates, host/layout, refresh and replacement. Common native drag success is excluded by contract; explicit rejection is required." + }, + { + "group": "UserLocation and migrated screen UI", + "disposition": "Core deterministic location action and supplied display, application-owned navigation/popups, SDK ornaments and legal attribution. No common acquisition, native units policy, source bubbling or removed controls are reintroduced." + }, + { + "group": "Selected wrapper and raw facilities", + "disposition": "Existing surface/peer/package and affected integration evidence reused. Raw SDK services are application-owned; no new general SDK certification, database/offline/capture/sensor campaign. SDK metadata/configuration limitations remain in original receipts." + }, + { + "group": "Density", + "disposition": "Retained rows record actual window.scale. Existing judgeNativeDensityMatrix requires two distinct positive observed scales per engine across Android+iOS. Android pinned source configuration420dpi corresponds to2.625; iOS expected3 must be actually observed, never inferred. No extra suite row is added. Identical/missing scales fail this explicit closeout gate." + }, + { + "group": "Excluded scope", + "disposition": "Physical devices, full VoiceOver/TalkBack certification, sensors, removed common services/controls/drag, RNMapbox invalidateAmbientCache/setMaximumAmbientCacheSize remain excluded; retained functionality is not relabeled unsupported." + } + ], + "fullContractMap": { + "source": "docs/requirements.md#purpose-and-scope, docs/revised-api-proposal.md and docs/api-coverage.md", + "fixedBaseline": "records/evidence/revised-api-u26-platform-batches-preparation.json", + "acceptedSelectedEvidence": { + "minimal": "revised-api-u25-f05-maplibre-android-minimal-attempt-01.json", + "lifetimes": "revised-api-u25-f05-maplibre-android-lifetimes-attempt-01.json", + "queries": "revised-api-u25-f05-maplibre-android-queries-attempt-05.json", + "sources": "revised-api-u25-f05-maplibre-android-sources-attempt-01.json", + "rendering": "revised-api-u25-f05-maplibre-android-rendering-attempt-01.json", + "camera": "revised-api-u26-android-maplibre-api36-attempt-30.json", + "core": "revised-api-u26-android-maplibre-api36-attempt-31.json" + }, + "reuseLimits": "Accepted camera30 and completed core31 retain recorded artifact/scope limits. Retained31 timedout after worker interruption and remains unverified; all six retained scenarios plus all initial/updated/final history must be fresh.", + "pendingRows": [ + "maplibre-android-retained" + ], + "pendingScenarioCount": 6, + "coverageRule": "All retained requirements must be passed, covered by applicable accepted evidence, or explicitly owner-excluded; unknown/failed work is never passed. No new general SDK/service/sensor/pixel campaign.", + "density": "Retained result top-level density is the actual current.window.scale; preserve raw observation array and APK/library identities. U27 later reconciles two distinct positive observed scales per engine across four retained rows. No assumed scale or extra test/platform switch.", + "selectedMatrix": "Mapbox API36 complete. MapLibre API36 camera30 and core31 passed; retained pending. Seven rows remain across three native units, including six iOS rows." + }, + "verifiedBinaries": { + "android": { + "maplibre": { + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/android/app/build/outputs/apk/debug/app-debug.apk", + "sha256": "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131" + } + } + }, + "resolvedPackageEvidence": { + "react-native": { + "version": "0.87.1", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native/package.json", + "sha256": "8c939f43cd569562f00f13a5b7326f14b13d7a4909e4bedec3fc4d73096858de" + }, + "react": { + "version": "19.2.3", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react/package.json", + "sha256": "c383aced6a67c8d06f02996015c0a163e78532a330a96dff1ccfd107b00ab326" + }, + "@maplibre/maplibre-react-native": { + "version": "11.5.0", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/package.json", + "sha256": "13cad2ed700ffbc475cbf90050a7a1322add8fc2a8ba1c9ec958f89f771607e4" + }, + "react-native-teleport": { + "version": "1.2.1", + "path": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/react-native-teleport/package.json", + "sha256": "03175c80b89d81f0466656bc6bf54be52436804c30cb97ee06b255271abda0fa" + } + }, + "packagedSdkEvidence": { + "nativeLibraries": { + "lib/arm64-v8a/libmaplibre.so": "d3a1ab9b9d056d84b93f2aa5f676d20d2d76723952dfcd8bd8d203d6eca6980d" + }, + "configuredNativeSdk": "org.maplibre.gl:android-sdk-opengl:13.6.1", + "configurationSource": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/examples/native-maplibre/node_modules/@maplibre/maplibre-react-native/android/gradle.properties", + "limit": "Configured SDK/version source and exact packaged native library hash; not an independent runtime version readback or general SDK certification." + }, + "batchInputSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/android-rendering.mjs": "c87cc0554803800ba47927db4ae4fbc3bd913629368e6f0eb2e1ce0ea289d34f", + "/private/tmp/one-map-android-restoration-review/scripts/android-camera-observer.mjs": "c1c589a6d74c1739e386af506f651a6c91b0c0a77e974a96b61c4a5ba2abae44", + "/private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-acceptance.mjs": "e66181da707b33b40823c49c69d42241d88ffbf0e053651fcb93d47442c01820", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-ui-smoke.mjs": "54073dfbc34632cff8861c974426001ea2b5fbd96ae3997287b8aba1050cf666", + "/private/tmp/one-map-android-restoration-review/scripts/native-smoke-process.mjs": "09faef759e0fe9fdda9695b069a2eb1f105a56343143f20d6750c2f3b5bd712b", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-smoke-contract.mjs": "fa4967297a3a0782d2aea89fe17b7d726a9b3052bac7437e0b47e1484cb3bf1b", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-retained-contract.mjs": "21dd6881cd052656ec1c3c63a173b62c817e5fe2c89dc156e529c606552f9695", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs": "26f2e069d5ce6f2578715442d4f192a0ce9f5dad4b3e3601cfeb95c6165d3715", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf04-camera-smoke.mjs": "13a9c48f32afc8118629f830f5d02c4c7e87d518f77e956a748f018194740e38", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-ui-smoke.mjs": "eee588dd20e8d712491045801a194f7d67a0a61f43791ef2df0f61eb2b944a11", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-smoke-contract.mjs": "74ca64dd2fb1c4a159e7f59edc213e9ca3d8893e433c61913c6f26682a062d2f", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/native-harness/scripts/tf07-retained-contract.mjs": "f4428fb5902170f57308738bfd44fa7a9a59d2a5aa957835ef199071a98b3852", + "/private/tmp/one-map-android-restoration-review/scripts/api36-reused-observations.mjs": "65af733c0e4a1804c90c54108bf2806af806fa93b29135a1b5d9ef8bea997815", + "/private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-resume.mjs": "19fa3b322b1137b962525a061dfccf83c573af7713b0cd4bbd776108db504484", + "/private/tmp/one-map-android-restoration-review/scripts/maplibre-android-api36-retained-resume.mjs": "92c0667b23bb2ca77f29dd66461acdb5aef52313ee64d4d9ac9e9baca55de645" + }, + "regressionSha256": { + "/private/tmp/one-map-android-restoration-review/scripts/mapbox-android-rendering.test.mjs": "cafa3f079bcf1fee66fa94ecc20578c33b89deca813f0d51f6e85655643f0fa0", + "/private/tmp/one-map-android-restoration-review/scripts/android-camera-observer.test.mjs": "7234012e787c0f4c835bdcea8ea56f3ffa0d20b1e0058ef2c3412c87eeac89ec", + "/private/tmp/one-map-android-restoration-review/scripts/android-installed-identity.test.mjs": "bd6b11bc709f7fd3ff95446179da2907224b1064d0e509f1ba9c78d54318008c", + "/private/tmp/one-map-android-restoration-review/scripts/tf07-native-runner.test.mjs": "49e1754c5ecdbfc762a294a0d518247489ee8e53bb84670a61391dd88b965989", + "/private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.test.mjs": "a4a0d9e05ec4a58e59fda03e254469465fbda4885c4e33489fc942c3e2430c2a", + "/private/tmp/one-map-android-restoration-review/scripts/android-operator.test.py": "07f013404f05dbe2e842251bfe599d551b0b952e1942ef08f9eb55d1e52b926f", + "/private/tmp/one-map-android-restoration-review/scripts/setup-android-api36.test.py": "18221ffa7dba7c5000e39e278928e2dfbb5e1f134520cc40d634620be021aab6", + "/private/tmp/one-map-android-restoration-review/scripts/launch-android-lifetime-emulator.test.py": "31c7caf00ecc75ad30f7833d6c0c6ad4fce472e811f3fa421496b6fc37c318d7", + "/private/tmp/one-map-android-restoration-review/scripts/api36-retained-observation.test.mjs": "6a18876689a41bff1a723a13feaecfed185999ab931b27fa426eefb4b09b2954", + "/private/tmp/one-map-android-restoration-review/scripts/api36-reused-observations.test.mjs": "7c56262934a2f851cffa0aa3fe869ba48011063fd93ff8f97b16e7b32171ff52", + "/private/tmp/one-map-android-restoration-review/scripts/fixtures/api36-maplibre-attempt30-rejected-input.json": "818e84f6b230f04c08756893d4302f684d925ff58516e7ac7cbab1d91f458b93" + }, + "storage": { + "measuredWholeUnitPeakAvailable": false, + "measurementGap": "No empirical whole-unit peak is claimed. Reuse existing verified4.3GiB image and unchanged APK; configured private userdata/sdcard and install/cache allowance budget4GiB,6GiB headroom and2GiB cleanup reserve. No download/build.", + "requiredFreeBytes": 12884901888, + "planningBudget": { + "privateUserdataUpperBytes": 2147483648, + "sdcardUpperBytes": 134217728, + "apkInstallAndTaskCacheAllowanceBytes": 2013265920, + "hostHeadroomBytes": 6442450944, + "cleanupReserveBytes": 2147483648 + }, + "meaning": "Conservative12GiB planning capacity, not an empirical peak or a SIGKILL explanation. Configured userdata/sdcard bounds plus install/cache allowance total4GiB, with6GiB host headroom and2GiB cleanup reserve. Historical modes keep their8.2GiB gate.", + "currentFreeBytes": 17875345408, + "readiness": "Require fresh12GiB plus absent attempt30 output immediately before dispatch; image member/hash check remains mandatory.", + "shortfallBytes": 0, + "preDispatchReadOnlyCheck": { + "cmd": "python3 -c 'import pathlib, shutil; p=pathlib.Path(\"/Users/rob/code/mapbox-code/one-map-f05-android-recovery\"); free=shutil.disk_usage(p).free; print({\"freeBytes\":free,\"requiredBytes\":12*1024**3}); assert (p/\"android-api36-image\").is_dir(),\"Hold: verified image missing\"; assert free>=12*1024**3,\"Hold:12GiB storage gate\"; assert not (p/\"android-platform-batch-attempt-32\").exists(),\"Hold: output exists\"'", + "workdir": "/private/tmp/one-map-android-restoration-review", + "shell": "/bin/sh", + "login": false, + "max_output_tokens": 1000, + "purpose": "Coordinator only, under existing owner execution authorization and after audit/readiness decision; no emulator/adb/app starts and no file is created. Do not dispatch on a known capacity failure." + }, + "imageReuse": "Reuse retained API36 image only after setup helper checks all28members and hashes. No download when verification succeeds." + }, + "timing": { + "estimateMinutes": "15-35minutes estimated: verifiedimage boot/install and one six-scenario retained row", + "manualPerRowMs": 1800000, + "driverPerRowMs": 2100000, + "bootMs": 180000, + "installMs": 120000, + "ordinaryCommandMs": 30000, + "workerAllocationMinutes": 150, + "limit": "Existing finite phase bounds retained;150minutes is coordinator supervision allocation, not a global launcher watchdog. Reserve cleanup; stop first failure without retry.", + "reuseEstimate": "15-35minutes estimated: verifiedimage boot/install and one six-scenario retained row" + }, + "resources": { + "serial": "emulator-5580", + "privateAvd": "OneMapF05MapboxApi36", + "ports": [ + 5580, + 5581, + 8081, + 8797 + ], + "ownedReverses": [ + "tcp:8081", + "tcp:8797" + ], + "lifetime": "Verified retained API36 image, fresh private historical-name AVD and unchanged checked MapLibre APK. Camera30/core31 accepted and unrun; exactly one retained driver/Metro/status owns remaining row.", + "cleanup": "Normal failure path: create a valid failure observation for the current manual scenario, use validated writer passed|failed CLI, and await driver readManual failure plus normal launcher finallycleanup. Preserve first failed report/latch; no upgrade. Interruption fallback only: independently verify acquired PID/PGID ownership from current checkpoint/diagnostics and exact private AVD, then bounded TERM/KILL only owned driver/emulator groups; verify processes/ports and private AVD+ini absence. Do not signal parent expecting finally; it has no handler. Preserve foreign resources, all raw30 evidence and verified image. Any uncertain ownership stops for coordinator review.", + "retention": "Compact outcome, provenance and row reports persist; essential raw logs/screenshots remain temporary. Existing kernel-console log is not byte-bounded; no new tracing campaign is added.", + "image": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-api36-image" + }, + "exclusions": [ + "No Mapbox rerun or interleaved backend", + "No build, dependency restore, peer/lock/version/fixture/APK/f05 change", + "No image download: retained image must exist and all28files match", + "No CUA, raw transport, Android Studio, signal calibration or speculative framework", + "No independent retry or changed artifact/environment", + "Physical devices, full VoiceOver/TalkBack, sensors and two owner-excluded RNMapbox cache operations remain outside scope" + ], + "routineVerification": { + "nativeExecuted": false, + "passed": [ + "Actual launcher mocks cover retained-only MapLibre rowselection and immutable completedcore status/identity/scope/hash/before-after proof failures; camera/core are not rerun", + "Both focused suites passed after formatting: actual launcher mocks, including retained-only row selection, core observed/manualComplete/remaining/scope/identity/hash/before-after negatives; all four exact packet livejudge subprocess controls", + "Targeted Vite+ formatting/lint passed on four JavaScript files" + ], + "pending": [ + "Independent coordinator audit" + ], + "commands": [ + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/mapbox-android-rendering.test.mjs", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node scripts/api36-retained-observation.test.mjs" + ] + }, + "authorization": "Owner Continue after the worker usage-limit interruption explicitly resumes the current unchanged MapLibre batch. After coordinator audit, the same exclusive Terra worker executes this retained-only continuation with samef05/APK/deviceOS/image/contract. No new artifact/target, camera/core rerun, independent retry, build, download or calibration.", + "exactOperatorCommands": [ + "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps status", + "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"" + ], + "compatibility": { + "source": "https://dl.google.com/android/repository/sys-img/google_apis/sys-img2-3.xml", + "repositorySha256": "b1261b4f645125367bc74d5e0881a55cb489cf13bae26a3c9d61bdef287d228e", + "package": "system-images;android-36;google_apis;arm64-v8a", + "revision": 7, + "channel": 0, + "url": "https://dl.google.com/android/repository/sys-img/google_apis/arm64-v8a-36_r07.zip", + "archiveBytes": 1872691175, + "archiveSha1": "5a99183b6d924da606260e45fd41a3eb8eca6eb7", + "uncompressedBytes": 4575096761, + "regularFiles": 28, + "zip64Resolved": true, + "sourcePropertiesSha256": "f53d5fbbb89420d911b9e5ed9243aff60caad24132a76e649efc8dfd96295731", + "buildPropSha256": "999e509f85b5edd5522e867842f27a10f4cb077082bbd70d8eea27fc073463af", + "kernelSha256": "9b300ef4ee5ea5ee21c0a1924991e92a740d93127b19edead1a9365e83df95ca", + "offlineKernelConfig": "CONFIG_ARM64_4K_PAGES=y;16K/64Knotset; official compressed kernel member inspected offline, not booted", + "image": "Android16 REL preview0 API36 google_apis arm64-v8a userdebug/debuggable1, Google Play services without Play Store, GPU support true", + "emulatorMinimum": "35.4.9", + "installedEmulator": "37.2.12", + "installedAdb": "37.0.1", + "retainedApkManifest": { + "minSdk": 24, + "targetSdk": 36, + "compileSdk": 37, + "method": "Direct offline binary AndroidManifest.xml parse of pinned MapLibre APK" + }, + "reason": "Retained MapLibre APK min24/target36 permits selected stable API36 arm64-v8a. Image requires emulator>=35.4.9; installed37.2.12 satisfies it. Pinned image standard4K kernel avoids API37/16K variant. Runtime API/ABI/page/GLES checks remain required; this is offline compatibility evidence.", + "runtimeGateBeforeInstall": "API36; arm64-v8a; getconf PAGE_SIZE=4096; ro.opengles.version>=196608. Skip API37-only ACCESS_LOCAL_NETWORK grant; old modes unchanged.", + "offlineImageVerification": { + "files": 28, + "manifestSha256": "e7be6e67a4aba4305918c4fa15a8b54bbe819c447eab4132e574a55af67c2b6c", + "mismatches": [], + "nativeExecuted": false + } + }, + "installedIdentityVerification": { + "method": "adb -s emulator-5580 shell /system/bin/toybox sha256sum EXACT_SOLE_BASE_APK_PATH", + "validation": "Unchanged input APK hash; exactly one pm path in safe shell alphabet; exact lower-case64hex digest and matching sole filename; digest equals pinned APK. Shared before/after checks remain. Nonzero/malformed output stops; no pull fallback/retry.", + "transportDiagnostics": "First8command failures retain redacted file/args, code, signal, killed, elapsedMs, timeoutMs and last4096characters of stdout/stderr. Timeout-compatible termination is not proven causation.", + "boundary": "Installed-byte digest replaces host readback hashing. Tool presence established offline in pinned image; runtime availability and native outcomes unverified.", + "samePatternReview": "Shared Android launcher identity and selected TF07 core/retained driver both use strict device-side SHA256. Historical standalone TF08 still pulls APKs outside this packet; no general transport cause is claimed." + }, + "retainedReadinessProtocol": { + "commands": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps status", + "readFocus": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps toolbar \"Read focus\"", + "dump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell uiautomator dump /sdcard/one-map-attempt32-retained-read.xml", + "hierarchy": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell cat /sdcard/one-map-attempt32-retained-read.xml", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell screencap -p /sdcard/one-map-attempt32-retained-read.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb pull /sdcard/one-map-attempt32-retained-read.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/retained-read.png", + "captureStatus": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps status > /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/retained-status.txt" + }, + "boundedReadback": "After Read focus, run fresh status then hierarchy/screenshot. If status remains null, observe status at most15times over30seconds without repeated input. A populated object is not a pass: inspect actual named-map readbacks and error events. Actual failed command/assertion/read-error stops immediately. After the bounded window with null only, present fresh post-read hierarchy/screenshot/status to coordinator before creating a failure latch, so the coordinator can classify obstruction evidence within this approved unit. No unilateral retry or null-only warning classification.", + "obstruction": "Existing helper computes a lower interior Y only for fresh retained top0 toolbar tap/swipe bounds. Inspect current hierarchy/screenshot if readback remains null; do not replay stale coordinates or assume a successful input proves a read.", + "notice": "Do not fail or dismiss solely for the known nonmodal synthetic debugger notice. Unknown visible errors/warnings require coordinator inspection; actual errors remain first failures." + }, + "liveJudgeCommand": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node --input-type=module -e 'import assert from \"node:assert/strict\"; import {readFileSync} from \"node:fs\"; import {judgeNativeRetained} from \"/private/tmp/one-map-android-restoration-review/scripts/tf07-retained-contract.mjs\"; const lines=readFileSync(process.argv[1],\"utf8\").trim().split(\"\\n\"); const start=lines.indexOf(\"START status http://127.0.0.1:8797/tf07\"); assert(start>=0 && lines.length===start+3 && lines.at(-1)===\"COMPLETE 0\",\"Expected successful operator status output\"); const body=JSON.parse(lines[start+1]); assert(body && typeof body===\"object\" && !Array.isArray(body),\"Await populated renderer status\"); const manual=JSON.parse(readFileSync(process.argv[2],\"utf8\")); console.log(JSON.stringify(judgeNativeRetained(body,manual,{installedBinarySha256:\"c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131\",libraryDistSha256:\"f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5\",environment:\"maplibre-android\",runId:manual.runId}),null,2));' /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/retained-status.txt /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json", + "retainedCheckpoints": [ + { + "step": "Initial context before Theme", + "actions": "Physically press BOTH initial child buttons using fresh bounds. Read focus, capture actual status and run liveJudgeCommand.", + "required": "checks.initialTheme and checks.currentRead true; both children initial/count>=1 and centers/zoom match their named maps. Do not press Theme until this actual read is in history." + }, + { + "step": "Updated context", + "actions": "Only after initial checkpoint: Theme, physically press BOTH child buttons again, Read focus, capture status and run liveJudgeCommand.", + "required": "checks.initialTheme, checks.updatedTheme and checks.currentRead true; both children updated/count>=2, with matching map centers/zoom." + }, + { + "step": "All six physical scenarios", + "actions": "Complete all six retained recipes as one row, observing actual known features/touches/image load-refresh, changed sizes, both orientations and isolated camera. After camera/layout/image changes physically press BOTH children and Read focus again.", + "required": "Preserve valid initial and updated history, actual window.scale positive. Errors remain first failures; all6 fresh physical receipts required." + }, + { + "step": "Final fresh snapshot before Finish", + "actions": "After ALL camera/resize/orientation/image changes, physically press BOTH child buttons, then Read focus, capture status and run liveJudgeCommand.", + "required": "EVERY checks entry except focusedComplete is true, especially currentRead/initialTheme/updatedTheme. Verify all6 current manual scenarios and meaningful action/seenResult receipts. focusedComplete=false is expected before Finish. Never synthesize or edit renderer history." + }, + { + "step": "Finish and verify", + "actions": "Only then Finish focus. Capture actual final status and run liveJudgeCommand if driver remains active; let driver judge the same unchanged contract and finish normally.", + "required": "Allchecks true, manualComplete true, status passed and final driver/launcher passed. Do not submit unverified output as completed acceptance." + } + ], + "coreExecutionOrder": [], + "completedEvidenceReused": { + "minimal": [ + "revised-api-u25-f05-maplibre-android-minimal-attempt-01.json" + ], + "lifetimes": [ + "revised-api-u25-f05-maplibre-android-lifetimes-attempt-01.json" + ], + "queries": [ + "revised-api-u25-f05-maplibre-android-queries-attempt-05.json" + ], + "sources": [ + "revised-api-u25-f05-maplibre-android-sources-attempt-01.json" + ], + "rendering": [ + "revised-api-u25-f05-maplibre-android-rendering-attempt-01.json" + ] + }, + "liveJudgeProtocol": "Capture exact actual helper START status / one JSON object / COMPLETE0 output to retained-status.txt. Live judge parses it strictly and binds pinned MapLibre APK/dist/environment plus current report runId. Before Finish focusedComplete=false is EXPECTED: Read focus calls read() with its defaultfalse; Finish focus calls read(true), which performs a fresh actual SDK read. Require EVERY other checks entry true and manualComplete=true before Finish. The running driver independently binds its runId and judges after that fresh finished read. Source: native-harness/examples/shared/native-tf07-retained-screen.tsx read default/SDK reads and Read focus/Finish focus bindings; scripts/tf07-ui-smoke.mjs nativeStatus completion gates.", + "unchangedInputVerification": { + "nativeExecuted": false, + "frozenFiles": 695, + "maplibreFrozenPaths": 297, + "frozenMismatches": [], + "archiveMembersPerCopy": 171, + "packageCopies": 2, + "selectedApkMatch": true, + "imageFiles": 28, + "freshOutputAbsent": true, + "apkManifest": { + "manifest": { + "versionCode": 1, + "versionName": "1.0", + "compileSdkVersion": 37, + "compileSdkVersionCodename": "17", + "package": "com.onemapmaplibre", + "platformBuildVersionCode": 37, + "platformBuildVersionName": 17 + }, + "uses-sdk": { + "minSdkVersion": 24, + "targetSdkVersion": 36 + } + } + }, + "scenarioCommands": { + "simultaneous-named-maps": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json simultaneous-named-maps passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/simultaneous-named-maps-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json simultaneous-named-maps failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/simultaneous-named-maps-observation.json" + }, + "provider-child-state": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained provider-child-state status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json provider-child-state passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/provider-child-state-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json provider-child-state failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/provider-child-state-observation.json" + }, + "annotation-image-refresh": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained annotation-image-refresh status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json annotation-image-refresh passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/annotation-image-refresh-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json annotation-image-refresh failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/annotation-image-refresh-observation.json" + }, + "resize-orientation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json resize-orientation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/resize-orientation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json resize-orientation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/resize-orientation-observation.json" + }, + "camera-target-isolation": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained camera-target-isolation status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json camera-target-isolation passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/camera-target-isolation-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json camera-target-isolation failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/camera-target-isolation-observation.json" + }, + "touch-density-bounds": { + "status": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained touch-density-bounds status", + "writePassed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json touch-density-bounds passed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/touch-density-bounds-observation.json", + "writeFailed": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-manual.json touch-density-bounds failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/touch-density-bounds-observation.json" + } + }, + "observationSchema": { + "allowedTopLevelFields": [ + "action", + "seenResult", + "rendererData", + "screenshot" + ], + "action": "Required nonempty actual physical action", + "seenResult": "Required nonempty actual observed result", + "rendererData": "Optional actual object; put receipts array INSIDE this object", + "screenshot": "Optional actual screenshot path", + "forbidden": "No top-level receipts or other keys. No fabricated historical or new renderer observations." + }, + "orientationCommands": { + "readOriginalAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings get system accelerometer_rotation", + "readOriginalRotation": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings get system user_rotation", + "disableAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings put system accelerometer_rotation 0", + "landscape": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings put system user_rotation 1", + "portrait": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings put system user_rotation 0", + "restoreOriginalRotation": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings put system user_rotation \"${ORIGINAL_USER_ROTATION:?Use actually observed validated0to3}\"", + "restoreOriginalAutoRotate": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained resize-orientation adb shell settings put system accelerometer_rotation \"${ORIGINAL_ACCELEROMETER_ROTATION:?Use actually observed validated0or1}\"" + }, + "orientationProtocol": "Read and retain original values before rotation; validate accelerometer_rotation is literal0or1 and user_rotation literal0..3 before using restoration templates. Do not substitute guessed values. Owned fresh private AVD only. If null/invalid values occur, stop for coordinator classification; no foreign settings changes. Record actual landscape and portrait renderer bounds, fresh BOTH-child reads in each orientation, restore observed originals before final fresh snapshot and Finish focus.", + "inputCommandTemplates": { + "maplibre-android-retained": { + "hierarchyDump": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell uiautomator dump /sdcard/one-map-attempt32-maplibre-android-retained-NNN.xml", + "hierarchyRead": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell cat /sdcard/one-map-attempt32-maplibre-android-retained-NNN.xml", + "tap": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell input tap \"${FRESH_X:?Set measured physicalX}\" \"${FRESH_Y:?Set measured physicalY}\"", + "swipe": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell input swipe \"${START_X:?Set measured physicalX}\" \"${START_Y:?Set measured physicalY}\" \"${END_X:?Set measured physicalX}\" \"${END_Y:?Set measured physicalY}\" 450", + "screenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb shell screencap -p /sdcard/one-map-attempt32-maplibre-android-retained-NNN.png", + "pullScreenshot": "python3 /private/tmp/one-map-android-restoration-review/scripts/android-operator.py /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32 maplibre-android-retained simultaneous-named-maps adb pull /sdcard/one-map-attempt32-maplibre-android-retained-NNN.png /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/maplibre-android-retained-NNN.png" + } + }, + "inputCommandProtocol": "Replace NNN with fresh monotonic capture names and select actual current scenario when using templates. Physical touch points come from fresh selected-package hierarchy/bitmap bounds. For projected source/map point, physicalX=(mapBoundsX+pointX)*actualScale; physicalY=(mapBoundsY+pointY)*actualScale, using actual logical layout bounds and sourcePoint from same current read; verify feature against bitmap and current bounds. No stale dimensions, hardcoded cross-engine point, direct callback or assumed scale.", + "coordinatorAudit": { + "status": "passed", + "nativeExecution": false, + "scope": "Pinned core31 completed row/status/observed/manualComplete/remaining/environment/UUID and before-after installed identity, retained-only row selection, exact live judge and first-failure cleanup", + "checks": [ + "Root source review and actual saved31 receipt verified", + "Root independently reran launcher and exact live-judge regressions", + "All preparation pins and695 frozen identities match; startupfree16.6GiB/output32absent", + "Coordinator added and executed fourth packet exact live-judge regression after finding it absent from test list" + ], + "authorization": "Owner Continue resumes the same approved unchanged MapLibre unit after worker quota interruption; camera/core reused, no new backend/build/calibration" + }, + "reusedCamera": { + "outcomePath": "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json", + "outcomeSha256": "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + "checkpointPath": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/checkpoint.json", + "checkpointSha256": "441e0a77035ce5f7157e550b63dc38c0d244802965164ec1bc74534836efcecf", + "row": "maplibre-android-camera", + "scope": "Immutable completed camera row and installed-byte identities before/after; not a completed core row." + }, + "failurePublication": { + "createInput": "Create a NEW output/SCENARIO-failure-observation.json with only action,seenResult and optional rendererData/screenshot. Preserve raw bad input. Describe the original failure; no synthetic passed output.", + "writerTemplate": "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/runtime-bin/node /private/tmp/one-map-android-restoration-review/scripts/record-native-ui-observation.mjs /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/ROW-manual.json SCENARIO failed /Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-32/SCENARIO-failure-observation.json", + "after": "Allow driver polling to observe failed scenario and perform cleanup. Await launcher exit and read checkpoint/receipt. If publication is impossible, report coordinator immediately and use only verified-ownership interruption fallback; no broad kills or retries." + }, + "reusedCoreRow": { + "rowId": "maplibre-android-core", + "status": "passed", + "runId": "654a874e-519e-46c0-91f1-1055acaa877b", + "sourceSha256": { + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/receipt.json": "500b1914deb2152bdfbf3ed52fa9490bb10ea80f4354ffc6ece18f956240a190", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-result.json": "ae647e0a42819166357ca697dccb1f3ee82dd9f79574577aa1ab228f4987ae9b", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-core-manual.json": "a11dab67a1f7b2c294fdf8b07e7409f708e6a9a5273d983a1761c4ba0f601097", + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-31/maplibre-android-retained-manual.json": "7adcfd6c7c05073988a2ce6cfcf36734a5238d5fffe923d7302bf2f217230b33" + }, + "outcomePath": "/private/tmp/one-map-android-restoration-review/records/evidence/revised-api-u26-android-maplibre-api36-attempt-31.json", + "outcomeSha256": "3317ec5e334434d33854b74a0bb6f51750e8565cb8259b48d96300f79b5390fc", + "proof": "Pinned receipt row status/observed/manualComplete/remaining[], APK/dist/environment/coreUUID and exact before+after installed-byte identities; all13core manual scenarios passed." + }, + "executionRecord": { + "status": "passed", + "outcome": "records/evidence/revised-api-u26-android-maplibre-api36-attempt-32.json", + "outcomeSha256": "886e73731e2ff3e206f60adce0f4cfa13fc5ed7a845e83c510b41d6a0e9d0a44", + "runId": "cfaeefdf-7430-4894-a54c-41fb9ab766eb", + "meaning": "Retained-only row32 passed all13renderer checks and six fresh physical scenarios, with camera30/core31 immutable reuse; executed source pins preserved unchanged.", + "next": "iOS Mapbox preparation only; no iOS execution authorized." + } +} diff --git a/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json b/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json new file mode 100644 index 0000000..e4ce446 --- /dev/null +++ b/records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json @@ -0,0 +1,26 @@ +{ + "action": "Requested each of Reject view draggable, Reject view callback, Reject annotation draggable, Reject annotation callback; verified exact rejection and recovered with matching helper, cleared and read normal scene each time.", + "seenResult": "All four matching recoveries reported rejection-verified; after every clear hierarchy showed No rejection requested and valid renderer. No drag callback. Final generation 2, load 4, feature 707, child 3, marker 1, annotation 1, source 2, popup-close 1, location 1, no error.", + "rendererData": { + "generation": 2, + "load": 4, + "feature": "707", + "child-click": 3, + "marker-click": 1, + "annotation-click": 1, + "source-click": 2, + "popup-close": 1, + "location": 1, + "center": [ + -122.33137856911692, + 47.61499999992865 + ], + "zoom": 11, + "receipts": [ + "toolbar-034.json", + "toolbar-038.json", + "toolbar-042.json", + "toolbar-046.json" + ] + } +} diff --git a/scripts/android-operator.py b/scripts/android-operator.py index 996c565..e30cb96 100644 --- a/scripts/android-operator.py +++ b/scripts/android-operator.py @@ -80,10 +80,10 @@ def main(arguments): raise ValueError("Unknown toolbar label for this row.") adb_arguments = [label] if operation == "dismiss-marker-rejection" and ( - row != "mapbox-android-core" or scenario != "marker-prop-rejection" + not row.endswith("-core") or scenario != "marker-prop-rejection" or len(adb_arguments) != 1 or adb_arguments[0] not in REJECTION_LABELS ): - raise ValueError("Expected the Mapbox core marker rejection case label.") + raise ValueError("Expected a selected Android core marker rejection case label.") candidate_report, identity = wait_for_row(attempt, row, latch) if identity.get("environment") != row.rsplit("-", 1)[0]: raise ValueError("Report environment differs from row.") @@ -255,7 +255,7 @@ def hierarchy(): remaining = None receipt["dismissals"] = [] for _ in range(2): - rectangle, count = marker_rejection_dismiss(xml, allow_notice=remaining == 2) + rectangle, count = marker_rejection_dismiss(xml, row, allow_notice=remaining == 2) if remaining is not None and count != remaining - 1: raise ValueError("Expected rejection log count to decrease by one.") remaining = count @@ -267,7 +267,7 @@ def hierarchy(): if count == 1: break toolbar_snapshot(xml, row) - require_rejection_result(xml, label) + require_rejection_result(xml, row, label) receipt["status"] = "rejection-verified" return previous = None @@ -316,13 +316,13 @@ def hierarchy(): print("TOOLBAR", json.dumps({**receipt, "receipt": str(receipt_path)}), flush=True) -def marker_rejection_dismiss(xml, allow_notice=False): +def marker_rejection_dismiss(xml, row, allow_notice=False): """Match a Marker rejection, or its following exact RN debugger notice.""" root = ET.fromstring(xml) nodes = list(root.iter("node")) - package = "com.onemapmapbox" + package = "com.onemap" + row.split("-", 1)[0] if not nodes or any(node.get("package") != package for node in nodes): - raise ValueError("Expected only the Mapbox application hierarchy.") + raise ValueError("Expected only the selected application hierarchy.") texts = [node.get("text") for node in nodes] if allow_notice and "Console Warning" in texts: # RN's Fusebox notice replaces warning bodies; it is not the hidden warning. @@ -362,11 +362,12 @@ def rectangle(node): return (left, top, right, bottom), count -def require_rejection_result(xml, label): +def require_rejection_result(xml, row, label): root = ET.fromstring(xml) + package = "com.onemap" + row.split("-", 1)[0] results = [node for node in root.iter("node") if node.get("resource-id") == "tf07-marker-rejection" - and node.get("package") == "com.onemapmapbox"] + and node.get("package") == package] if len(results) != 1 or results[0].get("text") != label + ": " + REJECTION_MESSAGE: raise ValueError("Expected exact fixture boundary rejection result.") diff --git a/scripts/android-operator.test.py b/scripts/android-operator.test.py index 09c9c8d..afc56ac 100644 --- a/scripts/android-operator.test.py +++ b/scripts/android-operator.test.py @@ -359,11 +359,33 @@ def test_expected_marker_overlays_dismiss_with_decreasing_count_then_check_bound def warning_xml(self): return Path("/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-26/toolbar-003-hierarchy-002.xml").read_text() - def test_actual_cli_saved_marker_then_migration_notice_recovers(self): - script = self.cli_copy() - saved = Path("/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-26/toolbar-003-hierarchy-001.xml").read_text() - (self.attempt / "snapshots.json").write_text(json.dumps([saved, self.warning_xml(), self.rejection_result_xml()])) - (self.attempt / "fake-adb").write_text(r"""#!/usr/bin/env python3 + def test_actual_cli_marker_and_notice_bind_to_selected_backend_and_result(self): + labels = ("Reject view draggable", "Reject view callback", + "Reject annotation draggable", "Reject annotation callback") + cases = [("mapbox", labels[0], None)] + [("maplibre", label, None) for label in labels] + cases += [("maplibre", labels[0], wrong) for wrong in ("overlay", "notice", "result")] + for backend, label, wrong in cases: + with self.subTest(backend=backend, label=label, wrong=wrong): + self.setUp() + row = backend + "-android-core" + self.original["environment"] = backend + "-android" + self.report.unlink() + self.report = self.attempt / (row + "-manual.json") + self.report.write_text(json.dumps(self.original)) + (self.attempt / "checkpoint.json").write_text(json.dumps({"currentRow": row})) + script = self.cli_copy() + saved = Path("/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-26/toolbar-003-hierarchy-001.xml").read_text() + snapshots = [saved, self.warning_xml(), self.rejection_result_xml(label)] + snapshots = [xml.replace("com.onemapmapbox", "com.onemap" + backend) for xml in snapshots] + if wrong is not None: + index = ("overlay", "notice", "result").index(wrong) + if wrong == "result": + # Keep the selected toolbar, but reject the other app's boundary result. + snapshots[index] = snapshots[index].replace('class="android.widget.TextView" package="com.onemapmaplibre"', 'class="android.widget.TextView" package="com.onemapmapbox"') + else: + snapshots[index] = snapshots[index].replace("com.onemapmaplibre", "com.onemapmapbox") + (self.attempt / "snapshots.json").write_text(json.dumps(snapshots)) + (self.attempt / "fake-adb").write_text(r"""#!/usr/bin/env python3 import json, pathlib, sys root = pathlib.Path(__file__).parent args = sys.argv[1:] @@ -375,16 +397,32 @@ def test_actual_cli_saved_marker_then_migration_notice_recovers(self): print(snapshots.pop(0)) path.write_text(json.dumps(snapshots)) """) - command = [sys.executable, str(script), str(self.attempt), ROW, "marker-prop-rejection", "dismiss-marker-rejection", "Reject view draggable"] - result = subprocess.run(command, capture_output=True, text=True, timeout=10) - self.assertEqual(result.returncode, 0, result.stdout + result.stderr) - calls = [json.loads(line) for line in (self.attempt / "calls.jsonl").read_text().splitlines()] - self.assertEqual([args for args in calls if args[2:4] == ["shell", "input"]], - [["-s", "emulator-5580", "shell", "input", "tap", "180", "2274"]] * 2) - self.assertEqual(json.loads((self.attempt / "snapshots.json").read_text()), []) - self.assertEqual(json.loads(self.report.read_text()), self.original) - self.assertEqual(json.loads((self.attempt / "toolbar-001.json").read_text())["status"], "rejection-verified") - self.assertFalse(self.latch.exists()) + command = [sys.executable, str(script), str(self.attempt), row, "marker-prop-rejection", "dismiss-marker-rejection", label] + result = subprocess.run(command, capture_output=True, text=True, timeout=10) + self.assertEqual(result.returncode, 0 if wrong is None else 1, result.stdout + result.stderr) + calls = [json.loads(line) for line in (self.attempt / "calls.jsonl").read_text().splitlines()] + taps = 2 if wrong is None else ("overlay", "notice", "result").index(wrong) + self.assertEqual([args for args in calls if args[2:4] == ["shell", "input"]], + [["-s", "emulator-5580", "shell", "input", "tap", "180", "2274"]] * taps) + report = json.loads(self.report.read_text()) + if wrong is None: + self.assertEqual(report, self.original) + else: + self.assertEqual(report["scenarios"]["marker-prop-rejection"], "failed") + self.assertEqual(report["metadata"], self.original["metadata"]) + receipt = json.loads((self.attempt / "toolbar-001.json").read_text()) + self.assertEqual(receipt["status"], "rejection-verified" if wrong is None else "failed") + if wrong is None: + self.assertEqual(json.loads((self.attempt / "snapshots.json").read_text()), []) + self.assertFalse(self.latch.exists()) + else: + saved_latch = self.latch.read_bytes() + saved_calls = (self.attempt / "calls.jsonl").read_bytes() + retry = subprocess.run(command, capture_output=True, text=True, timeout=10) + self.assertEqual(retry.returncode, 1) + self.assertIn("BLOCKED", retry.stdout) + self.assertEqual(self.latch.read_bytes(), saved_latch) + self.assertEqual((self.attempt / "calls.jsonl").read_bytes(), saved_calls) def test_migration_notice_rejects_unknown_content_identity_controls_and_order(self): xml = self.warning_xml() @@ -487,7 +525,7 @@ def test_marker_overlay_rejects_wrong_identity_controls_and_followup_without_inp self.assertEqual(len([args for args in calls if args[:2] == ["shell", "input"]]), 1) def test_marker_overlay_is_never_handled_for_another_scenario_or_row(self): - for prefix in ([ROW, SCENARIO], ["maplibre-android-core", "marker-prop-rejection"], [ROW, "marker-prop-rejection"]): + for prefix in ([ROW, SCENARIO], ["maplibre-android-retained", "marker-prop-rejection"], [ROW, "marker-prop-rejection"]): self.setUp() with patch("subprocess.run") as child: status, output = self.invoke(["dismiss-marker-rejection", "wrong" if prefix == [ROW, "marker-prop-rejection"] else "Reject view draggable"], prefix) diff --git a/scripts/android-rendering.mjs b/scripts/android-rendering.mjs index a06b14e..d256ca1 100644 --- a/scripts/android-rendering.mjs +++ b/scripts/android-rendering.mjs @@ -14,6 +14,7 @@ import { join, resolve } from "node:path"; import { promisify } from "node:util"; import { observeCamera } from "./android-camera-observer.mjs"; +import { loadMaplibreApi36Camera } from "./api36-reused-observations.mjs"; import { stopOwnedProcess } from "./native-smoke-process.mjs"; const recovery = "/Users/rob/code/mapbox-code/one-map-f05-android-recovery"; @@ -69,6 +70,9 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { "mapbox-acceptance", "mapbox-acceptance-api36", "mapbox-acceptance-api36-resume", + "maplibre-acceptance-api36", + "maplibre-acceptance-api36-resume", + "maplibre-acceptance-api36-retained-resume", ].includes(scene), "Unknown fixed scene." ); @@ -79,15 +83,27 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { const continuation = scene === "acceptance-continuation"; const signalDiagnostic = scene === "signal-diagnostic"; const api36Resume = scene === "mapbox-acceptance-api36-resume"; - const api36Unit = scene === "mapbox-acceptance-api36" || api36Resume; - const mapboxUnit = scene === "mapbox-acceptance" || api36Unit; + const maplibreRetained = + scene === "maplibre-acceptance-api36-retained-resume"; + const maplibreResume = scene === "maplibre-acceptance-api36-resume"; + const maplibreUnit = + scene === "maplibre-acceptance-api36" || maplibreResume || maplibreRetained; + const api36Unit = + scene === "mapbox-acceptance-api36" || api36Resume || maplibreUnit; + const mapboxUnit = + scene === "mapbox-acceptance" || (api36Unit && !maplibreUnit); + const selectedUnit = mapboxUnit || maplibreUnit; + assert( + !maplibreUnit || engine === "maplibre", + "Selected scene targets MapLibre only." + ); const avdName = api36Unit ? "OneMapF05MapboxApi36" : "OneMapU25F05"; assert( !(signalDiagnostic || mapboxUnit) || engine === "mapbox", "Selected scene targets Mapbox only." ); const batch = - scene === "acceptance" || continuation || signalDiagnostic || mapboxUnit; + scene === "acceptance" || continuation || signalDiagnostic || selectedUnit; const camera = scene === "camera" || batch; const ports = batch ? [5580, 5581, 8081, 8797] @@ -109,12 +125,16 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { apkSha256, cleanup: [], checkpoints: [], - ...(mapboxUnit && { - mode: "mapbox-android-unit", + ...(selectedUnit && { + mode: `${engine}-android-unit`, scope: [ - ...(api36Unit && !api36Resume ? ["mapbox-android-camera"] : []), - ...(!api36Resume ? ["mapbox-android-core"] : []), - "mapbox-android-retained", + ...(api36Unit && !api36Resume && !maplibreResume && !maplibreRetained + ? [`${engine}-android-camera`] + : []), + ...(!api36Resume && !maplibreRetained + ? [`${engine}-android-core`] + : []), + `${engine}-android-retained`, ], signalCalibration: "omitted; unsupported event and unresolved application SIGKILL", @@ -189,7 +209,7 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { }; const verifyInputs = (preparation, freeze) => { assert.equal(sha256(apk), apkSha256, "Verified retained APK changed."); - if (batch && !mapboxUnit) + if (batch && !selectedUnit) for (const [selected, target] of Object.entries(targets)) assert.equal( sha256( @@ -390,31 +410,54 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { } const peerEvidence = join( root, - api36Resume - ? "records/evidence/revised-api-u26-mapbox-android-api36-retained-preparation.json" - : api36Unit - ? "records/evidence/revised-api-u26-mapbox-android-api36-preparation.json" - : mapboxUnit - ? "records/evidence/revised-api-u26-mapbox-android-unit-preparation.json" - : signalDiagnostic - ? "records/evidence/revised-api-u26-signal-liveness-preparation.json" - : continuation - ? "records/evidence/revised-api-u26-android-kernel-console-preparation.json" - : batch - ? "records/evidence/revised-api-u26-platform-batches-preparation.json" - : `records/evidence/revised-api-u25-f05-${engine}-android-${scene}-preparation.json` + maplibreRetained + ? "records/evidence/revised-api-u26-maplibre-android-api36-retained-preparation.json" + : maplibreResume + ? "records/evidence/revised-api-u26-maplibre-android-api36-resume-preparation.json" + : maplibreUnit + ? "records/evidence/revised-api-u26-maplibre-android-api36-preparation.json" + : api36Resume + ? "records/evidence/revised-api-u26-mapbox-android-api36-retained-preparation.json" + : api36Unit + ? "records/evidence/revised-api-u26-mapbox-android-api36-preparation.json" + : mapboxUnit + ? "records/evidence/revised-api-u26-mapbox-android-unit-preparation.json" + : signalDiagnostic + ? "records/evidence/revised-api-u26-signal-liveness-preparation.json" + : continuation + ? "records/evidence/revised-api-u26-android-kernel-console-preparation.json" + : batch + ? "records/evidence/revised-api-u26-platform-batches-preparation.json" + : `records/evidence/revised-api-u25-f05-${engine}-android-${scene}-preparation.json` ); const preparation = JSON.parse(readFileSync(peerEvidence)); const freeze = JSON.parse(readFileSync(preparation.freeze.path)); verifyInputs(preparation, freeze); - if (api36Resume) { - assert.deepEqual(preparation.executionRows, ["mapbox-android-retained"]); + if (maplibreResume || maplibreRetained) { + const prior = loadMaplibreApi36Camera({ + installedBinarySha256: apkSha256, + libraryDistSha256: distSha256, + environment: "maplibre-android", + }); + receipt.reusedRows = [prior.row]; + receipt.priorOutcome = { + path: prior.outcomePath, + sha256: prior.outcomeSha256, + }; + } + if (api36Resume || maplibreRetained) { + assert.deepEqual(preparation.executionRows, [ + `${engine}-android-retained`, + ]); const path = join( recovery, - "android-platform-batch-attempt-27/receipt.json" + maplibreRetained + ? "android-platform-batch-attempt-31/receipt.json" + : "android-platform-batch-attempt-27/receipt.json" ); - const hash = - "43d2dd7e7f3de701d96e99f12cca9b45824c02e58c1af6590acffe07659b51db"; + const hash = maplibreRetained + ? "500b1914deb2152bdfbf3ed52fa9490bb10ea80f4354ffc6ece18f956240a190" + : "43d2dd7e7f3de701d96e99f12cca9b45824c02e58c1af6590acffe07659b51db"; assert.equal(sha256(path), hash, "Accepted API36 core receipt changed."); const prior = JSON.parse(readFileSync(path)); assert.equal(prior.apkSha256, apkSha256); @@ -422,7 +465,7 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { assert.equal(prior.frozenFiles, 695); assert.deepEqual( prior.rows.map(({ rowId, status }) => ({ rowId, status })), - [{ rowId: "mapbox-android-core", status: "passed" }] + [{ rowId: `${engine}-android-core`, status: "passed" }] ); const core = prior.rows[0].scene; assert.equal(core.status, "passed"); @@ -431,10 +474,10 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { assert.deepEqual(core.remaining, []); assert.equal(core.installedBinarySha256, apkSha256); assert.equal(core.libraryDistSha256, distSha256); - assert.equal(core.environment, "mapbox-android"); + assert.equal(core.environment, `${engine}-android`); for (const phase of [ - "mapbox-android-core-before", - "mapbox-android-core-after", + `${engine}-android-core-before`, + `${engine}-android-core-after`, ]) { const reads = prior.identityReads.filter( (read) => read.phase === phase @@ -442,6 +485,8 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { assert.equal(reads.length, 1); assert.equal(reads[0].sha256, apkSha256); } + if (maplibreRetained) + assert.equal(core.runId, "654a874e-519e-46c0-91f1-1055acaa877b"); receipt.reusedRows.push(prior.rows[0]); receipt.api36CoreReceipt = { path, sha256: hash }; } @@ -451,17 +496,17 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { const imageNeeded = api36Unit && !existsSync(join(recovery, "android-api36-image")); assert( - !api36Resume || !imageNeeded, + !(api36Resume || maplibreUnit) || !imageNeeded, "Resume requires the retained verified API36 image; no download is authorized." ); const requiredBytes = - (mapboxUnit ? 12 * 1024 ** 3 : 8804682957) + + (selectedUnit ? 12 * 1024 ** 3 : 8804682957) + (imageNeeded ? 4575096761 : 0); assert( receipt.freeBytes >= requiredBytes, api36Unit ? `API36 setup and batch require ${requiredBytes} free bytes; stop before staging.` - : `Android preboot requires ${mapboxUnit ? "12" : "8.2"} GiB free; stop without deleting files.` + : `Android preboot requires ${selectedUnit ? "12" : "8.2"} GiB free; stop without deleting files.` ); if (!camera) createRequire(join(pngRoot, "package.json"))("pngjs"); for (const port of ports) await requireFreePort(port, execute); @@ -557,7 +602,7 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { reverses.push(port); } receipt.rows = batch ? [] : undefined; - for (const selectedEngine of batch && !signalDiagnostic && !mapboxUnit + for (const selectedEngine of batch && !signalDiagnostic && !selectedUnit ? ["mapbox", "maplibre"] : [engine]) { engine = selectedEngine; @@ -626,9 +671,11 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { "android.permission.ACCESS_LOCAL_NETWORK", ]); for (const row of api36Unit - ? api36Resume + ? api36Resume || maplibreRetained ? ["retained"] - : ["camera", "core", "retained"] + : maplibreResume + ? ["core", "retained"] + : ["camera", "core", "retained"] : mapboxUnit ? ["core", "retained"] : signalDiagnostic @@ -668,12 +715,14 @@ export const run = async (output, engine = "mapbox", scene = "rendering") => { TF07_BORROWED_METRO_REVERSE: "1", TF07_PARENT_PROCESS_GROUP: "1", TF07_MANUAL_REPORT: join(output, `${rowId}-manual.json`), + TF07_REUSE_MAPLIBRE_API36_ATTEMPT30: + maplibreResume && row === "core" ? "1" : "", TF07_REUSE_API36_ATTEMPT24: api36Resume && row === "core" ? "1" : "", TF07_OUTPUT: join(output, `${rowId}-result.json`), TF07_NATIVE_TIMEOUT_MS: signalDiagnostic ? "900000" : "1800000", ...(signalDiagnostic && { TF07_ANDROID_SIGNAL_OUTPUT: output }), - ...(mapboxUnit && { TF07_ANDROID_SIGNAL_OUTPUT: "" }), + ...(selectedUnit && { TF07_ANDROID_SIGNAL_OUTPUT: "" }), TF07_ANDROID_DIAGNOSTICS: join( output, `${rowId}-diagnostics.json` diff --git a/scripts/api36-retained-observation.test.mjs b/scripts/api36-retained-observation.test.mjs index bcd06cc..66b74fc 100644 --- a/scripts/api36-retained-observation.test.mjs +++ b/scripts/api36-retained-observation.test.mjs @@ -48,47 +48,84 @@ console.log( ); // Run the exact packet command against the operator stdout envelope, without Android. -const packet = JSON.parse( - readFileSync( - new URL( - "../records/evidence/revised-api-u26-mapbox-android-api36-retained-preparation.json", - import.meta.url - ) - ) -); -const temporary = mkdtempSync(join(tmpdir(), "retained-live-judge-")); -try { - const statusPath = join(temporary, "status.txt"); - const manualPath = join(temporary, "manual.json"); - writeFileSync(manualPath, JSON.stringify(manual)); - const command = packet.liveJudgeCommand - .replace(`${packet.output}/retained-status.txt`, statusPath) - .replace( - `${packet.output}/mapbox-android-retained-manual.json`, - manualPath +for (const [engine, packetName] of [ + ["mapbox", "revised-api-u26-mapbox-android-api36-retained-preparation.json"], + ["maplibre", "revised-api-u26-maplibre-android-api36-preparation.json"], + [ + "maplibre", + "revised-api-u26-maplibre-android-api36-resume-preparation.json", + ], + [ + "maplibre", + "revised-api-u26-maplibre-android-api36-retained-preparation.json", + ], +]) { + const packet = JSON.parse( + readFileSync(new URL(`../records/evidence/${packetName}`, import.meta.url)) + ); + const temporary = mkdtempSync(join(tmpdir(), "retained-live-judge-")); + try { + const statusPath = join(temporary, "status.txt"); + const manualPath = join(temporary, "manual.json"); + const selectedIdentity = { + ...saved, + installedBinarySha256: packet.verifiedBinaries.android[engine].sha256, + environment: `${engine}-android`, + }; + const selectedManual = { + ...manual, + installedBinarySha256: selectedIdentity.installedBinarySha256, + environment: selectedIdentity.environment, + }; + writeFileSync(manualPath, JSON.stringify(selectedManual)); + const command = packet.liveJudgeCommand + .replace(`${packet.output}/retained-status.txt`, statusPath) + .replace( + `${packet.output}/${engine}-android-retained-manual.json`, + manualPath + ); + const invoke = (body, ending = "COMPLETE 0") => { + writeFileSync( + statusPath, + `WAIT row readiness ${engine}-android-retained\nSTART status http://127.0.0.1:8797/tf07\n${JSON.stringify(body)}\n${ending}\n` + ); + return spawnSync("/bin/sh", ["-c", command], { encoding: "utf8" }); + }; + const live = invoke(saved.observation); + assert.equal(live.status, 0, live.stderr); + assert.deepEqual( + JSON.parse(live.stdout), + judgeNativeRetained(saved.observation, selectedManual, selectedIdentity) + ); + const beforeFinish = structuredClone(refreshed); + delete beforeFinish.observations.at(-1).events["read-error"]; + beforeFinish.focusedComplete = false; + const pendingFinish = invoke(beforeFinish); + assert.equal(pendingFinish.status, 0, pendingFinish.stderr); + const pendingResult = JSON.parse(pendingFinish.stdout); + assert.equal(pendingResult.manualComplete, true); + assert.equal(pendingResult.checks.focusedComplete, false); + assert( + Object.entries(pendingResult.checks).every( + ([name, passed]) => name === "focusedComplete" || passed + ) ); - const invoke = (body, ending = "COMPLETE 0") => { + assert.notEqual(invoke(null).status, 0); + assert.notEqual(invoke(saved.observation, "FAILED status").status, 0); writeFileSync( - statusPath, - `WAIT row readiness mapbox-android-retained\nSTART status http://127.0.0.1:8797/tf07\n${JSON.stringify(body)}\n${ending}\n` + manualPath, + JSON.stringify({ + ...selectedManual, + installedBinarySha256: "a".repeat(64), + }) ); - return spawnSync("/bin/sh", ["-c", command], { encoding: "utf8" }); - }; - const live = invoke(saved.observation); - assert.equal(live.status, 0, live.stderr); - assert.deepEqual(JSON.parse(live.stdout), result); - assert.notEqual(invoke(null).status, 0); - assert.notEqual(invoke(saved.observation, "FAILED status").status, 0); - writeFileSync( - manualPath, - JSON.stringify({ ...manual, installedBinarySha256: "a".repeat(64) }) - ); - const tampered = invoke(saved.observation); - assert.equal(tampered.status, 0, tampered.stderr); - assert.equal(JSON.parse(tampered.stdout).manualComplete, false); -} finally { - rmSync(temporary, { recursive: true, force: true }); + const tampered = invoke(saved.observation); + assert.equal(tampered.status, 0, tampered.stderr); + assert.equal(JSON.parse(tampered.stdout).manualComplete, false); + } finally { + rmSync(temporary, { recursive: true, force: true }); + } } console.log( - "Exact live judge parses operator START/JSON/COMPLETE output and rejects null, failure and identity mismatch." + "Both exact packet live judges parses operator START/JSON/COMPLETE output and rejects null, failure and identity mismatch." ); diff --git a/scripts/api36-reused-observations.mjs b/scripts/api36-reused-observations.mjs index 0efced7..a9b4811 100644 --- a/scripts/api36-reused-observations.mjs +++ b/scripts/api36-reused-observations.mjs @@ -121,6 +121,105 @@ export const loadApi36ReusedObservations = (identity, read = readFileSync) => { ); }; +/** Validates the immutable MapLibre camera pass without re-running its scene. */ +export const loadMaplibreApi36Camera = (identity, read = readFileSync) => { + const outcomePath = resolve( + import.meta.dirname, + "../records/evidence/revised-api-u26-android-maplibre-api36-attempt-30.json" + ); + const outcome = readPinned( + outcomePath, + "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + read + ); + assert.equal(outcome.result, "stopped-at-observation-writer-schema-error"); + assert.equal( + outcome.candidateSha256, + "33828324898408485cd9211cc780f098d1564d90426887ff9fb4b64733913276" + ); + assert.equal(outcome.inputApkSha256, identity.installedBinarySha256); + assert.equal(outcome.distSha256, identity.libraryDistSha256); + assert.equal(identity.environment, "maplibre-android"); + assert.equal(outcome.environment, "api36-google-apis-revision7-arm64-4k"); + const checkpointPath = + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/checkpoint.json"; + const prior = readPinned( + checkpointPath, + "441e0a77035ce5f7157e550b63dc38c0d244802965164ec1bc74534836efcecf", + read + ); + assert.equal(prior.apkSha256, identity.installedBinarySha256); + assert.equal(prior.environment, outcome.environment); + assert.deepEqual(prior.rows, outcome.completedRows); + assert.deepEqual( + prior.rows.map(({ rowId, status }) => ({ rowId, status })), + [{ rowId: "maplibre-android-camera", status: "passed" }] + ); + for (const phase of [ + "maplibre-android-camera-before", + "maplibre-android-camera-after", + ]) { + const reads = prior.identityReads.filter((entry) => entry.phase === phase); + assert.equal(reads.length, 1); + assert.equal(reads[0].sha256, identity.installedBinarySha256); + } + return { + row: prior.rows[0], + outcomePath, + outcomeSha256: + "0fc374a6b7037883c71d6446240d4db1fbb482ac39f59c349a1fafa7a5ec8db6", + }; +}; + +/** Reuses only the twelve recorded physical observations, never old event counters. */ +export const loadMaplibreApi36ReusedObservations = ( + identity, + read = readFileSync +) => { + const camera = loadMaplibreApi36Camera(identity, read); + const reportPath = + "/Users/rob/code/mapbox-code/one-map-f05-android-recovery/android-platform-batch-attempt-30/maplibre-android-core-manual.json"; + const reportSha256 = + "0b3c5b46c960edc3fa129996bbc794d104c211f1230134af57248d1b263915d1"; + const prior = readPinned(reportPath, reportSha256, read); + for (const field of [ + "installedBinarySha256", + "libraryDistSha256", + "environment", + ]) + assert.equal(prior[field], identity[field], `Reused ${field} differs.`); + assert.equal(prior.runId, "8ca84053-4355-45bc-8d81-0b213cd34adb"); + assert.notEqual( + prior.runId, + identity.runId, + "Resume requires a fresh run identity." + ); + assert.equal(prior.scenarios["marker-prop-rejection"], "unverified"); + return Object.fromEntries( + api36ReusedScenarios.map((scenario) => { + assert.equal(prior.scenarios[scenario], "passed"); + assert( + prior.observations[scenario]?.action && + prior.observations[scenario]?.seenResult + ); + return [ + scenario, + { + source: { + reportPath, + reportSha256, + outcomePath: camera.outcomePath, + outcomeSha256: camera.outcomeSha256, + runId: prior.runId, + environment: "api36-google-apis-revision7-arm64-4k", + }, + observation: prior.observations[scenario], + }, + ]; + }) + ); +}; + const readPinned = (path, hash, read) => { const bytes = read(path); assert.equal( diff --git a/scripts/api36-reused-observations.test.mjs b/scripts/api36-reused-observations.test.mjs index 4307086..ec59a43 100644 --- a/scripts/api36-reused-observations.test.mjs +++ b/scripts/api36-reused-observations.test.mjs @@ -4,6 +4,8 @@ import { readFileSync } from "node:fs"; import { api36ReusedScenarios, loadApi36ReusedObservations, + loadMaplibreApi36Camera, + loadMaplibreApi36ReusedObservations, } from "./api36-reused-observations.mjs"; import { judgeNativeUi, nativeUiScenarios } from "./tf07-smoke-contract.mjs"; @@ -168,3 +170,50 @@ assert.equal( ).status, "unverified" ); + +const maplibreIdentity = { + ...identity, + installedBinarySha256: + "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131", + environment: "maplibre-android", +}; +const maplibreReused = loadMaplibreApi36ReusedObservations(maplibreIdentity); +assert.deepEqual(Object.keys(maplibreReused), api36ReusedScenarios); +assert(!Object.hasOwn(maplibreReused, "marker-prop-rejection")); +assert.equal( + loadMaplibreApi36Camera(maplibreIdentity).row.rowId, + "maplibre-android-camera" +); +for (const field of [ + "installedBinarySha256", + "libraryDistSha256", + "environment", + "runId", +]) + assert.throws(() => + loadMaplibreApi36ReusedObservations({ + ...maplibreIdentity, + [field]: + field === "runId" ? "8ca84053-4355-45bc-8d81-0b213cd34adb" : "wrong", + }) + ); +for (const suffix of ["checkpoint.json", "core-manual.json", "attempt-30.json"]) + assert.throws( + () => + loadMaplibreApi36ReusedObservations(maplibreIdentity, (path) => + path.endsWith(suffix) ? Buffer.from("changed") : readFileSync(path) + ), + /evidence changed/ + ); +assert.equal( + judgeNativeUi( + fresh, + { ...manual, ...maplibreIdentity }, + maplibreIdentity, + Object.keys(maplibreReused) + ).status, + "passed" +); +console.log( + "MapLibre30 camera and twelve physical receipts are pinned; fresh renderer and marker cases remain required." +); diff --git a/scripts/fixtures/api36-maplibre-attempt30-rejected-input.json b/scripts/fixtures/api36-maplibre-attempt30-rejected-input.json new file mode 100644 index 0000000..a39aa4a --- /dev/null +++ b/scripts/fixtures/api36-maplibre-attempt30-rejected-input.json @@ -0,0 +1 @@ +{"action": "Requested each of Reject view draggable, Reject view callback, Reject annotation draggable, Reject annotation callback; verified exact rejection and recovered with matching helper, cleared and read normal scene each time.", "seenResult": "All four matching recoveries reported rejection-verified; after every clear hierarchy showed No rejection requested and valid renderer. No drag callback. Final generation 2, load 4, feature 707, child 3, marker 1, annotation 1, source 2, popup-close 1, location 1, no error.", "rendererData": {"generation": 2, "load": 4, "feature": "707", "child-click": 3, "marker-click": 1, "annotation-click": 1, "source-click": 2, "popup-close": 1, "location": 1, "center": [-122.33137856911692, 47.61499999992865], "zoom": 11}, "receipts": ["toolbar-034.json", "toolbar-038.json", "toolbar-042.json", "toolbar-046.json"]} \ No newline at end of file diff --git a/scripts/mapbox-android-rendering.test.mjs b/scripts/mapbox-android-rendering.test.mjs index 065cfcb..5d934b8 100644 --- a/scripts/mapbox-android-rendering.test.mjs +++ b/scripts/mapbox-android-rendering.test.mjs @@ -38,6 +38,8 @@ for (const [ mapboxUnit = false, api36Unit = false, api36Resume = false, + maplibreResume = false, + maplibreRetained = false, ] of [ ["mapbox", false], ["maplibre", false], @@ -47,6 +49,9 @@ for (const [ ["mapbox", true, true, false, true], ["mapbox", true, true, false, false, true], ["mapbox", true, true, false, false, true, true], + ["maplibre", true, true, false, false, true, true], + ["maplibre", true, true, false, false, true, true, false, true], + ["maplibre", true, true, false, false, true, true, true, false, true], ["mapbox", true, true, false, false, true, true, true], ]) { const avdName = api36Unit ? "OneMapF05MapboxApi36" : "OneMapU25F05"; @@ -58,7 +63,9 @@ for (const [ null, ...(engine === "mapbox" ? ["missing-token", "whitespace-token"] : []), "existing-output", - ...(continuation || mapboxUnit ? ["prior-hash", "prior-prefix"] : []), + ...(continuation || (mapboxUnit && engine === "mapbox") + ? ["prior-hash", "prior-prefix"] + : []), ...(mapboxUnit ? ["retained-driver"] : []), ...(api36Resume ? [ @@ -67,6 +74,9 @@ for (const [ "core-proof-identity", "core-proof-after", "core-proof-scope", + "core-proof-observed", + "core-proof-manual", + "core-proof-remaining", ] : []), ...(api36Unit @@ -150,6 +160,9 @@ for (const [ "core-proof-identity", "core-proof-after", "core-proof-scope", + "core-proof-observed", + "core-proof-manual", + "core-proof-remaining", ] : []), ...(api36Unit @@ -388,13 +401,16 @@ for (const [ log: (message) => { if (String(message).startsWith("API36 ")) { const row = String(message).split(" ")[1]; - assert.equal(latestCheckpoint.currentRow, `mapbox-android-${row}`); - if (!api36Resume) + assert.equal( + latestCheckpoint.currentRow, + `${engine}-android-${row}` + ); + if (!api36Resume && !maplibreResume) assert.equal( latestCheckpoint.rows.at(-1).rowId, - row === "core" ? "mapbox-android-camera" : "mapbox-android-core" + `${engine}-android-${row === "core" ? "camera" : "core"}` ); - if (!api36Resume) + if (!api36Resume && !maplibreResume) assert.equal(latestCheckpoint.rows.at(-1).status, "passed"); phaseMessages.push(message); } @@ -402,6 +418,11 @@ for (const [ error: () => {}, }, assert, + loadMaplibreApi36Camera: () => ({ + row: { rowId: "maplibre-android-camera", status: "passed" }, + outcomePath: "/prior", + outcomeSha256: "prior-hash", + }), observeCamera: batch ? async () => { cameraRows++; @@ -422,7 +443,7 @@ for (const [ ? "" : failAt === "whitespace-token" ? " " - : engine === "mapbox" + : engine === "mapbox" || mapboxUnit ? "redacted-test-token" : "", }, @@ -439,7 +460,8 @@ for (const [ existsSync: (file) => file.endsWith("scene.json") ? launched - : api36Resume && file.endsWith("android-api36-image") + : (api36Resume || (api36Unit && engine === "maplibre")) && + file.endsWith("android-api36-image") ? failAt !== "image-capacity" : failAt === "avd", statfsSync: () => ({ @@ -473,6 +495,9 @@ for (const [ file.endsWith("signal-liveness-preparation.json") || file.endsWith("mapbox-android-unit-preparation.json") || file.endsWith("mapbox-android-api36-preparation.json") || + file.endsWith("maplibre-android-api36-preparation.json") || + file.endsWith("maplibre-android-api36-resume-preparation.json") || + file.endsWith("maplibre-android-api36-retained-preparation.json") || file.endsWith("mapbox-android-api36-retained-preparation.json") || file.endsWith("mapbox-android-api36-console-resume-preparation.json") ) @@ -483,10 +508,13 @@ for (const [ freeze: { path: "/freeze", sha256: "freeze-hash" }, executionRows: failAt === "core-proof-scope" - ? ["mapbox-android-core"] - : ["mapbox-android-retained"], + ? [`${engine}-android-core`] + : [`${engine}-android-retained`], }); - if (file.endsWith("android-platform-batch-attempt-27/receipt.json")) + if ( + file.endsWith("android-platform-batch-attempt-27/receipt.json") || + file.endsWith("android-platform-batch-attempt-31/receipt.json") + ) return JSON.stringify({ result: "failed", apkSha256: apkHash, @@ -496,24 +524,26 @@ for (const [ { rowId: failAt === "core-proof-row" - ? "mapbox-android-retained" - : "mapbox-android-core", + ? `${engine}-android-retained` + : `${engine}-android-core`, status: "passed", scene: { status: "passed", - observed: true, - manualComplete: true, - remaining: [], + runId: "654a874e-519e-46c0-91f1-1055acaa877b", + observed: failAt !== "core-proof-observed", + manualComplete: failAt !== "core-proof-manual", + remaining: + failAt === "core-proof-remaining" ? ["unverified"] : [], installedBinarySha256: failAt === "core-proof-identity" ? "wrong" : apkHash, libraryDistSha256: distHash, - environment: "mapbox-android", + environment: `${engine}-android`, }, }, ], identityReads: [ - "mapbox-android-core-before", - "mapbox-android-core-after", + `${engine}-android-core-before`, + `${engine}-android-core-after`, ].map((phase) => ({ phase, sha256: @@ -636,6 +666,10 @@ for (const [ if (args.some((arg) => arg.endsWith("tf07-ui-smoke.mjs"))) { coreRows++; assert.equal(options.env.TF07_REUSE_API36_ATTEMPT24 === "1", false); + assert.equal( + options.env.TF07_REUSE_MAPLIBRE_API36_ATTEMPT30 === "1", + maplibreResume && coreRows === 1 + ); if (api36Unit) assert.equal( phaseMessages.at(-1), @@ -732,7 +766,9 @@ for (const [ String(content).startsWith('{"result":"failed","apkSha256"') ? failAt === "core-proof-hash" ? "wrong" - : "43d2dd7e7f3de701d96e99f12cca9b45824c02e58c1af6590acffe07659b51db" + : maplibreRetained + ? "500b1914deb2152bdfbf3ed52fa9490bb10ea80f4354ffc6ece18f956240a190" + : "43d2dd7e7f3de701d96e99f12cca9b45824c02e58c1af6590acffe07659b51db" : String(content).startsWith( '{"result":"stopped-at-popup-attachment-observation"' ) @@ -749,7 +785,7 @@ for (const [ }; }; await runInNewContext( - `${source}\nrun("/attempt", "${engine}", "${api36Resume ? "mapbox-acceptance-api36-resume" : api36Unit ? "mapbox-acceptance-api36" : mapboxUnit ? "mapbox-acceptance" : signalDiagnostic ? "signal-diagnostic" : continuation ? "acceptance-continuation" : batch ? "acceptance" : camera ? "camera" : "rendering"}")`, + `${source}\nrun("/attempt", "${engine}", "${maplibreRetained ? "maplibre-acceptance-api36-retained-resume" : maplibreResume ? "maplibre-acceptance-api36-resume" : engine === "maplibre" && api36Unit ? "maplibre-acceptance-api36" : api36Resume ? "mapbox-acceptance-api36-resume" : api36Unit ? "mapbox-acceptance-api36" : mapboxUnit ? "mapbox-acceptance" : signalDiagnostic ? "signal-diagnostic" : continuation ? "acceptance-continuation" : batch ? "acceptance" : camera ? "camera" : "rendering"}")`, context ).catch((error) => { assert.equal(failAt, "existing-output"); @@ -775,10 +811,10 @@ for (const [ continue; } if (api36Resume && failAt === null) { - assert.deepEqual(receipt.scope, ["mapbox-android-retained"]); + assert.deepEqual(receipt.scope, [`${engine}-android-retained`]); assert.deepEqual( receipt.reusedRows.map(({ rowId }) => rowId), - ["mapbox-android-camera", "mapbox-android-core"] + [`${engine}-android-camera`, `${engine}-android-core`] ); assert.equal(coreRows, 1, "Exactly one retained driver, no core driver."); } @@ -955,14 +991,14 @@ for (const [ ); if (!signalDiagnostic && !api36Resume) assert( - late[0].endsWith("mapbox-android-core-driver-stderr.log"), + late[0].endsWith(`${engine}-android-core-driver-stderr.log`), late[0] ); assert.equal( receipt.rows.length, api36Resume ? 1 - : api36Unit && !api36Resume + : api36Unit && !api36Resume && !maplibreResume ? 3 : mapboxUnit ? 2 @@ -974,7 +1010,7 @@ for (const [ ); assert.equal( cameraRows, - api36Unit && !api36Resume + api36Unit && !api36Resume && !maplibreResume ? 1 : signalDiagnostic || mapboxUnit ? 0 @@ -984,8 +1020,8 @@ for (const [ ); assert.deepEqual( cameraEngines, - api36Unit && !api36Resume - ? ["mapbox"] + api36Unit && !api36Resume && !maplibreResume + ? [engine] : signalDiagnostic || mapboxUnit ? [] : continuation @@ -995,15 +1031,15 @@ for (const [ assert.deepEqual( receipt.rows.map(({ rowId }) => rowId), api36Resume - ? ["mapbox-android-retained"] - : api36Unit && !api36Resume + ? [`${engine}-android-retained`] + : api36Unit && !api36Resume && !maplibreResume ? [ - "mapbox-android-camera", - "mapbox-android-core", - "mapbox-android-retained", + `${engine}-android-camera`, + `${engine}-android-core`, + `${engine}-android-retained`, ] : mapboxUnit - ? ["mapbox-android-core", "mapbox-android-retained"] + ? [`${engine}-android-core`, `${engine}-android-retained`] : signalDiagnostic ? ["mapbox-android-core"] : [ @@ -1024,12 +1060,14 @@ for (const [ api36Resume ? 1 : mapboxUnit ? 2 : signalDiagnostic ? 1 : 4 ); if (mapboxUnit) { - assert.equal(receipt.mode, "mapbox-android-unit"); + assert.equal(receipt.mode, `${engine}-android-unit`); assert.equal(receipt.rows.at(-1).scene.density, 2.625); assert( !commands.some((call) => call.some((arg) => - /gradlew|maplibre|signal-calibration/.test(String(arg)) + new RegExp( + `gradlew|native-${engine === "mapbox" ? "maplibre" : "mapbox"}|signal-calibration` + ).test(String(arg)) ) ) ); @@ -1051,7 +1089,7 @@ for (const [ identityChecks, api36Resume ? 3 - : api36Unit && !api36Resume + : api36Unit && !api36Resume && !maplibreResume ? 7 : mapboxUnit ? 5 @@ -1069,7 +1107,7 @@ for (const [ if (["driver", "driver-stderr"].includes(failAt)) { assert.equal( receipt.rows.length, - api36Unit && !api36Resume + api36Unit && !api36Resume && !maplibreResume ? 1 : signalDiagnostic || continuation || mapboxUnit ? 0 @@ -1082,9 +1120,9 @@ for (const [ receipt.rows.map(({ rowId }) => rowId), api36Resume ? [] - : api36Unit && !api36Resume - ? ["mapbox-android-camera", "mapbox-android-core"] - : ["mapbox-android-core"] + : api36Unit && !api36Resume && !maplibreResume + ? [`${engine}-android-camera`, `${engine}-android-core`] + : [`${engine}-android-core`] ); assert.equal(coreRows, api36Resume ? 1 : 2); assert.match(receipt.error, /driver failed/); @@ -1163,6 +1201,33 @@ for (const unit of ["mapbox-acceptance", "mapbox-acceptance-api36"]) }), /targets Mapbox only/ ); +await assert.rejects( + runInNewContext( + `${source}\nrun('/attempt', 'mapbox', 'maplibre-acceptance-api36')`, + { + assert, + join, + mkdirSync: () => { + throw Error("Wrong backend acquired resources."); + }, + } + ), + /targets MapLibre only/ +); +const maplibreApi36Entrypoint = readFileSync( + new URL("./maplibre-android-api36-acceptance.mjs", import.meta.url), + "utf8" +) + .replace(/^import[^\n]+;\n/m, "") + .replace("await run", "run"); +await runInNewContext(maplibreApi36Entrypoint, { + process: { argv: ["node", "entrypoint", "/entrypoint"] }, + run: (output, engine, scene) => { + assert.equal(output, "/entrypoint"); + assert.equal(engine, "maplibre"); + assert.equal(scene, "maplibre-acceptance-api36"); + }, +}); console.log( "Both Android rendering branches and camera orchestration/entrypoint mocks passed." ); diff --git a/scripts/maplibre-android-api36-acceptance.mjs b/scripts/maplibre-android-api36-acceptance.mjs new file mode 100644 index 0000000..19e720e --- /dev/null +++ b/scripts/maplibre-android-api36-acceptance.mjs @@ -0,0 +1,3 @@ +import { run } from "./android-rendering.mjs"; + +await run(process.argv[2], "maplibre", "maplibre-acceptance-api36"); diff --git a/scripts/maplibre-android-api36-resume.mjs b/scripts/maplibre-android-api36-resume.mjs new file mode 100644 index 0000000..7611d30 --- /dev/null +++ b/scripts/maplibre-android-api36-resume.mjs @@ -0,0 +1,3 @@ +import { run } from "./android-rendering.mjs"; + +await run(process.argv[2], "maplibre", "maplibre-acceptance-api36-resume"); diff --git a/scripts/maplibre-android-api36-retained-resume.mjs b/scripts/maplibre-android-api36-retained-resume.mjs new file mode 100644 index 0000000..1bcc0f6 --- /dev/null +++ b/scripts/maplibre-android-api36-retained-resume.mjs @@ -0,0 +1,7 @@ +import { run } from "./android-rendering.mjs"; + +await run( + process.argv[2], + "maplibre", + "maplibre-acceptance-api36-retained-resume" +); diff --git a/scripts/record-native-ui-observation.test.mjs b/scripts/record-native-ui-observation.test.mjs index 4cb5f50..cfb5b10 100644 --- a/scripts/record-native-ui-observation.test.mjs +++ b/scripts/record-native-ui-observation.test.mjs @@ -1,5 +1,6 @@ import assert from "node:assert/strict"; import { spawnSync } from "node:child_process"; +import { createHash } from "node:crypto"; import fs from "node:fs"; import { tmpdir } from "node:os"; import { join } from "node:path"; @@ -198,6 +199,80 @@ try { JSON.parse(fs.readFileSync(reportPath)).scenarios[nativeUiScenarios[0]], "passed" ); + // Replay the actual operator input only on a temporary report; no acceptance credit. + const rejectedInputPath = new URL( + "./fixtures/api36-maplibre-attempt30-rejected-input.json", + import.meta.url + ); + const rawInput = fs.readFileSync(rejectedInputPath); + const syntheticReport = { + ...reportFor(nativeUiScenarios), + installedBinarySha256: + "c4c0ccf43f9d3b7217f8085827b351f10c5ececfb6a70c603be9f766dd64d131", + libraryDistSha256: + "f17855848fccf4aad07d2ebc02738d2bb799778ea0bd12070c448cd857251ab5", + environment: "maplibre-android", + scenarios: Object.fromEntries( + nativeUiScenarios.map((name) => [ + name, + name === "marker-prop-rejection" ? "unverified" : "passed", + ]) + ), + }; + const rawReport = Buffer.from(JSON.stringify(syntheticReport)); + assert.equal( + createHash("sha256").update(rawInput).digest("hex"), + "818e84f6b230f04c08756893d4302f684d925ff58516e7ac7cbab1d91f458b93" + ); + fs.writeFileSync(reportPath, rawReport); + fs.writeFileSync(observationPath, rawInput); + const replay = () => + spawnSync( + process.execPath, + [ + join(import.meta.dirname, "record-native-ui-observation.mjs"), + reportPath, + "marker-prop-rejection", + "passed", + observationPath, + ], + { encoding: "utf8" } + ); + const rejected = replay(); + assert.equal(rejected.status, 1); + assert.match(rejected.stderr, /Unknown observation field/); + assert.deepEqual(fs.readFileSync(reportPath), rawReport); + const corrected = JSON.parse( + fs.readFileSync( + new URL( + "../records/evidence/revised-api-u26-maplibre-android-attempt30-corrected-input.json", + import.meta.url + ) + ) + ); + assert.deepEqual( + corrected, + (() => { + const value = JSON.parse(rawInput); + value.rendererData.receipts = value.receipts; + delete value.receipts; + return value; + })() + ); + fs.writeFileSync(observationPath, JSON.stringify(corrected)); + const accepted = replay(); + assert.equal(accepted.status, 0, accepted.stderr); + const next = JSON.parse(fs.readFileSync(reportPath)); + const priorIdentity = JSON.parse(rawReport); + for (const field of [ + "installedBinarySha256", + "libraryDistSha256", + "environment", + "runId", + ]) + assert.equal(next[field], priorIdentity[field]); + assert.equal(next.scenarios["marker-prop-rejection"], "passed"); + assert.deepEqual(fs.readFileSync(rejectedInputPath), rawInput); console.log("Native UI observation writer filesystem regressions passed."); } finally { fs.rmSync(directory, { recursive: true, force: true }); diff --git a/scripts/tf07-native-runner.test.mjs b/scripts/tf07-native-runner.test.mjs index 3635f20..475788e 100644 --- a/scripts/tf07-native-runner.test.mjs +++ b/scripts/tf07-native-runner.test.mjs @@ -54,6 +54,7 @@ for (const [engine, borrowed, reuse = false] of [ ["mapbox", true, true], ["maplibre", false], ["maplibre", true], + ["maplibre", true, true], ]) { for (const failure of [ null, @@ -206,7 +207,10 @@ for (const [engine, borrowed, reuse = false] of [ process: { env: { ANDROID_SERIAL: "emulator-5580", - ...(reuse && { TF07_REUSE_API36_ATTEMPT24: "1" }), + ...(reuse && + (engine === "mapbox" + ? { TF07_REUSE_API36_ATTEMPT24: "1" } + : { TF07_REUSE_MAPLIBRE_API36_ATTEMPT30: "1" })), TF07_NATIVE_BINARY_SHA256: hash, TF07_MANUAL_REPORT: "/report", TF07_ANDROID_DIAGNOSTICS: "/diagnostics", @@ -494,7 +498,7 @@ for (const [engine, borrowed, reuse = false] of [ }; try { const result = await runInNewContext( - `const loadApi36ReusedObservations = () => JSON.parse(${JSON.stringify(JSON.stringify(reused))});\n${source}\nrunNative("${engine}")`, + `const loadMaplibreApi36ReusedObservations = () => JSON.parse(${JSON.stringify(JSON.stringify(reused))});\nconst loadApi36ReusedObservations = () => JSON.parse(${JSON.stringify(JSON.stringify(reused))});\n${source}\nrunNative("${engine}")`, context ); assert(result.androidRecorder, "Successful row saves recorder status."); diff --git a/scripts/tf07-ui-smoke.mjs b/scripts/tf07-ui-smoke.mjs index 3cc4f5b..992aae0 100644 --- a/scripts/tf07-ui-smoke.mjs +++ b/scripts/tf07-ui-smoke.mjs @@ -15,7 +15,10 @@ import { dirname, join, resolve } from "node:path"; import { StringDecoder } from "node:string_decoder"; import { prepareAndroidSignalCapture } from "./android-signal-capture.mjs"; -import { loadApi36ReusedObservations } from "./api36-reused-observations.mjs"; +import { + loadApi36ReusedObservations, + loadMaplibreApi36ReusedObservations, +} from "./api36-reused-observations.mjs"; import { stopOwnedProcess } from "./native-smoke-process.mjs"; import { judgeNativeRetained, @@ -426,9 +429,21 @@ const runNative = async (selectedEngine) => { (platform === "android" && selectedEngine === "mapbox" && !retained), "Attempt24 reuse is core Mapbox Android only." ); - const reusedObservations = reuseApi36 - ? loadApi36ReusedObservations(identity) - : {}; + const reuseMaplibreApi36 = + process.env.TF07_REUSE_MAPLIBRE_API36_ATTEMPT30 === "1"; + assert( + !reuseMaplibreApi36 || + (!reuseApi36 && + platform === "android" && + selectedEngine === "maplibre" && + !retained), + "Attempt30 reuse is core MapLibre Android only." + ); + const reusedObservations = reuseMaplibreApi36 + ? loadMaplibreApi36ReusedObservations(identity) + : reuseApi36 + ? loadApi36ReusedObservations(identity) + : {}; const reusedScenarios = Object.keys(reusedObservations); const manualPath = process.env.TF07_MANUAL_REPORT; let completed; @@ -595,7 +610,7 @@ const runNative = async (selectedEngine) => { JSON.stringify( { ...identity, - ...(reuseApi36 && { reusedObservations }), + ...((reuseApi36 || reuseMaplibreApi36) && { reusedObservations }), scenarios: Object.fromEntries( scenarios.map((scenario) => [ scenario, @@ -636,7 +651,7 @@ const runNative = async (selectedEngine) => { ? { nativeTarget: platform === "ios" ? iosDevice : serial } : {}), observation, - ...(reuseApi36 && { reusedObservations }), + ...((reuseApi36 || reuseMaplibreApi36) && { reusedObservations }), }; } catch (error) { failures.push(error);