Skip to content
Back to skills

Agile Claims

ASecurity

Creating tracker artifacts and taking hold of one — ID allocation, the full frontmatter block, the compare-and-swap claim protocol that keeps parallel agents from stealing each other's work, and who may write which part of a spec. Load this only if you create tickets or claim them: `pm` and `qa` do, an engineer never does. Editing a ticket you already hold is `agile-artifacts`.

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 7, 2026
ai-agentspythonbashbackend

Security analysis

A100/100

Scanned October 7, 2026

npx -y skills add vstlmkh/forge --skill agile-claims --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Agile Claims?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Agile Claims
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/vstlmkh-agile-claims/badge)](https://www.skillsdirectory.com/skills/vstlmkh-agile-claims)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: agile-claims
description: Creating tracker artifacts and taking hold of one — ID allocation, the full frontmatter block, the compare-and-swap claim protocol that keeps parallel agents from stealing each other's work, and who may write which part of a spec. Load this only if you create tickets or claim them: `pm` and `qa` do, an engineer never does. Editing a ticket you already hold is `agile-artifacts`.
---

# Creating and claiming

`agile-artifacts` covers reading a ticket and editing one you already hold —
every agent needs that. This covers the two things only `pm` and `qa` do: making
an artifact exist, and taking hold of one. An engineer is *handed* its ticket,
already claimed, already specified, with failing tests already on the branch, so
none of this binds it and none of it is worth its context.

## Creating an artifact

1. `agile.py next-id <kind>` — never guess an ID, never reuse one.
2. Write `<tracker>/<folder>/<ID>-<kebab-slug>.md` with the full frontmatter
   block from `SCHEMA.md`. **Every field, including the null ones.** A missing
   field is a lint error, not a shortcut — and a new task or bug with no `docs:`
   or no `spec:` is refused outright by a `PreToolUse` hook, because those two
   fields are what make the consult step and the grilling step happen at all.
3. `created` and `updated` are today's date — get it from `date +%F`, do not
   assume.
4. `agile.py lint`, then commit:
   `chore(agile): opens STORY-014 with TASK-0231, TASK-0232`.

Only `pm` creates artifacts. The one exception is `qa`, which files bugs — and
`qa` must call `next-id bug` immediately before writing the file, with the write
as the last thing it does, so the window for an ID collision stays near zero.

## The claim protocol — a compare-and-swap, not a lock

**`qa` claims, not the engineer.** A ticket leaves `todo` into `speccing`, held
by `qa`, which grills it into a brief, writes the failing tests against that
brief in `writing_tests`, and only then hands the ticket to an engineer in
`in_progress`. An engineer never claims out of `todo`; by the time it sees a
ticket, the claim already exists, the brief is agreed and the branch already has
a red test commit on it.

There is no central lock file, and `agile.py` does not do this for you — it has
never written a ticket, deliberately. The claim is a single `Edit` whose
`old_string` is the contiguous unclaimed block. Because `Edit` requires an exact
match, a racing second agent's edit **fails** — and that failure is the lock. A
script rewriting the same frontmatter would have to invent a lock to replace it.

1. Read the ticket. Abort unless `status: todo`, `assignee: null`, and every
   `blocked_by` target is `done` or `cancelled`.
2. One `Edit`, `old_string` covering the whole contiguous block from `status:`
   through `claimed_at:`:

   ```
   status: todo
   parent: STORY-014
   scope: backend
   priority: P2
   assignee: null
   claimed_at: null
   ```

   `new_string` — same block with `status: speccing`, `assignee: qa`, and
   `date -u +%Y-%m-%dT%H:%M:%SZ`.
3. **If the Edit fails, you lost the race.** Do not retry, do not re-read and
   force it through. Report the loss and pick another ticket.
4. Commit immediately so the claim is published:
   `chore(agile): claims TASK-0231`.
5. Re-read the file and confirm your own name is in `assignee` before starting
   work.

`speccing -> writing_tests` is a second edit of the same block, by the same
agent — the claim does not change hands, the stage does.

The handover to the engineer is a third edit of the same block:
`writing_tests -> in_progress`, `assignee` to the engineer that owns the scope,
`claimed_at` refreshed. `branch` must already be filled in — the engineer
continues on `qa`'s branch rather than cutting its own.

Releasing a claim is the first edit in reverse: back to `todo`, assignee and
`claimed_at` to `null`, with a `## Log` line saying why.

## The spec is the contract

A task or bug carries `spec:` — either `specs/<ID>.md` or `null` with
`spec_waiver: NO-SPEC (<reason>)`. The file is **created by the script, never by
hand**, for the same reason a knowledge-base note is:

```bash
python3 .claude/scripts/agile.py spec new TASK-0231    # then set the spec: it prints
python3 .claude/scripts/agile.py next-req TASK-0231    # -> REQ-0004
```

A `PreToolUse` hook denies a spec file that is not named after an existing
ticket, and `lint` reports an orphan spec as an error — a spec that outlived its
ticket is a document nobody will ever reconcile.

Requirement ids are **per-ticket, never reused and never renumbered**, exactly
like artifact ids: a requirement that is dropped keeps its row with
`Status: dropped`, so a REQ id written into a test name or a commit message
stays meaningful. The full specification is `SCHEMA.md` §10.

The one part of a spec written from outside the subagent that owns the gate is
the `## Questions` table, and it is written by a command rather than by hand:

```bash
python3 .claude/scripts/agile.py spec answer TASK-0231 Q1="<what the user said>"
```

The orchestrator runs it the moment the user answers. Those words are the only
thing in the cycle the repository cannot reconstruct, and a relayed copy of them
lives exactly as long as one context window.

Who may write what:

| | May write |
|---|---|
| `qa`, in `speccing` | the whole file |
| the orchestrator, at any time | `## Questions` answers, via `spec answer` |
| `qa`, later | nothing — a brief that moves after the tests were written is not a brief |
| `pm`, at gate 6 | the `Becomes` cell of a `## Carryover` row, and nothing else |
| anyone else | nothing |

**Gates 5 and 6 run at the same time, and that is only safe because their file
sets are disjoint.** At gate 5 `qa` writes the knowledge base and this ticket's
`## Log`; at gate 6 `pm` writes *other* tickets, the parent, and those carryover
cells. Neither touches the other's files, and `pm` in particular does not edit
the ticket under review.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.