


Change a Database Storage Engine Without Breaking Speed or Compatibility
Use when an AI edits a database storage engine. It keeps error handling and concurrency correct, speeds up frequently run code only with benchmark proof, keeps APIs, file formats, and builds compatible, and requires repeatable tests before approving a change.
To use this AI rule
## Handle Errors and Concurrency Correctly in Readable Code
Write clear, self-documenting code with meaningful names and comments for non-obvious invariants.
Prefer readable control flow over clever tricks that offer only marginal speed.
Follow the repository's formatter, naming rules, and structural patterns.
Use the project's standard status or error type consistently.
Propagate failures with enough context to identify the failed operation.
Never silently discard an error or unchecked status value.
Avoid assertions for recoverable failures in production paths.
Cover invalid input, resource exhaustion, I/O failure, corruption, and partial progress.
Preserve database semantics such as key ordering, snapshot visibility, durability, and recovery behavior.
Document synchronization assumptions beside the data they protect.
Review locking, atomic operations, memory ordering, race risk, and deadlock risk together.
Keep resource cleanup explicit across success, error, cancellation, and shutdown paths.
Keep comments focused on local contracts rather than one caller's current rationale.
Deduplicate repeated logic when a shared abstraction has a stable, coherent responsibility.
Do not mark a correctness-sensitive change merge-ready until failure paths and concurrency behavior are tested.
## Speed Up Code by How Often It Runs, Proven with Benchmarks
Treat performance awareness as a requirement for storage-engine work.
Establish correctness before micro-optimization, while choosing sound algorithms and data structures from the start.
Classify affected code by execution frequency:
- Hot paths multiply every allocation, copy, branch, and cache miss across frequent operations.
- Warm paths require a measured balance between clarity and speed.
- Cold paths favor maintainability unless profiling shows material cost.
Back performance claims with benchmarks and profiling data.
Compare against an appropriate baseline and report workload, configuration, and variance.
Reduce dynamic allocation in hot paths through reuse, preallocation, arenas, or memory pools when justified.
Prefer moves, views, references, and in-place operations over unnecessary copies.
Arrange data and access patterns for locality and avoid false sharing.
Hoist invariant work, batch repeated operations, and reduce unpredictable branches.
Use branch-likelihood hints only for genuinely rare or costly cases, not popular configurations.
Enable compiler vectorization through suitable data layout before reaching for explicit intrinsics.
Use explicit SIMD only where supported, measured, and maintainable.
Apply RAII and clear ownership to prevent leaks while preserving low overhead.
Do not retain a complex optimization that lacks reproducible benefit.
## Design Compatible APIs with Single-Purpose Options
Keep high-level policy in the caller or policy layer.
Expose precise, reusable mechanisms from lower layers.
Do not make generic code depend on one caller's identity or rationale.
Give each flag or parameter one coherent behavior.
Replace booleans that bundle ownership, caching, I/O mode, and prefetching with explicit fields or an options object.
Do not infer policy from incidental implementation details such as cache handles or reader state.
Use assertions, narrower interfaces, and clearer names to make contracts enforceable.
Make new APIs consistent with established naming, parameter order, return types, and error handling.
Use type-safe options, including fixed-width integer types and scoped enums where appropriate.
Validate option values and return clear errors.
Make dynamic configuration changes thread-safe and verify when they take effect.
Preserve source and binary compatibility unless a breaking change has exceptional justification.
Review layout, symbols, and calling conventions when a public binary interface is exposed.
Deprecate through the documented multi-release process and provide migration guidance.
Document public APIs with usage, parameter meaning, thread-safety rules, performance costs, and compatibility notes.
Do not export third-party implementation types through a public API.
## Review Write-Ahead Logs and Other Risky Parts Most Deeply
Apply the deepest review to write-ahead logging, memory tables, compaction, recovery, and other database-core paths.
Test core changes under varied configurations, compaction styles, failures, and concurrent workloads.
Ensure compaction respects configured limits and handles empty or single-file cases.
Treat public headers as the highest compatibility-impact surface.
Treat persistent table and block formats as long-lived data contracts.
Verify checksums across compression choices, block sizes, corruption cases, and compatibility boundaries.
Test iterator seek, next, previous, deletion, and endpoint semantics.
Keep cache keys unique and ensure prefetching respects resource limits.
Benchmark table, cache, and utility changes that can run in hot paths.
Make cache synchronization, memory ownership, and eviction policy explicit.
Keep optional utilities isolated from database internals.
For options, verify type safety, validation, deprecation, and thread-safe dynamic updates.
For internal utilities, test overflow, underflow, invalid input, and assertion contracts.
Do not approve high-risk format, recovery, compaction, or cache changes without unit, integration, stress, and benchmark evidence.
## Keep All Build Systems in Sync and Build on Every Supported OS
Maintain every supported build system when adding or removing a source file.
Update the canonical source manifest first and regenerate derived build files with the approved generator.
Do not hand-edit a generated internal build file.
Search all build definitions, languages, documentation, and implementations for affected references.
Use the host's CPU count for parallel builds within resource limits.
Prevent mixed build modes from reusing incompatible object files.
Enable the build system's automatic clean-on-configuration-change mechanism for manual builds.
Support the project's operating-system, compiler, standard-library, sanitizer, and build-mode matrix.
Expect Linux, macOS, Windows, native and cross-compilers, release builds, sanitizers, unity builds, and language bindings where configured.
Prefer the project's portability abstractions over direct platform APIs.
Guard unavoidable platform-specific headers, calls, attributes, and built-ins.
Include every standard header directly instead of relying on transitive includes.
Ensure production and stress binaries build without runtime type information when that is a project constraint.
Restrict runtime downcasts to tests; use the project's checked static-cast helper elsewhere.
Run source checks that reject unsupported characters and other CI-incompatible content.
Use ASCII punctuation in source comments and strings when the repository requires it.
## Write Reproducible Tests Without Relying on Sleeps
Match test depth to risk: unit tests for isolated behavior, integration tests for interactions, and stress tests for concurrency and performance.
Cover boundaries, error paths, recovery, platform differences, and regression cases.
Use table-driven cases when inputs differ but the tested contract is shared.
Extract helpers for repeated construction, round trips, and assertion sequences.
Keep deterministic edge cases separate from randomized coverage.
Prefer randomized sampling over exhaustive parameter products when it gives broader useful coverage.
Use the project's random source and print the seed so failures are reproducible.
Do not sleep while waiting for concurrent events.
Use synchronization points or explicit signals to control thread progress.
Cap individual unit-test execution with a defined timeout.
Run a small number of focused tests serially and larger sets through the parallel test harness.
Stress new concurrency tests repeatedly under forced context switching.
Investigate CI-only flakes with the project's dedicated reproduction tooling.
Test every supported platform affected by paths, APIs, compilers, or build flags.
Ensure test failures report enough state to reproduce the triggering configuration.
Add new configuration options and performance features to stress and benchmark coverage.
Review updated tests for duplication and accidental shared state before submission.
## Add License Headers and Keep Docs and Release Notes in Sync
Give every new source file the repository's required license header.
Preserve upstream copyright notices in derived files in addition to the project header.
Use the correct comment prefix for each source language.
Do not replace a required dual-license designation with a generic rights statement.
Run automatic formatting after changes and inspect the resulting diff.
Run dependency-maintenance tools and reject unrelated manifest churn.
When adding a feature, evaluate useful metrics without adding hot-path regression.
Expose performance-related features through the standard benchmark tool.
Keep release notes short, external, and focused on user-visible behavior.
Document component designs in the subsystem's index and focused chapters.
Ensure generated sites or posts reference valid author metadata when required.
For a new API, option, or deprecation, follow the repository's dedicated procedure.
Update migration guidance before removing a deprecated surface.
Keep implementation, build metadata, tests, documentation, and release notes synchronized.
Do not leave a new source file reachable from one build system but absent from another.
## Pass a Clean Build and Tests Before Approving a Change
Review correctness, testing, performance, compatibility, contract boundaries, style, and documentation as separate gates.
Require benchmark results for performance-sensitive changes.
Require stress coverage for new concurrent or configurable behavior.
Run the full clean build-and-test target after focused checks pass.
Run the stricter status-checking build that detects ignored error results.
Use automatic clean mode so changed build flags cannot reuse stale objects.
Monitor long test runs through the build system's machine-readable progress output.
Track phase, completed work, total work, failures, percent, and bounded failure details.
Distinguish assertion failures from crashes, signals, timeouts, and infrastructure errors.
Retain benchmark parameters and test configurations with the reported evidence.
Build benchmarks in release mode for measurement.
Switch to a debug build when diagnosing a crash, then rebuild cleanly before measuring again.
Run format, source, build, test, sanitizer, and platform checks required by the affected surface.
Re-run directly affected gates after review fixes.
Do not narrow a repository-wide consistency search merely because some matches appear unlikely.
Approve only when code, contracts, tests, build metadata, documentation, and measured evidence agree.
