Development workflow
Status: Proposed 2026-09-24
One flow for all four repos. Small branches, one PR each, squash into main. The only repo with a second long-lived branch is the web app, and only once it has real traffic.
Branches
Branch from main, name with the same prefixes as the commit subjects:
| Prefix | Use |
|---|---|
feat/ | new behavior |
fix/ | a bug, ideally with the failing test first |
docs/ | documentation only (any repo) |
chore/ | tooling, dependencies, CI |
refactor/ | no behavior change |
test/ | tests only |
Short kebab-case after the slash: feat/places-bbox-query. No ticket numbers; the PR is the ticket.
Pull requests
Every PR starts from .github/pull_request_template.md. The summary block is the completion triple from the principles checklist, plus rollback:
Activist outcome:
What changed:
Privacy and trust checks done:
Signal to watch:
Rollback plan:
Fill it in even for a one-line fix. "Activist outcome: none, tooling" is a valid answer; a blank is not. The checklist below it mirrors the privacy rules and is ticked, not deleted.
Review: CODEOWNERS routes every path to the maintainer. The ruleset requires a code-owner review and a green validate. With one maintainer, the admin bypass covers the review requirement; it never covers the check. Before you push, run npm run validate locally so the PR is green on arrival.
Merge: squash only. The squash subject is a conventional commit subject, because it is the line that shows up in releases.
The web promotion pattern (reserved)
The web app is the only public surface that redeploys on every merge (Amplify builds main). Once the site has members, the web repo gains a staging branch: feature PRs merge to staging, Amplify builds it as a preview, and one promotion PR moves staging to main. A production-promotion check rejects any PR into main from another branch. Until then the web repo works like the others. The API, mobile, and docs repos do not get a staging branch: the API has a release-directory rollback (backend deployment), mobile has store tracks, docs are docs.
When CI fails
- Open the failed job and read the first error, not the last. Biome and
tsclist everything; the first item is usually the cause. - Reproduce locally with
npm run validate. If it passes locally and fails in CI, check Node (.nvmrcis the truth), line endings (see linting), and whether a lockfile change was left uncommitted. - Fix, commit, push. Do not re-run a job hoping for a different answer unless it failed on a network step.
- If the
secretsjob fails, stop. Treat the finding as live: rotate the credential first, then remove it from history before the PR merges. Rewritingmainis never the fix; rewriting the branch is.
Dependencies
Dependabot opens grouped minor and patch PRs weekly. Merge them when validate is green; read the changelog for anything that touches auth, crypto, or the map. Major bumps get their own branch and a note in the PR about what was checked by hand.