# AGENTS.md

HarfBuzz is a low-level text shaping engine with stable public API and ABI expectations. Keep changes narrow, preserve behavior unless the task explicitly requires otherwise, and avoid style-only churn.

## Read first

Before non-trivial work, read:

- `README.md`
- `BUILD.md`
- `TESTING.md`
- `CONFIG.md`
- `RELEASING.md`

## Core rules

- Prefer minimal diffs. Do not rename, reorder, or reformat unrelated code.
- Scope changes to one subsystem or concern when possible. Prefer incremental follow-up commits over large rewrites.
- Public API and ABI are hard constraints. Do not add new API unless explicitly asked. Do not change or remove existing API/ABI unless explicitly asked.
- Follow local conventions in the touched file.
- Preserve optional-feature behavior, reduced-feature builds, and compile-time feature guards.
- Keep out-of-memory behavior in mind. New code should fail safely and follow existing allocation and error-handling patterns.
- Prefer HarfBuzz's established `likely`/`unlikely` and nil-object/null-pattern conventions where they fit the surrounding code.
- Prefer HarfBuzz helpers from `hb-algs.hh` such as `hb_memcpy`, `hb_memcmp`, and `hb_memset` over raw `memcpy`, `memcmp`, and `memset` where those helpers are available.
- Do not introduce STL containers in library code. Follow HarfBuzz container and utility patterns instead.
- Leave unrelated user changes and untracked artifacts alone.

## Repo map

- `src/`: core library code.
- `src/OT/`: OpenType shaping/layout internals.
- `src/graph/`: subsetter graph helpers.
- `src/rust/`: HarfRust and fontations integration.
- `util/`: installed tools such as `hb-shape`, `hb-view`, `hb-info`, `hb-subset`, `hb-vector`, `hb-raster`.
- `test/`: API, shape, subset, vector, threads, and fuzzing tests.
- `perf/`: benchmarks.
- `docs/`: API/manual docs.

## Build and verify

Default flow:

```sh
meson setup build --reconfigure
meson compile -C build
meson test -C build
```

If `build/` does not exist yet, omit `--reconfigure`.

General expectations:

- Rebuild touched targets and make sure there are no new warnings.
- For shaping changes, run at least `meson test -C build --suite shape`.
- For subset changes, run at least `meson test -C build --suite subset`.
- For API changes, run at least `meson test -C build --suite api`.
- For `util/` changes, rebuild the relevant tool and exercise it on a small sample.
- When fixing a bug or hardening a parser, add or update the nearest regression test, fuzz seed, fuzz target, or expected output when practical.
- Treat portability regressions as real bugs. HarfBuzz regularly fixes GCC, Clang, MSVC, 32/64-bit, and reduced-feature build issues.

## Change-specific guidance

- Shaping work: check nearby tests under `test/shape/`.
- Subsetting work: check `test/subset/`; `src/graph/` is part of the subsetter.
- Raster/vector/SVG work: prefer extracting helpers and splitting oversized files by responsibility instead of adding more branching to large translation units.
- Fuzzing/parser-hardening work: inspect `test/fuzzing/` and existing guardrail code first. Fuzzers run with failing-malloc enabled, so treat out-of-memory handling as part of the exercised surface.
  For experimental libraries such as raster, vector, and gpu, the minimum bar under failing-malloc is still no crashes, no out-of-bounds access, and no memory corruption. Best-effort early failure is acceptable; do not add complex rollback logic just to preserve partial work after OOM.
- Build-system work: keep Meson options, summaries, installed tools, tests, and dependent targets in sync. If packaging or cross-build behavior is affected, inspect CMake too.
- Generated data work: update the generator or makefile flow, then regenerate outputs. Do not hand-edit generated tables unless the task explicitly calls for it.
- Rust integration work: inspect `src/rust/meson.build` and `src/rust/Cargo.toml` before changing build glue.

For API work:

- Public API lives in `src/hb-*.h`, not `.hh`.
- If new API is explicitly requested, document it in `NEWS`, add `XSince: REPLACEME` in the public header docs, and update `docs/harfbuzz-sections.txt` and `docs/harfbuzz-docs.xml` when needed.
- If functionality becomes user-visible through tools or libraries, update the relevant docs and install/build wiring in the same change when appropriate.
- Keep documentation placement consistent with local practice: public API docs may live in source files, while generated section indexes live in `docs/`.

## Avoid

- Do not make broad formatting passes.
- Do not silently change Meson defaults or feature defaults unless required.
- Do not assume generated outputs, local fonts, or untracked artifacts are disposable.
- Do not disable tests to get a green run without documenting why.

## Working mindset

- Reproduce the issue before fixing it when practical.
- Understand root cause before writing code. If there is real ambiguity, ask instead of guessing.
- Validate simplifications carefully. This repo has many targeted reverts where a local cleanup broke broader behavior.
- If code looks unusually complex, it probably handles a real edge case. Check history before simplifying it.
- Centralize duplicated parsing, caching, or helper logic once duplication starts spreading.

## Commit guidance

- Before any commit, run the entire test suite with `meson test -C build`.
- Exception: simple documentation-only or CI-only changes may be committed without running tests if they do not affect code, build logic, generated outputs, or test inputs.
- Keep each commit focused on a single issue or concern. Do not combine unrelated fixes, API renames, refactors, or behavior changes into one commit unless the user explicitly asks for that.
- Never push to the remote repository. The user handles pushing.
- Use descriptive commit messages with consistent bracketed subsystem prefixes such as `[subset]`, `[raster]`, `[util]`, or `[meson]`.
- Wrap commit message bodies to about 70 columns.
- For multi-line commit messages, write the message from a file or editor-backed input. Do not pass escaped `\n` sequences via shell `-m` arguments.
- Explain root cause, fix, and testing in the commit body when testing was actually performed or is relevant.
- When relevant, link issues or PRs with trailers such as `Fixes:`.
- Always include an `Assisted-by:` or `Co-Authored-By` trailer on commits you write through the agent.

## Wisdom

- HarfBuzz sits at the bottom of the stack. Small changes can have very wide effects.
- If code looks unusually complex, assume it handles a real edge case until proven otherwise.
- Simplifications and optimizations are common sources of later reverts; validate them broadly.
- Prefer reproducible regressions over fix-only changes.
- When duplication starts to spread, extract the shared helper before it calcifies.
