Skip to content

Latest commit

 

History

History
81 lines (63 loc) · 3.41 KB

File metadata and controls

81 lines (63 loc) · 3.41 KB

Contributing to Codexa

Codexa is offline-first by default. Please do not include private corpus content, absolute local paths, API keys, logs with sensitive passages, or persisted index data in issues, pull requests, screenshots, or patches.

Feedback

Use GitHub issues for opt-in feedback:

  • Bug reports: include the command, sanitized config snippets, expected behavior, actual behavior, and the smallest non-sensitive reproduction you can share.
  • Retrieval quality reports: include the query, sanitized expected source names, relevant metrics if available, and whether dense, BM25, rerank, or RAG output looked wrong.
  • Feature requests: describe the job you are trying to complete, the workaround you use today, and why local/offline behavior matters for that job.

Pull Requests

Keep changes focused. Run the Python pre-finish checks before submitting when the change touches code:

ruff check codexa tests
pyright
python scripts/check_repo_privacy.py
pytest --cov=codexa

Update TODO.md when you implement or add backlog items.

Mutation testing

Line coverage says a line ran, not that a test would notice it changing. scripts/run_mutation.py mutates one module (comparison flips, and/or swaps, dropped not, arithmetic swaps, off-by-one constants, True/False flips) and re-runs a focused set of tests per mutant:

python scripts/run_mutation.py codexa/search/passage_quality.py \
    tests/test_mutation_passage_quality_2026_08_03.py

Mutants are compiled in memory by the mutation_hook pytest plugin, so a run never writes a mutated file into the working tree. A survivor is a change the suite cannot see — either write a test that fails under it, or record why it is an equivalent mutant in the test module's docstring.

A bare run exits non-zero on any survivor, which is what you want while writing tests and the wrong signal for a gate — every module keeps some genuinely equivalent mutants. scripts/mutation_baseline.json records how many each module is allowed, so a change can be checked for regression instead:

python scripts/run_mutation.py --check codexa/search/passage_quality.py \
    tests/test_mutation_passage_quality_2026_08_03.py

--check fails only when your change leaves more mutants alive than the baseline allows. Survivors, not the percentage, is the gated number: adding code adds mutation sites, so a module can grow while its score dips without anything having got worse. Once you kill survivors — or document them as equivalent — lock the gain in:

python scripts/run_mutation.py --update-baseline codexa/search/passage_quality.py \
    tests/test_mutation_passage_quality_2026_08_03.py

Never raise a baseline number to make a run pass; that is the one edit the file does not accept in review. A module absent from the ledger is not gated yet — --check says so and passes, and adding it is how mutation coverage grows.

Architectural changes should check the decision records in docs/adr/ first — each ADR scopes a functional or non-functional feature (offline posture, pipeline shape, plugin security, cache lifecycle, …) and names what a change in that area must touch. A change that contradicts a recorded decision supersedes it with a new ADR rather than silently diverging. New enrichment ideas register their riskiest assumption in ADR 0002 before implementation.