Skip to content

Contributing to Photon

Thanks for wanting to help. Photon is small on purpose, so the bar for adding things is high and the bar for fixing things is low. Bug reports, failing tests, documentation fixes, and measurements are the most valuable contributions.

  • Bugs: open an issue with a minimal program that reproduces it. A failing test is even better.
  • Features: open an issue first and describe the problem, not the solution. Photon’s core stays small — see ADR-0011 for the test every addition has to pass. Many good ideas belong in your application or in a separate package, and an issue is the cheap way to find out.
  • Security issues: do not open an issue. See SECURITY.md.

You need Go 1.24 or newer. The race detector also needs a C toolchain with CGO_ENABLED=1 (on Windows, MinGW-w64 or LLVM-MinGW).

Terminal window
make test # go test ./...
make race # the race detector, three runs - the gate that matters
make check # gofmt, go vet, and the docs coverage test
make fuzz # the routing and SSE framing fuzzers, 30 s each
make bench # microbenchmarks
make all-modules # also the example backend and the benchmark harness modules

No make? Every target is one Go command; read the Makefile. On Windows, .\test.ps1 runs every module.

The repository holds four Go modules: the library at the root, and examples/openai-backend, bench/baseline, and bench/stream, which have their own dependencies. go test ./... from the root covers only the first.

  • One change. A fix and a refactor are two pull requests.
  • A test that fails without the change. For a bug, the test reproduces it. For behaviour, the test pins it. Several tests here were proven by sabotage — break the code, watch the test fail — and that is the standard.
  • Measurements for performance claims. Run the before and after interleaved, as described in bench/RESULTS-2026-10.md, and report medians and ranges. A single run on a laptop is not evidence.
  • Documentation updated in the same commit. Every exported symbol must appear in docs/API.md (a test enforces it), and behaviour changes go in CHANGELOG.md under Unreleased.
  • No new dependencies in the root module. This is enforced in CI and is not negotiable — see ADR-0013.
  • gofmt and go vet clean.
  • Comments explain why. The codebase is heavily commented with the reasoning behind each decision, and the reviewer will ask for the reason if it is missing. A comment that restates the code can go.
  • Error messages say what happened and what to do: “MaxStreams is -1: use 0 for the derived default” rather than “invalid value”.
  • Security-relevant defaults do not change without discussion; changing one is a breaking change.

Significant decisions are written down in docs/adr/. If your change reverses or amends one, add a dated amendment to that ADR explaining what was learned. Those amendments are the most useful documents in the repository, because a decision that is never revisited is not a decision.

By contributing you agree that your contribution is licensed under the project’s Apache License 2.0, as described in its section 5.