Contributing
Conventions
- Use Conventional Commits (enforced by commitlint).
- Keep changes small and scoped to a single capability.
- Maintain tenant scoping on every data access.
- Keep modules and symbols aligned to single responsibility.
- Keep code DRY; extract repeated logic into focused helpers (typically
src/utils/*). - Prefer Zod schemas in
src/data/*/*.validators.tsfor inputs. - Ports live in
src/data/*/*.repository.tsand contain no framework imports. - Adapters live in
src/data/*/*.repository.<impl>.tsand may use mongoose/express. - Treat
src/init/*.init.tsas composition roots and keepsrc/server.tslauncher-only. - Add JSDoc for exported/shared classes, functions, and methods.
- Add explicit inline comments for non-obvious logic paths.
Tooling
- Format on demand:
pnpm format - Lint:
pnpm lint - Typecheck:
pnpm typecheck - Cycle detection:
pnpm check:cycles(no circular deps undersrc/; run before pushing). - E2E:
pnpm run e2e - Pre-commit: doc automation runs first (
pnpm docs:pre-commit-update), then lint-staged, typecheck, test, contract coverage, semgrep, and e2e.
Recommended local order: pnpm typecheck → pnpm lint → pnpm test → pnpm run e2e → pnpm check:cycles.
Pre-commit documentation automation
When you commit changes to source files, the pre-commit hook may require documentation updates. The hook invokes scripts/docs/doc-update-cmd.sh which runs Claude headlessly to update the affected docs.
Required environment variable
| Variable | Purpose |
|---|---|
ANTHROPIC_API_KEY | Anthropic API key used by the claude CLI to update docs. Get one at console.anthropic.com. |
Export it in your shell profile (~/.zshenv, ~/.bashrc, etc.):
export ANTHROPIC_API_KEY=sk-ant-...
Install the claude CLI
npm i -g @anthropic-ai/claude-code
Verify it works:
claude --version
Optional environment variables
| Variable | Default | Purpose |
|---|---|---|
CLAUDE_BIN | claude | Path to the claude binary if it is not on PATH. |
MAX_PARALLEL_DOC_AGENTS | 4 | Maximum number of doc-type agents to run concurrently. |
DOC_UPDATE_LOG_DIR | scripts/docs/.doc-update-logs/ | Directory where per-doc-type agent logs are written. |
Verified happy path
With ANTHROPIC_API_KEY exported and claude on PATH, a normal commit proceeds without any bypass:
# One-time setup (already done if ANTHROPIC_API_KEY is in your shell profile)
export ANTHROPIC_API_KEY=sk-ant-...
export DOC_UPDATE_CMD="bash scripts/docs/doc-update-cmd.sh"
# Stage your changes and commit normally — no --no-verify needed
git add src/...
git commit -m "feat(order): add new pricing logic"
What happens during the commit:
scripts/docs/pre-commit-doc-update.mjsexamines the staged diff againstscripts/docs/documentation-types.rules.json.- For each affected doc type (e.g.
service-guide,api),doc-update-cmd.shspawns a Claude agent (up toMAX_PARALLEL_DOC_AGENTSin parallel) with a focused prompt. - Each agent writes docs to
docs/and the hook stages them automatically. - If all agents succeed the hook exits 0 and the commit proceeds.
- Agent logs land in
scripts/docs/.doc-update-logs/<doctype>.logfor post-commit inspection.
If the hook exits non-zero, check the log for the failing doc type. Common causes: API key invalid, claude CLI version mismatch, or a doc type whose docPaths directory does not exist yet.
Emergency bypass
If you need to commit without doc automation (e.g., ANTHROPIC_API_KEY is temporarily unavailable):
export DOC_UPDATE_CMD='echo skipped'
git commit ...
unset DOC_UPDATE_CMD
This bypasses the AI doc update entirely. Use only in emergencies — the docs will be stale until you update them manually or via a follow-up commit.
Release process
- Canonical release source is conventional commits on
main. - semantic-release computes semver, updates
docs/releases/CHANGELOG.md, tags, and publishes GitHub Releases. - Validate release impact without publishing:
pnpm release:dry.
Reviews
- New/changed behavior must include at least unit tests.
- Tests are co-located with source (
*.spec.ts/*.integration.spec.ts). - Bug fixes include a test that reproduces the issue.
- No cross-layer imports.
- No public API changes without updating docs/tests.