chore: set up branching, CI, and PR workflow
CI / Repo hygiene (pull_request) Successful in 24s
CI / API (lint, types, tests) (pull_request) Successful in 55s
CI / Web (lint, typecheck, build) (pull_request) Successful in 25s
CI / Migrations reversible (pull_request) Successful in 3s

Prepares the repo for parallel agent work. No application code.

- CLAUDE.md: conventions, branch naming, and the six non-negotiable
  invariants from the design (immutable raw bytes, no stored odometers,
  SI integers, dual-layer user isolation, secret containment, single
  ingestion path). Also records a model-allocation policy: the
  orchestrator runs Opus 5, workers default to Sonnet, and Opus is
  reserved for review plus the areas where a mistake is silent and
  expensive (ingest, wear SQL, auth/RLS, the Bryton protocol client).
  And the Gitea Actions gotchas, so nobody rediscovers them:
  GITEA_TOKEN cannot push to the container registry, jobs.*.environment
  is ignored, and cron needs a workflow_dispatch pair.
- CONTRIBUTING.md: day-to-day flow, worktrees for parallel branches,
  review expectations.
- .gitea/workflows/ci.yml: repo hygiene (branch naming, secret scan,
  no ride data in git), plus API/web/migration jobs that guard on whether
  the code exists yet, so CI is meaningful now and grows into the real
  thing rather than being rewritten.
- .gitea/PULL_REQUEST_TEMPLATE.md: forces an honest "how this was
  verified" and an invariant checklist.
- scripts/pr.sh, scripts/review.sh: open and inspect PRs via the Gitea API.
- Directory scaffold with placeholder READMEs.

Agents open PRs; humans merge them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-20 21:12:22 -04:00
co-authored by Claude Opus 5
parent d3f5ed7e7b
commit d5e473959c
11 changed files with 574 additions and 0 deletions
+76
View File
@@ -0,0 +1,76 @@
# Contributing
Short version: branch, commit, push, open a PR, get it reviewed, squash-merge.
`main` is never committed to directly.
Conventions live in [`CLAUDE.md`](CLAUDE.md) — branch naming, style, the non-negotiable
invariants, and the rules for agents working in parallel. Read that first.
## One-time setup
SSH to Gitea should already be pinned in `~/.ssh/config`:
```
Host 192.168.0.3
HostName 192.168.0.3
User git
IdentityFile ~/.ssh/gitea
IdentitiesOnly yes
```
`IdentitiesOnly yes` matters: without it, SSH may offer an older deploy key first and Gitea will
authorize against *that* key's narrower permissions.
For opening PRs from the command line, create a Gitea token at
http://192.168.0.3:3000/user/settings/applications with scopes `read:user`, `write:repository`,
`write:issue`, then:
```bash
export GITEA_TOKEN=<token> # add to your shell profile
export GITEA_URL=http://192.168.0.3:3000
```
## Day-to-day
```bash
git switch main && git pull
git switch -c feat/ingest-fit-parser
# work, commit in logical steps
git push -u origin feat/ingest-fit-parser
scripts/pr.sh "feat(ingest): parse Bryton FIT activities"
```
`scripts/pr.sh` opens the PR against `main` and prints its URL. Pass `--draft` if it isn't ready.
## Parallel work
Use worktrees so branches don't fight over one checkout:
```bash
git worktree add ../bike-app-ingest -b feat/ingest-fit-parser
cd ../bike-app-ingest
# ...
git worktree remove ../bike-app-ingest
```
## Review
- CI must be green before review is requested. A red PR isn't ready.
- Reviewers look for: correctness, the invariants in `CLAUDE.md`, whether the tests actually prove
what the PR claims, and whether it reuses what already exists.
- Address feedback with new commits. Don't force-push over review history unless asked.
- **Agents open PRs; humans merge them.**
## Commits
Conventional prefixes, imperative mood, and a body that explains *why*:
```
feat(ingest): discriminate activities from Bryton course files
Bryton writes routes as .fit too, so a naive importer turns saved routes
into phantom rides. Check file_id.type first, falling back to message-shape
inspection since Bryton's encoder omits it on some firmware.
```