Execute a single task or batch of tasks with memory support and status propagation
Executes tasks with dependency resolution, memory application, and status propagation for project workflows.
/plugin marketplace add mwguerra/claude-code-plugins/plugin install docs-specialist@mwguerra-marketplace[<task-id>] [--batch N] [--memory "..."] [--task-memory "..."]You are implementing taskmanager:run.
Execute tasks with dependency resolution, memory application, and status propagation. Replaces: execute-task, run-tasks.
$1 (optional): Task ID to execute. If omitted, picks the next available task.--batch N: Execute up to N tasks sequentially (default: 1 if omitted)--memory "description" or -gm "description": Add a global memory (persists to memories table)--task-memory "description" or -tm "description": Add a task-scoped memory (temporary)All operations use the SQLite database at .taskmanager/taskmanager.db.
run → next available task (single)run <id> → specific taskrun --batch N → batch execution of up to N taskssess-$(date +%Y%m%d%H%M%S).UPDATE state SET
session_id = '<session-id>',
last_update = datetime('now')
WHERE id = 1;
.taskmanager/logs/activity.log:
<timestamp> [DECISION] [<session-id>] Started run command
$1 if provided.--batch N value if provided.--memory provided: create global memory via taskmanager-memory skill.--task-memory provided: add to state.task_memory JSON array.For batch mode, task memories use taskId = "*" (applies to all tasks in batch).
If task ID provided, load it:
SELECT * FROM tasks WHERE id = '<task-id>' AND archived_at IS NULL;
If no task ID, find next available (milestone-aware, dependency-type-aware):
WITH done_ids AS (
SELECT id FROM tasks WHERE status IN ('done', 'canceled', 'duplicate')
),
active_milestone AS (
SELECT id FROM milestones
WHERE status IN ('active', 'planned')
ORDER BY phase_order
LIMIT 1
)
SELECT * FROM tasks t
WHERE t.archived_at IS NULL
AND t.status NOT IN ('done', 'canceled', 'duplicate', 'blocked')
AND NOT EXISTS (SELECT 1 FROM tasks c WHERE c.parent_id = t.id)
-- Only check hard dependencies (soft/informational don't block)
AND NOT EXISTS (
SELECT 1 FROM json_each(t.dependencies) d
WHERE d.value NOT IN (SELECT id FROM done_ids)
AND COALESCE((SELECT je.value FROM json_each(t.dependency_types) je WHERE je.key = d.value), 'hard') = 'hard'
)
ORDER BY
-- Prefer tasks from active milestone
CASE WHEN t.milestone_id = (SELECT id FROM active_milestone) THEN 0
WHEN t.milestone_id IS NOT NULL THEN 1
ELSE 2 END,
CASE t.priority WHEN 'critical' THEN 0 WHEN 'high' THEN 1 WHEN 'medium' THEN 2 ELSE 3 END,
COALESCE(t.business_value, 3) DESC,
CASE t.complexity_scale WHEN 'XS' THEN 0 WHEN 'S' THEN 1 WHEN 'M' THEN 2 WHEN 'L' THEN 3 WHEN 'XL' THEN 4 ELSE 2 END,
t.id
LIMIT 1;
Loop up to N times, each iteration finding the next available task using the same query.
Check dependencies with type awareness:
-- Hard dependencies (block execution)
SELECT d.value as dep_id,
COALESCE((SELECT je.value FROM json_each(t.dependency_types) je WHERE je.key = d.value), 'hard') as dep_type,
dep_t.status as dep_status
FROM tasks t, json_each(t.dependencies) d
LEFT JOIN tasks dep_t ON dep_t.id = d.value
WHERE t.id = '<task-id>'
AND d.value NOT IN (
SELECT id FROM tasks WHERE status IN ('done', 'canceled', 'duplicate')
);
Handle by dependency type:
SELECT d.id, d.title, d.body, d.reason, d.source_task_id,
t.title as source_title
FROM deferrals d
LEFT JOIN tasks t ON t.id = d.source_task_id
WHERE d.target_task_id = '<task-id>' AND d.status = 'pending'
ORDER BY d.created_at;
If deferrals exist, display them prominently:
DEFERRED WORK FOR THIS TASK:
D-0001: "Add OAuth support" (from task 1.2: "Auth System")
Reason: Too complex for MVP, deferred from sprint 1
Details: Implement OAuth2 with Google and GitHub providers...
D-0003: "Rate limiting edge cases" (from task 2.1: "API Gateway")
Reason: Non-critical, deferred to hardening phase
Details: Handle burst traffic scenarios...
These deferrals represent requirements the agent must incorporate into the task execution. They are not optional.
If the task has acceptance_criteria (non-empty JSON array), display them prominently:
ACCEPTANCE CRITERIA:
1. User can log in with email and password
2. Login page shows error for invalid credentials
3. Session persists across browser refresh
These are the product-level "done" conditions that the implementation must satisfy.
taskmanager-memory skill to query relevant memories.importance >= 3).state.task_memory.scope.tasks:
SELECT id, title, body, importance FROM memories
WHERE status = 'active'
AND EXISTS (
SELECT 1 FROM json_each(json_extract(scope, '$.tasks')) t
WHERE t.value = '<task-id>'
)
ORDER BY importance DESC;
use_count and update last_used_at for applied memories.-- Update task status
UPDATE tasks SET
status = 'in-progress',
started_at = COALESCE(started_at, datetime('now')),
updated_at = datetime('now')
WHERE id = '<task-id>';
-- Update state
UPDATE state SET
current_task_id = '<task-id>',
last_update = datetime('now')
WHERE id = 1;
Propagate in-progress status to ancestors using recursive CTE.
test_strategy exists, follow it to verify implementation.acceptance_criteria are met:
Step 1: Promote existing task-scoped memories.
state.task_memory for this task.Step 2: Proactive knowledge capture.
After promotion review, the agent MUST ask: "Did you discover anything during this task that the rest of the project should know?"
This covers architectural decisions made, constraints discovered, conventions established, patterns found, or any other knowledge that future tasks should be aware of. Examples:
If the user or agent identifies new knowledge:
Generate next memory ID:
SELECT 'M-' || printf('%04d', COALESCE(MAX(CAST(SUBSTR(id, 3) AS INTEGER)), 0) + 1)
FROM memories;
Insert with appropriate importance (4 for decisions that affect multiple tasks, 5 for hard constraints):
INSERT INTO memories (id, title, kind, why_important, body, source_type, source_name, importance, confidence, status, scope, tags)
VALUES ('<id>', '<title>', '<kind>', '<why_important>', '<body>', 'agent', 'run', <importance>, 0.8, 'active', '<scope_json>', '<tags_json>');
Log to activity.log:
<timestamp> [DECISION] [run] Created memory <id>: "<title>" (importance: <n>) from task <task-id>
These memories are automatically loaded by Step 4b of every future task execution (importance >= 3), so all subsequent tasks will be aware of them.
After memory review, ask the user: "Was any work deferred from this task to a later task?"
If yes, for each deferred item:
Generate next deferral ID:
SELECT 'D-' || printf('%04d', COALESCE(MAX(CAST(SUBSTR(id, 3) AS INTEGER)), 0) + 1)
FROM deferrals;
Collect deferral details via AskUserQuestion:
Insert the deferral:
INSERT INTO deferrals (id, source_task_id, target_task_id, title, body, reason)
VALUES ('<deferral-id>', '<current-task-id>', '<target-task-id>', '<title>', '<body>', '<reason>');
Log to activity.log:
<timestamp> [DECISION] [run] Created deferral <id>: "<title>" from task <source> to task <target>
-- Update leaf task
UPDATE tasks SET
status = '<final-status>',
completed_at = CASE WHEN '<final-status>' = 'done' THEN datetime('now') ELSE completed_at END,
duration_seconds = CASE
WHEN '<final-status>' IN ('done', 'canceled', 'duplicate') AND started_at IS NOT NULL
THEN CAST((julianday(datetime('now')) - julianday(started_at)) * 86400 AS INTEGER)
ELSE duration_seconds
END,
updated_at = datetime('now')
WHERE id = '<task-id>';
-- Propagate to ancestors
WITH RECURSIVE ancestors AS (
SELECT parent_id as id FROM tasks WHERE id = '<task-id>' AND parent_id IS NOT NULL
UNION ALL
SELECT t.parent_id FROM tasks t JOIN ancestors a ON t.id = a.id WHERE t.parent_id IS NOT NULL
)
UPDATE tasks SET
status = (
SELECT CASE
WHEN EXISTS(SELECT 1 FROM tasks c WHERE c.parent_id = tasks.id AND c.status = 'in-progress') THEN 'in-progress'
WHEN EXISTS(SELECT 1 FROM tasks c WHERE c.parent_id = tasks.id AND c.status = 'blocked') THEN 'blocked'
WHEN EXISTS(SELECT 1 FROM tasks c WHERE c.parent_id = tasks.id AND c.status = 'needs-review') THEN 'needs-review'
WHEN EXISTS(SELECT 1 FROM tasks c WHERE c.parent_id = tasks.id AND c.status IN ('planned','draft','paused')) THEN 'planned'
WHEN EXISTS(SELECT 1 FROM tasks c WHERE c.parent_id = tasks.id AND c.status = 'done') THEN 'done'
ELSE 'canceled'
END
),
updated_at = datetime('now')
WHERE id IN (SELECT id FROM ancestors);
Before marking a task as terminal (done, canceled, duplicate), check for unresolved pending deferrals:
SELECT d.id, d.title, d.status
FROM deferrals d
WHERE d.target_task_id = '<task-id>' AND d.status = 'pending';
If pending deferrals exist, the agent MUST resolve each one before proceeding. For each pending deferral, use AskUserQuestion:
UPDATE deferrals SET status = 'applied', applied_at = datetime('now'), updated_at = datetime('now')
WHERE id = '<deferral-id>';
UPDATE deferrals SET status = 'reassigned', target_task_id = '<new-target>', updated_at = datetime('now')
WHERE id = '<deferral-id>';
INSERT INTO deferrals (id, source_task_id, target_task_id, title, body, reason, status)
VALUES ('<new-id>', '<original-source>', '<new-target>', '<title>', '<body>', '<reason>', 'pending');
UPDATE deferrals SET status = 'canceled', updated_at = datetime('now')
WHERE id = '<deferral-id>';
Archive if terminal. Clear state current_task_id.
After all tasks or reaching limit:
Log completion to activity.log. Reset state session.
All logging goes to .taskmanager/logs/activity.log (single log file):
# Execute next available task
taskmanager:run
# Execute specific task
taskmanager:run 1.2.3
# Batch execute 5 tasks
taskmanager:run --batch 5
# With global memory
taskmanager:run --memory "Always validate API inputs"
# With task-scoped memory
taskmanager:run 1.2.3 --task-memory "Focus on error handling"
taskmanager:show - View tasks, dashboard, statstaskmanager:update - Update task fields and statustaskmanager:memory - Manage memories directly