Best for
- "What's the execution order for specs?"
- "What's blocking progress?"
- "Show me the dependency graph"
gmickel/flow-next/plugins/flow-next/codex/skills/flow-next-deps/SKILL.md
Show spec dependency graph and execution order. Use when asking 'what's blocking what', 'execution order', 'dependency graph', 'what order should specs run', 'critical path', 'which specs can run in parallel'.
Decision brief
Visualize spec dependencies, blocking chains, and execution phases.
Compatibility matrix
| Platform | Status | Evidence | What to check |
|---|---|---|---|
| Codex | Not declared | No explicit evidence | Portability before use |
| Claude Code | Not declared | No explicit evidence | Portability before use |
| Cursor | Not declared | No explicit evidence | Portability before use |
| Gemini CLI | Not declared | No explicit evidence | Portability before use |
Installation
The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.
npx skills add https://github.com/gmickel/flow-next --skill "plugins/flow-next/codex/skills/flow-next-deps"Inspect the Agent Skill "flow-next-deps" from https://github.com/gmickel/flow-next/blob/efe60be268df748bdfbfc546a38751f8cf26c912/plugins/flow-next/codex/skills/flow-next-deps/SKILL.md at commit efe60be268df748bdfbfc546a38751f8cf26c912. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.
Workflow
Review the “Setup” section in the pinned source before continuing.
Build a consolidated view of all specs with their dependencies — a single heavy per-spec loop for the whole skill. Steps 2 and 3 reuse the cached file (bash vars do not survive across prompt turns, so the cache is a file at a literal agent-composed path — compose once, e.g. 4 ra…
Determine which specs are ready vs blocked (pure jq, works on any shell):
SPECSFILE="${TMPDIR:-/tmp}/flow-deps-specs-.json"
Group specs into parallel execution phases:
Permission review
The documentation asks the agent to read local files, directories, or repositories.
# ONE gather — Steps 2 and 3 read this file; never re-run the per-spec loopThe documentation asks the agent to read local files, directories, or repositories.
The per-spec `flowctl show` loop has run exactly once for this invocation. **Steps 2 and 3 read that file.** A second run of the gather loop has broken this.Evidence record
| Signal | Value | Evidence type | Meaning |
|---|---|---|---|
| Quality score | 91/100 | Computed | Documentation, specificity, maintenance, and trust rules |
| Repository stars | 689 | Source | Repository attention, not individual Skill quality |
| Compatibility | 0 platforms | Source | Declared in the catalog source record |
| Usage guide | automated source guide | Editorial | Generated or reviewed according to the visible evidence level |
Pinned source
Visualize spec dependencies, blocking chains, and execution phases.
flowctl is bundled with the plugin (not on PATH). Define once; subsequent blocks use $FLOWCTL:
FLOWCTL="${CODEX_HOME:-$HOME/.codex}/scripts/flowctl"
[ -x "$FLOWCTL" ] || FLOWCTL="<plugin-root>/scripts/flowctl" # <plugin-root> = the directory two levels above this skill's SKILL.md file (the harness gave you that file's absolute path when the skill loaded); substitute it literally
[ -x "$FLOWCTL" ] || FLOWCTL=".flow/bin/flowctl"
$FLOWCTL detect --json | jq -e '.exists' >/dev/null && echo "OK: .flow/ exists" || echo "ERROR: run $FLOWCTL init"
command -v jq >/dev/null 2>&1 && echo "OK: jq installed" || echo "ERROR: brew install jq"
Build a consolidated view of all specs with their dependencies — a single heavy per-spec loop for the whole skill. Steps 2 and 3 reuse the cached file (bash vars do not survive across prompt turns, so the cache is a file at a literal agent-composed path — compose <suffix> once, e.g. 4 random chars, and reuse the same literal path in every later block):
# ONE gather — Steps 2 and 3 read this file; never re-run the per-spec loop
SPECS_FILE="${TMPDIR:-/tmp}/flow-deps-specs-<suffix>.json"
$FLOWCTL specs --json | jq -r '.specs[].id' | while read id; do
$FLOWCTL show "$id" --json | jq -c '{
id: .id,
title: .title,
status: .status,
plan_review: .plan_review_status,
deps: (.depends_on_epics // [])
}'
done | jq -s '.' > "$SPECS_FILE"
cat "$SPECS_FILE"
$SPECS_FILE exists at the composed literal path and parses as a JSON array with one object per spec returned by flowctl specs --json.flowctl show loop has run exactly once for this invocation. Steps 2 and 3 read that file. A second run of the gather loop has broken this.Determine which specs are ready vs blocked (pure jq, works on any shell):
# Reuse the Step 1 gather — same literal path, NO re-fetch (one heavy loop total)
SPECS_FILE="${TMPDIR:-/tmp}/flow-deps-specs-<suffix>.json"
# Compute blocking status
jq -r '
# Build status lookup
(map({(.id): .status}) | add // {}) as $status |
# Check each non-done spec
.[] | select(.status != "done") |
.id as $id | .title as $title |
# Find deps that are not done
([.deps[] | select($status[.] != "done")] | join(", ")) as $blocked_by |
if ($blocked_by | length) == 0 then
"READY: \($id) - \($title)"
else
"BLOCKED: \($id) - \($title) (by: \($blocked_by))"
end
' "$SPECS_FILE"
done spec in $SPECS_FILE emitted exactly one READY: or BLOCKED: line, and each BLOCKED: line names the specific deps holding it.flowctl show sweep.Group specs into parallel execution phases:
# Reuse the Step 1 gather — same literal path, NO re-fetch (one heavy loop total)
SPECS_FILE="${TMPDIR:-/tmp}/flow-deps-specs-<suffix>.json"
# Phase assignment algorithm (run in jq for reliability)
jq '
# Build status lookup
(map({(.id): .status}) | add // {}) as $status |
# Filter to non-done specs
[.[] | select(.status != "done")] as $open |
# Assign phases iteratively
reduce range(10) as $phase (
{assigned: [], result: [], open: $open};
.assigned as $assigned |
.open as $remaining |
# Find specs not yet assigned whose deps are all done or in earlier phases
([.open[] | select(
([.id] | inside($assigned) | not) and
((.deps // []) | all(. as $d | $status[$d] == "done" or ($assigned | index($d))))
)] | map(.id)) as $ready |
if ($ready | length) > 0 then
.result += [{phase: ($phase + 1), specs: [.open[] | select(.id | IN($ready[]))]}] |
.assigned += $ready
else . end
) |
# Emit the phases AND the residue: any open spec never assigned is UNRESOLVABLE — a
# dependency cycle (A→B→A), a dep on a missing/closed spec, or a chain deeper than 10.
# Dropping it silently is the one way /deps gives a WRONG answer (the graph it exists to
# expose hides the deadlock). Surface it, with the offending deps for diagnosis.
.assigned as $asg |
{ phases: .result,
deadlocked: [ $open[] | select(.id as $i | ($asg | index($i)) | not)
| { id, status,
unresolved_deps: [ (.deps // [])[] | select(. as $d | ($asg | index($d)) or ($status[$d] == "done") | not) ] } ] }
' "$SPECS_FILE"
.phases and .deadlocked, and every open spec appears in exactly one of them..phases and .deadlocked. Phases narrated from a reading of the spec titles have broken this.Present results as:
## Spec Dependency Graph
### Status Overview
| Spec | Title | Status | Dependencies | Blocked By |
|------|-------|--------|--------------|------------|
| **fn-1-add-auth** | Add Authentication | **READY** | - | - |
| fn-2-add-oauth | Add OAuth Login | blocked | fn-1-add-auth | fn-1-add-auth |
| fn-3-user-profile | User Profile Page | blocked | fn-1-add-auth, fn-2-add-oauth | fn-2-add-oauth |
### Execution Phases
Render from the jq result's `.phases`:
| Phase | Specs | Can Start |
|-------|-------|-----------|
| **1** | fn-1-add-auth | **NOW** |
| 2 | fn-2-add-oauth | After Phase 1 |
| 3 | fn-3-user-profile | After Phase 2 |
### ⚠️ Deadlocked / Unresolvable
**This section renders exactly when `.deadlocked` is non-empty** — and when it does, it is the
most important part of the report. Each entry is an open spec that could not be placed in
any phase: a dependency **cycle**, a dep on a **missing/closed** spec, or a chain deeper
than 10. These are invisible to `ready`/pilot (they just never become ready) — this is the
one place the graph surfaces them.
| Spec | Status | Unresolved deps | Likely cause |
|------|--------|-----------------|--------------|
| fn-7-x | blocked | fn-9-y | fn-9-y not found / closed, or a cycle fn-7↔fn-9 |
For each, state the likely cause: if two deadlocked specs list each other → **cycle** (fix
with `flowctl spec rm-dep`); if an unresolved dep isn't among the open specs → **missing or
closed dependency**. **Every entry of `.deadlocked` reaches the report.** A report that lists phases while silently dropping an open spec has broken this.
### Critical Path
fn-1-add-auth → fn-2-add-oauth → fn-3-user-profile (3 phases)
This skill is read-only inspection. Edge changes are reported as commands for the
operator to run — flowctl spec add-dep <spec> <dep> / rm-dep <spec> <dep>. A run that
executes either command itself, or edits a spec file, has broken this.
For a fast dependency check:
$FLOWCTL specs --json | jq -r '.specs[] | select(.status != "done") | "\(.id): \(.title) [\(.status)]"'
Frequently asked questions
Visualize spec dependencies, blocking chains, and execution phases.
The source record exposes this install command: npx skills add https://github.com/gmickel/flow-next --skill "plugins/flow-next/codex/skills/flow-next-deps". Inspect the command and pinned source before running it.
Static rules flagged read-files in the source; the page lists the matching lines and excerpts.
Alternatives