Git Guidelines (for agents)¶
Tactical conventions for branches, commits, and PRs in this repo. The high-level branch model and milestone cadence live in GIT-WORKFLOW.md; read both.
Issue validation gate (do this BEFORE any code)¶
Backend specs live as GitHub issues on project #3. An issue is only ready to be worked when the user (the human PO/lead) has read it and consciously moved it from Backlog → Ready on the board. That move is the validation signal. Without it, the agent has no green light.
Concretely, when the user asks you to work on issue #NN:
- Fetch the issue's current Status field value:
-
Refuse to start if Status is
Backlog. Reply with something like:Issue #NN is still in
Backlogon project #3. Please read it on the project board and move it toReadyto validate the spec. I'll wait — once it's inReady, ping me and I'll move it toIn progressand start. -
Refuse to start if Status is
In progress,QA, orDoneand the user hasn't explicitly explained why — that usually means another stream is in flight, and you should ask before stepping on it. - Once Status is
Ready, move it toIn progressyourself before writing any code. The mutation:The Status option IDs you'll need:# itemId comes from the previous query. gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input:{ projectId:"PVT_kwDOEDWgyc4BTwoh", itemId:"<itemId>", fieldId:"PVTSSF_lADOEDWgyc4BTwohzhA9WpI", value:{singleSelectOptionId:"47fc9ee4"} # 47fc9ee4 = "In progress" }) { projectV2Item { id } } }' f75ad846— Backlog61e4505c— Ready47fc9ee4— In progressdf73e18b— QA (used after PR merges)98236657— Done (set after the paired frontend issue closes; not by this repo's flow)- Only after the move to
In progresssucceeds, proceed to "Before you start" below.
This gate exists because every backend issue is paired with a frontend issue, and the spec on the card is the contract for both. Working on an unvalidated card means burning effort against requirements the user hasn't reviewed yet.
Before you start¶
- Always run
git statusfirst to see the current branch and any uncommitted changes. Never assume you are ondev— a previous session may have left you on a feature branch, possibly with unpushed work that you don't want to bury. - If the working tree is dirty, ask the user what to do. Do not stash, reset, or commit on their behalf without explicit permission.
- If you are already on a feature branch and the user is asking for new work, switch back to
devonly after confirming no unpushed commits will be lost. - Switch to
devand fast-forward:git switch dev && git pull --ff-only. Skipping this is the most common cause of avoidable conflicts. - Create the feature branch with
git switch -c <name>— nevergit checkout -b.checkoutoverloads file restoration and branch movement; the project prefers the modern split. - If your work depends on a still-open PR, branch from that PR's head — not
dev. Stacked PRs are fine; keep them small and merge in order.
Branch naming¶
The feature code matches the module/domain you're touching. Examples drawn from real history:
forms/submit-and-trigger-followupproject-leads/browse-pipelineproject-leads/filter-pipeline
Short, kebab-case, no issue numbers in the branch.
Commits¶
Format¶
<feature-area>: <imperative summary> (#<issue-number>)
<2–4 short paragraphs explaining what changed and why,
focusing on the substance of the change rather than the
file list. Wrap at ~72 chars.>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Real examples to mirror:
forms: submit and trigger follow-up (#53)project-leads: browse project pipeline (#61)project-leads: search + scoreTier + createdAt filters (#62)
Rules¶
- One feature = one PR, but feel free to split into multiple commits within the branch — fixup commits in response to review feedback are encouraged (e.g.,
forms: address PR feedback on submit slice). Do not amend; create new commits. - Pre-commit hooks must pass. Never use
--no-verify,--no-gpg-sign, or other bypasses without explicit user authorization. If a hook fails, fix the underlying issue. - Stage files explicitly by name, or use
git add -ufor modifications + named untracked files. Avoidgit add -A/git add .to keep accidental.env-like files out. - Always include the
Co-Authored-Bytrailer when an agent (Claude Code) authored or co-authored the work.
Pre-commit checklist¶
Run before committing:
pnpm run check:lint # must be 0 errors (warnings OK)
pnpm run check:format # must be clean
pnpm run test # all green
pnpm run test:e2e # all green
pnpm run build # clean compile
If a check finds something to auto-fix, run pnpm run lint (with --fix) or pnpm run format, re-stage, and commit.
Pull requests¶
Title¶
Same format as the commit summary, without the issue number suffix:
The issue link belongs in the body, not the title.
Body template¶
## Summary
- 2–5 bullets covering the user-visible change, the architectural decisions worth surfacing, and any seams introduced.
- Reference the issue number explicitly (e.g., "issue #61") so reviewers can jump to it.
## Out of scope (deferred)
- Things you deliberately did NOT do, with the issue number that owns each.
## Test plan
- [x] `pnpm run check:lint` — 0 errors.
- [x] `pnpm run check:format` — clean.
- [x] `pnpm run build` — clean.
- [x] `pnpm run test` — N passing (+ M new in `tests/...`).
- [x] `pnpm run test:e2e` — N passing (+ M new in `tests/e2e/...`).
- [ ] Manual smoke notes (curl, browser, etc.) when relevant.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Critical rules for backend PRs¶
- Never include
Closes #N(orFixes #N,Resolves #N) in the body. Backend issues stay open until the pairedikloze-frontend#NNissue closes. - Base branch is always
dev(unless you're stacking on another open backend PR, in which case base = that PR's head). - Keep the test plan honest. If you didn't manually smoke-test something, leave the box unchecked rather than ticking it speculatively.
Responding to review¶
Reply inline to each comment thread once you've addressed it. Use the GitHub API:
gh api repos/<owner>/<repo>/pulls/<PR>/comments \
-f body="Done in <commit-sha>: <one-sentence>." \
-F in_reply_to=<comment-id>
Reference the commit SHA that fixed it. Don't dismiss or hide threads — let the reviewer mark them resolved.
Post-merge ritual¶
When your backend PR is merged into dev:
- Move the GitHub issue to "QA" on project #3 — never to "Done". Closing happens later, when the paired frontend issue closes.
- The mutation:
# Find the project item id for the issue: gh api graphql -f query='query { repository(owner:"ikloze",name:"ikloze-backend") { issue(number:NN) { projectItems(first:5) { nodes { id project { title } } } } } }' # Move it (Status → "QA"): gh api graphql -f query='mutation { updateProjectV2ItemFieldValue(input:{ projectId:"PVT_kwDOEDWgyc4BTwoh", itemId:"<itemId>", fieldId:"PVTSSF_lADOEDWgyc4BTwohzhA9WpI", value:{singleSelectOptionId:"df73e18b"} }) { projectV2Item { id } } }' - Locally,
git switch dev && git pull --ff-only. If you have follow-up work on the same domain, recreate your next branch from the freshly pulleddev(or rebase a stacked branch onto it).
Database migrations¶
While v2 is in flight, schema changes to existing tables go into the original migration file in place — not a new follow-up migration. Brand-new tables for new feature areas still get their own migration. See CLAUDE.md for the canonical statement of this rule.
Things to never do¶
- Force-push to
devormain. Period. git reset --hardon a branch with unpushed work the user might want.- Update the
git config(user.name, user.email, signingkey, hooks). - Skip hooks (
--no-verify,--no-gpg-sign). - Amend a commit that has already been pushed.
- Commit
.env, credentials, or large binaries — even when staging with-A. - Close a backend issue manually. The frontend close cascade does it.
Quick reference¶
# Validate the issue first
# 1. Fetch its Status; refuse if Backlog.
# 2. Ask the user to move Backlog → Ready on project #3 if needed.
# 3. Once Ready, move it Ready → In progress yourself (option id 47fc9ee4).
# Start a new feature
git status # confirm current branch + clean tree
git switch dev && git pull --ff-only
git switch -c <area>/<short-description>
# Iterate
# ... edit, run pnpm checks ...
git add <files>
git commit -m "<area>: <summary> (#<issue>)" -m "<body>" -m "Co-Authored-By: ..."
git push -u origin <branch>
# Open the PR
gh pr create --base dev --title "<area>: <summary>" --body "<<EOF
... template above ...
EOF"
# After merge
gh api graphql -f query='...' # move issue to "QA"
git switch dev && git pull --ff-only