Raxx · internal docs

internal · gated

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.

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

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:

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:

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

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