How It Works
The AGENTS.md contributor contract: stop conditions, 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.
Stop conditions
If any of these are true, STOP immediately. Do not attempt another fix. Explain what happened and wait for the human.
- Tests failed twice on the same task. You tried a fix, tests broke,
you tried again, tests still break. STOP.
git checkout -- .and explain. - You’re about to modify a 4th file. Your change touches 3 files already and you need a 4th. STOP and explain what you’re doing.
- You’re modifying a test to make your code pass. STOP. Your code is wrong, not the test. Revert.
- You’re not sure what a function does. STOP. Read it. Read its tests. Read its callers. Then proceed.
- The build has been broken for more than 2 attempts. STOP. Revert
everything:
git checkout -- .and start over with a different approach.
The rules
These are non-negotiable. Violating them wastes human time.
1. Read before write
Before modifying ANY file:
- Read the entire file you’re about to change
- Read the test file for that package
- Run existing tests:
go test ./internal/{pkg}/... -v - Only then make your change
- Run tests again immediately after
2. Test before fix
Before fixing any bug:
- Write a test that demonstrates the bug
- Run the test — it MUST fail
- Fix the code
- Run the test — it MUST pass
- 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. Revert on regression
After EVERY change, run: go test ./... -count=1
If ANY package that was previously passing now fails:
git checkout -- .
Revert first. Think second. Explain what you tried and why it broke. Do NOT try to fix the regression with another patch.
4. One thing at a time
Work on exactly ONE bug or feature per commit. No batching. No “while I’m here” changes.
- State what you’re fixing (one sentence)
- Write the failing test
- Make the minimal change
- Verify:
go test ./... -count=1 - Commit
- Move to the next thing
If you find a second bug while fixing the first, NOTE it and move on.
5. Blast radius limit
Each commit touches at most 3 files. If your fix needs more than 3 files, STOP and explain what you’re doing. The human decides.
6. Protected files — do not modify without human approval
These files affect the entire system:
internal/api/helpers.go— shared helpersinternal/api/errors.go— error constantsinternal/api/api.go— API struct + middlewareinternal/server/server.go— server wiringinternal/db/migrations/— database schemasqlc.yaml— sqlc configuration.gitlab-ci.yml— CI pipelineAGENTS.md— this file
If you need to change a protected file, explain why and wait for approval.
7. 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.
8. Verify everything
After every change:
just check
This runs every local-runnable CI gate:
check:go— golangci-lint,go test ./...,go build, govulncheck, file-size limits (Go ≤400 / Svelte ≤250 LOC)check:frontend—npm ci,npm run build,npm audit --omit=dev --audit-level=highcheck:i18n—scripts/check-i18n.sh(no hardcoded English strings)- sqlc drift: run
just generateif you touched SQL or Go types;types.tsmust not differ from HEAD - openapi drift: run
just generateif you changed any huma operation; commit the updatedtypes.ts
If just check passes locally, it passes in CI.
Prohibited patterns
- No raw
http.Error()— use huma errors orErr() - No raw SQL in handlers — use sqlc
- No raw
fetch()in frontend — use the shared client - No
anytypes 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.