Skill instructions
coverage-check4.25 KB
View saved version →
---
name: coverage-check
description: Run the repo's unit tests with coverage and verify that every file touched in the current change keeps line, branch, and function coverage at or above 95%. Language- and framework-agnostic. Use before committing, before PR creation, or when the user asks about coverage.
---
# Coverage Check
Enforce the team's coverage gate: **every touched file must stay ≥ 95%** (line, branch, function). This skill is stack-agnostic — it runs whatever the consuming repo declares and parses whatever standard report the run produces.
## 1. Find the touched files
`git diff --name-only` against the base branch, plus staged and unstaged changes. Exclude, by convention: generated/vendored code, database migrations, and the test files themselves. Group the remaining files by the module/project they belong to so you can run the narrowest useful test set first.
## 2. Determine the coverage command(s)
In order of preference:
1. **Declared in config** — read `.claude/dev-kit.json` (`test.coverageCommands`) and the consuming repo's `CLAUDE.md`. If a command is declared, use it verbatim.
2. **Declared by the repo's tooling** — a `test:coverage` script in `package.json`, a `Makefile`/`Taskfile` target, a `coverage` task in the build file.
3. **From the stack profile** — if `.claude/dev-kit.json` has `stacks` (or you detect one), read `instructions/stacks/<id>.md` for the stack's coverage command, report path, and format, plus any prerequisite (e.g. PHP needs Xdebug/PCOV; without it, report that rather than 0%).
4. **Detected from the stack** — infer from the project files present, e.g.:
| Stack signal | Typical coverage command | Report produced |
|---|---|---|
| `*.csproj` / `*.sln` | `dotnet test --collect:"XPlat Code Coverage"` | Cobertura XML |
| `package.json` (jest/vitest) | `npm test -- --coverage` | lcov / json-summary |
| `angular.json` | `ng test --watch=false --code-coverage` | lcov |
| `pom.xml` / `build.gradle` | `mvn test` / `gradle test jacocoTestReport` | JaCoCo XML |
| `pyproject.toml` / `setup.py` | `pytest --cov --cov-report=xml` | coverage.py XML |
| `go.mod` | `go test ./... -coverprofile=cover.out` | Go coverprofile |
| `Cargo.toml` | `cargo llvm-cov --lcov` | lcov |
A monorepo may need several commands (one per language/area). Run each and merge the per-file results.
If you detect the command by inference (not from config), **offer to persist it** to `.claude/dev-kit.json` under `test.coverageCommands` so the next run is deterministic.
## 3. Run and parse
Run the command(s), then parse the produced report for per-file line/branch/function metrics. Handle the common formats: **Cobertura XML, lcov (`lcov.info`), JaCoCo XML, coverage.py XML, Go coverprofile, and json-summary**. Map each report path back to the touched source files from step 1.
## 4. Verdict
Report a table, worst offenders first:
```
| File | Lines | Branches | Functions | Verdict |
|------|-------|----------|-----------|---------|
| src/payments/payment_service.<ext> | 97.2% | 95.0% | 100% | PASS |
| src/payments/payment-list.component.<ext> | 88.4% | 71.0% | 90.0% | FAIL |
```
- **The bar is the project's own** (adaptive — see `instructions/testing-standards.md`). Use the project's configured threshold or `gates.coverage.min` in `.claude/dev-kit.json`; **default ≥ 95%** when none is set. Also **FAIL on a regression** (a touched file dropping below its pre-change coverage) even if it's above the bar.
- **N/A, not FAIL, when the project has no test/coverage setup.** If there is no test suite or coverage tooling, report `NOT APPLICABLE — no coverage setup` with a recommendation to add tests (and offer to set it up) — do **not** invent a failure or a number. Only enforce a hard gate when `gates.coverage` is `required`.
- **FAIL** (when the gate applies) if any touched file is below the bar or regresses; list the uncovered lines/branches and propose the specific missing test cases, and don't mark work complete / open a PR while it fails.
- If tests themselves fail, report the failures verbatim — never report coverage from a failing run as authoritative.
- If a metric is genuinely unavailable for a stack (e.g. a runner reports no branch coverage), state that plainly rather than reporting a fabricated number.
create-pr5.24 KB
View saved version →
---
name: create-pr
description: Create a branch, commit the work, and open a pull request for a completed user story, after all quality gates pass. Use when the user asks to open/create a PR or as the final step of the story workflow.
---
# Create PR
Final step of the story workflow. Runs when the **applicable** gates pass (gates are adaptive to the project — see `instructions/testing-standards.md`).
## Preconditions (verify, do not assume)
1. Unit tests for touched files pass — *when the project has a test framework*.
2. `coverage-check` passes — *when the project has coverage tooling* (project's bar, default ≥ 95%, no regression).
3. Related e2e tests pass — *when the project does e2e* (`e2e-generate` ran for user-facing changes).
4. Lint passes for touched files — *when the project lints*.
5. A `pr-review`-style self-review found no unresolved blocking findings.
6. Security pass has no blocking findings (**always applies**).
A gate that **does not apply** (no test/e2e/lint setup) is not a blocker — but it must be **called out in the PR "How it was verified" section** as *not applicable, recommend adding*, never omitted. A gate that applies and **fails** stops the PR: report what's missing instead of opening it. (A `gates` policy in `.claude/dev-kit.json` can force `required`/`off`.)
## Branch & commit
1. Branch from the repo's default integration branch. Naming: `<type>/<TICKET-KEY>-<short-slug>` (e.g. `feat/PROJ-1234-payment-status-filter`). Follow the repo's convention if one exists.
2. Stage only files related to the story. List anything intentionally left out.
3. Commit message: `<type>: <TICKET-KEY> <imperative summary>` plus a short body of key changes. Follow the repo's convention if one exists.
## Pull request
Open the PR on the configured host (`prHost` in `.claude/dev-kit.json`; default `github`). Branch/commit/push are the same everywhere (plain git); only the "open the PR" call differs:
- **github** — `gh pr create` (`gh` authenticated).
- **bitbucket** — push the branch, then create the PR via the REST API: `POST https://api.bitbucket.org/2.0/repositories/{workspace}/{repo_slug}/pullrequests` with `{title, source:{branch:{name}}, destination:{branch:{name}}}`, authenticated with a Bitbucket app password / access token from the environment (e.g. `BITBUCKET_TOKEN`). The `acli` CLI works too if the team uses it. Derive `{workspace}/{repo_slug}` from the `origin` remote.
- **gitlab** — `glab mr create` (`glab` authenticated).
- **azure** — `az repos pr create --source-branch <branch> --target-branch <base> --title <title> --description <body>` (Azure CLI with the `azure-devops` extension, `az login` authenticated; run `az extension add --name azure-devops` once if missing). The org/project/repo come from the `origin` remote or `az devops configure --defaults`.
- **other/none** — print the branch and the ready-to-paste PR title/body and let the user open it.
The body must include (adapt field names to the host — GitHub/GitLab render Markdown; Bitbucket PR descriptions accept Markdown too):
```

## <TICKET-KEY>: <story title>
### Summary
<the product-facing summary: what was delivered in user terms and the
decisions taken, plain language — same content as the tracker comment>
### What changed
- ...
### How it was verified
- Unit tests: <command + result>
- Coverage on touched files: <summary — meets the project's bar>
- E2E: <suites run + result>
- Security pass: <verdict>
- Lint: clean
### Notes for reviewers
- <risks, follow-ups, technical decisions>
### Delivery readiness
<Include only the lines that apply — skip this whole section for trivial/internal changes; don't pad.>
- Rollback: safe to revert this PR on its own? Flag anything that isn't.
- Migrations: reversible and safe on a live DB (no long locks; backfill plan)?
- Config/secrets: new keys have safe defaults; nothing required-but-undocumented.
- Docs/contract: user-facing or API changes reflected in the docs.
- Breaking change / behind a feature flag: called out explicitly.
Issue: <link to the tracker item>
---
🤖 Generated with [Claude Code](https://claude.com/claude-code) via the
fullstack-dev-kit plugin. Plan approved by a human before implementation;
human review still required before merge.
```
Use the repo's PR template instead if one exists (`.github/PULL_REQUEST_TEMPLATE.md`), adding the badge, summary, verification evidence, and AI footer into it.
**AI traceability metadata**, best effort after creation:
- Add an `ai-generated` label/tag to the PR when the host supports it — GitHub: `gh pr edit <url> --add-label ai-generated` (create it once with `gh label create ai-generated --color 8A2BE2` if missing), then **verify it stuck** with `gh pr view <url> --json labels` — `gh pr edit` can error without applying anything on repos whose org ever used classic Projects; on a miss, apply via REST: `gh api repos/<owner>/<repo>/issues/<pr-number>/labels -f "labels[]=ai-generated"`. Bitbucket/GitLab: skip or use the host's equivalent. If not possible, skip silently — the badge and footer already carry the signal.
## After creation
Report the PR URL, the verification evidence, and any follow-up risks explicitly.
dev-kit-setup9.17 KB
View saved version →
---
name: dev-kit-setup
description: First-use bootstrap for the dev kit. Detects the team's issue tracker, discovers what it can via MCP/CLI, asks only what cannot be discovered, and persists the result to .claude/dev-kit.json in the consuming repo. Use when that file is missing, when the user asks to set up or reconfigure the kit, or when issue-fetch cannot resolve its configuration.
---
# Dev Kit Setup
Make the kit self-sufficient: detect the tracker, discover everything possible automatically, ask the user only for genuine choices, and persist the result so **nobody on the team has to configure anything again**.
## When to run
- `.claude/dev-kit.json` does not exist (or lacks a `tracker` block) and a kit skill (e.g. `issue-fetch`) needs it.
- The user explicitly asks to set up or reconfigure the kit.
- A stored value turns out to be invalid (e.g. a field ID no longer exists) — re-discover just that value.
## 1. Determine the tracker
Pick `tracker.type` with the least friction:
1. If the triggering reference makes it obvious, use it (`PROJ-1234`/`ENG-42` → Jira/Linear key style; `#123` → GitHub/Azure).
2. Check which backends are actually available: is an Atlassian or Linear MCP authenticated? Is `gh` logged in for this repo? Is Azure DevOps configured?
3. If still ambiguous, **ask the user once** which tracker the team uses: Jira, Linear, GitHub Issues, or Azure DevOps.
Then run the matching discovery below. For any MCP/CLI that is not authenticated, **offer to set it up for them** (users are encouraged to just ask "connect my Jira" — do the work, don't only hand back a command):
- **Claude Code:** the tracker/design MCPs are plugin-declared (`atlassian`, `linear`, `figma`) — authorize with `claude mcp login <server>` (or tell them to run `/mcp` inside the session; the OAuth browser step is theirs to complete).
- **Codex:** install the curated connector and have them sign in from the app — `codex plugin add atlassian-rovo@openai-curated` (Jira/Confluence) · `linear@openai-curated` · `figma@openai-curated`.
- **GitHub / Azure:** `gh auth login` / `az login` (no MCP).
Run the command for them when you can; the OAuth/browser sign-in is always the user's step. Then stop — never continue with invented values until the backend is actually reachable.
## 2. Discover per tracker
### Jira
- **Site**: list accessible sites via the Atlassian MCP — one → use it; several → ask which.
- **Project key**: derive from the triggering ticket prefix and verify it exists; otherwise list projects and ask.
- **Custom fields (auto-detect, no questions)**: resolve field IDs by matching names case-insensitively — Acceptance Criteria ("Acceptance Criteria"/"AC"), Sprint ("Sprint"), Story Points ("Story Points"/"Story point estimate"). If a name matches nothing, inspect a recent issue's custom fields; if still ambiguous, ask once showing the candidates.
### Linear
- **Team**: list teams via the Linear MCP — one → use it; several → ask which. Store its `teamKey`.
- No custom-field discovery needed; acceptance criteria come from the issue body.
### GitHub Issues
- **Repo**: default to the current repo's `origin` (`gh repo view --json nameWithOwner`); confirm if the kit will track issues in a different repo.
- Nothing else to configure.
### Azure DevOps
- **Org and project**: read from the configured Azure DevOps connection or ask once. Store `org` and `project`.
## 3. Detect the stack(s)
Identify the tech stack from the project's files so the kit can load the right baseline commands. Match against the profiles in `instructions/stacks/` (each profile lists its detection signals), e.g.:
| Signal | Stack id |
|---|---|
| `package.json` | `node` |
| `angular.json` | `angular` |
| `react` / `react-dom` in `package.json` | `react` |
| `vue` in `package.json` | `vue` |
| `pyproject.toml` / `requirements*.txt` | `python` |
| `*.csproj` / `*.sln` | `dotnet` |
| `pom.xml` / `build.gradle` | `java` |
| `go.mod` | `go` |
| `Gemfile` | `ruby` |
| `composer.json` | `php` |
| `Cargo.toml` | `rust` |
A JS/TS frontend matches **both** `node` and its framework — prefer the **more specific** one (`angular`/`react`/`vue`); those profiles reference `node` for the shared toolchain. A monorepo may match several — record all of them (e.g. `["dotnet", "angular"]`). If nothing matches a shipped profile, record the closest label anyway and tell the user there is no stack profile yet (the kit still works from the repo's `CLAUDE.md` and generic rules — and contributing `instructions/stacks/<id>.md` is one small PR).
## 4. Persist
Write `.claude/dev-kit.json` at the consuming repo root. Only the active tracker's block is required:
```json
{
"tracker": {
"type": "jira",
"site": "https://<org>.atlassian.net",
"cloudId": "<discovered-cloud-id>",
"projectKey": "PROJ",
"fields": {
"acceptanceCriteria": "customfield_XXXXX",
"sprint": "customfield_XXXXX",
"storyPoints": "customfield_XXXXX"
},
"reviewState": null
},
"stacks": ["node"],
"prHost": "github",
"gates": {
"coverage": { "mode": "auto", "min": 95 },
"e2e": { "mode": "auto" }
},
"test": {
"coverageCommands": []
}
}
```
Shape of `tracker` per type: **jira** → `site`, `cloudId`, `projectKey`, `fields`; **linear** → `teamKey`, optional `workspace`; **github** → `repo` (`owner/name`, optional if same as origin); **azure** → `org`, `project`. `stacks` is the detected stack id(s) — skills load `instructions/stacks/<id>.md` as their baseline. `prHost` is where PRs live — **detect it from the `origin` remote** (`github.com` → `github`, `bitbucket.org` → `bitbucket`, `gitlab.com` → `gitlab`; otherwise ask); `create-pr`/`pr-review`/`fix-pr` use it. For `bitbucket`/`gitlab`, remind the user that PR actions need a token/CLI authenticated (e.g. `BITBUCKET_TOKEN`, or `glab auth login`). `reviewState` is filled the first time `issue-update` transitions an item, then reused. `test.coverageCommands` is optional — `coverage-check` fills it in when it detects the repo's coverage command.
**Quality gates — mostly auto-detected, one preference optionally asked.** The full optional shape:
```json
"gates": {
"coverage": { "mode": "auto", "min": 95 },
"e2e": { "mode": "auto" }
}
```
- `mode`: **`auto`** (default — detect each run whether the project has the setup and enforce only then) · `required` (hard-fail even if absent) · `off` (skip). **Never detect-and-store `mode`** — a project's test setup changes over time, so it's resolved at runtime (see `instructions/testing-standards.md`).
- `coverage.min`: the coverage bar for touched files (**default 95**). This is a *stable team preference*, not a moving property — so **ask it once here** and persist it: **only if you detected a test/coverage setup**, ask "Minimum coverage to hold touched files to? [95]" and store the answer under `gates.coverage.min`. If the repo has no tests, don't ask (nothing to gate). Do **not** ask `mode` — leave it auto. Teams can hand-edit `mode` to `required`/`off` later.
**Optional top-level `a11y` key** (accessibility review for frontend diffs — honored by `pr-review`):
```json
{ "a11y": "auto" }
```
`auto` (default, and the value when the key is **absent** — run the a11y basics only on user-facing frontend diffs) · `required` (make it a blocking gate) · `off` (never run). **Do not ask this in setup and do not write it by default** — leave it absent so the default `auto` applies. Only write it when the user explicitly asks (e.g. *"make accessibility a required gate"* / *"turn off the a11y checks"*): set the key to the requested value, preserving the rest of the file.
**If the repo has no `CLAUDE.md`:** say so, proceed using the stack profile(s) + detected commands as the baseline, and suggest the user run `/init` (or let the kit propose a minimal `CLAUDE.md`) so future runs are grounded in the repo's own conventions. Never silently assume conventions the repo hasn't stated.
- This file contains **no secrets** (auth lives in each developer's MCP OAuth grant or CLI login) — it is safe and intended to be committed, so one setup serves the whole team.
- Tell the user the file was created and suggest committing it.
## 5. Design tool (optional)
Figma needs no configuration — file keys come from URLs, auth is the MCP OAuth. Verify authentication lazily, only when a Figma URL first appears.
## 6. Telemetry (optional, opt-in, off by default)
Do not enable or configure telemetry here, and never turn it on silently. If the user asks about it, point them to `TELEMETRY.md` and the plugin's `telemetry_enabled` option (set per developer). Absent an explicit opt-in, it stays off.
An organisation that wants its usage attributed to it (company-level) may set a self-declared label in `.claude/dev-kit.json`:
```json
{ "telemetry": { "org": "acme-corp" } }
```
This is optional, organisation-level (not per-person), and only ever set deliberately by the team — never derive it from a git email, commit author, or remote URL. Only add it if the user explicitly asks for company attribution.
## After setup
Continue seamlessly with whatever task triggered the bootstrap (e.g. proceed with the `issue-fetch` that was interrupted). Setup must feel like a one-time speed bump, not a separate ceremony.
e2e-generate2.92 KB
View saved version →
---
name: e2e-generate
description: Create or update end-to-end tests for a user-facing flow that changed, using whatever e2e framework the repo already uses. Use after implementing a user story that alters UI behavior, routing, forms, or API-driven views.
---
# E2E Test Generation
When a user story changes user-facing behavior **and the project already does e2e**, an existing e2e test must be updated or a new one created before the story is done. This skill is framework-agnostic — it uses whatever e2e stack the consuming repo already has, and **never introduces a new one unprompted**.
**Adaptive gate** (see `instructions/testing-standards.md`): if the repo has **no e2e setup**, this is a *recommendation*, not a blocker — report "no e2e setup; recommend adding one" (and offer to, if the user wants), and do not scaffold a framework. Only treat missing e2e as a hard failure when `gates.e2e` is `required` in `.claude/dev-kit.json`.
## Process
1. **Identify the affected flow(s)** from the story's acceptance criteria and the diff: which pages, routes, forms, and roles are involved.
2. **Discover the project's e2e framework and conventions first** — before writing anything. If `.claude/dev-kit.json` names a stack, `instructions/stacks/<id>.md` lists the frameworks common for it as a starting hint. Then look for the config and test tree of whatever the repo actually uses (e.g. `playwright.config.*` + `e2e/`, `cypress.config.*` + `cypress/`, a Selenium/WebDriver test project, `*.feature` files for Cucumber, etc.) and reuse its existing page objects, fixtures, helpers, and app/API seeding or stubbing. Follow them exactly; do not introduce a new pattern or framework when one exists. If the repo has no e2e setup at all, say so and propose one that fits the stack instead of scaffolding silently.
3. **Prefer updating an existing test** for the flow over creating a parallel one.
4. **Write the scenarios.** Every generated suite must cover realistic edge cases, not just the happy path:
- Empty states
- API failures and timeouts
- Validation errors
- Role/permission differences where applicable
- Navigation and back-flow behavior where applicable
5. **Run the tests** with the project's e2e command (check the consuming repo's CLAUDE.md; e.g. `npx playwright test <file>`, `npx cypress run`, or the repo's WebDriver test command). Related e2e tests must pass before PR creation.
## Quality rules
- Page Object Model: new pages get a page object; interactions go through it, not raw selectors in the test body.
- Stable selectors: prefer test ids / accessible roles over CSS chains.
- No sleeps: use the framework's waiting primitives.
- Keep test names descriptive of the user behavior, not the implementation.
- Preserve existing test names when updating a file.
## Output
Report which flows are covered, which test files were added/updated, the run result, and any flow you could not cover (with the reason) — never silently skip a flow.
figma-fetch1.74 KB
View saved version →
---
name: figma-fetch
description: Extract frame/component structure and all visible text from a Figma design URL. Use whenever a prompt or a fetched issue contains a figma.com/design or figma.com/file link.
---
# Figma Fetch
Pull design context from Figma so the implementation matches the intended UI.
## Trigger
Any URL matching `figma.com/(design|file)/([A-Za-z0-9]+)`.
## How to parse the URL
Given `https://www.figma.com/design/ABcd1234EFgh/My-File?node-id=123-456`:
- **File key**: segment after `/design/` or `/file/` → `ABcd1234EFgh`
- **Node ID**: the `node-id` query param with `-` replaced by `:` → `123:456`
## How to fetch
Use the **Figma MCP** tools to read the file/node. Walk the node tree; collect `TEXT` node content and the name/type of every named node, preserving nesting depth.
If the MCP server is not authenticated, tell the user to authorize the Figma connector (via `/mcp` or their claude.ai connector settings) and stop. Do not invent design content.
## Output format
1. **Node hierarchy** with all text content, indented by depth:
```
===== Figma Node: <name> (<type>) =====
[FRAME] Screen name
[TEXT] Visible label
[INSTANCE] ComponentName
[TEXT] Button copy
```
2. **Plain-English UI summary**: what screens/components are shown, what labels exist, and the apparent layout intent.
3. **Designer notes**: call out any text layers that read as annotations rather than UI copy.
## After fetching
Incorporate the Figma context into the implementation plan before presenting it to the user. When implementing:
- Reuse existing project components first, then the project's UI library, and only then create new components.
- Never use inline styles; follow the project's styling conventions (see the consuming repo's CLAUDE.md).
fix-pr5.3 KB
View saved version →
---
name: fix-pr
description: Resolve the findings on an existing pull request - review comments, CI failures, and self-review findings - driving each to a decision (fix / defer to a tracked issue / discard), re-verifying the gates, replying to each reviewer, and watching for late feedback. The counterpart to pr-review that closes the loop.
---
# Fix PR
Drive a PR's feedback to done: run a review, triage **every** item to a decision, fix what deserves fixing, file what deserves doing later, discard what deserves nothing, answer every reviewer, and re-check after pushing in case late feedback (bots, CI) arrives. The bar for correctness is high; the bar for new machinery is low — fix the defect, don't redesign around it.
## 1. Establish the PR intent (the scope ruler)
Write one or two sentences: **what this PR is for, and what it deliberately does not change** — derived from the title, body, linked issue, and the diff. Every scope call below is measured against it. If the intent is genuinely ambiguous, ask the author before triaging.
## 2. Gather the findings
Collect from every surface, deduplicated. Commands below are for `github` (`prHost` in `.claude/dev-kit.json`); for **bitbucket** use the REST API (`/pullrequests/{id}` comments, `/statuses`), for **gitlab** `glab mr view/checks`.
1. **CI failures**: `gh pr checks <pr>` — read the failing job logs, not just the status.
2. **Review feedback**: unresolved inline threads, review summary bodies, and PR conversation comments — bots included (`gh pr view <pr> --comments`, `gh api` for threads). Keep outdated threads: the code moved, the concern may not have.
3. **Self-review findings** handed over by the caller (the `pr-review` pass).
## 3. Build the ledger
One row per **distinct claim**, merging duplicates across sources (if the review pass and a human flagged the same defect, that's one row citing both — and the human's thread still gets a reply):
| id | source | file:line | claim | category | verdict |
Assign exactly one verdict per row — nothing stays undecided:
- **`FIX_NOW`** — fix it in this PR.
- **`DEFER_TO_ISSUE`** — real value, wrong moment → a tracked issue.
- **`DISCARD`** — not worth anyone's time; no fix, no issue.
**Never `DISCARD`** (from `instructions/secure-coding.md` + `instructions/testing-standards.md`): security/data-exposure, serious performance regressions, duplication this PR introduces, and missing test coverage for behavior it changes (when the project has tests). Only defer one of these when the fix is genuinely a separate project — and say so, treating the PR as blocked on the author's call, not quietly filing an issue.
Show the classified ledger before touching code — the cheapest moment to correct a bad call.
## 4. Ask about scope conflicts
Batch every fix that would push past the PR's intent into **one** round of questions (AskUserQuestion) with your recommendation. Don't widen scope silently.
## 5. Fix
Smallest correct change per `FIX_NOW`, following the repo's conventions and the kit instructions. Add/update the tests that prove each fix (a test that fails without it); keep touched files at the project's coverage bar (adaptive — see `testing-standards.md`). One commit per coherent group; push to the PR branch. No opportunistic refactors, no force-push/amend/rebase of remote commits.
## 6. Answer every reviewer (consent-first)
Reply to each human/bot comment with the decision taken, then resolve the thread. **Show the exact replies and get confirmation before posting to GitHub** (in `--auto-approve` pipeline runs, post them and flag prominently in the report). Never resolve someone else's thread without a reply. A finding you believe is wrong gets a reasoned reply, not silence.
## 7. File deferred work
For each `DEFER_TO_ISSUE`, confirm the batch with the user, then create a tracked issue **via the configured tracker** (the `issue-*` adapters / `.claude/dev-kit.json`) — or the PR host's issues — and link it from the reply.
## 8. Re-verify the gates
Same as `create-pr`, adaptive to the project: unit tests for touched files pass; `coverage-check` holds the project's bar with no regression; related e2e pass if user-facing and the project does e2e; lint clean; no suppressions to dodge a gate.
## 9. Watch for late feedback, then loop
Bots and CI often post minutes after a push. Right after pushing, run the bundled watcher in the background. It ships with the kit at `scripts/watch-pr-feedback.sh`; resolve its path from the kit install — `$CLAUDE_PLUGIN_ROOT` on Claude Code, the kit checkout path on Codex:
```bash
BASELINE=<ledger github ids> "$CLAUDE_PLUGIN_ROOT"/scripts/watch-pr-feedback.sh <pr> # Claude Code
# Codex: run the same script from the kit's install path (no $CLAUDE_PLUGIN_ROOT there)
```
Read its exit code: **10** = new feedback (printed) → back to step 3 with the new items; **20** = a bot signalled all-clear (👍 on the PR / approving review); **0** = ten quiet minutes; **30** = inconclusive → re-run it. Only close out on **0** or **20** from a window covering the last push. (GitHub only; for other hosts, do a single post-push re-check instead.)
## 10. Report
Account for **every** ledger row (fixed / deferred+issue link / discarded+why / answered), the verification evidence, how the feedback window closed, and the PR URL. Never report the PR clean while blocking threads remain open.
follow-ups3.71 KB
View saved version →
---
name: follow-ups
description: Turn the loose ends a finished story leaves — out-of-scope notes, deferred review findings, deliberate TODOs — into tracked follow-up work items in the team's tracker, linked to the source story, after approval. Supports Jira, Linear, GitHub Issues, and Azure DevOps via adapters. Use at the end of a story, or when the user asks to track follow-ups.
---
# Follow-ups
Close the loop: when a story finishes, the loose ends it surfaced should be **tracked**, not just described in the PR body. This skill turns them into real work items in the configured tracker, **linked back to the source story** — created only after approval. It's the tracking counterpart to the "Out of scope / follow-ups" section `create-pr` already writes.
## Preconditions
- `.claude/dev-kit.json` exists with a `tracker` block (otherwise run `dev-kit-setup` first).
- The adapter's backend is authenticated (MCP connector authorized, or `gh`/`az` logged in) — otherwise tell the user how to authenticate and stop.
- The **source story key** (the item just delivered) is known, for linking. If unknown, ask once.
## 1. Gather the loose ends — only real ones
Collect follow-ups from the story just finished, from where they were already surfaced:
- the **"Out of scope / follow-ups"** list in the `create-pr` PR body,
- **deferred review findings** from `fix-pr` / `pr-review` (the "defer to a tracked issue" bucket),
- deliberate **TODOs / known gaps** the implementation left.
**Never invent follow-ups.** If there are none, say so and stop — don't pad a backlog to look thorough.
## 2. Propose — WAIT FOR APPROVAL
For each loose end, propose a work item:
- **Type**: default **Task**; use a **User Story** when it's a user-facing increment (ask if unsure).
- **Title** + a one-line description + **why** (the context from the story that produced it).
- **Link** to the source story (and its epic/parent when there is one) for traceability.
- A sizing hint or label when the team uses them (discover, don't assume).
Present the full list and **wait for explicit approval**; the user may edit or drop items. **Create nothing until approved.**
## 3. Create — via the tracker's write adapter
Create each approved item and link it to the source story. Verify writes by read-back where the CLI can silently no-op.
### Jira (`type: "jira"`) — Atlassian MCP
`createJiraIssue` for each item (project, type, summary, description, labels); link to the source with `createIssueLink` ("Relates to", or a sub-task under the story when appropriate).
### Linear (`type: "linear"`) — Linear MCP
Create the issue under the team; relate it to the source (relation or sub-issue); set labels/estimate.
### GitHub Issues (`type: "github"`) — `gh`
`gh issue create --repo <owner/name> --title <t> --body-file - --label <type>`, referencing the source in the body (`Follow-up of #<n>` / a task-list link). **Verify by read-back** (`gh issue view --json labels`) and apply labels via REST on a miss (classic-Projects orgs can silently no-op).
### Azure DevOps (`type: "azure"`) — `az boards` / MCP
`az boards work-item create --type "Task|User Story" ...`; link to the source with `az boards work-item relation add` (Related / Parent).
## 4. Report
List each created item with its key/URL, and record them where the story lives — add a **"Follow-ups tracked: `<keys>`"** line to the PR and/or the tracker comment so the trail is visible. On partial failure, report exactly what was created and what wasn't.
## Guardrails
- **Never create anything before approval.**
- **Only genuine loose ends** from the work — no fabricated backlog.
- **Always link** to the source story for traceability.
- Watch for secrets/PII in the source material; don't copy them into tickets.
issue-fetch4.27 KB
View saved version →
---
name: issue-fetch
description: Fetch a work item (summary, status, description, acceptance criteria, comments) from the team's issue tracker and display a clean summary. Supports Jira, Linear, GitHub Issues, and Azure DevOps via adapters. Use whenever a prompt contains an issue reference (e.g. PROJ-1234, ENG-42, #123) or the user asks to work on a user story.
---
# Issue Fetch
Fetch full context for a work item before any planning or implementation begins. The tracker is configured once (see below); this skill speaks to whichever one the team uses.
## Trigger
Any prompt containing an issue reference, or an explicit request to fetch/work on a story. Reference shapes differ by tracker:
| Tracker | Key shape | Example |
|---|---|---|
| Jira | `[A-Z][A-Z0-9]+-\d+` | `PROJ-1234` |
| Linear | `[A-Z]+-\d+` | `ENG-42` |
| GitHub Issues | `#\d+` or `owner/repo#\d+` | `#123` |
| Azure DevOps | `#?\d+` (work item id) | `#4567` |
## Project configuration
Read `.claude/dev-kit.json` at the consuming repo root. The `tracker` block names the active adapter and its settings:
```json
{ "tracker": { "type": "jira" | "linear" | "github" | "azure", ... } }
```
**If the file does not exist (or has no `tracker` block), run the `dev-kit-setup` skill first** — it detects the tracker, gathers what it needs, persists the file, and returns here. Do not ask the user for values that setup can discover.
If the requested key's project/prefix does not match the configured one, confirm with the user before fetching (it may be a cross-project item — allowed, just not silently).
## Adapters — how to fetch
Use the adapter matching `tracker.type`. In every case request at minimum: **summary/title, type, status, priority, assignee, reporter, labels, description, acceptance criteria, and all comments** (plus story points and sprint/cycle when the tracker has them).
### Jira (`type: "jira"`)
Config: `site`, `cloudId`, `projectKey`, `fields` (custom field IDs for acceptance criteria / sprint / story points).
Use the **Atlassian MCP** tools against the configured site to get the issue and its comments, reading acceptance criteria via the configured field IDs.
- If a configured field ID turns out to be invalid, re-run `dev-kit-setup` discovery for that field and update the config.
### Linear (`type: "linear"`)
Config: `teamKey` (and optionally `workspace`).
Use the **Linear MCP** tools to fetch the issue by identifier, its description, labels, state, assignee, and comments. Acceptance criteria usually live in the description body or a checklist — extract them from there.
### GitHub Issues (`type: "github"`)
Config: `repo` (`owner/name`); defaults to the current repo's `origin` when omitted.
Fetch with the GitHub CLI (no MCP needed):
```bash
gh issue view <number> --repo <owner/name> --json number,title,state,labels,assignees,body,comments
```
Acceptance criteria are parsed from the issue body (task lists / a "Acceptance criteria" section).
### Azure DevOps (`type: "azure"`)
Config: `org`, `project`.
Fetch via the Azure DevOps MCP if configured, otherwise the REST API / `az boards work-item show --id <id>`. Map fields: `System.Title`, `System.State`, `System.Description`, `Microsoft.VSTS.Common.AcceptanceCriteria`, and the work-item comments.
## Authentication
If the adapter's backend is not authenticated (MCP connector not authorized, `gh`/`az` not logged in), tell the user exactly how to authenticate — MCP connectors via `/mcp` or claude.ai connector settings; CLIs via `gh auth login` / `az login` — and stop. **Never invent ticket content.**
## Output format
Display a concise summary before doing anything else:
```
===== KEY =====
Summary : ...
Type : ...
Status : ...
Priority : ...
Assignee : ...
Points : ... (omit if the tracker has no such field)
Sprint : ... (omit if the tracker has no such field)
Labels : ...
--- Description ---
...
--- Acceptance Criteria ---
...
--- Comments (N) ---
[date] author: ...
```
## After fetching
1. If the description or comments contain a **Figma URL** (`figma.com/(design|file)/...`), invoke the `figma-fetch` skill next.
2. Present an **implementation plan** and **wait for explicit user approval** before writing any code (see the issue-to-PR workflow). Never skip this gate unless the caller explicitly says the plan is pre-approved.
issue-update4.61 KB
View saved version →
---
name: issue-update
description: Update the work item after delivery - comment the PR link and a product-facing summary, and transition it to the team's review status. Supports Jira, Linear, GitHub Issues, and Azure DevOps via adapters. Use right after a PR is created for a story, or when the user asks to update/move a ticket.
---
# Issue Update
Close the loop: after the code ships, the tracker must reflect it without anyone updating it by hand. This skill speaks to whichever tracker is configured in `.claude/dev-kit.json` (`tracker.type`).
## Preconditions
- `.claude/dev-kit.json` exists with a `tracker` block (otherwise run `dev-kit-setup` first).
- The adapter's backend is authenticated (MCP connector authorized, or `gh`/`az` logged in) — otherwise tell the user how to authenticate and stop.
- A PR URL and a product-facing summary of the delivered work are available from the delivery flow.
## 1. Comment the delivery summary
**Audience: product owners and other non-technical readers.** The comment explains what was delivered and why, in user terms — no test counts, coverage percentages, lint, or tooling jargon. All technical evidence lives in the PR, which is linked.
Post a comment (via the adapter below) containing:
```
Pull request: <PR URL>
What was delivered:
- <the new behavior, described as a user would experience it — one bullet per acceptance criterion addressed>
Decisions taken:
- <each meaningful decision or interpretation made during implementation, in plain language, with the reason>
Out of scope / follow-ups:
- <anything deliberately left out or worth a future ticket, or "Nothing pending.">
```
Keep it factual and grounded in what was actually built — never a template filled with assumptions. If an acceptance criterion was NOT met, say so here plainly.
## 2. Ensure the item has a named owner
Every item carries a named owner: if it has no assignee, assign it to the current user. Agents act on a person's behalf — the item must always show whose behalf that is. (Skip only for trackers/flows where assignment is not applicable, and say so.)
## 3. Transition to review
Move the item to the team's review status. **Never hardcode transition/state IDs** — discover the available ones and pick the target named like "In Review" / "Code Review" / "Review"; if none matches, ask the user once and persist the choice under `tracker.reviewState` in `.claude/dev-kit.json`.
## Adapters
### Jira (`type: "jira"`)
- Comment and assign via the **Atlassian MCP**.
- Transition: fetch available transitions via the MCP (IDs vary per tenant), pick/persist the review transition under `tracker.reviewState`.
### Linear (`type: "linear"`)
- Comment and assign via the **Linear MCP**.
- Transition: set the issue's workflow state to the team's review state (discover states via the MCP; persist the chosen state id).
### GitHub Issues (`type: "github"`)
- Comment: `gh issue comment <number> --repo <owner/name> --body-file -`.
- Owner: `gh issue edit <number> --add-assignee @me` if unassigned.
- "Review status": GitHub issues have no workflow states — apply the label the team uses (e.g. `in-review`) via `gh issue edit --add-label`, and/or move it in the project board if one is configured. Persist the label under `tracker.reviewState`.
- **Verify both writes by read-back — never trust the exit code.** `gh issue edit` can fail while applying nothing (its project-fields prefetch trips on repos whose org ever used classic Projects), which is the worst shape for the step the story is not done without. After editing, run `gh issue view <number> --json assignees,labels` and confirm the assignee and label actually landed; on a miss, apply via REST instead — `gh api repos/<owner>/<repo>/issues/<number>/assignees -f "assignees[]=<login>"` / `gh api repos/<owner>/<repo>/issues/<number>/labels -f "labels[]=<label>"` — and report which path worked.
### Azure DevOps (`type: "azure"`)
- Comment and assign via the Azure DevOps MCP or REST / `az boards`.
- Transition: set `System.State` to the team's review state (discover valid states for the work-item type; persist under `tracker.reviewState`).
## 4. Report
Tell the user, explicitly and always covering all three: comment posted (link), **owner ensured (who — or why it could not be assigned)**, and transition applied (from → to). Anything that could not be done gets a reason — no step is ever skipped silently.
## Failure handling
- No matching review state (workflow differs): list the available ones and ask once; persist the answer.
- No permission to transition: report it explicitly — do not silently skip.
- The comment must be posted even if the transition fails.
plan-backlog6.42 KB
View saved version →
---
name: plan-backlog
description: Turn an idea or description (in any format) into a well-formed backlog — epics, user stories with acceptance criteria, sub-tasks — and create it in the team's tracker after approval. Supports Jira, Linear, GitHub Issues, and Azure DevOps via adapters. Use when a product owner wants to draft or create tickets from an idea, brief, or document.
---
# Plan Backlog
Turn a product idea into a structured, well-formed backlog in the team's tracker — the **upstream** half of the issue-to-PR workflow, for the product-owner persona. It closes the loop **idea → backlog → ticket → PR** (created stories feed straight into `work-story`).
This is the *write* counterpart to `issue-fetch` (which reads). **Nothing is created until you approve the draft.**
## Trigger
A request to turn an idea / brief / description / document into tickets, epics, or a backlog — e.g. *"draft stories for this feature"*, *"create Jira tickets from this doc"*, *"break this initiative into a backlog"*.
## Project configuration
Read `.claude/dev-kit.json` at the consuming repo root. The `tracker` block names the active adapter and its settings:
```json
{ "tracker": { "type": "jira" | "linear" | "github" | "azure", ... } }
```
**If the file does not exist (or has no `tracker` block), run `dev-kit-setup` first** — it detects the tracker and persists the config, then returns here. Don't ask for values setup can discover.
## 1. Intake — read the idea in whatever form it arrives
- **Pasted text / chat description** → use directly.
- **PDF** → read it (page range as needed).
- **Word (`.docx`)** → not natively readable; convert first (`textutil -convert txt file.docx -output -` on macOS, or `pandoc file.docx -t markdown`), then read. If neither tool is available, ask the user to paste the text or export a PDF.
- **Artifact / Confluence page / URL** → fetch it.
- **Figma link** (`figma.com/(design|file)/…`) → run `figma-fetch` for design context.
Work only from what the source says plus what the user confirms — **never invent scope or acceptance criteria.**
## 2. Discovery-first — learn the team's hierarchy and conventions
Don't impose a structure; **mirror the team's.** Using the adapter for `tracker.type`, discover:
- the **issue types available and their hierarchy** (Epic / Story / Task / Feature / Sub-task, …),
- the **fields that matter** (acceptance criteria, story points/estimate, epic/parent link, labels, components),
- a **sample of recent issues** to calibrate granularity and writing style.
Ask only what can't be discovered.
## 3. Draft — a neutral model mapped to native types
Work with a neutral backlog model, then map it onto the tracker's native types (§5):
- **Initiative / Epic** → the outcome / theme.
- **User Story** → *"As a `<role>`, I want `<capability>`, so that `<value>`."* with **acceptance criteria** written as Given / When / Then, and **INVEST**-sized.
- **Sub-tasks** → concrete steps, when they add clarity.
- **Dependencies**, sizing hints, labels/components, and explicit **out-of-scope** notes.
Recommend a shape based on discovery and **confirm it** with the user (e.g. *"1 Epic + 5 stories, or split by feature/milestone?"*) — don't force one.
## 4. Approval gate (mandatory — create nothing yet)
Present the **full draft**: the hierarchy plus each item's title, description, acceptance criteria, labels, and links. **Wait for explicit approval**; the user may edit anything. Only after approval proceed to create. (Same doctrine as `work-story`'s plan gate — never create tickets without a human OK.)
## 5. Create — via the tracker's write adapter
Create **parents before children**, link children to parents, and set labels/components/points where discovered. Report each created item with its key/URL.
### Jira (`type: "jira"`) — Atlassian MCP
Config: `site`, `cloudId`, `projectKey`, `fields`.
- Discover types/fields with `getJiraProjectIssueTypesMetadata` / `getJiraIssueTypeMetaWithFields`.
- Create with `createJiraIssue` (project, issue type, summary, description, the acceptance-criteria field, labels, story points). Link stories to the epic via the epic-link field or `createIssueLink`; model dependencies with `createIssueLink` (Blocks / Relates).
### Linear (`type: "linear"`) — Linear MCP
Config: `teamKey` (and optionally `workspace`).
- Create issues under the team; use a **Project** (or a parent issue) as the epic, and **sub-issues** for sub-tasks; set labels/estimate/state. Put acceptance criteria in the description (a checklist).
### GitHub Issues (`type: "github"`) — `gh`
Config: `repo` (`owner/name`; defaults to `origin`).
- `gh issue create --repo <owner/name> --title <t> --body-file - --label <type>` (use `--milestone` as the epic/initiative). Acceptance criteria as a task list in the body; sub-tasks as sub-issues / task lists.
- **Verify writes by read-back — never trust the exit code.** `gh issue edit`/label can fail while applying nothing on repos whose org ever used classic Projects. After creating/labelling, run `gh issue view <number> --json labels,milestone` and, on a miss, apply via REST (`gh api repos/<owner>/<repo>/issues/<number>/labels -f "labels[]=<label>"`).
### Azure DevOps (`type: "azure"`) — Azure DevOps MCP / `az boards`
Config: `org`, `project`.
- `az boards work-item create --type "Epic|Feature|User Story|Task" --title <t> --fields ...`; link parent/child with `az boards work-item relation add`. Acceptance criteria → `Microsoft.VSTS.Common.AcceptanceCriteria`.
## Authentication
If the adapter's backend is not authenticated (MCP connector not authorized, `gh`/`az` not logged in), tell the user exactly how to authenticate — MCP connectors via `/mcp` or claude.ai connector settings; CLIs via `gh auth login` / `az login` — and stop. **Never create partial or placeholder items.**
## 6. Handoff
List the created items with their keys/URLs and hand off: each story is ready for **`work-story <KEY>` → PR**. That completes the loop **idea → backlog → ticket → PR**.
## Guardrails
- **Never create anything before explicit approval.**
- **Discovery-first:** mirror the team's hierarchy and conventions; don't impose one.
- **Don't fabricate** scope or acceptance criteria — ground everything in the source plus user confirmation.
- Watch for **secrets/PII** in the source material; don't copy them into tickets.
- On partial failure, report exactly what was created and what wasn't — never leave a half-built backlog unreported.
pr-review6.29 KB
View saved version →
---
name: pr-review
description: Structured review of a pull request or the current diff - correctness, contract drift, security, missing tests, coverage gate - producing classified findings and a verdict. Use when the user asks to review a PR or diff, or as the self-review step of the story workflow.
---
# PR Review
Produce a high-signal review: findings a reviewer would act on, classified and ordered, ending in a clear verdict. The kit instructions (`instructions/secure-coding.md`, `instructions/testing-standards.md`) define what counts as blocking.
## Scope the diff
- Reviewing an existing PR: fetch the diff and description from the configured host (`prHost` in `.claude/dev-kit.json`). **github:** `gh pr diff <pr>` + `gh pr view <pr>`. **bitbucket:** `GET /2.0/repositories/{ws}/{repo}/pullrequests/{id}/diff` and `/pullrequests/{id}` (REST, token from env). **gitlab:** `glab mr diff <id>` + `glab mr view <id>`.
- Reviewing the working tree (self-review before PR): `git diff` against the base branch, including staged changes.
- Read the linked ticket's acceptance criteria — a diff can be flawless and still not do what the story asked.
- Write the **PR intent** — one line on what this PR is for and what it deliberately leaves alone. It's the ruler for scope: a real defect *inside* the intent blocks; a valid concern *outside* it is a note or a follow-up, not a reason to expand the PR.
## Review dimensions (in priority order)
1. **Acceptance criteria**: does the change actually satisfy each criterion? List any criterion not covered.
2. **Correctness**: behavioral regressions, broken edge cases, wrong logic. Read the code, don't skim the diff.
3. **Contract drift**: routes, payloads, enums, schemas, validation, status codes — every side that depends on the contract updated together.
4. **Security**: apply the checklist in `instructions/secure-coding.md` (auth on new endpoints, secrets, input validation, data exposure). Any automatic-blocker present is a blocking finding.
5. **Tests** (adaptive — judge against the project's own setup, see `instructions/testing-standards.md`): when the project has tests, every behavioral change has one that would fail without it and touched files stay at the project's bar (default ≥ 95%, no regression — run `coverage-check` if evidence is missing); when it does e2e, user-facing changes have e2e coverage with edge cases. A project with **no** test/e2e setup is not a blocking finding — flag it as a recommendation. Test-quality violations from `instructions/testing-standards.md` (assertion-free tests, suppressions, deleted/renamed tests) are findings.
6. **Performance regressions introduced here** (blocking): algorithmic blowups over collections that grow with usage; N+1 queries or per-item network calls on a request path; unbounded result sets / memory / missing pagination; blocking work on a hot path; a new query filtering/joining on an unindexed column. *Not* this: micro-optimizations or "could be faster" with no mechanism.
7. **Duplication introduced by this PR** (blocking): new code reimplementing logic already in the repo, or copy-paste between the files this PR adds — fix by reusing/extracting once. *Not* this: two blocks that merely look alike and are about to diverge; pre-existing duplication is a follow-up at most.
8. **Accessibility** (conditional — evaluate **only** when the diff changes user-facing UI in a frontend stack: changed components/templates/JSX/HTML/CSS in a node/angular/react/vue-style project. Skip entirely for backend or non-UI diffs — no cost when it doesn't apply). Honors `a11y` in `.claude/dev-kit.json`: `auto` (default — run on user-facing frontend diffs) · `required` (blocking gate) · `off` (never run). Check the high-value, low-effort basics on the changed markup only: images have meaningful `alt`, form controls have associated labels, interactive elements have an accessible name, keyboard/focus works (no click-only handlers, visible focus), no obvious color-contrast failures, ARIA present where needed and not misused. If the repo already runs a11y tooling (axe-core, `eslint-plugin-jsx-a11y`, Lighthouse), use its output; **never scaffold one**. Target **WCAG 2.2 level AA**, and cite the specific Success Criterion in each finding (e.g. missing `alt` → *WCAG 1.1.1 (A)*, low contrast → *WCAG 1.4.3 (AA)*) so it's verifiable, not vague. **Recommendation by default; blocking only when `a11y: required`.**
9. **Maintainability**: only issues that materially affect future changes — no style nitpicks a formatter or linter should catch.
## Adversarial check (proportional — do not double every review)
For **high-stakes diffs only** (auth/authorization, money, personal data, migrations, concurrency, anything hard to roll back), before the verdict take one targeted skeptical pass: pick the 1–2 conclusions most likely to be wrong and the 1–2 "looks fine" spots most likely to hide a defect, and actively try to break them (an edge input, a failure/timeout path, a race, a partial write). Routine or low-risk diffs get the normal single pass — this is a focused second look where being wrong is expensive, not a mandatory re-review.
## Output format
```
## Review: <PR/diff identifier>
### Blocking
- [file:line] <finding> — <why it blocks, one line>
### Non-blocking
- [file:line] <suggestion>
### Questions
- <anything ambiguous that needs the author's intent>
### Verdict
APPROVE | REQUEST CHANGES — <one-line rationale>
Acceptance criteria: <met / partially met (which ones missing)>
```
## Rules
- **Report first, publish only with consent.** Findings are delivered in the conversation. Never submit a GitHub review verdict (approve / request changes) and never post comments on the PR without the user's explicit confirmation — show exactly what would be posted and wait. This applies doubly to PRs authored by other people.
- Every finding cites file and line. No finding without a concrete failure scenario or rule reference.
- Do not pad: if the diff is clean, say so and approve — a review's value is its signal ratio.
- Never approve with unresolved blocking findings, and never report a criterion as met without seeing the code that implements it.
- When invoked as the self-review step of the story workflow, hand the blocking findings to the `fix-pr` playbook (the `pr-fixer` subagent on Claude Code) and re-review after the fixes.
work-story4.7 KB
View saved version →
---
name: work-story
description: Work a user story end to end — fetch the ticket, plan (with approval), implement, verify the applicable gates, self-review, open the PR, and update the tracker. Use when given an issue key like PROJ-1234, ENG-42, or #123. This is the orchestration playbook for hosts without a dedicated orchestrator subagent (Codex, and other Agent-Plugins clients); on Claude Code the `/work-story` command + `coding-agent` subagent do this instead.
---
# Work Story (orchestration)
You are the story orchestrator. Input: an issue key from the team's tracker. Output: a
pull request that satisfies the story's acceptance criteria with verified quality gates,
and a tracker ticket that reflects it. **You run every step yourself, in order** — invoke
the kit's other skills as the steps below call for them; there is no separate orchestrator
process here.
If no issue reference is given, ask for one — don't guess. Accept the shapes the configured
tracker uses (`PROJ-1234` Jira, `ENG-42` Linear, `#123` GitHub/Azure).
**Stack-agnostic.** Carry no assumptions about language, framework, or test runner. Read the
repo's `AGENTS.md` / `CLAUDE.md` and `.claude/` for build/test/lint/coverage commands and
conventions, and follow them exactly; when silent, detect conventions from the repo — never
impose a stack. The always-on rules in `instructions/secure-coding.md` and
`instructions/testing-standards.md` bind every step.
## 1. Context
- If `.claude/dev-kit.json` is missing, run **`dev-kit-setup`** first (one-time bootstrap:
tracker, project/team, field IDs).
- Run **`issue-fetch`** for the ticket and show the summary.
- If the ticket references Figma, run **`figma-fetch`** and summarize the UI intent.
- Read the repo's project instructions and load the baseline stack profile
(`instructions/stacks/<id>.md` for the `stacks` in `.claude/dev-kit.json`); the repo's own
instructions always win, the profile fills gaps.
## 2. Plan — WAIT FOR APPROVAL
Validate assumptions against the running product when feasible (boot the app / exercise the
flow) before writing the plan. Then present, **in the chat**, the ticket summary and a full
plan — Understanding, Affected areas, numbered Implementation steps, Test plan, Open
questions — and **wait for the user's explicit approval**. Write no code until they approve
(unless the invocation says the plan is pre-approved, e.g. an automated run).
## 3. Implement
- Follow the repo's conventions and architecture. Keep the diff scoped to the story — no
opportunistic refactors.
- Update every side of any changed contract (payload/route/enum/schema/validation) together.
- For user-facing frontend work, write accessible markup as you go (semantic HTML, labels,
`alt`, keyboard/focus) — cheaper than fixing it at review.
## 4. Verify (gates — adaptive to the project)
Apply the gates that fit the project (detect its setup each run; see
`instructions/testing-standards.md`). Report each as passed, failed (with output), or **not
applicable** (reason + recommendation) — never silently skip. A `gates` policy in
`.claude/dev-kit.json` can force `required`/`off`; default is auto-detect.
- Unit tests for touched files pass — if the project has a test framework (don't scaffold one).
- **`coverage-check`** — if the project has coverage tooling (touched files meet the bar,
default ≥ 95%, no regression). If none: recommend, don't fail.
- **`e2e-generate`** for user-facing changes — if the project already does e2e.
- Lint clean on touched files (when the project lints).
- **Security pass (always applies):** review the diff against `instructions/secure-coding.md`;
any automatic-blocker is a gate — fix and re-check.
## 5. Self-review
Run **`pr-review`** on the full diff. Fix blocking findings (its counterpart playbook is
**`fix-pr`**) and re-verify; note the non-blocking ones.
## 6. Ship
Run **`create-pr`**. Report the PR URL, the verification evidence, and any follow-up risks.
## 7. Update the ticket
Run **`issue-update`**: comment a product-facing summary (plain language) plus the PR link,
and transition the ticket to the team's review status. The story isn't done until the
tracker reflects it.
## 8. Track follow-ups (offer — never force)
If the story left **loose ends** (out-of-scope notes in the PR, deferred `pr-review`/`fix-pr`
findings, deliberate TODOs), run **`follow-ups`**: offer to create them as tracked work items
linked to this story. Approval-gated — present the list, create nothing until approved; the
user may edit or skip. No genuine loose ends → say so and skip. Never fabricate follow-ups.
## Reporting
At every step, state plainly what passed, what failed (with output), and what was skipped.
Never report a gate as passed without having run it.