Developer Docs

The Planning Loop

The five Claude Code skills that shape a DevStride roadmap — Capabilities, Epics, Stories, and their dependency graph — before any code is written.

The Planning Loop

Before /ds-story or /ds-ultracode-build ever touch the repo, a DevStride roadmap has to exist: a Capability → Epic → Story hierarchy, wired into a real blocked_by/blocks dependency graph, dated so the Gantt renders as a clean cascade. Five Claude Code skills do that work — /ds-plan, /ds-comprehend-plan, /ds-insert-story, /ds-insert-defect, and /ds-rationalize-gantt.

Skills at a Glance

SkillArgument shapeEntry point or building blockWrites live data?
/ds-plan<parent-item> [description]Top-level entry point, run directly by a developerYes — after explicit sign-off
/ds-comprehend-plan<item-number> [focus question]Both — standalone research tool AND an internal building block other skills call firstNo — strictly read-only
/ds-insert-story[parent-item] <free-text description>Both — directly runnable AND the canonical capture path ds-story step 6.5 invokes when a build turns up untracked workYes
/ds-insert-defect[parent-item] <free-text description>Both — same dual role as /ds-insert-story, for bugsYes
/ds-rationalize-gantt<plan-root>Both — direct entry point after date drift AND invoked internally at the end of /ds-planYes — overwrites existing dates

/ds-plan

Drives a full Capability → Epic → Story hierarchy into existence under a parent item (a Module, Capability, or Epic). It is explicitly not a one-shot document generator — it's an interactive, loop-based discovery process. The payoff is a hierarchy specced to a depth ds-ultracode-build can execute unattended, with every Story wired into a real dependency chain so /ds-story can walk it end to end.

/ds-plan <parent-item> [description]

<parent-item> is a Module/Capability/Epic number (e.g. I10992), optionally followed by a short description of what's being planned. If omitted, the skill asks which item to plan under rather than guessing.

Entry point. A developer runs this directly to kick off planning for a new slice of the roadmap.

Safety and autonomy. The interactive Q&A, scope calls, and architecture judgment calls always happen in the main conversation with the user — never inside a fanned-out Workflow agent. /ds-plan orchestrates its heavy drafting via the Workflow tool at ultracode effort, but a Workflow script can't itself pause to ask a question, so the split is strict: humans decide, Workflow only drafts. If the user tries to skip the discovery loop ("just make something up," "you decide"), the skill pushes back once explicitly, then complies but labels every assumption it made. It requires an explicit "yes, build this" sign-off on the full Capability → Epic → Story shape before creating anything live, and a content review of the drafted specs before any create_item/add_relationship call. It also batches a heads-up into that same sign-off: the final step needs the Gantt's dependency auto-scheduler turned OFF, which can't be done via the API — the user has to flip it manually.

/ds-comprehend-plan

Recursively reads a plan's descriptions and comments, at every level, to build a grounded picture of what a Module/Capability/Epic actually contains, where it stands, and what its real (not just titled) intent is. Comments carry the "as-built" history and mid-flight decisions that descriptions often never get updated to reflect, so a description-only pass doesn't count as comprehension.

/ds-comprehend-plan <item-number> [focus question]

<item-number> is the plan root to comprehend (e.g. I10992), optionally followed by a focus question such as "what's left before webhook intake is done?" — the question sharpens the synthesis but never narrows what gets read.

Both an entry point and a building block. Run it standalone any time the question is "what's the state of X" — or let another skill call it internally: /ds-plan step 1 invokes it on the root to classify what already exists (empty root, partial plan, or shallow placeholders) before step 2's full multi-round discovery loop — not a single question, but a series of rounds across source material, scope boundaries, Capability/Epic breakdown, Story shape, sequencing, and risk areas. Its own doc also says to use it before /ds-insert-story, /ds-insert-defect, /ds-rationalize-gantt, or any surgical edit to a plan you don't already carry full context on.

Safety and autonomy. This is a strictly read-only research skill — it must never call create_item, update_item, add_relationship, or any other mutating MCP tool. That also means it needs no sign-off of its own; the caution belongs to whatever mutating skill consumes its output next. It reads more free-text, externally-authored content than any other /ds-* skill — every comment on every node of a plan tree — so it's the primary exposure point for prompt injection in this system: embedded instructions inside a description or comment are treated as untrusted data, never acted on, and flagged in the report if they appear.

/ds-insert-story

Inserts ONE new Story into a live roadmap, spliced into the dependency chain and dated so /ds-story picks it up next. Its position in the sequence is made to look native to the plan; its description stays an honest spec of the real work — never a fabricated "this was always planned" backstory.

/ds-insert-story [parent-item] <free-text description>

The parent item number (Module/Capability/Epic) can prefix or suffix the free-text description, e.g. I10992 add rate limiting to webhook intake or just add rate limiting to webhook intake if there's no ambiguity about which plan it belongs to.

Both an entry point and a building block. A developer can run it directly to splice in one more Story once a plan already exists. It is also the canonical capture path ds-story step 6.5 uses — after merge and the completion ritual, at the very tail of the per-story loop — to turn an untracked deferral surfaced during /ds-ultracode-build's adversarial review into a tracked, dependency-ordered item. /ds-ultracode-build itself never calls this skill; it only compiles the untracked-deferral list that /ds-story step 6.5 acts on afterward.

Safety and autonomy. Before wiring any blocked_by edge, the skill must confirm the Gantt auto-scheduler is OFF (a probe write + read-back, same check /ds-rationalize-gantt uses) — adding a dependency edge while it's on can silently overwrite live dates on downstream items. If it can't confirm the scheduler is off, it warns the user rather than wiring blind. What actually removes the current-next item from contention is the relationship splice itself — it becomes blocked_by the new item, independent of priority. Priority (an org-specific priorityId, resolved via get_workspace_context, not a comparable string) only matters for candidates other than that one: it's set to at least match the currently-next item's so the new Story doesn't lose a tie within the same date tier — but priority alone can't out-rank a still-open container that started earlier elsewhere in the plan, since the canonical selection sorts by container date first. Rather than assume the splice worked, the skill re-derives what /ds-story would actually pick next and tells the user plainly if some other earlier-dated container still wins. It explicitly does not re-rationalize the rest of the plan's dates — that's a separate, deliberate follow-up call to /ds-rationalize-gantt, not something this skill does on your behalf. It is a Gantt-grooming skill only: it does not run any part of the build loop.

/ds-insert-defect

Nearly identical to /ds-insert-story, but for bugs: it splices a new Defect into the dependency chain with an honest repro/root-cause description instead of a feature spec.

/ds-insert-defect [parent-item] <free-text description>

Same argument shape as /ds-insert-story — free text describing the defect, optionally anchored to a parent Module/Capability/Epic.

Both an entry point and a building block, with the same dual role as /ds-insert-story: directly runnable, and the canonical capture path ds-story step 6.5 uses — after merge, not mid-build — when a defect surfaces during /ds-ultracode-build's adversarial review with no existing tracked home.

Safety and autonomy. All the same guardrails as /ds-insert-story apply — confirm the auto-scheduler is off before wiring, resolve and set priority via get_workspace_context, re-derive what /ds-story would actually pick next rather than assuming the splice worked, never fabricate history. It has one extra behavior /ds-insert-story doesn't: a defect often needs to jump ahead of already-planned Stories because it's blocking something real. The skill is explicit that this is not something to decide unilaterally — it states the case for queue-jumping and gets the user's explicit confirmation before splicing a defect earlier in the sequence than a plain "insert next" would.

/ds-rationalize-gantt

Backfills synthetic one-story-per-day dates and rationalizes the dependency graph of a plan so its Gantt renders as a maximally compressed, gapless, fully valid cascade. It assumes every Story takes exactly one day — the Claude Code build pace — so the result is a synthetic critical-path view, not a real-world forecast.

/ds-rationalize-gantt <plan-root>

<plan-root> is the item number whose descendant tree is the plan (a Solution/workstream/Epic, e.g. I10992), or a roadmap/Gantt name. Empty invocation prompts the user for which plan to rationalize.

Both an entry point and a building block. Run it directly any time a plan's dates have drifted, gone stale, or never reflected the real dependency graph. /ds-plan also invokes it internally as its final step, once the new hierarchy's dependency graph has been wired with zero orphan Stories.

Safety and autonomy. Disabling the Gantt's dependency auto-scheduler is treated as non-negotiable and comes first, before any mass write: when it's on, DevStride forward-reschedules every item with a blocked_by edge and overwrites the dates this skill just set — and there is no API flag to suppress it (staticMode only skips rank/event side effects, not date scheduling). The skill cannot toggle it itself; it has to ask the user to turn it off in the Gantt UI, then verifies the toggle actually took by writing a probe date to a dependent item and reading it back before proceeding. On the dependency-graph side, it treats every "red line" (invalid dependency) as a decision point rather than something to blindly offset — each violated edge gets reviewed and resolved as REMOVE, REPOINT, or a rare, deliberate KEEP-with-offset, and offsetting (which de-compresses the timeline) is called out to the user explicitly rather than applied silently.

How They Compose

Planning a new Epic from scratch

A developer runs /ds-plan I10992 under the parent Module or Capability. Internally, /ds-plan doesn't hand-roll a tree read — its first move is to invoke /ds-comprehend-plan on the root to learn what already exists (empty root, a partial plan to extend, or shallow placeholder items). That classification is followed by a full multi-round interactive discovery loop — source material, scope boundaries, Capability breakdown, Epic breakdown per Capability, Story shape, sequencing intent, and risk areas, asking as many rounds as it takes — that happens entirely in the main conversation; Workflow is only opened once the human has signed off on the shape, purely for bulk drafting of the full specs.

When it's time to actually create items, /ds-plan reuses the same create_item call patterns /ds-insert-story and /ds-insert-defect use — same field shape, same today-dated placeholder — but explicitly not their insert-before splice topology. Those two skills wire one item between an existing upstream and next item; /ds-plan is building a whole fan-out/fan-in graph, so its own step 5 owns that wiring, with a hard requirement that every new Story ends up with at least one blocked_by or blocks edge — zero orphans allowed. Once the graph is fully wired, /ds-plan finishes by invoking /ds-rationalize-gantt on the plan root to backfill dates and clean up any invalid-dependency lines the new items introduced, rather than computing cascade dates by hand.

Splicing in one more Story later

Once a plan already exists, adding a single piece of newly discovered work doesn't need a full /ds-plan pass. Running /ds-insert-story (or /ds-insert-defect for a bug) directly resolves the parent plan, identifies the item /ds-story would currently pick up next and what it was blocked by, and splices the new item in between with blocked_by/blocks edges — leaving the rest of the plan's dates untouched. This is the same mechanism /ds-story step 6.5 invokes automatically — after merge and the completion ritual — when /ds-ultracode-build's adversarial review turns up an untracked deferral or follow-up with no existing home; /ds-ultracode-build only compiles that list, it does not call these insert skills itself. If the plan's dates genuinely need re-compressing around the new item afterward, that's a separate, explicit call to /ds-rationalize-gantt — insertion and date rationalization are deliberately kept as two different actions, not bundled into one.

Gantt-Grooming, Not Code

Three of the five skills on this page — /ds-insert-story, /ds-insert-defect, and /ds-rationalize-gantt — are what their own definitions literally call Gantt-grooming skills: they change DevStride roadmap data and never touch the repo. /ds-plan and /ds-comprehend-plan don't use that specific term (and /ds-comprehend-plan is read-only, so "grooming" doesn't fit it anyway), but the same underlying fact holds across all five: none of them write code. If planning surfaces something that also needs code, that's a separate, later /ds-story (or /ds-ultracode-build) run against the Story these skills created — not something any of them do themselves.

Next Steps

  • The Delivery Loop — what happens once a Story exists: selecting it, building it, and shipping it