task-cleanup
workflow
claude_code
Created by Prasham Trivedi
Copy This Prompt
export const meta = {
name: 'task-cleanup',
description: 'Migrate legacy task directories to GitHub issues in parallel, then mark each for deletion',
whenToUse: 'Bulk-archiving a taskNotes/ directory full of completed task folders into GitHub issues',
phases: [
{ title: 'Discover', detail: 'inventory + categorize task dirs' },
{ title: 'Migrate', detail: 'one task-cleanup-specialist per dir, in parallel' },
],
}
// args: { root?: string } — parent dir holding task subdirectories. Default: "taskNotes"
const ROOT = (args && args.root) || 'taskNotes'
const INVENTORY = {
type: 'object', additionalProperties: false, required: ['dirs'],
properties: {
dirs: {
type: 'array',
items: {
type: 'object', additionalProperties: false,
required: ['path', 'name', 'category', 'existingIssue', 'extraFiles', 'commits'],
properties: {
path: { type: 'string', description: 'absolute path to the task directory' },
name: { type: 'string' },
category: { type: 'string', enum: ['completed', 'in-progress', 'planned'] },
existingIssue: { type: 'integer', description: 'GitHub issue number if taskFindings references one, else -1' },
extraFiles: { type: 'array', items: { type: 'string' }, description: 'other .md files to migrate as comments' },
commits: { type: 'array', items: { type: 'string' } },
},
},
},
},
}
const MIGRATION = {
type: 'object', additionalProperties: false,
required: ['name', 'status', 'issue', 'renamed'],
properties: {
name: { type: 'string' },
status: { type: 'string', enum: ['created', 'commented-existing', 'skipped', 'failed'] },
issue: { type: 'string', description: 'issue URL or number, else empty' },
renamed: { type: 'boolean', description: 'whether dir was renamed with [toDelete] prefix' },
},
}
phase('Discover')
const inv = await agent(
`Inventory the task directories under "${ROOT}" (resolve to an absolute path first).
For each subdirectory that contains taskFindings.md or other .md docs, determine:
- category: "completed" (has taskFindings + currentCommitHash + taskWalkThrough), "in-progress" (taskFindings + currentCommitHash), or "planned" (taskFindings only)
- existingIssue: read taskFindings.md; if it references an existing GitHub issue, return its number, else -1
- extraFiles: any other .md files in the dir (besides taskFindings) to migrate as separate comments
- commits: any commit hashes referenced (e.g. from currentCommitHash)
Skip dirs already prefixed with [toDelete]. Do NOT modify anything in this phase — read only.`,
{ label: 'discover', phase: 'Discover', schema: INVENTORY, agentType: 'task-cleanup-specialist' }
)
if (!inv || !inv.dirs.length) {
log(`No migratable task directories found under ${ROOT}.`)
return { migrated: [], note: 'nothing to do' }
}
log(`Found ${inv.dirs.length} task dir(s) to migrate.`)
phase('Migrate')
// Each dir is independent (separate GitHub issue, separate folder) — true fan-out, no worktree needed.
const migrations = await parallel(inv.dirs.map(d => () =>
agent(
`Migrate exactly ONE task directory to GitHub, then mark it for deletion. Directory (absolute): ${d.path}
Category: ${d.category}. Existing issue number: ${d.existingIssue} (-1 means none).
Steps:
1. Extract a meaningful title from taskFindings.md ("{Verb}: {context}", never generic).
2. If existingIssue >= 0: add taskFindings.md verbatim as the first comment on that issue. Else: create a new issue with taskFindings.md verbatim as the body.
3. Add each extra file (${JSON.stringify(d.extraFiles)}) as its own separate comment.
4. If there are commits (${JSON.stringify(d.commits)}), add one comment: "Related commits: <hashes>".
5. Close the issue (these are archives).
6. Rename the dir: mv "${d.path}" to the same parent with a "[toDelete]_" prefix. Verify the rename succeeded.
Use the gh CLI and absolute paths throughout. Return the outcome.`,
{ label: `migrate:${d.name}`, phase: 'Migrate', schema: MIGRATION, agentType: 'task-cleanup-specialist' }
)
))
const done = migrations.filter(Boolean)
return {
migrated: done,
summary: {
total: inv.dirs.length,
created: done.filter(m => m.status === 'created').length,
commented: done.filter(m => m.status === 'commented-existing').length,
failed: done.filter(m => m.status === 'failed').length,
renamed: done.filter(m => m.renamed).length,
},
}
Workflow Details
- Phases: None
Format Availability
Workflows are available in Claude Code format only and are delivered as-is. They cannot be converted to Codex or Gemini.
Actions
(Clears cached conversions and forces re-processing)