@chris1807/claude-kit 2.3.0 → 2.3.2
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 +5 -3
- package/package.json +1 -1
- package/templates/commands/create-work-item.md +4 -2
- package/templates/commands/rework.md +38 -21
- package/templates/hooks/work-item-intent.sh +38 -0
- package/templates/infrastructure/CLAUDE-WORKFLOW.md +10 -1
- package/templates/infrastructure/settings.json +10 -0
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Every session Claude learns from your feedback and gets better at helping you sp
|
|
|
27
27
|
|-----------|-------|----------------|-------------|
|
|
28
28
|
| **Global Agents** | 10 | `~/.claude/agents/` (your machine, all projects) | backend, frontend, legacy (Lucee/CFML), mockup, reviewer, test-runner, build-validator, lint-checker, azure-ops, security-auditor |
|
|
29
29
|
| **Project Agents** | 2 | `.claude/agents/` (in the project) | deployer, db-admin |
|
|
30
|
-
| **Hooks** |
|
|
30
|
+
| **Hooks** | 10 | `.claude/hooks/` (in the project) | Secret blocker, sensitive data blocker (Bash + MCP + output), protected files, auto-format, test suggestions, work item intent, UAT reminder, self-improve |
|
|
31
31
|
| **Slash Commands** | 24 | `.claude/commands/` (in the project) | `/implement`, `/review`, `/deep-review`, `/resolve-feedback`, `/fix-review`, `/deploy`, `/create-release`, `/deploy-release`, `/add-to-release`, `/cherry-pick`, `/promote`, `/rollback`, `/track`, `/plan-backlog`, `/plan-sprint`, `/quote-backlog`, `/cleanup-branches`, `/close-orphan-tasks`, `/quote`, `/explain`, `/create-work-item`, `/edit-work-item` |
|
|
32
32
|
| **MCP Servers** | Up to 6 | `.mcp.json` (in the project) | **Azure DevOps** (work items, repos, pipelines, wiki), Playwright, MongoDB/SQL/Postgres, Teams, Stripe, Azure CLI |
|
|
33
33
|
| **Workflow Template** | 1 | Appended to `CLAUDE.md` | Documents the full development process |
|
|
@@ -105,7 +105,7 @@ npx @chris1807/claude-kit init --all
|
|
|
105
105
|
This installs:
|
|
106
106
|
- ✅ Global agents (backend, frontend, legacy, mockup, reviewer, test-runner, build-validator, lint-checker, azure-ops, security-auditor)
|
|
107
107
|
- ✅ Project agents (deployer, db-admin)
|
|
108
|
-
- ✅ All
|
|
108
|
+
- ✅ All 10 hooks
|
|
109
109
|
- ✅ All 13 slash commands
|
|
110
110
|
- ✅ MCP servers: Playwright, Teams, Azure CLI (+ your DB choice)
|
|
111
111
|
- ✅ Settings, CLAUDE.md workflow, .gitignore
|
|
@@ -201,6 +201,7 @@ your-project/ ← Project-specific
|
|
|
201
201
|
│ │ ├── protected-files.sh # BLOCKS/warns on critical file edits
|
|
202
202
|
│ │ ├── auto-format.sh # Auto-runs formatters after edits
|
|
203
203
|
│ │ ├── test-on-change.sh # Suggests related tests after edits
|
|
204
|
+
│ │ ├── work-item-intent.sh # Routes "create a bug/story" prompts to /create-work-item
|
|
204
205
|
│ │ ├── uat-reminder.sh # Reminds to run UAT after features
|
|
205
206
|
│ │ └── self-improve.sh # Saves learnings after each session
|
|
206
207
|
│ │
|
|
@@ -691,7 +692,7 @@ Claude reviews for:
|
|
|
691
692
|
| `/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). Also audits the drop-out queue — tagged bugs and stories bounced to Design Review — for items whose creator answered but which nobody returned to the sweep |
|
|
692
693
|
| `/quote` | `/quote AB#1234` | Estimate a work item in story points (senior-calibrated Fibonacci rubric) |
|
|
693
694
|
| `/explain` | `/explain AB#1234` | Summarize and explain a work item in plain language |
|
|
694
|
-
| `/create-work-item` | `/create-work-item [description]` | Interactively draft and create a Feature, Bug, User Story, or Hot Fix — proposes story points (user must agree), creates pointed items in Dev Ready; on a Feature, also drafts its child stories with `Custom.Order` waves |
|
|
695
|
+
| `/create-work-item` | `/create-work-item [description]` | Interactively draft and create a Feature, Bug, User Story, or Hot Fix — proposes story points (user must agree), creates pointed items in Dev Ready; on a Feature, also drafts its child stories with `Custom.Order` waves. Runs automatically for any plain-language request to create a work item |
|
|
695
696
|
| `/edit-work-item` | `/edit-work-item AB#1234 [what to change]` | Revise an existing work item field-by-field. On a Feature, cascades into its child stories — updates, adds, retires, and re-sequences `Custom.Order` waves — with a safety gate on anything already past Dev Ready |
|
|
696
697
|
| `/cleanup-branches` | `/cleanup-branches` | Delete merged feature/work branches |
|
|
697
698
|
| `/close-orphan-tasks` | `/close-orphan-tasks --dry-run` | Close open Tasks whose parent is Ready to Deploy / Deployed / Closed |
|
|
@@ -707,6 +708,7 @@ These run automatically — no action needed:
|
|
|
707
708
|
| **Before** any Bash command | `sensitive-data-blocker.sh` | Blocks `mongosh` commands that reference sensitive PII fields (TIN, SSN, bank accounts). **Blocks the command.** |
|
|
708
709
|
| **Before** any MCP database tool | `sensitive-data-mcp-blocker.sh` | Blocks MongoDB/MSSQL/Postgres MCP tool calls that reference PII fields. **Blocks the call.** |
|
|
709
710
|
| **After** any Bash/MCP/Read/Grep | `sensitive-data-output-blocker.sh` | Scans output for PII field names in JSON, C#, YAML formats — catches broad queries, seed data, test fixtures, log files, and git diffs. **Blocks the output.** |
|
|
711
|
+
| **When you send a prompt** | `work-item-intent.sh` | Spots plain-language requests to create a work item ("log a bug…", "make a story…") and tells Claude to run `/create-work-item` instead of creating it directly. Never blocks; slash-command prompts are skipped. |
|
|
710
712
|
| **Before** any file write | `secret-blocker.sh` | Scans for hardcoded credentials (MongoDB URIs, AWS keys, Stripe keys, passwords). **Blocks the write.** |
|
|
711
713
|
| **Before** any file edit | `protected-files.sh` | Blocks edits to production/staging configs. Warns on critical files (CLAUDE.md, pipelines, Program.cs). |
|
|
712
714
|
| **After** any file edit | `auto-format.sh` | Runs `dotnet format` on .cs files, `eslint --fix` on .ts/.tsx files |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chris1807/claude-kit",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.2",
|
|
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": {
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
-
Create a new Azure DevOps work item interactively. Usage: `/create-work-item`
|
|
1
|
+
Create a new Azure DevOps work item (Bug, User Story, Feature, or Hot Fix) interactively. Use this whenever the user asks to create, log, file, open, or raise a work item, ticket, bug, story, feature, or hot fix, whether or not they typed the command. Usage: `/create-work-item [description]`
|
|
2
2
|
|
|
3
3
|
This command walks the user through creating a Feature, Bug, User Story, or Hot Fix, develops an acceptance-criteria-ready plan, optionally embeds a UI mockup in the description, and creates the item in the chosen Azure DevOps project. For a Feature it can also draft and create the child User Stories that make the Feature implementable.
|
|
4
4
|
|
|
5
5
|
Treat `$ARGUMENTS` as an optional rough description that the user may have typed inline (e.g. `/create-work-item users should be able to export payments`). If provided, skip the initial "describe your requirements" prompt in Step 2 and use it as the starting requirements text — but still confirm with the user before proceeding.
|
|
6
6
|
|
|
7
|
+
**This command is the only way Claude creates a Feature, Bug, User Story, or Hot Fix.** A plain-language request ("log a bug that the export button 500s", "make a story for bulk assign") runs this command even when the user didn't type it. Claude invokes it through the Skill tool with the request text as `$ARGUMENTS`, and the `work-item-intent.sh` hook adds a reminder whenever a prompt reads like one. Every step below applies the same way to an invoked run: prior art, duplicate check, draft approval, and proposed points. Never skip ahead to a direct `wit_work_item_write` create.
|
|
8
|
+
|
|
7
9
|
## Step 1: Choose Work Item Type
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
If `$ARGUMENTS` already names the type unambiguously (`bug`, `user story` / `story`, `feature`, `hot fix` / `hotfix`), use it and skip the question. Name the type in the Step 2 confirmation so the user can correct it. Otherwise, ask the user:
|
|
10
12
|
|
|
11
13
|
```
|
|
12
14
|
What type of work item do you want to create?
|
|
@@ -12,7 +12,7 @@ The one exception is Step 2 (gathering feedback), which runs **before** the Step
|
|
|
12
12
|
When Ultracode is in use, these rules apply:
|
|
13
13
|
|
|
14
14
|
- **Fan out the read / analyze / verify work** — gathering feedback (Step 2), exploring the codebase (Step 4), and reviewing + verifying the diff and AC coverage (Steps 9–10) are run as `Workflow` scripts with one agent per independent unit (per comment, per subsystem, per review dimension, per acceptance criterion). Each agent returns **structured findings** via a `schema`; you synthesize the results in the main loop.
|
|
15
|
-
- **Never fan out an interactive gate or a write.** Every user prompt (Steps 3, 4-approval, 5, 10-decisions, 11) and every work-item or git mutation (Step 0 worktree, Step 5 create, Step 6 branch, Step 7 implement, Step 12 push/close, Step 13 cleanup) stays in the **main loop**. Workflow agents here are **read-only analysts** — they use MCP read tools, `Read`, and `Grep`, and they return data. They do not create or close work items, switch branches, write code, or ask the user anything.
|
|
15
|
+
- **Never fan out an interactive gate or a write.** Every user prompt (Steps 3, 4-approval, 5, 10-decisions, 11) and every work-item or git mutation (Step 0 worktree, Step 5 create, Step 6 branch, Step 7 implement, Step 12 push/PR/close, Step 13 cleanup) stays in the **main loop**. Workflow agents here are **read-only analysts** — they use MCP read tools, `Read`, and `Grep`, and they return data. They do not create or close work items, switch branches, write code, or ask the user anything.
|
|
16
16
|
- **Give every Workflow agent the ticket's worktree path** (Step 0) — that is where the code under analysis lives, not the folder the session started in.
|
|
17
17
|
- **Stay in the loop between phases.** Run one `Workflow` per phase, read its results, present/await the user as the steps require, then launch the next phase's workflow. This is several short workflows in sequence — not one monolithic run that tries to swallow the approval gates.
|
|
18
18
|
- **Review uses the canonical find → adversarially-verify pipeline** (Step 10): fan out per dimension, then spawn skeptic verifiers per finding and drop findings the majority refute, so only confirmed issues reach the user.
|
|
@@ -29,7 +29,7 @@ Find the most recent PR linked to this work item:
|
|
|
29
29
|
2. For each linked PR, fetch its details via `repo_get_pull_request_by_id` and record the **creationDate**
|
|
30
30
|
3. Identify the **most recent PR** by creation date — this is the baseline for detecting new feedback
|
|
31
31
|
|
|
32
|
-
Save the PR's `creationDate` as `LAST_PR_DATE` — everything after this timestamp is new feedback. Also save its **source branch** and **target branch** (`sourceRefName` / `targetRefName`, minus `refs/heads/`) — Step 0 needs both.
|
|
32
|
+
Save the PR's `creationDate` as `LAST_PR_DATE` — everything after this timestamp is new feedback. Also save its **source branch** and **target branch** (`sourceRefName` / `targetRefName`, minus `refs/heads/`) — Step 0 needs both — and its **status** (`active`, `completed`, or `abandoned`). The status decides which branch the rework builds on (Step 0c) and whether Step 12 has to open a new PR.
|
|
33
33
|
|
|
34
34
|
## Step 0: Set Up the Ticket's Workspace
|
|
35
35
|
|
|
@@ -67,14 +67,19 @@ Look at every **other** worktree in `git worktree list --porcelain` whose folder
|
|
|
67
67
|
Remove with `git -C "{MAIN}" worktree remove "{path}"`, then `git -C "{MAIN}" branch -D "{branch}"`. **Never `--force`, never `rm` the folder.** If a removal fails because another session removed it first, ignore that and move on.
|
|
68
68
|
- **Anything else stays.** List what was kept in one line, with the reason — `Kept: ../CSIPay-AB5301 (2 uncommitted files), ../CSIPay-AB5310 (locked — another session, or abandoned: git worktree unlock "{path}")`.
|
|
69
69
|
|
|
70
|
-
### 0c. Put the worktree on the
|
|
70
|
+
### 0c. Put the worktree on the rework's branch
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
**First, pick `BRANCH`** — the branch this rework builds on:
|
|
73
73
|
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
- **The PR is `active` or `abandoned`, and `SOURCE` is still on origin** (`git -C "{MAIN}" rev-parse --verify --quiet "refs/remotes/origin/{SOURCE}"` succeeds) → `BRANCH` is `SOURCE`. The rework continues the unmerged work.
|
|
75
|
+
- **Otherwise** → `BRANCH` is a **new branch** from the PR's target. This covers a `completed` PR (merged), or `SOURCE` deleted. A completed PR's work is already in the target, so the rework starts there even if `SOURCE` still exists. Building on the merged branch would make the new PR show the old changes again after a squash merge. Name the new branch by `/implement` Step 4's convention (`{prefix}AB#{id}-{sanitized-title}`). If that name is still on origin (the merged branch was kept), append `-rework-{N}`, where `{N}` is the rework round Step 5 will use: existing `Rework AB#{id}` child Tasks + 1.
|
|
76
|
+
|
|
77
|
+
Then take the first case that matches:
|
|
78
|
+
|
|
79
|
+
1. **A worktree is already on `BRANCH`** — a `branch refs/heads/{BRANCH}` line in `git worktree list --porcelain` → use that worktree as `WT`, wherever it is (a hand-made folder, or even `MAIN` itself). Don't create a second one, and don't fail because the branch is checked out elsewhere. If `BRANCH` is `SOURCE`, bring it up to date with `git -C "{WT}" pull --ff-only`.
|
|
80
|
+
2. **`WT` is already a worktree, but on something else** (a detached HEAD, another branch) → show `git -C "{WT}" status -sb` and ask whether to switch it to `BRANCH` or stop.
|
|
76
81
|
3. **`WT` exists but git doesn't know it** (not in the list even after 0a's prune) → stop and ask the user to delete or rename it. Its contents aren't in git, so there is no way to tell whether anything in it is worth keeping.
|
|
77
|
-
4. **`
|
|
82
|
+
4. **`BRANCH` is `SOURCE`** → check it out, tracking `origin/{SOURCE}`:
|
|
78
83
|
- **No local branch:**
|
|
79
84
|
|
|
80
85
|
```bash
|
|
@@ -83,13 +88,13 @@ Take the first case that matches:
|
|
|
83
88
|
- **A local branch exists:** run `git -C "{MAIN}" worktree add "{WT}" "{SOURCE}"`, then `git -C "{WT}" branch --set-upstream-to "origin/{SOURCE}"`, then `git -C "{WT}" pull --ff-only`.
|
|
84
89
|
|
|
85
90
|
If `pull --ff-only` fails, the local branch and origin have diverged. Stop and show both sides (`git -C "{WT}" log --oneline --left-right '@{u}...HEAD'`). Never merge, rebase, or reset without asking.
|
|
86
|
-
5. **`
|
|
91
|
+
5. **`BRANCH` is new** → create it from the PR's **target** — the rule from before worktrees, now inside the worktree:
|
|
87
92
|
|
|
88
93
|
```bash
|
|
89
|
-
git -C "{MAIN}" worktree add --no-track -b "{
|
|
94
|
+
git -C "{MAIN}" worktree add --no-track -b "{BRANCH}" "{WT}" "origin/{TARGET}"
|
|
90
95
|
```
|
|
91
96
|
|
|
92
|
-
It has no upstream until Step 12 pushes it with `-u
|
|
97
|
+
It has no upstream until Step 12 pushes it with `-u`, and no PR until Step 12 opens one. If `-b` fails because a leftover local branch has that name, show what it holds that the target doesn't (`git -C "{MAIN}" log --oneline "origin/{TARGET}..{BRANCH}"`). Then ask whether to delete it (`git -C "{MAIN}" branch -D "{BRANCH}"`) and retry, or reuse it.
|
|
93
98
|
|
|
94
99
|
Then **lock it** so another session's 0b leaves it alone — a clean, fully pushed worktree would otherwise pass every tidy check the moment its PR merges:
|
|
95
100
|
|
|
@@ -129,7 +134,7 @@ Report the workspace in one short block, then go on to Step 2:
|
|
|
129
134
|
|
|
130
135
|
```
|
|
131
136
|
Workspace for AB#{id}: {WT}
|
|
132
|
-
{reused, on {
|
|
137
|
+
{reused, on {BRANCH} | new, on {SOURCE} from origin | new branch {BRANCH} from origin/{TARGET} — PR #{n} {was completed | lost its branch}}
|
|
133
138
|
Tidied: {removed worktrees, or "nothing to tidy"} Kept: {kept worktrees + reason, or omit}
|
|
134
139
|
Edits there need approval once — run `/add-dir {WT}` to allow them for this session.
|
|
135
140
|
```
|
|
@@ -175,7 +180,8 @@ Present a summary of the rework feedback to the user. **Every feedback item must
|
|
|
175
180
|
```
|
|
176
181
|
## Rework for AB#{id}: {title}
|
|
177
182
|
|
|
178
|
-
**Last PR:** #{pr_id} (created {date})
|
|
183
|
+
**Last PR:** #{pr_id} (created {date}, {status})
|
|
184
|
+
{only if status is not active: "PR #{pr_id} is {status} — this rework goes up as a new PR."}
|
|
179
185
|
**New comments:** {count}
|
|
180
186
|
|
|
181
187
|
### Current Acceptance Criteria
|
|
@@ -383,15 +389,15 @@ If the user cancels, skip task creation and proceed — note "No rework task cre
|
|
|
383
389
|
|
|
384
390
|
## Step 6: Switch to Existing Branch
|
|
385
391
|
|
|
386
|
-
**In a worktree** (the default), there is nothing to switch. Step 0c has already put `WT` on the previous PR's branch and pulled it
|
|
392
|
+
**In a worktree** (the default), there is nothing to switch. Step 0c has already put `WT` on the previous PR's branch and pulled it. If that PR was completed or its branch deleted, Step 0c put it on a new branch from the PR's target instead. Confirm with `git -C "{WT}" status -sb` and go on to "Move the Work Item to Active".
|
|
387
393
|
|
|
388
|
-
**Working in place**, the work item already has a branch from the previous PR. Switch to it:
|
|
394
|
+
**Working in place**, if the PR is `active` or `abandoned`, the work item already has a branch from the previous PR. Switch to it:
|
|
389
395
|
|
|
390
396
|
1. Get the source branch name from the most recent PR
|
|
391
397
|
2. Switch to that branch: `git checkout <branch-name>`
|
|
392
398
|
3. Pull the latest: `git pull`
|
|
393
399
|
|
|
394
|
-
If the PR was completed
|
|
400
|
+
If the PR was completed, or its branch was deleted, create a new branch from the PR's target branch instead, following the same naming convention as `/implement` Step 4 (`git fetch --prune origin`, then `git checkout -b "<branch-name>" "origin/<target>"`). Don't build on a completed PR's branch even if it still exists. Add the `-rework-{N}` suffix when the name is still on origin. Step 0c explains both rules.
|
|
395
401
|
|
|
396
402
|
### Move the Work Item to Active
|
|
397
403
|
|
|
@@ -499,18 +505,29 @@ Wait for the user's response before proceeding. Do NOT push until confirmed.
|
|
|
499
505
|
|
|
500
506
|
## Step 12: Push and Update
|
|
501
507
|
|
|
502
|
-
1. Push the changes: `git push` (in a worktree: `git -C "{WT}" push`
|
|
503
|
-
2. **
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
508
|
+
1. Push the changes: `git push` (in a worktree: `git -C "{WT}" push`). A **new branch** from Step 0c case 5, or from the in-place fallback in Step 6, has no upstream yet, so push it with `git push -u origin HEAD` (`git -C "{WT}" push -u origin HEAD`).
|
|
509
|
+
2. **Open a PR if none is active.** A push only reaches a reviewer through an active PR. Re-read the latest PR's status, since it may have changed during the rework:
|
|
510
|
+
- **Still `active`** → the push updated it. Nothing to create.
|
|
511
|
+
- **`completed` or `abandoned`, or the rework is on a new branch** → nothing is reviewing these commits yet. Create a PR the way `/implement` Step 10 does:
|
|
512
|
+
- **sourceRefName**: `refs/heads/{branch}` — the branch just pushed
|
|
513
|
+
- **targetRefName**: `refs/heads/{target}` — the latest PR's target
|
|
514
|
+
- **title**: `AB#{id}: {work item title} (rework round {N})`
|
|
515
|
+
- **description**: `Rework round {N} of AB#{id}. Follows PR #{old} ({status}).` Keep it to that one line; item 3 applies.
|
|
516
|
+
- **labels**: `["hotfix"]` if the work item type is Hot Fix
|
|
517
|
+
|
|
518
|
+
Link it to the work item via `wit_work_item_link_write` (action `link_to_pull_request`). Report `Opened PR #{new} → {target} (PR #{old} is {status})`. The next `/rework` finds this PR as the latest.
|
|
519
|
+
- **Completed during this rework** (it was `active` at Step 1, so the rework was built on the old branch) → open the new PR the same way, but warn first: if #{old} was squash-merged, the new PR shows its changes again. Offer to merge `origin/{target}` into the branch and push again before opening the PR, which clears them.
|
|
520
|
+
3. **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.
|
|
521
|
+
4. **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).
|
|
522
|
+
5. **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.
|
|
523
|
+
6. **Move the work item back to `Code Review`** via `wit_work_item_write` (action `update`):
|
|
507
524
|
- **path**: `/fields/System.State`
|
|
508
525
|
- **value**: `Code Review`
|
|
509
526
|
|
|
510
527
|
Rework is triggered by reviewer feedback, so the item was likely in `Active` / `In Progress` / `Rework` while the fixes were being made. Pushing the rework hands it back to the reviewer, so it belongs in `Code Review` again.
|
|
511
528
|
|
|
512
529
|
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. Do not silently swallow the error.
|
|
513
|
-
|
|
530
|
+
7. **Remove the ticket's worktree** — Step 13, once everything above is done.
|
|
514
531
|
|
|
515
532
|
> **PR completion closes the Task only.** When the PR is later completed/merged, only the child **Task** may be closed — never the parent User Story or Bug. Azure DevOps's "Complete associated work items" option transitions *every* linked work item (including the parent the PR is linked to), so do **not** enable it when completing the PR. Close the child Task explicitly instead; the parent stays in `Code Review` until it is promoted through `dev → test → staging → prod` (see **Work Item States ↔ Environments** in CLAUDE.md).
|
|
516
533
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Work Item Intent Hook (UserPromptSubmit)
|
|
3
|
+
# Routes plain-language requests to create a work item through /create-work-item,
|
|
4
|
+
# so "log a bug for the export 500" gets the same prior-art check, title prefix,
|
|
5
|
+
# AC field, proposed points, and draft approval as typing the command.
|
|
6
|
+
#
|
|
7
|
+
# Never blocks. On a match it prints a note that Claude Code adds to the
|
|
8
|
+
# prompt's context; the note is conditional, so a false positive ("add a
|
|
9
|
+
# feature flag") costs a few tokens and is ignored.
|
|
10
|
+
|
|
11
|
+
# Read the hook input from stdin
|
|
12
|
+
INPUT=$(cat)
|
|
13
|
+
|
|
14
|
+
MATCH=$(echo "$INPUT" | python3 -c "
|
|
15
|
+
import sys, json, re
|
|
16
|
+
try:
|
|
17
|
+
prompt = json.load(sys.stdin).get('prompt', '').strip()
|
|
18
|
+
except Exception:
|
|
19
|
+
sys.exit(0)
|
|
20
|
+
|
|
21
|
+
# Slash commands run their own flow — /create-work-item is already running,
|
|
22
|
+
# and work items other commands create (Tasks, child stories) follow theirs.
|
|
23
|
+
if prompt.startswith('/'):
|
|
24
|
+
sys.exit(0)
|
|
25
|
+
|
|
26
|
+
verb = r'\b(create|make|add|file|log|open|raise|write\s+up|submit|draft|put\s+in|enter)\b'
|
|
27
|
+
noun = (r'\b(work\s*items?|tickets?|bugs?|user\s+stor(y|ies)|stor(y|ies)|'
|
|
28
|
+
r'features?(?!\s+(flags?|toggles?|branch(es)?))|hot\s*fix(es)?|backlog\s+items?|pbis?)\b')
|
|
29
|
+
|
|
30
|
+
if re.search(verb + r'.{0,40}?' + noun, prompt, re.IGNORECASE | re.DOTALL):
|
|
31
|
+
print('match')
|
|
32
|
+
" 2>/dev/null)
|
|
33
|
+
|
|
34
|
+
if [ "$MATCH" = "match" ]; then
|
|
35
|
+
echo "Work item request check: if the user is asking to create an Azure DevOps work item (Bug, User Story, Feature, or Hot Fix), run /create-work-item now with the Skill tool, passing their request as the arguments. Do not create it with a direct wit_work_item_write call. If /create-work-item is already running in this conversation, or this prompt is not a request to create a work item, ignore this note."
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
exit 0
|
|
@@ -68,6 +68,7 @@ These run automatically — no action needed:
|
|
|
68
68
|
| **Before any Bash command** | Sensitive data blocker prevents database queries that reference TIN, SSN, or other PII fields |
|
|
69
69
|
| **Before any MCP database tool** | Sensitive data MCP blocker prevents MCP database queries that reference PII fields |
|
|
70
70
|
| **After any Bash/MCP/Read/Grep command** | Sensitive data output blocker scans results for PII field names and blocks exposure |
|
|
71
|
+
| **When you send a prompt** | Work item intent check — a plain-language request to create a work item is routed to `/create-work-item` |
|
|
71
72
|
| **Before any file write** | Secret blocker scans for hardcoded credentials and blocks them |
|
|
72
73
|
| **Before any file edit** | Protected files guard warns/blocks edits to production configs |
|
|
73
74
|
| **After any file edit** | Auto-formatter runs (dotnet format for .cs, eslint --fix for .ts) |
|
|
@@ -109,6 +110,14 @@ Claude maintains persistent memory across sessions in `~/.claude/projects/.../me
|
|
|
109
110
|
|
|
110
111
|
**One worktree per ticket.** `/implement` and `/rework` never check out in the folder the session started in. Each ticket gets a sibling git worktree, `../{repo}-AB{id}` (e.g. `../CSIPay-AB5373`), where every build, test, and commit happens. It is removed once the branch is pushed, or kept with a note if anything is uncommitted or unpushed. That lets several sessions work different tickets in the same repo at once. Say **"work in place"** (or "no worktree") to opt a run out. Sessions sharing a repo still share **local ports and the Dev database** — two dev servers on one port, or two integration runs against Dev, will still collide.
|
|
111
112
|
|
|
113
|
+
### Creating Work Items — Always Through `/create-work-item`
|
|
114
|
+
|
|
115
|
+
Every Feature, User Story, Bug, or Hot Fix Claude creates goes through `/create-work-item`, whether or not the user typed the command. "Log a bug that the export 500s", "make a story for bulk assign", "open a ticket for this" all mean: invoke `create-work-item` with the Skill tool, passing the request text as the arguments. Never create one with a direct `wit_work_item_write` call. That skips the prior-art and duplicate checks, the title prefix, the AC field, the proposed points, and the user's approval of the draft. The `work-item-intent.sh` hook adds a reminder to any prompt that reads like a creation request.
|
|
116
|
+
|
|
117
|
+
This includes items Claude decides to raise itself, such as a defect found mid-task or out-of-scope work. Propose it, and if the user agrees, run `/create-work-item` with what you found.
|
|
118
|
+
|
|
119
|
+
Work items a command creates as one of its own steps keep that command's flow: child Tasks from `/implement`, `/rework`, `/plan-backlog`, and `/plan-sprint`, and child stories from `/create-work-item` and `/edit-work-item`. A new Bug or Story requested in the middle of one of those commands still goes through `/create-work-item`.
|
|
120
|
+
|
|
112
121
|
### Story Points & Dev Ready Policy
|
|
113
122
|
|
|
114
123
|
These rules apply to **every** command or flow that creates or estimates work items:
|
|
@@ -365,7 +374,7 @@ All deployment and release operations are available as slash commands:
|
|
|
365
374
|
| `/plan-sprint` | `/plan-sprint [project]` | Sweep the current sprint for stories/bugs with no child tasks → propose one child task with hours per item |
|
|
366
375
|
| `/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 |
|
|
367
376
|
| `/quote` | `/quote AB#1234` | Estimate story points for one work item; on approval, sets the points and moves the item to Dev Ready. If it can't be estimated, offers to send a story back to **Design Review** or tag a bug **`needs-info`** |
|
|
368
|
-
| `/create-work-item` | `/create-work-item [description]` | Interactively draft and create a Feature, Bug, User Story, or Hot Fix — proposes story points (user must agree) and creates pointed items in Dev Ready; on a Feature, also drafts its child stories with `Custom.Order` waves |
|
|
377
|
+
| `/create-work-item` | `/create-work-item [description]` | Interactively draft and create a Feature, Bug, User Story, or Hot Fix — proposes story points (user must agree) and creates pointed items in Dev Ready; on a Feature, also drafts its child stories with `Custom.Order` waves. Runs automatically for any plain-language request to create a work item |
|
|
369
378
|
| `/edit-work-item` | `/edit-work-item AB#1234 [what to change]` | Revise an existing work item field-by-field. On a Feature, cascades the change into its child stories — updates, adds, retires, and re-sequences `Custom.Order` waves — with a safety gate on anything already past Dev Ready |
|
|
370
379
|
| `/cleanup-branches` | `/cleanup-branches` | Delete merged branches |
|
|
371
380
|
| `/close-orphan-tasks` | `/close-orphan-tasks [scope] [--dry-run]` | Close open Tasks whose parent is Ready to Deploy / Deployed / Closed |
|