Generate sprints
Phase 2.5 — Sprint synthesis. Takes the approved Tech Spec and the ratified Acceptance Criteria for the active slug, synthesizes a task list whose entries realize the Acceptance Criteria's User Stories (US-NNN), partitions the tasks into sprints with explicit delivery objectives and binary DoD, and writes the runtime sprint bundles at `.yoke/sprints/<slug>-s<NN>.md` via `templates/sprint.md`. The skill is the single Phase 2.5 producer of sprint runtime bundles; the legacy `/yoke:tech-spec` stage 3 producer is retired in Sprint 4 of the parent PRD. After the bundle render stage, the skill renders the shared approval menu (`templates/approval-menu.md`) — Trigger 2.5 — and on `approve` / `approve_and_continue` flips every produced sprint file's frontmatter `status: draft` → `status: approved` atomically.From its SKILL.md
npx -y skills add iurykrieger/claude-yoke --skill generate-sprintsAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
24.4 KB, as published. Nobody here has run it
/yoke:generate-sprints — Phase 2.5 (Sprint synthesis)
Synthesize sprint runtime bundles from the approved
(spec, acceptance-criteria) pair for the active task. The skill is
the Phase 2.5 producer; it sits between Phase 3 (Acceptance Criteria
ratification) and Phase 4 (/yoke:implement's council protocol).
Status (Sprint 03 of parent PRD). Stages 1–6 are now bodied. The skill walks pre-flight, reads the inputs, runs the LLM-driven synthesis bracketed by deterministic shell+python validators, partitions the resulting task list into sprints (deterministic), renders one runtime bundle per partition entry via
templates/sprint.md, and renders the Trigger 2.5 approval menu. Sprint 04 of the parent PRD adds the legacy-task rejection branch, the cutover of/yoke:tech-spec(stage 2 + 3 strip), and the wiring with/yoke:statusand/yoke:implement.
Lineage
skills/generate-sprints/ is native to Yoke — there is no upstream
lineage. The skill was introduced in the parent PRD
.yoke/prds/2026-05-03-generate-sprints-skill.md (approved
2026-05-03) to decouple sprint generation from the architectural lens
of /yoke:tech-spec and from the use-case-catalog lens of
/yoke:acceptance-criteria. The decision to introduce a dedicated
producer is recorded inline in the parent PRD's "Goals" and "Product
invariants" sections; the doctrine entry
concepts/yoke-pattern-sprint-synthesis is staged in the parent
spec's Sprint 04 canonize-handoff packet.
Your role (Senior Engineer persona, inline)
You are running this skill as the Senior Engineer persona: a technical lead who synthesizes shippable sprint plans from a binding Acceptance-Criteria envelope and an architecture spec. You do not relax the Acceptance-Criteria envelope (Trigger 3 already bound it); you partition it into sprints whose tasks each realize one or more US-NNN entries, respect one or more architecture decisions from the spec, and ship a coherent value increment per sprint.
You force every produced task to be self-contained enough that any of
the council personas (Sr Eng, Sr QA, Sr Staff) can execute its lens
with no follow-up reads beyond the cited US-NNN and the cited sensors.
You refuse per-persona forks inside a task body (decision 5A of the
parent PRD); you refuse inlined criterion bodies inside the produced
sprint files (reference-by-ID per
concepts/yoke-pattern-sprint-runtime-bundle Rule 1); you refuse
non-deterministic output (FR-3 of the binding AC).
Process
The skill is a blueprint wrapping agentic nodes: the synthesis stage is LLM-driven, every other stage is deterministic Bash.
1. Pre-flight
Run five sequential gate checks. Each check that fails exits the
skill non-zero with a wm:-prefixed stderr line naming the offending
path and the next-step the user should take. The diagnostics are
exact strings — they're asserted character-for-character in
tests/smoke/generate-sprints-preflight.test.sh.
Steps, in order:
-
Provider hard break. Source
<plugin_dir>/lib/yoke-prelude.shand callyoke_require_provider. The helper aborts non-zero with stderrwm: <abs_path> not found. Run /yoke:bootstrap to initialize this project.(rc=2) when.yoke/config.yamlis missing, orwm: canonical_memory.provider not configured. Run /yoke:bootstrap to migrate.(rc=1) when the provider key is missing/empty. Surface the helper's stderr verbatim and exit. (Realises AC-003-1 branchno-configandno-provider; FR-6 of the parent PRD.)source <plugin_dir>/lib/yoke-prelude.sh yoke_require_provider || exit 1 -
Active slug. Source
<plugin_dir>/lib/working-memory/paths.shand resolve the slug viawm_active_slug. The helper aborts non-zero with stderrwm: no active task; run \/yoke:discover` firstwhen.yoke/runtime/.currentis missing. (Realises AC-003-1 branchno-slug`.)source <plugin_dir>/lib/working-memory/paths.sh slug="$(wm_active_slug)" || exit 1 -
Approved Phase-1 artifact. Source
<plugin_dir>/lib/working-memory/check-approved.shand callwm_check_phase1_approved "$(wm_phase1_artifact_path "$slug")". The resolver returns whichever Phase-1 artifact backs the slug (.yoke/prds/<slug>.mdfor/yoke:discover-authored PRDs,.yoke/fixes/<slug>.mdfor/yoke:fix-authored fix-specs); it hard-aborts non-zero with the structured FR-9 recovery diagnostic when both archives exist for the same slug (PRD FR-9 / AC-004-1) and when neither exists ("Run/yoke:discoveror/yoke:fixfirst."). The approval helper aborts non-zero with stderrwm: Phase-1 artifact missing or unapproved at <path>. Run /yoke:discover or /yoke:fix first.when the resolved file's> Status:line is neitherapprovednorratified. The artifact is read as opaque Phase-1 input —/yoke:generate-sprintsdoes not branch its core logic on PRD-vs-fix-spec identity. -
Approved Spec. Call
wm_check_spec_approved "$(wm_spec_path "$slug")". The helper aborts non-zero with stderrwm: spec missing or unapproved at <path>. Run /yoke:tech-spec first.when the file is missing or its> Status:line is notapproved. (Realises AC-003-1 branchunapproved-spec; FR-7 of the parent PRD.) -
Ratified Acceptance Criteria. Call
wm_check_ac_ratified "$(wm_acceptance_criteria_path "$slug")". The helper aborts non-zero with stderrwm: acceptance-criteria missing or un-ratified at <path>. Run /yoke:acceptance-criteria first.when the file is missing or its> Status:line is notratified. (Realises AC-003-1 branchun-ratified-AC; FR-7 of the parent PRD.) The Acceptance-Criteria status isratified(Trigger 3 ratifies);approvedis the spec / PRD status — do not conflate the two.
After gate (3) (Approved PRD) but BEFORE gate (4) (Approved Spec) and
gate (5) (Ratified Acceptance Criteria), run the legacy-task
rejection branch. Per Decision 6A of the parent PRD
(.yoke/prds/2026-05-03-generate-sprints-skill.md), legacy tasks
emitted by the legacy /yoke:tech-spec stage 3 MUST NOT be migrated
automatically — /yoke:generate-sprints rejects them and leaves
their sprint files untouched. The detection rule is two-pronged:
- If
.yoke/acceptance-contracts/<slug>.mdexists, the task is legacy (the legacy ratified envelope lives under that path; the post-rename canonical envelope lives under.yoke/acceptance-criteria/<slug>.md). - Or, if
.yoke/sprints/<slug>-s*.mdfiles already exist with frontmattertraceabilitylacking the new-flow marker (the semicolon-separated AC path containing the substringacceptance-criteria/<slug>.md), the task is legacy (sprint files emitted by the legacy stage 3 cite only the spec).
On legacy detection, abort non-zero with the literal stderr below
and exit cleanly. Do NOT touch any file under .yoke/sprints/.
The legacy-coexistence guarantee in FR-15 binds: legacy tasks keep
walking under /yoke:implement unmodified.
wm: legacy task — generate-sprints does not migrate
The detection rule is encapsulated in
lib/generate-sprints/legacy-detect.sh :: legacy_detect, which the
SKILL body invokes inline:
# legacy-task rejection (Decision 6A; PRD §"User Stories :: US-007").
# concepts/yoke-pattern-memory-model — legacy archive coexistence is
# permanent; in-flight legacy tasks are never auto-migrated.
source <plugin_dir>/lib/generate-sprints/legacy-detect.sh
legacy_detect "$slug" || exit 1
The helper exits non-zero with the literal stderr line above on
either prong of the detection rule and never touches any file under
.yoke/sprints/. Callers should run with set -euo pipefail so the
short-circuit propagates.
After the legacy-task rejection passes, source
<plugin_dir>/lib/generate-sprints/plan-io.sh and call
init_plan_file "$slug". This writes the empty plan stub at
.yoke/runtime/.generate-sprints-plan.yaml with top-level keys
slug, generated_at, tasks: [], sprint_partition: []. Then
call ensure_plan_tmp_dir to scaffold the parser-output scratch
directory at .yoke/runtime/.generate-sprints-tmp/.
2. Read inputs
Source <plugin_dir>/lib/generate-sprints/parse-inputs.sh and run
both helpers, redirecting their stdout into the scratch directory:
source <plugin_dir>/lib/generate-sprints/parse-inputs.sh
ac_path="$(wm_acceptance_criteria_path "$slug")"
spec_path="$(wm_spec_path "$slug")"
parse_acceptance_criteria "$ac_path" \
> .yoke/runtime/.generate-sprints-tmp/ac.json
parse_spec_architecture "$spec_path" \
> .yoke/runtime/.generate-sprints-tmp/spec.json
The AC parser emits a JSON object whose top-level keys are
user_stories (array of US-NNN entries with id, title, story,
dod, acceptance_criteria), functional_requirements (array of
FR-N entries with id, text), and sensor_pool (flat list of
sensor IDs from ## Sensor pool). The spec parser emits an object
with objective, contracts, and dependencies. Both helpers exit
non-zero with wm:-prefixed stderr on parse failure (missing input,
legacy UC-N shape, malformed US block missing DoD or Acceptance
Criteria).
3. Synthesis
The skill's primary agentic node — bracketed by deterministic bash on both sides. Inputs to the synthesis prompt:
- The JSON emitted by
parse_acceptance_criteria(Sprint 02 helper), at.yoke/runtime/.generate-sprints-tmp/ac.json. - The JSON emitted by
parse_spec_architecture, at.yoke/runtime/.generate-sprints-tmp/spec.json. - Optional canonical-memory hits — when a User Story names an
existing pattern / decision / convention, invoke
/yoke:search-canonical-memoryvia theSkilltool with a narrowly-scoped query (≤ 15 entity reads, one wikilink hop per the progressive-disclosure invariant). Log each invocation once to.yoke/runtime/progress.mdas asearch:event (per FR-12 of the parent PRD; AC-004-4 of the binding AC).
Pre-flight the inputs. Before invoking the LLM step, run the deterministic validator that asserts both intermediates carry the expected top-level shape:
source <plugin_dir>/lib/generate-sprints/synthesize.sh
synthesize_validate_inputs \
.yoke/runtime/.generate-sprints-tmp/ac.json \
.yoke/runtime/.generate-sprints-tmp/spec.json \
|| exit 1
The helper exits non-zero with wm:-prefixed stderr on shape
violations (AC has no user_stories, US block missing dod, spec
missing objective, etc.).
Run the LLM synthesis. Compose a prompt that carries the two JSON intermediates verbatim plus the following hard requirements:
- Output is a JSON array of tasks (no prose wrapper, no Markdown fences).
- Every task object has the keys
{task_id, realizes_user_stories, applies_decisions, instructions, sensors, acceptance_criterion}(+ optionalstory,validation,technical_implementationprojection hints consumed by the render stage). task_idis a placeholder of the formT-<n>(zero-padded per-arrival ordinal); the partition stage assigns final<slug>-s<NN>-t<MM>ids.realizes_user_storiesis a non-empty array whose entries match^US-[0-9]{3}$.instructionsis a single unified block readable by Sr Eng / Sr QA / Sr Staff — no per-persona forks like**For Sr Eng:**(forbidden by FR-1 of the binding AC; the validator below greps for the pattern and aborts).- Every US in the input AC's
user_storiesarray MUST appear in ≥ 1 task'srealizes_user_stories(US-coverage invariant).
Persist the LLM's output to
.yoke/runtime/.generate-sprints-tmp/tasks.json (the file is
gitignored under the same .yoke/runtime/.generate-sprints-tmp/
scratch dir).
Post-flight the LLM output. Validate the tasks JSON, enforce the
US-coverage invariant, then merge into the plan via
synthesize_write_tasks:
synthesize_write_tasks \
.yoke/runtime/.generate-sprints-plan.yaml \
.yoke/runtime/.generate-sprints-tmp/tasks.json \
.yoke/runtime/.generate-sprints-tmp/ac.json \
|| exit 1
The helper:
- Validates each task's schema (placeholder
task_idmatches^T-[0-9]+$; non-emptyrealizes_user_stories; non-emptyinstructionsandacceptance_criterion). - Rejects per-persona forks in
instructions(FR-1 enforcement). - Enforces US-coverage by computing
(AC user stories) - (realised user stories); if non-empty, exits non-zero with stderrwm: unrealized USs: US-NNN[, US-MMM]. - Sorts the merged tasks by placeholder ordinal so the plan's
tasksarray is stable regardless of LLM emission order. - Rewrites
.yoke/runtime/.generate-sprints-plan.yamlwith the merged tasks via PyYAML'ssafe_dump(deterministic serialisation; matchespartition.sh's policy).
4. Partition
Pure deterministic — zero LLM. Implementation lives in
lib/generate-sprints/partition.sh :: partition_tasks.
source <plugin_dir>/lib/generate-sprints/partition.sh
partition_tasks .yoke/runtime/.generate-sprints-plan.yaml || exit 1
The helper:
- Reads
.yoke/runtime/.generate-sprints-plan.yaml :: tasks. - Builds the overlap graph — two tasks share an edge when they
share ≥ 2 entries from their
applies_decisionslists. Connected components become candidate sprints. - Caps each component at 8 tasks (AC-005-5 upper bound). When a
component exceeds the cap, splits into chunks of 8 ordered by
acceptance_criterionlexical clustering with placeholder-ordinal tie-break. - Orders sprints across the partition by their first task's placeholder ordinal so re-runs converge.
- For each resulting sprint, computes
delivery_objective(concatenated realised US ids + dominant spec anchor) anddod(one entry per task, formatted as<final-task-id>: <acceptance_criterion>). - Assigns final task ids
<slug>-s<NN>-t<MM>in walk order. - Rewrites every task's placeholder
task_idto the final id and re-orders the plan'stasksarray to match the partition walk order; populatessprint_partition. - Re-serialises the plan via PyYAML (deterministic output across runs — FR-3 / AC-005-2).
5. Render
Pure deterministic — zero LLM. Implementation lives in
lib/generate-sprints/render-bundle.sh :: render_sprint_bundle. The
helper performs the four placeholder substitutions on
templates/sprint.md (<slug>, <NN>, <N>, <iso8601>), rewrites
the frontmatter (status: draft, traceability: ".yoke/specs/<slug>.md; .yoke/acceptance-criteria/<slug>.md",
Migrated-from: []), and fills the five body sections from the
partition data:
- Sprint objective — from
delivery_objective. - Sprint DoD — from
dod(one bullet per task). - Tasks — one
### Task <ID>per task, four inline labels (**Story:**,**Technical implementation:**,**Validation:**,**Acceptance criterion:**), with(Realizes: US-NNN[, US-MMM])clause adjacent to the**Story:**line. The Story / Technical implementation / Validation projection consumes optionalstory,technical_implementation,validationkeys when the synthesis stage emitted them; otherwise it splits the unifiedinstructionsblock on paragraph boundaries (first paragraph → Story, last → Validation, remainder → Technical implementation). - Functional acceptance criteria — union of US-IDs realised by tasks in the sprint, deduplicated and sorted.
- Sensors — union of sensor IDs from the realised US tasks, deduplicated and sorted.
Iterate over every sprint_partition entry via the convenience
wrapper:
source <plugin_dir>/lib/working-memory/paths.sh
source <plugin_dir>/lib/generate-sprints/render-bundle.sh
render_all_bundles "$slug" .yoke/runtime/.generate-sprints-plan.yaml \
|| exit 1
The wrapper resolves each sprint number from the partition's
sprint_id field and calls render_sprint_bundle once per sprint.
Each rendered file is validated post-write: 5 H2 headings present
and ordered, otherwise the file is removed and the helper aborts
with wm: render shape violation at <path>: missing heading <name>
(or heading order broken at <name> for an out-of-order anchor).
This realises AC-005-1.
6. Trigger 2.5 — Sprint plan ratification
After all sprint files are rendered, render the shared approval menu
(templates/approval-menu.md) with the following inputs:
artifact_path:.yoke/runtime/.generate-sprints-plan.yaml(the plan is the artifact under review; the sprint files are derivatives the user inspects via the per-sprint summary block below).artifact_label:"Sprint plan".next_skill:/yoke:implement.language:<detected>(whatever the discovery / tech-spec dialogues resolved).binding_statement: empty string (Trigger 2.5 ratifies the partition, not the criteria; the binding envelope is owned by Trigger 3 which already ratified the AC).
Per-sprint summary (custom block rendered before the 4-option prompt) — list each produced sprint id with its delivery objective, in walk order:
### Produced sprint plan (N)
- <slug>-s01 — <delivery_objective> (.yoke/sprints/<slug>-s01.md)
- <slug>-s02 — <delivery_objective> (.yoke/sprints/<slug>-s02.md)
…
The list is built from wm_list_sprint_paths "$slug" (= positional
order via the s<NN> filename suffix) joined with the corresponding
sprint_partition[i].delivery_objective field of the plan.
The 4 verbs route as follows:
approve_and_continue— flip every produced sprint file's frontmatterstatus: draft→status: approvedatomically (one pass overwm_list_sprint_paths "$slug"rewriting in place via a python3 helper). Then chain into/yoke:implementvia theSkilltool. When theSkilltool is unavailable, fall back to the approval-menu template's documented Fallback rule (record approval and print the manual-advance instruction).approve— same status flip; do not chain.reject— after the secondaryyesconfirmation, delete every path returned bywm_list_sprint_paths "$slug"(plainrmper path) and exit cleanly. The plan file at.yoke/runtime/.generate-sprints-plan.yamlis preserved (audit trail).revise— print awm:-prefixed warning naming every sprint file that will be deleted plus the captured feedback; delete every sprint file viawm_list_sprint_paths; truncate the plan'stasksandsprint_partitionarrays back to empty (preservingslug+generated_atso the audit trail is continuous); re-run the Synthesis → Partition → Render cascade with the captured feedback prepended to the synthesis prompt as additional context; re-render the Trigger 2.5 menu.
The atomic status flip for approve / approve_and_continue is
implemented via:
for sprint_path in $(wm_list_sprint_paths "$slug"); do
python3 - "$sprint_path" <<'PY'
import sys, re
path = sys.argv[1]
with open(path, encoding="utf-8") as f:
body = f.read()
new_body, count = re.subn(
r"^status: draft$",
"status: approved",
body,
count=1,
flags=re.MULTILINE,
)
if count != 1:
print(f"wm: status flip failed at {path}: no 'status: draft' line", file=sys.stderr)
sys.exit(1)
with open(path, "w", encoding="utf-8") as f:
f.write(new_body)
PY
done
The sweep is best-effort atomic — the python step is single-line per
file and the loop fail-fast on any rc=1 (so a partial sweep aborts
before it touches the next file). The contract surface for AC-006-1
(PASS: approve flips status atomically) is the post-sweep
invariant: every produced sprint file's frontmatter carries
status: approved xor every produced sprint file's frontmatter
carries status: draft.
Pre-conditions
.yoke/config.yamlexists with a non-emptycanonical_memory.providerkey (v2.0.0 hard break)..yoke/runtime/.currentexists and points at a valid slug..yoke/prds/<slug>.mdexists with> Status: approved(orratified)..yoke/specs/<slug>.mdexists with> Status: approved..yoke/acceptance-criteria/<slug>.mdexists with> Status: ratified(Trigger 3 already ratified the criteria envelope).
Output contract
-
Plan file. The skill writes / mutates
.yoke/runtime/.generate-sprints-plan.yamlwith top-level keysslug,generated_at,tasks(populated by Synthesis), andsprint_partition(populated by Partition). The path is gitignored. -
Sprint runtime bundles. The skill emits one or more files at
.yoke/sprints/<slug>-s<NN>.mdconforming totemplates/sprint.md. Each file's frontmatter carriesstatus: draftuntil Trigger 2.5 approves; onapprove/approve_and_continue, the field flips tostatus: approvedatomically across every produced sprint file. Onreject(after secondary confirmation), every produced sprint file is deleted. -
Read-only artifacts. No file under
.yoke/specs/,.yoke/acceptance-criteria/, or.yoke/prds/is modified. The binding-AC envelope (Trigger 3) is preserved verbatim — drift between the produced plan and the AC envelope escalates Trigger 4 in/yoke:implement's council protocol, never an inline AC edit here.
Anti-patterns
-
Inlining criterion bodies inside sprint files. The
## Functional acceptance criteriaand## Sensorssections inside produced sprint files carry only IDs that resolve against.yoke/acceptance-criteria/<slug>.mdand.yoke/sensors/<id>.mdrespectively (Rule 1 ofconcepts/yoke-pattern-sprint-runtime-bundle). -
Per-persona forks inside a task body. Each task carries a single unified instruction block readable by all three council personas. Sub-sections like
**For Sr Eng:**,**For Sr QA:**, or**For Sr Staff:**are forbidden (decision 5A of the parent PRD; FR-1 of the binding AC). -
Modifying upstream artifacts. This skill is read-only against
.yoke/prds/,.yoke/specs/, and.yoke/acceptance-criteria/. Drift between the produced sprint plan and the binding AC envelope escalates Trigger 4 — never edit the AC inline. -
Non-deterministic partition output. Re-running the skill against an unchanged
(spec, acceptance-criteria)pair MUST converge to the same sprint partition modulo deterministic ordering (FR-3). Random ordering, timestamp-keyed task ids, or LLM-temperature drift in the partition stage is a defect. -
Auto-migrating legacy tasks. A legacy task (sprint files emitted by
/yoke:tech-specstage 3, no.yoke/acceptance-criteria/<slug>.mdpresent) is rejected on re-run with stderrwm: legacy task — generate-sprints does not migrate(decision 6A; AC-007-2 of the binding AC). Sprint 04 of the parent PRD implements the rejection branch.
See also
concepts/yoke-pattern-phase-flow— the six-phase flow envelope. This skill sits at Phase 2.5, between Phase 2 (Tech Spec) and Phase 3 (Acceptance Criteria ratification's downstream consumer).concepts/yoke-pattern-roles— the Senior Engineer persona contract this skill instantiates.concepts/yoke-pattern-human-triggers— Trigger 2.5 (Sprint plan ratification) is added by the parent PRD and amended into the doctrine entry via the Sprint 04 canonize-handoff packet.concepts/yoke-pattern-sprint-runtime-bundle— the binding shape of every produced sprint file (reference-by-ID, single working set per cycle, no inlined bodies).concepts/yoke-pattern-memory-model— Rule 5: runtime state (including.yoke/runtime/.generate-sprints-plan.yaml) is gitignored and never promoted to the versioned archive.- Parent PRD:
.yoke/prds/2026-05-03-generate-sprints-skill.md. - Parent Spec:
.yoke/specs/2026-05-03-generate-sprints-skill.md. - Binding Acceptance Criteria:
.yoke/acceptance-criteria/2026-05-03-generate-sprints-skill.md.