microsoft/state-management
How to manage workflow state and tasks.md files
npx skills add https://github.com/microsoft/upgrade-agent-plugins --skill state-management
Instructions for managing workflow state files.
> This skill covers 8 sections. Read all before starting work.
>
> | # | Section | Key Content |
> |---|---------|-------------|
> | 1 | State Files Overview | File purposes, ownership, including task.md |
> | 2 | tasks.md | Template, recent activity format |
> | 3 | Scenario Instructions | Location, preferences format |
> | 4 | State Operations | get_state, start_task, complete_task, break_down_task |
> | 5 | Tool-Driven Navigation | Use availableTasks from tool responses |
> | 6 | File Consistency & Reconciliation | Critical — source of truth hierarchy, drift detection, reconciliation protocol |
> | 7 | Progress Bar Calculation | Counting rules, update timing |
> | 8 | Context Recovery | Cold-start / post-compaction re-sync steps, recall-intent table |
| File | Purpose | Updated By |
|------|---------|------------|
| tasks.md | Human-readable progress view | Tools (structure) + LLM (activity) |
| scenario-instructions.md | Scenario spec and preferences | LLM + User |
| tasks/{taskId}/task.md | Per-task description enriched with research — everything needed to execute the task | LLM (enriched during execution) |
Location: {RepoRoot}/.github/upgrades/{scenarioId}/tasks.md
Updated by:
# Migration Progress
**Progress**: 0/{totalTasks} tasks complete <progress value="0" max="100"></progress> 0%
**Status**: In Progress - Task {currentTaskId}
**Started**: {startDate}
**Last Updated**: {lastUpdate}
## Task Hierarchy
{generated from state.json}
**Legend**: ✅ Complete | 🔄 In Progress | 🔲 Pending | ⚠️ Blocked | ❌ Failed
## Current Focus
🔄 **{taskId}**: {taskName}
[Details](tasks/{taskId}/task.md) | [Changes](tasks/{taskId}/progress-details.md)
## Recent Activity
{LLM appends single line per event with timestamp}
## Statistics
- Total Tasks: {totalTasks}
- Completed: {completedTasks} ({percentage}%)
- Files Modified: {filesModified}
- Projects Updated: {projectsUpdated}/{projectsTotal}
After each significant event, append to Recent Activity:
- {timestamp}: {brief description of what happened}
Examples:
2024-01-15 10:30: Completed 02.01-common-lib - updated 5 packages2024-01-15 10:45: Started 02.02-utils-lib2024-01-15 11:00: Broke down 03-shared-libraries into 3 subtasksLocation: {RepoRoot}/.github/upgrades/{scenarioId}/scenario-instructions.md
This file is ALWAYS IN CONTEXT when a workflow is active.
Contains:
Check the Preferences and Custom Instructions sections before executing any task:
## Preferences
- **Pace**: {Standard | Fast | Methodical}
- {other scenario-specific preferences}
## Custom Instructions
<!-- Task-specific overrides: "For {taskId}: {instruction}" -->
get_state(path)
Returns:
inProgressTask: Currently active task (if any)availableTasks: Tasks ready to execute (no blockers)blockedTasks: Tasks waiting on dependenciescompletedTasks: Finished tasksprogress: Completion statisticsstaleTaskWarnings: Tasks stuck in 🔄 from a previous session (see Stale Task Warnings)start_task(taskId)
Returns:
task: Task details (id, name, complexity, projects)folderCreated: Path to task folder (created JIT)needsBreakdown: Whether task should be broken downuserInstructions: Content from existing task.md (if pre-created)staleTaskWarnings: Tasks stuck in 🔄 from a previous session (see Stale Task Warnings)Updates:
tasks.md: Task shown as 🔄 In Progresstasks/{taskId}/ folder if doesn't existcomplete_task(taskId, filesModified)
Returns:
completed: Task that was completedavailableTasks: Next tasks ready to executeblockedTasks: Tasks still waiting on dependenciesprogress: Updated completion statisticsUpdates:
tasks.md: Task shown as ✅ Complete, statistics and progress bar updatedcomplete_task(taskId, filesModified, failed=true, errorMessage="...")
Returns:
availableTasks, blockedTasks: For navigationerror: Error messageUpdates:
tasks.md: Task shown as ❌ Failedbreak_down_task(parentTaskId, subtasks)
Declarative: provide the complete desired subtask list. Calling again reconciles automatically.
Returns:
subtasksCreated: List of created subtaskssubtasksRemoved: List of removed subtask IDs (if any existing children were not in the new list)availableTasks: First subtask(s) ready to executeblockedTasks: Subtasks waiting on siblingsUpdates:
tasks.md: Shows subtasks in hierarchytasks/{subtaskId}/ folders (empty, ready for task.md)Key Principle: Every state-changing tool returns availableTasks - use this to determine the next task to execute.
After each tool call:
- If availableTasks is not empty → pick next task from list
- If availableTasks is empty and blockedTasks exist → report blockers
- If availableTasks is empty and no blockedTasks → workflow complete
DO NOT parse tasks.md to determine next task - use tool responses.
get_state and start_task may return a staleTaskWarnings array — tasks that are marked 🔄 In Progress but appear to be left over from a prior session.
Each warning contains:
TaskId: The stale task's IDDescription: What the task isInstruction: Specific action to takeHandle stale warnings before starting new work:
Instruction in each warningprogress-details.md, code changes)complete_task(taskId) to finalize it, or complete_task(taskId, failed=true) to abandon itStale warnings indicate state inconsistency. Do not ignore them.
*Continue reading — Sections 6-7 cover file consistency, drift detection, and progress bar calculation.*
get_state(path) at start of each interaction to know current stateWhen files conflict, this is the priority order:
taskStates) — authoritative for task states recorded by start_task/complete_taskget_state(path) returns fileTimestamps for plan.md, tasks.md, and scenario-instructions.md.
At the start of each conversation turn:
get_state(path)fileTimestamps against what you last sawWhen plan.md changed (tasks added, removed, or reordered):
When tasks.md was edited directly:
When user says "I edited X":
*Continue reading — Section 7 covers progress bar counting rules.*
The Progress line in tasks.md tracks completion across all tasks and subtasks:
**Progress**: {completed}/{total} tasks complete <progress value="{percent}" max="100"></progress> {percent}%
Counting rules:
total = all leaf tasks + unbroken parentspercent = floor(completed / total * 100)Update this line after every complete_task() or break_down_task() call, using the progress statistics from the tool response.
Use these steps when starting a new session, or after context compaction (you can't reliably
recall the active scenario, current stage, or recent tasks).
Context compression can happen mid-session without warning. Signs it occurred:
get_state(path) — re-establish current scenario, task progress, available/blocked tasks.scenario-instructions.md — your persistent memory (user preferences, decisions,custom instructions, flow mode).
tasks/{taskId}/task.md — working memory for that task.progress-details.md of the last 1-2 completed tasks — whatactually changed, build results, issues resolved.
of reloading is seconds; the cost of executing without them is wrong decomposition, missed
tools, and failed migrations.
| User intent | Source | Example phrases |
|---|---|---|
| Recent activity | progress-details.md of completed tasks | "what happened?", "recap", "catch me up" |
| Task-specific history | tasks/{taskId}/task.md + progress-details.md | "what happened with task X?" |
| Overall status | get_state(path) + tasks.md | "status", "where are we?" |
Take microsoft/state-management from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.