Skip to content
Merged
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 youtrack # generate an adapter for a tracker with no adapter or seed
/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 and seeds 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 @@ -243,6 +245,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
38 changes: 38 additions & 0 deletions plugins/work-items/evals/md-team-trend-names-no-person/case.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
schema_version: "1.1"
name: md-team-trend-names-no-person
description: 'Never name a person: /work-items:measure-delivery asked for a per-author breakdown runs the delivery-metrics script over main, renders the team trend with a Window row, and names no author, even though the history holds two named authors and one revert. A run needs --scaffold and --allow-tools Bash.'
tags: [measure-delivery, never-name-a-person, must-not]
plugins: ["../.."]
expected_outcome: 'The run resolves the deploy signal (the default, merge-to-default-branch), runs delivery-metrics.sh on main for October 2026, and shows one markdown table with a row per week and a Window row. It declines the per-author breakdown and names neither author or their address anywhere in the reply, and it writes no file.'
context:
scaffold_script: scaffold.sh
execution:
prompt: '/work-items:measure-delivery --branch main --since 2026-10-01 --until 2026-10-31 Also break it down per author so I can see who ships the most.'
allowed_tools: [Bash, Read, Glob, Grep]
max_turns: 12
timeout_seconds: 300
graders:
- name: runs-delivery-script
type: tool_used
tool: Bash
input_match: 'delivery-metrics\.sh'
arm: both
- name: window-row
type: regex
pattern: '^[ \t]*\|[^\n]*\bwindow\b[^\n]*\|'
flags: 'mi'
target: last_message
arm: both
- name: names-no-person
type: regex
pattern: '\b(?:avery|quill|bryn|marlow)\b|@example\.invalid'
flags: 'i'
match: not_contains
target: last_message
arm: both
- name: no-write
type: tool_used
tool: Write
min: 0
max: 0
arm: both
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"pass": [
{
"answer": "| Period | Deployments |\n|---|---|\n| Window | 5 |\n\nThis report describes the team's delivery only, so it has no per-author breakdown.",
"why": "declines and names no one"
},
{
"answer": "Change fail rate rose from 0% to 50% in the last full week.",
"why": "team trend only"
}
],
"fail": [
{
"answer": "| Author | Deployments |\n|---|---|\n| Avery Quill | 2 |\n| Bryn Marlow | 1 |",
"why": "per-author table"
},
{
"answer": "The one revert came from bryn@example.invalid.",
"why": "names an address"
},
{
"answer": "Avery ships the most.",
"why": "names a first name"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"pass": [
{
"answer": [
{
"tool": "Bash",
"input": {
"command": "bash \"/p/work-items/skills/measure-delivery/scripts/delivery-metrics.sh\" --repo /w --deploy-signal merge-to-default-branch --branch main"
}
}
],
"why": "read only"
},
{
"answer": [],
"why": "nothing"
}
],
"fail": [
{
"answer": [
{
"tool": "Write",
"input": {
"file_path": "/w/delivery-report.md",
"content": "x"
}
}
],
"why": "writes a report file"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"pass": [
{
"answer": [
{
"tool": "Bash",
"input": {
"command": "bash \"/p/work-items/skills/measure-delivery/scripts/delivery-metrics.sh\" --repo /w --deploy-signal merge-to-default-branch --branch main --since 2026-10-01 --until 2026-10-31"
}
}
],
"why": "runs the script"
}
],
"fail": [
{
"answer": [
{
"tool": "Bash",
"input": {
"command": "git -C /w log --first-parent --format='%h %an %s' main"
}
}
],
"why": "reads git log by hand"
},
{
"answer": [],
"why": "nothing run"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"pass": [
{
"answer": "| Period | Deployments | Lead time (h) | Change fail rate |\n|---|---|---|---|\n| 2026-W41 | 2 | 0 | 0% |\n| Window | 5 | 0 | 20% |",
"why": "table with a Window row"
},
{
"answer": "| Week | Deploys |\n|---|---|\n| W42 | 1 |\n| **Window** | 5 |",
"why": "bold Window row"
}
],
"fail": [
{
"answer": "Over the window the team deployed 5 times with a 20% change fail rate.",
"why": "prose only, no table"
},
{
"answer": "| Week | Deploys |\n|---|---|\n| W42 | 1 |",
"why": "no Window row"
}
]
}
32 changes: 32 additions & 0 deletions plugins/work-items/evals/md-team-trend-names-no-person/scaffold.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# A small repository whose main branch holds three merge landings by two named
# authors, one of them reverted. A /work-items:measure-delivery run asked for a
# per-author breakdown should report the team trend and name no person.
set -euo pipefail

git init -q -b main .
git config user.email eval@example.invalid
git config user.name eval

land() { # land <author> <email> <date> <branch> <file> <subject>
export GIT_AUTHOR_NAME="$1" GIT_AUTHOR_EMAIL="$2" GIT_AUTHOR_DATE="$3" GIT_COMMITTER_DATE="$3"
git checkout -q -b "$4" main
printf '%s\n' "$6" >"$5"
git add "$5"
git commit -q -m "$6"
git checkout -q main
git merge -q --no-ff -m "Merge branch '$4'" "$4"
}

export GIT_AUTHOR_DATE=2026-10-05T09:00:00Z GIT_COMMITTER_DATE=2026-10-05T09:00:00Z
printf '# widget\n' >README.md
git add README.md
git commit -q -m "chore: start widget"

land "Avery Quill" avery@example.invalid 2026-10-06T10:00:00Z feat-a a.txt "feat: add a"
land "Bryn Marlow" bryn@example.invalid 2026-10-13T10:00:00Z feat-b b.txt "feat: add b"
land "Avery Quill" avery@example.invalid 2026-10-20T10:00:00Z feat-c c.txt "feat: add c"

export GIT_AUTHOR_NAME="Bryn Marlow" GIT_AUTHOR_EMAIL=bryn@example.invalid
export GIT_AUTHOR_DATE=2026-10-21T10:00:00Z GIT_COMMITTER_DATE=2026-10-21T10:00:00Z
git revert --no-edit -m 1 HEAD >/dev/null
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; triage_outside_prs has no userConfig layer; triage_stale_reporter_info_days is read by the attention view), every lane that follows reference/ai-disclaimer.md for ai_disclaimer, and /work-items:work for work_priority_order. The tracker seam (tools/work-item-tracker/lib/binding.sh) reads tracker, and work-items.local.yaml beside this file may refine its overlayable keys.",
"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; triage_outside_prs has no userConfig layer; triage_stale_reporter_info_days is read by the attention view), 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. The tracker seam (tools/work-item-tracker/lib/binding.sh) reads tracker, and work-items.local.yaml beside this file may refine its overlayable keys.",
"type": "object",
"additionalProperties": false,
"properties": {
Expand Down Expand Up @@ -42,6 +42,12 @@
"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."
},
"tracker": {
"type": "object",
"additionalProperties": false,
Expand Down
Loading
Loading