Raklet Engineering Workflow¶
This is the canonical end-to-end workflow for shipping a change at Raklet.
Operating model¶
AI is the implementer. Humans are the gatekeepers.
The engineer takes a task from the tracker, hands the link to an AI agent (Claude or Codex), and the AI drives the work — planning, worktree creation, implementation, QA, PR — pausing at named gates for human approval. The engineer's job is no longer to write the code; it's to pick the work, approve the plan, approve the QA, and review the final PR. Humans give feedback when the AI gets it wrong; the AI iterates.
This shifts the engineer's leverage: instead of one task at a time, an engineer can supervise multiple AI-driven tasks in parallel, moving between them as gates open.
Tracker¶
We are transitioning from Trello (8+ years of use) to Linear. Linear is canonical for all new work going forward. During the transition both boards have active tickets:
- New tasks — features, bugs, ops, hotfixes — open as Linear issues.
- In-flight Trello cards stay on Trello until they ship; do not re-create them in Linear partway through.
- Pickup is fine from either board while the transition is in progress.
When the AI receives a Trello card, it links the card URL in the PR; when it
receives a Linear issue, it links
RAK-*. - If a customer report arrives without a ticket, the engineer who picks it up opens the Linear issue before handing the link to the AI.
The nine phases¶
Each phase has one required action and one artifact. Two human-approval gates sit inside the loop: the Plan Gate (after phase 3) and the QA Gate (after phase 5). Nothing past those gates happens without human signoff.
1. Pickup — engineer claims the task¶
Who: Engineer. Action: Move the Linear issue to In Progress (or the equivalent Trello column) and confirm your understanding of the task in a comment. Artifact: Ticket status moved, ticket link copied.
- If the task is ambiguous, get the author's confirmation in writing on the ticket before handing it to the AI. Ambiguous prompts produce ambiguous plans.
- Don't pick up ad-hoc work that isn't on a board. Open a Linear issue first, even for yourself.
2. Hand-off — engineer → AI¶
Who: Engineer. Action: Open Claude Code (or Codex CLI) and paste the ticket link with a short prompt: "Take this task: . Plan it, then check in with me before coding." Artifact: AI session started, AI has the ticket context.
- The engineer does not write the code. The engineer's role from here on is to approve at the two gates and to review the PR.
- One ticket = one AI session = one branch = one PR. Don't bundle multiple tickets into one AI session.
3. Plan — AI plans, human approves (Plan Gate)¶
Who: AI proposes, human approves.
Action: AI runs /autoplan (always). For non-trivial scope, AI also runs
/plan-eng-review and/or /plan-ceo-review. AI surfaces the plan to the
engineer. The engineer reviews, asks questions, and approves the plan.
Artifact: A plan document the engineer has explicitly approved.
/autoplanis the auto-decision pipeline — it surfaces only the genuine taste-decisions (close approaches, borderline scope, codex disagreements) for human input. It is mandatory for every issue./plan-eng-reviewis the engineering-manager-mode review. Run it when the task touches architecture, data flow, edge cases, performance, or test coverage. Engineer's judgment./plan-ceo-reviewis the founder/CEO-mode review (rethink the problem, challenge premises, find the 10-star product). Run it when the task is meaningful product scope and the AI should sanity-check ambition vs the smallest-version-that-works. Engineer's judgment, escalate to CEO/CTO when the call isn't yours to make.- No code is written before the plan is approved. This is the first hard gate. AI must wait.
- Acceptable to iterate: engineer pushes back, AI revises the plan, re-surfaces. Loop until the engineer types "approved" (or equivalent).
- For obvious tiny work (typo, copy fix, single-config bump), the AI can surface a one-line plan; the engineer can approve in one line.
4. Implement — AI does the work¶
Who: AI.
Action: AI creates a worktree from latest origin/master, branches in
type/short-kebab-summary form, and implements the approved plan with
logically grouped commits.
Artifact: A worktree under .claude/worktrees/<short-name>/ with commits
on a feature branch.
- AI uses
.agents/skills/worktree-workflow/SKILL.mdfor worktree commands. Ifpackages/references break, junction it to the main checkout'spackages/. - New task, release-fix, and promotion-unblocker branches always start from
origin/master. Do not branch fromtestorprod, and do not target them with manual fix PRs; fix onmasterand let Dev->Test / Test->Prod promotions carry the change forward. Emergency integration-branch work needs explicit approval in the current thread. - AI builds with
scripts/dev/build-fast.ps1— never rawmsbuild. - New
.csfiles MUST be registered in the matching old-style.csprojas<Compile Include="..." />. The build silently skips them otherwise. - Frontend asset changes under
Raklet.Backend/Content/needscripts/dev/invoke-backend-grunt.ps1to actually serve. - EF migrations go in their own branch and PR, released before the logic that depends on them — see Migration-first rule.
- AI does not deviate from the approved plan. If implementation reveals the plan was wrong, AI pauses and re-surfaces a revised plan to the engineer (back to phase 3) — does not just silently change direction.
5. QA — AI runs, engineer approves (QA Gate)¶
Who: AI runs the suites, engineer approves the result.
Action: AI runs /qa against the local environment. The skill captures
screenshots of the changed flows, uploads them to Azure Blob via the
pr-evidence skill, and posts a
QA report (test results + screenshot links) back to the engineer. The
engineer reviews the QA report and approves it.
Artifact: A QA report with screenshot URLs and pass/fail per scenario,
approved by the engineer.
- The engineer who handed the task to the AI is the same person who approves the QA. Self-approval is fine here — the second pair of eyes is the PR reviewer in phase 8, not this gate.
- If QA fails or the screenshots show something off, engineer gives feedback, AI iterates: fix → re-run QA → re-surface. Loop until QA passes.
- Screenshots are mandatory for any user-facing change (controllers,
views, services reached from controllers, JS/CSS bundles). They live in
Azure Blob (
rakletlocalfiles/customcodes/pr-evidence/<num>/), never in the repo. - Acceptable QA-skip cases (state in the PR): docs-only, infra-only
(CI/scripts/
.agents//.github/), build/csproj-only.
6. Open PR — AI, draft¶
Who: AI. Action: AI pushes the branch and opens a draft pull request with the full template body, the screenshot links from phase 5, and the ticket link. Artifact: Draft PR on GitHub linked to the Linear issue or Trello card.
- PR opens as draft. Phase 7 is what flips it to ready.
- Title: short, imperative, conventional-commit style:
fix(crm): denylist stale Stripe refs. Under 70 characters. - Body uses
.github/pull_request_template.mdsections (Problem / Root Cause / Solution / Scope of Change / Risk / Test Notes). Skip sections that don't apply, but state why. - Body must include:
- Ticket link (
Linear: RAK-273orTrello: <card url>) - Screenshot links from the QA run (Azure Blob URLs)
- Plan approval reference (one line: who approved, when)
- Re-check the description matches the actual diff after creation. PR text drifts during writing; catch it on first read.
7. Mark Ready — engineer flips draft to ready, CI runs¶
Who: Engineer. Action: After QA was approved (phase 5), engineer flips the PR from draft to ready. This triggers the full CI pipeline. Artifact: PR in Open state with CI checks running.
- Refresh the description checklist before flipping to ready. The "How to test" boxes and "Remaining todos for production" section are not write-once — they drift as the work evolves. Right before marking ready, the author re-reads every checkbox against the final diff and makes each one true and current:
- Delete boxes that no longer apply (a step you dropped, a template placeholder you never filled in, a check another PR now covers).
- Tick anything already verified — including steps CI/
/qaproved in phases 5–7. An unchecked box means "not yet done", so don't leave verified work unchecked. - Add any verification or production step the change introduced that isn't listed yet.
- Move real follow-up work that won't be done in this PR out of the checklist and into a Linear issue — don't leave it as a box.
This matters because the promotion gate later blocks Dev→Test / Test→Prod on these exact boxes. A stale unchecked box becomes a phantom blocker on every future promotion; a missing box lets unverified work ship. Curating the list at ready-time is what keeps the promotion gate meaningful instead of noise. The same review applies to any later push that changes scope — keep the checklist matching the diff. - The local QA in phase 5 is the smoke gate. The CI in phase 7 is the broader net (unit tests, integration tests, linters, build matrix). - Today: CI runs on GitHub Actions hosted runners on push, including while the PR is still draft. - Target state (in progress): CI for ready PRs runs on a Raklet-owned VM separate from developer machines. The dev machine is freed up the moment the engineer flips to ready; PR progress is tracked on GitHub. - After flip, the engineer can move on to the next task (handed to a new AI session). Watch the GitHub PR for CI status and reviewer feedback.
8. Review & Merge — peer reviewer approves, author squash-merges¶
Who: A different engineer (peer review), then the PR author merges.
Action: Peer reviewer reads the diff, the PR body, the screenshots. One
approval is required. Author squash-merges.
Artifact: A squash commit on master with the PR's title and body, and
a deleted feature branch.
- One approval is the standard. CODEOWNERS may add owners automatically for high-risk areas (payments, auth, migrations, prod infra) — wait for those if they appear.
- AI agents do not approve PRs. Copilot reviews are signal, not approval.
When Copilot or bot comments arrive, AI triages them with
.agents/skills/pr-comment-triage/SKILL.mdbefore the human reviewer sees them. - Author merges. Use
gh pr merge <num> --squash --delete-branch. No merge commits on master. mergeStateStatus: BLOCKEDon a PR with green CI usually means "review required" — master no longer requires CI checks to merge as of 2026-05-15.
9. Post-deploy — verify and close¶
Who: Engineer (the one who handed the task off, supervising the AI). Action: Verify the deploy landed and the live behavior matches expectations. Move the Linear issue to Done. Artifact: Linear issue moved to Done with a deploy timestamp and a brief "verified by …" note. (Trello cards still in flight: move to the Done column and link the merge commit.)
- Master deploys automatically through the Azure pipeline (master → test → prod). Watch the pipeline; deploy is not done until prod is green.
- For user-facing changes, run the post-deploy browse smoke against the
deployed environment:
This is the deployed-environment version of the same suite that ran in phase 5 against local. The hosted-runner workflow is
gh workflow run browse-ui-tests.yml --ref master ` -f suite=smoke ` -f test_domain=.raklet.net ` -f admin_url=https://admin.raklet.net/ng/ gh run watchworkflow_dispatchonly by design — it validates the deployed environment, not the PR branch. - Watch GlitchTip (monitor.raklet.net) for new exceptions tied to the change for the first hour after deploy.
Migration-first rule¶
EF migrations are released in their own PR, merged and deployed before the logic that depends on them. Two PRs, in order:
- Migration PR: the
Add-Migrationoutput and only that. Merged, deployed, verified on test. - Logic PR: the code that reads/writes the new schema. Merged after the migration is live in prod.
This protects against rollback scenarios where logic referencing a not-yet- shipped column starts throwing in prod. The AI must surface this split during the Plan phase — it is a planning decision, not an implementation detail.
Promotion gate: Dev→Test and Test→Prod¶
Master deploys roll out through two branch promotions — master → test and
test → prod — each opened automatically as a "Dev to Test" / "Test to Prod"
PR by dev-to-test.yml and
test-to-prod.yml.
A promotion PR must not be merged while any feature PR rolled up in it still has an outstanding description todo. This is a hard rule, not a suggestion. The "How to test" checkboxes and the "Remaining todos for production" section of a feature PR are the author's record of what must be verified or finished before the change is safe in test/prod — promoting with them open ships unverified or known-incomplete work to a shared environment.
To make this enforceable instead of trusting memory, every promotion PR carries an auto-generated checklist:
scripts/ci/promotion-checklist.mjsruns inside the promotion workflow each time the PR is opened or updated.- It enumerates every feature PR in the promotion (squash subjects ending in
(#N)), pulls each PR's outstanding todos, and posts one sticky comment on the promotion PR — a per-PR checklist with links straight back to each source PR, so the deployer knows exactly what to look at. - It sets a
promotion-todo-gatecommit status on the promotion PR: red while any todo is open, green when all are clear.
Before merging a Dev→Test or Test→Prod PR:
- Open the
promotion-todo-gatechecklist comment. - For each PR listed under Outstanding, complete the work and tick the box on that source PR (or, if a box is stale/not-applicable, edit it out and say why in the PR). The checklist refreshes on the next push.
- Merge only once
promotion-todo-gateis green.
A todo that genuinely does not gate the promotion (e.g. a follow-up tracked separately) should be removed from the source PR's description and captured as a Linear issue instead — don't leave it as an unchecked box that blocks every future rollout.
The gate is only as good as the boxes. It assumes each source PR's checklist was curated to be true and current when the PR was marked ready (phase 7). If you hit the gate and find a box is outdated — stale, a leftover template placeholder, or already satisfied — fix it at the source: edit the source PR's description (tick it if done, delete it if no longer applicable and note why), don't work around it on the promotion PR. The promotion gate enforces completion; keeping the items accurate is the author's job upstream, not the deployer's at promotion time.
What happens when you merge a promotion PR¶
Merging a promotion PR automatically starts the build on Azure DevOps. The
merge commit on test / prod triggers the corresponding AzDO build pipeline —
there is no manual "queue build" step. For Test→Prod, the build runs
automatically on merge, but the prod deploy stage then waits at a manual
approval gate before it goes live, so the new build serves at an unknown time
(minutes to days) after merge — see
prod-deploy-sentry-canary.md. The merge is
not the deploy: watch the AzDO pipeline through to the prod stage going green.
Two mechanics to know when clearing the gate to merge:
- The
promotion-todo-gatecheck only recomputes on a push to the destination branch. Ticking todo boxes on the rolled-up source PRs does not refresh the check, and re-running its workflow run is a no-op (the promotion PR already exists, so the gate step is skipped). It next recomputes on the following merge intomaster/test. So the check can read stale-red even when every blocking box is genuinely ticked — verify the boxes at the source (gh pr view <n> --json body) rather than trusting a stale status. testandprodhave no required status checks (onlymastercarries a ruleset). A stale-redpromotion-todo-gate— or an environmental red like the ci-vm-1 browsesmokeleg — therefore does not mechanically blockgh pr merge. That makes verifying the actual todo state (above) the real gate, not the check colour.
Tiny PR exception¶
For trivial changes — typo fix, formatting, single-config bump, doc-only — the workflow shortens but does not skip phases:
- Plan: AI surfaces a one-line plan; engineer approves in one line.
- QA: Skipped only when the change is genuinely docs-only, infra-only
(CI/scripts/
.agents//.github/), or build/csproj-only. State the skip reason in the PR. - Review & Merge: A single peer approval is still required. No self-merge for AI-authored PRs, even tiny ones — the human review is the audit trail for AI-generated code.
Rules of thumb¶
- AI implements, humans gate. No code without an approved plan. No PR ready without an approved QA. No merge without a peer review.
- Plan-first, code-second. If the AI starts coding before the plan is approved, stop the session and restart at phase 3.
- No promotion with open todos. Never merge a Dev→Test or Test→Prod PR while
promotion-todo-gateis red — every rolled-up PR's description todos must be complete first. See Promotion gate. - One ticket = one session = one PR. No multi-ticket bundles.
- No master commits. Worktree + branch + PR every time.
- Build with
build-fast.ps1. Never rawmsbuild. - English in all agent-facing files (commits, branches, PR text).
- No AI co-author trailers on commits, branches, or PRs unless explicitly requested.
- No screenshots or binaries in the repo. Always Azure Blob via
.agents/skills/pr-evidence/SKILL.md.
When things go wrong¶
- AI disagrees with the engineer at the Plan Gate: AI explains why, engineer either accepts the AI's reasoning or overrides explicitly. AI defers to human override but logs the disagreement in the plan.
- QA fails repeatedly: if the AI cannot get QA green after 2-3 iterations, pause and re-plan (back to phase 3). Don't keep grinding.
- Merge conflicts on the branch: AI rebases onto
origin/master, resolves in the worktree, force-pushes with--force-with-lease. Never--force. - CI failing on something the PR didn't change: engineer or AI checks
git log origin/masterfor recent infra changes. May be flaky or a real rebase need. - You shipped something that broke prod: revert first, investigate
after. Use the GitHub UI's Revert button on the merged PR (creates a
revert PR you fast-merge), or locally:
Page the on-call channel immediately. Post-mortem comes later, rollback comes now.
git revert <squash-commit-sha> gh pr create --title "Revert: <original title>" --fill gh pr merge --squash --delete-branch --admin - Local DB drift after a migration shuffle: see the resolved memory note
on Models-context drift, or ask
#engineering. Do not runUpdate-Databaseagainst a context that may have abandoned migrations.
Reference¶
.agents/AGENTS.md— canonical agent policy..agents/skills/— per-domain skills (build, test, QA, review, worktree, etc.)..agents/workflows/— workflow shortcuts that mirror the phases here..agents/context/sentry-no-silence-policy.md— Sentry no-mute triage and definition-of-done policy (ENG-165/ENG-161).scripts/dev/build-fast.ps1— fast .NET build.scripts/dev/pr-ready-check.ps1— pre-flight smoke runner (called by/qain phase 5).scripts/ci/promotion-checklist.mjs— Dev→Test / Test→Prod todo gate (sticky checklist comment +promotion-todo-gatecommit status).scripts/dev/invoke-backend-grunt.ps1— frontend asset rebuild..github/pull_request_template.md— PR template..github/workflows/— CI pipelines.PROJECT_DOCUMENTATION.md— repo architecture overview.
Gstack skills referenced in this workflow:
- /autoplan — mandatory in phase 3 for every issue.
- /plan-eng-review — phase 3, judgment.
- /plan-ceo-review — phase 3, judgment, escalate to CEO/CTO when needed.
- /plan-design-review — phase 3, when the task has UI/UX components.
- /qa — phase 5, mandatory for user-facing changes.
- /pr-evidence — phases 5 and 6, for Azure Blob screenshot uploads.