@chris1807/claude-kit 2.1.54 → 2.1.56

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -98,12 +98,13 @@ Claude maintains persistent memory across sessions in `~/.claude/projects/.../me
98
98
  1. **Pick a work item** from Azure DevOps (or describe what you need)
99
99
  2. **Claude implements** using `/implement AB#<id>` (auto-creates branch)
100
100
  3. **Hooks guard** against secrets and bad patterns automatically
101
- 4. **PR merges** into `develop` → deploys to Dev environment
102
- 5. **Create a release** using `/create-release <N>` to group work items
103
- 6. **Deploy the release** using `/deploy-release 23 staging` then `/deploy-release 23 production`
104
- 7. **Test** using Playwright MCP for browser testing
105
- 8. **Track** work items via the Azure DevOps MCP server
106
- 9. **Learn** — Claude saves what worked for next time
101
+ 4. **PR merges** into `main` — the compare branch. **Nothing deploys yet.** The work item stays in `Code Review` until it is promoted
102
+ 5. **Promote or release** — `/promote main dev` carries everything on `main` to Dev; `/create-release <N>` groups work items so `/deploy-release <N> test` → `staging` → `prod` can carry just those
103
+ 6. **Say who verifies** — before the merge, the command asks who each product group (`COM`, `PAY`, …) should be assigned to in the target environment, offering the non-developer names already on those work items
104
+ 7. **Merge each promotion PR** — that merge triggers the environment's CD pipeline. The command watches it and, once it's green, sets the work items to `Testing`, `Staging`, or `Deployed` **and** assigns them to the approved verifiers — automatically, no reply needed
105
+ 8. **Test** using Playwright MCP for browser testing
106
+ 9. **Track** work items via the Azure DevOps MCP server
107
+ 10. **Learn** — Claude saves what worked for next time
107
108
 
108
109
  ### Story Points & Dev Ready Policy
109
110
 
@@ -121,33 +122,71 @@ These rules apply to **every** command or flow that creates or estimates work it
121
122
  An item that merely **needs to be split** keeps its state and gets no tag — the work is understood, nothing is missing.
122
123
 
123
124
  **The drop-out mechanism has no expiry, so every sweep must audit it.** Removing the `needs-info` tag is the *only* thing that re-queues a bug, and moving a story back to `Design Approved` is the only thing that re-queues a story. A creator who supplies the missing information but leaves the tag on — or answers in a comment instead of editing the field — makes the item invisible to every future sweep, permanently. That failure looks exactly like a clean backlog. `/quote-backlog` Step 2b therefore audits tagged items for activity after the tag was applied and reports the stale ones; it never clears a tag on the creator's behalf. Two traps when writing such a check: automation bots bump a revision after nearly every human write, so the *latest* revision author is unreliable — scan the whole range after the tag revision; and a `System.CommentCount` increase counts as a creator response.
124
- 6. **Never assume two work item types share a state list.** WIQL doesn't validate state names, so a query filtering on a state the type doesn't have returns **zero rows instead of an error** — the classic symptom is a backlog sweep that silently never surfaces a single bug. Confirm with `mcp__azure-devops__wit_work_item` (`action: get_type`) before writing a state name into a query or an update. In CSI Development: `User Story` has `New → Dev Ready → In Design → Design Review → Design Approved → Active → …`; `Bug` and `Hot Fix` have `New → Dev Ready → Active → …`.
125
+ 6. **Never assume two work item types share a state list.** WIQL doesn't validate state names, so a query filtering on a state the type doesn't have returns **zero rows instead of an error** — the classic symptom is a backlog sweep that silently never surfaces a single bug. Confirm with `mcp__azure-devops__wit_work_item` (`action: get_type`) before writing a state name into a query or an update. In CSI Development (verified 2026-09-06): `User Story` has `New → Dev Ready → In Design → Design Review → Design Approved → Active → Code Review → Ready for Testing → Testing → Ready for Staging → Staging → Ready to Deploy → Deployed → Closed`; `Bug` and `Hot Fix` have the same list minus the three design states (`New → Dev Ready → Active → Code Review → …`). `Ready for Staging` and `Staging` were added on 2026-09-06 so every environment has a state — see **Work Item States ↔ Environments** below.
125
126
 
126
127
  ### Branching Strategy
127
128
 
128
129
  #### Target Branch-to-Environment Mapping
129
130
 
130
- All projects should converge to this standard. Each long-lived branch maps to an Azure subscription and environment:
131
+ All projects converge to this standard. `main` is the **compare branch** — the default branch, the one feature PRs target, and the one every environment branch is compared against. **Merging into `main` deploys nothing.** Each environment has its own long-lived branch, and a PR merging into that branch is what triggers its CD pipeline:
131
132
 
132
- | Branch | Azure Subscription | Environment | CD Pipeline Trigger |
133
- |---|---|---|---|
134
- | `develop` | Dev | Development | Auto on merge |
135
- | `staging` | Staging | Staging | Auto on merge |
136
- | `main` | Production | Production | Auto on merge (with approval gate) |
133
+ | Branch | Environment | CD Pipeline Trigger |
134
+ |---|---|---|
135
+ | `main` | — (compare / integration branch) | **None** — merging a PR into `main` does not deploy |
136
+ | `dev` | Development | Auto when a PR merges into `dev` |
137
+ | `test` | Test (QA) | Auto when a PR merges into `test` |
138
+ | `staging` | Staging | Auto when a PR merges into `staging` |
139
+ | `prod` | Production | Auto when a PR merges into `prod` |
140
+
141
+ Branch names are lowercase. COMPASS and CSIPay are on this layout (CSIPay renamed its branches on 2026-09-04; `test` replaced `QA`).
137
142
 
138
- > **Note:** Some projects are not yet in sync — they may use `master` instead of `main`, or lack a `staging` branch. Until a project is migrated, the deployer and `/implement` use the **current branch** dynamically and do not assume branch names.
143
+ > **Note:** A project that hasn't migrated yet (e.g. one that still has only `main` and `develop`) keeps working — the deployer and every slash command read the project's **Pipeline Configuration** table and use the **current branch** dynamically; no branch names are hardcoded.
139
144
 
140
145
  #### Promotion Flow
141
146
 
142
- Code flows through environments via PRs — never by direct push:
147
+ Code flows through environments via PRs — never by direct push. Every arrow below is a PR, and every merge **after** `main` deploys:
143
148
 
144
149
  ```
145
- feature/AB#1234-... ──PR──▸ develop ──PR──▸ staging ──PR──▸ main
146
- (work branch) (Dev) (Staging) (Production)
150
+ feature/AB#1234-... ──PR──▸ main ──PR──▸ dev ──PR──▸ test ──PR──▸ staging ──PR──▸ prod
151
+ (work branch) (compare, (Dev) (Test) (Staging) (Production)
152
+ no deploy)
147
153
  ```
148
154
 
149
- - **develop → staging**: PR to promote all work ready for QA/stakeholder review
150
- - **staging → main**: PR to promote to production. May cherry-pick individual commits if only some stories are ready (see Cherry-Pick Deployments below)
155
+ - **feature → main**: the `/implement` PR. Code review happens here. Merging it deploys nothing.
156
+ - **main → dev**: `/promote main dev` — usually everything on `main`, so developers can smoke-test on Dev.
157
+ - **dev → test**: `/promote dev test` or `/deploy-release <N> test` — hands the work to QA.
158
+ - **test → staging**: `/deploy-release <N> staging` — only what QA passed (`Ready for Staging`).
159
+ - **staging → prod**: `/deploy-release <N> prod` — only what stakeholders approved (`Ready to Deploy`). Cherry-pick a subset when only some stories are ready (see Cherry-Pick Deployments below).
160
+
161
+ #### Work Item States ↔ Environments
162
+
163
+ Every environment in the chain has a work item state, so the board shows where each story physically is. The **"Ready for …" states are human gates** — QA or stakeholders set them when something passes; the slash commands never do. The **environment states** (`Testing`, `Staging`, `Deployed`) are set by the promotion commands once the PR into that branch has merged and its CD pipeline has come back green.
164
+
165
+ | Branch | Environment | Gate — items should already be in… | Set once the PR into this branch merges |
166
+ |---|---|---|---|
167
+ | `main` | — | `Code Review` (the `/implement` PR is open) | *(no change — nothing deployed)* |
168
+ | `dev` | Dev | `Code Review` (merged to `main`) | `Ready for Testing` |
169
+ | `test` | Test | `Ready for Testing` | `Testing` |
170
+ | `staging` | Staging | `Ready for Staging` | `Staging` |
171
+ | `prod` | Production | `Ready to Deploy` | `Deployed` |
172
+
173
+ Human-only transitions — no slash command ever makes these: `Testing → Ready for Staging` (QA sign-off), `Staging → Ready to Deploy` (stakeholder / UAT sign-off), `Deployed → Closed` (verified in production).
174
+
175
+ How the commands use this table:
176
+
177
+ - **Gate check before the PR.** `/deploy-release`, `/cherry-pick`, and `/promote` compare each carried work item's state against the gate for the target environment. Anything behind the gate (e.g. still `Testing` when deploying to `staging`) is flagged and the user decides whether to include it. Items *ahead* of the gate (e.g. already `Deployed` on a cherry-pick to `prod`) are reported and left alone.
178
+ - **Advance on a green pipeline, automatically.** `/promote`, `/cherry-pick`, and `/deploy-release` do not stop at the PR. They poll it until it is `completed`, then poll the target branch's CD pipeline until every run finishes. Only on `succeeded` do they write the new state — for every carried User Story, Bug, and Hot Fix, never a Feature or Task, and never backward. A failed or canceled run changes **nothing** and is reported with the log link. `/status` reports items whose state lags the branch their commits are on and offers to catch them up.
179
+ - **Assign the verifier at the same time.** The state change hands the item to a person, so the same three commands ask **before the merge** who each group of items should go to, then apply the assignee alongside the state once the pipeline is green. See **Verifier Assignment** below.
180
+ - **Never assume the state list.** Confirm with `mcp__azure-devops__wit_work_item` (`action: get_type`) on an unfamiliar project before writing a state name — a bad name is accepted silently by a query and rejected only at write time.
181
+
182
+ #### Verifier Assignment
183
+
184
+ Moving an item to `Testing`, `Staging`, or `Deployed` puts it on someone's plate, so `/promote`, `/cherry-pick`, and `/deploy-release` also change who owns it. The developer implemented it; from here on it belongs to whoever checks it in that environment.
185
+
186
+ - **Grouped by product prefix.** Work item titles are `PREFIX - Title`, so the commands group the carried items by prefix (`COM`, `PAY`, `CDA`, …) and ask **one question per group**. A staging → prod deploy carrying 2 `COM` and 2 `PAY` items asks twice; answering with the same person both times is fine, and `all 1` gives the whole batch to one person.
187
+ - **Candidates come from the work items, never from a directory.** For each group the commands read the items' own history — who set the gate state (`Ready for Staging` / `Ready to Deploy`, from `list_revisions`), who created the item, who commented on it, who last edited it — then subtract the developers (current assignee, PR author, commit authors). What's left are the non-developer names actually attached to that work, ranked with the sign-off setter first. No name is ever invented.
188
+ - **Asked before the merge, applied after.** The question comes while the PR is still in review and requires an explicit `yes`; nothing is written until the CD pipeline reports success. Then state and `System.AssignedTo` are set in the same update, and the report shows `was → now` for both so a wrong assignment is one edit to undo.
189
+ - **`Leave the current assignee alone`** is always an option — the commands never clear an assignee, and never touch a Feature's or a Task's assignee.
151
190
 
152
191
  #### Release Management
153
192
 
@@ -161,43 +200,47 @@ This creates a `Release #23` iteration, assigns the selected work items to it, a
161
200
 
162
201
  **Deploying a release to an environment:**
163
202
  ```
203
+ /deploy-release 23 test
164
204
  /deploy-release 23 staging
165
- /deploy-release 23 production
205
+ /deploy-release 23 prod
166
206
  ```
167
- This finds all work items in Release #23, cherry-picks their commits into a release branch (`release/23-to-staging`), creates a PR targeting the environment branch, and links all work items.
207
+ This finds all work items in Release #23, checks each one against the target environment's gate state, cherry-picks their commits into a release branch (`release/23-to-staging`), creates a PR targeting the environment branch, links all work items, asks who verifies each product group, and — once the merge's CD pipeline comes back green — advances them to the environment's state (`Testing`, `Staging`, `Deployed`) and assigns them to those verifiers.
168
208
 
169
- **Selective deployment:** Since releases are deployed via cherry-pick, you can deploy a full release or a subset. If staging has 5 user stories but only 3 should go to production, create a release with just those 3 and deploy it.
209
+ **Selective deployment:** Since releases are deployed via cherry-pick, you can deploy a full release or a subset. If staging has 5 user stories but only 3 are `Ready to Deploy`, create a release with just those 3 and deploy it.
170
210
 
171
211
  **Release flow:**
172
212
  ```
173
213
  /create-release 23 → Groups work items into Release #23
174
- /deploy-release 23 staging → Cherry-picks Release #23 to staging
175
- (QA/testing on staging)
176
- /deploy-release 23 → Auto-detects next env (production), deploys
214
+ /deploy-release 23 test → Cherry-picks Release #23 to test → items go to Testing
215
+ (QA passes → sets Ready for Staging)
216
+ /deploy-release 23 → Auto-detects next env (staging) → items go to Staging
217
+ (stakeholders approve → set Ready to Deploy)
218
+ /deploy-release 23 → Auto-detects next env (prod) → items go to Deployed
177
219
  ```
178
220
 
179
221
  #### Cherry-Pick Deployments
180
222
 
181
223
  Cherry-pick specific work items to an environment without a formal release:
182
224
  ```
183
- /cherry-pick AB#1234 AB#1235 production
225
+ /cherry-pick AB#1234 AB#1235 prod
184
226
  ```
185
- This finds commits for the specified work items, cherry-picks them into a branch (`cherry-pick/<date>-to-<environment>`), and creates a PR.
227
+ This finds commits for the specified work items, checks them against the target's gate state, cherry-picks them into a branch (`cherry-pick/<date>-to-<environment>`), creates a PR, asks who verifies each product group, and — once the merge's CD pipeline is green — advances and assigns the work items.
186
228
 
187
229
  #### Promoting Environments
188
230
 
189
231
  Promote all code from one environment to the next:
190
232
  ```
191
- /promote staging production
233
+ /promote main dev
234
+ /promote staging prod
192
235
  /promote ← auto-detects source and target from current branch
193
236
  ```
194
- This creates a PR from the source branch to the target branch with a summary of all included commits.
237
+ This creates a PR from the source branch to the target branch with a summary of all included commits and their work items, checks the work items against the target's gate state, asks who verifies each product group, and — once the merge's CD pipeline is green — advances and assigns them. `main → dev` is the usual first hop after feature PRs merge.
195
238
 
196
239
  #### Rollbacks
197
240
 
198
241
  Roll back a deployment on any environment:
199
242
  ```
200
- /rollback AB#1234 production ← revert specific work items
243
+ /rollback AB#1234 prod ← revert specific work items
201
244
  /rollback last staging ← revert the most recent deployment
202
245
  ```
203
246
  This creates a revert branch, reverts the specified commits, runs pre-flight checks, and creates a PR.
@@ -211,7 +254,7 @@ Commit, push, and deploy the current changes:
211
254
  /deploy "Add payment export feature"
212
255
  /deploy ← auto-generates commit message
213
256
  ```
214
- This runs pre-flight checks, commits, pushes the current branch, and triggers the CD pipeline if on an environment branch.
257
+ This runs pre-flight checks, commits, pushes the current branch, and triggers the CD pipeline if on an environment branch (`dev`, `test`, `staging`, `prod`). On `main` or a work branch nothing is triggered — `main` has no pipeline.
215
258
 
216
259
  #### Branch Naming Convention
217
260
 
@@ -235,13 +278,13 @@ PRs always target the branch you were on when `/implement` was invoked. The base
235
278
 
236
279
  #### Hot Fix Workflow
237
280
 
238
- Hot Fix work items follow the same automated checks (build, lint, tests, review) but skip manual UAT. An abbreviated confirmation is shown instead. Hot Fix PRs get a `hotfix` label. Hot Fixes target the current branch (which should be the project's production branch for production hot fixes).
281
+ Hot Fix work items follow the same automated checks (build, lint, tests, review) but skip manual UAT. An abbreviated confirmation is shown instead. Hot Fix PRs get a `hotfix` label. Hot Fixes target the current branch — for a production hot fix, start on `prod` so the PR merges (and deploys) straight there. **Then bring the fix back to `main`:** open a second PR from the same hotfix branch into `main` (or `/cherry-pick AB#<id> main`) so the next `main → dev` promotion doesn't overwrite it. A hot fix that lives only on `prod` is lost on the next release.
239
282
 
240
283
  #### Feature Workflow (ordered story waves)
241
284
 
242
285
  Running `/implement` on a **Feature** implements its child User Stories in **waves** driven by the `Custom.Order` field: stories sharing the same order value are implemented **in parallel** (one agent per story, each in an isolated git worktree), and waves run sequentially in ascending order so later stories build on earlier ones. All work merges into a single `feature/AB#<id>-...` branch; quality checks, code review, UAT, and one PR happen at the feature level, and every implemented story is linked to that PR. Stories without a `Custom.Order` value run in a final catch-all wave (flagged for confirmation first).
243
286
 
244
- **Work item states:** `/implement` moves the work item to `Active` when implementation starts — for a single work item (User Story, Bug, Hot Fix) right after the branch is created; for a Feature, each child story goes `Active` as its wave begins. When the PR is created, each implemented child **User Story** moves to `Code Review` — the **Feature's state is never changed**. The Feature is a parent container; it advances only as its child stories are verified/closed. Only child **Tasks** are ever closed — never the stories or the Feature.
287
+ **Work item states:** `/implement` moves the work item to `Active` when implementation starts — for a single work item (User Story, Bug, Hot Fix) right after the branch is created; for a Feature, each child story goes `Active` as its wave begins. When the PR is created, each implemented child **User Story** moves to `Code Review` — the **Feature's state is never changed**. The Feature is a parent container; it advances only as its child stories are verified/closed. Only child **Tasks** are ever closed — never the stories or the Feature. From `Code Review` onward the stories follow the **Work Item States ↔ Environments** table above as they are promoted.
245
288
 
246
289
  **Hours live on the Task.** `/implement` will not implement a story that has no open child Task: if there isn't one, it proposes a title and an hour estimate (from the story's points, same mapping `/plan-backlog` uses — points set the hour band, complexity picks where in the band it lands) and creates it once the user agrees — exactly one per story, inheriting the parent's assignee, area, and iteration. When the PR is created, that Task is closed with the hours worked logged to `CompletedWork` and `RemainingWork` zeroed. Closing happens at **PR creation**, not at merge, so hours are recorded while they're still known. Never enable Azure DevOps's "Complete associated work items" when merging — it transitions the parent too.
247
290
 
@@ -254,14 +297,15 @@ All deployment and release operations are available as slash commands:
254
297
  | `/implement` | `/implement AB#1234` | Summarize work item → approve plan → ensure an open child Task with hours → implement → PR (closes the Task, logs hours). On a Feature: child stories in `Custom.Order` waves, same-order stories in parallel |
255
298
  | `/review` | `/review 142` | Automated code review on a PR |
256
299
  | `/resolve-feedback` | `/resolve-feedback 142` | Address unresolved PR comment threads, push fixes, reply + resolve threads |
257
- | `/deploy` | `/deploy "commit message"` | Commit, push, trigger pipeline |
300
+ | `/deploy` | `/deploy "commit message"` | Commit, push, trigger pipeline (only on `dev`/`test`/`staging`/`prod` — never on `main`) |
258
301
  | `/create-release` | `/create-release 23` | Group work items into Release #23 |
259
- | `/deploy-release` | `/deploy-release 23 staging` | Cherry-pick release to environment |
302
+ | `/deploy-release` | `/deploy-release 23 staging` | Gate-check → cherry-pick release to environment → PR → ask who verifies → advance + assign on a green pipeline |
260
303
  | `/add-to-release` | `/add-to-release 24 AB#4599` | Add work items to existing release |
261
- | `/cherry-pick` | `/cherry-pick AB#1234 AB#1235 production` | Cherry-pick specific work items |
262
- | `/promote` | `/promote staging production` | Promote all code between environments |
263
- | `/rollback` | `/rollback AB#1234 production` | Revert commits on an environment |
264
- | `/status` | `/status release 24` | Check release, pipeline, or work item status |
304
+ | `/cherry-pick` | `/cherry-pick AB#1234 AB#1235 prod` | Gate-check → cherry-pick specific work items → PR → ask who verifies → advance + assign on a green pipeline |
305
+ | `/promote` | `/promote main dev` | Promote all code between environments (`main → dev → test → staging → prod`) → ask who verifies → advance + assign on a green pipeline |
306
+ | `/rollback` | `/rollback AB#1234 prod` | Revert commits on an environment |
307
+ | `/status` | `/status release 24` | Check release, pipeline, environment, or work item status; flags work items whose state lags their environment |
308
+ | `/where` | `/where AB#1234` | Show which environment branches contain a work item's commits |
265
309
  | `/plan-backlog` | `/plan-backlog [project]` | Sweep backlog for Dev Ready stories with points and no tasks → propose child tasks with hours |
266
310
  | `/plan-sprint` | `/plan-sprint [project]` | Sweep the current sprint for stories/bugs with no child tasks → propose one child task with hours per item |
267
311
  | `/quote-backlog` | `/quote-backlog [project]` | Sweep backlog for unpointed items ready to estimate — stories in `Design Approved`, **bugs in `New`** (bugs have no design states) → review completeness, check for duplicates, suggest rewrites, propose points + creator comments (10 at a time, approval-gated). Pointed items move to Dev Ready; stories that can't be quoted move back to **Design Review**, bugs that can't be quoted get a **`needs-info`** tag, so the next sweep skips them. Every run also audits the drop-out queue (tagged bugs **and** stories bounced to Design Review) and reports any whose creator answered but which nobody returned to the sweep — neither mechanism expires, so those are otherwise invisible forever |
@@ -271,11 +315,11 @@ All deployment and release operations are available as slash commands:
271
315
  | `/cleanup-branches` | `/cleanup-branches` | Delete merged branches |
272
316
  | `/close-orphan-tasks` | `/close-orphan-tasks [scope] [--dry-run]` | Close open Tasks whose parent is Ready to Deploy / Deployed / Closed |
273
317
 
274
- The CD pipeline is only triggered manually when pushing directly to an environment branch. For feature/work branches, the pipeline triggers on PR merge.
318
+ The CD pipeline is only triggered manually when pushing directly to an environment branch (`dev`, `test`, `staging`, `prod`). For feature/work branches and for `main`, nothing is triggered — a feature PR merging into `main` deploys nothing; the first deployment happens when `main` is promoted to `dev`.
275
319
 
276
320
  ### Pipeline Configuration
277
321
 
278
- Each project must define its environment chain and pipeline IDs so the slash commands (`/deploy`, `/promote`, `/deploy-release`) know which pipelines to trigger and what the promotion order is.
322
+ Each project must define its compare branch, its environment chain, and its pipeline IDs so the slash commands (`/deploy`, `/promote`, `/deploy-release`, `/cherry-pick`, `/where`, `/status`) know which pipelines to trigger and what the promotion order is.
279
323
 
280
324
  Add this section to your project's `CLAUDE.md`:
281
325
 
@@ -284,33 +328,50 @@ Add this section to your project's `CLAUDE.md`:
284
328
 
285
329
  | Branch | Environment | Pipeline(s) |
286
330
  |--------|------------|-------------|
287
- | develop | Dev | My API (ID), My Client (ID) |
331
+ | main | — (compare branch, no deployment) | — |
332
+ | dev | Dev | My API (ID), My Client (ID) |
333
+ | test | Test | My API (ID), My Client (ID) |
288
334
  | staging | Staging | My API (ID), My Client (ID) |
289
- | main | Production | My API (ID), My Client (ID) |
335
+ | prod | Production | My API (ID), My Client (ID) |
290
336
  ```
291
337
 
292
338
  **Rules for slash commands:**
293
- - `/deploy` triggers the pipeline(s) listed for the current branch. If the current branch is not in this table, no pipeline is triggered.
294
- - `/promote` uses this table to determine the next environment (e.g., `develop` → `staging` → `main`).
295
- - `/deploy-release` and `/cherry-pick` create PRs targeting environment branches listed here.
296
- - The **order of rows** defines the promotion flow (top to bottom).
339
+ - The **first row is the compare branch**. Feature PRs target it. It has no pipeline — merging into it deploys nothing. A row whose Pipeline(s) cell is `—` is never triggered.
340
+ - The **order of rows** defines the promotion flow (top to bottom): `main → dev → test → staging → prod`.
341
+ - `/deploy` triggers the pipeline(s) listed for the current branch. If the current branch is not in this table, or its pipeline cell is `—`, no pipeline is triggered.
342
+ - `/promote` uses this table to determine the next environment (the next row down).
343
+ - `/deploy-release` and `/cherry-pick` create PRs targeting environment branches listed here, and use the **Work Item States ↔ Environments** table to gate-check and advance work items.
344
+ - `/where` and `/status` check every row; the compare branch reports as "merged to main", not as a deployment.
297
345
 
298
346
  **Examples from actual projects:**
299
347
 
300
- CSIPay (4 environments):
348
+ COMPASS:
349
+ ```markdown
350
+ | Branch | Environment | Pipeline(s) |
351
+ |--------|------------|-------------|
352
+ | main | — (compare branch, no deployment) | — |
353
+ | dev | Dev | Compass API (YAML) (32), Compass Client (YAML) (33) |
354
+ | test | Test | Compass API (YAML) (32), Compass Client (YAML) (33) |
355
+ | staging | Staging | Compass API (YAML) (32), Compass Client (YAML) (33) |
356
+ | prod | Production | Compass API (YAML) (32), Compass Client (YAML) (33) |
357
+ ```
358
+
359
+ CSIPay:
301
360
  ```markdown
302
361
  | Branch | Environment | Pipeline(s) |
303
362
  |--------|------------|-------------|
304
- | Dev | Dev | CSIPay API (12), CSIPay Client (13) |
305
- | QA | QA | CSIPay API (12), CSIPay Client (13) |
306
- | Staging | Staging | CSIPay API (12), CSIPay Client (13) |
307
- | master | Production | CSIPay API (12), CSIPay Client (13) |
363
+ | main | — (compare branch, no deployment) | — |
364
+ | dev | Dev | CSIPay API (12), CSIPay Client (13) |
365
+ | test | Test | CSIPay API (12), CSIPay Client (13) |
366
+ | staging | Staging | CSIPay API (12), CSIPay Client (13) |
367
+ | prod | Production | CSIPay API (12), CSIPay Client (13) |
308
368
  ```
309
369
 
310
- Glasswing and Monarch (1 environment currently):
370
+ Glasswing and Monarch (not yet migrated — 1 environment):
311
371
  ```markdown
312
372
  | Branch | Environment | Pipeline(s) |
313
373
  |--------|------------|-------------|
374
+ | main | — (compare branch, no deployment) | — |
314
375
  | develop | Dev | CD - Development (28) |
315
376
  ```
316
377
 
@@ -6,20 +6,28 @@
6
6
  # Usage:
7
7
  # 1. Copy this file to your project root as azure-pipelines.yml
8
8
  # 2. Replace all {{PLACEHOLDER}} values with your project-specific values
9
- # 3. Remove stages you don't need (e.g., QA if your project doesn't have it)
9
+ # 3. Remove stages you don't need (e.g., Test if your project doesn't have it)
10
10
  # 4. Create a new pipeline in Azure DevOps pointing to this file
11
11
  #
12
12
  # Branch-to-environment mapping:
13
- # develop → Dev
13
+ # main → (compare branch — NOT a trigger; merging a PR into main deploys nothing)
14
+ # dev → Dev
15
+ # test → Test
14
16
  # staging → Staging
15
- # main → Production
17
+ # prod → Production
18
+ #
19
+ # Code moves main → dev → test → staging → prod by PR; each merge below main
20
+ # triggers this pipeline for that one environment.
16
21
 
17
22
  trigger:
18
23
  branches:
19
24
  include:
20
- - develop
25
+ - dev
26
+ - test
21
27
  - staging
22
- - main
28
+ - prod
29
+ exclude:
30
+ - main # compare branch — never deploys
23
31
  paths:
24
32
  include:
25
33
  - "{{PROJECT_PATH}}/**" # e.g., Api/**, Client/**, src/**
@@ -37,6 +45,10 @@ variables:
37
45
  devWebsiteName: "{{DEV_WEBSITE_NAME}}" # e.g., dev.api.compass.caresolutions.com
38
46
  devAppPoolName: "{{DEV_APP_POOL}}" # e.g., dev.api.compass.com
39
47
 
48
+ # Test environment
49
+ testWebsiteName: "{{TEST_WEBSITE_NAME}}" # e.g., test.api.compass.caresolutions.com
50
+ testAppPoolName: "{{TEST_APP_POOL}}" # e.g., test.api.compass.com
51
+
40
52
  # Staging environment
41
53
  stagingWebsiteName: "{{STAGING_WEBSITE_NAME}}" # e.g., staging.api.compass.caresolutions.com
42
54
  stagingAppPoolName: "{{STAGING_APP_POOL}}" # e.g., staging.api.compass.com
@@ -73,7 +85,7 @@ stages:
73
85
  - stage: Dev
74
86
  displayName: "Deploy to Dev"
75
87
  dependsOn: "Build"
76
- condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
88
+ condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/dev'))
77
89
  jobs:
78
90
  - deployment: DeployDev
79
91
  displayName: "Deploy to Dev"
@@ -112,6 +124,49 @@ stages:
112
124
  TakeAppOfflineFlag: true
113
125
  XmlVariableSubstitution: true
114
126
 
127
+ # ── Test ───────────────────────────────────────────────
128
+ - stage: Test
129
+ displayName: "Deploy to Test"
130
+ dependsOn: "Build"
131
+ condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/test'))
132
+ jobs:
133
+ - deployment: DeployTest
134
+ displayName: "Deploy to Test"
135
+ environment:
136
+ name: "{{TEST_ENVIRONMENT_NAME}}" # e.g., Test
137
+ resourceType: VirtualMachine
138
+ strategy:
139
+ runOnce:
140
+ deploy:
141
+ steps:
142
+ - task: DownloadPipelineArtifact@2
143
+ inputs:
144
+ artifact: "drop"
145
+ path: "$(Build.ArtifactStagingDirectory)"
146
+
147
+ - task: IISWebAppManagementOnMachineGroup@0
148
+ displayName: "Configure IIS"
149
+ inputs:
150
+ IISDeploymentType: "IISWebsite"
151
+ ActionIISWebsite: "CreateOrUpdateWebsite"
152
+ WebsiteName: "$(testWebsiteName)"
153
+ WebsitePhysicalPath: "$(WebsitePhysicalPath)"
154
+ WebsitePhysicalPathAuth: "WebsiteUserPassThrough"
155
+ AddBinding: false
156
+ CreateOrUpdateAppPoolForWebsite: true
157
+ AppPoolNameForWebsite: "$(testAppPoolName)"
158
+ DotNetVersionForWebsite: "No Managed Code"
159
+ PipeLineModeForWebsite: "Integrated"
160
+ AppPoolIdentityForWebsite: "ApplicationPoolIdentity"
161
+
162
+ - task: IISWebAppDeploymentOnMachineGroup@0
163
+ displayName: "Deploy to IIS"
164
+ inputs:
165
+ WebsiteName: "$(testWebsiteName)"
166
+ Package: "$(Build.ArtifactStagingDirectory)/$(projectName).zip"
167
+ TakeAppOfflineFlag: true
168
+ XmlVariableSubstitution: true
169
+
115
170
  # ── Staging ────────────────────────────────────────────
116
171
  - stage: Staging
117
172
  displayName: "Deploy to Staging"
@@ -159,7 +214,7 @@ stages:
159
214
  - stage: Production
160
215
  displayName: "Deploy to Production"
161
216
  dependsOn: "Build"
162
- condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
217
+ condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/prod'))
163
218
  jobs:
164
219
  - deployment: DeployProd
165
220
  displayName: "Deploy to Production"