Skip to content

Latest commit

 

History

History
138 lines (110 loc) · 5.8 KB

File metadata and controls

138 lines (110 loc) · 5.8 KB

Contributing

Thanks for your interest. This is a personal research project — drive-by PRs are welcome, but please open an issue first for anything beyond a typo or single-line fix so we can align on scope.

Local setup

Prerequisites: Python 3.12, uv, Docker + Docker Compose, and a CUDA-capable GPU if you want to run the visual or rerank stack locally.

git clone https://github.com/NorthernLightx/spectrarag.git
cd spectrarag
uv sync --extra dev
cp .env.example .env
docker compose up -d qdrant postgres langfuse ollama
docker exec rag-ollama ollama pull bge-m3

What CI runs (mirror locally before pushing)

uv run ruff check .
uv run ruff format --check .
uv run mypy src tests scripts
uv run pytest -v --cov=src --cov-report=term-missing
uv run python -m scripts.eval_retrieval_ci --output data/eval/runs/retrieval-ci.json
uv run python -m scripts.check_regression \
    --baseline data/eval/baseline_retrieval.json \
    --candidate data/eval/runs/retrieval-ci.json \
    --metrics ndcg_at_5 recall_at_10 mrr --threshold 0.05

Scripts layout

scripts/ is three tiers by stability:

  • top level — maintained entrypoints + the data-reproduction pipeline (eval_run, check_regression, ingest, render_pages, bootstrap_corpus, eval_visual, fetch_*, …). CI, the root README, and docs/evals.md invoke these as python -m scripts.<name>; their import paths are an API contract — relocating one is a cross-repo change (CI + docs + ADRs in the same commit), not a move.
  • scripts/experiments/ — the ADR-linked DoE / study / probe drivers from the retrieval investigation (ADRs 0012–0016).
  • scripts/legacy/ — superseded one-off and earlier-phase scripts kept for the historical record (referenced by older ADRs / docs/results.md).

experiments/ and legacy/ are intentionally exempt from the CI ruff / format / mypy-strict gates (pyproject.toml extend-exclude + mypy exclude): they are audit and reproducibility artifacts, not library code. New exploratory scripts start in experiments/; nothing graduates out of legacy/. A script stays top-tier (gated) if it is a documented entrypoint, has a maintained test, or is referenced by maintained code/CLI — even if its approach was superseded. legacy/ is for untested, unreferenced, frozen spikes.

Commit conventions

We use Conventional Commits. The pattern is type(scope): subject, lowercase, imperative mood. Common types:

  • feat(<scope>): — new behavior
  • fix(<scope>): — bug fix
  • docs(<scope>): — README / ADR / docstring changes
  • test(<scope>): — test-only changes
  • refactor(<scope>): — no behavior change
  • chore: — repo housekeeping
  • ci: / build: — workflow / build config
  • perf(<scope>): — perf-only changes

Examples from this repo:

feat(eval): --refusal-score-threshold CLI flag wires gate into eval_run
fix(ci): drop unused pull-requests:write permission from deploy workflow
docs(adr): 0006 — OOC refusal gate (accepted opt-in; judge artifact noted)
chore(deploy): tighten az containerapp create args; default min-replicas=0

Keep commits atomic — each commit should pass pytest -m "not integration" on its own. If a refactor and a feature ride together, split them.

Architecture decisions

Any non-obvious choice gets an ADR in docs/decisions/NNNN-<slug>.md. Mirror the structure of the existing ones (Status / Date / Phase / Context / Implementation / Decision / Caveats / References). PRs that change behavior in an area covered by an ADR should reference or supersede it.

What NEVER goes in a commit

This repo is open-source by design. Be defensive about leakage:

  • Secrets — API keys, tokens, DSNs, private keys, OAuth secrets. .env is gitignored; .env.example is the only sanctioned secrets-ish file (with placeholder values only). Pre-commit gitleaks hook is the safety net, not a substitute for care.
  • Personal info — your home directory paths (/c/Users/<you>/..., /home/<you>/..., C:\Users\<you>\...), your real-name email if you prefer pseudonymity, internal hostnames, customer data, anything you wouldn't paste into a public Gist. Use ~ or env vars in pasted shell commands.
  • Large binary blobsdata/papers/, data/pages/, model weights, .parquet, anything > 1 MB unless it's a versioned artifact like data/eval/baseline.json. Use the fetch scripts to reproduce locally.
  • Ephemeral local state.venv/, logs/, .coverage*, __pycache__/, qdrant_storage/, postgres_data/, IDE configs. These are covered by .gitignore; if you introduce a new tool whose state isn't already gitignored, add it to .gitignore in the same PR.
  • Work-in-progress notesSTATUS.md-style running logs, scratchpad plans, one-off task lists, anything intended as a personal thinking aid. What belongs in the repo is the ADR after the decision is made, not the deliberation that led to it.

If you accidentally commit something sensitive, do not just delete it in a follow-up commit — the data stays in history. Use git filter-repo to purge the file from every commit, then force-push and rotate the secret. See GitHub's removing sensitive data guide.

Pre-commit hooks

Recommended (mirrors CI + adds secret scanning):

uv pip install pre-commit
pre-commit install

After install, git commit runs ruff, gitleaks, basic file-shape checks locally. CI runs the same set on push.

Reporting security issues

See SECURITY.md. Please do not file public issues for security-impacting bugs — use GitHub's private vulnerability reporting.