This file is for AI agents working in this repo. It records hard invariants and rules that must survive across sessions — self-contained, no need to read the design doc to follow them. User-facing introduction and usage lives in
README.md(do not move user-facing content into this file); this file is strictly "how to change code correctly."Doc map (each has one job; don't mix them):
README.md— user-facing: what the project is, how to build, CLI usage, data compliance.CLAUDE.md(this file) — AI-agent-facing: hard conventions, invariants, minefields..notes/— local working docs (gitignored, not committed):README.mdis the directory index,DESIGN.mdis the full design document,plans//records//research/are historical plans and records. Start from.notes/README.mdwhen you need background.docs/— public-facing docs (CONTRIBUTING, algorithm articles, etc.; committed).
One-line background (details in README / DESIGN): a realistic/compliant flight route engine that parses X-Plane 12 native navigation data (including ARINC 424 procedures), builds a directed graph, and finds candidate routes respecting aviation constraints via A* + Yen K-shortest.
- Conversations, comments, documentation, and commit messages default to Simplified Chinese; docs prefer Chinese.
- Exceptions (keep in original): code identifiers, existing code style, technical proper nouns/commands/APIs, and code comments use English.
- Modern C++20; Google C++ Style (format base, clang-format
BasedOnStyle: Google)- C++ Core Guidelines (semantic correctness).
- File names
snake_case, extensions.h/.cc; namespacebf. - Error handling uses the project's own
bf::Result<T, E>(lib/core/result.h); expected failures (no route found, missing data) go throughResult, exceptions are only for truly exceptional situations. No barenew/delete, nogoto, no catch-by-value, nostatic/global mutable state (v2's static-sharing bugs were one motivation for the rewrite). - JSON output uses RapidJSON
Writer(SAX streaming, auto-escaping); no hand-rolled strings, no nlohmann.
- After
NavDatabase::Open()succeeds, the instance is read-only, with the sole exception of internal synchronized caches;FindRoutes()/MsaForAirport()areconstand safe for concurrent calls on the same instance. - On-demand:
procedure_cache_is guarded bycache_mutex_(double-checked locking), only locking map lookup/insert, never disk I/O; append-only +unique_ptrvalues → returned pointers are stable across rehash. - Eager:
FetchAllfills the cache atOpentime then freezes it;ProceduresFordoes lock-free reads (no insert = no rehash = no race). - Eager mode is "frozen, lock-free reads" — it is not missing locks. Do not flag it in audits.
- After touching concurrency-related code, must pass the tsan preset:
ctest --preset tsan.
- ① Program semver (CMake
project VERSION→lib/core/version.h.in'skBravoFinderVersion→bf --version). - ② Unified container
format_version(one single version, magic "BFDB"; mismatch →Result::Err(kFormatMismatch)). Three sections (graph/cifp/detail) share one file and one version; no per-section version. - ③ Program semver + source_loader + AIRAC cycle are written into the container header
as provenance (
buildremoved — it was an X-Plane-only field). - Cache disk layout change → bump container
format_version; release behavior change → bump program semver. Read-side / internal-only changes do not change the layout and do not bump.
- Real data, no mocks. Real AIRAC data lives under
navdata/(gitignored), located viaBRAVOFINDER_NAVDATA(defaultnavdata/); missing data →SKIP, never mock as a substitute. - Unit tests use hand-constructed minimal real-format samples (not mock objects).
- For airports without CIFP procedures, test with KIKR / KNWL.
- Real navigation data /
*.dat/*.bfdbmust never be committed (Jeppesen copyright, redistribution prohibited).
User-facing CLI usage (
bf build/bf routearguments) lives in README; this section only lists the presets you must run after making changes. Always use--preset, never the path form.
cmake --preset debug # Debug + ASan/UBSan + warnings-as-errors
cmake --preset release # Release -O2
cmake --preset tsan # ThreadSanitizer (concurrency verification)
cmake --build --preset <debug|release|tsan>
ctest --preset <debug|release|tsan>
On Windows MSVC, windows-debug / windows-release presets are available (no
sanitizers; used in CI).
Dependencies are pure CMake + FetchContent (Catch2 v3 / CLI11 / RapidJSON); no vendoring,
no vcpkg.
ctest runs each case in its own process. Cache round-trip tests (bfdb: / cifp section:, 11 cases) each take 20–40s and dominate wall-clock time — only run them when
the cache disk layout / serialization changed. For day-to-day work, pick by scope:
ctest --preset unit # pure logic unit tests (~1.4s): algorithm/constraint/pure-function changes only
ctest --preset quick # exclude cache tests (~12s): routing/query/constraint changes but cache layout untouched
ctest --preset debug # full suite (~56s): cache layout/serialization changed, or pre-release
ctest --preset tsan # must run after any concurrency-related change (Contract B)
(unit/quick are based on the debug config, with ASan/UBSan; they just use filter to
exclude the slow cache tests.)
- Commits use English Conventional Commits; body paragraphs are single unwrapped lines; keep the Claude co-author signature.
- For complex milestones, align on the approach first, then implement; at the end of each major task, do a docs / memory handoff.