Claude-skill-registry discovery-tree-workflow

Use when planning and tracking work - creates visible, emergent work breakdown using TypeScript API with just-in-time planning and hierarchical task trees

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/discovery-tree-workflow" ~/.claude/skills/majiayu000-claude-skill-registry-discovery-tree-workflow && rm -rf "$T"
manifest: skills/data/discovery-tree-workflow/SKILL.md
source content

Discovery Tree Workflow

Overview

Discovery Trees make work visible through hierarchical task breakdown that emerges just-in-time. Track work programmatically with the TypeScript API, grow the tree as you discover new requirements, maintain focus by capturing distractions.

Core principle: Start minimal, plan just-in-time, grow through discovery, make status visible.

Announce at start: "I'm using the Discovery Tree workflow to track this work."

When to Use

Always use when:

  • Starting any non-trivial work (more than a single simple task)
  • Planning features, bugs, or investigations
  • Working with multiple related tasks
  • Need to make progress visible
  • Want to capture emergent work without losing focus

Instead of:

  • TodoWrite for tracking progress
  • Upfront detailed planning
  • Hidden mental task lists
  • Linear task lists that don't show relationships

Core Philosophy

Just-in-Time Planning

  • Start with minimal detail (one task describing user value)
  • Have short conversations (2-10 minutes) to break down next steps
  • Don't plan everything upfront - plan what you need now
  • Delays planning until the last responsible moment

Emergent Work

  • New requirements discovered during work → add to tree
  • Unexpected complexity → break down further
  • Distractions or ideas → capture as tasks, mark low priority
  • Tree grows organically as understanding deepens

Visual Status

  • Color by status (open, in_progress, closed, blocked)
  • Progress visible at a glance
  • No context needed to see what's done, active, remaining
  • Bottom-up view shows full context for any task

The Discovery Tree Workflow

API Location: This skill includes a ready-to-use TypeScript API in

src/discovery-tree.ts
- a unified entry point that consolidates database operations and Shortcut integration.

TypeScript Execution: All code examples use top-level await (no async wrapper needed). Single-line imports only.

1. Set Workspace and Create Root Epic

Every Discovery Tree starts with setting workspace context, then creating an epic (container) and root task (actual work):

// Import from discovery-tree-workflow skill's src directory
// IMPORTANT: Use single-line imports only
import {
  setWorkspace,
  createTask,
  addDependency,
  updateTask,
  closeTask,
  findReadyTasks,
  getEpicStatus,
  drawTree
} from '~/.claude/skills/discovery-tree-workflow/src/discovery-tree.js';

// Set workspace context
await setWorkspace({ workspacePath: '/path/to/project' });

// Create epic (container for all work)
const epic = await createTask({
  title: "Feature: User Authentication",
  type: "epic",
  priority: 1
});

// Create root task (describes the user value)
const rootTask = await createTask({
  title: "User Authentication [root]",
  type: "task",
  priority: 1
});

// Link root task to epic
await addDependency({
  taskId: rootTask.id,
  dependsOnId: epic.id,
  type: "parent-child"
});

Why both epic and root task?

  • Epic: Container that tracks overall completion
  • Root task: Actual work item that can have subtasks

2. Initial Breakdown

Have a quick conversation (2-10 minutes) to identify first level of work:

Questions to ask:

  • "What are the main pieces of this?"
  • "What do we need to understand first?"
  • "What can we start with minimal detail?"

Create tasks for what you discover:

// Create main tasks
const task1 = await createTask({
  title: "API endpoint for login",
  type: "task",
  priority: 1
});

const task2 = await createTask({
  title: "Password validation logic",
  type: "task",
  priority: 1
});

const task3 = await createTask({
  title: "Session management",
  type: "task",
  priority: 1
});

// Link them to root task
await addDependency({
  taskId: task1.id,
  dependsOnId: rootTask.id,
  type: "parent-child"
});

await addDependency({
  taskId: task2.id,
  dependsOnId: rootTask.id,
  type: "parent-child"
});

await addDependency({
  taskId: task3.id,
  dependsOnId: rootTask.id,
  type: "parent-child"
});

Don't over-plan: Stop when you have enough to start. More detail emerges as you work.

3. Start Working

Pick a task and claim it:

// Find what's ready to work on
const readyTasks = await findReadyTasks({ limit: 10 });

// Claim the first ready task
await updateTask({
  taskId: readyTasks[0].id,
  status: "in_progress"
});

As you work:

  • Discover subtasks needed? Create and link them
  • Find blocking issues? Create with
    blocked
    status
  • Get distracted by ideas? Create low-priority task to bookmark
// Discovered more work
const subtask = await createTask({
  title: "Validate email format",
  type: "task",
  priority: 1
});

await addDependency({
  taskId: subtask.id,
  dependsOnId: task1.id,
  type: "parent-child"
});

// Found blocker
const blocker = await createTask({
  title: "Database schema needs user table",
  type: "task",
  priority: 0
});

await updateTask({
  taskId: task1.id,
  status: "blocked"
});

4. Complete and Continue

When task is done:

await closeTask({
  taskId: task1.id,
  reason: "Completed"
});

// Update parent with what was accomplished
await updateTask({
  taskId: rootTask.id,
  notes: "Completed: API endpoint for login. Previously: Initial setup"
});

IMPORTANT: Update parent task with what was accomplished to keep context accurate as subtasks complete.

Check progress:

const status = await getEpicStatus({ epicId: epic.id });
console.log(`Progress: ${status.completionPercentage}%`);
console.log(`${status.completedTasks}/${status.totalTasks} tasks complete`);

// See what's ready to work on next
const nextReady = await findReadyTasks({ limit: 5 });

If more work remains: Claim next task, repeat cycle

If work emerges: Add to tree, keep going

If blocked: Mark blocked, work on unblocked tasks

5. View Progress

// Bottom-up view from any task (current → parent → grandparent → root)
const tree = await getDependencyTree({ taskId: currentTask.id });

// Visual tree (top-down view from epic)
const visualTree = await drawTree({ taskId: epic.id });
console.log(visualTree); // Display to user

// Epic completion stats
const epicStatus = await getEpicStatus({ epicId: epic.id });

Integration with Skills

With TDD

  1. Create task for feature
  2. TDD cycle: RED → GREEN → REFACTOR
  3. If new test reveals complexity → create subtask
  4. Close task when all tests pass

With Example-Driven Design

  1. Create task for user story
  2. EXAMPLE phase discovers API shape → might create subtasks
  3. Each phase completion → progress visible in tree
  4. CHECK phase → close task or create next example task

With Mikado Method

  1. Discover prerequisite → create task with
    discovered-from
    dependency
  2. Each prerequisite becomes subtask
  3. Work on leaf tasks (no dependencies)
  4. Close prerequisites, return to parent

Quick Reference

ActionAPI Function
Set workspace
setWorkspace({ workspacePath })
Create epic
createTask({ title, type: "epic", priority: 1 })
Create task
createTask({ title, type: "task", priority })
Link to parent
addDependency({ taskId, dependsOnId, type: "parent-child" })
Claim task
updateTask({ taskId, status: "in_progress" })
Complete task
closeTask({ taskId, reason })
Update task
updateTask({ taskId, notes, description, title })
View tree
getDependencyTree({ taskId })
Draw visual tree
drawTree({ taskId })
Check progress
getEpicStatus({ epicId })
Find ready work
findReadyTasks({ limit })
Mark blocked
updateTask({ taskId, status: "blocked" })
Show task details
showTask({ taskId })
Append notes
appendNotes({ taskId, notes })

Common Patterns

Capture Distractions

// Something came up while working
const distraction = await createTask({
  title: "Refactor utils.ts for clarity",
  type: "task",
  priority: 3
});

await addDependency({
  taskId: distraction.id,
  dependsOnId: currentParent.id,
  type: "parent-child"
});
// Now it's captured, back to current work

Break Down Complex Task

// Realized task is bigger than expected
const subtask1 = await createTask({
  title: "Part 1: Schema validation",
  type: "task",
  priority: 1
});

const subtask2 = await createTask({
  title: "Part 2: Error handling",
  type: "task",
  priority: 1
});

await addDependency({
  taskId: subtask1.id,
  dependsOnId: complexTask.id,
  type: "parent-child"
});

await addDependency({
  taskId: subtask2.id,
  dependsOnId: complexTask.id,
  type: "parent-child"
});

// Parent stays open until children done
await updateTask({
  taskId: complexTask.id,
  status: "open"
});

Handle Discovered Prerequisites

// Found something that must be done first
const prerequisite = await createTask({
  title: "Add user_id column to sessions table",
  type: "task",
  priority: 0
});

await addDependency({
  taskId: currentTask.id,
  dependsOnId: prerequisite.id,
  type: "blocks"
});

await updateTask({
  taskId: currentTask.id,
  status: "blocked"
});

await updateTask({
  taskId: prerequisite.id,
  status: "in_progress"
});

Restructure Tree Based on New Learnings

// When requirements change and tree needs reorganizing
await setWorkspace({ workspacePath });

// Create new epic/structure
const newEpic = await createTask({
  title: "Revised Approach",
  type: "epic",
  priority: 1
});

// Create tasks programmatically
const tasks = await Promise.all([
  createTask({ title: "New component A", type: "task", priority: 1 }),
  createTask({ title: "New component B", type: "task", priority: 1 }),
  createTask({ title: "Integration layer", type: "task", priority: 2 })
]);

// Link all at once
for (const task of tasks) {
  await addDependency({
    taskId: task.id,
    dependsOnId: newEpic.id,
    type: "parent-child"
  });
}

// Close obsolete tasks
await closeTask({
  taskId: oldTask.id,
  reason: "Superseded by revised approach"
});

API Types

type TaskType = "bug" | "feature" | "task" | "epic" | "chore";
type TaskStatus = "open" | "in_progress" | "blocked" | "closed";
type DependencyType = "parent-child" | "blocks" | "related" | "discovered-from";

interface Task {
  id: string;
  title: string;
  description: string;
  status: TaskStatus;
  priority: number;
  taskType: TaskType;
  createdAt: string;
  updatedAt: string;
}

interface EpicStatus {
  epicId: string;
  totalTasks: number;
  completedTasks: number;
  inProgressTasks: number;
  blockedTasks: number;
  openTasks: number;
  completionPercentage: number;
}

Red Flags

STOP if you catch yourself:

  • Planning all details upfront before starting work
  • Using TodoWrite instead of discovery trees for multi-step work
  • Keeping task breakdown in your head instead of API
  • Not capturing emerged work because "it's small"
  • Marking tasks complete without using
    closeTask()
  • Closing subtasks without updating parent task with what was done
  • Forgetting to check
    findReadyTasks()
    when looking for next work
  • Creating flat task lists instead of hierarchical trees

All of these mean: Use Discovery Trees with the TypeScript API for visible, emergent planning.

Why This Works

Just-in-time planning:

  • Short conversations vs hours of upfront meetings
  • Plan what you need now, defer rest
  • Less waste from planning things that change

Emergent structure:

  • Tree grows as understanding deepens
  • Captures reality of software development (new discoveries)
  • Makes unexpected work visible, not hidden

Visual progress:

  • Anyone can see status without asking
  • Bottom-up tree shows full context
  • Epic progress shows completion percentage

Focus maintenance:

  • Distractions captured as low-priority tasks
  • Current work stays visible
  • Easy to return to main path