{"owner":"Project-OSRM","repo":"osrm-backend","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"## Open Source Routing Machine\n\nOSRM (Open Source Routing Machine) is a high performance routing engine written in C++ designed to run on OpenStreetMap data.\nIt provides various routing services including route finding, distance/duration tables, GPS trace matching, and traveling salesman problem solving.\nIt is accessible via HTTP API, C++ library interface, and Node.js wrapper.\nOSRM supports two routing algorithms: Contraction Hierarchies (CH) and Multi-Level Dijkstra (MLD).\n\n## Developing\n\nWe target C++20 but need to deal with older compilers that only have partial support.\n\nUse `./scripts/format.sh` to format the code. Ensure clang-format-15 is available on the system.\n\n## Coding Standards\n\nSpecific practices to follow (see [wiki](https://github.com/Project-OSRM/osrm-backend/wiki/Coding-Standards)):\n\n- **No `using namespace`**: Always use explicit `std::` prefixes, never `using namespace std;` (especially in headers)\n- **Naming conventions**:\n  - Type names (classes, structs, enums): `UpperCamelCase` (e.g. `TextFileReader`)\n  - Variables: `lower_case_with_underscores`, private members start with `m_` (e.g. `m_node_count`)\n  - Functions: `lowerCamelCase` verb phrases (e.g. `openFile()`, `isValid()`)\n  - Enumerators and public members: `UpperCamelCase` (e.g. `VK_Argument`)\n- **Include order**: (1) Module header, (2) Local headers, (3) Parent directory headers, (4) System includes - sorted lexicographically within each group\n- **Comments**: Minimal use of comments on internal interfaces. Use C++ style `//` comments, not C style `/* */`. Use `#if 0` / `#endif` to comment out blocks\n- **Integer types**: Use only `int`/`unsigned` for 32-bit, or precise-width types like `int16_t`, `int64_t`\n- **No RTTI/exceptions**: Avoid `dynamic_cast<>` and exceptions (except for IO operations)\n- **Compiler warnings**: Treat all warnings as errors - fix them, don't ignore them\n- **Assert liberally**: Use `BOOST_ASSERT` to check preconditions and assumptions\n- **Indentation**: 4 spaces (enforced by clang-format)\n\n## Building\n\nThis project uses CMake. The build directory should be `build` or `build-{something}` or `build/{something}/`. For example:\n- `./build`\n- `./build-gcc-debug`\n- `./build/gcc-debug`\n- `./build/gcc`\n- `./build/clang-debug`\n- `./build-clang-release` \n\nUse `cmake --build ${BUILD_DIR} --target ${TARGET} -j $(nproc --ignore=2)` to build a target.\n\n\n## Running\n\nOSRM supports two data preparations: Contraction Hierarchies (CH) and Multi-Level Dijkstra (MLD).\n\nFor CH:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm` (optional, improves CH performance due to cache locality of node reordering)\n3. `./${BUILD_DIR}/osrm-contract data.osrm`\n4. `./${BUILD_DIR}/osrm-routed -a CH data.osrm`\n\nFor MLD:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm`\n3. `./${BUILD_DIR}/osrm-customize data.osrm`\n4. `./${BUILD_DIR}/osrm-routed -a MLD data.osrm`\n\nA dataset can be both MLD and CH if both `osrm-contract` and `osrm-customize` are executed:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm`\n3. `./${BUILD_DIR}/osrm-contract data.osrm`\n4. `./${BUILD_DIR}/osrm-customize data.osrm`\n5. `./${BUILD_DIR}/osrm-routed -a CH data.osrm` OR `./${BUILD_DIR}/osrm-routed -a MLD data.osrm`\n\n\n## Testing\n\n### Running Unit tests\n\nUnit tests are contained in `unit_tests/` using boost test and can be build with:\n```bash\ncmake --build ${BUILD_DIR} --target tests\n```\n\nThis will create various tests in `${BUILD_DIR}/unit_tests/`.\n\n### Running Integration Tests\n\nIntegration tests are contained in `features/` using cucumber-js\n\nTo run cucumber tests with the full test matrix across different algorithms (CH, MLD) and load methods (mmap, directly, datastore).\n```bash\nnpm test\n```\n\nTo run cucumber tests for a specific configuration:\n```bash\nnpx cucumber-js -p home -p ch -p datastore\nnpx cucumber-js -p home -p mld -p mmap\n```\n\n**IMPORTANT: Profile changes MUST follow this checklist:**\n\n1. **Cucumber tests**: Every change to a profile (`.lua` files in `profiles/`) must be accompanied by a corresponding cucumber test in `features/` that validates the new or changed behavior.\n   - Run the relevant cucumber tests before committing profile changes:\n     ```bash\n     OSRM_BUILD_DIR=build npx cucumber-js -p home -p mld -p mmap features/<profile>/<feature>.feature\n     ```\n     The test cache is keyed by a content hash of all profiles, binaries, and the feature file, so profile changes automatically invalidate the cache. Old cache directories can optionally be cleaned up with `rm -rf test/cache`.\n   - Run the whole `.feature` file (not just the new scenario) to verify no regressions.\n   - Use the existing test patterns: `routability should be` tables where any column header starting with `forw`, `backw`, or `bothw` (including `*_rate` variants) is an expectation column (not an OSM tag). Headers matching `node/<tag>` apply to node tags. All other columns become OSM way tags.\n   - Do NOT add `@todo` to new scenarios — verify the expected behavior matches actual routing output.\n\n2. **taginfo.json**: If modifying tag handling (adding, removing, or changing how OSM tags are parsed), update `taginfo.json` with any new OSM tags that are now recognized or any tags whose semantics have changed.\n\n3. **OSM Wiki adherence**: Verify that the behavior matches [OSM tagging conventions](https://wiki.openstreetmap.org/wiki/Key:access):\n   - Mode-specific tags (e.g. `bicycle=yes`) override vehicle-level restrictions (e.g. `vehicle=no`)\n   - Directional suffixes (`:forward`/`:backward`) scope a tag to a specific travel direction\n   - The access tag hierarchy is: mode-specific > vehicle-level > general access\n   - When in doubt, consult the relevant OSM wiki pages for the tags being changed\n\n\n## Python Bindings\n\nPython bindings live under `src/python/` using nanobind + scikit-build-core.\n\n### Layout\n\n- `src/python/CMakeLists.txt` — nanobind module definition, installs everything under `osrm/` namespace\n- `src/python/osrm/` — Python package (`__init__.py`, `__main__.py`, `.pyi` stubs)\n- `src/python/src/` — C++ nanobind source files (16 files)\n- `src/python/include/python/` — C++ binding headers (`.hpp`)\n\n### Key details\n\n- `ENABLE_PYTHON_BINDINGS=ON` triggers `add_subdirectory(src/python)` in root CMakeLists.txt\n- Links against the in-tree `osrm` target directly (no FetchContent)\n- Binding headers use `#include \"python/...\"` prefix; OSRM headers use `engine/...` paths (not the `osrm/` forwarding headers), except `osrm/osrm.hpp`\n- LTO disabled for `osrm_ext` target (nanobind `NB_MAKE_OPAQUE` + GCC LTO + `-Werror` = ODR violation)\n- Wheel installs executables to `osrm/bin/`, profiles to `osrm/share/profiles/`; `wheel.exclude` filters out root CMake install artifacts (`lib/`, `include/`, `bin/`, `share/`)\n- `__main__.py` finds executables: `osrm/bin/` (wheel) → `build/*/` (editable) → PATH\n- Type stubs (`osrm_ext.pyi`) auto-generated by `nanobind_add_stub()`; rebuild + commit after C++ changes\n- C++ formatted by project clang-format; Python by ruff (both via `.pre-commit-config.yaml`)\n- When changing the Python binding API (function signatures, classes, exposed attributes, parameter semantics), update [docs/python/api.md](docs/python/api.md) in the same change\n- When changing the build, packaging, or release flow (pyproject.toml, CMake options, cibuildwheel config, `.github/workflows/release-monthly.yml`, `.github/workflows/osrm-backend.yml` Python steps), update [docs/python/development.md](docs/python/development.md) in the same change\n\n### Building & testing\n\n```bash\npip install -e \".[dev]\"                    # editable install\ncd test/data && make                       # build test data\npython -m osrm datastore test/data/ch/monaco\npytest test/python/\n```\n\n## Contributing\n\n<IMPORTANT>\nUse the [PR template](.github/PULL_REQUEST_TEMPLATE.md) to build the PR description.\nRemove irrelevant tasks, but NEVER remove `review` or submit it checked.\nWhen creating PRs via `gh`, do not pass escaped `\\n` in `--body`; use a real multiline body (heredoc or `--body-file`) so GitHub renders actual line breaks.\nDisclose AI participation in the PR description by stating only the harness name and model (e.g. \"GitHub Copilot, Claude Sonnet 4.6\"), add a robot emoji. Do not include links, fake email addresses, or session identifiers.\n\nDo NOT include any AI attribution (e.g. `Co-authored-by:` trailers) in git commit messages.\n</IMPORTANT>\n"},"files":{"AGENTS.md":"## Open Source Routing Machine\n\nOSRM (Open Source Routing Machine) is a high performance routing engine written in C++ designed to run on OpenStreetMap data.\nIt provides various routing services including route finding, distance/duration tables, GPS trace matching, and traveling salesman problem solving.\nIt is accessible via HTTP API, C++ library interface, and Node.js wrapper.\nOSRM supports two routing algorithms: Contraction Hierarchies (CH) and Multi-Level Dijkstra (MLD).\n\n## Developing\n\nWe target C++20 but need to deal with older compilers that only have partial support.\n\nUse `./scripts/format.sh` to format the code. Ensure clang-format-15 is available on the system.\n\n## Coding Standards\n\nSpecific practices to follow (see [wiki](https://github.com/Project-OSRM/osrm-backend/wiki/Coding-Standards)):\n\n- **No `using namespace`**: Always use explicit `std::` prefixes, never `using namespace std;` (especially in headers)\n- **Naming conventions**:\n  - Type names (classes, structs, enums): `UpperCamelCase` (e.g. `TextFileReader`)\n  - Variables: `lower_case_with_underscores`, private members start with `m_` (e.g. `m_node_count`)\n  - Functions: `lowerCamelCase` verb phrases (e.g. `openFile()`, `isValid()`)\n  - Enumerators and public members: `UpperCamelCase` (e.g. `VK_Argument`)\n- **Include order**: (1) Module header, (2) Local headers, (3) Parent directory headers, (4) System includes - sorted lexicographically within each group\n- **Comments**: Minimal use of comments on internal interfaces. Use C++ style `//` comments, not C style `/* */`. Use `#if 0` / `#endif` to comment out blocks\n- **Integer types**: Use only `int`/`unsigned` for 32-bit, or precise-width types like `int16_t`, `int64_t`\n- **No RTTI/exceptions**: Avoid `dynamic_cast<>` and exceptions (except for IO operations)\n- **Compiler warnings**: Treat all warnings as errors - fix them, don't ignore them\n- **Assert liberally**: Use `BOOST_ASSERT` to check preconditions and assumptions\n- **Indentation**: 4 spaces (enforced by clang-format)\n\n## Building\n\nThis project uses CMake. The build directory should be `build` or `build-{something}` or `build/{something}/`. For example:\n- `./build`\n- `./build-gcc-debug`\n- `./build/gcc-debug`\n- `./build/gcc`\n- `./build/clang-debug`\n- `./build-clang-release` \n\nUse `cmake --build ${BUILD_DIR} --target ${TARGET} -j $(nproc --ignore=2)` to build a target.\n\n\n## Running\n\nOSRM supports two data preparations: Contraction Hierarchies (CH) and Multi-Level Dijkstra (MLD).\n\nFor CH:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm` (optional, improves CH performance due to cache locality of node reordering)\n3. `./${BUILD_DIR}/osrm-contract data.osrm`\n4. `./${BUILD_DIR}/osrm-routed -a CH data.osrm`\n\nFor MLD:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm`\n3. `./${BUILD_DIR}/osrm-customize data.osrm`\n4. `./${BUILD_DIR}/osrm-routed -a MLD data.osrm`\n\nA dataset can be both MLD and CH if both `osrm-contract` and `osrm-customize` are executed:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm`\n3. `./${BUILD_DIR}/osrm-contract data.osrm`\n4. `./${BUILD_DIR}/osrm-customize data.osrm`\n5. `./${BUILD_DIR}/osrm-routed -a CH data.osrm` OR `./${BUILD_DIR}/osrm-routed -a MLD data.osrm`\n\n\n## Testing\n\n### Running Unit tests\n\nUnit tests are contained in `unit_tests/` using boost test and can be build with:\n```bash\ncmake --build ${BUILD_DIR} --target tests\n```\n\nThis will create various tests in `${BUILD_DIR}/unit_tests/`.\n\n### Running Integration Tests\n\nIntegration tests are contained in `features/` using cucumber-js\n\nTo run cucumber tests with the full test matrix across different algorithms (CH, MLD) and load methods (mmap, directly, datastore).\n```bash\nnpm test\n```\n\nTo run cucumber tests for a specific configuration:\n```bash\nnpx cucumber-js -p home -p ch -p datastore\nnpx cucumber-js -p home -p mld -p mmap\n```\n\n**IMPORTANT: Profile changes MUST follow this checklist:**\n\n1. **Cucumber tests**: Every change to a profile (`.lua` files in `profiles/`) must be accompanied by a corresponding cucumber test in `features/` that validates the new or changed behavior.\n   - Run the relevant cucumber tests before committing profile changes:\n     ```bash\n     OSRM_BUILD_DIR=build npx cucumber-js -p home -p mld -p mmap features/<profile>/<feature>.feature\n     ```\n     The test cache is keyed by a content hash of all profiles, binaries, and the feature file, so profile changes automatically invalidate the cache. Old cache directories can optionally be cleaned up with `rm -rf test/cache`.\n   - Run the whole `.feature` file (not just the new scenario) to verify no regressions.\n   - Use the existing test patterns: `routability should be` tables where any column header starting with `forw`, `backw`, or `bothw` (including `*_rate` variants) is an expectation column (not an OSM tag). Headers matching `node/<tag>` apply to node tags. All other columns become OSM way tags.\n   - Do NOT add `@todo` to new scenarios — verify the expected behavior matches actual routing output.\n\n2. **taginfo.json**: If modifying tag handling (adding, removing, or changing how OSM tags are parsed), update `taginfo.json` with any new OSM tags that are now recognized or any tags whose semantics have changed.\n\n3. **OSM Wiki adherence**: Verify that the behavior matches [OSM tagging conventions](https://wiki.openstreetmap.org/wiki/Key:access):\n   - Mode-specific tags (e.g. `bicycle=yes`) override vehicle-level restrictions (e.g. `vehicle=no`)\n   - Directional suffixes (`:forward`/`:backward`) scope a tag to a specific travel direction\n   - The access tag hierarchy is: mode-specific > vehicle-level > general access\n   - When in doubt, consult the relevant OSM wiki pages for the tags being changed\n\n\n## Python Bindings\n\nPython bindings live under `src/python/` using nanobind + scikit-build-core.\n\n### Layout\n\n- `src/python/CMakeLists.txt` — nanobind module definition, installs everything under `osrm/` namespace\n- `src/python/osrm/` — Python package (`__init__.py`, `__main__.py`, `.pyi` stubs)\n- `src/python/src/` — C++ nanobind source files (16 files)\n- `src/python/include/python/` — C++ binding headers (`.hpp`)\n\n### Key details\n\n- `ENABLE_PYTHON_BINDINGS=ON` triggers `add_subdirectory(src/python)` in root CMakeLists.txt\n- Links against the in-tree `osrm` target directly (no FetchContent)\n- Binding headers use `#include \"python/...\"` prefix; OSRM headers use `engine/...` paths (not the `osrm/` forwarding headers), except `osrm/osrm.hpp`\n- LTO disabled for `osrm_ext` target (nanobind `NB_MAKE_OPAQUE` + GCC LTO + `-Werror` = ODR violation)\n- Wheel installs executables to `osrm/bin/`, profiles to `osrm/share/profiles/`; `wheel.exclude` filters out root CMake install artifacts (`lib/`, `include/`, `bin/`, `share/`)\n- `__main__.py` finds executables: `osrm/bin/` (wheel) → `build/*/` (editable) → PATH\n- Type stubs (`osrm_ext.pyi`) auto-generated by `nanobind_add_stub()`; rebuild + commit after C++ changes\n- C++ formatted by project clang-format; Python by ruff (both via `.pre-commit-config.yaml`)\n- When changing the Python binding API (function signatures, classes, exposed attributes, parameter semantics), update [docs/python/api.md](docs/python/api.md) in the same change\n- When changing the build, packaging, or release flow (pyproject.toml, CMake options, cibuildwheel config, `.github/workflows/release-monthly.yml`, `.github/workflows/osrm-backend.yml` Python steps), update [docs/python/development.md](docs/python/development.md) in the same change\n\n### Building & testing\n\n```bash\npip install -e \".[dev]\"                    # editable install\ncd test/data && make                       # build test data\npython -m osrm datastore test/data/ch/monaco\npytest test/python/\n```\n\n## Contributing\n\n<IMPORTANT>\nUse the [PR template](.github/PULL_REQUEST_TEMPLATE.md) to build the PR description.\nRemove irrelevant tasks, but NEVER remove `review` or submit it checked.\nWhen creating PRs via `gh`, do not pass escaped `\\n` in `--body`; use a real multiline body (heredoc or `--body-file`) so GitHub renders actual line breaks.\nDisclose AI participation in the PR description by stating only the harness name and model (e.g. \"GitHub Copilot, Claude Sonnet 4.6\"), add a robot emoji. Do not include links, fake email addresses, or session identifiers.\n\nDo NOT include any AI attribution (e.g. `Co-authored-by:` trailers) in git commit messages.\n</IMPORTANT>\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"## Open Source Routing Machine\n\nOSRM (Open Source Routing Machine) is a high performance routing engine written in C++ designed to run on OpenStreetMap data.\nIt provides various routing services including route finding, distance/duration tables, GPS trace matching, and traveling salesman problem solving.\nIt is accessible via HTTP API, C++ library interface, and Node.js wrapper.\nOSRM supports two routing algorithms: Contraction Hierarchies (CH) and Multi-Level Dijkstra (MLD).\n\n## Developing\n\nWe target C++20 but need to deal with older compilers that only have partial support.\n\nUse `./scripts/format.sh` to format the code. Ensure clang-format-15 is available on the system.\n\n## Coding Standards\n\nSpecific practices to follow (see [wiki](https://github.com/Project-OSRM/osrm-backend/wiki/Coding-Standards)):\n\n- **No `using namespace`**: Always use explicit `std::` prefixes, never `using namespace std;` (especially in headers)\n- **Naming conventions**:\n  - Type names (classes, structs, enums): `UpperCamelCase` (e.g. `TextFileReader`)\n  - Variables: `lower_case_with_underscores`, private members start with `m_` (e.g. `m_node_count`)\n  - Functions: `lowerCamelCase` verb phrases (e.g. `openFile()`, `isValid()`)\n  - Enumerators and public members: `UpperCamelCase` (e.g. `VK_Argument`)\n- **Include order**: (1) Module header, (2) Local headers, (3) Parent directory headers, (4) System includes - sorted lexicographically within each group\n- **Comments**: Minimal use of comments on internal interfaces. Use C++ style `//` comments, not C style `/* */`. Use `#if 0` / `#endif` to comment out blocks\n- **Integer types**: Use only `int`/`unsigned` for 32-bit, or precise-width types like `int16_t`, `int64_t`\n- **No RTTI/exceptions**: Avoid `dynamic_cast<>` and exceptions (except for IO operations)\n- **Compiler warnings**: Treat all warnings as errors - fix them, don't ignore them\n- **Assert liberally**: Use `BOOST_ASSERT` to check preconditions and assumptions\n- **Indentation**: 4 spaces (enforced by clang-format)\n\n## Building\n\nThis project uses CMake. The build directory should be `build` or `build-{something}` or `build/{something}/`. For example:\n- `./build`\n- `./build-gcc-debug`\n- `./build/gcc-debug`\n- `./build/gcc`\n- `./build/clang-debug`\n- `./build-clang-release` \n\nUse `cmake --build ${BUILD_DIR} --target ${TARGET} -j $(nproc --ignore=2)` to build a target.\n\n\n## Running\n\nOSRM supports two data preparations: Contraction Hierarchies (CH) and Multi-Level Dijkstra (MLD).\n\nFor CH:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm` (optional, improves CH performance due to cache locality of node reordering)\n3. `./${BUILD_DIR}/osrm-contract data.osrm`\n4. `./${BUILD_DIR}/osrm-routed -a CH data.osrm`\n\nFor MLD:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm`\n3. `./${BUILD_DIR}/osrm-customize data.osrm`\n4. `./${BUILD_DIR}/osrm-routed -a MLD data.osrm`\n\nA dataset can be both MLD and CH if both `osrm-contract` and `osrm-customize` are executed:\n1. `./${BUILD_DIR}/osrm-extract -p profiles/car.lua data.osm.pbf`\n2. `./${BUILD_DIR}/osrm-partition data.osrm`\n3. `./${BUILD_DIR}/osrm-contract data.osrm`\n4. `./${BUILD_DIR}/osrm-customize data.osrm`\n5. `./${BUILD_DIR}/osrm-routed -a CH data.osrm` OR `./${BUILD_DIR}/osrm-routed -a MLD data.osrm`\n\n\n## Testing\n\n### Running Unit tests\n\nUnit tests are contained in `unit_tests/` using boost test and can be build with:\n```bash\ncmake --build ${BUILD_DIR} --target tests\n```\n\nThis will create various tests in `${BUILD_DIR}/unit_tests/`.\n\n### Running Integration Tests\n\nIntegration tests are contained in `features/` using cucumber-js\n\nTo run cucumber tests with the full test matrix across different algorithms (CH, MLD) and load methods (mmap, directly, datastore).\n```bash\nnpm test\n```\n\nTo run cucumber tests for a specific configuration:\n```bash\nnpx cucumber-js -p home -p ch -p datastore\nnpx cucumber-js -p home -p mld -p mmap\n```\n\n**IMPORTANT: Profile changes MUST follow this checklist:**\n\n1. **Cucumber tests**: Every change to a profile (`.lua` files in `profiles/`) must be accompanied by a corresponding cucumber test in `features/` that validates the new or changed behavior.\n   - Run the relevant cucumber tests before committing profile changes:\n     ```bash\n     OSRM_BUILD_DIR=build npx cucumber-js -p home -p mld -p mmap features/<profile>/<feature>.feature\n     ```\n     The test cache is keyed by a content hash of all profiles, binaries, and the feature file, so profile changes automatically invalidate the cache. Old cache directories can optionally be cleaned up with `rm -rf test/cache`.\n   - Run the whole `.feature` file (not just the new scenario) to verify no regressions.\n   - Use the existing test patterns: `routability should be` tables where any column header starting with `forw`, `backw`, or `bothw` (including `*_rate` variants) is an expectation column (not an OSM tag). Headers matching `node/<tag>` apply to node tags. All other columns become OSM way tags.\n   - Do NOT add `@todo` to new scenarios — verify the expected behavior matches actual routing output.\n\n2. **taginfo.json**: If modifying tag handling (adding, removing, or changing how OSM tags are parsed), update `taginfo.json` with any new OSM tags that are now recognized or any tags whose semantics have changed.\n\n3. **OSM Wiki adherence**: Verify that the behavior matches [OSM tagging conventions](https://wiki.openstreetmap.org/wiki/Key:access):\n   - Mode-specific tags (e.g. `bicycle=yes`) override vehicle-level restrictions (e.g. `vehicle=no`)\n   - Directional suffixes (`:forward`/`:backward`) scope a tag to a specific travel direction\n   - The access tag hierarchy is: mode-specific > vehicle-level > general access\n   - When in doubt, consult the relevant OSM wiki pages for the tags being changed\n\n\n## Python Bindings\n\nPython bindings live under `src/python/` using nanobind + scikit-build-core.\n\n### Layout\n\n- `src/python/CMakeLists.txt` — nanobind module definition, installs everything under `osrm/` namespace\n- `src/python/osrm/` — Python package (`__init__.py`, `__main__.py`, `.pyi` stubs)\n- `src/python/src/` — C++ nanobind source files (16 files)\n- `src/python/include/python/` — C++ binding headers (`.hpp`)\n\n### Key details\n\n- `ENABLE_PYTHON_BINDINGS=ON` triggers `add_subdirectory(src/python)` in root CMakeLists.txt\n- Links against the in-tree `osrm` target directly (no FetchContent)\n- Binding headers use `#include \"python/...\"` prefix; OSRM headers use `engine/...` paths (not the `osrm/` forwarding headers), except `osrm/osrm.hpp`\n- LTO disabled for `osrm_ext` target (nanobind `NB_MAKE_OPAQUE` + GCC LTO + `-Werror` = ODR violation)\n- Wheel installs executables to `osrm/bin/`, profiles to `osrm/share/profiles/`; `wheel.exclude` filters out root CMake install artifacts (`lib/`, `include/`, `bin/`, `share/`)\n- `__main__.py` finds executables: `osrm/bin/` (wheel) → `build/*/` (editable) → PATH\n- Type stubs (`osrm_ext.pyi`) auto-generated by `nanobind_add_stub()`; rebuild + commit after C++ changes\n- C++ formatted by project clang-format; Python by ruff (both via `.pre-commit-config.yaml`)\n- When changing the Python binding API (function signatures, classes, exposed attributes, parameter semantics), update [docs/python/api.md](docs/python/api.md) in the same change\n- When changing the build, packaging, or release flow (pyproject.toml, CMake options, cibuildwheel config, `.github/workflows/release-monthly.yml`, `.github/workflows/osrm-backend.yml` Python steps), update [docs/python/development.md](docs/python/development.md) in the same change\n\n### Building & testing\n\n```bash\npip install -e \".[dev]\"                    # editable install\ncd test/data && make                       # build test data\npython -m osrm datastore test/data/ch/monaco\npytest test/python/\n```\n\n## Contributing\n\n<IMPORTANT>\nUse the [PR template](.github/PULL_REQUEST_TEMPLATE.md) to build the PR description.\nRemove irrelevant tasks, but NEVER remove `review` or submit it checked.\nWhen creating PRs via `gh`, do not pass escaped `\\n` in `--body`; use a real multiline body (heredoc or `--body-file`) so GitHub renders actual line breaks.\nDisclose AI participation in the PR description by stating only the harness name and model (e.g. \"GitHub Copilot, Claude Sonnet 4.6\"), add a robot emoji. Do not include links, fake email addresses, or session identifiers.\n\nDo NOT include any AI attribution (e.g. `Co-authored-by:` trailers) in git commit messages.\n</IMPORTANT>\n","category":"root","tokens":2144}]}