Skip to content
Skills Library
Programming · Automation

dev-workflow

/dev-workflow

Run the governed SDLC pipeline for a work item. USER-ENTRY — invoke only when the user explicitly runs /dev-workflow <work-item-id>; never trigger autonomously from conversation, and never from a subagent (guard-enforced).

Licence
MIT
Last repository change
27.08.2026

Assessment and security

100/ 100Class: good
Format25 / 25
Frontmatter with name and description, valid name, description up to 1,024 characters, name matching the folder.
Discoverability25 / 25
Description explains when to use the skill, has a reasonable length and uses third person.
Content35 / 35
At least 150 words and at most 500 lines, headings, step lists, examples or code.
Hygiene15 / 15
No placeholders such as TODO, no Windows paths, with a licence.
Riskno signals detected in the scan
Files in this package
34
Scripts
0
HTML comments
0
URLs in SKILL.md
0
Deprecation

No signals detected. Repository changed on 27.08.2026, without references to retired models or APIs.

Licence

MIT, open: use and modify while retaining author attribution.

What it does and when to use it

Run the governed SDLC pipeline for a work item. USER-ENTRY — invoke only when the user explicitly runs /dev-workflow <work-item-id>; never trigger autonomously from conversation, and never from a subagent (guard-enforced).

Original author description

Run the governed SDLC pipeline for a work item. USER-ENTRY — invoke only when the user explicitly runs /dev-workflow <work-item-id>; never trigger autonomously from conversation, and never from a subagent (guard-enforced).

How it works

  1. Startup
  2. The walk
  3. Cross-cutting rules
Original SKILL.md headings · 192 lines, 1,854 words
SKILL.md preview
---
name: dev-workflow
description: >
  Run the governed SDLC pipeline for a work item. USER-ENTRY — invoke only
  when the user explicitly runs /dev-workflow <work-item-id>; never trigger
  autonomously from conversation, and never from a subagent (guard-enforced).
---

# dev-workflow — the thin orchestrator walker

You are the **orchestrator**: a coordinator, not an implementer. You never
write code, never touch `ai/<run>/` authority files directly, and never run
raw `git commit|merge|rebase` — every mutation goes through `harness`
(guards block the raw paths and redirect you here).

Every command below runs through `${CLAUDE_PLUGIN_ROOT}/bin/harness` — a
wrapper script that resolves the plugin venv (created by /init-workspace,
either OS layout) and falls back to system `python3`/`python` pre-setup;
it runs under Git Bash on Windows too. `--workspace <ws>` and
`--run <run>` may go before or after the verb, in any mix — e.g. both
`harness --workspace <ws> --run <run> <verb> …` and
`harness <verb> --workspace <ws> --run <run> …` work. Always use the full
`${CLAUDE_PLUGIN_ROOT}` path; a bare `harness` is not on PATH, and shell
variables do not persist between separate Bash calls. Non-zero exit =
refused; read the JSON error.

## Startup

1. `${CLAUDE_PLUGIN_ROOT}/bin/harness fetch --id <work-item-id>` — refuses if bootstrap is incomplete
   (run `/init-workspace` first) or a live run already exists (offer the user
   **Resume or Abort** — never clobber). Abort is a real verb:
   `${CLAUDE_PLUGIN_ROOT}/bin/harness abort --run <run> --reason "<why>"` —
   terminal (mutations refuse from then on), sweeps worktrees, keeps the
   audit trail, and releases the work-item slot so a fresh fetch works.
   On success note `run`, `mode`.
2. The pipeline manifest (`${CLAUDE_PLUGIN_ROOT}/pipeline/manifest.yaml`) is
   the single source of truth for step order. Do not improvise steps.

## The walk

Loop until the mode's sequence is exhausted, then close the run:
`${CLAUDE_PLUGIN_ROOT}/bin/harness complete --run <run>` (terminal, the
successful sibling of abort — the final step's file says exactly when).

1. `${CLAUDE_PLUGIN_ROOT}/bin/harness show --run <run>` → current step, mode, tasks, gates.
   It also returns `next_steps` (the engine-legal cursor moves right now,
   the same `{step: reason}` set `cursor --to` validates against), `derived`
   (ledger-fresh `verdict_bound` outcomes that the persisted `state.artifacts`
   cache hasn't caught up to yet — e.g. a plan-review already APPROVED in the
   ledger shows `{"plan-review.outcome": "approved"}` here while `state` still
   reads `pending`), and `probe_error` (`null` normally; a non-null value is
   the engine's own reason there is no legal move yet — a seal-valid but
   malformed state, a `when` predicate needing an artifact this step still
   produces, or a corrupt ledger — so an empty `next_steps` is never mistaken
   for "wedged" (a fail-closed verdict window is NOT one of these: the walk
   completes and returns `{}` with `probe_error` null).
   These are a read-only compass, not a substitute for the step contract: the
   step file (2) remains the instruction authority for what to actually do.
2. Read the step's file: `${CLAUDE_PLUGIN_ROOT}/skills/dev-workflow/steps/<step>.md`
   — load ONE step file at a time (context economy). Gate steps all use
   `steps/gate.md`.
3. Execute it. Spawning a shape? The prompt MUST carry the structured headers
   (`harness-mode`, `harness-task`, `harness-run`, `harness-repo`,
   `harness-test-cmd`, `harness-plugin-root`). **Agent identity**: step text
   says "Spawn `reviewer`" — that's the shape word; pass the agent's
   frontmatter name (`ai-sdlc-reviewer`), not a generic agent. See
   `shared/spawn-identity.md` for the mapping and the reason a wrong
   identity silently disables governance. The spawn guard now BLOCKS a
   harness-headed spawn that uses a non-harness agent type. Enforcement, precisely: the spawn guard BLOCKS a
   harness-shape spawn missing `harness-mode`, and one missing
   `harness-run` whenever the spawn is legalized by a run's current step
   (the header must name THAT run). The remaining headers are capture
   conventions — `harness-task` attributes the token ledger and reviewer
   verdicts (a per-task review whose spawn omits it cannot satisfy the
   task's completion guard), `harness-repo`/`harness-test-cmd` scope the
   subagent's work, `harness-plugin-root` passes the resolved plugin
   install path (agents use it as `$PLUGIN_ROOT` to open instruction files
   and run `bin/harness` — the token must NOT be `${CLAUDE_PLUGIN_ROOT}`
   because Qwen's `templateString` scans agent bodies for braced tokens
   and rejects unknown keys at spawn). Before
   every spawn, resolve its model: `${CLAUDE_PLUGIN_ROOT}/bin/harness
   resolve-model --shape <shape> --mode <mode>` (per-mode ?? per-shape
   default ?? `inherit`, from `subagent_models`). Pass the result as the
   spawn's `model` param — unless it's the literal string `inherit`, in
   which case omit the `model` param entirely so the subagent runs on the
   session model. If the resolve-model result carries a `notice` key,
   relay its text to the user verbatim the FIRST time it appears in this
   run; it repeats on every resolve and needn't be repeated. **Background
   or foreground — both are captured:** where the Agent tool has
   `run_in_background`, `true` and `false` are equally legal; where it
   defaults spawns to background or has no such parameter, the spawn
   returns a launch STUB in place of the reply. On a stub: WAIT for its
   completion notification, do not proceed on the stub, and do not `stall`
   (`show`'s `outstanding_spawns` names every spawn still in flight — the
   Stalls triage below starts there, not at the events tail). Read the verdict from
   the LEDGER (`show`, or the cursor/task gate refusing) — never from reply
   text. One live spawn per (task, mode): the guard refuses a second while
   the first is unreported; different tasks and modes stay parallel, panel
   lenses (`plan-attack`) are exempt, and batching spawns in ONE message
   still runs them concurrently. `harness-task` must name a task the run
   registered — the guard blocks a typo at the spawn. Task dispatch in
   `develop` is DAG-DRIVEN, not lane-ordered: `ready-tasks` names every task
   whose `depends_on` is satisfied and they all go out together (steps/
   develop.md owns the loop).
4. Advance: `${CLAUDE_PLUGIN_ROOT}/bin/harness cursor --to <next> --run <run>`. If refused, you are
   off-manifest — re-read `show` and correct course; never force. A refusal
   that reports **waiting for the run lock**, or a `MergePreconditionError`
   naming this run's `ai/<run>` paths or feature branch, is not off-manifest
   at all: a sibling lane is mid-flight. Wait for its completion
   notification and re-run the IDENTICAL command — never stash, never
   hand-commit, never conclude a git operation the message did not name. If
   the refusal is `verdict_bound` (a reviewer verdict was not captured), the
   **only** sanctioned recovery is to re-spawn the reviewer for that mode
   — correct agent identity (`ai-sdlc-reviewer`), full headers, spawned per
   (3) — and let the hook capture it. Never write `reviews.ndjson` or
   any ledger directly, never synthesize a capture-hook payload (they are
   platform-fired; a synthetic payload forges evidence), and never force
   the cursor. If a second correctly-formed spawn still yields no verdict,
   stop and report to the user with the run path and what was attempted —
   a broken capture is a bug to surface, not to route around.

## Cross-cutting rules

- **Session cwd:** stay at the workspace ROOT — the prompt-capture hook
  defaults its workspace from cwd, so a bare `cd` into a repo silently
  drops gate evidence (field-proven). Use absolute paths / `git -C` /
  `(cd X && …)` subshells for repo work.
- **Gates:** always `gate --present`, show the artifact to the user verbatim,
  wait for their reply, then `gate --decide`. The decision is derived from
  captured human input — you cannot write it, only request the derivation.
  The reply must be a plain typed chat message (never AskUserQuestion —
  its answers bypass the capture hook and can never qualify). Refusals NAME
  their cause, and the remedies DIFFER: a STALE reply, or one typed in
  ANOTHER session, wants one more reply then `--decide` alone; re-present
  only where steps/gate.md says (ad-hoc route, or a confirmed-dead session).
- **Stalls:** a subagent that stops without a status block → `${CLAUDE_PLUGIN_ROOT}/bin/harness stall
  --task <T>` and follow the returned action (`reinvoke` → `recovery` →
  `human`). For a TASK-LESS spawn (plan-review, pre-pr, analyze-comments)
  omit `--task` — the stall counts per step, same bounds — except when the
  step file declares finer keys (plan-review counts each panel lens as
  `--task step:plan-review:<lens>`; the step file is the authority). NEVER
  commit or write on a stalled agent's behalf. **Verdicts live in
  `<run>/reviews.ndjson`; `<run>/events.ndjson` carries stall/hook/
  status-block events, never verdicts** — looking for a verdict in the wrong
  ledger is what makes a captured round read as a stall. Blockless reply?
  Ask `show` before calling `stall`: `outstanding_spawns` names every spawn
  still in flight as `{task, mode, agent_id, step, at, clearable,
  clearing_key}` — the owned answer to "which lane is wedged", so never
  hand-read the events ledger for it. Yours listed there → that subagent is
  still running in the background, WAIT for it; never stall — `stall`
  refuses over an open pending, and forcing it (`--confirm-no-verdict`)
  ABANDONS that spawn: its key is freed for a re-spawn and its reply, if it
  ever lands, is refused rather than captured. Three exceptions, in order:
  - **`clearable: false`** (a `repo-map` / `request-triage` pending — no
    step's spawn-set declares its mode, so no `stall` key matches it) →
    **leave it.** It refuses nothing and cannot wedge a run; it clears when
    that agent stops. Forcing a key here bumps a stall counter, writes no
    override, clears nothing, and degrades the run for a brand-new reason.
  - **`step` is not the cursor's** → the run has LEFT that step and nothing
    is coming. Abandon it with the key the entry hands you:
    `stall --task <clearing_key> --confirm-no-verdict`.
  - **`step` IS the cursor's, and siblings share it** — pipelined `develop`
    holds every lane at one step (the cursor cannot leave while any task is
    non-terminal), so a dead lane and a live one differ only in `at`.
    Compare ages: the OUTLIER — launched with the batch, still open long
    after its siblings reported — is the wedged lane. Age is evidence, not
    proof (a big task is slow, not dead), so name the lane and why, and get
    the user's go-ahead before `stall --task <its clearing_key>
    --confirm-no-verdict`.
  NOT listed → check `legacy_spawn_pendings` first: one listed there was
  launched by a pre-upgrade harness, its deferred capture is impossible, and
  the fix is to re-spawn that agent in the FOREGROUND — never stall it.
  Otherwise read the TAIL of `<run>/events.ndjson`: `status-block-malformed`
  → the verdict WAS captured despite the loose block, proceed on the ledger,
  never stall; `missing-status-block` → genuine stall, procedure above. For
  a task-less **step** key, `stall` refuses outright when that step's ledger
  already holds a verdict for the current round (`--confirm-no-verdict`
  overrides, for a spawn that stalled *after* the capture); per-task and
  per-lens keys are never refused — the engine reads no verdict for those.
- **Ad-hoc human requests mid-run:** spawn `reviewer` with
  `harness-mode: request-triage` (+ plugin-root header, always legal), surface the triage verdict
  to the user; out-of-scope items are never silently merged.
- **Publish:** the mirror snapshots the run's audit trail INTO a registered
  **project repo's** feature branch (so the governance record travels with
  the code in the PR) — never into the workspace, which isn't a git repo and
  isn't a mirror target. So it only makes sense once a repo has a feature
  branch, i.e. **after `preflight`**. Rules:
  - **Before preflight** (`fetch`/`confirm-repo`/`intake`/`plan`/
    `plan-review`/⟨approve-plan⟩/⟨approve-plan-lean⟩): there is no branch yet
    — **skip the mirror entirely**, don't guess a `--repo`.
  - **After preflight** (task completion, and each later gate crossing):
    mirror into **every preflighted repo** (the `branches` artifact in
    `show` lists them) — one call per repo:
    `${CLAUDE_PLUGIN_ROOT}/bin/harness publish-mirror --repo <preflighted-repo-path> --run <run>`.
  - It's best-effort/non-blocking: a repo that can't be committed to (no
    git, detached, etc.) just isn't mirrored — never block the run on it.
- **Status:** render progress with `${CLAUDE_PLUGIN_ROOT}/bin/harness show`; the ledgers
  (`events/tokens.ndjson`) are append-only — read, never write.
Files in this package (34)
  • SKILL.md 13 KB
  • shared/diagram-styling.md 3 KB
  • shared/engineering.md 1 KB
  • shared/spawn-identity.md 2 KB
  • shared/status-block.md 2 KB
  • steps/analyze-comments.md 2 KB
  • steps/apply-fixes.md 2 KB
  • steps/comment-analysis.md 1 KB
  • steps/confirm-repo.md 4 KB
  • steps/create-pr.md 2 KB
  • steps/develop-task.md 4 KB
  • steps/develop.md 11 KB
  • steps/fetch.md 3 KB
  • steps/fixup-task.md 1 KB
  • steps/gate.md 6 KB
  • steps/harden-task.md 1 KB
  • steps/harden.md 2 KB
  • steps/intake.md 4 KB
  • steps/metrics.md 1 KB
  • steps/plan-attack-task.md 3 KB
  • steps/plan-review-task.md 8 KB
  • steps/plan-review.md 8 KB
  • steps/plan-task.md 11 KB
  • steps/plan.md 11 KB
  • steps/pre-pr-fixes.md 1 KB
  • steps/pre-pr-review.md 1 KB
  • steps/pre-pr.md 1 KB
  • steps/preflight.md 5 KB
  • steps/quick-recheck.md 1 KB
  • steps/reconcile.md 1 KB
  • steps/repo-map-task.md 2 KB
  • steps/review-task.md 2 KB
  • steps/security.md 1 KB
  • steps/triage-request.md 1 KB

Versions

RepositoryScoreLicence
This page · mostashraf/ai-sdlc-harness100MIT
RichardDou0607/developer-mode100MIT
AsiaOstrich/universal-dev-standards95MIT
AsiaOstrich/universal-dev-standards95MIT
openflocon/flocon90MIT
sagargupta16/claude-skills90MIT
lflish/devflow90MIT
andreibesleaga/gabbe90CC-BY-4.0

Database snapshot: 13.11.2026 · package version 2183dd79e19a (SHA-256 digest of the entire package)

Downloads in the last 30 days: 0 · ranking

Report a problem with this skill: harmful content, incorrect descriptions or an author’s removal request.

Similar skills

  • 86workflow-status
    Read-only dashboard of ai-sdlc-harness runs in this workspace. USER-ENTRY — invoke only when the user explicitly runs /workflow-status; never autonomously, never from a subagent (guard-enforced).
  • 100init-workspace
    One-time workspace setup for the ai-sdlc-harness pipeline. USER-ENTRY and HUMAN-ONLY — invoke only when the user explicitly runs /init-workspace; never autonomously, never from a subagent (guard-enforced).
  • 100fix
    Explicit-use only — invoke when the user explicitly names this skill, or when an active explicitly invoked workflow calls it. Runs a test-first bug-fix lifecycle and then enters the explicitly requested SDLC workflow.
  • 100sdlc-auto
    Start an autonomous ("factory mode") SDLC run from a task description, external work-item reference, story path, or greenfield idea, on hosts that support skills but not custom slash commands. Trigger on "run autonomously", "factory mode", "ship this without asking", or a…
  • 96dev-reviewing-pull-request
    Use for /sdlc-review-pr: review a teammate's PR from its diff.
  • 100sdlc
    Run the autonomous SDLC pipeline on a task — the single entrypoint driving spec → review → build → test → security → delivery through the profile's quality gates. Use to run the SDLC or ship a feature.

Feedback and reports

Your message goes to Bartosz Sokoliński. An email address is needed only for a reply. See the privacy policy.