Adding a feature
The standard playbook.
0. Start with an issue
Either pick an existing sub-issue under an epic (#78–#81) or create one using the Feature Request template. Link the parent epic.
Do not start coding without an issue. Agents that work without a tracked issue make changes that slip through review.
1. Branch + flag
git fetch origin main
git switch -c feature/<short-name> origin/main
Always branch from origin/main. Never branch from another PR's branch or a
worktree-agent-* branch. Branching from a feature branch silently includes that
branch's commits in your PR and can cause ghost merges. On 2026-04-25 (incident
330) this caused content loss; on 2026-04-29 (#457) it contaminated an unrelated
PR with dep-bump commits. The CI job base_branch_lint in ci-pr.yml will block
your PR if contamination is detected.
Name feature flags FLAG_<SCREAMING_SNAKE> and add them to backend_v2/api/feature_flags.yaml with a default of false. Don't skip the flag for "small" features — a flag is your rollback path.
Required YAML fields (B1 gate will fail without these)
<flag_name>:
default: false
category: release # one of: release, experiment, ops, permission, business
surface: <surface> # one of: console, antlers, raptor, queue, status-page, getraxx, internal-docs, freescout, velvet, reasonator, ci, multi, legacy
soak_period_hours: <N> # 24 (low) / 48 (medium) / 72 (high)
area: <area>
risk: high|medium|low
description: "default OFF; <one-line description> (#NNN)"
references: # at least one entry per [ADR-0098](https://internal-docs.raxx.app/architecture/adr/0098-flag-operator-ux-and-pony-docs.html)
- kind: issue
number: <issue_number>
B1 promotion migration — same PR, specific path
When you add a new flag, you MUST also add an Alembic Python migration to console/migrations/versions/00NN_promote_<flag>.py. The B1 enforcement gate fails the PR without it.
- Path:
console/migrations/versions/(the Console Alembic chain). - NOT:
backend_v2/db/migrations/*.sql(that's the Raptor SQLite chain — the B1 gate does not scan it; the 2026-05-18 wave burned 3 PRs on this exact misplacement). - Filename:
00NN_promote_<flag_name>.pywhere NN is the next sequential revision. Checkls console/migrations/versions/ | tail -3for the current head. - Template: copy the most recent
console/migrations/versions/00*_promote_*.pyverbatim and adjustrevision,down_revision,_FLAG,_TARGET_APP,_SOAK(matchessoak_period_hours * 3600),_REASON,_RISK. The_FLAG = "<flag_name>"literal must appear within ~500 chars of_INSERT_SQLso the B1 regex matches.
If your CI fails with KeyError: <revision_id> in the Alembic gate after another PR merged, your migration's down_revision is now stale. Rebase on main and renumber to the next available 00NN.
See [[feedback_new_flag_needs_b1_migration_same_pr]] for the full failure-mode catalog.
2. Code + tests in the same commit
- Backend: add tests under
backend_v2/tests/. Copy the shape oftest_smoke_api.pyfor route tests. - Frontend: add tests under
frontend/trademaster_ui/src/**/__tests__/next to the code. - Do not merge feature code without the test that proves it works.
3. Run locally
./scripts/agent-tools/run_smoke.sh # full smoke sweep
python -m pytest backend_v2/tests -q # backend unit + integration
npm --prefix frontend/trademaster_ui test -- --watchAll=false # frontend
Playwright-driven UI verification is preferred when the feature has a visible component. Don't claim a feature works without actually loading it in a browser (headless or headed).
4. Security sanity
Before opening a PR, think about each of these and note them in the PR template:
- Auth / credentials touched?
- Order submission / broker integration touched?
- New external HTTP call or data source?
- New dependency?
If any "yes," expect the security-* CI jobs to scrutinize your PR. Bandit + pip-audit + npm audit + gitleaks run on every push.
5. Open the PR
Fill in the template completely. The sections aren't optional:
- What — 1-3 sentences.
- Why — link the issue.
- How to test — commands/URLs a reviewer runs in ≤2 min.
- Security — real answer, not "N/A".
- Flag — name the flag or justify no flag.
6. CI
CI runs:
- backend-tests — pytest
- frontend-tests — jest
- security-deps — pip-audit + npm audit
- security-sast — bandit
- security-secrets — gitleaks
HIGH/CRITICAL findings block merge. If the finding is a false positive, document the suppression in the PR and link the rule that generated it. Do not blindly add suppressions.
7. Merge
- One human review minimum (or designated agent review)
- CI green on all 5 jobs
- Flag defaulted to
falseunless we're ready to release
After merge, the flag stays false until a follow-up flip. That follow-up is its own PR with a "flip FLAG_X to true" title, so the release has an audit trail.
8. Close the loop
- Close the issue (auto via "Closes #N" in commit message)
- Update the parent epic checklist if applicable
- Note any lessons in
docs/agents/onboarding.mdso the next agent benefits