Skip to content

Latest commit

 

History

History
118 lines (86 loc) · 3.97 KB

AGENTS.md

File metadata and controls

118 lines (86 loc) · 3.97 KB

langid.cpp Agent Conventions

Read CONTRIBUTING.md for contribution policy, review gates, and coding style. This file is only the local command/automation convention sheet for coding agents.

notes/PLAN.md (implementation spec) and notes/DECISIONS.md (decision log) are maintainer-local working notes, not in the repository; code comments cite them by section and decision number.

Python

  • ALWAYS use uv run for every Python invocation. Never bare python, python3, or pip.
  • Use uv pip for packages, uv sync for envs, and uv run for scripts.
  • Per-family reference environments live under scripts/envs/<family>/ and are invoked as:
uv run --project scripts/envs/<family> scripts/<script>.py ...
  • Tools with PEP-723 headers run as uv run scripts/<tool>.py.

Build

  • After C++ changes, run:
cmake --build build --target langid-cli
  • The default posture is a static liblangid + static ggml, so build/bin/langid-cli is self-contained. -DLANGID_BUILD_SHARED=ON is the packaging/binding configuration.

Formatting

  • Format our C/C++ before committing. The formatter is pinned and fetched via uvx, so do not rely on a system clang-format:
scripts/ci/clang-format.sh            # format our tree in place (default)
scripts/ci/clang-format.sh --check    # verify, no changes
  • Scope is our code only. The vendored tree (ggml/) and verbatim upstream copies (examples/common/dr_wav.h) are never formatted. CI gates our C/C++ in .github/workflows/clang-format.yml.

C ABI Exception Discipline

No C++ exception may escape a public entry point.

  • A new public entry point must either route through an api_guard_* wrapper (src/langid.cpp) or be nothrow by construction. Accessors are not pure reads; guard them.
  • Entry points with ownership out-params enforce "non-OK => *out == NULL, nothing leaked" in their forwarders on every error return.
  • Teardown never uses raw ggml_backend_free / ggml_backend_buffer_free / ggml_backend_sched_free in library code: use langid::safe_* from src/langid-backend.h. tests/lint_teardown.cmake fails CI on violations.
  • Host log callbacks are contained at the emission site (langid_log_invoke).
  • The LANGID_TEST_* fault hooks (_DEV_INIT_THROW, _TEARDOWN_THROW) intentionally ship in release artifacts. Present-but-empty values are inert.
  • Caller-supplied enum fields are read as raw ints (enum_field_raw) and validated before any enum-typed load: a C caller can store any int there.

Verification

CONTRIBUTING.md has the review-gate table; docs/validation.md explains what each gate proves. The commands:

  • Default suite (CI runs this on Linux and macOS, plus an ASan+UBSan lane):
ctest --test-dir build --output-on-failure
  • Install + link manifest, both postures (CI runs both):
cmake --install build --prefix /tmp/langid-static
python3 scripts/ci/link_smoke.py --prefix /tmp/langid-static
  • End-to-end numerical checks (local only: needs a converted GGUF and the pinned reference env). Required for any change that can move numerics — graph, front end, converter, loader, ggml pin:
uv run scripts/validate.py all --family <f>
  • Dataset gate (local only): does the C++ engine make the same decisions as the reference over the full FLEURS sweep?
uv run scripts/eval/compare.py \
  reports/eval/ref-speechbrain-untrimmed.jsonl \
  reports/eval/cpp-f32-untrimmed.jsonl
  • Manual tensor debugging:
uv run scripts/compare_tensors.py ...
  • Never suppress test failures without root cause analysis. A tolerance is widened only with the mechanism named in the tolerance file's _comment.

Git Hygiene

  • Do not commit, push, tag, create remotes, create pull requests, or comment on pull requests unless the user explicitly asks for that action.
  • Do not reformat unrelated code in the same change as a behavior fix.
  • Model files, GGUFs, reference dumps, and dataset audio are never committed.