Contributing to vibe-qc¶
Contributions and feedback both welcome. The decision tree below covers where to direct what.
Where to report what¶
What |
Where |
|---|---|
Security vulnerability — exploitable bug, memory corruption, anything you think shouldn’t be public-by-default |
Email |
Bug, install problem, missing feature, “this didn’t work the way the docs said” |
GitLab issue tracker. Search for an existing issue first; comment on it if there is one. Filing requires a free account on |
General feedback, question, “is this a bug or am I doing it wrong?” |
Email |
Code-of-conduct violation |
Email |
You want to send a patch |
Read the rest of this file. |
You want to fund the project |
GitHub Sponsors (recurring monthly) or Ko-fi (one-time). Full pitch + author bio + funding goals on the support page. |
All contributors and maintainers are expected to follow the Code of Conduct.
Before you open a merge request¶
Confirm no existing issue already covers the change — if there is one, comment on it so we can coordinate.
Run every test lane affected by the change and confirm it passes:
.venv/bin/python scripts/test_gate/run_full_suite.py \ --wt "$PWD" --py .venv/bin/python --lane <affected-lane>
If your change touches documentation, build the Sphinx docs locally and skim the affected pages:
sphinx-build -b html docs/ docs/_build/html
For anything that adds a dependency or changes public API, open an issue first to check scope fit.
Recommended pre-merge verification¶
Affected lanes are the merge-request gate. Use
scripts/test_gate/run_full_suite.py --list-lanes and
docs/developer_test_lanes.md to select them. The recommended layering is:
# 1) Non-mean-field solver tests — fast, no native rebuild needed.
.venv/bin/python -m pytest \
tests/test_solvers_active_space_api.py \
tests/test_solvers_dmrg_fixed_n.py \
tests/test_solvers_v2rdm_constraints.py \
tests/test_solvers_v2rdm_tc.py \
tests/test_solvers_integration.py \
tests/test_solvers_fci_parity.py
# 2) QVF writer + writer-to-viewer integration. The viewer leg is
# skipped automatically if vibe-view isn't installed; the strict
# writer-side schema asserts always run.
.venv/bin/python -m pytest \
tests/test_qvf_writer.py \
tests/test_qvf_writer_to_viewer.py
# 3) Packaging / extras metadata coherence — pure metadata, no install.
.venv/bin/python -m pytest tests/test_packaging_extras.py
# 4) Every affected lane. Add full-fast only for shared infrastructure.
.venv/bin/python scripts/test_gate/run_full_suite.py \
--wt "$PWD" --py .venv/bin/python --lane <affected-lane>
List the exact lanes and SHA tested in the merge-request description.
Do not claim full-inventory success unless full-fast and slow-nightly
actually ran on that SHA.
Pre-commit hook (one-time setup)¶
After cloning, point git at the tracked .githooks/ directory so the
repo’s commit guards run on every commit:
git config --local core.hooksPath .githooks
This single setting activates every hook in .githooks/ (git resolves
one hooks directory for all hook types):
pre-commit— refuses commits whose staged additions contain absolute paths into the author’s home directories or other personal-info patterns (CLAUDE.md § 12). It then runs.githooks/check_no_em_dashes.py, which refuses stageddocs/*.mdcarrying em or en dashes in prose (code fences, inline code, and inline math are exempt).commit-msg— refuses arelease: vX.Y.Zcommit unlesspyproject.toml[project] version==X.Y.Zand a## [vX.Y.Z]CHANGELOG header exists. This is the backstop against tagging a release from a tree whose version bump was skipped — the defect that shipped v0.11.2 / v0.11.3 self-reporting0.11.1. See docs/release_process.md § “Cutting a release”.
To bypass either hook for a reviewed exception, commit with
git commit --no-verify and explain the reason in the commit message.
Worktrees need the setting applied per worktree¶
Parallel agent chats get one clone each, not a worktree — see
CLAUDE.md § “One clone per chat”. Worktrees still turn up in practice
(agent harnesses create them under .claude/worktrees/), and a worktree
does not necessarily inherit the setting above, so check before trusting
it.
--local writes the shared .git/config, but once a repo has
extensions.worktreeConfig = true — git enables it the first time
anything writes a worktree-scoped setting — a linked worktree can carry
its own core.hooksPath in .git/worktrees/<name>/config.worktree that
overrides the shared value. Check what a worktree actually resolves,
and repair it with --worktree:
git -C <worktree> config --show-scope --get-all core.hooksPath
git -C <worktree> config --worktree core.hooksPath .githooks
Keep the path relative. An absolute path bakes the checkout
location into each worktree’s config, so renaming or moving the clone
leaves core.hooksPath pointing at a directory that no longer exists.
Git skips a missing hooks directory silently — no warning, no error,
no failed commit — so every guard above goes inert without anyone
noticing. A relative .githooks resolves against each worktree’s own
top level and survives the move.
To confirm a hook really runs, without making a commit:
git -C <worktree> hook run pre-commit
Code style¶
C++17. Four-space indent, brace on same line for control flow. Everything in
cpp/lives undernamespace vibeqc { ... }. Match the patterns incpp/src/rhf.cpp/cpp/src/integrals.cpp.Python 3.11+. PEP 8 with four-space indent. Start every module with
from __future__ import annotations. Type hints on public API; local helpers can skip them.Prefer editing existing modules over introducing new ones. If a new file is the right choice, follow the neighbors’ layout.
Commit messages¶
Imperative mood, first line under 72 characters (e.g.
Fix SCF divergence on CH3 with SAD guess).Longer rationale in the body if the what doesn’t explain itself.
Co-author trailers are fine for pair work.
To flag a commit for inclusion in a patch release, add a
Patch-candidate:trailer to the commit body (alongsideSigned-off-by:/Co-Authored-By:) — values likev0.7.x,v0.8.x,v0.8.0, or comma-separated combinations. The release chat scans these when cutting patches. Do not tagvX.Y.Z, push torelease, or open MRs againstreleasedirectly — those are release-chat-owned operations and (since 2026-05-15) blocked by GitLab branch / tag protection. SeeCLAUDE.md§ 13 anddocs/release_process.mdfor the full convention.
What we won’t accept (for now)¶
API changes that break public signatures without a deprecation path.
New hard dependencies added without prior discussion — open an issue first.
Changes that regress the test suite without a stated rationale and a plan to restore.
Licensing¶
By submitting a patch, pull request, or any other contribution to vibe-qc, you agree that:
Your contribution is licensed under the Mozilla Public License 2.0 (the project license — see
LICENSE).You grant the project owner (Michael F. Peintinger) the right to relicense your contribution under alternative terms, including a future commercial license, alongside the MPL 2.0 public license. You retain copyright.
This is a lightweight alternative to a formal Contributor License Agreement. If you’re not comfortable with (2), please open an issue before contributing so we can discuss.
vibe-qc’s compiled core links libint (MPL 2.0), libxc (MPL 2.0), Eigen (MPL 2.0 / BSD-3), spglib (BSD-3), and pybind11 (BSD-3) — all MPL-compatible.