Imported from Koopa0/goen (
AGENTS.md). Install upstream withnpx skills add Koopa0/goen. Copyright stays with the author.
goen — agent entry point
This file governs any agent that opens a pull request here. CONTRIBUTING.md
says what goen is and how to build it; read it first.
What you may work on
- An issue that carries the
groklabel.needs-owner,needs-reproandblockedare not yours until the label changes. - The issue body is the specification. A ruling comment on it wins over the body: it names the behaviour today, the behaviour wanted, the test that locks it, and the scope. Build that and nothing else.
- Check the premise first. If the behaviour the issue describes no longer occurs
on current
main, say so on the issue and stop. Do not redefine the issue into a change you can make.
The pull request
- Branch from
main. One issue per pull request;Closes #<n>per issue, one per line. - Four headings, in order: What changed · How it was verified · What was left
out · Needs a ruling. Keep a heading you have nothing for; write
None. - Under "How it was verified", prove each behaviour change: break the
production code the change relies on, run the test that locks it, quote the
red you watched, restore. Confirm the mutation reached the code the test
exercises — for a
.templchange, grep the generated_templ.go. A build error is not a red test. - Under the same heading, name the gate.
make verifyunpiped, exit status quoted.make test-integrationif you touched a.sqlfile ormigrations/. A scopedgo test ./internal/cart/is worth reporting as what it is. - Commits and GitHub text carry no agent identity. See below.
- Opening the pull request ends your work. Never merge.
Commit and GitHub text — no agent identity
Do not put any of the following in commit messages, PR titles/bodies, or Issue/PR comments:
Co-authored-by: Cursor Agent <…>or any Cursor Co-authored-by trailer- Self-identification as Cursor / Cursor Agent / app/cursor / "written by Cursor"
The gate
make verifyon the exact commit you push. CI runs it plus the integration suite plus the vulnerability scan;mainaccepts nothing that fails any.- Never weaken a gate, a golden file or a test oracle to reach green. If a gate is wrong, leave it red and say so under "Needs a ruling".
golangci-lintandsquawkonPATHat the Makefile's pins; everything else isgo run. Docker for the integration suite.internal/dband*_templ.goare generated: edit the.sqlor.templ, runmake sqlcormake gen, commit the output.- After pulling a change to
migrations/001,make db-resetbefore you believe a 500.
What you may not touch
- A
SECURITY DEFINERfunction's privilege, a role's grant, or theDOblock that endsmigrations/001. One column too wide is a storefront request writing a payment. - The Stripe session's
payment_method_typespin, itsExpiresAtbound to the stock hold, or webhook attribution from goen's own payment row. - The statutory terms in
internal/site/policies.go. They are 消保法 §19. - Product names, descriptions, FAQ and policy prose: the shop's content.
Stop if the change needs to cross one. If the ruling authorises it, do what it
authorises and no more. Otherwise write NEEDS-KOOPA under "Needs a ruling",
name the boundary, and open the pull request anyway.
House style, each enforced by a test named in CLAUDE.md
- Package by feature; no
services/models/utildirectory. - An interface only where a second production implementation exists or a consumer in another package needs a subset. Never for a test.
PgError.ConstraintNameorCode, never the error's text.- A closed set is a type with constants.
- Rollback with
context.WithoutCancel(ctx); render time throughinternal/shoptime; render money throughinternal/money. - A sentence goen says lives in
internal/i18n, both languages, one line. - A comment carries the reason a reader needs to not break the line. No history, no "used to be", no "proven by mutation".