description: Decompose a project plan into numbered POML task files for systematic AI-assisted execution tags: [tasks, planning, project-structure, poml] techStack: [all] appliesTo: ["projects/*/plan.md", "create tasks", "decompose plan"] alwaysApply: false exemplar: projects/ai-procedure-quality-r1/tasks/ last-reviewed: 2026-07-16
task-create
Last Reviewed: 2026-05-17 Reviewed By: ai-procedure-quality-r1 (Phase 2b Wave 2c —
leave-alone-justifiedon body length per dereferencing-reliability concern; light extract: 3 worked Examples moved toexamples/examples.md) Exemplar rationale:projects/ai-procedure-quality-r1/tasks/is a recent multi-task project (32 tasks across 7 phases) produced by this skill — a live reference output. Justified length: procedural Workflow body kept inline. Task POML callers cite Step 3.5.5, 3.65, 3.8 — these step numbers are external API and stay in body. Examples moved toexamples/because they're reference content, not procedure.
Purpose
Transforms plan.md work breakdown structure (WBS) into individual, executable task files in the tasks/ directory. Each task is a valid POML/XML document (.poml extension) optimized for AI agent execution. This skill bridges planning (project-init) and implementation (task-execute).
When to Use
- After
project-inithas created plan.md with WBS phases - User says "create tasks", "decompose plan", or "generate task files"
- Explicitly invoked with
/task-create {project-name} - Plan.md exists but tasks/ directory is empty
Inputs Required
| Input | Required | Source |
|-------|----------|--------|
| Project path | Yes | Path to project in projects/ folder |
| plan.md | Yes | Auto-loaded from projects/{project-name}/plan.md |
| Task granularity | No | Default: "medium" (2-4 hours of work per task) |
Workflow
Step 1: Load Project Context
EXTRACT project-name from provided path
LOAD: projects/{project-name}/plan.md
LOAD: projects/{project-name}/README.md # For context
LOAD: .claude/templates/task-execution.template.md # POML SKELETON (pointer) — this skill's Steps 3.5.x–3.85 + Step 4 are the AUTHORITATIVE field set; the template mirrors them for copy-paste
EXTRACT from plan.md:
- WBS phases (Section 5)
- Dependencies (Section 6 if present)
- Risks/constraints (Section 7)
- Acceptance criteria (Section 8)
Step 2: Validate Plan Readiness
CHECK plan.md has:
✓ At least one WBS phase defined
✓ Each phase has deliverables or outcomes listed
✓ No "TBD" in critical sections
IF validation fails:
→ List missing elements
→ Offer to help complete plan.md first
→ STOP until plan is ready
Step 3: Decompose Phases into Tasks
FOR each WBS phase:
IDENTIFY discrete work items:
- Each item should be completable in one session (2-4 hours)
- Each item should have a verifiable output
- Dependencies should be explicit
APPLY numbering scheme:
- Phase 1 tasks: 001, 002, 003...
- Phase 2 tasks: 010, 011, 012...
- Phase 3 tasks: 020, 021, 022...
(10-gap allows inserting tasks later)
Step 3.4: Discover Related Resources (REQUIRED)
Every task MUST have a <knowledge> section with relevant files based on its tags.
Tag-to-Knowledge Mapping (MANDATORY)
When a task has these tags, ALWAYS include these knowledge files:
| Tag | Constraints | Patterns | Additional Files |
|-----|-------------|----------|------------------|
| pcf, react, fluent-ui, frontend, e2e-test | .claude/constraints/pcf.md | .claude/patterns/pcf/control-initialization.md, .claude/patterns/pcf/theme-management.md | src/client/pcf/CLAUDE.md, docs/guides/PCF-DEPLOYMENT-GUIDE.md, .claude/skills/ui-test/SKILL.md |
| bff-api, api, minimal-api, endpoints | .claude/constraints/api.md | .claude/patterns/api/endpoint-definition.md, .claude/patterns/api/endpoint-filters.md | src/server/api/CLAUDE.md (if exists) |
| dataverse, solution, fields, plugin | .claude/constraints/plugins.md | .claude/patterns/dataverse/plugin-structure.md | .claude/skills/dataverse-deploy/SKILL.md |
| auth, oauth, authorization | .claude/constraints/auth.md | .claude/patterns/auth/spaarke-sso-binding.md (canonical v2), .claude/patterns/auth/obo-flow.md, .claude/patterns/auth/oauth-scopes.md | .claude/adr/ADR-028-spaarke-auth-architecture.md, docs/guides/auth-deployment-setup.md |
| cache, redis, caching | .claude/constraints/data.md | .claude/patterns/caching/distributed-cache.md | — |
| ai, azure-openai, document-intelligence | .claude/constraints/ai.md | .claude/patterns/ai/streaming-endpoints.md | — |
| deploy | — | — | .claude/skills/dataverse-deploy/SKILL.md, docs/guides/PCF-DEPLOYMENT-GUIDE.md |
| testing, unit-test, integration-test | .claude/constraints/testing.md | .claude/patterns/testing/unit-test-structure.md, .claude/patterns/testing/mocking-patterns.md | — |
| worker, job, background | .claude/constraints/jobs.md | — | — |
Critical: PCF tasks MUST reference PCF-DEPLOYMENT-GUIDE.md
The PCF-DEPLOYMENT-GUIDE.md guide contains mandatory version bumping instructions:
- Version must be updated in 4 locations before deployment
- Footer must show version number
- Failure to follow this results in stale deployments
FOR each task:
EXTRACT tags from <metadata><tags>
FOR each tag:
LOOKUP in Tag-to-Knowledge Mapping
ADD matching constraint file to <knowledge><files>
ADD matching pattern files to <knowledge><files>
ADD matching additional files to <knowledge><files>
ENSURE <knowledge> section is NOT empty
IF no matches found:
ADD at minimum: relevant CLAUDE.md for the module being modified
Step 3.5: Map ADRs to Tasks (REQUIRED)
FOR each task identified:
DETERMINE resource types being created/modified:
- API Endpoint → ADR-001, ADR-008, ADR-010
- Authorization → ADR-003, ADR-008
- Caching → ADR-009
- Dataverse Plugin → ADR-002
- Graph/SPE Integration → ADR-007
- PCF Control → ADR-006, ADR-011, ADR-012, ADR-021
- Background Worker → ADR-001, ADR-004
- DI Registration → ADR-010
- AI Features → ADR-013, ADR-014, ADR-015, ADR-016
- Testing → ADR-022
ADD to task:
- <constraints> with source="ADR-XXX" for each applicable ADR
- <knowledge><files> include CONCISE ADR paths:
- Use .claude/adr/ADR-XXX-*.md (100-150 lines, AI-optimized)
- NOT docs/adr/ADR-XXX-*.md (full version, load only if needed)
REFERENCE: See adr-aware skill for full mapping table
Step 3.5.5: Determine Task Rigor Level (REQUIRED)
FOR each task identified:
DETERMINE rigor level using the same decision tree from task-execute skill:
RIGOR LEVEL = FULL IF task has ANY of:
- Tags include: bff-api, api, pcf, plugin, auth
- Will modify code files (.cs, .ts, .tsx) - check <relevant-files>
- Has 6+ steps in <steps> section
- Task description includes: "implement", "refactor", "create service"
- Dependencies on 3+ other tasks
RIGOR LEVEL = STANDARD IF task has ANY of:
- Tags include: testing, integration-test
- Will create new files (check <outputs> for new paths)
- Has explicit <constraints> or ADRs listed
- Phase 2.x or higher (integration/deployment phases)
RIGOR LEVEL = MINIMAL OTHERWISE:
- Documentation tasks
- Inventory/checklist creation
- Simple configuration updates
ADD to task <metadata> (canonical field is <rigor>; <rigor-hint> is a deprecated alias — do NOT emit it):
<rigor>{FULL | STANDARD | MINIMAL}</rigor>
<rigor-reason>{Why this level - reference specific trigger from decision tree}</rigor-reason>
EXAMPLE rigor values:
<rigor>FULL</rigor>
<rigor-reason>Task tags include 'bff-api' (code implementation)</rigor-reason>
<rigor>STANDARD</rigor>
<rigor-reason>Task tags include 'testing', 'integration-test'</rigor-reason>
<rigor>MINIMAL</rigor>
<rigor-reason>Documentation task (no code implementation)</rigor-reason>
PURPOSE:
- Makes rigor level explicit in task file (documented, not inferred)
- task-execute skill uses this hint but can override based on actual characteristics
- User can override by editing task file before execution
- Audit trail shows why rigor level was chosen
REFERENCE: See .claude/skills/task-execute/SKILL.md Step 0.5 for full decision tree
Step 3.5.5b: Assign Execution Model Tier + Effort (REQUIRED — added 2026-07-08 for Sonnet-5 execution)
Model strategy (binding): planning phases (design-to-spec, project-pipeline Steps 0–3) run on Opus 4.8 / Fable 5; task execution defaults to Sonnet 5 (near-Opus coding quality at lower cost). project-pipeline/task-create flags the minority of tasks that genuinely need top-tier reasoning back up to Opus/Fable via a per-task <model-tier>, and sets an explicit <effort> per task (see the effort rubric below).
FOR each task identified, assign a model tier:
MODEL TIER = opus (or fable) IF the task has ANY of:
- Cross-cutting refactor / migration touching 3+ existing files or consumers (high blast radius)
- Architectural change, new pattern/abstraction authoring, or ADR-migration / ADR-compliance work
- Security/auth-sensitive code (tags include: auth, security)
- Ambiguous or underspecified goal requiring significant judgment, or novel algorithm design
- FULL rigor AND (dependencies on 3+ tasks OR flagged high-risk in the plan Risk Register)
→ fable ONLY for the very hardest of these (whole-subsystem migration, novel architecture);
opus for everything else in this bucket.
MODEL TIER = sonnet OTHERWISE (default):
- Standard single-component code implementation with an explicit canonical reference to follow
- Test authoring, wiring, configuration, deployment steps
- Documentation / inventory tasks
ADD to task <metadata>:
<model-tier>{sonnet | opus | fable}</model-tier>
<model-tier-reason>{Why - reference the specific trigger}</model-tier-reason>
EXAMPLES:
<model-tier>opus</model-tier>
<model-tier-reason>Cross-cutting migration of 4 wizard families onto a shared module (high blast radius)</model-tier-reason>
<model-tier>opus</model-tier>
<model-tier-reason>ADR-024 resolver-compliance migration of an existing non-compliant wizard</model-tier-reason>
<model-tier>sonnet</model-tier>
<model-tier-reason>New single-component wizard following the canonical workAssignmentService.ts reference</model-tier-reason>
PURPOSE:
- project-pipeline Step 5 dispatches each task's subagent with model = <model-tier>
- task-execute declares the tier and escalates if the current session model is lower
- Keeps the expensive top tier scoped to the tasks that actually need it (cost control)
Effort rubric (REQUIRED — set <effort> per task). Sonnet 5 respects effort strictly: high is the default; xhigh is for the hardest coding/agentic work. Blanket xhigh is NOT free — at xhigh Sonnet-5 cost approaches Opus 4.8, so reserve it. Route on how hard the reasoning is, given a complete spec:
EFFORT = xhigh IF (model-tier is sonnet AND) the task is:
- Brownfield debugging / root-cause / race-condition-class work (Sonnet 5 is documented
as particularly strong here — some tasks once tagged "Opus-required" belong here instead)
- Complex multi-file change with a COMPLETE spec (hard depth, low ambiguity)
EFFORT = high OTHERWISE (default):
- Routine, well-patterned work with a clear reference (CRUD endpoints, PCF wiring,
mechanical refactors, test authoring, config)
EFFORT = medium/low: reserve for short, scoped, latency-sensitive mechanical steps only.
opus/fable tasks: set <effort>high</effort> unless the task is a genuine whole-subsystem
reasoning problem (then xhigh). Do NOT stack fable + xhigh reflexively.
ADD to task <metadata>:
<effort>{low | medium | high | xhigh}</effort>
Cost guardrail: if a SONNET task genuinely needs sustained xhigh, re-check whether it should
be <model-tier>opus</model-tier> instead — xhigh is for tasks where Sonnet's follow-through
profile fits but depth is needed, not a substitute for correct Opus routing.
Authoring for literal (Sonnet-5) execution (applies to EVERY task, all tiers). Sonnet 5 follows instructions literally and does NOT generalize intent or infer unstated requests. Under-specified tasks degrade Sonnet-5 output more than Opus. Author each POML so a literal executor cannot go wrong:
-
Explicit scope everywhere. List the exact files to touch (not "the follow-on components"); point at the canonical reference implementation to copy (e.g.
workAssignmentService.ts) rather than describe it; state the exact contract (e.g. the ADR-024 resolver's 5 fields + mutual-exclusion). A<constraint>without an explicit scope clause is a defect — write "Every endpoint added or modified in this task appliesDocumentAuthFilter," not "use endpoint filters for auth." -
Acceptance criteria are a CLOSED SET. The executor treats every listed
<criterion>as mandatory and anything not listed as out of scope. Criteria must be exhaustive, not illustrative — include the negative/authorization cases (the 401, the empty-input, the unauthorized-user path), not just the happy path. -
"Above and beyond" must be requested. If a task should include opportunistic improvements (e.g. "also fix adjacent lint violations in touched files"), say so explicitly. Do NOT rely on the model to infer it — and do NOT add anti-laziness scaffolding ("be exhaustive", "double-check everything"); Sonnet 5 over-triggers on those and burns effort on ritual verification.
-
Test-scope clause (added 2026-08-28). For any task that will add or modify tests, state in
<acceptance-criteria>which behaviours and edge cases are in scope for test coverage — not just the production behaviour. Frame it as intent, and say what is not wanted:"Cover the stated contract plus the edge cases named above. Anything beyond that needs a one-line justification in task notes."
Two reasons. First, the closed-set rule above already tells the executor that unlisted criteria are out of scope; without a test-scope clause, "write tests" is an open instruction inside an otherwise closed contract, and the predictable result is breadth padding as uncertainty-hedging — three near-identical happy-path variants that each pass every ADR-038 §7 ban individually while adding no unique verification value. Second, it gives
/test-dietsomething concrete to check a MAINTAIN classification against at project close.Do NOT state a numeric test count. A number invites satisfying the number, which is the padding behaviour this clause exists to prevent.
-
Step mode (see Step 3.5.5c) and escalation triggers (see the
<escalation>element) are the other two literal-execution levers — set them deliberately per task. -
Frontend tasks need concrete visual direction (see Step 3.65): anchor the look in a
<knowledge>pattern reference to an existing Fluent v9 component or an explicit spec. "Clean and modern" is not a spec — Sonnet 5 will settle into a fixed default house style. -
Knowledge curation (token discipline). The 1M context window is headroom for genuinely cross-cutting tasks, NOT license to load the full ADR corpus by default. The Sonnet-5 tokenizer produces ~30% more tokens for the same text, so padding is materially more expensive — load what the task needs via the Tag-to-Knowledge mapping, reference the rest by path.
Step 3.5.5c: Choose Step Mode + Escalation Triggers (REQUIRED — added 2026-07-08 for Sonnet-5 execution)
A literal, agentic executor treats granular ordered <steps> as a binding contract — it will do exactly the six steps written even if step 3 is wrong for the actual codebase state. Choose a step mode per task:
<steps mode="directional"> ← DEFAULT for standard implementation tasks.
Steps are guidance; the binding contract is <goal> + <acceptance-criteria> + <constraints>.
The executor MAY adapt the sequence to the real codebase state.
<steps mode="prescriptive"> ← for migrations, deployment-touching work, anything under
azure-deployment.md constraints, or any irreversible/ordered procedure.
The exact sequence is binding; deviations require escalation (not silent improvisation).
Escalation triggers. A literal model will not infer when to invoke human escalation (root CLAUDE.md §6 / §6.5), and Sonnet 5's follow-through tendency makes it more likely to push to a completion than to stop at a judgment boundary. For any task with a known failure mode or judgment boundary, add an <escalation> element naming the concrete trip-wire:
<escalation>
<trigger>If the Graph API contract differs from the spec, STOP and escalate (root CLAUDE.md §6) rather than adapting the implementation.</trigger>
</escalation>
This element is also load-bearing for the /goal wave loop (Step 3.8): inside a goal loop, firing an <escalation> trigger is the correct way out — the worker writes BLOCKED.md and the loop ends on the escalation branch instead of improvising.
Step 3.5.6: Component Justification Gate (REQUIRED per CLAUDE.md §11)
This step enforces the universal rule from root CLAUDE.md §11 "Component Justification — Default to Reuse."
For every task that introduces a NEW component (service, abstraction, interface, endpoint, route, DI registration, package dependency, Dataverse column, file path under src/), add a <justification> element answering the three-question template:
<justification>
<existing>Closest existing neighbor — cite file:line from Grep evidence (or "none found" with grep command shown)</existing>
<extension>Yes/No + reason in ≤2 sentences. "Cleaner separation" is NOT a reason.</extension>
<cost-of-doing-nothing>Concrete behavior or contract that fails without this. NOT "scalability" / "abstraction layer" / "future flexibility."</cost-of-doing-nothing>
</justification>
Decision logic during decomposition:
FOR each new-component task:
EVALUATE the three answers:
IF <extension> is "Yes → can extend existing":
→ REWRITE the task to "Extend `<existing>` with …" instead of "Build new `<new-component>`"
→ Continue with the rewritten task
IF <cost-of-doing-nothing> cannot name a concrete behavior or contract that fails:
→ DEMOTE the task (mark as "deferred — needs concrete failure mode") OR DROP
IF all three answers are concrete + extension genuinely impossible:
→ PROCEED with new-component task
Reviewer flag: hollow / boilerplate answers ("for separation of concerns", "for testability", "for future flexibility") fail this gate.
Scope of this gate — applies to tasks that ADD surface:
- New
.cs/.ts/.tsxfile - New endpoint route / handler
- New DI registration
- New package reference (
<PackageReference>/dependenciesentry) - New Dataverse column / entity / alternate key
- New skill / agent / pattern / constraint file
NOT required for: tasks that ONLY modify existing files (edit, refactor, fix bug, add tests for existing surface, rename, format). The rule applies to NEW surface, not modification.
Audit trail: tasks with hollow or missing <justification> are blocked from code review per CLAUDE.md §11. The code-review skill Step 6.6 verifies justification concreteness at PR time.
Component-complexity check (per docs/standards/COMPONENT-COMPLEXITY.md) — for any task that creates a new component OR materially grows an existing one, evaluate complexity/cohesion, not line count:
- If the task would add a second (or Nth) responsibility to an already-multi-purpose component, design the task to extract the diverging responsibility into the right seam up front — don't accrete another concern onto a god-class. (Prefer extending a cohesive component; don't manufacture thin components to dodge a size number.)
- A large file is not a defect by itself — a large, single-responsibility/cohesive component (state machine, exhaustive mapping, generated code) is legitimate; note it in the task if relevant.
- When an existing component's responsibilities have genuinely diverged, prefer a deliberate decomposition task over reactively splitting mid-feature. (There is no hard LOC gate — the retired God-class ratchet is replaced by this authoring/review guidance + a non-blocking observation report,
scripts/report-large-server-files.ps1.)
Step 3.6: Add Deployment Tasks (REQUIRED)
FOR each deliverable type in the project, CREATE deployment task(s):
DEPLOYMENT TASK MAPPING:
┌──────────────────────┬────────────────────────────────────────────────────────────┐
│ Deliverable Type │ Required Deployment Task(s) │
├──────────────────────┼────────────────────────────────────────────────────────────┤
│ BFF API Endpoints │ - Deploy to Azure App Service │
│ │ - Tags: [deploy, azure, bff-api] │
│ │ - Skill: (azure deployment commands) │
├──────────────────────┼────────────────────────────────────────────────────────────┤
│ PCF Controls │ - Deploy PCF to Dataverse (pac pcf push) │
│ │ - Tags: [deploy, dataverse, pcf] │
│ │ - Skill: dataverse-deploy │
├──────────────────────┼────────────────────────────────────────────────────────────┤
│ Dataverse Fields │ - Deploy solution to Dataverse │
│ │ - Configure Relevance Search (if applicable) │
│ │ - Tags: [deploy, dataverse, solution] │
│ │ - Skill: dataverse-deploy │
├──────────────────────┼────────────────────────────────────────────────────────────┤
│ Azure AI Resources │ - Provision Azure AI Search/OpenAI resources │
│ │ - Configure connection strings in App Service │
│ │ - Tags: [deploy, azure, azure-ai] │
│ │ - Skill: (bicep/infrastructure scripts) │
├──────────────────────┼────────────────────────────────────────────────────────────┤
│ Background Workers │ - Deploy worker to Azure Container Apps │
│ │ - Tags: [deploy, azure, worker] │
└──────────────────────┴────────────────────────────────────────────────────────────┘
PLACEMENT:
- Deployment tasks should be at the END of each phase (after implementation + testing)
- OR create a dedicated "Deployment" phase if multiple deployments needed
- Final integration testing task should come AFTER all deployment tasks
EXAMPLE Phase Structure:
Phase 1: Implementation
001-010: Build features
009: Unit tests
Phase 1-Deploy:
015: Deploy BFF API to Azure
016: Deploy PCF to Dataverse
017: Integration tests (post-deployment)
Phase 2: Next feature set...
...
090: Project wrap-up
Step 3.65: Add UI Test Definitions for PCF/Frontend Tasks (REQUIRED)
Concrete visual direction (REQUIRED for frontend tasks — added 2026-07-08 for Sonnet-5). Before writing UI tests, verify the task anchors its visual direction concretely. Sonnet 5 settles into a fixed default house style on open-ended frontend briefs, and generic adjustments ("cleaner", "more modern") just shift it to a different fixed palette rather than matching intent. Every pcf/frontend/fluent-ui task MUST anchor the look via ONE of: a <knowledge><patterns> reference to an existing Fluent v9 component in the repo to mirror, an explicit spec (tokens/spacing/layout), or a referenced design artifact. Reject "clean and modern" as a spec — if the plan gives only that, add the concrete anchor from an existing component (e.g. mirror RecordHeaderShell) or flag the task as needing design input.
FOR each task with tags: pcf, frontend, fluent-ui, e2e-test:
ADD <ui-tests> section to task POML with:
- Test name and description
- Target URL (use {org} placeholder for environment)
- Step-by-step test actions
- Expected outcomes
- ADR-021 dark mode checks (for Fluent UI components)
EXAMPLE <ui-tests> structure:
<ui-tests>
<test name="Component Renders">
<url>https://{org}.crm.dynamics.com/main.aspx?appid={app-id}&pagetype=entityrecord&etn=account</url>
<steps>
<step>Navigate to Account form</step>
<step>Verify {component-name} control is visible</step>
<step>Check console for JavaScript errors</step>
</steps>
<expected>Control renders without console errors</expected>
</test>
<test name="Dark Mode Compliance (ADR-021)">
<steps>
<step>Toggle dark mode in D365 settings</step>
<step>Verify background colors adapt (no white in dark mode)</step>
<step>Verify text colors adapt (no black in dark mode)</step>
<step>Verify icons use currentColor</step>
</steps>
<expected>All colors use Fluent UI v9 semantic tokens per ADR-021</expected>
</test>
<test name="User Interaction">
<steps>
<step>Click primary action button</step>
<step>Verify loading indicator appears</step>
<step>Verify response displays correctly</step>
</steps>
<expected>Interaction completes within 3 seconds</expected>
</test>
</ui-tests>
WHY: UI tests are executed by task-execute Step 9.7 via ui-test skill
when Claude Code has Chrome integration enabled (--chrome flag)
REQUIREMENTS:
- Tests must be specific to the component being built
- Include dark mode test if task involves Fluent UI
- Include console error check for all PCF controls
- Use {placeholder} syntax for environment-specific values
Step 3.8: Identify Parallel Task Groups (REQUIRED)
Purpose: Enable efficient parallel execution by grouping independent tasks.
FOR each phase:
ANALYZE task dependencies to identify parallel groups:
PARALLEL GROUP = Tasks where:
- All have the SAME prerequisite task(s) (or none)
- NO task depends on another in the same group
- Tasks do NOT modify the same files (check <relevant-files>)
- Tasks are in the same phase or adjacent phases
EXAMPLE dependency analysis:
Task 020: dependencies="010"
Task 021: dependencies="010"
Task 022: dependencies="010"
→ These three CAN run in parallel (Group A)
Task 023: dependencies="020,021"
→ This MUST wait for both 020 and 021 (serial)
CREATE Parallel Groups list:
Group A: [020, 021, 022] - prereq: 010
Group B: [031, 032] - prereq: 030
FOR each task in a parallel group:
ADD to <metadata>:
<parallel-group>{group-letter}</parallel-group>
<parallel-safe>true</parallel-safe>
FOR tasks NOT safe to parallelize:
ADD to <metadata>:
<parallel-safe>false</parallel-safe>
<parallel-reason>{why: shared files, sequential logic, etc.}</parallel-reason>
**AUTO-DEMOTION RULE — `.claude/` permission boundary:**
IF any file in <relevant-files> starts with `.claude/`:
→ FORCE <parallel-safe>false</parallel-safe>
→ SET <parallel-reason>touches .claude/ — main-session-only (permission boundary)</parallel-reason>
→ This is NON-NEGOTIABLE. Sub-agents cannot write to .claude/.
→ See CLAUDE.md "Sub-Agent Write Boundary" section.
**AUTO-DEMOTION RULE — file overlap check:**
WITHIN each proposed parallel group:
FOR each pair of tasks (A, B) in the group:
IF intersection(A.relevant-files, B.relevant-files) is non-empty:
→ SPLIT: move one task to a different group
→ OR mark both <parallel-safe>false</parallel-safe>
→ Add <parallel-reason>file-overlap with task {other-id}</parallel-reason>
DOCUMENT in TASK-INDEX.md "Parallel Execution Groups" section with wave structure:
```
## Parallel Execution Plan
Phase 1:
Wave 1 (parallel, 4 agents): 010, 011, 012, 013
Wave 2 (parallel, 3 agents): 020, 021, 022 — prereq: Wave 1
Wave 3 (sequential): 030 — touches .claude/, main-session-only
```
WHY THIS MATTERS:
- The project-pipeline executes parallel groups CONCURRENTLY by default
- Claude Code spawns one task agent per task in a group simultaneously
- Independent tasks complete faster when run in parallel
- Dependencies prevent race conditions and merge conflicts
- Explicit grouping prevents accidental parallel execution of conflicting tasks
- EVERY task MUST have parallel-group and parallel-safe metadata — no exceptions
DESIGN FOR PARALLELISM:
- When decomposing work, PREFER creating independent tasks over sequential chains
- Split by file/component ownership (e.g., one task per endpoint, per component)
- Avoid tasks that touch the same files — this prevents parallelization
- A project with no parallel groups will execute slowly (one task at a time)
- Aim for at least 2-3 parallel groups per project phase
Step 3.85: Assign /goal Wave-Completion Eligibility (REQUIRED — added 2026-07-08)
/goal (Claude Code v2.1.139+) keeps a session working turn-after-turn until a separate transcript-only evaluator (Haiku by default — it reads the conversation, runs NO commands, NO file reads) judges a completion condition met. It is the per-wave completion loop that removes the operator "continue" press between tasks. It is NOT a per-task mechanism and NOT a quality gate — Step 9.5 + the orchestrator remain the arbiter of whether work is good.
Assign eligibility per wave (from the Step 3.8 wave structure), analogous to <model-tier>:
FOR each wave in the Parallel Execution Plan:
GOAL-ELIGIBLE = true IFF ALL of:
(1) Machine-verifiable end-state exists — the wave's tasks prove done via transcript-visible
output: tests pass / build exits 0 / lint clean / git status clean. (The evaluator can
only see what the worker surfaces — no verifiable signal ⇒ not eligible.)
(2) ≥3 tasks batched in the wave (enough sequential handoffs to be worth automating).
(3) Tasks are well-specified — exhaustive <acceptance-criteria>, explicit <constraints>.
(4) Low architectural-judgment / low-ambiguity (these should stop for human input, not loop).
GOAL-ELIGIBLE = false IF ANY of:
- Wave touches security / auth / secrets (tags: auth, security)
- Wave is deployment-touching or otherwise irreversible (tags: deploy; azure-deployment.md scope)
- Wave has likely breaking changes / expected ADR conflicts (escalation expected)
- Exploratory / design / research tasks with no crisp end-state
- Single-task or two-task wave (no batching benefit)
IF GOAL-ELIGIBLE:
COMPILE a by-reference condition (stay under the 4,000-char /goal cap — do NOT enumerate every
criterion). Store it in TASK-INDEX.md next to the wave. Template:
All of the following hold in this session:
(1) Every task in Wave {N} ({id-list}) shows its acceptance criteria passing via transcript
output — {the wave's verify command, e.g. "dotnet test exits 0" / "npm test passes"};
(2) Each task's Step 9.5 gates (code-review + adr-check) have been RUN and their full findings
surfaced in the transcript;
(3) git status shows only the waves' expected file changes.
OR: a BLOCKED.md exists under projects/{name}/ documenting a root-CLAUDE.md §6 escalation, shown in transcript.
Stop after {N_tasks × 6} turns if neither state is reached.
RECORD in TASK-INDEX.md Parallel Execution Plan:
Wave 2 (parallel, 3 agents): 020, 021, 022 — prereq: Wave 1 — goal-eligible: YES
goal-condition: "{compiled condition}"
Wave 3 (sequential): 030 — touches .claude/ — goal-eligible: NO (single-task, .claude/ boundary)
Why by-reference + capped: the 4,000-char limit and the transcript-only evaluator mean the condition proves completion through the worker's surfaced test runs and gate outputs, not by re-listing criteria. The turn cap is the runaway guard. Escalation (a fired <escalation> trigger → BLOCKED.md) is a legitimate loop exit, never an error.
Step 3.7: Add Mandatory Project Wrap-up Task (REQUIRED)
ALWAYS create a final "Project Wrap-up" task as the LAST task in the project.
Task ID: Use highest phase number + 90 (e.g., if last phase is 050, wrap-up is 090)
This ensures wrap-up is always at the end regardless of task additions.
This task is MANDATORY for all projects and must include these steps:
1. Run final quality gates:
- /code-review on all project code (identifies remaining issues)
- /adr-check on all project code (validates architecture compliance)
- Fix any critical issues before proceeding
2. Run repository cleanup:
- /repo-cleanup projects/{project-name} (audits and cleans ephemeral files)
- Review cleanup report
- Approve removals (notes/debug/, notes/spikes/, notes/drafts/)
- Archive handoffs if any (notes/handoffs/ → .archive/)
3. Update README.md:
- Set Status to "Complete"
- Update Last Updated date
- Set Phase to "Complete" and Progress to "100%"
- Add Completed Date
- Check all Graduation Criteria checkboxes
- Add completion entry to Changelog
4. Update plan.md:
- Set Status to "Complete"
- Update all milestone statuses to ✅
5. Document lessons learned:
- Append to notes/lessons-learned.md (the existing per-project convention — 51+ projects use it).
One lesson per entry, one-line summary, record BOTH corrections and confirmed non-obvious
approaches + why they mattered. Do NOT create a new central lessons store — durable,
cross-project lessons are promoted into .claude/FAILURE-MODES.md or an ADR by
doc-drift-audit / ai-procedure-maintenance at project close.
- When authoring NEW tasks (Step 3.4), scan the project's notes/lessons-learned.md and
.claude/FAILURE-MODES.md and reference any relevant lesson from the task's <knowledge>.
6. Final verification:
- All task files marked completed in TASK-INDEX.md
- All documentation is current
- No critical code-review issues remaining
- Repository cleanup completed
Step 4: Generate Task Files
For each task, create tasks/{NNN}-{task-slug}.poml as a valid XML document:
<?xml version="1.0" encoding="UTF-8"?>
<task id="{NNN}" project="{project-name}">
<metadata>
<title>{Task Title}</title>
<phase>{N} {Phase Name}</phase>
<gate>startable | blocked | {dep-condition}</gate> <!-- readiness -->
<status>not-started</status>
<rigor>{FULL | STANDARD | MINIMAL}</rigor> <!-- Step 3.5.5 (author hint; task-execute may override) -->
<rigor-reason>{Why this level - from Step 3.5.5 decision tree}</rigor-reason>
<model-tier>{sonnet | opus | fable}</model-tier> <!-- Step 3.5.5b; sonnet default -->
<model-tier-reason>{Why this tier - from Step 3.5.5b}</model-tier-reason>
<effort>{low | medium | high | xhigh}</effort> <!-- from Step 3.5.5b effort rubric; default high -->
<parallel-group>{A/B/C/... or "none" - from Step 3.8}</parallel-group>
<parallel-safe>{true/false - can this run in parallel?}</parallel-safe>
<parallel-reason>{why, when parallel-safe is false}</parallel-reason>
<deps>{comma-separated task IDs or "none"}</deps>
<tags>{context tags for Claude Code focus - see Standard Tag Vocabulary}</tags>
<estimated-effort>{optional, e.g. 2-4 hours}</estimated-effort>
</metadata>
<!-- CANONICAL METADATA FIELD NAMES (reconciled 2026-07-16 to match live practice + the shared skeleton in
.claude/templates/task-execution.template.md). Deprecated aliases accepted for back-compat but NOT emitted:
<rigor-hint> → <rigor>; <dependencies> (metadata sibling) → <deps>. The <dependencies> element remains
valid INSIDE <context> to describe prerequisite tasks. <blocks> is dropped — the DAG lives in TASK-INDEX.md. -->
<prompt>
{Natural language instruction for AI agent. 1-3 sentences describing
what needs to be accomplished and why. This is the "executable" part
the operator hands to the AI.}
</prompt>
<role>
SPAARKE platform developer. Follow ADRs strictly. {Add specific expertise
needed: e.g., "Expert in ASP.NET Core Minimal APIs and Microsoft Graph SDK."}
</role>
<goal>
{Clear, measurable definition of done. What artifact(s) will exist when complete?}
</goal>
<context>
<background>
{Why this task exists - business context from plan.md/spec.md}
</background>
<relevant-files>
<file>{path to file to create/modify}</file>
<file>{path to related file}</file>
</relevant-files>
</context>
<constraints>
<constraint source="ADR-{NNN}">{Constraint text}</constraint>
<constraint source="ADR-{NNN}">{Another constraint}</constraint>
<constraint source="project">{Project-specific constraint}</constraint>
</constraints>
<knowledge>
<files>
<file>docs/adr/ADR-{NNN}-{name}.md</file>
<file>{path to relevant knowledge article}</file>
</files>
<patterns>
<pattern name="{pattern name}" location="{file path}">
{Brief description of pattern to follow}
</pattern>
</patterns>
</knowledge>
<steps mode="directional"> <!-- directional (default) = goal+criteria+constraints are binding, executor may adapt sequence;
prescriptive = exact sequence binding (migrations/deploys/irreversible) — see Step 3.5.5c -->
<step order="1">{First concrete action}</step>
<step order="2">{Second concrete action}</step>
<step order="3">{Continue until task is complete}</step>
<step order="N-2">Run tests and verify all pass</step>
<step order="N-1">Update TASK-INDEX.md: change this task's status to ✅ completed</step>
<step order="N">If any deviations from plan, document in projects/{project-name}/notes/</step>
</steps>
<escalation> <!-- OPTIONAL but REQUIRED for tasks with a known failure mode / judgment boundary (Step 3.5.5c) -->
<trigger>{Concrete trip-wire: "If X differs from the spec, STOP and escalate per CLAUDE.md §6 rather than adapting."}</trigger>
</escalation>
<tools>
<tool name="dotnet">Build and test .NET projects</tool>
<tool name="npm">Build TypeScript/PCF projects</tool>
<tool name="terminal">Run shell commands</tool>
</tools>
<outputs>
<output type="code">{exact path to code file}</output>
<output type="test">{exact path to test file}</output>
<output type="docs">{exact path to doc file if any}</output>
</outputs>
<acceptance-criteria>
<criterion testable="true">
Given {precondition}, when {action}, then {expected result}.
</criterion>
<criterion testable="true">
{Another testable criterion}
</criterion>
<criterion testable="true">All unit tests pass.</criterion>
</acceptance-criteria>
<notes>
{Implementation hints, gotchas to avoid, references to spec.md sections}
</notes>
<execution>
<skill>.claude/skills/task-execute/SKILL.md</skill>
<protocol>
Before starting this task, load all files listed in <knowledge><files>.
Follow the task-execute skill for mandatory pre-execution checklist.
</protocol>
</execution>
</task>
Step 5: Update Project Files
UPDATE projects/{project-name}/CLAUDE.md:
- Add task count and phase mapping
- Update "Next Action" to reference first task
CREATE tasks/TASK-INDEX.md:
| ID | Title | Phase | Status | Dependencies | Parallel |
|----|-------|-------|--------|--------------|----------|
| 001 | ... | 1 | 🔲 | none | — |
| 002 | ... | 1 | 🔲 | 001 | — |
| 020 | ... | 2 | 🔲 | 010 | Group A |
| 021 | ... | 2 | 🔲 | 010 | Group A |
...
ADD "Parallel Execution Groups" section:
```markdown
## Parallel Execution Groups
Tasks in the same group can run simultaneously once prerequisites are met.
| Group | Tasks | Prerequisite | Files Touched | Safe to Parallelize |
|-------|-------|--------------|---------------|---------------------|
| A | 020, 021, 022 | 010 ✅ | Separate endpoints | ✅ Yes |
| B | 031, 032 | 030 ✅ | Separate components | ✅ Yes |
**How to Execute Parallel Groups:**
1. Check all prerequisites are complete (✅ in Status)
2. Invoke Task tool with multiple subagents in ONE message
3. Each subagent runs task-execute for one task
4. Wait for all to complete before next group
### Step 6: Output Summary
✅ Tasks created for: projects/{project-name}/
Task breakdown: Phase 1: {n} tasks (001-00{n}) Phase 2: {m} tasks (010-01{m}) ... Wrap-up: 1 task (090-project-wrap-up) Total: {total} tasks
Rigor level distribution: FULL: {count} tasks (code implementation, architecture changes) STANDARD: {count} tasks (tests, new files, constraints) MINIMAL: {count} tasks (documentation, inventory)
Task list with rigor levels: 001 - {title} (FULL - {reason}) 002 - {title} (STANDARD - {reason}) 003 - {title} (MINIMAL - {reason}) ... 090 - Project Wrap-up (FULL - code-review + adr-check + repo-cleanup)
Files created:
- tasks/TASK-INDEX.md
- tasks/001-{slug}.poml
- tasks/002-{slug}.poml ...
- tasks/090-project-wrap-up.poml # MANDATORY final task
Execution order recommendation:
- Start with task 001 (no dependencies)
- ... N. End with task 090 (project-wrap-up) - updates README, plan, documents completion
Run /task-execute 001 to begin implementation.
## Conventions
### File Naming
- Format: `{NNN}-{task-slug}.poml`
- Extension: `.poml` (valid XML document)
- Slug: 3-5 words, kebab-case (e.g., `setup-redis-connection`)
- Numbers: 3 digits, zero-padded (001, 010, 100)
### Standard Tag Vocabulary (for `<tags>` element)
Use these standardized tags in the `<metadata><tags>` element to help Claude Code focus context:
| Category | Tags | Purpose |
|----------|------|---------|
| **API/Backend** | `bff-api`, `api`, `backend`, `minimal-api`, `endpoints` | BFF API development |
| **Frontend/PCF** | `pcf`, `react`, `typescript`, `frontend`, `fluent-ui` | PCF control development |
| **Dataverse** | `dataverse`, `solution`, `fields`, `plugin`, `ribbon` | Dataverse customization |
| **Azure** | `azure`, `app-service`, `azure-ai`, `azure-search`, `bicep` | Azure infrastructure |
| **AI/ML** | `azure-openai`, `ai`, `embeddings`, `document-intelligence` | AI features |
| **Operations** | `deploy`, `ci-cd`, `devops`, `infrastructure` | Deployment tasks |
| **Quality** | `testing`, `unit-test`, `integration-test`, `e2e-test` | Testing tasks |
| **Refactoring** | `refactoring`, `rename`, `restructure`, `migration` | Code restructuring |
| **Configuration** | `config`, `options`, `di`, `settings` | Configuration changes |
**Usage in POML:**
```xml
<metadata>
<tags>bff-api, refactoring, services</tags> <!-- Task 001: rename service -->
<tags>pcf, react, frontend, fluent-ui</tags> <!-- Task 013: update panel -->
<tags>deploy, dataverse, pcf</tags> <!-- Task 015: deploy PCF -->
</metadata>
Context Loading Benefit:
When Claude Code starts a task with <tags>bff-api, services</tags>, it can:
- Load
src/server/api/CLAUDE.mdfor BFF context - Reference
dataverse-deployskill for deployment - Skip loading PCF-specific context (saving tokens)
Task Sizing
| Granularity | Hours/Task | Tasks/Phase | |-------------|------------|-------------| | fine | 1-2 | 5-10 | | medium | 2-4 | 3-7 | | coarse | 4-8 | 2-4 |
Default to "medium" unless user specifies otherwise.
POML Tag Requirements
Every task file MUST have these POML sections (valid XML):
<task>- Root element with id and project attributes<metadata>- title, phase, gate, status, rigor (+ rigor-reason), deps, tags (canonical names;<deps>not<dependencies>)<prompt>- Natural language task instruction for AI agent<role>- Persona/expertise for the AI to adopt<goal>- Clear definition of done<context>- Background and relevant files<constraints>- With explicit ADR source attributes<steps>- Ordered steps with order attribute<outputs>- Exact file paths with type attribute<acceptance-criteria>- Testable criteria with testable="true" attribute
Required metadata (added 2026-07-08 for Sonnet-5 execution):
<rigor>+<rigor-reason>- rigor level (Step 3.5.5; canonical name —<rigor-hint>deprecated)<model-tier>+<model-tier-reason>- execution tier (Step 3.5.5b)<effort>- low/medium/high/xhigh (Step 3.5.5b effort rubric; defaulthigh)<parallel-group>+<parallel-safe>- wave grouping (Step 3.8; EVERY task)<steps mode="...">-directional(default) orprescriptive(Step 3.5.5c)
Recommended sections:
<knowledge>- ADRs, patterns, and reference files (REQUIRED if task has tags - see Tag-to-Knowledge Mapping)<tools>- Available tools for execution<notes>- Implementation hints<execution>- Reference to task-execute skill and pre-execution protocol<escalation>- Concrete stop-and-escalate trigger (REQUIRED for tasks with a known failure mode / judgment boundary — Step 3.5.5c)<ui-tests>- Browser-based UI tests for PCF/frontend tasks (REQUIRED if tags include: pcf, frontend, fluent-ui, e2e-test)
Status Values
not-started- Initial statein-progress- Currently being workedblocked- Waiting on dependency or external inputcompleted- All deliverables and criteria metdeferred- Postponed (with reason in notes)
Resources
Templates (Auto-loaded)
.claude/templates/task-execution.template.md— POML skeleton (pointer only). It mirrors this skill's Step 4 block for copy-paste; the AUTHORITATIVE field set + per-field decision logic is THIS skill (Steps 3.5.5 / 3.5.5b / 3.5.5c / 3.5.6 / 3.8 / 3.65 / 3.85). Keep the two in sync (ai-procedure-maintenanceChecklist F).
Related Skills
- project-init: Creates plan.md that this skill consumes
- task-execute: Runs individual tasks (calls ui-test in Step 9.7)
- ui-test: Executes browser-based UI tests defined in task
<ui-tests>sections - project-pipeline: Orchestrates spec → setup → create → execute
Examples
See examples/examples.md for 3 worked examples:
- Example 1: Decomposing the SDAP Refactor plan into 14 POML files across 4 phases
- Example 2: Fine-grained decomposition (15 tasks vs 8, each ~1-2 hours)
- Example 3: Handling missing WBS in plan.md (graceful failure with recovery prompt)
Failure Modes & Recovery
| Failure | Cause | Prevention / Recovery |
|---|---|---|
| Generated POML files have empty <knowledge><files> blocks | Tag-to-knowledge mapping (Step 3.5.5) didn't match the task's tags | Verify the mapping table covers the task's tags. If a tag has no mapping, add one OR change the task to use a known tag. The mapping is the connective tissue between tasks and ADRs/constraints. |
| TASK-INDEX.md missing parallel-group annotations | Step 3.8 (parallel grouping) skipped or incomplete | Always run Step 3.8 — it identifies independent tasks that can run in parallel, which is critical for efficient execution (per project-pipeline orchestration). |
| Task POMLs lack <ui-tests> for PCF/frontend tasks | Step 3.65 (UI test annotation) skipped | PCF/frontend tasks MUST include <ui-tests> sections so task-execute Step 9.7 can invoke ui-test skill against them. The skill body Step 3.65 covers the format. |
| Generated task numbering collides with existing tasks | Author re-ran task-create over an existing tasks/ directory without merge logic | task-create is idempotent ON FIRST RUN but doesn't merge. If re-running, delete existing tasks/ first OR manually merge. Don't overwrite without confirmation. |
| External callers (e.g., task-execute referencing Step 3.5.5) silently break | Step numbers in Workflow body got renumbered during refinement | Step number scaffolding is external API (callers cite by number). NEVER renumber Step 3.5.5, 3.65, 3.8, etc. without coordinating with all callers (verified post-edit via grep -rn "Step 3.5"). |
Validation Checklist
Before completing task-create, verify:
- [ ] TASK-INDEX.md created with all tasks listed
- [ ] Each task file has all required POML sections
- [ ] Task numbers follow gap convention (001, 010, 020...)
- [ ] Dependencies form a valid DAG (no circular refs)
- [ ] First task(s) have no unmet dependencies
- [ ] Acceptance criteria are copy/referenced from plan.md
- [ ] Project CLAUDE.md updated with task summary
- [ ] PCF/frontend tasks have
<ui-tests>sections (Step 3.65) - [ ] UI tests include dark mode compliance check for Fluent UI tasks (ADR-021)
- [ ] Each task has
<rigor>and<rigor-reason>in metadata (Step 3.5.5) — canonical field is<rigor>, not the deprecated<rigor-hint> - [ ] Rigor levels match task characteristics (FULL for code, STANDARD for tests, MINIMAL for docs)
- [ ] Each task has
<model-tier>+<model-tier-reason>+<effort>in metadata (Step 3.5.5b);xhighonly where the effort rubric justifies it (not blanket) - [ ] Each task's
<steps>has an explicitmode(directional default; prescriptive for migrations/deploys) (Step 3.5.5c) - [ ] Tasks with a known failure mode / judgment boundary carry an
<escalation><trigger>(Step 3.5.5c) - [ ] Constraints are scoped explicitly and acceptance criteria are a closed set incl. negative/authorization cases (Authoring for literal execution)
- [ ] Frontend tasks anchor visual direction concretely — pattern ref or explicit spec, not "clean and modern" (Step 3.65)
- [ ] Parallel groups identified and documented (Step 3.8)
- [ ] Each task has
<parallel-group>and<parallel-safe>in metadata - [ ] TASK-INDEX.md includes "Parallel Execution Groups" section
- [ ] No tasks in same parallel group modify the same files
Completeness Lint (REQUIRED — added 2026-07-16 to prevent silent metadata drift)
Run this mechanical check on every generated POML before declaring task-create complete. It is the forcing
function the 2026-07-16 template-drift finding recommended (rec C): the omissions it catches are silent otherwise —
a well-formed POML missing <model-tier> just falls back to a default at dispatch, and nothing flags it.
FOR each tasks/*.poml:
REQUIRE present + non-empty: <model-tier>, <effort>, <rigor>, <parallel-group>, <parallel-safe>
REQUIRE <steps> carries an explicit mode="directional|prescriptive"
IF the task adds NEW surface (new .cs/.ts/.tsx file, endpoint, DI registration, package,
Dataverse column, or a <relevant-files> entry with role="new"):
REQUIRE a non-hollow <justification> (existing / extension / cost-of-doing-nothing) — Step 3.5.6
IF tags include pcf|frontend|fluent-ui|e2e-test: REQUIRE <ui-tests>
REJECT the deprecated <rigor-hint> / metadata-sibling <dependencies> field names (use <rigor> / <deps>)
FAIL the checklist (do not report task-create complete) if any POML is missing a required field.
- Automatable via
scripts/Validate-TaskPoml.ps1(runpwsh scripts/Validate-TaskPoml.ps1 projects/{name}/tasks). - The same gate runs again at PR time in
code-review(Step 6.7 — POML completeness) so a hand-edited task can't slip an incomplete POML past review.
Portfolio Hook (added 2026-06-23 by spaarke-devops-project-tracking-r1 task 032 · FR-18)
At end of skill (after all task POMLs scaffolded): invoke /devops-project-sync to set the Task Count field on the Project Issue.
Task Count = ls projects/{name}/tasks/*.poml | wc -l (computed by /devops-project-sync from local state).
Silent on success. Hook is a no-op if projects/{name}/README.md lacks the portfolio pointer block (project not registered).
Next.js App Router Expert
Development
A skill that turns Claude into a Next.js App Router expert.
README Generator
Development
Creates professional and comprehensive README.md files for your projects.
API Documentation Writer
Development
Generates comprehensive API documentation in OpenAPI/Swagger format.