Thanks for your interest in contributing. This document covers the branch model, PR workflow, and release process. For setting up a local development environment, see docs/3-local-development.md.
| Branch | Purpose |
|---|---|
develop |
Default branch. All PRs and releases flow through here. |
Release flow:
- As PRs merge to
develop, the changeset bot opens and maintains a "chore: release vX.Y.Z" PR targetingdevelop - Merging that PR to
developcreates a GitHub release automatically
-
Branch off
developgit checkout develop && git pull git checkout -b my-feature -
Make your changes and write tests. All PRs must pass
npm run lint,npm run validate-config, andnpm test. -
Add a changeset (see below)
-
Open the PR against
develop
Every PR that changes behaviour needs a changeset - a small file that describes what changed and what kind of version bump it warrants. The changeset check CI will fail if one is missing.
Add a changeset:
npm run changesetThis prompts you to pick a bump type and write a one-line description, then writes a file to .changeset/. Commit that file with your PR.
Bump types:
| Type | When to use |
|---|---|
patch |
Bug fixes, internal refactors with no behaviour change, dependency bumps |
minor |
New features, new config options, new scanner support |
major |
Breaking changes to config format, removed options, changed defaults |
Skipping the changeset:
For PRs that don't warrant a release entry - CI fixes, typos, documentation updates - add the no-changeset label to the PR. The check will be skipped.
- One thing per PR. If you find yourself writing "and also..." in the description, split it.
- Explain the why. The diff shows what changed. The description should say why.
- Every behaviour change needs a test. If you're fixing a bug, the test should fail on the old code.
- Security-sensitive areas get extra scrutiny - webhook verification, auth, file path handling, scanner output parsing. Explain your threat model.
Example description:
Fix scanner timeout not being applied to Claude batches
The 10-minute job timeout in worker.js wraps the full runScan() call,
but individual Claude API batches had no timeout of their own. A hung
API call would block the worker until the top-level timeout fired,
tying up a concurrency slot for the full 10 minutes.
Added a per-batch 90-second timeout via Promise.race. Batches that
exceed it log a warning and return { error: true } so the rest of
the scan continues.
Closes #42
npm test # run the full test suite
npm run test:watch # watch mode during development
npm run lint # ESLint
npm run validate-config # validate config/layne.json schemaAll four must pass before a PR can be merged.
- Adding a new scanner: see docs/6-extending.md - Adding a New Scanner
- Adding a notification provider: see docs/6-extending.md - Adding a New Notifier
Please do not open a GitHub issue for security vulnerabilities. See SECURITY.md for the responsible disclosure policy.