YotoShelf
Contribute

How It Works

The AGENTS.md contributor contract: blast-radius limits, and the one-thing-at-a-time rule.

YotoShelf uses an explicit contributor contract documented in AGENTS.md. The rules keep changes safe, reviewable, and reversible, and they apply equally to human contributors and AI coding agents. What follows is that file, read from the repository when this page was built.

The rules

These are non-negotiable. Violating them wastes human time.

1. Read before write

Before modifying ANY file:

  1. Read the entire file you’re about to change
  2. Read the test file for that package
  3. Run existing tests: go test ./internal/{pkg}/... -v
  4. Only then make your change
  5. Run tests again immediately after

2. Test before fix

Before fixing any bug:

  1. Write a test that demonstrates the bug
  2. Run the test — it MUST fail
  3. Fix the code
  4. Run the test — it MUST pass
  5. Run ALL tests: go test ./... -count=1 — nothing else broke

If you can’t write a failing test, you don’t understand the bug.

3. One thing at a time

Work on exactly ONE bug or feature per commit. No batching. No “while I’m here” changes.

  1. State what you’re fixing (one sentence)
  2. Write the failing test
  3. Make the minimal change
  4. Verify: go test ./... -count=1
  5. Commit
  6. Move to the next thing

If you find a second bug while fixing the first, NOTE it and move on.

A commit has no file-count limit. Say in the commit message what the change is and why every file in it belongs to that one change. Changes to the database schema (internal/db/migrations/), to sqlc.yaml, or to .gitlab-ci.yml are the ones a reviewer reads closely — call them out in the MR description so they get that attention.

4. Never modify tests to fix code

If your code change breaks an existing test, your code is wrong — not the test. Revert your change. The tests are the specification.

Exception: if a test is genuinely wrong (tests the wrong behavior), explain why before changing it.

5. Verify everything

After every change:

just check-fast

just check-fast is the inner loop (no network, no race detector); run the full just check, which mirrors CI, before pushing.

just check runs the same commands as these CI jobs:

  • check:go — golangci-lint, go test ./... -race -shuffle=on, go build, govulncheck, and the Go half of scripts/check-licenses.sh
  • check:file-size — scripts/check-file-size.sh (Go and Svelte LOC caps)
  • check:frontend — npm ci, npm run build, and the raw-fetch() layering gate
  • check:frontend-types — astro check over .astro, .svelte and .ts, and the npm half of scripts/check-licenses.sh
  • check:i18n — scripts/check-i18n.sh (no hardcoded English strings)
  • check:generated — just generate then git diff: sqlc output and types.ts must not move

Four CI jobs have no local equivalent and can only fail in the pipeline: check:secrets, check:hygiene, build:container and e2e:playwright. (just e2e runs the same specs, but is not part of just check — it takes minutes.) A green just check means those four are the only jobs still unproven.

Prohibited patterns

  • No raw http.Error() — use huma errors or Err()
  • No raw SQL in handlers — use sqlc
  • No raw fetch() in frontend — use the shared client
  • No any types in TypeScript — use generated types
  • No hand-editing generated files (types.ts, db/gen/, openapi.yaml)

Read the whole contract before opening a merge request: AGENTS.md.