Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
bump: minor
---

### Added

- `/work-items:measure-delivery`: a read-only report of the five DORA delivery metrics (deployment frequency, change lead time, change fail rate, failed deployment recovery time, deployment rework rate) as a weekly or monthly team trend, read from the default branch's git history and never broken down by person (#11874). The repository setting `delivery_deploy_signal` in `docs/conventions/work-items.yaml` sets what counts as a deployment; its one value and default, `merge-to-default-branch`, counts each commit landing on the default branch, and one a later commit reverts counts as a failed deployment.
2 changes: 1 addition & 1 deletion docs/catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ plugin manifests and kept in sync by CI. Never hand-edit it; the category vocabu

## Project Management

- [`work-items`](../plugins/work-items): Work items through a provider-neutral tracker seam (github, local-markdown, jira, gitea, linear adapters): track (dashboard, creation, race-safe claims, recurring-schedule checks, stale-lease audits), scan-todos, decompose (plans into vertical-slice items), ship (route and run one spec container), triage (raw intake and unsolicited PRs), work, work-loop (autonomous PR-only drain), attend-queue (escalations), onboard-adapter (new tracker adapter), and setup (binds the provider).
- [`work-items`](../plugins/work-items): Work items through a provider-neutral tracker seam (github, local-markdown, jira, gitea, linear adapters): track (dashboard, creation, race-safe claims, recurring checks, stale-lease audits), scan-todos, decompose (plans into vertical slices), ship (run one spec container), triage (raw intake and unsolicited PRs), work, work-loop (autonomous PR-only drain), attend-queue (escalations), onboard-adapter (new tracker adapter), measure-delivery (DORA metrics), and setup (binds the provider).

## Operations

Expand Down
1 change: 1 addition & 0 deletions docs/skill-cheat-sheet.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ owned by [docs/catalog-taxonomy.md](catalog-taxonomy.md).
| [`/visualization:visualize`](../plugins/visualization/skills/visualize/SKILL.md) | `visualization` | Pick the best visual form for what is in the conversation and render it |
| [`/wizard:generate`](../plugins/wizard/skills/generate/SKILL.md) | `wizard` | Author a hardened interactive bash wizard for human-only setup, credential, and cutover steps |
| [`/wizard:unattended`](../plugins/wizard/skills/unattended/SKILL.md) | `wizard` | Author an unattended script a human launches once for a privilege or policy boundary |
| [`/work-items:measure-delivery`](../plugins/work-items/skills/measure-delivery/SKILL.md) | `work-items` | Report the five DORA delivery metrics as a team trend from default-branch history |
| [`/work-items:scan-todos`](../plugins/work-items/skills/scan-todos/SKILL.md) | `work-items` | Sweep source comments for TODO and FIXME markers, resolve or file each |
| [`/work-items:ship`](../plugins/work-items/skills/ship/SKILL.md) | `work-items` | Route and run a spec container's macro journey. Status, execution shape, next step |
| [`/work-items:track`](../plugins/work-items/skills/track/SKILL.md) | `work-items` | Backlog CRUD through the bound tracker. Add, list, close, stats |
Expand Down
2 changes: 1 addition & 1 deletion plugins/work-items/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "work-items",
"version": "3.15.3",
"description": "Work items through a provider-neutral tracker seam (github, local-markdown, jira, gitea, linear adapters): track (dashboard, creation, race-safe claims, recurring-schedule checks, stale-lease audits), scan-todos, decompose (plans into vertical-slice items), ship (route and run one spec container), triage (raw intake and unsolicited PRs), work, work-loop (autonomous PR-only drain), attend-queue (escalations), onboard-adapter (new tracker adapter), and setup (binds the provider).",
"description": "Work items through a provider-neutral tracker seam (github, local-markdown, jira, gitea, linear adapters): track (dashboard, creation, race-safe claims, recurring checks, stale-lease audits), scan-todos, decompose (plans into vertical slices), ship (run one spec container), triage (raw intake and unsolicited PRs), work, work-loop (autonomous PR-only drain), attend-queue (escalations), onboard-adapter (new tracker adapter), measure-delivery (DORA metrics), and setup (binds the provider).",
"author": {
"name": "Melodic Software",
"email": "info@melodicsoftware.com"
Expand Down
10 changes: 9 additions & 1 deletion plugins/work-items/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ file-based TODO lists, designed for teams where humans and autonomous agents
pick work from the same queue. The skill core is backend-agnostic; GitHub is the
bound adapter today.

The tracker's capabilities are split across nine focused skills (plus a setup
The tracker's capabilities are split across ten focused skills (plus a setup
skill). Invoke the one that matches the job (or let Claude invoke it when you ask
about work items, tickets, issues, tracked work, or what to do next):

Expand All @@ -20,6 +20,7 @@ about work items, tickets, issues, tracked work, or what to do next):
/work-items:ship run #300 # run the container's ready items under its shape (attended)
/work-items:scan-todos # sweep TODO/FIXME/HACK markers
/work-items:onboard-adapter gitea # generate an adapter for an unbundled tracker
/work-items:measure-delivery # DORA delivery metrics as a weekly team trend
```

## Skills
Expand All @@ -34,6 +35,7 @@ about work items, tickets, issues, tracked work, or what to do next):
| `/work-items:decompose` | Break a plan/PRD/item into vertical-slice items with AFK/HITL classification and dependency ordering. When a spec container is published and the design behind the plan produced typed artifacts (frontmatter carrying `scope` and `dialect`), each is inlined into the container body as a fenced block plus a one-line provenance note naming the scope and dialect, with no file path; an `integration` design labels two, and both are inlined. Slice bodies are unchanged. |
| `/work-items:ship` | Macro-journey router over one spec container: rollup + scoped frontier, the container's recorded execution shape (per-item PRs vs integration branch → single PR) with that mode's discipline, and the routed next step. `run` works the container's ready items in parallel through `/implementation:implement-dispatch` and lands them one at a time, attended only. Mechanics stay with their owners. |
| `/work-items:scan-todos` | Sweep the codebase for TODO/FIXME/HACK markers; resolve or file each. |
| `/work-items:measure-delivery` | Read-only report of the five DORA delivery metrics (deployment frequency, change lead time, change fail rate, failed deployment recovery time, deployment rework rate) as a team trend from the default branch's git history, never per person. |
| `/work-items:onboard-adapter` | Onboard a tracker this plugin does not bundle: interview to lock the provider's shape, explore the consumer's real instance for the per-instance facts only it can settle, generate a consumer-owned adapter (hardened security skeleton, honest capability manifest, contract-fixed verb scaffolds, conformance binding) into the consuming repo, then verify. The tail half of the hybrid adapter model. Bundled adapters cover the majors. |
| `/work-items:setup` | `check` inspects the tracked `.github/recurring-schedule.json`, the jq/tracker-seam entry gates, and the recurring-maintenance role label read-only; `apply` binds the provider, writes the empty schedule skeleton, and offers the canonical-role → label remap in the tracker binding (re-runnable). Seeding actual rows, inferring candidate items from the repo and interviewing per item, is opt-in via `apply --seed-schedule` or an offer that recommends skipping; a schedule that already carries items is offered updates as before. |

Expand Down Expand Up @@ -210,6 +212,12 @@ work_priority_order:

The work skill's "Selection Priority" section says how it is read.

`delivery_deploy_signal` also lives only in the repository file. It sets what
`/work-items:measure-delivery` counts as a deployment, and its one value, the
default, is `merge-to-default-branch`: each commit on the default branch's
first-parent history is a deployment, and one a later commit reverts is a
failed deployment.

Everything else is project-specific behavior that routes through the consuming
repo's own surfaces: the bound provider in `.work-item-tracker.json` (including
the optional `config.role_labels` canonical-role → label remap), its labels
Expand Down
8 changes: 7 additions & 1 deletion plugins/work-items/schemas/work-items.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://raw.githubusercontent.com/melodic-software/claude-code-plugins/main/plugins/work-items/schemas/work-items.schema.json",
"title": "work-items team config",
"description": "Schema for a repository's docs/conventions/work-items.yaml, the team layer of the work-items plugin's settings (ADR 0064). A key set here wins over the same key in the plugin's userConfig. Readers: /work-items:triage for the triage keys (the /work-items:work-loop admission gate reads the objection window's end from the marker comment triage posts), every lane that follows reference/ai-disclaimer.md for ai_disclaimer, and /work-items:work for work_priority_order.",
"description": "Schema for a repository's docs/conventions/work-items.yaml, the team layer of the work-items plugin's settings (ADR 0064). A key set here wins over the same key in the plugin's userConfig. Readers: /work-items:triage for the triage keys (the /work-items:work-loop admission gate reads the objection window's end from the marker comment triage posts), every lane that follows reference/ai-disclaimer.md for ai_disclaimer, /work-items:work for work_priority_order, and /work-items:measure-delivery for delivery_deploy_signal.",
"type": "object",
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -31,6 +31,12 @@
"uniqueItems": true,
"default": ["priority: critical", "priority: high", "priority: medium", "priority: low"],
"description": "The priority: label names, highest first, that /work-items:work ranks candidates by within each selection tier before the tier's own order (next_due, the guardrails preference, or oldest-first) breaks ties; the work-loop lane ranks its admitted items the same way. A candidate with no priority: label, or one this list does not name, ranks below every listed label. Quote each item (- \"priority: high\"): an unquoted item parses as a mapping and drops out of the list. Absent: the default list."
},
"delivery_deploy_signal": {
"type": "string",
"enum": ["merge-to-default-branch"],
"default": "merge-to-default-branch",
"description": "What /work-items:measure-delivery counts as one deployment. merge-to-default-branch: each commit on the default branch's first-parent history is one deployment (a merge commit or a squash landing is one; a rebase landing is one per commit it lands), and one a later commit reverts is a failed deployment. Absent: merge-to-default-branch."
}
}
Comment thread
melodic-automation-lanes[bot] marked this conversation as resolved.
Resolved
}
113 changes: 113 additions & 0 deletions plugins/work-items/skills/measure-delivery/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
---
description: "Read-only report of the five DORA delivery metrics (deployment frequency, change lead time, change fail rate, failed deployment recovery time, deployment rework rate) as a team trend from the default branch's history, never per person. Use when: 'measure delivery', 'DORA metrics', 'deployment frequency', 'change lead time', 'change fail rate', 'how fast do we ship', 'delivery trend'. Backlog counts are /work-items:track stats."
argument-hint: "[--since YYYY-MM-DD] [--until YYYY-MM-DD] [--bucket week|month] [--branch <ref>]"
user-invocable: true
disable-model-invocation: false
metadata:
workflow-stage: anytime
summary: Report the five DORA delivery metrics as a team trend from default-branch history
---

## Variables

Arguments: `$ARGUMENTS`, the window and period flags below, passed through to the script.

- `--since <YYYY-MM-DD>`: first UTC day of the window (default: the 84 days ending with `--until`).
- `--until <YYYY-MM-DD>`: last UTC day, inclusive (default: now).
- `--bucket week|month`: trend period (default `week`, ISO weeks starting Monday).
- `--branch <ref>`: the default branch (default: the ref `origin/HEAD` names).

## Purpose

Show how the team delivers over time: one row per period and a window total, for the five
delivery metrics DORA defines. This skill reports one repository's trend against its own past,
never a comparison between teams. It reads history and writes nothing.

- **Pointer**: when a metric's definition is in question, fetch
<https://dora.dev/guides/dora-metrics/> live. **As of**: 2026-11-01. **Recheck trigger**: DORA
renames, adds or removes a delivery metric.

## Metrics

| Metric | Measured here as |
|---|---|
| Deployment frequency | Deployments per period, and per week over the window |
| Change lead time | Median hours from the earliest author date among a deployment's commits to its landing |
| Change fail rate | Failed deployments / deployments |
| Failed deployment recovery time | Median hours from a failed deployment to the first deployment that reverts it |
| Deployment rework rate | Deployments that revert an earlier change / deployments |

## Deploy signal

What counts as a deployment is the team setting `delivery_deploy_signal` in the repository's
`docs/conventions/work-items.yaml` (schema: `${CLAUDE_PLUGIN_ROOT}/schemas/work-items.schema.json`).
Its one value, and the default, is `merge-to-default-branch`:

- Each commit on the default branch's first-parent history is one deployment, at its committer
date. A merge commit or a squash landing is one deployment; a rebase landing puts each of its
commits on that history, so each one counts as its own deployment.
- A deployment a later first-parent commit reverts is a failed deployment. A commit reverts a
deployment when its message has `This reverts commit <sha>` naming the deployment or a commit
it merged, or, with no such line, when its subject is `Revert "<subject>"` for an earlier
deployment's subject. A merge counts the messages of the commits it merges, so a revert that
lands through a merge commit is seen. A revert landing after `--until` still marks a
deployment in the window as failed.

The signal reads only git history, so no tracker or forge call is made and any host works.

## Workflow

1. Resolve the deploy signal from the repository root:

```bash
bash "${CLAUDE_PLUGIN_ROOT}/skills/triage/scripts/parse-concern-value.sh" \
docs/conventions/work-items.yaml delivery_deploy_signal
```

Empty output means the key is unset: use the default, `merge-to-default-branch`. Report
whether the value came from the file or the default. A value other than
`merge-to-default-branch` stops the run: name the value and the one the schema allows.

2. Run the report. With no `--branch`, the script reads the ref `origin/HEAD` names, as of the
last fetch. Run `git fetch` first only when the user asks for the remote's latest history;
otherwise say the report covers history up to the last fetch.

```bash
bash "${CLAUDE_PLUGIN_ROOT}/skills/measure-delivery/scripts/delivery-metrics.sh" \
--repo "<repo root>" --deploy-signal "<signal>" <the flags from $ARGUMENTS>
```

Exit `2` is a bad flag or a branch that does not resolve: show the script's stderr line,
and when `origin/HEAD` is unset, ask for `--branch`. Exit `3` is a failed git read and exit
`8` a missing `git` or `jq`: report it and stop.

3. Render the JSON as one markdown table, a row per `trend` period then a `Window` row from
`totals`, a column per metric. Show a null value as `n/a` (nothing to measure, such as a
period with no deployments), and show rates as percentages. Mark the first or last period
as partial when the window starts or ends inside it.

4. Add two or three lines that read the trend: which metrics moved between the first and last
full periods with deployments, and in which direction. Describe the team's delivery only.

Done when the table and the trend lines are shown, with the window, branch and deploy signal
they cover.

## Next

`/work-items:track stats` for the open backlog behind the trend.

## Gotchas

- **Never name a person.** The script emits counts, medians and ratios only. Do not add
authors, committers, reviewers or a per-person breakdown, even when asked: DORA metrics
describe a team's delivery, and per-person delivery numbers are a different report.
- **Squash and rebase landings can shorten lead time.** Lead time starts at the earliest author
date git keeps for the change. A landing that rewrites author dates moves that start later,
so the lead time reads short; a merge commit keeps every commit's author date.
- **A rebase landing counts each of its commits as a deployment.** A team that rebase-merges
sees deployment frequency raised by its changes' commit counts, and a reverted change marks
only the commits its revert names as failed, so the change fail rate reads low.
- **A revert under another subject goes uncounted.** A hand-written undo with neither the
`This reverts commit` line nor the `Revert "<subject>"` subject is invisible to the signal.
- **Per-item stage times are out of scope.** Time an item spent in each tracker stage is a
separate report, not one of these five metrics.
Loading
Loading