diff --git a/README.md b/README.md new file mode 100644 index 0000000..d84f5c6 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Road Compiler + +Compiles a `native-road-package/v1` `RoadCompilerInput` JSON file into native-road GeoJSON, diagnostics, traffic-signal runtime assets, and a deterministic completion marker. + +```bash +npx road-compiler --input /absolute/path/road-compiler.input.json +``` + +The compiler does not read host area configuration. The caller owns configuration normalization and creates the input JSON. Successful compilation writes exactly one `NATIVE_ROAD_COMPILE_DONE` JSON marker to stdout. + +Run `npm test` and `npm run test:road-parity` after `npm ci` to validate the package without the host repository. diff --git a/bin/road-compiler.js b/bin/road-compiler.js new file mode 100755 index 0000000..d5b69cb --- /dev/null +++ b/bin/road-compiler.js @@ -0,0 +1,16 @@ +#!/usr/bin/env node +"use strict"; + +const fs = require("fs"); +const path = require("path"); +const { compiler } = require("../src"); + +const args = process.argv.slice(2); +const index = args.indexOf("--input"); +if (index < 0 || !args[index + 1] || index + 2 !== args.length) { + throw new Error("Usage: road-compiler --input "); +} +const inputFile = path.resolve(args[index + 1]); +const input = JSON.parse(fs.readFileSync(inputFile, "utf8")); +const { result, comparison } = compiler.compileInput(input); +console.log(`NATIVE_ROAD_COMPILE_DONE ${JSON.stringify({ areaId: input.areaId, roads: result.model.roads.length, endpoints: result.model.endpoints.length, diagnostics: result.diagnostics.length, output: input.outDir, comparison })}`); diff --git a/bin/road-workbench.js b/bin/road-workbench.js new file mode 100755 index 0000000..8aa2a15 --- /dev/null +++ b/bin/road-workbench.js @@ -0,0 +1,14 @@ +#!/usr/bin/env node +"use strict"; + +const path = require("path"); +const { startWorkbench } = require("../workbench/server"); + +const args = process.argv.slice(2); +const index = args.indexOf("--input"); +if (index < 0 || !args[index + 1]) throw new Error("Usage: road-workbench --input [--port ]"); +const inputFile = path.resolve(args[index + 1]); +const input = require(inputFile); +const portIndex = args.indexOf("--port"); +const port = portIndex >= 0 ? Number(args[portIndex + 1]) : 8787; +startWorkbench({ input, inputFile, port }); diff --git a/docs/native-road-package-v1.md b/docs/native-road-package-v1.md new file mode 100644 index 0000000..b508157 --- /dev/null +++ b/docs/native-road-package-v1.md @@ -0,0 +1,98 @@ +# Native Road Package v1 + +`native-road-package/v1` defines the boundary between the host area pipeline +and the native road compiler. The compiler accepts only the input below; it +does not read `config/areas/*.json` or derive host paths. + +## Input + +```js +{ + areaId: string, + osmFile: string, + outDir: string, + stagingDir: string, + overridesFile: string, + trafficSignalsFile: string, + comparisonDir?: string, + options: { + edgeLines: boolean, + junctionTemplates: { + enabled: boolean, + references: [], + clusters: [] + } + } +} +``` + +All paths are absolute at the process boundary. `stagingDir` is the parent for +the compiler's temporary output and `outDir` is promoted atomically only after +all files are written. The host maps normalized area configuration to this +shape and owns all path derivation. + +## Output + +`outDir` contains these JSON documents: + +- `compiled.json`: top-level keys are `schema`, `areaId`, `source`, `model`, + `movements`, `trafficSignals`, `diagnostics`, and `layers`. `source` has + `osm`, `overrides`, and `trafficSignals` paths. +- `diagnostics.json`: `{ schema: "native-road-diagnostics/v1", diagnostics: [] }`. + Each diagnostic has `id`, `severity`, `subjectId`, `sourceIds`, `rule`, + `message`, and `geometry` (a GeoJSON geometry or `null`). +- `comparison.json`: coverage counts for the road workbench. +- `traffic-signal-assemblies.json` and `traffic-signals.json`: compiler-owned + signal assembly and runtime views. + +`layers/` always contains these twelve GeoJSON FeatureCollections: + +1. `road_surface.geojson` +2. `intersection_surface.geojson` +3. `sidewalk_surface.geojson` +4. `edge_lines.geojson` +5. `lane_separators.geojson` +6. `center_lines.geojson` +7. `crosswalks.geojson` +8. `vehicle_stop_lines.geojson` +9. `direction_arrows.geojson` +10. `turn_arrows.geojson` +11. `lane_centerlines.geojson` (semantic, not rendered) +12. `connectors.geojson` (semantic, not rendered) + +The editable signal source at `trafficSignalsFile` is a sibling of `outDir`. +It is included in the parity baseline because regeneration must be stable. + +Successful CLI execution prints exactly one completion marker: + +```text +NATIVE_ROAD_COMPILE_DONE {"areaId":...,"roads":N,"endpoints":N,"diagnostics":N,"output":...,"comparison":...} +``` + +Consumers use the CLI process plus files in `outDir` and parse this marker. +An in-process import may be an optimization, never the sole contract. + +## Comparison Input Decision + +`comparison.json` remains part of v1. The road workbench currently reads it, +so removing it would break a real consumer. `comparisonDir` is therefore an +optional compiler input for a future standalone package: when absent, the +compiler emits native-only counts and marks osm2streets coverage unavailable. + +## Parity Rules + +`scripts/road-parity.js` snapshots every file below `outDir` plus the sibling +editable signal document. JSON object keys are recursively sorted before +hashing. GeoJSON records both a sorted-feature `contentHash` and original-order +`orderHash`; either difference is reported. + +The only normalization is intentional volatility removal: + +- absolute paths below this repository become `/...`; +- other absolute paths become `/`; +- `native-road-*` temporary directory names become ``. + +No coordinates are rounded and no feature order changes are ignored. Control +experiments on 2026-08-25 compiled `fengshu-er-road` and +`nantaizi-lake-innovation-valley` twice, then regenerated their editable +signal documents. All 18 tracked files per area matched. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8d7bb8b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,223 @@ +{ + "name": "@osm-asset/road-compiler", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@osm-asset/road-compiler", + "version": "0.1.0", + "dependencies": { + "ol": "10.10.0" + }, + "bin": { + "road-compiler": "bin/road-compiler.js" + } + }, + "node_modules/@petamoriken/float16": { + "version": "3.9.3", + "resolved": "http://172.16.1.86:4873/@petamoriken/float16/-/float16-3.9.3.tgz", + "integrity": "sha512-8awtpHXCx/bNpFt4mt2xdkgtgVvKqty8VbjHI/WWWQuEw+KLzFot3f4+LkQY9YmOtq7A5GdOnqoIC8Pdygjk2g==", + "license": "MIT" + }, + "node_modules/@types/rbush": { + "version": "4.0.0", + "resolved": "http://172.16.1.86:4873/@types/rbush/-/rbush-4.0.0.tgz", + "integrity": "sha512-+N+2H39P8X+Hy1I5mC6awlTX54k3FhiUmvt7HWzGJZvF+syUAAxP/stwppS8JE84YHqFgRMv6fCy31202CMFxQ==", + "license": "MIT" + }, + "node_modules/@zarrita/storage": { + "version": "0.2.0", + "resolved": "http://172.16.1.86:4873/@zarrita/storage/-/storage-0.2.0.tgz", + "integrity": "sha512-855ZXqtnds7spnT8vNvD+MXa3QExP1m2GqShe8yt7uZXHnQLgJHgkpVwFjE1B0KDDRO0ki09hmk6OboTaIfPsQ==", + "license": "MIT", + "dependencies": { + "reference-spec-reader": "^0.2.0", + "unzipit": "2.0.0" + } + }, + "node_modules/earcut": { + "version": "3.2.3", + "resolved": "http://172.16.1.86:4873/earcut/-/earcut-3.2.3.tgz", + "integrity": "sha512-vnS4AVwp1KHAF13i1vp1/2D5evWy3k5u/iW/B81QVsUZtV8cv2tU0b2VNFlqvh4kYwrFMDdjPCfAmfyJW9y14Q==", + "license": "ISC" + }, + "node_modules/fflate": { + "version": "0.8.3", + "resolved": "http://172.16.1.86:4873/fflate/-/fflate-0.8.3.tgz", + "integrity": "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==", + "license": "MIT" + }, + "node_modules/geotiff": { + "version": "3.1.0-beta.0", + "resolved": "http://172.16.1.86:4873/geotiff/-/geotiff-3.1.0-beta.0.tgz", + "integrity": "sha512-wbVwOaQYuN+ywly5NoMXn37nHslwkQg5EFHqMeUTtjDACrSag0EEVlFsc+2DK3Pzmmp6XzJW2RTZOamPsBM6ng==", + "license": "MIT", + "dependencies": { + "@petamoriken/float16": "^3.9.3", + "lerc": "^3.0.0", + "pako": "^2.0.4", + "parse-headers": "^2.0.2", + "quick-lru": "^6.1.1", + "web-worker": "^1.5.0", + "xml-utils": "^1.10.2", + "zstddec": "^0.2.0" + }, + "engines": { + "node": ">=10.19" + } + }, + "node_modules/lerc": { + "version": "3.0.0", + "resolved": "http://172.16.1.86:4873/lerc/-/lerc-3.0.0.tgz", + "integrity": "sha512-Rm4J/WaHhRa93nCN2mwWDZFoRVF18G1f47C+kvQWyHGEZxFpTUi73p7lMVSAndyxGt6lJ2/CFbOcf9ra5p8aww==", + "license": "Apache-2.0" + }, + "node_modules/numcodecs": { + "version": "0.3.2", + "resolved": "http://172.16.1.86:4873/numcodecs/-/numcodecs-0.3.2.tgz", + "integrity": "sha512-6YSPnmZgg0P87jnNhi3s+FVLOcIn3y+1CTIgUulA3IdASzK9fJM87sUFkpyA+be9GibGRaST2wCgkD+6U+fWKw==", + "license": "MIT", + "dependencies": { + "fflate": "^0.8.0" + } + }, + "node_modules/ol": { + "version": "10.10.0", + "resolved": "http://172.16.1.86:4873/ol/-/ol-10.10.0.tgz", + "integrity": "sha512-tLPKn6zl+6uWdPufYlqG/lQzuVUTVmfwahQqVr5+wZNyZecyAtIhMTyOtKpu7ooNDLY2sEjKZNXw9HL+sOjC1A==", + "license": "BSD-2-Clause", + "dependencies": { + "@types/rbush": "4.0.0", + "earcut": "^3.0.0", + "geotiff": "^3.1.0-beta.0", + "pbf": "5.1.2", + "rbush": "^4.0.0", + "zarrita": "^0.7.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/openlayers" + } + }, + "node_modules/pako": { + "version": "2.2.0", + "resolved": "http://172.16.1.86:4873/pako/-/pako-2.2.0.tgz", + "integrity": "sha512-zJq6RP/5q+TO2OpFV3FHzlPnFjmkb7Nc99a5SNjJE+uu/PkpChs+NIZSSzbBoD+6kjiISXjfYdwj1ZRQ81dz/w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "(MIT AND Zlib)" + }, + "node_modules/parse-headers": { + "version": "2.0.6", + "resolved": "http://172.16.1.86:4873/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", + "license": "MIT" + }, + "node_modules/pbf": { + "version": "5.1.2", + "resolved": "http://172.16.1.86:4873/pbf/-/pbf-5.1.2.tgz", + "integrity": "sha512-mnvGdvOrIvJOBGUEdGkrVXjN8E/VkIJCkf2eS1DH2yv82ORUlLttmDt0rWY38yYZmVwciZwBUvHM20qxBZf40w==", + "license": "BSD-3-Clause", + "dependencies": { + "resolve-protobuf-schema": "^2.1.0" + }, + "bin": { + "pbf": "bin/pbf" + } + }, + "node_modules/protocol-buffers-schema": { + "version": "3.6.1", + "resolved": "http://172.16.1.86:4873/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz", + "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==", + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "6.1.2", + "resolved": "http://172.16.1.86:4873/quick-lru/-/quick-lru-6.1.2.tgz", + "integrity": "sha512-AAFUA5O1d83pIHEhJwWCq/RQcRukCkn/NSm2QsTEMle5f2hP0ChI2+3Xb051PZCkLryI/Ir1MVKviT2FIloaTQ==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/quickselect": { + "version": "3.0.0", + "resolved": "http://172.16.1.86:4873/quickselect/-/quickselect-3.0.0.tgz", + "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==", + "license": "ISC" + }, + "node_modules/rbush": { + "version": "4.0.1", + "resolved": "http://172.16.1.86:4873/rbush/-/rbush-4.0.1.tgz", + "integrity": "sha512-IP0UpfeWQujYC8Jg162rMNc01Rf0gWMMAb2Uxus/Q0qOFw4lCcq6ZnQEZwUoJqWyUGJ9th7JjwI4yIWo+uvoAQ==", + "license": "MIT", + "dependencies": { + "quickselect": "^3.0.0" + } + }, + "node_modules/reference-spec-reader": { + "version": "0.2.0", + "resolved": "http://172.16.1.86:4873/reference-spec-reader/-/reference-spec-reader-0.2.0.tgz", + "integrity": "sha512-q0mfCi5yZSSHXpCyxjgQeaORq3tvDsxDyzaadA/5+AbAUwRyRuuTh0aRQuE/vAOt/qzzxidJ5iDeu1cLHaNBlQ==", + "license": "MIT" + }, + "node_modules/resolve-protobuf-schema": { + "version": "2.1.0", + "resolved": "http://172.16.1.86:4873/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz", + "integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==", + "license": "MIT", + "dependencies": { + "protocol-buffers-schema": "^3.3.1" + } + }, + "node_modules/unzipit": { + "version": "2.0.0", + "resolved": "http://172.16.1.86:4873/unzipit/-/unzipit-2.0.0.tgz", + "integrity": "sha512-DVeVIWUZCAQPNzm5sB0hpsG1GygTTdBnzNtYYEpInkttx5evkyqRgZi6rTczoySqp8hO5jHVKzrH0f23X8FZLg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/web-worker": { + "version": "1.5.0", + "resolved": "http://172.16.1.86:4873/web-worker/-/web-worker-1.5.0.tgz", + "integrity": "sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw==", + "license": "Apache-2.0" + }, + "node_modules/xml-utils": { + "version": "1.10.2", + "resolved": "http://172.16.1.86:4873/xml-utils/-/xml-utils-1.10.2.tgz", + "integrity": "sha512-RqM+2o1RYs6T8+3DzDSoTRAUfrvaejbVHcp3+thnAtDKo8LskR+HomLajEy5UjTz24rpka7AxVBRR3g2wTUkJA==", + "license": "CC0-1.0" + }, + "node_modules/zarrita": { + "version": "0.7.4", + "resolved": "http://172.16.1.86:4873/zarrita/-/zarrita-0.7.4.tgz", + "integrity": "sha512-NChufj86SceFj45z4CYjndmI98dphaG7hU8Wj0UGpMyT21o0V3HTY6zo87aSobYWts1tNFivSXzH2AR1AkaWjA==", + "license": "MIT", + "dependencies": { + "@zarrita/storage": "^0.2.0", + "numcodecs": "^0.3.2" + } + }, + "node_modules/zstddec": { + "version": "0.2.0", + "resolved": "http://172.16.1.86:4873/zstddec/-/zstddec-0.2.0.tgz", + "integrity": "sha512-oyPnDa1X5c13+Y7mA/FDMNJrn4S8UNBe0KCqtDmor40Re7ALrPN6npFwyYVRRh+PqozZQdeg23QtbcamZnG5rA==", + "license": "MIT AND BSD-3-Clause" + } + } +} diff --git a/package.json b/package.json index 336e583..c45305e 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,18 @@ { "name": "@osm-asset/road-compiler", "version": "0.1.0", - "private": true, + "private": false, "type": "commonjs", "main": "src/index.js", + "bin": { + "road-compiler": "bin/road-compiler.js" + }, "scripts": { - "test": "node test/index.js" + "test": "node test/index.js", + "test:road-parity": "node test/road-parity.js", + "road:workbench": "node bin/road-workbench.js" + }, + "dependencies": { + "ol": "10.10.0" } } diff --git a/test/baseline/fengshu-er-road.json b/test/baseline/fengshu-er-road.json new file mode 100644 index 0000000..1d10646 --- /dev/null +++ b/test/baseline/fengshu-er-road.json @@ -0,0 +1,108 @@ +{ + "contract": "native-road-package/v1", + "areaId": "fengshu-er-road", + "files": { + "../native-traffic-signals.json": { + "contentHash": "88e7f0ef4fc7bdb9ef202af018b3fb3179035ffc8ed5eeba03276c263e1f0476", + "bytes": 5886 + }, + "comparison.json": { + "contentHash": "651eb4000a44a7521a79c3e1429795b83d20f8899e0c67c4bb25b56cf4a6f75d", + "bytes": 1295 + }, + "compiled.json": { + "contentHash": "2ab82eafcdab70155078fae3559692ef1fde0645a52c6decbaea762a9ffeb24a", + "bytes": 159230 + }, + "diagnostics.json": { + "contentHash": "1d9fdae06ddcbc19b5262b797a4a35c494fc30a98a66dbfa111533b12c5fdfc7", + "bytes": 6862 + }, + "layers/center_lines.geojson": { + "contentHash": "04db66df5821b319d59297b8515502fabcad95faf083cae19edb338be2f6024b", + "orderHash": "04db66df5821b319d59297b8515502fabcad95faf083cae19edb338be2f6024b", + "features": 5, + "bytes": 6909 + }, + "layers/connectors.geojson": { + "contentHash": "e7979d4642c7c10f33fb23e92721f22533a851ae1a2b4d35f224d50927bf2fe9", + "orderHash": "c327b7b154d4d9ca04cd895523eb0d8ad67c37051ef1d2135b2b46c51e12df58", + "features": 90, + "bytes": 197885 + }, + "layers/crosswalks.geojson": { + "contentHash": "354cd4d7ed105a11b95904b44848dce567b3a3383f76755936d8c00691fe29af", + "orderHash": "d24376438ac956bde52fcbfa955dd72c2ba31a97995608aaed1c79f6fd3633ab", + "features": 152, + "bytes": 219286 + }, + "layers/direction_arrows.geojson": { + "contentHash": "7b8362ad4912c997a7661befde55ddfe58757c3c8d139c15867e1938ea8f6918", + "orderHash": "5274e8b433946410a7cdffdaa452c1750e04f53e73a86bf81d034cfb26d4c254", + "features": 686, + "bytes": 1053308 + }, + "layers/edge_lines.geojson": { + "contentHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8", + "orderHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8", + "features": 0, + "bytes": 52 + }, + "layers/intersection_surface.geojson": { + "contentHash": "b2022ca70339aa470f3be451bf3ba2f55b59c3900645c864538372173811309f", + "orderHash": "b2022ca70339aa470f3be451bf3ba2f55b59c3900645c864538372173811309f", + "features": 5, + "bytes": 13048 + }, + "layers/lane_centerlines.geojson": { + "contentHash": "19c550c794810c1071de55dee158295235106a56e3877a2ba10da920ee214593", + "orderHash": "67f8e7d33ec578644416e4837dd4aafef62a55aaeb4d438d07ab07eddfbb1df1", + "features": 84, + "bytes": 73294 + }, + "layers/lane_separators.geojson": { + "contentHash": "02fdf2c7b6e89c2850a60ea2ac72b9f62910259bdb2949681fcaa7e67d2b51f0", + "orderHash": "81782a059c4ff9f69fdf7de9107d20a8d6cf55d34bb0620ec28a9a8c5106c982", + "features": 3596, + "bytes": 4164106 + }, + "layers/road_surface.geojson": { + "contentHash": "5a2936a705e64338d0d79b395a13d761f1893dd72330a9b9ee4696ae75eab295", + "orderHash": "d8402ae6e772e0778b862b190abfa291de1b02a15537d455f7dcd8596245dfd8", + "features": 30, + "bytes": 49554 + }, + "layers/sidewalk_surface.geojson": { + "contentHash": "b6f8f876e9f18fd2ef6749125a09d654c73d986e916bd262ceb9967bca1a54c6", + "orderHash": "3fd42a67e18e3b8743fa538428e039ef66a1f44150a6881a7aaa18326607b5cb", + "features": 26, + "bytes": 54997 + }, + "layers/turn_arrows.geojson": { + "contentHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8", + "orderHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8", + "features": 0, + "bytes": 52 + }, + "layers/vehicle_stop_lines.geojson": { + "contentHash": "cb904550ab8eec011cf33e5edfa81044de6dfca0280dbfe488e77229055ed590", + "orderHash": "8a4b877a17a5af60adc8656465afad6756944736291664139e878d46c5a4f363", + "features": 4, + "bytes": 4191 + }, + "traffic-signal-assemblies.json": { + "contentHash": "1788026a0c8c531b2fc7dd49628f7fbadd809c7b2f7f8819cffb3ac7d30689ca", + "orderHash": "b409ea6b77b6c8639f63c33a156581f9b184a84fde34d265b5deb05705828251", + "features": 7, + "bytes": 5411 + }, + "traffic-signals.json": { + "contentHash": "625b79b6eb82b41f2099ba51960717c7f794fdfbd87310eb12e99da966540d89", + "bytes": 15491 + } + }, + "volatileExcluded": [ + "absolute paths -> or ", + "native-road-* staging directory -> " + ] +} diff --git a/test/baseline/nantaizi-lake-innovation-valley.json b/test/baseline/nantaizi-lake-innovation-valley.json new file mode 100644 index 0000000..554b0e5 --- /dev/null +++ b/test/baseline/nantaizi-lake-innovation-valley.json @@ -0,0 +1,108 @@ +{ + "contract": "native-road-package/v1", + "areaId": "nantaizi-lake-innovation-valley", + "files": { + "../native-traffic-signals.json": { + "contentHash": "36cb9f069fb44a6e24f0af0d130ef8cb5b4a93250dc9fb0891191d1ba039a5b2", + "bytes": 28329 + }, + "comparison.json": { + "contentHash": "5aa11da443221a48288641ac6950c6e4d75d834713a93110bbf265859202a265", + "bytes": 1153 + }, + "compiled.json": { + "contentHash": "ea5ae4a04f1259b1ccec9fc1cca7ef8ba81426a77584a447480b6047b37f5e01", + "bytes": 184985 + }, + "diagnostics.json": { + "contentHash": "7e9327f0424dd612f389c560c114a4cafee1349bbfa36f49b2b4eab846e5ca91", + "bytes": 9755 + }, + "layers/center_lines.geojson": { + "contentHash": "2b2710fce06e75b0a3e4941c2da6119cea7b8bb7834345607bbee384de20ee6b", + "orderHash": "ea71a8841370689d6fc2b75d0b30ec7104638fb2904da6d707dc82ff3131e065", + "features": 511, + "bytes": 694102 + }, + "layers/connectors.geojson": { + "contentHash": "901a86bc6c536d38bb73ae4654ec1ce7d1c0790c2d6eba92543c48f584cd15ac", + "orderHash": "4df882ad59b65a97d892df64de0156b35beaf071b04eed671ef7b535e9e2a7b9", + "features": 76, + "bytes": 160866 + }, + "layers/crosswalks.geojson": { + "contentHash": "53fda76182c0d1db5f9e7ac284337ece62655d7fee8bb446fe170ea26abe8bbc", + "orderHash": "53fda76182c0d1db5f9e7ac284337ece62655d7fee8bb446fe170ea26abe8bbc", + "features": 48, + "bytes": 50536 + }, + "layers/direction_arrows.geojson": { + "contentHash": "38e80bbfe02d4f12ce40e7d0c8342e3bef6b602c64f81dd320b366b6a6b3d205", + "orderHash": "579aa6c37585bf4edf9d6b6b1e120f976b93ec2d0c303d82a154b75c114a45f5", + "features": 324, + "bytes": 493431 + }, + "layers/edge_lines.geojson": { + "contentHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8", + "orderHash": "ad37fe6278e0c7caf3b77c1c5068a56e18a6c87b78ed5a840ee22a0f961ea7a8", + "features": 0, + "bytes": 52 + }, + "layers/intersection_surface.geojson": { + "contentHash": "7f79e57215e3fd07c5c0f703c71e516873db770cb869efdf18925a3184059ca3", + "orderHash": "d69df8d92d0fce8f7ee172959b978d941fd011e094857e9ab7304b3d1e98bf92", + "features": 12, + "bytes": 38528 + }, + "layers/lane_centerlines.geojson": { + "contentHash": "3fea4ebfe62e0d720c6977e2289f4e6517ed7b3c5ab361270d03378971aec780", + "orderHash": "69a8ebaa42a74da4f7d5940c5a81bd82ceb104efd3f858723dccfadbae12121e", + "features": 50, + "bytes": 43582 + }, + "layers/lane_separators.geojson": { + "contentHash": "dc0b50b53da191e65f3dba01162acb7561966d1796a9c0789527cebfd6ed06a4", + "orderHash": "0bfd873e5698869fb4855783fe30bb6db29456958e4d154b7264374a5fdb4a10", + "features": 731, + "bytes": 835933 + }, + "layers/road_surface.geojson": { + "contentHash": "81af19c71cf6fc8a3884488c00cfb590e1a7fe9ed9e4351fce65825ceadd50fa", + "orderHash": "f2ddec5258411fbdbc050b7ecefbb157b59e00b8226afcc30d2b772e1859e357", + "features": 25, + "bytes": 38275 + }, + "layers/sidewalk_surface.geojson": { + "contentHash": "bb8f4516e27b16238d753b112d18b8acfa5cfad2cea522a65b7972a609be9563", + "orderHash": "4fa773a6f39c5b6d23551e1338c6d99ef8a5ecd9ebfcafa16154c9765fef8c6e", + "features": 73, + "bytes": 122432 + }, + "layers/turn_arrows.geojson": { + "contentHash": "a65bb8fe079f27e00bf2e6208148fc6b73d2d07e76d48b1cd1bf8a610d7e2d66", + "orderHash": "66966ac2c65464f9c6715ca9cda5a3620520bf1d066cba2dee36114dc46af936", + "features": 108, + "bytes": 132536 + }, + "layers/vehicle_stop_lines.geojson": { + "contentHash": "4f45caf3c0bf13bbf10d9cac15fa80b1a9be3969ed84803ba48e56c4a0080992", + "orderHash": "4f45caf3c0bf13bbf10d9cac15fa80b1a9be3969ed84803ba48e56c4a0080992", + "features": 8, + "bytes": 8475 + }, + "traffic-signal-assemblies.json": { + "contentHash": "9f8d032c00784bb72bb1322238cd7b0a80e621d435b43c728da86f1e77ca352a", + "orderHash": "0b9cae13094dba1994faca4bf1d4d80e8bc5497daa46df5899bf5e6fc7f26d61", + "features": 35, + "bytes": 26398 + }, + "traffic-signals.json": { + "contentHash": "c4b68cc1cefeb0d393a18eef6c7eb79933fba28630826745165ed433c25779d0", + "bytes": 74151 + } + }, + "volatileExcluded": [ + "absolute paths -> or ", + "native-road-* staging directory -> " + ] +}