


Make Small Fixes to a Low-Level Library Without Breaking Its Public API
Use when an AI fixes or changes a low-level system library. It keeps changes small, leaves the public API and ABI alone unless asked, runs the build and the affected subsystem's tests, fails safely on memory errors, and never pushes to the remote.
To use this AI rule
## Keep changes small and leave the public API and ABI alone unless asked
Treat a stable public application programming interface and application binary interface as hard constraints.
### Before Editing
- Read the repository's build, testing, configuration, contribution, and release documentation for non-trivial work.
- Identify the single subsystem or concern that owns the requested change.
- Follow local conventions in every touched file.
- Preserve unrelated user changes and untracked artifacts.
### Change Boundaries
- Prefer minimal diffs and incremental follow-up changes over broad rewrites.
- Do not rename, reorder, reformat, or clean up unrelated code.
- Do not add a new public interface unless explicitly requested.
- Do not change or remove an existing public interface or binary contract unless explicitly requested.
- Preserve optional-feature behavior, reduced-feature builds, and compile-time guards.
- Do not silently change build or feature defaults.
When apparently awkward code sits on a compatibility boundary, assume it may cover a real edge case until tests, history, and surrounding behavior show otherwise.
## Build with the standard flow and run the changed subsystem's tests
Use the repository's standard configure, compile, and test flow before relying on specialized checks.
### Default Sequence
1. Configure or reconfigure the designated build directory.
2. Compile the affected targets.
3. Run the test suite appropriate to the current stage.
4. Confirm the build introduces no new warnings.
If the build directory does not exist, use initial setup rather than a reconfiguration-only path. Rebuild touched targets after every material code change.
### Minimum Targeted Checks
- For transformation or shaping logic, run its dedicated behavior suite.
- For reduction, subsetting, or graph work, run the corresponding subsystem suite.
- For public-interface work, run the application programming interface suite.
- For command-line tool work, rebuild the relevant tool and exercise it with a small representative sample.
- For a bug fix or parser hardening, add or update the nearest regression test, fuzz input, fuzz target, or expected output when practical.
Targeted checks accelerate iteration but do not replace broader validation when shared behavior or release readiness is affected.
## Choose where to change code by subsystem and follow project patterns
Understand adjacent responsibilities before choosing where to modify code.
### Responsibility Boundaries
- Keep core library behavior distinct from installed tools, benchmarks, documentation, language bindings, and experimental components.
- Treat graph helpers as part of the reduction pipeline when they participate in its behavior.
- For raster, vector, graphics, or similar oversized translation units, prefer extracting focused helpers and splitting by responsibility instead of adding more branching.
- For a language integration, inspect both the native build definition and the language package manifest before changing build glue.
### Existing Conventions
- Use the project's established allocation, error, branch-prediction, null-object, container, and utility patterns.
- Prefer project wrappers over raw platform primitives when wrappers encode portability or safety behavior.
- Do not introduce a foreign container library into core code when the project has established containers and utilities.
- Add public-interface documentation in the repository's customary source or documentation location.
Centralize duplicated parsing, caching, or helper logic once duplication begins spreading, but do not turn a focused fix into an unrelated architecture rewrite.
## Fail safely on memory errors and hostile input on every supported platform
Treat allocation failure, hostile input, compiler diversity, and reduced-feature builds as normal parts of the supported surface.
### Allocation and Parser Safety
- Follow existing allocation and error-handling patterns so new code fails safely under memory pressure.
- Inspect existing parser guardrails and fuzz infrastructure before hardening input handling.
- Under injected allocation failure, the minimum acceptable result is no crash, out-of-bounds access, or memory corruption.
- For experimental components, best-effort early failure is acceptable under memory pressure.
- Do not add complex rollback logic solely to preserve partial work after allocation failure unless the component's contract requires it.
### Portability
- Treat compiler, operating-system, architecture-width, cross-build, and reduced-feature regressions as real bugs.
- Validate assumptions across the toolchains and integer widths supported by the project.
- Keep compile-time feature guards and fallback paths exercised.
- When simplifying low-level code, check whether the original complexity handled alignment, overflow, lifetime, aliasing, or platform-specific behavior.
Prefer a reproducible regression over a fix-only change that cannot demonstrate the original failure.
## Regenerate generated tables from their generator instead of editing them by hand
Keep every build description and generated output synchronized with the source change.
### Build-System Changes
- Update options, configuration summaries, installed tools, tests, and dependent targets together.
- If packaging or cross-build behavior is affected, inspect every supported build system rather than changing only the primary one.
- Preserve option defaults unless the task explicitly requires a default change.
- Validate both enabled and disabled forms of affected optional features.
### Generated Data
- Modify the generator, source data, or makefile flow, then regenerate outputs.
- Do not hand-edit generated tables or indexes unless the task explicitly requires it.
- Do not assume generated outputs, local test assets, fonts, or untracked artifacts are disposable.
- Review regenerated diffs for unexpected breadth or nondeterministic changes.
If a generator change affects public data or test expectations, update the relevant tests and documentation in the same focused change.
## Add public API only when asked, with a version marker and docs
Handle user-visible behavior as a coordinated code, documentation, versioning, and build-wiring change.
### Public Interface Gate
- Keep public declarations in the designated public headers or modules, not internal implementation files.
- Add new public surface only when the request explicitly authorizes it.
- When a new interface is authorized, add the repository's required version marker and release-note entry.
- Update generated section indexes, documentation manifests, or reference lists through their approved workflow.
- Preserve binary layout, symbol visibility, calling conventions, and source compatibility unless a breaking change is explicitly approved.
### User-Visible Behavior
- Update relevant documentation when functionality becomes visible through a library or installed tool.
- Keep installation and build wiring synchronized with newly exposed behavior.
- Place public-interface documentation and generated indexes where local practice requires them.
- Do not disable a failing test merely to obtain a green run; document a justified exception and its impact.
## Find the root cause first and commit without pushing
Prove the cause and the result before presenting a change as complete.
### Working Method
1. Reproduce the issue when practical.
2. Understand the root cause before writing the fix.
3. If material ambiguity remains, ask rather than guessing.
4. Inspect history before simplifying code that appears unusually complex.
5. Add or update the closest regression coverage.
6. Validate the changed subsystem, affected configurations, and broader behavior.
### Commit Discipline
- Run the complete test suite before committing code, build logic, generated outputs, or test inputs.
- Documentation-only or continuous-integration-only changes may skip full tests only when they cannot affect those areas; report the omission.
- Keep each commit focused on one issue or concern.
- Never push to the remote repository; leave pushing to the authorized human.
- Use the repository's subsystem prefix, attribution trailers, and message conventions.
- For a multi-line commit message, use a file or editor-backed input rather than escaped newline sequences.
- Describe root cause, fix, and testing only when supported by the work actually performed.
At handoff, report the changed scope, tests run, warnings, unsupported configurations, unresolved risks, and any validation not performed.
