Skip to content
Back to skills

Roadmap To Workflow

ASecurity

Fan an approved `.task/roadmap/<slug>.md` out to a dynamic Workflow — parallel planning, serialized implementation, dependency-ordered waves.

  • 7 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added August 30, 2026
developmentjavascriptjavabashcode-reviewgit

Works with

  • claude code
  • cli

Security analysis

A100/100

Scanned October 5, 2026

npx -y skills add SpaiR/task-pipeline --skill roadmap-to-workflow --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Roadmap To Workflow?

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

Security grade badge for Roadmap To Workflow
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/spair-roadmap-to-workflow/badge)](https://www.skillsdirectory.com/skills/spair-roadmap-to-workflow)

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: roadmap-to-workflow
description: 'Fan an approved `.task/roadmap/<slug>.md` out to a dynamic Workflow — parallel planning, serialized implementation, dependency-ordered waves.'
argument-hint: '[<roadmap-slug>]'
disable-model-invocation: true
user-invocable: true
allowed-tools: 'Bash(bash *skills/_lib/preflight.sh* *) Bash(bash *skills/_lib/write-task.sh* *) Bash(bash *skills/_lib/roadmap-items.sh* *) Bash(bash *skills/_lib/detect-project.sh* *) Bash(bash *skills/validate/validate.sh* *)'
---

Drive an approved roadmap through a dynamic Workflow. This skill reports the roadmap's unchecked items and the scope the user picks; the **plugin-shipped driver** (`skills/_lib/roadmap-driver.js`, invoked by name as `task:roadmap-driver`) sorts them into dependency-ordered **waves** and, per wave, plans in parallel then implements, reviews and ticks off one item at a time in the shared working tree. The driver is a static file, inspectable at any time and parameterized only through `args` (Step 2) — never hand-rolled here, never re-authored inline. Without the Workflow tool, Step 2 hard-stops instead of running the items itself.

**Per-item execution is a three-stage split, sized by the item's `**Size:**` hint (`S` / `M` / `L`, `M` when absent):** opus plans it, at medium effort for `S` and high otherwise; sonnet implements and commits at medium effort for `S` and `M`, opus at medium for `L`; and `task:code-reviewer` reviews, commits its fixes on top, and ticks the checkbox once its review passes. The reviewer pins its own model and effort, so an item's size never lowers its review.

**This skill *is* the opt-in** for the Workflow tool: following its Steps is the authorization. No magic keyword, no separate confirmation.

**Input:** `$ARGUMENTS` — optional. A single positional `<roadmap-slug>` (or its path under `.task/roadmap/`) to skip the roadmap picker. No flags — item scope is chosen interactively (Step 0).

**Format contract:** [contract § Roadmap file format](../../docs/contract.md#roadmap-file-format-taskroadmapslugmd) owns the item grammar (`### N.` plus its `- [ ] Done` status line, `**Dependencies:**`, `**Size:**`), and [§ execution shape](../../docs/contract.md#roadmap-to-workflow-execution-shape-driver-contract) the driver's stages.

## Step 0: Setup gate, pick roadmap, pick scope

This is **not** an intake skill: it never runs setup. A roadmap cannot exist without `.task/CLAUDE.md`, so an absent one means something upstream is broken.

The entry state, gathered before this skill reached you — no tool call of your own:

!`bash "${CLAUDE_PLUGIN_ROOT}/skills/_lib/preflight.sh" workflow`

[docs/contract.md § Helpers](../../docs/contract.md#helpers) owns that block's shape. Read it, then act:

1. `PLUGIN_ROOT:` and `AI_DIR:` are Step 2's `pluginRoot` and `aiDir` args, used verbatim — the sandbox expands neither.
2. **`CONFIG: absent`** → hard-stop redirect (do **not** bootstrap here):
   > The project isn't set up yet. Capture something first with `/task:to-task`, `/task:to-roadmap`, or `/task:to-spec` — those three set the project up inline.
   > → Next: `/task:to-roadmap`
3. **`VALIDATE:` holds `validate.sh all`'s output** — every artifact, so an error may belong to a task or roadmap unrelated to this run. Surface every `ERROR` line, block on none of them yet, and **hold** the roadmap ones: once `<slug>` is resolved below, an error against **that** file is a stop — "→ Next: fix the reported error in `.task/roadmap/<slug>.md`, then rerun `/task:roadmap-to-workflow <slug>`". `WARN` lines are informational. (`ERROR precondition: CLAUDE.md not found` is case 2, not a validation error.)
4. `ROADMAPS:` carries each roadmap's progress and open item numbers — the picker below reads it, and lists no directory of its own.

If that block arrived unexpanded — the command line itself rather than its output — the preprocessing did not fire: run that command yourself and continue exactly as above.

### Roadmap

A positional `<roadmap-slug>` in `$ARGUMENTS` is matched against the `ROADMAPS:` slugs. A positional **path** (contains `/`) is accepted only when it names `$AI_DIR/roadmap/<slug>.md` itself — relative to the working directory or absolute — and `<slug>` from here on is always that bare slug: Step 1 reads the file and the reviewer ticks it through the path the driver rebuilds from `slug`, so a roadmap anywhere else would be read from one file and ticked in another. A path outside `$AI_DIR/roadmap/` is no match. No match — stop, and list what is there, rather than falling through with an unresolved path:

> no roadmap `<arg>` under `$AI_DIR/roadmap/`. Available: `<slug>` (2/7), `<slug>` (0/4).
> → Next: `/task:roadmap-to-workflow <one of those slugs>`

With no positional argument, pick from the `ROADMAPS:` lines:

- **`ROADMAPS: none`** → stop: "no roadmaps found — create one with `/task:to-roadmap`. → Next: `/task:to-roadmap`"
- **Exactly one line** → use it (still refuse if it is fully complete — `unchecked=none` with a total above 0 — or if it has no item at all, `0/0`).
- **A `0/0` roadmap** — `unchecked=none` over zero items — has no item heading that parses, which is not the same as every item being ticked. It is never a pick and never called complete: stop with "no item heading in `.task/roadmap/<slug>.md` parses. → Next: `bash "${CLAUDE_PLUGIN_ROOT}/skills/validate/validate.sh" roadmap <slug>`, fix the headings, then rerun `/task:roadmap-to-workflow <slug>`", whether it came from the picker or a positional argument.
- **An `unchecked=unreadable` roadmap** — its file could not be read — is never a pick: stop with "`.task/roadmap/<slug>.md` could not be read. → Next: fix the file's permissions, then rerun `/task:roadmap-to-workflow <slug>`", whether it came from the picker or a positional argument.
- **More than one** → `AskUserQuestion` (convention (c)), one chip per roadmap labelled `<slug>  (<done>/<total>)`; sort partial roadmaps first, complete ones (`unchecked=none`, total above 0) last with a `(complete)` suffix, and refuse to proceed on a complete pick. A `0/0` roadmap is labelled `(no items parsed)`, never `(complete)`, and refused the same way as above.

Every refusal on a complete roadmap (not a `0/0` one, which has its own above) — picked, the only one, or named positionally — ends the same way: "Every item in `<slug>` is already checked off — nothing left to run. → Next: `/task:to-roadmap` for a new initiative, or uncheck the items you want rerun."

Read the roadmap's `Spec:` header lines, if any, and resolve each slug to an **absolute** `$AI_DIR/spec/<slug>.md` — the slug is the link label, or the whole value when it is a bare slug, never the relative target ([contract § Cross-artifact references](../../docs/contract.md#cross-artifact-references)). These become Step 2's `specPaths` and reach every plan agent as fixed anchors; absolute because the sandbox expands nothing.

### Item scope

No flags — always ask, unless there is nothing to ask. The open item numbers are the roadmap's `unchecked=` list; with **more than one**, one `AskUserQuestion` (convention (c)) — *"How much of `<slug>` should this run cover?"*:

- **All remaining** (default) — every unchecked item.
- **Only next wave** — `scope: 'next-wave'`. The driver sorts every unchecked item and keeps wave 1, so nothing is filtered or reordered here.
- **Pick range** — via the free-text ("Other") option, e.g. `1,3-5,8`, expanded to the numbers themselves. A number that is not in `unchecked=` is refused **with the valid set named**, which is what turns a rejection into a second attempt that works: "#9 isn't a runnable item in `<slug>` (already checked, or no such item). Unchecked right now: #2, #3, #5, #7. → Next: rerun `/task:roadmap-to-workflow <slug>` and pick from those."

One open item → skip the question, run it. `unchecked=none` → the complete-roadmap refusal above, word for word (the `0/0` stop instead, when the total is 0).

## Step 1: Report the items

```bash
bash "${CLAUDE_PLUGIN_ROOT}/skills/_lib/roadmap-items.sh" "<slug>"
```

One line per unchecked item — `N<TAB>deps<TAB>size<TAB>title` — then `DONE<TAB><n,…>` with the already-marked numbers ([contract § Helpers](../../docs/contract.md#helpers) owns the shape). Exit 1 means the roadmap did not resolve or could not be read: stop, rather than running with zero items, which reads exactly like a finished roadmap — relay the helper's `ERROR` line, then "→ Next: check that `.task/roadmap/<slug>.md` exists and is readable, then rerun `/task:roadmap-to-workflow <slug>`".

Pass those lines through to Step 2 as data — **every** unchecked item, unsorted and unfiltered: each item line becomes one `items` entry `{n, title, size, deps}`, the `DONE` line becomes `done`, and Step 0's pick becomes `scope`. Numbers are parsed as **integers**, and an empty field is an **empty array**: a dependency-free item is `deps: []`, and a roadmap with nothing marked yet is `done: []`. Narrowing is `scope`'s job; the driver needs the full set to see the dependencies that define a wave.

The driver's `computeWaves` sorts them and hard-stops **before spawning anything**, returning one line. Relay it as-is and add the matching footer:

- `out of scope: #4 depends on #2, …` → `→ Next: rerun \`/task:roadmap-to-workflow <slug>\` with a scope that includes #2`
- `dependency cycle among #1, #2 …` → `→ Next: edit \`.task/roadmap/<slug>.md\` to break the cycle, then rerun \`/task:roadmap-to-workflow <slug>\``
- `not runnable in this roadmap …: #9` → name the valid set, as Step 0's bad-range pick does: `Unchecked right now: #2, #3. → Next: rerun \`/task:roadmap-to-workflow <slug>\` and pick from those`
- `bad args — …` → this skill built the args wrong, not the user: `→ Next: rerun \`/task:roadmap-to-workflow <slug>\` (the args are rebuilt from the roadmap file)`

## Step 2: Invoke the Workflow driver

**Do not author a Workflow script.** The driver ships at `skills/_lib/roadmap-driver.js`, declared in the plugin manifest under `"workflows"`, so the platform registers it as `task:roadmap-driver` and reads the file itself. It is reached **by name, never by path** — a `scriptPath` into the plugin is checked for read permission against this session's working directory, which a plugin is never inside. Assemble its `args` from Steps 0–1, record `git rev-parse --verify -q HEAD` (Output's `Commits:` range starts there; it prints nothing on a repository with no commit yet), and invoke it:

```javascript
Workflow({
  name: "task:roadmap-driver",
  args: {
    slug: "<roadmap-slug>",
    aiDir: "<absolute value of $AI_DIR>",                    // echoed in Step 0
    pluginRoot: "<absolute value of $CLAUDE_PLUGIN_ROOT>",   // echoed in Step 0
    specPaths: ["<absolute $AI_DIR/spec/<slug>.md>"],        // from Step 0 — [] when the roadmap has no Spec: headers
    items: [                                                 // from Step 1 — EVERY unchecked item, unsorted
      { n: 1, title: "…", size: "M", deps: [] },
      { n: 2, title: "…", size: "S", deps: [1] },
      { n: 3, title: "…", size: "L", deps: [1] },
    ],
    done: [],                                                // from Step 1's DONE line — already-marked numbers
    scope: "all",                                            // from Step 0 — "all" | "next-wave" | [2, 3]
  },
})
```

**Args are real JSON values, every path absolute** — `items` an actual array of objects, `done` an actual array of numbers, never JSON-encoded strings. The driver asserts all of it up front and returns one explanatory line instead of launching an agent against garbage.

The stage details are the driver's ([contract § execution shape](../../docs/contract.md#roadmap-to-workflow-execution-shape-driver-contract)).

**Rerun / resume.** The workflow name and args are static, so `resumeFromRunId` replays completed stages from cache — use it only for a run **interrupted before the driver returned**, in the same session. After a stop the driver did return, the stage that failed is itself a completed stage: a resume would replay its cached `FAIL` and stop at the same place, however the item was fixed. Rerun plainly instead — Step 1 reports only unchecked items, and ticked ones never rerun.

**Driver not registered** — the Workflow tool is there, but `task:roadmap-driver` does not resolve; the tool's error names the workflow and lists what is registered. The driver ships with the plugin, so this is an install fact rather than an environment one: a stale plugin snapshot, an update this session never reloaded, or a CLI build that does not load plugin-shipped workflows yet. Do not retry by path, and do not treat it as the no-Workflow-tool case below — that would hide a broken install behind the slowest available path. Stop, quoting the tool's own error:

```
`task:roadmap-driver` is not registered in this session, so autopilot cannot start — the `task` plugin is stale, or was updated without a restart. The Workflow tool reported: "<its error, verbatim>". The items can still be run by hand, but the fix is the reinstall.
→ Next: update or reinstall the `task` plugin, restart Claude Code, then rerun `/task:roadmap-to-workflow <slug>`.
```

**No Workflow tool** — the Workflow tool itself is absent from this environment, which is a different case from the one above (there, the tool is present but the driver's name fails to resolve). Autopilot cannot run without it, so this skill stops rather than looping the items itself. Stop, with this message:

```
Autopilot needs the Workflow tool, and it isn't available in this environment, so `/task:roadmap-to-workflow` can't run. The items can still be run by hand, one at a time, in dependency order: in this chat, run `/task:to-task <slug>#<N>` for one unchecked item, then start a fresh session and say `implement .task/task/<item-slug>.md`. That session's `## Execution` pointer carries plan → commit → `task:code-reviewer` on its own (`## Executing a task` step 4), and the reviewer ticks the roadmap checkbox once its review passes — nothing further to do per item.
→ Next: run `/task:to-task <slug>#<N>` for the first unchecked item.
```

## Output

- **No driver return** — the Workflow call errored or was interrupted before the driver returned, so there is no headline. Quote the tool's error verbatim, print the `Commits:` range below from the recorded start `HEAD` (the run may have committed before it died), and close with `→ Next:` either resuming through `resumeFromRunId` in this same session (see Step 2's rerun / resume) or a plain rerun of `/task:roadmap-to-workflow <slug>`. Skip the `Ran` line: its `<K>` counts `#N` lines of a return that does not exist. The bullets below assume a return.
- The driver's return value, surfaced as-is. Its **first line is the headline** — `roadmap-to-workflow: all items shipped.` or `roadmap-to-workflow stopped in wave <W> …: <failing digest>` — and it alone decides done versus stopped. Below it comes one line per item that landed (reviewed **and** ticked), in landing order, on a stop too: `#N <item-slug> — <implement summary>; review: <review summary>`. The per-stage digest lines (`OK|FAIL #N <item-slug> <summary>`) went to the Workflow progress view as the run went; they are not repeated in the return value.
- **One run-summary line above the footer, in both outcomes** — after an unattended run, nobody should have to count `OK` lines to learn how much landed. `<K>` is the number of `#N` lines under the headline:

  ```
  Ran `<slug>`: <K> of <M> items landed and ticked, <R> still unchecked. Commits: <first-sha>..<last-sha>.
  ```

  The driver's return carries none of the numbers past `<K>`, so take them from the tree and the roadmap:
  - `<M>` is the count of item lines Step 1 reported, before the run.
  - `<R>` is the count of item lines a second `bash "${CLAUDE_PLUGIN_ROOT}/skills/_lib/roadmap-items.sh" "<slug>"` prints after the run — the roadmap file is the truth about what is still unchecked, an item reviewed but not ticked included. If that call exits 1, use `<M> − <K>`.
  - `Commits:` comes from the `HEAD` recorded before Step 2's Workflow call: `git log --oneline <start>..HEAD` lists every commit the run made, implement commits and reviewer fix commits alike. When nothing was recorded because the repository had no commit yet, every commit is the run's: take the range from `git log --oneline HEAD`, and print `Commits: none` when `HEAD` is still unborn after the run. Print the oldest and newest as `<first-sha>..<last-sha>` (a single commit: just its sha). An empty range — a stop before anything was committed, `<K>` = 0 — prints `Commits: none`. A stop can leave commits from the failing item in the range too; the range is what `git log` shows, not only the `#N` lines.

- End with the canonical next-step footer (convention (a), flag-free):
  - All items shipped, `<R>` = 0 → `→ Done. Roadmap complete — \`.task/roadmap/<slug>.md\` fully checked; review the landed commits with \`git log\`.`
  - All items shipped, `<R>` > 0 — the headline speaks for the run's scope (Only next wave, or a picked range), not the roadmap → `→ Next: \`/task:roadmap-to-workflow <slug>\` to run the remaining <R> item(s)`. Never say "Roadmap complete" while `<R>` is above 0.
  - Stopped in **planning** — the headline says `(planning)` → no implement of that wave ran, so none of its work is in the tree, and there may be no `<item-slug>`: do not invent one. Relay the headline's own remedy when it names one (the duplicate-slug stop says to give one of the two items a more distinct title), else "edit the item in `.task/roadmap/<slug>.md`": `Stopped in wave <W> while planning #<N>: nothing of that wave was implemented. → Next: <the headline's remedy, or edit #<N> in \`.task/roadmap/<slug>.md\`>, then rerun \`/task:roadmap-to-workflow <slug>\`.`
  - Stopped on the **tick** — the headline ends by telling you to tick `#<N>` "by hand, then rerun", or says `never reported MARK-OK` → the item's reviewed work is committed and only its checkbox is behind, so re-planning it would re-implement work that already landed: `Stopped at #<N> <item-slug> in wave <W>: its review passed and its work is committed, but the checkbox was not flipped. → Next: tick #<N> in \`.task/roadmap/<slug>.md\` by hand if it is still unchecked, then rerun \`/task:roadmap-to-workflow <slug>\`.`
  - Stopped because the implementation **was never committed** — the headline says `implementation never committed` → `Stopped at #<N> <item-slug> in wave <W>: its work is in the working tree, uncommitted. → Next: commit it (\`git status\` shows what), tick #<N> in \`.task/roadmap/<slug>.md\` by hand, then rerun \`/task:roadmap-to-workflow <slug>\`.`
  - Stopped on any other `FAIL` in an implement or review stage → surface the failing digest, then say **where** it stopped and **what state the tree is in**: `Stopped at #<N> <item-slug> in wave <W>. Its work is left in the working tree — inspect it with \`git status\` and \`git log --oneline -3\`. → Next: fix #<N> by hand and tick it, or edit the item in \`.task/roadmap/<slug>.md\` so the rerun re-plans it from the new text, then rerun \`/task:roadmap-to-workflow <slug>\` — already-ticked items stay ticked, only the unchecked remainder reruns.` Never suggest re-planning it with `to-task` before the rerun: the rerun's plan agent regenerates an unchecked item's task file from the roadmap, and that plan would be lost.

## Forbidden

- Running setup on a missing `.task/CLAUDE.md`. This skill hard-stops and redirects; only the three capture skills (`to-task`, `to-roadmap`, `to-spec`) are intake-capable.
- Looping the items yourself in this session's thread, or authoring a Workflow script inline via the `script` input. The shipped driver is what gives each item fresh context, per-item model control, parallel planning and the serial review that ticks each item; a hand-rolled loop or a re-authored copy drifts from it — including when the Workflow tool is unavailable, which is a hard stop, not a cue to loop the items yourself.
- Reaching the driver by path instead of by its registered name. The Workflow tool checks a `scriptPath` for read permission against this session's working directory, and a plugin's own directory is never inside it — so the run dies before the first agent, everywhere except a checkout of the plugin itself. A name that does not resolve gets the hard-stop above, never a path retry.
- Modifying project code or any file yourself — including the roadmap. Implementation happens in the per-item agents, review fixes and the checkbox flip in the review agent.

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.