Create POML task files from project plan decomposition

Decompose a project plan into numbered POML task files for systematic AI-assisted execution. Turns plan.md WBS into executable task files.

Sby Skills Guide Bot
ProductivityIntermediate
308/29/2026
Claude Code
#tasks#planning#project-structure#poml

Recommended for


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-justified on body length per dereferencing-reliability concern; light extract: 3 worked Examples moved to examples/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 to examples/ 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-init has 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 applies DocumentAuthFilter," 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-diet something 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 / .tsx file
  • New endpoint route / handler
  • New DI registration
  • New package reference (<PackageReference> / dependencies entry)
  • 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}&amp;pagetype=entityrecord&amp;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:

  1. Start with task 001 (no dependencies)
  2. ... 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:

  1. Load src/server/api/CLAUDE.md for BFF context
  2. Reference dataverse-deploy skill for deployment
  3. 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; default high)
  • <parallel-group> + <parallel-safe> - wave grouping (Step 3.8; EVERY task)
  • <steps mode="..."> - directional (default) or prescriptive (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 state
  • in-progress - Currently being worked
  • blocked - Waiting on dependency or external input
  • completed - All deliverables and criteria met
  • deferred - Postponed (with reason in notes)

Resources

Templates (Auto-loaded)

  • .claude/templates/task-execution.template.mdPOML 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-maintenance Checklist 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); xhigh only where the effort rubric justifies it (not blanket)
  • [ ] Each task's <steps> has an explicit mode (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 (run pwsh 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).

See: .claude/skills/devops-project-sync/SKILL.md.

Related skills