Contributing¶
The full rules are in the repository's CONTRIBUTING.md and CLAUDE.md. This page collects only the ones people most often trip over.
Branches¶
feat/<module>/<description> New feature
fix/<module>/<description> Bug fix
chore/<module>/<description> Everything else (docs, tests, refactoring, CI, config)
These three are the only branch types. refactor, test, docs, perf, and ci are used
only as commit types.
<module> is one of stack, cicd, admin, auth, o11y, product, ui,
shared, infra, and cli.
There is no csp module
For cloud and deployment infrastructure, use infra.
Commits¶
<type>(<module>): <description>
feat(stack): implement the stack install workflow
fix(cicd): preserve PVCs on pipeline deployment rollback
docs(infra): correct the local E2E guide
PRs¶
The PR Convention Check in CI enforces the title and body.
- Title:
<type>(<module>): <description>— the description is 1–72 characters - Required in the body: the
## Summary,## Changes, and## Testingsections, and aScope:line with content
gh pr create --body does not apply the template
Even when you write the body yourself, you must include all four elements above.
If you only changed the title or body, close and reopen the PR to re-run the check
The workflow triggers only on opened and reopened.
CHANGELOG¶
The CHANGELOG Check requires an entry that corresponds to your change. The exempt paths are
docs/, e2e/, _test.go, .test.tsx, .spec.tsx,
.github/ISSUE_TEMPLATE/, CHANGELOG.md, .gitignore, LICENSE, and
README.md.
website/ is not exempt
Changes to this docs site need a CHANGELOG entry.
Tests¶
| What you want to do | Command |
|---|---|
| Go unit tests | make test (untagged tests only) |
| DB integration tests | make test-integration — testcontainers starts Postgres itself, so you do not need make dev |
| kind E2E | make test-golden-path (60 minutes) |
| Go lint | make lint |
| Frontend unit tests | cd web && npx vitest run |
| Frontend lint | cd web && npm run lint |
Without a DB, E2E tests are skipped, not failed
The DB-backed tests in go test ./e2e/ have no build tag, so they run along with the regular
tests, and when they cannot connect to localhost:5433 they drop out with t.Skip. The
result is ok, so it looks like a pass. Bring up the infrastructure with make dev, or, to
run without infrastructure, use make test-integration, which uses testcontainers.
Coverage¶
The gate and the target are different
The threshold CI enforces is 49% (scripts/check-coverage.sh, which counts only
./internal/...); 70% is the v1 GA target.
Architecture rules¶
- Modular Monolith — modules communicate only through public interfaces. Do not import another module's internal packages directly
- Clean Architecture — dependencies always point inward (toward the domain).
domaindoes not import frameworks - DDD — a module is a bounded context. Modules also own their tables and do not query another module's tables directly
- TDD — new features start with a test; bug fixes start with a test that reproduces the bug
Editing this site¶
pip install -r website/requirements.txt
./website/stage.sh # Pulls in the standalone HTML guides from docs/
python3 website/check_i18n.py # Checks that Korean and English pages pair up
cd website && mkdocs serve # http://127.0.0.1:8000 (English under /en/)
Every page exists in Korean and English. The Korean X.md is the source, and the English
X.en.md sits next to it. When you change the Korean page, update the English page in the same PR.
- In English pages, quote the real English UI text (
web/src/i18n/en.json) - Link to pages by their Korean file name (
list.md) — in the English site the plugin points the link at the English page. Heading anchors follow the English heading - When you add a title to nav, add its English title to
nav_translationsinwebsite/mkdocs.yml - Run
npm run shots:docsinwebto capture screenshots: it writes*.png(Korean) and*.en.png(English) together. Both versions of a page keep the image path as*.png
Once a change lands on main, GitHub Actions deploys the site automatically. PRs only build it —
with mkdocs build --strict, so CI fails if a page listed in nav is missing or an internal
link or anchor is broken. check_i18n.py also fails a page whose English version is missing,
or that gained a section or image in only one language.