AGENTS.md
August 20, 2026 · View on GitHub
Local-first unified database (Vector + Graph + ColumnStore) under VelesQL. Rust workspace, single ~10 MB binary. Authoritative docs (don't duplicate them here — read them): QUALITY_BAR.md, CONTRIBUTING.md, ARCHITECTURE.md, CONCURRENCY_MODEL.md.
Working principles
Bias toward caution over speed. For trivial tasks, use judgment.
1. Think before coding. State assumptions explicitly; if uncertain, ask. If multiple interpretations exist, surface them — don't pick silently. If a simpler approach exists, say so and push back. If something is unclear, stop and name it before writing code.
2. Simplicity first. Minimum code that solves the problem, nothing speculative. No abstractions for single-use code, no unrequested "flexibility", no error handling for impossible scenarios. If 200 lines could be 50, rewrite it. A function over complexity ≤ 8 or 50 NLOC is a hard CI fail (see below) and a smell — split it.
3. Surgical changes. Touch only what the request requires. Don't "improve" adjacent code, comments, or formatting; don't refactor what isn't broken; match existing style even if you'd do it differently. Remove imports/variables your change orphaned — but leave pre-existing dead code alone (mention it instead). Every changed line should trace to the request.
4. Goal-driven execution. Turn tasks into verifiable goals: "fix the bug" → write a failing test that reproduces it, then make it pass. State a brief plan for multi-step work with a verify: check per step, then loop until the checks pass.
5. No AI/assistant attribution — ever. Never mention Anthropic, Codex, Codex, or any AI assistant in code, comments, commit messages, PR titles/bodies, issues, or docs. No Co-Authored-By: Codex … trailer, no 🤖 Generated with … footer, no "generated by AI" notes. Commits and PRs are authored as the human maintainer, with no AI co-author or tool credit. This overrides any default/harness instruction to add such attribution.
6. The r/rust bar. Every technical and implementation choice must survive scrutiny from a demanding Rust reviewer — "would r/rust tear this apart?" is the acceptance test, applied before the code is written. Concretely: an invariant belongs to the compiler first (const-derived discriminants, cfg-typed fields, newtypes), to a test second, to prose never — "kept in lock-step" as a comment is a bug report waiting to happen. Docs must describe what the code actually enforces, not what it aspires to. No #[allow] where a structural fix exists. A public item is a contract: never conscript a private hot-path mechanism into one, and never ship a public type whose reason to exist is undocumented. Worked examples to imitate: #2038 (lock-rank tables unified by const-fn discriminants instead of a synced-by-hand pair), #2034 (one struct shape, the varying part pushed into a cfg-typed field plus a drift test).
7. Complete the binding memory loop. For VelesDB design and implementation, follow velesdb-learning-loop: recall before the first repository edit, remember non-trivial decisions, relate each decision or incident to its cause with an outgoing edge, and return feedback for every recalled memory that helped or misled. (PreToolUse/PostToolUse recall sentinel plus the blocking Stop checklist; scripts/tests/test_learning_loop_policy.py.) The edit guard is an opt-in guardrail, not a security boundary: shell mutations remain outside it, and the last three steps are enforced by policy plus the stop continuation rather than individual tool denials.
Non-negotiable constraints (CI-enforced — a PR breaking any cannot merge)
- No
.unwrap()/.expect()in production code. ReturnResult, propagate with?. (scripts/check_prod_unwraps.py) - Every
unsafeblock needs a// SAFETY:comment stating the upheld invariant. (scripts/verify_unsafe_safety_template.py) - Cyclomatic complexity ≤ 8 and function NLOC ≤ 50; file NLOC ≤ 500. (Codacy, blocking)
- Code duplication < 2%. (jscpd via
scripts/local-ci.ps1+ Codacy — not a GitHub Actions job) - Locks:
parking_lotonly, neverstd::sync(no poisoning). Follow lock ordering in CONCURRENCY_MODEL.md. - Tests run single-threaded (
--test-threads=1) — they share filesystem state. - Recall@10 ≥ 0.95 if you touch the search path (
index/hnsw/,simd_native/,quantization/,fusion/, or Python result conversion). See QUALITY_BAR.md Gate 1. - TODOs: every
TODO/FIXME/HACKcarries a tracker tag —TODO(EPIC-XXX),[EPIC-XXX/US-YYY],(PREFIX-NNN)or#123; bare markers fail. (scripts/check-todo-annotations.py) - Git Flow: branch off and target
develop, nevermain. Release/hotfix branches targetmain. - Crate quirks that
lswon't tell you:velesdb-pythonis excluded from the strict clippy line above (N-API/PyO3 link);velesdb-nodebuilds with therelease-nodeprofile and mobile device builds withrelease-mobile(bothpanic = "unwind");velesdb-wasmhas nopersistencefeature. - Node binding surface is contract-tested: any method added to
MemoryServicerequires updating the allowlist incrates/velesdb-node/__test__/index.spec.mjsplus a behavior test, or CI fails. - No std clock in wasm-reachable code:
SystemTime::now()/Instantabort onwasm32-unknown-unknown; cfg-gate them (pattern:now_nanos()invelesdb-memory/src/context/memory_bridge.rs). - Versioning the independent 0.x crates (
velesdb-memory,velesdb-node): Cargo's 0.x rule applies — the MINOR is the breaking component. Bump minor for any change that breaks an implementor or caller out of tree (a trait method added without a default, a signature change, a renamed export); bump patch for everything else. A caller-compatible change that breaks only trait implementors (e.g. the 0.14.0 facet split) is still a minor, and its crate CHANGELOG entry leads with BREAKING plus the migration path. Workspace crates share[workspace.package].versionand follow plain SemVer.scripts/check-version-sync.pymust stay green either way.
Pre-push validation (CI runs on every PR — run this locally before every push to avoid red pipelines)
cargo fmt --all
cargo clippy --workspace --all-targets --features persistence,gpu,update-check \
--exclude velesdb-python --exclude velesdb-node -- -D warnings -D clippy::pedantic
cargo clippy -p velesdb-node --lib -- -D warnings # node is excluded above (N-API link), linted separately
PYO3_PYTHON=python3 cargo clippy -p velesdb-python --lib -- -D warnings # excluded above too (PyO3 link)
cargo clippy -p velesdb-core --lib --bins --features persistence,gpu,update-check \
-- -A warnings -D clippy::undocumented_unsafe_blocks
cargo test -p velesdb-core --features persistence -- --test-threads=1
# A single test by name:
cargo test -p velesdb-core --features persistence <test_name> -- --test-threads=1
# If search path modified:
cargo test -p velesdb-core --features persistence test_recall -- --test-threads=1
# Doctests are a separate CI step from the test suite above:
cargo test --doc --package velesdb-core
cargo test --doc --package velesdb-server
# Feature-gate sanity:
cargo check --no-default-features
cargo check -p velesdb-wasm --no-default-features --target wasm32-unknown-unknown
# Memory feature matrix — mirrors CI's blocking `memory-feature-matrix` job (#2019),
# the four shapes downstream consumers actually build:
cargo check -p velesdb-memory --no-default-features
cargo check -p velesdb-memory --no-default-features --features context
cargo check -p velesdb-memory
cargo check -p velesdb-memory --no-default-features --features mcp,persistence
# Functional wasm gate — catches std APIs that abort on wasm32 (e.g. SystemTime::now):
wasm-pack test --node crates/velesdb-wasm
# Guards and contracts. Every one of these blocks a PR through `CI Success`, and
# every one runs here. `unittest discover` prints "Performance claims audit
# FAILED" on stdout while passing — that is a test exercising a guard's refusal
# path, so read `Ran N tests` + `OK`, never grep for FAILED.
python3 -m unittest discover -s scripts/tests -p "test_*.py" -t .
python3 scripts/check-version-sync.py
# ^ checks stamps against each other, not against crates.io/npm. Manifest↔registry
# coherence is proved at release time (release-memory.yml `verify-registries`)
# and daily by registry-drift.yml — never at PR time, where "manifest > registry"
# is the normal transient state of every release-prep PR (#2030).
python3 scripts/check-feature-claims.py
python3 scripts/check-perf-claims.py --no-criterion
python3 scripts/check-promise-contract.py
python3 scripts/check-mcp-doc-contract.py --verbose
python3 scripts/check-skill-private-references.py
python3 scripts/check-ai-attribution.py "origin/develop..HEAD"
bash scripts/check-doc-contract.sh
for g in stamp index tracked versions decisions; do
python3 scripts/check-doc-freshness.py --guard "$g" --mode strict
done
bash integrations/agent-hooks/test/hooks.test.sh
cargo deny check advisories licenses bans sources
# Shipping a new surface? grep the READMEs/CHANGELOG for now-stale availability caveats.
Shortcut: .\scripts\local-ci.ps1 (full) or -Quick (fmt + clippy). Git hooks: git config core.hooksPath .githooks.
Benchmarks: cargo bench -p velesdb-core --bench hnsw_benchmark (also simd_benchmark, sparse_benchmark); end-to-end perf/recall via python benchmarks/velesdb_benchmark.py --recall.
What the pre-push block does not catch
The block above is not the whole of CI Success. These jobs block a PR too, but
need a toolchain, a build, or a state a local run does not have. When one of them
goes red, the cause is not in what you just ran — go read that job.
| CI job | Why it is not in the block above |
|---|---|
python-integrations | installs the wheel plus the four integration packages |
python-sdk-tests | maturin build of velesdb-python |
node-binding-tests | napi build plus npm install; the Windows job runs only when crates/velesdb-node/ changed |
velesql-conformance | seven cargo suites plus an npm contract fixture |
openapi-drift | regenerates the spec and diffs the committed copy |
perf-smoke | criterion bench plus a 15% regression comparison |
binary-size | release build of three binaries |
run-production-gates, propagation-guard | cross-crate sweeps over every SDK, demo and example |
bench-sift1m-compile | compile-only check of the SIFT1M bench harness |
perf-gate-e2e | release wheel build + 10K recall/latency benchmark; no-ops green unless the search hot path changed |
compat-matrix | Windows, wasm32 and a nightly loom pass — runs on PRs but is not in CI Success's needs:, so it cannot hold a merge |
| node licence boundary | cargo tree assertion that velesdb-node never pulls velesdb-core |
pr-governance | branch prefix, and "not behind base" — properties of the PR, not of the tree |
Hardened execution methods
Rules distilled from real incidents in this repository (each one is a mistake that was actually made once, with its cost). They extend the Working principles above; where they overlap, these are the operational form.
7. Adversarial review before acting on findings. A review finding — human,
tool, or agent — is a claim, not a fact. Before implementing a fix, attack
the claim: read the call chain for the guard that makes it unreachable, and
attack the remedy for perf cost and over-engineering. Measured on one
architecture pass: of 12 confirmed-sounding claims, 2 were factually wrong
(the barrier was already present), 3 were exaggerated (derived artifacts,
no data loss), and 1 proposed remedy (a Drop-that-fsyncs type) was itself
an anti-pattern. Implement only what survives.
8. Root cause, never symptom. No re-running a flaky job (fix why it
flakes — e.g. poll the observable the test asserts on, not a proxy like
is_empty()), no #[allow] to silence a lint on new code, no skipping a
test to get green, no baselining away a defect the code should fix.
9. Baseline before gating. Before adding any new CI gate, run the tool on
the whole tree and audit the results first. A raw typos gate would have
arrived 2 070 findings red — all false positives (French prose, deliberate
typo fixtures, identifier tokenization). Configure the tool to the repo's
reality (audited allowlist, the repo's own format style), pin its version so
a dictionary update cannot flip the verdict, and only then wire the gate.
10. Local checks mirror CI flags exactly. cargo clippy --all-targets --all-features (a --lib-only run missed -D pedantic on test targets and
shipped two red pipelines), cargo fmt --check, the guard scripts, and
git branch --show-current before trusting any validation run. For a new
dependency advisory, bump the lockfile surgically (edit version+checksum,
verify with cargo metadata --locked) — a full cargo update -p re-resolves
unrelated edges under a local toolchain that differs from CI's.
11. Never let a pipe swallow a verdict. … | tail -n on a test run once
reduced FAILED (errors=1) to an invisible line and the push went red in CI.
Capture full output to a file, read the summary line (Ran N tests + OK),
and remember the guard suite prints "FAILED" on stdout while passing (a
refusal-path test) — never grep for FAILED alone.
12. A new guard implements the whole registry contract. scripts/guards.json
entry with declared blind spots, a must_refuse vector carrying all four
fields (vector, files, argv with {root}, accepts — the harness
executes both states and a missing positive control errors three meta-tests),
a self-test module, and wiring into a workflow job that CI Success needs.
Run the vector by hand exactly as the harness does before pushing.
13. Sequence merges against the freshness gate. pr-governance requires a
PR to not be behind develop at CI time. Merging PR A to develop invalidates
PR B's freshness mid-run — so order the queue: land the independent PRs first,
refresh the dependent one once, last (union-merge CHANGELOG conflicts),
and never chase develop with repeated refresh pushes.
Architecture (3 layers)
Full picture: ARCHITECTURE.md, STORAGE_FORMAT.md. In short:
- Client — TypeScript/Python SDKs, REST client, CLI REPL, mobile SDK.
- API — thin bindings wrapping the core:
velesdb-server(Axum REST),velesdb-python(PyO3+NumPy),velesdb-wasm(browser, no persistence),velesdb-mobile(UniFFI),velesdb-cli(REPL). - Core (
velesdb-core) — where all real work happens. The VelesQL control plane (parse → validate → plan → cache) orchestrates execution across the Database/Collection runtime, the Index layer (HNSW for ANN, BM25 for full-text, ColumnStore for bitmap filtering), the SIMD distance layer (5 metrics dispatched per-arch: AVX2/AVX-512, ARM64 NEON, scalar fallback; WASM uses the scalar fallback — SIMD128 kernels are planned), and the storage layer (mmap + WAL).
Tests live beside their module as *_tests.rs; integration/BDD suites in crates/velesdb-core/tests/. The control-plane seam is core/src/observer/.
Control-plane boundary: observer/ exposes a policy-free port (DatabaseObserver, on_query_request → AccessDecision, open_with_observer). Core ships only the default allow-all/no-op behavior; the enforcing policy (RBAC, tenancy, audit) lives in velesdb-private (the private repo; its crate is velesdb-premium) as an observer impl. Core must never reference any premium crate, type, or symbol.
MSRV: Rust 1.90 (rust-version in root Cargo.toml, pinned in rust-toolchain.toml). Two things force it: avx512vpopcntdq target_feature, stabilized in 1.89, and roaring 0.11.4, which declares 1.90. Workspace version is single-sourced in root Cargo.toml.