Skip to content

Latest commit

 

History

History
161 lines (127 loc) · 7.4 KB

CONTRIBUTING.md

File metadata and controls

161 lines (127 loc) · 7.4 KB

Contributing to CodeTrial

README.md covers what CodeTrial is, how to build it, and how to run it. docs/development.md covers the test gate, the formatter chain, the git hooks, and the generated files. This page covers what neither does: how a change gets in, and the rules a reviewer would otherwise have to say out loud every time.

Everything posted to GitHub is written in clear English, with identifiers and error messages kept verbatim. The conversation that produced a change can be in any language; the issue, the pull request, and the code cannot.

Reporting a bug

Use the bug report form. It asks for the facts a maintainer always needs, because asking for them afterwards costs a round trip that usually never completes.

Before filing, search open and closed issues. If a thread already covers the symptom, add the new evidence there instead of opening a second one.

A feature idea, a question, or a design objection goes in a blank issue, which the chooser offers beside the form. Only bug reports get a form, because only bug reports have a fixed set of facts a maintainer always needs.

Nothing public carries credentials, session tokens, candidate recordings, or personal interview content. Sanitize logs and screenshots before attaching them. This repository has no security mailbox and GitHub's private vulnerability reporting is turned off, so there is no private channel to send a report to. Do not put the details anywhere public: open an issue that says only that you have a security report and asks for a private contact, and wait for one.

Before changing code

docs/ holds decisions that are already made, and several of them refuse a change that looks obviously right. Find the document that owns the area and read the rule there first: provider cost and degradation owns what an interview may spend and what may be cached, the observable delivery policy owns what a report may say about a person, the recording contract owns what happens to candidate media, and the rest of docs/ owns its area the same way.

A document that refuses your change is the answer, not an oversight. The move is to propose changing that document on purpose, with the reason, rather than working around it.

A subcommand, flag, or helper that turns out to be redundant is deleted, along with its call sites in the Makefile, the scripts, the README, and the tests. It does not become an alias and it does not get a deprecation warning. The compatibility promise here is the versioned contract in docs/interview-contract-versions.md, not the convenience surface of the CLI. The prompt and report goldens in tests/golden/ are how a change to that contract gets noticed, not a promise of their own: they are regenerated on purpose when a version is bumped. The other fixtures there answer to the tests that own them.

Tests

Every non-trivial change leaves a runnable check behind: the smallest thing that fails if the change breaks.

src/ holds implementation and must not contain a test body. A module declares its tests and the body lives under tests/unit/, mirroring the path:

#[cfg(test)]
#[path = "../tests/unit/gemini.rs"]
mod tests;

Declared this way they are still unit tests, with super:: and private items in reach. A standalone integration target under tests/ compiles as its own crate and reaches only the public API, which would have meant publishing internals for the tests' benefit. Never name such a file tests/<dir>/main.rs: Cargo compiles that as a second crate root, where every super:: in it fails.

No gate enforces the rule, so grep -rn '#\[test\]' src/ is the check, and it returns nothing today.

Running the gate

make hooks           # once per clone; installs every scripts/git-*.sh hook
./scripts/test.sh    # the credential-free gate CI runs

make hooks installs a wrapper for each scripts/git-*.sh, so the push is gated as well as the commit and a rebase that rewrote a message is caught before it reaches GitHub.

The gate ends by naming any lane it skipped; read that rather than assuming green means covered. docs/development.md has what each hook and lane does, which generated files have to be regenerated first, and the checks that need credentials or a browser.

Commit messages

The house style is Chris Beams' seven rules. scripts/git-commit-msg.sh both prints the enforced list and enforces it, so read it from there rather than from a copy that can drift:

./scripts/git-commit-msg.sh --rules

The prepare-commit-msg hook puts the same list in your editor. Subjects from this tree's log read like this:

Bound a video frame by the memory it will take
Refuse a permission listing that may be truncated
Prove an empty test run is not a pass

A commit needs a body: the hook and CI refuse a subject alone. Fixup, squash and merge commits are exempt, and so are Dependabot's. The body carries the premise and the trade, usually in a single paragraph. This tree keeps its detailed reasoning in the comment next to the code, so a body retelling the mechanics duplicates that comment and then goes stale on its own. The hook rejects the shape that does it outright: a body line opening with How:, Step:, Steps:, Changes: or an Implementation: heading. Whether what is left says anything is the part only a reviewer can judge.

Comments follow from the same rule: every line says something the code cannot. The ASCII rule the hook enforces covers the commit message, and source comments follow it by convention, with no em dash, typographic quote, arrow character, or CJK.

Pull requests

Open a pull request from a topic branch, never from main, including the main of a fork. A pull request follows its head branch, so one opened from main takes in every later push there and blocks the next change until it merges. The pre-push hook refuses new work on a fork's main once upstream is a remote in the clone, and CI fails a pull request opened from one either way.

Branch from an up-to-date main, keep one change per branch, and update the pull request by pushing to that same branch, force-pushing after a rebase. Syncing a fork's main with upstream is still allowed, since it carries only commits upstream already has.

A title carries no category, type, or area prefix: no [Bug], [Feature], Bug:, feat:, fix(web):, or web:. GitHub issue types do the classifying, and brackets that are part of the text, such as argv[0], stay. A pull request title follows the commit subject rules above; a single-commit pull request reuses its subject. An issue title names the symptom or the outcome instead: Interview does not resume after reconnecting, not [Bug] Interview broken.

Issue and pull request bodies are read in a browser, so write each paragraph as one line. The 72-column wrap is for commit messages only. A pull request that finishes an issue ends with Closes #N alone on the last line; one that only touches it ends with Refs #N.

A review thread carries a correction, a measurement, or nothing: no pasted agent walkthroughs, no severity tables, no re-summarizing a diff that GitHub already shows. Close an addressed thread with "Resolve conversation".