Skill 3 task gen
Task generation with dependency analysis — convert gap analysis into a structured task list with types (Green/Yellow/Red), dependencies, and deliverables. Use when the user says 'generate tasks', 'break down into tasks', 'create task list', or after /gap-scan.From its SKILL.md
npx -y skills add ezagent42/prd2impl --skill skill-3-task-genAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 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
26.1 KB, as published. Nobody here has run it
Skill 3: Task Generation
<SUBAGENT-STOP> If you were dispatched as a subagent to execute a specific task, skip this skill. </SUBAGENT-STOP>Convert gap analysis results into a structured task list with dependency graph, color classification, and verification criteria.
Trigger
- User runs
/task-gen - User says "generate tasks", "break down into tasks", "create task list"
- After
/gap-scanhas producedgap-analysis.yaml
Input
- Required (or B2 fallback):
{plans_dir}/*-gap-analysis.yaml(output from skill-2 or skill-0) — see §Step 1.5 B2 Degradation - Required (or B2 fallback):
{plans_dir}/*-prd-structure.yaml(output from skill-1 or skill-0) — see §Step 1.5 B2 Degradation - Optional (REQUIRED for B2 fallback mode):
{plans_dir}/*-task-hints.yaml(output from skill-0 only — see §Step 2.5) - Optional:
docs/plans/project.yaml(team configuration; always at project root) - Optional: Existing
{plans_dir}/tasks.yaml(for incremental updates — see docs/superpowers/specs/2026-04-20-plans-dir-scoping-design.md §8 Limitation 6 for status)
Execution Flow
Path resolution: Before constructing any output path, resolve
{plans_dir}perlib/plans-dir-resolver.md. Alldocs/plans/references below (exceptdocs/plans/project.yaml, which stays at repo root) are relative to that resolved directory.
Step 1: Load Gap Analysis
- Find the most recent
gap-analysis.yamlandprd-structure.yaml. Do NOT error on miss — if either file is absent, remember which is missing and proceed to §Step 1.5 to evaluate B2 degradation before emitting any error. - Also check for the most recent
task-hints.yaml— if found, load it (see §Step 2.5) - Group gaps by module (skip if
gap_analysiswas synthesized in §Step 1.5) - Sort by estimated effort and dependency chain
Step 1.5: B2 Degradation — task-hints-only mode
skill-3 can operate without prd-structure.yaml and/or gap-analysis.yaml provided task-hints.yaml is present and has a non-empty implementation_steps list. This unblocks the design-spec workflow where no gap-scan has run.
Trigger
At the end of Step 1 (Load Gap Analysis), check what was loaded:
- If
gap-analysis.yamlwas NOT found ANDtask-hints.yamlWAS found: synthesizegap_analysis = { gaps: [] }in memory. - If
prd-structure.yamlwas NOT found ANDtask-hints.yamlWAS found: synthesize a skeletonprd_structurein memory (see §Skeleton synthesis below). - If
task-hints.yamlwas NOT found ORimplementation_stepsis empty: do NOT synthesize — fall through to the original hard-error behavior of Step 1.
The synthesized structures are never written to disk — they exist only for the duration of this /task-gen invocation.
Skeleton synthesis
prd_structure:
source_type: "synthesized-from-task-hints"
source_role: "design-spec"
modules:
# One module per implementation_step entry
- id: MOD-01
name: "<step.description truncated to 60 chars>"
description: "<step.description (full)>"
prd_sections: []
sub_modules:
# One sub_module per file in step.touches_files
- id: MOD-01a
name: "<file basename>"
description: "<file path>"
user_stories: []
nfrs: []
constraints: []
external_deps: []
Sequential numbering: MOD-01, MOD-02, ... matching the step numbers. Sub-module suffix: MOD-01a, MOD-01b, ... per file within a step.
Task output marker
Every task emitted under B2 degradation MUST include:
tasks:
- id: T<phase><line>.<seq>
...
traceability: task-hints-only # NEW field — absent in normal mode
synthesized_module_id: MOD-NN # NEW field — links to skeleton module
Downstream skills (contract-check, retro) key off traceability: task-hints-only to skip checks that need real user_stories / constraints / external_deps.
User-facing warning
Before writing tasks.yaml, print:
─────────────────────────────────────────────────────
B2 degradation mode active
─────────────────────────────────────────────────────
Missing: {list of absent required files}
Synthesized {N} skeleton modules (MOD-01..MOD-{N}) from implementation_steps.
user_stories / nfrs / constraints / external_deps are empty — downstream
skills (contract-check, retro) will skip checks that depend on these fields.
Re-run /ingest-docs on a richer source document to upgrade.
─────────────────────────────────────────────────────
What does NOT change
- If all three input files are present → zero behavior change.
- Synthesized structures are NEVER persisted. Running
/ingest-docsafterward produces real files; this skeleton was only scaffolding for this/task-geninvocation.
Step 2: Generate Tasks
For each gap, generate one or more tasks:
Task ID Convention: T{Phase}{Line}.{Seq}
- Phase: 0-9 (milestone/phase number)
- Line: identifier from
project.yamlteam config (e.g.A,front,infra), orSfor shared/cross-line - Seq: sequential within phase+line
Classification Rules:
- Green (AI-independent): Pure code implementation with clear specs. No ambiguous design decisions. Has existing patterns to follow.
- Yellow (AI + human review): Involves prompt engineering, ML model selection, strategy design, or content that needs domain expert review.
- Red (human-driven): Requires stakeholder decisions, legal/compliance review, external API negotiations, or architecture trade-offs with no clear winner.
Auto color-promotion (0.4.0+): After applying the standard rules
above, run the auto-promote check. A task originally typed green is
promoted to yellow (and auto_promoted: true is set on the task)
when ANY of:
affects_files/deliverables[*].pathglob matches any of:**/auth*/**,**/permission*/**,**/login*,**/token*,**/credential***/*contract*,**/*protocol*,**/*schema*(excluding test files)
must_call_unchangedlist is non-emptymeta.connector_seam: true(already set by R15 / 0.3.1 connector-seam rule)env_var.class: A(security boundary)
When auto-promotion fires, set type: yellow and auto_promoted: true
on the generated task. Yellow handling proceeds as normal (review,
preflight, contract re-read).
Rationale: M3 retro batch-2 §🟢 finding "some Green tasks have hidden security surface that should go through review." The 14/14 reviewer-caught Critical bug rate in M3 confirms this is high ROI.
Task Structure:
tasks:
- id: T1A.1
name: "Mode/Gate minimal implementation"
description: "Implement state machine for conversation modes and gate transitions"
line: backend # Line identifier from project.yaml, or 'shared'
type: green # green | yellow | red
phase: P1
module: MOD-01
gap_ref: GAP-003 # Links to gap-analysis
story_refs: [US-005, US-006] # Links to PRD stories
depends_on: [T0.4]
blocked_by: [] # External blockers (not task deps)
deliverables:
- path: "autoservice/conversation_engine/mode_gate.py"
type: code # code | test | doc | config
- path: "tests/unit/test_mode_gate.py"
type: test
may_touch: # Files this task might modify beyond deliverables
- "autoservice/conversation_engine/__init__.py" # Add import
- "autoservice/config.yaml" # Add config entry
verification: "pytest tests/unit/test_mode_gate.py — all green"
estimated_effort: small # small (<2h) | medium (2-8h) | large (>8h)
status: pending
owner: null
artifacts: []
Step 2.5: Apply task-hints (only when task-hints.yaml is present)
Gate: Skip this entire step if no task-hints.yaml was found in Step 1. When absent, task generation is byte-identical to before this change was made.
When task-hints.yaml is present, FIRST check for the plan-passthrough short-circuit (Step 2.5.0). If it fires, the Behavior 1/2/3 logic below does NOT apply. Otherwise, apply the three behaviors that override defaults in Step 2.
Step 2.5.0 — Plan-passthrough mapping (Option B, coarse-grained — 0.4.1+)
Triggers when: task_hints.source_type == "ingested" AND task_hints.tasks[] is present and non-empty AND every entry in tasks[] carries a source_plan_path.
When triggered, use the plan-file mapping below INSTEAD of Behaviors 1/2/3 below. The legacy file_changes / implementation_steps logic remains the default for design-spec ingest and hand-written plans without the writing-plans header.
Emission rule — one task per plan FILE
Group task_hints.tasks[] by source_plan_path. For each unique plan-file group, emit exactly one prd2impl task to tasks.yaml:
- id: "{see ID rule}"
name: "{see name rule}"
type: green # default; see type-inference rule
phase: "{see phase rule}"
module: "" # plan itself is the module
source_plan_path: "{unique plan path for this group}"
source_plan_task_count: {count of entries in this group}
source_plan_step_count: {sum of len(steps) across the group}
deliverables:
# aggregated across all plan-tasks in the group, de-duplicated by path
- path: "{path}"
change_type: "create | modify"
verification:
- "All checkbox steps in {source_plan_path} are checked (executing-plans tick state)"
- "git diff vs base branch matches the plan's aggregated File Structure (see skill-10 Step 2.5)"
depends_on: [] # see dependency-inference rule
Note: prd2impl tasks emitted via Step 2.5.0 do NOT carry source_plan_anchor (no anchor — the whole plan is the unit). The per-plan-task anchors, files, and step counts stay in task-hints.yaml and are read directly by skill-9 / skill-10.
Aggregation rule for deliverables
For each unique source_plan_path:
- Union
files.createacross alltasks[]entries →change_type: create. - Union
files.modifyacross all entries →change_type: modify. - Union
files.testand merge intocreateif the test path is a new file undertests/, else intomodify. - De-duplicate by
path. If a file appears in both create and modify across different plan-tasks, prefercreate.
ID rule
Match the plan filename pattern \d{4}-\d{2}-\d{2}-(?:[a-z0-9-]+-)?p(\d+)([a-z]?)-.+\.md to extract the plan-letter:
*-p1-*.md→T1*-p2-*.md→T2*-p4a-*.md→T4A*-p4b-*.md→T4B*-p6a-*.md→T6A
If the filename does NOT match the p\d+[a-z]? pattern, fall back to TP{1-based ordinal of plan in input list} (e.g. TP3 for the 3rd plan).
Name rule
Use the plan's H1 with the trailing Implementation Plan stripped. Fall back to the filename stem (with date prefix stripped) if the H1 is missing or generic.
Phase rule
If project.yaml defines phases[], match the plan-letter to a phase (e.g. p1 → phase P1). If no match, set phase: "ingested".
Type-inference rule
Default: type: green. The granularity is now plan-level — most plans bundle a mix of green/yellow/red work. Default to green and let the user re-classify in tasks.yaml if needed. Exception: if the plan filename or H1 mentions design, policy, decision, architecture, default to red (these plans typically front-load design decisions).
Dependency-inference rule
For each emitted task, order by plan-letter (p1 < p2 < p3 < p4a < p4b < p5 < p6a < p6b — natural ordering by digit then letter suffix). Set depends_on: ["T{prev-plan-letter}"] if a prev plan was ingested in the same call. Sequential chaining is the safe default — the user edits tasks.yaml afterward for non-linear deps.
Print a hint at end of generation:
Cross-plan dependencies inferred sequentially (T2 depends on T1, T3 on T2, ...).
Review tasks.yaml depends_on if your plans have non-linear deps.
What is NOT done in plan-passthrough mode
- No
gap-analysis.yamlcross-referencing (writing-plans format does not carry GAP-NNN refs) - No NFR mapping (plans encode "how", not "what" — NFRs come from prd-structure)
- No intra-plan parallelism (executing-plans / subagent-driven-development runs plan-tasks sequentially within one plan; cross-plan parallelism still works via batch-dispatch)
- No batch packing (skill-4-plan-schedule does that)
When this step fires, skip Behaviors 1/2/3 below
The legacy file_changes / implementation_steps / non_goals logic is not applicable: writing-plans format doesn't use those fields. Continue to Step 2.6 (house conventions) after this step.
Branching note: the three Behaviors below run ONLY when Step 2.5.0 did NOT fire (i.e.,
task_hintscarries legacy file_changes / implementation_steps but notasks[]). For plan-passthrough hints, Step 2.5.0 fully replaces them.
Behavior 1 — Deliverables come from file_changes
Instead of inferring deliverable paths from gap descriptions:
- For each
task_hints.file_changesentry, create a deliverable. - Group
file_changesby theirrelated_gap_refs[0](primary gap ref). Allfile_changessharing the same primary gap → one task with multiple deliverables. - If a
file_changehas additionalrelated_gap_refsbeyond the first, store those ascross_referenceson the task (do not create duplicate deliverables). file_changeswith emptyrelated_gap_refs→ assign to a shared catch-all task; emit warning "orphan file_change assigned to shared task".
Behavior 2 — depends_on comes from implementation_steps
Instead of (or in addition to) dependency inference in Step 3:
- For each
task_hints.implementation_stepsentry:- Identify which task(s) own the files listed in
touches_files(matched via deliverables from Behavior 1). - For each
step.depends_on_stepsreference → find the tasks that own those step's files → add those tasks todepends_on.
- Identify which task(s) own the files listed in
- Cross-step dependencies take precedence over implicit inference; explicit gap
depends_on_gapsstill applies.
Behavior 3 — non_goals is a hard boundary
Before emitting any task, check each task.deliverables[*].path against task_hints.non_goals:
- Tokenize each non_goal string (split on spaces; strip punctuation).
- If any token appears in the deliverable path → reject the task; emit warning:
"task excluded per non_goal: '{non_goal}' matches '{path}'" - Rejected tasks are not written to
tasks.yaml; they are listed at the bottom of the summary.
Step 2.6: Inline house conventions into task context (0.4.0+)
Before emitting each task, read {plans_dir}/conventions.md (if
exists, written by skill-2-gap-scan Step 3.5). For each task whose
affects_files glob matches a file referenced by the conventions
cheat-sheet, inline the relevant conventions into the task's
context_block field:
- id: T-EXAMPLE.2
...
context_block: |
Project conventions for files touched here:
- IDs: secrets.token_urlsafe(36) (see autoservice/customer_manager.py:42)
- Timestamps: ISO 8601 (`datetime.utcnow().isoformat()`)
- Logger: `logger = logging.getLogger(__name__)` per module
- MCP servers: hook into cc_pool.py:691 auto-inject — DO NOT duplicate
Subagents in skill-8-batch-dispatch see this in their dispatch
prompt, eliminating the "reinvented ID format" and "reinvented MCP
bootstrap" failure modes.
When conventions.md is absent (skill-2 not run, or skill-2 missing
Step 3.5 from older 0.3.x install), skip silently — task generation
proceeds without the inlined block.
Step 3: Dependency Analysis
- Explicit dependencies: From gap_ref → gap.depends_on_gaps → task mapping
- Implicit dependencies (auto-inferred):
- If task A produces a file that task B imports → B depends on A
- If task A defines an interface that task B implements → B depends on A
- If task A is in phase N and task B is in phase N+1 of same module → likely dependency
- Cross-line dependencies: Frontend tasks depending on backend APIs
- Validate: No circular dependencies (topological sort check)
Generate dependency graph:
dependency_graph:
# Adjacency list: task → [tasks that depend on it]
T0.1: [T0.3, T0.4, T1A.4]
T0.2: [T0.3, T0.5, T0.6]
T0.4: [T0.5, T1A.1, T1A.2, T1A.3]
# ...
critical_path: [T0.1, T0.4, T1A.1, T2A.1, T3A.7, T4A.4, T5A.1]
critical_path_length: 7 # Longest chain
Step 3.N: Generate Test Requirements (0.7.0+)
For each non-Red task generated in the previous step, derive test_requirements
from the linked acceptance criteria.
Input sources:
gap_ref→ gap-analysis.yaml →gaps[].acceptance_criteriaorgaps[].expected_behaviorstory_refs→ prd-structure.yaml →user_stories[].acceptance_criteriamust_call_unchanged→ contract symbols (for integration layer)
Derivation logic:
For each task:
1. If task.type == "red":
- test_requirements: {} (empty, no test obligation)
- completion_criteria: { tests_pass_required: false, review_required: true, artifacts_required: [review_checklist] }
- SKIP remaining steps for this task
2. Resolve acceptance criteria:
a. For each story_ref in task.story_refs:
- Find user_story in prd-structure.yaml where id matches
- Extract acceptance_criteria list
b. If task.gap_ref:
- Find gap in gap-analysis.yaml where id matches
- Extract expected_behavior or acceptance_criteria
c. If neither source has criteria → test_requirements left empty, mark task with warning:
"⚠️ No acceptance criteria found for {task.id} — test_requirements will be stub.
Add acceptance criteria to prd-structure.yaml or gap-analysis.yaml and re-run /task-gen."
3. Generate unit test requirements:
For each acceptance criterion:
- description: Convert criterion into a testable assertion
- covers: [story_id, ac_id]
- expected_count: 1 (default); increase for multi-branch criteria
- status: active
- status_reason: null
- status_decided_by: auto
4. Generate integration test requirements:
For each contract_symbol in task.must_call_unchanged:
- description: "Verify {symbol} contract is not broken by this task"
- covers: [task.gap_ref]
- contract_symbols: [symbol]
- status: active
If task.meta.connector_seam == true:
- Generate integration test for producer→consumer data flow
5. Generate e2e test requirements:
- Single-module task with no cross-task dependencies → e2e: []
- Entry/exit point of dependency graph → mark for skill-4 E2E inclusion
6. Set completion_criteria defaults by task type:
Green: { tests_pass_required: true, review_required: false, artifacts_required: [eval_doc, test_plan, test_diff, e2e_report] }
Yellow: { tests_pass_required: true, review_required: true, artifacts_required: [test_plan, test_diff, e2e_report, review_checklist] }
Red: { tests_pass_required: false, review_required: true, artifacts_required: [review_checklist] }
7. Write test_requirements and completion_criteria to the task entry in tasks.yaml
Degradation handling:
If prd-structure.yaml or gap-analysis.yaml is unavailable or has no acceptance_criteria:
⚠️ TEST REQUIREMENTS DEGRADED — acceptance criteria source missing.
{missing_source} not found or has no acceptance_criteria.
test_requirements will be generated as stub (empty) for all tasks.
Tasks will fall back to legacy verification field for gating.
To restore: ensure prd-structure.yaml and gap-analysis.yaml have
acceptance_criteria fields, then re-run /task-gen.
Record in capability-profile.yaml:
degraded_paths:
- skill: skill-3
capability: test_requirements_generation
fallback: stub_test_requirements
reason: "{missing_source} not found or has no acceptance_criteria"
Step 4: Phase Assignment
Group tasks into phases/milestones based on:
- Dependency ordering (topological sort)
- Module cohesion (keep related tasks in same phase)
- Logical checkpoints (each phase should be independently verifiable)
phases:
- id: P0
name: "Contracts & Skeleton"
milestone: M0
tasks: [T0.1, T0.2, T0.3, T0.4, T0.5, T0.6]
gate: "All contract files frozen, skeleton code compiles"
- id: P1
name: "Core Features"
milestone: M1
tasks: [T1A.1, T1A.2, ..., T1B.1, T1B.2, ...]
gate: "End-to-end conversation flow works"
Step 5: Line Assignment
If project.yaml defines team lines, assign tasks:
- Check each task's module → which line owns that module (match module skills to line skills)
- Check deliverable file paths → which line's directory
- Cross-cutting tasks → assign to
sharedwith designated driver - If only 1 line defined → assign all tasks to that line (no splitting needed)
Step 6: Statistics & Warnings
Generate summary:
summary:
total_tasks: 75
by_type:
green: 48 (64%)
yellow: 18 (24%)
red: 9 (12%)
by_line:
# Dynamic — one entry per line from project.yaml
backend: 43
frontend: 29
shared: 3
by_phase:
P0: 6
P1: 17
P2: 12
# ...
critical_path_length: 7
estimated_duration: "3 days (with 2 parallel lines)"
warnings:
- "T3A.4 (Red) blocks 3 downstream tasks — start early"
- "P5 has 8 tasks depending on external zchat API (DEP-01)"
- "Line 'backend' has 48% more tasks than 'frontend' — consider rebalancing"
Step 7: Output
- Write
{plans_dir}/{date}-tasks.yaml(structured data) - Write
{plans_dir}/{date}-tasks.md(human-readable table format) - Write dependency graph as Mermaid in the markdown file
- Print summary to terminal
Step 8: Human Review Checkpoint
STOP here. Present task list and wait for user review.
Task generation complete. {N} tasks across {P} phases. Type split: {G} Green / {Y} Yellow / {R} Red Critical path: {CP} tasks deep
Review
{plans_dir}/{date}-tasks.yamland confirm:
- Task granularity — any too large (>8h) or too small (<30min)?
- Color classification — any Green that should be Yellow/Red?
- Dependencies — any missing or incorrect links?
- Phase grouping — any tasks in the wrong phase?
When ready, see the chain-hint footer below for next steps.
Task Granularity Guidelines
- Too large: If a task has >3 deliverables or touches >3 files in different modules → split
- Too small: If a task is <30 min of work with no interesting design → merge with related task
- Sweet spot: 1-4 hours of focused work, 1-2 deliverables, clear verification
- Red tasks: Can be larger (design docs, compliance reviews) since they're human-paced
Pipeline Integration Test Rule
When task decomposition splits a producer/consumer pair across separate tasks (e.g. one task implements a data emitter, a sibling task implements the consumer that filters/routes/displays it), the decomposition leaves a connector seam: each unit-tests cleanly in isolation, but a missing field or contract mismatch at the seam makes the whole pipeline silently inert in production.
When this applies
Detect connector seams by these signals during task generation:
- Two or more tasks share a
modulebut cover different stages of a data flow (one writes a field, another reads it) - A task's
gap_refsays "evaluate per-tenant" / "filter by X" / "route to Y" while a sibling task says "produce records of type X" — the producer must populate the field the consumer keys on - A task's
deliverablesproduce records consumed by another task'sdeliverables(cross-task data dependency, not just file-import dependency)
Required additional task
For every detected seam, append an integration task:
- id: T<phase><line>.<seq>
name: "Integration: {producer task} → {consumer task} pipeline"
type: green
module: <shared module>
description: "End-to-end test that exercises the full pipeline from {producer} through {consumer}, asserting the observable behavior at the consumer end (not just that each unit's tests pass)."
depends_on: [<producer task id>, <consumer task id>]
deliverables:
- path: "tests/integration/test_<feature>_pipeline.py"
type: test
verification: "Test fails if producer omits the connector field OR consumer ignores it OR the wire format drifts."
estimated_effort: small # usually 30-60min
meta:
connector_seam: true
connects: [<producer task id>, <consumer task id>]
Why this matters
M3 retro evidence (T2S.5 AlertEngine): producer task built FiredAlert records, consumer task added per-tenant push filter. Both tasks' unit tests passed. The producer never set tenant_id on the record — so the consumer's filter always short-circuited and the feature was dead in production despite 100% green tests. Reviewer caught it; integration test would have caught it earlier and cheaper.
Heuristic budget
Add at most one integration task per connector seam. Do not generate integration tasks for trivial seams where the producer and consumer share a single file and the unit tests already exercise the full path. The goal is catching cross-task data drift, not test inflation.
───────────────────────────────────────────────────── ⬆ /task-gen complete ─────────────────────────────────────────────────────
📋 Next: /plan-schedule — create batches and milestones /next-task — start working immediately ─────────────────────────────────────────────────────