@chris1807/claude-kit 2.2.2 → 2.2.4

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.
package/README.md CHANGED
@@ -279,6 +279,7 @@ Claude automatically:
279
279
  7. Generates a UAT checklist from acceptance criteria
280
280
  8. **Pauses for you to manually test**
281
281
  9. Creates the PR after you confirm
282
+ 10. **Attaches any hand-run deployment script** to the work item, with the run command in the attachment comment, so `/promote`, `/cherry-pick`, and `/deploy-release` list it for every environment. Data fixes are planned as run-once migrations the app applies by itself wherever the project has that mechanism; a hand-run script is the fallback and the plan says why
282
283
 
283
284
  **Implementing a whole Feature:** point `/implement` at a Feature work item and it implements the child User Stories in waves driven by the `Custom.Order` field — stories with the same order value are implemented in parallel (one agent per story, each in an isolated git worktree), and the next order value starts only after the previous wave is merged and green. Everything lands on one `feature/` branch with a single review, UAT pass, and PR that links every story.
284
285
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chris1807/claude-kit",
3
- "version": "2.2.2",
3
+ "version": "2.2.4",
4
4
  "description": "Claude Code starter kit for Azure DevOps teams — agents, hooks, MCP servers, slash commands, and end-to-end work item → PR → release → deploy workflow automation",
5
5
  "type": "module",
6
6
  "bin": {
@@ -38,7 +38,7 @@ Wait for confirmation.
38
38
 
39
39
  ## Step 4: Assign and Tag
40
40
 
41
- Use `wit_update_work_items_batch` to:
41
+ Use `wit_work_item_write` (action `update_batch`) to:
42
42
  1. Set the Iteration Path to `{project}\Release #{N}` on each new work item
43
43
  2. Append `release-{N}` to each work item's tags
44
44
 
@@ -52,14 +52,16 @@ Show them with the table above, before the confirmation:
52
52
  ```
53
53
  📜 Scripts to run with this promotion:
54
54
 
55
- | Work Item | Script |
56
- |-----------|--------|
57
- | AB#1234 | 2026-09-11_add_delivery_index.sql |
58
- | AB#1240 | backfill-tenant-flags.ps1 |
55
+ | Work Item | Script | How to run |
56
+ |-----------|--------|------------|
57
+ | AB#1234 | 2026-09-11_add_delivery_index.sql | sqlcmd -S <server> -d Compass -i 2026-09-11_add_delivery_index.sql |
58
+ | AB#1240 | backfill-tenant-flags.ps1 | — |
59
59
 
60
60
  Download them from the work items. This command does not run them.
61
61
  ```
62
62
 
63
+ `How to run` is the attachment's comment (`attributes.comment` on the relation) — `/implement` and `/rework` write the run command there when they attach a script. Show `—` when it is empty.
64
+
63
65
  If nothing carries an attachment, say `No deployment scripts attached` on one line and move on.
64
66
 
65
67
  **Reported, never enforced.** A script does not block the promotion and does not change the gate check: the attachment may already have been run, may be a reference copy, may not be a script at all. Listing it is the whole job — the person deploying decides.
@@ -123,7 +125,7 @@ Cherry-picking:
123
125
  - **targetRefName**: `refs/heads/<target-environment-branch>`
124
126
  - **title**: `Cherry-pick AB#1234, AB#1235 → {Environment}`
125
127
  - **description**: List all work items with IDs and titles, and — under a `Scripts to run` heading — any deployment scripts found in Step 1b, so whoever merges sees them without opening the work items
126
- 3. Link all work items to the PR via `wit_link_work_item_to_pull_request`
128
+ 3. Link all work items to the PR via `wit_work_item_link_write` (action `link_to_pull_request`)
127
129
 
128
130
  ## Step 6: Pick Who Verifies Each Group (before the merge)
129
131
 
@@ -16,7 +16,7 @@ All work items live in the **CSI Development** Azure DevOps project (see CLAUDE.
16
16
 
17
17
  ## Step 1: Find Orphaned Tasks
18
18
 
19
- Use the Azure DevOps MCP `wit_query_by_wiql` with a hierarchy link query. The Source is the parent, the Target is the child Task:
19
+ Use the Azure DevOps MCP `wit_query` (action `wiql`) with a hierarchy link query. The Source is the parent, the Target is the child Task:
20
20
 
21
21
  ```sql
22
22
  SELECT [System.Id]
@@ -31,11 +31,11 @@ MODE (MustContain)
31
31
 
32
32
  If a **scope** was given, add the matching constraint to the `[Target]` clause (e.g. `AND [Target].[System.AreaPath] UNDER 'CSI Development\\Compass'`, or `AND [Target].[System.Title] CONTAINS 'PAY'`).
33
33
 
34
- > **Note on state names:** Process templates vary. Some projects close tasks to `Done` instead of `Closed`, or use `Resolved`. If the query returns nothing or errors on an unknown state, first confirm the valid states for the Task type via `wit_get_work_item_type`, then adjust the `NOT IN` list and the close target in Step 3 accordingly.
34
+ > **Note on state names:** Process templates vary. Some projects close tasks to `Done` instead of `Closed`, or use `Resolved`. If the query returns nothing or errors on an unknown state, first confirm the valid states for the Task type via `wit_work_item` (action `get_type`), then adjust the `NOT IN` list and the close target in Step 3 accordingly.
35
35
 
36
36
  If the link query is unsupported or returns no usable pairs, fall back to: query all open Tasks in scope with a flat WIQL, fetch each task's parent via `relations`, and keep only those whose parent state is in the three target states.
37
37
 
38
- Fetch the matched tasks (and their parents) in a batch via `wit_get_work_items_batch_by_ids` to get titles, states, assignees, and parent context.
38
+ Fetch the matched tasks (and their parents) in a batch via `wit_work_item` (action `get_batch`) to get titles, states, assignees, and parent context.
39
39
 
40
40
  ## Step 2: Present the Candidates
41
41
 
@@ -59,11 +59,11 @@ Otherwise, wait for explicit confirmation before proceeding. Never close tasks w
59
59
 
60
60
  ## Step 3: Close the Tasks
61
61
 
62
- For each confirmed task, use `wit_update_work_items_batch`:
62
+ For each confirmed task, use `wit_work_item_write` (action `update_batch`):
63
63
  - **path**: `/fields/System.State`
64
64
  - **value**: `Closed` (or the project's terminal Task state confirmed in Step 1)
65
65
 
66
- Then add a comment on each via `wit_add_work_item_comment` so the auto-close is traceable:
66
+ Then add a comment on each via `wit_work_item_comment_write` (action `add`) so the auto-close is traceable:
67
67
 
68
68
  > Auto-closed by `/close-orphan-tasks` — parent AB#{parentId} is in state "{parentState}".
69
69
 
@@ -38,13 +38,13 @@ Create a new iteration in Azure DevOps via `work_create_iterations`:
38
38
 
39
39
  ## Step 4: Assign Work Items to the Release
40
40
 
41
- Use `wit_update_work_items_batch` to set the Iteration Path on each work item to the new release iteration:
41
+ Use `wit_work_item_write` (action `update_batch`) to set the Iteration Path on each work item to the new release iteration:
42
42
  - **path**: `/fields/System.IterationPath`
43
43
  - **value**: `{project}\Release #{N}`
44
44
 
45
45
  ## Step 5: Tag Work Items
46
46
 
47
- Use `wit_update_work_items_batch` to add a release tag to each work item:
47
+ Use `wit_work_item_write` (action `update_batch`) to add a release tag to each work item:
48
48
  - **path**: `/fields/System.Tags`
49
49
  - **value**: append `release-{N}` to existing tags
50
50
 
@@ -404,7 +404,7 @@ This applies to **User Story**. It does **not** apply to Bug or Hot Fix: neither
404
404
 
405
405
  ### Call the create API
406
406
 
407
- Call `mcp__azure-devops__wit_create_work_item` with:
407
+ Call `mcp__azure-devops__wit_work_item_write` (action `create`) with:
408
408
 
409
409
  - **project**: the chosen project
410
410
  - **workItemType**: `Feature`, `Bug`, `User Story`, or `Hot Fix` (two words, exact casing)
@@ -431,7 +431,7 @@ If the `Open Questions` section is non-empty, append it as a clearly-labeled HTM
431
431
 
432
432
  ### Move to Dev Ready (pointed items only)
433
433
 
434
- If story points were agreed in Step 4, set `System.State` to `Dev Ready` via `mcp__azure-devops__wit_update_work_item` **after** the item is created (a separate call — new items start in `New`, and some process templates reject a non-initial state in the create call). If the state transition is rejected, report the error and leave the state as-is — don't silently retry through intermediate states. Items created without points stay in `New`.
434
+ If story points were agreed in Step 4, set `System.State` to `Dev Ready` via `mcp__azure-devops__wit_work_item_write` (action `update`) **after** the item is created (a separate call — new items start in `New`, and some process templates reject a non-initial state in the create call). If the state transition is rejected, report the error and leave the state as-is — don't silently retry through intermediate states. Items created without points stay in `New`.
435
435
 
436
436
  **Features are never moved.** A Feature stays in `New` and advances only as its child stories are verified and closed — the same rule `/implement` follows.
437
437
 
@@ -462,7 +462,7 @@ On `yes`:
462
462
  ```
463
463
 
464
464
  **Wait for the user.** Revise and re-present until approved. Do not create anything before approval.
465
- 5. On approval, create each story with `mcp__azure-devops__wit_create_work_item` in the same project, setting:
465
+ 5. On approval, create each story with `mcp__azure-devops__wit_work_item_write` (action `create`) in the same project, setting:
466
466
  - `System.Description` and `Microsoft.VSTS.Common.AcceptanceCriteria` — rendered to HTML per the Step 8 rules
467
467
  - `Custom.Order` — the wave number
468
468
  - `Microsoft.VSTS.Scheduling.StoryPoints` — the agreed points
@@ -489,7 +489,7 @@ For a **Bug**, fetch `Microsoft.VSTS.TCM.ReproSteps` and `Microsoft.VSTS.TCM.Sys
489
489
 
490
490
  For a **Hot Fix**, fetch `System.Description` and `Microsoft.VSTS.TCM.ReproSteps`, and confirm the narrative is in the former and the reproduction detail in the latter.
491
491
 
492
- If a check fails the write didn't take — fix it with `wit_update_work_item` before reporting success. Don't report a created item you haven't read back.
492
+ If a check fails the write didn't take — fix it with `wit_work_item_write` (action `update`) before reporting success. Don't report a created item you haven't read back.
493
493
 
494
494
  After creation, report:
495
495
 
@@ -20,7 +20,7 @@ Resolve branch names from the project's `CLAUDE.md` **Pipeline Configuration** t
20
20
 
21
21
  ## Step 1: Read the Release
22
22
 
23
- Query Azure DevOps for all work items tagged with `release-{N}` or assigned to the `Release #{N}` iteration using `search_workitem` or `wit_get_work_items_for_iteration`.
23
+ Query Azure DevOps for all work items tagged with `release-{N}` or assigned to the `Release #{N}` iteration using `search_workitem` or `wit_work_item` (action `list_for_iteration`).
24
24
 
25
25
  Present the release contents:
26
26
 
@@ -93,14 +93,16 @@ Show them with the gate check, before Step 4's confirmation:
93
93
  ```
94
94
  📜 Scripts to run with this promotion:
95
95
 
96
- | Work Item | Script |
97
- |-----------|--------|
98
- | AB#1234 | 2026-09-11_add_delivery_index.sql |
99
- | AB#1240 | backfill-tenant-flags.ps1 |
96
+ | Work Item | Script | How to run |
97
+ |-----------|--------|------------|
98
+ | AB#1234 | 2026-09-11_add_delivery_index.sql | sqlcmd -S <server> -d Compass -i 2026-09-11_add_delivery_index.sql |
99
+ | AB#1240 | backfill-tenant-flags.ps1 | — |
100
100
 
101
101
  Download them from the work items. This command does not run them.
102
102
  ```
103
103
 
104
+ `How to run` is the attachment's comment (`attributes.comment` on the relation) — `/implement` and `/rework` write the run command there when they attach a script. Show `—` when it is empty.
105
+
104
106
  If nothing carries an attachment, say `No deployment scripts attached` on one line and move on.
105
107
 
106
108
  **Reported, never enforced.** A script does not block the promotion and does not change the gate check: the attachment may already have been run, may be a reference copy, may not be a script at all. Listing it is the whole job — the person deploying decides.
@@ -179,7 +181,7 @@ Cherry-picking commits for Release #{N}:
179
181
  - **targetRefName**: `refs/heads/<target-environment-branch>`
180
182
  - **title**: `Release #{N} → {Environment}`
181
183
  - **description**: List all work items included with their IDs and titles, and — under a `Scripts to run` heading — any deployment scripts found in Step 3b, so whoever merges sees them without opening the work items
182
- 3. Link all work items to the PR via `wit_link_work_item_to_pull_request`
184
+ 3. Link all work items to the PR via `wit_work_item_link_write` (action `link_to_pull_request`)
183
185
 
184
186
  ## Step 8: Pick Who Verifies Each Group (before the merge)
185
187
 
@@ -230,9 +230,9 @@ Render every Markdown section to HTML first — Azure DevOps description and acc
230
230
 
231
231
  Apply writes in this order, so a failure partway through leaves the most useful state behind:
232
232
 
233
- 1. **Update the parent item** — one `mcp__azure-devops__wit_update_work_item` call with every changed field. Never include `System.State` for a Feature.
233
+ 1. **Update the parent item** — one `mcp__azure-devops__wit_work_item_write` (action `update`) call with every changed field. Never include `System.State` for a Feature.
234
234
  2. **Update existing children** (verdict `Update`) — one call per story, points and `Custom.Order` in the same call as the text changes. If points were set on a story still at or before `Dev Ready`, set `System.State` = `Dev Ready` in that same call.
235
- 3. **Create added children** — `mcp__azure-devops__wit_create_work_item` with description, acceptance criteria, `Custom.Order`, agreed `Microsoft.VSTS.Scheduling.StoryPoints`, and `System.AssignedTo` copied from the Feature if it has an assignee. Then link each to the Feature as a child via `mcp__azure-devops__wit_work_item_link_write` (`System.LinkTypes.Hierarchy-Reverse`), then move pointed ones to `Dev Ready` in a follow-up call.
235
+ 3. **Create added children** — `mcp__azure-devops__wit_work_item_write` (action `create`) with description, acceptance criteria, `Custom.Order`, agreed `Microsoft.VSTS.Scheduling.StoryPoints`, and `System.AssignedTo` copied from the Feature if it has an assignee. Then link each to the Feature as a child via `mcp__azure-devops__wit_work_item_link_write` (`System.LinkTypes.Hierarchy-Reverse`), then move pointed ones to `Dev Ready` in a follow-up call.
236
236
  4. **Re-order** any story whose only change is `Custom.Order` — one call each, touching that field alone.
237
237
  5. **Retire** stories the user approved — set `System.State` = `Removed`, or remove the parent link, whichever the user chose. **Never delete a work item.**
238
238
  6. **Post comments** (if the user said yes) via `mcp__azure-devops__wit_work_item_comment_write` — one short comment per edited item saying what changed and why, and naming the Feature edit that drove it (e.g. `Scope updated via edit of AB#6240: acceptance criteria 2 reworded to cover SSO; re-ordered from wave 3 to wave 2.`).
@@ -32,7 +32,7 @@ The description and acceptance criteria fields may contain embedded images (scre
32
32
 
33
33
  ### Comments
34
34
 
35
- Read the work item comments via `wit_list_work_item_comments`. Comments often contain clarifications, scope changes, or additional requirements added after the work item was created. Incorporate any relevant information from comments into your understanding of the work item.
35
+ Read the work item comments via `wit_work_item` (action `list_comments`). Comments often contain clarifications, scope changes, or additional requirements added after the work item was created. Incorporate any relevant information from comments into your understanding of the work item.
36
36
 
37
37
  ## Step 2: Summarize and Confirm
38
38
 
@@ -98,7 +98,7 @@ Each question below is about a cost that is cheap now and expensive once the cod
98
98
  | 2 | **Is each piece in the right layer?** Domain / Application / Infrastructure / API boundaries hold — no business rules in a controller, no Mongo or EF types in Domain, no HTTP concepts below API. | An `IMongoCollection<T>` parameter on a Domain method |
99
99
  | 3 | **What is the simplest plan that still meets every AC?** State it, then adopt it or say in one line why the heavier one is needed. | An interface with exactly one implementation, added "for testability" |
100
100
  | 4 | **What else touches the files being modified?** Name the callers. A change to a shared contract, DTO, or response shape is a breaking change until proven otherwise. | Editing a shared DTO with no note about its other consumers |
101
- | 5 | **What happens to data that already exists?** New required fields, schema changes, and backfills each need an answer for rows written before this change. | A non-nullable field added with no default and no backfill |
101
+ | 5 | **What happens to data that already exists?** New required fields, schema changes, and backfills each need an answer for rows written before this change — and the answer should run itself: the project's run-once migration mechanism if it has one, not a script someone has to remember in every environment (see **Deployment Scripts** in CLAUDE.md). | A non-nullable field added with no default and no backfill; a `backfill.js` to run by hand on test, staging and prod when the API already runs one-time migrations at startup |
102
102
  | 6 | **How does it fail?** Partial failure, concurrent callers, a retried request. Is the operation idempotent, and does it need to be? | A multi-step write with no story for a crash between steps |
103
103
  | 7 | **Does it hold at real data volume?** Queries inside loops, unbounded result sets, a missing index, a list endpoint with no paging. | A `foreach` over accounts issuing one query each |
104
104
  | 8 | **Is it safe?** Authorization on every new endpoint, and **no sensitive field** (TIN, SSN, EIN, TaxId, BankAccountNumber, RoutingNumber, any `Encrypted*`) read, logged, returned, or projected — see the sensitive-data rule in CLAUDE.md. | A new endpoint returning a whole entity because it was convenient |
@@ -131,6 +131,10 @@ Present the plan to the user:
131
131
  ### Files to Delete (if any)
132
132
  - `path/to/old/file.cs` — {why it's being removed}
133
133
 
134
+ ### Data Changes (if any)
135
+ - {what changes in existing data} — **automated** by {the project's run-once mechanism}: `{file}`
136
+ - {what changes in existing data} — **hand-run** `{script path}`, because {which Deployment Scripts reason applies}. Attached to the work item when the PR goes up.
137
+
134
138
  ### Unit Tests
135
139
  - `path/to/new.tests.cs` — covers {scenario 1}, {scenario 2}, {edge case}
136
140
  - `path/to/existing.tests.cs` — adds cases for {new behavior}
@@ -188,12 +192,14 @@ Remember the `BASE_BRANCH` — you will need it for the PR step.
188
192
 
189
193
  ### Move the Work Item to Active
190
194
 
191
- Once the branch is created, move the work item (User Story, Bug, Hot Fix, or other single work item — never a Feature) to `Active` via `wit_update_work_item`:
195
+ Once the branch is created, move the work item (User Story, Bug, Hot Fix, or other single work item — never a Feature) to `Active` via `wit_work_item_write` (action `update`):
192
196
  - **path**: `/fields/System.State`
193
197
  - **value**: `Active`
194
198
 
195
199
  If the work item is already `Active`, skip the update. If the project's process template does not have an `Active` state (the update call returns an invalid-state error), fall back in this order: `In Progress` → `Doing` → leave the current state and warn the user that the state could not be advanced automatically. Do not silently swallow the error.
196
200
 
201
+ After the update, **read the work item back** (`wit_work_item`, action `get`) and confirm `System.State` actually changed. If it didn't, say so explicitly — do not proceed reporting the item as in progress when the board still shows it otherwise.
202
+
197
203
  ### Ensure an Open Child Task Exists
198
204
 
199
205
  The child **Task** is where hours live: Step 10 closes it and logs the hours worked when the PR goes up. So an implementation run must never proceed without one — if there's nothing to close, nothing gets logged.
@@ -264,7 +270,7 @@ Create it? (yes / edit / skip)
264
270
  - `edit` → ask what to change (title or hours), revise, re-show, ask again
265
271
  - `skip` → continue without a Task, and **warn** that Step 10 will have no Task to close and no hours will be logged for this story
266
272
 
267
- On `yes`, create it with `mcp__azure-devops__wit_create_work_item`:
273
+ On `yes`, create it with `mcp__azure-devops__wit_work_item_write` (action `create`):
268
274
 
269
275
  - **workItemType**: `Task`
270
276
  - **title**: `{PREFIX} - Implement: {short summary of the story}` — reuse the parent's product prefix (`COM`, `PAY`, `CDA`, …), extracted from the parent's title
@@ -275,7 +281,7 @@ On `yes`, create it with `mcp__azure-devops__wit_create_work_item`:
275
281
  - `System.AssignedTo` — copy from the parent (pass the parent's `uniqueName` / email if the value is an identity object). If the parent is unassigned, leave it unset rather than failing.
276
282
  - `System.State` — `Active`, since implementation is starting right now (fall back to the template's in-progress equivalent, or leave it at the default and note it)
277
283
 
278
- Then link it as a child of the work item with `mcp__azure-devops__wit_add_child_work_items` (or `wit_work_items_link` with `System.LinkTypes.Hierarchy-Forward`, parent → task).
284
+ Then link it as a child of the work item with `mcp__azure-devops__wit_work_item_write` (action `add_child`) (or `wit_work_item_link_write` (action `link`) with `System.LinkTypes.Hierarchy-Forward`, parent → task).
279
285
 
280
286
  If the create or link call fails, report it and ask whether to implement without a Task or stop. Don't silently continue — the user needs to know hours won't be tracked.
281
287
 
@@ -387,15 +393,26 @@ Wait for the user's response before proceeding. Do NOT create a PR until confirm
387
393
  - **targetRefName**: `refs/heads/{BASE_BRANCH}` (the branch captured in Step 4)
388
394
  - **title**: `AB#{id}: {work item title}`
389
395
  - **labels**: `["hotfix"]` if the work item type is Hot Fix
390
- 3. Link the PR to the work item via `wit_link_work_item_to_pull_request`
391
- 4. **Close related Tasks and log hours** — see "Closing Related Tasks" below.
392
- 5. **Move the work item to `Code Review`** via `wit_update_work_item`:
396
+ 3. Link the PR to the work item via `wit_work_item_link_write` (action `link_to_pull_request`)
397
+ 4. **Attach deployment scripts** — see "Attaching Deployment Scripts" below.
398
+ 5. **Close related Tasks and log hours** — see "Closing Related Tasks" below.
399
+ 6. **Move the work item to `Code Review`** via `wit_work_item_write` (action `update`):
393
400
  - **path**: `/fields/System.State`
394
401
  - **value**: `Code Review`
395
402
 
396
403
  If the project's process template does not have a `Code Review` state (the update call returns an invalid-state error), fall back in this order: `Resolved` → `In Review` → leave the current state and warn the user that the state could not be advanced automatically. Do not silently swallow the error.
397
404
 
398
- > **Only the Task ever gets closed — never the parent.** The child Task is closed here, at PR creation (step 4 above). When the PR is later completed/merged, do **not** enable Azure DevOps's "Complete associated work items" option: it transitions *every* linked work item, including the parent this PR is linked to. The parent User Story or Bug stays in `Code Review`: merging this PR into `main` deploys nothing, and promoting to `dev` deploys the code but **leaves the state alone** — the developer moves it to `Ready for Testing` once they have checked it on Dev. From there `/promote` and `/deploy-release` advance it to `Testing` → `Staging` → `Deployed` across `test → staging → prod` (see **Work Item States ↔ Environments** in CLAUDE.md).
405
+ > **Only the Task ever gets closed — never the parent.** The child Task is closed here, at PR creation (step 5 above). When the PR is later completed/merged, do **not** enable Azure DevOps's "Complete associated work items" option: it transitions *every* linked work item, including the parent this PR is linked to. The parent User Story or Bug stays in `Code Review`: merging this PR into `main` deploys nothing, and promoting to `dev` deploys the code but **leaves the state alone** — the developer moves it to `Ready for Testing` once they have checked it on Dev. From there `/promote` and `/deploy-release` advance it to `Testing` → `Staging` → `Deployed` across `test → staging → prod` (see **Work Item States ↔ Environments** in CLAUDE.md).
406
+
407
+ ### Attaching Deployment Scripts
408
+
409
+ A script that has to be run by hand — a SQL migration, a data backfill, a rename — is useless to the next environment if it only lives in the repo: `/promote`, `/cherry-pick` and `/deploy-release` find scripts on the **work item**, never in the diff. So every one this change adds or modifies is attached to the work item now, not left for someone to remember.
410
+
411
+ List the files the PR adds or modifies (`git diff --name-only --diff-filter=AM {BASE_BRANCH}...HEAD`) and pick out the ones a person runs by hand, once per environment. The test: if the UAT checklist, the PR, or your report tells someone to run it, it's one of these. App code, tests, build tooling and migrations the app or pipeline applies by itself are not. Each one should already be in the approved plan's **Data Changes** section with its reason for not being automated. A hand-run script that isn't there still gets attached, but say plainly that it wasn't in the plan.
412
+
413
+ Attach each one per **Deployment Scripts** in CLAUDE.md — upload through the REST API (the MCP server can only download), link it as an `AttachedFile` whose comment holds the repo path and the exact run command with the environment as a placeholder, and replace a stale same-name attachment rather than adding a second copy. Never attach a file with a connection string, key, password, or sensitive field value in it.
414
+
415
+ Report it on one line per script — `📜 Attached to AB#{id}: {file} — {how to run}` — or `No deployment scripts in this change` when there are none. A failed upload does not undo the PR; say `⚠️ NOT attached: {file} → AB#{id}` with the error and keep going.
399
416
 
400
417
  ### Closing Related Tasks
401
418
 
@@ -452,7 +469,7 @@ For each task being processed, prompt for completed hours:
452
469
 
453
470
  **Wait for the user's response on every task.** Accept the suggested/current value (enter), a new numeric value, or `skip` to leave that one untouched.
454
471
 
455
- Once the user has answered, update each task in a **single** `wit_update_work_item` call per task:
472
+ Once the user has answered, update each task in a **single** `wit_work_item_write` (action `update`) call per task:
456
473
  - `Microsoft.VSTS.Scheduling.CompletedWork` → the agreed value
457
474
  - `Microsoft.VSTS.Scheduling.RemainingWork` → `0`
458
475
  - `Microsoft.VSTS.Scheduling.OriginalEstimate` → only if it is still empty; set it to the agreed completed hours so the Task isn't left with no estimate at all. Never overwrite an estimate that's already there — the gap between estimate and actual is the useful signal.
@@ -557,6 +574,7 @@ Present **one combined UAT checklist grouped by story** (Step 9 rules). Wait for
557
574
 
558
575
  1. Push the feature branch and create **one PR**: title `AB#{feature-id}: {feature title}`, source `feature/...`, target `BASE_BRANCH`.
559
576
  2. Link the **Feature and every implemented story** to the PR.
560
- 3. Run **Closing Related Tasks** (Step 10) once, covering the child Tasks of every implemented story — one combined table, then the usual per-task hour prompts. Every story that got a Task in F4 has one to close here; a story whose Task creation was skipped gets one created and closed now, as in Step 10.
561
- 4. Move each implemented story to `Code Review` (same fallback rules as Step 10). **Do not change the Feature's state** — the Feature is a parent container; it advances only when its child stories are verified/closed, not when the PR goes up for review.
562
- 5. The Step 10 closing rule applies unchanged: only child **Tasks** are ever closed — here at PR creation, never the stories and never the Feature. Don't enable "Complete associated work items" when the PR is merged; it would transition the stories and the Feature along with the Tasks.
577
+ 3. Run **Attaching Deployment Scripts** (Step 10) over the whole feature diff. Each script goes on the **story** whose change needs it — never on the Feature, which promotions don't gate.
578
+ 4. Run **Closing Related Tasks** (Step 10) once, covering the child Tasks of every implemented story — one combined table, then the usual per-task hour prompts. Every story that got a Task in F4 has one to close here; a story whose Task creation was skipped gets one created and closed now, as in Step 10.
579
+ 5. Move each implemented story to `Code Review` (same fallback rules as Step 10). **Do not change the Feature's state** — the Feature is a parent container; it advances only when its child stories are verified/closed, not when the PR goes up for review.
580
+ 6. The Step 10 closing rule applies unchanged: only child **Tasks** are ever closed — here at PR creation, never the stories and never the Feature. Don't enable "Complete associated work items" when the PR is merged; it would transition the stories and the Feature along with the Tasks.
@@ -27,7 +27,7 @@ If the user types `list`, call `mcp__azure-devops__core_list_projects` and prese
27
27
 
28
28
  ## Step 2: Query the Backlog
29
29
 
30
- Run a WIQL query via `mcp__azure-devops__wit_query_by_wiql` to find candidate stories. "Backlog" means items at the **root iteration path** (not assigned to any sprint).
30
+ Run a WIQL query via `mcp__azure-devops__wit_query` (action `wiql`) to find candidate stories. "Backlog" means items at the **root iteration path** (not assigned to any sprint).
31
31
 
32
32
  ```sql
33
33
  SELECT [System.Id], [System.Title], [System.State],
@@ -55,7 +55,7 @@ and stop.
55
55
 
56
56
  ## Step 3: Filter Out Stories That Already Have Child Tasks
57
57
 
58
- For each candidate from Step 2, fetch the work item with `mcp__azure-devops__wit_get_work_item` expanding `relations`. If the item has any `System.LinkTypes.Hierarchy-Forward` relation pointing at a `Task`, mark it as **already broken down** and skip it.
58
+ For each candidate from Step 2, fetch the work item with `mcp__azure-devops__wit_work_item` (action `get`) expanding `relations`. If the item has any `System.LinkTypes.Hierarchy-Forward` relation pointing at a `Task`, mark it as **already broken down** and skip it.
59
59
 
60
60
  Present a one-line summary of what was skipped:
61
61
 
@@ -175,7 +175,7 @@ Approve? (yes / edit / skip / cancel-all)
175
175
 
176
176
  ### 5e. Create the child task
177
177
 
178
- Create the approved task with `mcp__azure-devops__wit_create_work_item`:
178
+ Create the approved task with `mcp__azure-devops__wit_work_item_write` (action `create`):
179
179
 
180
180
  - **project**: the chosen project
181
181
  - **workItemType**: `Task`
@@ -187,7 +187,7 @@ Create the approved task with `mcp__azure-devops__wit_create_work_item`:
187
187
  - `System.AreaPath` — copy from the parent
188
188
  - `System.AssignedTo` — copy from the parent (pass the parent's `uniqueName` / email if its `System.AssignedTo` value is an identity object). If the parent is unassigned, leave this field unset rather than failing.
189
189
 
190
- Then link the new task as a child of the parent with `mcp__azure-devops__wit_add_child_work_items` (or fall back to `wit_work_items_link` with link type `System.LinkTypes.Hierarchy-Forward` from parent → task).
190
+ Then link the new task as a child of the parent with `mcp__azure-devops__wit_work_item_write` (action `add_child`) (or fall back to `wit_work_item_link_write` (action `link`) with link type `System.LinkTypes.Hierarchy-Forward` from parent → task).
191
191
 
192
192
  If the create or link call fails, report the failure and ask the user whether to continue with the next story or abort the loop.
193
193
 
@@ -44,7 +44,7 @@ and stop.
44
44
 
45
45
  ## Step 3: Query the Sprint
46
46
 
47
- Run a WIQL query via `mcp__azure-devops__wit_query_by_wiql` using the **literal iteration path** from Step 2:
47
+ Run a WIQL query via `mcp__azure-devops__wit_query` (action `wiql`) using the **literal iteration path** from Step 2:
48
48
 
49
49
  ```sql
50
50
  SELECT [System.Id], [System.Title], [System.State],
@@ -73,7 +73,7 @@ and stop.
73
73
 
74
74
  ## Step 4: Filter Out Items That Already Have Child Tasks
75
75
 
76
- For each candidate from Step 3, fetch the work item with `mcp__azure-devops__wit_get_work_item` expanding `relations`. If the item has any `System.LinkTypes.Hierarchy-Forward` relation pointing at a `Task`, mark it as **already broken down** and skip it.
76
+ For each candidate from Step 3, fetch the work item with `mcp__azure-devops__wit_work_item` (action `get`) expanding `relations`. If the item has any `System.LinkTypes.Hierarchy-Forward` relation pointing at a `Task`, mark it as **already broken down** and skip it.
77
77
 
78
78
  Present a one-line summary of what was skipped:
79
79
 
@@ -196,7 +196,7 @@ For unpointed items, the header line reads `(no points — estimated from descri
196
196
 
197
197
  ### 6e. Create the child task
198
198
 
199
- Create the approved task with `mcp__azure-devops__wit_create_work_item`:
199
+ Create the approved task with `mcp__azure-devops__wit_work_item_write` (action `create`):
200
200
 
201
201
  - **project**: the chosen project
202
202
  - **workItemType**: `Task`
@@ -208,7 +208,7 @@ Create the approved task with `mcp__azure-devops__wit_create_work_item`:
208
208
  - `System.AreaPath` — copy from the parent
209
209
  - `System.AssignedTo` — copy from the parent (pass the parent's `uniqueName` / email if its `System.AssignedTo` value is an identity object). If the parent is unassigned, leave this field unset rather than failing.
210
210
 
211
- Then link the new task as a child of the parent with `mcp__azure-devops__wit_add_child_work_items` (or fall back to `wit_work_items_link` with link type `System.LinkTypes.Hierarchy-Forward` from parent → task).
211
+ Then link the new task as a child of the parent with `mcp__azure-devops__wit_work_item_write` (action `add_child`) (or fall back to `wit_work_item_link_write` (action `link`) with link type `System.LinkTypes.Hierarchy-Forward` from parent → task).
212
212
 
213
213
  If the create or link call fails, report the failure and ask the user whether to continue with the next item or abort the loop.
214
214
 
@@ -98,14 +98,16 @@ Show them with the gate check, before the confirmation:
98
98
  ```
99
99
  📜 Scripts to run with this promotion:
100
100
 
101
- | Work Item | Script |
102
- |-----------|--------|
103
- | AB#1234 | 2026-09-11_add_delivery_index.sql |
104
- | AB#1240 | backfill-tenant-flags.ps1 |
101
+ | Work Item | Script | How to run |
102
+ |-----------|--------|------------|
103
+ | AB#1234 | 2026-09-11_add_delivery_index.sql | sqlcmd -S <server> -d Compass -i 2026-09-11_add_delivery_index.sql |
104
+ | AB#1240 | backfill-tenant-flags.ps1 | — |
105
105
 
106
106
  Download them from the work items. This command does not run them.
107
107
  ```
108
108
 
109
+ `How to run` is the attachment's comment (`attributes.comment` on the relation) — `/implement` and `/rework` write the run command there when they attach a script. Show `—` when it is empty.
110
+
109
111
  If nothing carries an attachment, say `No deployment scripts attached` on one line and move on.
110
112
 
111
113
  **Reported, never enforced.** A script does not block the promotion and does not change the gate check: the attachment may already have been run, may be a reference copy, may not be a script at all. Listing it is the whole job — the person deploying decides.
@@ -91,7 +91,7 @@ If the user types `list`, call `mcp__azure-devops__core_list_projects` and prese
91
91
 
92
92
  ## Step 2: Query the Backlog
93
93
 
94
- Run a WIQL query via `mcp__azure-devops__wit_query_by_wiql` to find candidate items. "Backlog" means items at the **root iteration path** (not assigned to any sprint).
94
+ Run a WIQL query via `mcp__azure-devops__wit_query` (action `wiql`) to find candidate items. "Backlog" means items at the **root iteration path** (not assigned to any sprint).
95
95
 
96
96
  ```sql
97
97
  SELECT [System.Id], [System.Title], [System.State],
@@ -203,7 +203,7 @@ For each item in the batch, do all of 3a–3e before presenting anything. Collec
203
203
 
204
204
  ### 3a. Fetch the full work item
205
205
 
206
- Fetch with `mcp__azure-devops__wit_get_work_item` expanding `relations`. Capture: title, type, description, acceptance criteria, tags, `System.CreatedBy` (display name + unique name — needed for the comment draft), child items, and any linked PRs, commits, or branches.
206
+ Fetch with `mcp__azure-devops__wit_work_item` (action `get`) expanding `relations`. Capture: title, type, description, acceptance criteria, tags, `System.CreatedBy` (display name + unique name — needed for the comment draft), child items, and any linked PRs, commits, or branches.
207
207
 
208
208
  ### 3b. Completeness review
209
209
 
@@ -368,8 +368,8 @@ Approve? (all / numbers e.g. "1,2,4" / edit N / skip N / apply rewrite N / cance
368
368
 
369
369
  Only for approved items, in batch order:
370
370
 
371
- 1. **Set Story Points and move to Dev Ready** (items with a proposed number): in one `mcp__azure-devops__wit_update_work_item` call, set `Microsoft.VSTS.Scheduling.StoryPoints` **and** `System.State` = `Dev Ready`. The state change applies only to `User Story`, `Bug`, and `Hot Fix` types, and never moves an item backward — if an item is somehow already past Dev Ready, set the points only and note it. Touch no other field — assignee, iteration, and tags stay as they are.
372
- 2. **Send unquotable User Stories back to Design Review** (approved `User Story` items with **no** proposed points, where the blocker is missing information): set `System.State` = `Design Review` via `mcp__azure-devops__wit_update_work_item`. Do this **before** posting the comment in step 4, so the creator's notification arrives with the item already back in their queue. Rules:
371
+ 1. **Set Story Points and move to Dev Ready** (items with a proposed number): in one `mcp__azure-devops__wit_work_item_write` (action `update`) call, set `Microsoft.VSTS.Scheduling.StoryPoints` **and** `System.State` = `Dev Ready`. The state change applies only to `User Story`, `Bug`, and `Hot Fix` types, and never moves an item backward — if an item is somehow already past Dev Ready, set the points only and note it. Touch no other field — assignee, iteration, and tags stay as they are.
372
+ 2. **Send unquotable User Stories back to Design Review** (approved `User Story` items with **no** proposed points, where the blocker is missing information): set `System.State` = `Design Review` via `mcp__azure-devops__wit_work_item_write` (action `update`). Do this **before** posting the comment in step 4, so the creator's notification arrives with the item already back in their queue. Rules:
373
373
 
374
374
  - **`User Story` only.** Do not attempt this on a `Bug` or a `Hot Fix` — those types have no `Design Review` state, so the update fails at runtime in the middle of the batch. They take step 3 instead.
375
375
  - Only from `Design Approved` — **never move an item backward past the design stage.** An item at `Dev Ready`, or anything at `Active` or later (`Active`, `Code Review`, `Ready for Testing`, `Testing`, `Ready for Staging`, `Staging`, `Ready to Deploy`, …), keeps its state; note it in the summary instead.
@@ -387,8 +387,8 @@ Only for approved items, in batch order:
387
387
  - Skip items whose only finding is **needs to be split** — nothing is missing, so no tag.
388
388
  - Touch no other field — points stay empty; assignee, iteration, and state stay as they are.
389
389
 
390
- 4. **Post the comment** (items with an approved draft): add it with `mcp__azure-devops__wit_add_work_item_comment` (or the server's work-item comment tool). Use the mention syntax the server supports so the creator is notified; otherwise lead with their display name as drafted. For a story that just moved to Design Review, the comment must say so — the creator needs to know why it left their Design Approved column. For a bug that just got the `needs-info` tag, the comment must say that too, and say that removing the tag re-queues it.
391
- 5. **Apply the rewrite** (only items the user marked `apply rewrite N`): update `System.Description` (and `System.Title` if the rewrite included one) via `wit_update_work_item`, and adjust the comment to say the rewrite was applied ("rewrote the description/AC per the above — please review") rather than suggesting it. Never apply a rewrite the user didn't explicitly mark.
390
+ 4. **Post the comment** (items with an approved draft): add it with `mcp__azure-devops__wit_work_item_comment_write` (action `add`) (or the server's work-item comment tool). Use the mention syntax the server supports so the creator is notified; otherwise lead with their display name as drafted. For a story that just moved to Design Review, the comment must say so — the creator needs to know why it left their Design Approved column. For a bug that just got the `needs-info` tag, the comment must say that too, and say that removing the tag re-queues it.
391
+ 5. **Apply the rewrite** (only items the user marked `apply rewrite N`): update `System.Description` (and `System.Title` if the rewrite included one) via `wit_work_item_write` (action `update`), and adjust the comment to say the rewrite was applied ("rewrote the description/AC per the above — please review") rather than suggesting it. Never apply a rewrite the user didn't explicitly mark.
392
392
 
393
393
  **Guard on `Microsoft.VSTS.Common.AcceptanceCriteria`:** write it only if the item's AC field was **non-empty** when fetched in 3a. Re-check the fetched value at write time — if it was blank, drop AC from the update payload and write the other fields. Blank means no criteria at all: empty string, whitespace, an empty HTML shell like `<div></div>` or `<p><br></p>`, **or the process template's placeholder tip text** (`💡 Tip: Add "@serena rewrite" to Description for AI suggestions Define acceptance criteria: - [ ] - [ ] - [ ]`). The placeholder is the one that bites — it is a stored, non-empty field value that means the exact opposite of what its length suggests.
394
394
 
@@ -111,7 +111,7 @@ After displaying the estimate, ask the user: *"Want me to set Story Points = {n}
111
111
 
112
112
  Only update the work item if the user explicitly says yes. Do not modify anything otherwise.
113
113
 
114
- When the user agrees, in the **same** `wit_update_work_item` call:
114
+ When the user agrees, in the **same** `wit_work_item_write` (action `update`) call:
115
115
 
116
116
  1. Set `Microsoft.VSTS.Scheduling.StoryPoints` to the agreed value (the user's number wins if they adjusted it).
117
117
  2. Set `System.State` to `Dev Ready` — **but only if** the work item type is `User Story`, `Bug`, or `Hot Fix` **and** the item is not already past Dev Ready in the workflow (e.g. `Active`, `Code Review`, `Testing`, `Staging`, `Ready to Deploy`). Never move an item backward — if it's already past Dev Ready, set the points only and mention the state was left alone.
@@ -134,7 +134,7 @@ In the CSI Development process template, `Bug` and `Hot Fix` have **no design st
134
134
 
135
135
  > *"I can't size this until {what's missing}. Want me to move AB#{id} back to Design Review so it's out of the next `/quote-backlog` sweep until the creator responds?"*
136
136
 
137
- **Wait for the user.** Only update the work item if they say yes. Then set `System.State` = `Design Review` with `mcp__azure-devops__wit_update_work_item`. Rules:
137
+ **Wait for the user.** Only update the work item if they say yes. Then set `System.State` = `Design Review` with `mcp__azure-devops__wit_work_item_write` (action `update`). Rules:
138
138
 
139
139
  - **`User Story` only** — never a Bug, Hot Fix, Feature, or Task. A Bug takes 5b; the update would fail on it anyway.
140
140
  - **Never move an item backward past the design stage.** Only from `Design Approved`; if it's already `Dev Ready` or anything at `Active` or later (`Active`, `Code Review`, `Ready for Testing`, `Testing`, `Ready for Staging`, `Staging`, `Ready to Deploy`, …), leave the state alone and say so — someone is already working on it, and a state bounce there does real damage.
@@ -146,7 +146,7 @@ In the CSI Development process template, `Bug` and `Hot Fix` have **no design st
146
146
 
147
147
  > *"I can't size this until {what's missing} — and a Bug has no design state to send it back to. Want me to tag AB#{id} `needs-info` so it drops out of the next `/quote-backlog` sweep? Removing the tag is what re-queues it — a reply alone leaves it excluded, though `/quote-backlog`'s stale-tag audit will surface it."*
148
148
 
149
- **Wait for the user.** Only update the work item if they say yes. Then add the tag with `mcp__azure-devops__wit_update_work_item`. Rules:
149
+ **Wait for the user.** Only update the work item if they say yes. Then add the tag with `mcp__azure-devops__wit_work_item_write` (action `update`). Rules:
150
150
 
151
151
  - **Append to `System.Tags`, never replace it.** Take the current tag list captured in Step 1, append `needs-info`, and write the whole semicolon-separated list back. Writing the field bare wipes tags someone else set — `release-{N}`, triage labels, scope hints.
152
152
  - Already tagged `needs-info` → no-op; say it's already there.
@@ -36,13 +36,13 @@ Save the PR's `creationDate` as `LAST_PR_DATE` — everything after this timesta
36
36
 
37
37
  ### New Comments
38
38
 
39
- Read the work item comments via `wit_list_work_item_comments`. Filter to only comments created **after** `LAST_PR_DATE`. These contain the rework feedback.
39
+ Read the work item comments via `wit_work_item` (action `list_comments`). Filter to only comments created **after** `LAST_PR_DATE`. These contain the rework feedback.
40
40
 
41
41
  For each new comment, check for embedded images (`<img>` tags with `src` URLs pointing to Azure DevOps attachments). **Download and view every embedded image** using WebFetch — they often contain screenshots of bugs, visual issues, or annotated UI showing what needs to change.
42
42
 
43
43
  ### Description & Acceptance Criteria Changes
44
44
 
45
- Read the work item revisions via `wit_list_work_item_revisions`. Check if the **description** or **acceptance criteria** fields were modified **after** `LAST_PR_DATE`.
45
+ Read the work item revisions via `wit_work_item` (action `list_revisions`). Check if the **description** or **acceptance criteria** fields were modified **after** `LAST_PR_DATE`.
46
46
 
47
47
  - If changed: extract the **current** description and acceptance criteria, and note what was added or modified
48
48
  - If unchanged: still read the current description and acceptance criteria — a comment may reference something that was in the original requirements but missing from the implementation
@@ -123,7 +123,7 @@ Each question below is about a cost that is cheap now and expensive once the cod
123
123
  | 2 | **Is each piece in the right layer?** Domain / Application / Infrastructure / API boundaries hold — no business rules in a controller, no Mongo or EF types in Domain, no HTTP concepts below API. | An `IMongoCollection<T>` parameter on a Domain method |
124
124
  | 3 | **What is the simplest plan that still meets every AC?** State it, then adopt it or say in one line why the heavier one is needed. | An interface with exactly one implementation, added "for testability" |
125
125
  | 4 | **What else touches the files being modified?** Name the callers. A change to a shared contract, DTO, or response shape is a breaking change until proven otherwise. | Editing a shared DTO with no note about its other consumers |
126
- | 5 | **What happens to data that already exists?** New required fields, schema changes, and backfills each need an answer for rows written before this change. | A non-nullable field added with no default and no backfill |
126
+ | 5 | **What happens to data that already exists?** New required fields, schema changes, and backfills each need an answer for rows written before this change — and the answer should run itself: the project's run-once migration mechanism if it has one, not a script someone has to remember in every environment (see **Deployment Scripts** in CLAUDE.md). | A non-nullable field added with no default and no backfill; a `backfill.js` to run by hand on test, staging and prod when the API already runs one-time migrations at startup |
127
127
  | 6 | **How does it fail?** Partial failure, concurrent callers, a retried request. Is the operation idempotent, and does it need to be? | A multi-step write with no story for a crash between steps |
128
128
  | 7 | **Does it hold at real data volume?** Queries inside loops, unbounded result sets, a missing index, a list endpoint with no paging. | A `foreach` over accounts issuing one query each |
129
129
  | 8 | **Is it safe?** Authorization on every new endpoint, and **no sensitive field** (TIN, SSN, EIN, TaxId, BankAccountNumber, RoutingNumber, any `Encrypted*`) read, logged, returned, or projected — see the sensitive-data rule in CLAUDE.md. | A new endpoint returning a whole entity because it was convenient |
@@ -158,6 +158,10 @@ Present the plan to the user:
158
158
  ### Files to Delete (if any)
159
159
  - `path/to/old/file.cs` — {why it's being removed}
160
160
 
161
+ ### Data Changes (if any)
162
+ - {what changes in existing data} — **automated** by {the project's run-once mechanism}: `{file}`
163
+ - {what changes in existing data} — **hand-run** `{script path}`, because {which Deployment Scripts reason applies}. Attached to the work item when the PR goes up.
164
+
161
165
  ### Unit Tests
162
166
  - `path/to/new.tests.cs` — covers {scenario the rework adds or fixes}
163
167
  - `path/to/existing.tests.cs` — updates assertions for {changed behavior}
@@ -236,7 +240,7 @@ Enter the estimated hours for this task (press enter to accept {n}):
236
240
 
237
241
  If the user provided hours (suggested or overridden):
238
242
 
239
- 1. Call `mcp__azure-devops__wit_create_work_item`:
243
+ 1. Call `mcp__azure-devops__wit_work_item_write` (action `create`):
240
244
  - **workItemType**: `Task`
241
245
  - **title**: `Rework AB#{id} — round {N}`
242
246
  - **fields**: JSON Patch document setting:
@@ -262,8 +266,9 @@ If the user provided hours (suggested or overridden):
262
266
  - `System.AreaPath` — same as the parent
263
267
  - `System.IterationPath` — same as the parent
264
268
  - `System.AssignedTo` — same as the parent (copy the parent's `System.AssignedTo` value; pass the `uniqueName` / email if the parent's value is an identity object). If the parent is unassigned, leave this field unset rather than failing.
269
+ - `System.State` — `Active`, since the rework starts right now (fall back to the template's in-progress equivalent, or leave it at the default and note it). A rework Task left at `New` while the work is underway misreports the board.
265
270
 
266
- 2. Link the new Task as a child of the parent work item via `wit_work_items_link`:
271
+ 2. Link the new Task as a child of the parent work item via `wit_work_item_link_write` (action `link`):
267
272
  - **type**: `Child` (the parent → child link from the parent's perspective; equivalent to `Parent` from the task's perspective)
268
273
  - **source**: parent work item ID
269
274
  - **target**: new task ID
@@ -282,6 +287,18 @@ The work item already has a branch from the previous PR. Switch to it:
282
287
 
283
288
  If the PR was completed/merged and the branch was deleted, create a new branch from the PR's target branch following the same naming convention as `/implement` Step 4.
284
289
 
290
+ ### Move the Work Item to Active
291
+
292
+ Once you are on the branch, move the work item (User Story, Bug, Hot Fix, or other single work item — **never** a Feature) to `Active` via `wit_work_item_write` (action `update`):
293
+ - **path**: `/fields/System.State`
294
+ - **value**: `Active`
295
+
296
+ Rework restarts implementation, so the item must leave `Code Review` / `Rework` and go back to in-progress for the duration of this round — Step 12 hands it back to `Code Review` when the fixes are pushed. Without this the item sits in a review state while it is actively being worked, and the board lies.
297
+
298
+ If the work item is already `Active`, skip the update. If the project's process template does not have an `Active` state (the update call returns an invalid-state error), fall back in this order: `In Progress` → `Doing` → leave the current state and warn the user that the state could not be advanced automatically. Do not silently swallow the error.
299
+
300
+ After the update, **read the work item back** (`wit_work_item`, action `get`) and confirm `System.State` actually changed. If it didn't, say so explicitly — do not proceed reporting the item as in progress when the board still shows it otherwise.
301
+
285
302
  ## Step 7: Implement
286
303
 
287
304
  1. **Implement** the rework using backend and/or frontend agents according to the approved plan
@@ -375,9 +392,10 @@ Wait for the user's response before proceeding. Do NOT push until confirmed.
375
392
  ## Step 12: Push and Update
376
393
 
377
394
  1. Push the changes: `git push`
378
- 2. **Do not post a rework summary comment.** Do not add a summary of what changed to the work item Discussion (`wit_add_work_item_comment`) or as a PR thread. The pushed commits and the PR diff are the record of what changed — a prose summary duplicates them and clutters the work item. If the reviewer left specific PR comment threads, reply on those threads directly (that is what `/resolve-feedback` and `/fix-review` do); otherwise post nothing.
379
- 3. **Close related Tasks and log hours** — see "Closing Related Tasks" below. This includes the rework Task created in Step 5 as well as any other child Tasks that became `Completed` as a result of this rework round.
380
- 4. **Move the work item back to `Code Review`** via `wit_update_work_item`:
395
+ 2. **Do not post a rework summary comment.** Do not add a summary of what changed to the work item Discussion (`wit_work_item_comment_write` (action `add`)) or as a PR thread. The pushed commits and the PR diff are the record of what changed — a prose summary duplicates them and clutters the work item. If the reviewer left specific PR comment threads, reply on those threads directly (that is what `/resolve-feedback` and `/fix-review` do); otherwise post nothing.
396
+ 3. **Attach deployment scripts.** Run `/implement`'s **Attaching Deployment Scripts** step against this branch — diff it against the PR's target branch (`git diff --name-only --diff-filter=AM {target}...HEAD`), so a script the original PR added and never attached is caught too. A script this rework changed is already attached in its old form: replace that attachment, don't add a second copy — a promotion that lists both versions invites someone to run the stale one. Same rules and report lines as in `/implement` (see **Deployment Scripts** in CLAUDE.md).
397
+ 4. **Close related Tasks and log hours** — see "Closing Related Tasks" below. This includes the rework Task created in Step 5 as well as any other child Tasks that became `Completed` as a result of this rework round.
398
+ 5. **Move the work item back to `Code Review`** via `wit_work_item_write` (action `update`):
381
399
  - **path**: `/fields/System.State`
382
400
  - **value**: `Code Review`
383
401
 
@@ -440,7 +458,7 @@ For each task being processed, prompt for completed hours:
440
458
 
441
459
  **Wait for the user's response on every task.** Accept the suggested/current value (enter), a new numeric value, or `skip` to leave that one untouched.
442
460
 
443
- Once the user has answered, update each task via `wit_update_work_item`:
461
+ Once the user has answered, update each task via `wit_work_item_write` (action `update`):
444
462
  - `Microsoft.VSTS.Scheduling.CompletedWork` → the agreed value
445
463
  - `Microsoft.VSTS.Scheduling.RemainingWork` → `0`
446
464
  - `System.State` → `Closed` (fall back to `Done` if the project's task template uses Agile; warn if neither is valid)
@@ -49,7 +49,7 @@ Deployed to:
49
49
  Catch these up? (yes/no)
50
50
  ```
51
51
 
52
- If the user says yes, set `System.State` on each lagging item to the expected state via `wit_update_work_item` — never backward, never on a Feature or Task — and report `Was → Now`.
52
+ If the user says yes, set `System.State` on each lagging item to the expected state via `wit_work_item_write` (action `update`) — never backward, never on a Feature or Task — and report `Was → Now`.
53
53
 
54
54
  ## If Pipeline (e.g., `/track pipeline` or `/track build`):
55
55
 
@@ -185,10 +185,48 @@ How the commands use this table:
185
185
 
186
186
  #### Deployment Scripts
187
187
 
188
- A SQL migration or a backfill script is attached to the work item it belongs to, and it has to run in **every** environment that item's code lands in — test, then staging, then prod. The promotion carries the code, never the script.
188
+ A SQL migration, a data backfill, a rename script — anything someone has to **run by hand** against an environment — is attached to the work item it belongs to, and it has to run in **every** environment that item's code lands in — test, then staging, then prod. The promotion carries the code, never the script.
189
189
 
190
190
  `/promote`, `/cherry-pick` and `/deploy-release` therefore read the carried items' attachments (`wit_work_item` `action: get`, `expand: "Relations"`) and list any that look like something to run: an `AttachedFile` whose extension is **not** a document, image or video (`.docx .xlsx .csv .pdf .png .jpg .mp4` and friends). Everything else counts — the rule is loose on purpose, because a filename glanced at and dismissed costs seconds while a migration nobody ran costs an environment. The list appears before the confirmation, in the PR description, and again once the pipeline is green, which is when it actually has to be run.
191
191
 
192
+ **Automate first — a hand-run script is the fallback.** When a change needs existing data corrected, backfilled or renamed, Claude plans it through the project's own run-once migration mechanism if it has one: a seeder that records finished migrations (COMPASS's `DataSeeder` and its `dataMigrations` collection), EF Core migrations applied at startup, DbUp, a migration step the pipeline already runs. Those run by themselves on every environment's deploy, after the new code is live, with the app's own connection string — nothing to remember, nothing to attach. A hand-run script is right only when the change can't live there, and the plan names which reason applies:
193
+
194
+ - the project has no such mechanism — building one is its own work item, never folded into this one;
195
+ - the script creates the database or tenant the app would run in (provisioning);
196
+ - it touches something outside the app's own data stores (Azure resources, another system);
197
+ - a person has to check the result before it is applied.
198
+
199
+ **Claude always attaches the hand-run script it writes.** Committing it to the repo is not enough: the promotion commands look for scripts on the work item, never in the repo, so an unattached script is reported as `No deployment scripts attached` and goes unrun in staging or prod. Whenever Claude writes one — in `/implement`, `/rework`, or any other session — or tells someone to run one that isn't attached yet, it attaches it before finishing:
200
+
201
+ - **Which files.** A file in the change that a person runs by hand, once per environment: `.sql`, a Mongo script, a `.sh` / `.ps1` / `.py` / `.js` data fix. The test: if the UAT checklist, the PR, or Claude's report tells someone to run it, it gets attached. Not app code, not tests or build tooling, not a migration the app or the pipeline applies by itself.
202
+ - **Which work item.** The one whose change needs it. In a Feature run, the child story — never the Feature.
203
+ - **The comment says how to run it.** The attachment comment carries the repo path and the exact command, with the environment as a placeholder (e.g. `scripts/tenant-provisioning/rename-manager-roles.sh — after each environment's deploy: RMR_CONFIRM='apply <Env>' scripts/…/rename-manager-roles.sh apply <Env>`). Whoever deploys to prod next month won't have this session.
204
+ - **No secrets in the file.** Never attach a script with a connection string, key, password, or sensitive field value in it — the script reads those from the environment. If it can't, stop and tell the user instead of attaching.
205
+ - **Replace, don't duplicate.** If an attachment with the same filename is already on the item, compare it with the repo copy (`curl` the attachment's `url` into `diff`). Identical → leave it. Different → swap it in one PATCH (`remove` the old relation by its index, then `add` the new one), so a promotion never lists two versions of one script.
206
+
207
+ The Azure DevOps MCP server can only *download* attachments, so the upload goes through the REST API with an `az` token. The org and project GUID come from the work item's own `url` (`https://dev.azure.com/{org}/{projectId}/_apis/wit/workItems/{id}`):
208
+
209
+ ```bash
210
+ TOKEN=$(az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798 --query accessToken -o tsv)
211
+ BASE="https://dev.azure.com/{org}/{projectId}/_apis/wit"
212
+
213
+ # 1. Upload the bytes — the response JSON carries the attachment "url"
214
+ curl -sS -X POST "$BASE/attachments?fileName={file name}&api-version=7.1" \
215
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/octet-stream" \
216
+ --data-binary @"{repo path}"
217
+
218
+ # 2. Link it to the work item. The body goes in a scratch file, because the run command
219
+ # in the comment usually has quotes that break inline JSON:
220
+ # [{"op":"test","path":"/rev","value":{rev from a fresh get}},
221
+ # {"op":"add","path":"/relations/-","value":{"rel":"AttachedFile","url":"{attachment url}",
222
+ # "attributes":{"comment":"{repo path} — {how to run}"}}}]
223
+ curl -sS -X PATCH "$BASE/workitems/{id}?api-version=7.1" \
224
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json-patch+json" \
225
+ --data-binary @"{scratch dir}/attach-patch.json"
226
+ ```
227
+
228
+ Never print the token. If `az` has no session, swap the bearer header for `-u ":$AZURE_DEVOPS_PAT"`; if neither works, ask the user to run `! az login`. A failed attachment never blocks the PR, and it is never skipped quietly — the summary says `⚠️ NOT attached: {file} → AB#{id}` so it can be fixed before the first promotion.
229
+
192
230
  **Reported, never enforced.** A script never blocks a promotion and never changes the gate check — it may already have been run, or be a reference copy. The person deploying decides; the commands only make sure nobody finds out afterwards.
193
231
 
194
232
  #### Verifier Assignment