| name | project-documentation-workflow |
| description | Wave-based comprehensive project documentation generator with dynamic task decomposition. Analyzes project structure and generates appropriate documentation tasks, computes optimal execution waves via topological sort, produces complete documentation suite including architecture, methods, theory, features, usage, and design philosophy. |
| argument-hint | [-y|--yes] [-c|--concurrency N] [--continue] "project path or description" |
| allowed-tools | spawn_agents_on_csv, Read, Write, Edit, Bash, Glob, Grep, request_user_input |
Auto Mode
When --yes or -y: Auto-confirm task decomposition, skip interactive validation, use defaults.
Project Documentation Workflow (Optimized)
Usage
$project-documentation-workflow "Document the authentication module in src/auth/"
$project-documentation-workflow -c 4 "Generate full docs for the FEM solver project"
$project-documentation-workflow -y "Document entire codebase with architecture and API"
$project-documentation-workflow --continue "doc-auth-module-20260304"
Flags:
-y, --yes: Skip all confirmations (auto mode)
-c, --concurrency N: Max concurrent agents within each wave (default: 3)
--continue: Resume existing session
Output Directory: .workflow/.csv-wave/{session-id}/
Core Output: tasks.csv + results.csv + discoveries.ndjson + wave-summaries/ + docs/ (ๅฎๆดๆๆกฃ้)
Overview
ไผๅ็๏ผๅจๆไปปๅกๅ่งฃ + ๆๆๆๅบๆณขๆฌก่ฎก็ฎ + ๆณขๆฌก้ด็ปผๅๆญฅ้ชคใ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PROJECT DOCUMENTATION WORKFLOW (Dynamic & Optimized) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Phase 0: Dynamic Decomposition โ
โ โโ Analyze project structure, complexity, domain โ
โ โโ Generate appropriate documentation tasks (ๅจๆๆฐ้) โ
โ โโ Compute task dependencies (deps) โ
โ โโ Compute execution waves (topological sort) โ
โ โโ User validates task breakdown (skip if -y) โ
โ โ
โ Phase 1: Wave Execution (with Inter-Wave Synthesis) โ
โ โโ For each wave (1..N, dynamically computed): โ
โ โ โโ Load Wave Summary from previous wave โ
โ โ โโ Build wave CSV with prev_context injection โ
โ โ โโ spawn_agents_on_csv(wave CSV) โ
โ โ โโ Collect results, merge into master tasks.csv โ
โ โ โโ Generate Wave Summary (ๆณขๆฌก็ปผๅ) โ
โ โ โโ Check: any failed? โ skip dependents โ
โ โโ discoveries.ndjson shared across all waves โ
โ โ
โ Phase 2: Results Aggregation โ
โ โโ Export final results.csv โ
โ โโ Generate context.md with all findings โ
โ โโ Generate docs/index.md navigation โ
โ โโ Display summary: completed/failed/skipped per wave โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
CSV Schema
tasks.csv (Master State)
id,title,description,doc_type,target_scope,doc_sections,formula_support,priority,deps,context_from,wave,status,findings,doc_path,key_discoveries,error
"doc-001","้กน็ฎๆฆ่ฟฐ","ๆฐๅ้กน็ฎ็ๆดไฝๆฆ่ฟฐ","overview","README.md,package.json","purpose,background,positioning,audience","false","high","","","1","pending","","","",""
Columns:
| Column | Type | Required | Description |
|---|
id | string | Yes | Task ID (doc-NNN, auto-generated) |
title | string | Yes | Document title |
description | string | Yes | Detailed task description |
doc_type | enum | Yes | `overview |
target_scope | string | Yes | File scope (glob pattern) |
doc_sections | string | Yes | Required sections (comma-separated) |
formula_support | boolean | No | LaTeX formula support |
priority | enum | No | `high |
deps | string | No | Dependency task IDs (semicolon-separated) |
context_from | string | No | Context source task IDs |
wave | integer | Computed | Wave number (computed by topological sort) |
status | enum | Output | `pendingโcompleted |
findings | string | Output | Key findings summary |
doc_path | string | Output | Generated document path |
key_discoveries | string | Output | Key discoveries (JSON) |
error | string | Output | Error message |
Implementation
Session Initialization
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()
const AUTO_YES = $ARGUMENTS.includes('--yes') || $ARGUMENTS.includes('-y')
const continueMode = $ARGUMENTS.includes('--continue')
const concurrencyMatch = $ARGUMENTS.match(/(?:--concurrency|-c)\s+(\d+)/)
const maxConcurrency = concurrencyMatch ? parseInt(concurrencyMatch[1]) : 3
const requirement = $ARGUMENTS
.replace(/--yes|-y|--continue|--concurrency\s+\d+|-c\s+\d+/g, '')
.trim()
const slug = requirement.toLowerCase()
.replace(/[^a-z0-9\u4e00-\u9fa5]+/g, '-')
.substring(0, 40)
const dateStr = getUtc8ISOString().substring(0, 10).replace(/-/g, '')
const sessionId =
sessionFolder =
()
(, )
Phase 0: Dynamic Task Decomposition
Objective: Analyze the project and dynamically generate appropriate documentation tasks.
Step 1: Project Analysis
Bash({
command: `ccw cli -p "PURPOSE: Analyze the project and determine appropriate documentation tasks.
TASK:
1. Scan project structure to identify:
- Project type (library/application/service/CLI/tool)
- Primary language(s) and frameworks
- Project scale (small/medium/large based on file count and complexity)
- Key modules and their purposes
- Existing documentation (README, docs/, etc.)
2. Determine documentation needs based on project characteristics:
- For ALL projects: overview, tech-stack, directory-structure
- For libraries: api-reference, usage-guide, best-practices
- For applications: system-architecture, feature-list, usage-guide
- For numerical/scientific projects: theoretical-foundations (with formula_support=true)
- For services: api-reference, module-interactions, deployment
- For complex projects (>50 files): add design-patterns, data-model
- For simple projects (<10 files): reduce to essential docs only
3. Generate task list with:
- Unique task IDs (doc-001, doc-002, ...)
- Appropriate doc_type for each task
- Target scope (glob patterns) based on actual project structure
- Required sections for each document type
- Dependencies (deps) between related tasks
- Context sources (context_from) for information flow
- Priority (high for essential docs, medium for useful, low for optional)
4. Task dependency rules:
- overview tasks: no deps (Wave 1)
- architecture tasks: depend on overview tasks
- implementation tasks: depend on architecture tasks
- feature/api tasks: depend on implementation
- synthesis tasks: depend on most other tasks
MODE: analysis
CONTEXT: @**/*
EXPECTED: JSON with:
- project_info: {type, scale, languages, frameworks, modules[]}
- recommended_waves: number of waves suggested
- tasks: [{id, title, description, doc_type, target_scope, doc_sections, formula_support, priority, deps[], context_from[]}]
CONSTRAINTS:
- Small projects: 5-8 tasks max
- Medium projects: 10-15 tasks
- Large projects: 15-25 tasks
- Each doc_type should appear at most once unless justified
- deps must form a valid DAG (no cycles)
PROJECT TO ANALYZE: ${requirement}" --tool gemini --mode analysis --rule planning-breakdown-task-steps`,
run_in_background: true
})
Step 2: Topological Sort (Wave Computation)
function computeWaves(tasks) {
const graph = new Map()
const inDegree = new Map()
const taskMap = new Map()
for (const task of tasks) {
taskMap.set(task.id, task)
graph.set(task.id, [])
inDegree.set(task.id, 0)
}
for (const task of tasks) {
const deps = task.deps.filter(d => taskMap.has(d))
for (const dep of deps) {
graph.get(dep).push(task.id)
inDegree.set(task.id, inDegree.get(task.id) + 1)
}
}
const waves = []
let currentWave = []
for (const [id, degree] inDegree) {
(degree === ) currentWave.(id)
}
(currentWave. > ) {
waves.([...currentWave])
nextWave = []
( id currentWave) {
( neighbor graph.(id)) {
inDegree.(neighbor, inDegree.(neighbor) - )
(inDegree.(neighbor) === ) {
nextWave.(neighbor)
}
}
}
currentWave = nextWave
}
( w = ; w < waves.; w++) {
( id waves[w]) {
taskMap.(id). = w +
}
}
assignedCount = tasks.( t. > ).
(assignedCount < tasks.) {
()
}
{
: tasks,
: waves.,
: waves.( ({ : i + , : w. }))
}
}
Step 3: User Validation
const analysisResult = JSON.parse(decompositionOutput)
const { tasks, project_info, waveCount } = analysisResult
const { tasks: tasksWithWaves, waveCount: computedWaves, waveDistribution } = computeWaves(tasks)
if (!AUTO_YES) {
console.log(`
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PROJECT ANALYSIS RESULT โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ Type: ${project_info.type.padEnd(20)} Scale: ${project_info.scale.padEnd(10)} โ
โ Languages: ${project_info.languages.join(', ').substring(0, 40).padEnd(40)} โ
โ Modules: ${project_info.modules.length} identified โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฃ
โ WAVE DISTRIBUTION (${computedWaves} waves, ${tasksWithWaves.length} tasks) โ
${waveDistribution.map(w => `โ Wave ${w.wave}: ${w.tasks} tasks${' '.repeat(50 - w.tasks.toString().length)}`).join('\n')}
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
`)
for (let w = 1; w <= computedWaves; w++) {
const waveTasks = tasksWithWaves.( t. === w)
.()
( t waveTasks) {
.()
}
}
answer = functions.({
: [{
: ,
: ,
: ,
: [
{ : , : },
{ : , : }
]
}]
})
(answer...[] !== ) {
.()
}
}
(, (tasksWithWaves))
(, .(project_info, , ))
Phase 1: Wave Execution (with Inter-Wave Synthesis)
Key Optimization: Add Wave Summary generation between waves for better context propagation.
const masterCsv = Read(`${sessionFolder}/tasks.csv`)
let tasks = parseCsv(masterCsv)
const maxWave = Math.max(...tasks.map(t => t.wave))
for (let wave = 1; wave <= maxWave; wave++) {
console.log(`\n{'='*60}`)
console.log(`Wave ${wave}/${maxWave}`)
console.log('='.repeat(60))
const waveSummaryPath = `${sessionFolder}/wave-summaries/wave-${wave-1}-summary.md`
let prevWaveSummary = ''
if (wave > 1 && fileExists(waveSummaryPath)) {
prevWaveSummary = Read(waveSummaryPath)
console.log(`Loaded Wave ${wave-1} Summary (${prevWaveSummary.length} chars)`)
}
const waveTasks = tasks.filter( t. === wave && t. === )
( task waveTasks) {
depIds = (task. || ).().()
depStatuses = depIds.( tasks.( t. === id)?.)
(depStatuses.( s === || s === )) {
task. =
task. =
}
}
pendingTasks = waveTasks.( t. === )
(pendingTasks. === ) {
.()
}
( task pendingTasks) {
contextIds = (task. || ).().()
prevFindings = contextIds.( {
src = tasks.( t. === id)
(!src?.)
}).().()
waveContext = prevWaveSummary ?
:
discoveries = ()
relevantDiscoveries = discoveries
.()
.( line.())
.( .(line))
.( (d, task))
.(, )
.( )
.()
discoveryContext = relevantDiscoveries ?
:
task. = prevFindings + waveContext + discoveryContext
}
(, (pendingTasks))
({
: ,
: ,
: (sessionFolder, wave),
: maxConcurrency,
: ,
: ,
: {
: ,
: {
: { : },
: { : , : [, ] },
: { : },
: { : },
: { : },
: { : }
}
}
})
results = (())
( r results) {
t = tasks.( t. === r.)
(t) .(t, r)
}
(, (tasks))
completedThisWave = results.( r. === )
(completedThisWave. > ) {
waveSummary = (wave, completedThisWave, tasks)
(, waveSummary)
.()
}
()
completed = results.( r. === ).
failed = results.( r. === ).
.()
}
Wave Summary Generation (Inter-Wave Synthesis)
function generateWaveSummary(waveNum, completedTasks, allTasks) {
let summary = `# Wave ${waveNum} Summary\n\n`
summary += `**Completed Tasks**: ${completedTasks.length}\n\n`
const byType = {}
for (const task of completedTasks) {
const type = task.doc_type || 'unknown'
if (!byType[type]) byType[type] = []
byType[type].push(task)
}
for (const [type, tasks] of Object.entries(byType)) {
summary += `## ${type.toUpperCase()}\n\n`
for (const t of tasks) {
summary += `### ${t.title}\n`
if (t.findings) {
summary += `${t.findings.substring(0, 300)}${t.findings.length > 300 ? '...' : ''}\n\n`
}
if (t.key_discoveries) {
try {
const discoveries = JSON.parse(t.key_discoveries)
summary += `**Key Points**:\n`
for ( d discoveries.(, )) {
summary +=
}
summary +=
} (e) {}
}
}
}
nextWaveTasks = allTasks.( t. === waveNum + )
(nextWaveTasks. > ) {
summary +=
summary +=
}
summary
}
() {
taskScope = task. ||
taskType = task. ||
(taskType === && discovery..())
(taskType === && discovery..())
(taskType === && discovery..())
(discovery.?.) {
taskScope.(discovery...()[])
}
}
Optimized Instruction Template
function buildOptimizedInstruction(sessionFolder, wave) {
return `## DOCUMENTATION TASK โ Wave ${wave}
### โ ๏ธ MANDATORY FIRST STEPS (DO NOT SKIP)
1. **CHECK DISCOVERIES FIRST** (้ฟๅ
้ๅคๅทฅไฝ):
\`\`\`bash
# Search for existing discoveries about your topic
grep -i "{doc_type}" ${sessionFolder}/discoveries.ndjson
grep -i "{target_keywords}" ${sessionFolder}/discoveries.ndjson
\`\`\`
2. **Read Wave Summary** (้ซๅฏๅบฆไธไธๆ):
- Read: ${sessionFolder}/wave-summaries/wave-${wave-1}-summary.md (if exists)
3. **Read prev_context** (provided below)
---
## Your Task
**Task ID**: {id}
**Title**: {title}
**Document Type**: {doc_type}
**Target Scope**: {target_scope}
**Required Sections**: {doc_sections}
**LaTeX Support**: {formula_support}
**Priority**: {priority}
### Task Description
{description}
### Previous Context (USE THIS!)
{prev_context}
---
## Execution Protocol
### Step 1: Discovery Check (MANDATORY)
Before reading any source files:
- Search discoveries.ndjson for existing findings
- Note any pre-discovered components, patterns, algorithms
- Avoid re-documenting what's already found
### Step 2: Scope Analysis
- Read files matching \`{target_scope}\`
- Identify key structures, functions, classes
- Extract relevant code patterns
### Step 3: Context Integration
- Build on findings from prev_context
- Reference Wave Summary insights
- Connect to discoveries from other agents
### Step 4: Document Generation
**Output Path**: Determine based on doc_type:
- \`overview\` โ \`docs/01-overview/\`
- \`architecture\` โ \`docs/02-architecture/\`
- \`implementation\` โ \`docs/03-implementation/\`
- \`feature\` โ \`docs/04-features/\`
- \`api\` โ \`docs/04-features/\`
- \`usage\` โ \`docs/04-features/\`
- \`synthesis\` โ \`docs/05-synthesis/\`
**Document Structure**:
\`\`\`markdown
# {Title}
## Overview
[Brief introduction]
## {Required Section 1}
[Content with code examples]
## {Required Section 2}
[Content with diagrams if applicable]
...
## Code Examples
\`\`\`{language}
// file:line references
\`\`\`
## Cross-References
- Related: [Doc](path)
- Depends: [Prereq](path)
## Summary
[Key takeaways]
\`\`\`
### Step 5: Share Discoveries (MANDATORY)
Append to discovery board:
\`\`\`bash
echo '{"ts":"${getUtc8ISOString()}","worker":"{id}","type":"<TYPE>","data":{...}}' >> ${sessionFolder}/discoveries.ndjson
\`\`\`
**Discovery Types**:
- \`component_found\`: {name, type, file, purpose}
- \`pattern_found\`: {pattern_name, location, description}
- \`algorithm_found\`: {name, file, complexity, purpose}
- \`formula_found\`: {name, latex, file, context}
- \`feature_found\`: {name, entry_point, description}
- \`api_found\`: {endpoint, file, parameters, returns}
- \`config_found\`: {name, file, type, default_value}
### Step 6: Report
\`\`\`json
{
"id": "{id}",
"status": "completed",
"findings": "Key discoveries (max 500 chars, structured for context propagation)",
"doc_path": "docs/XX-category/filename.md",
"key_discoveries": "[{\"name\":\"...\",\"type\":\"...\",\"description\":\"...\",\"file\":\"...\"}]",
"error": ""
}
\`\`\`
---
## Quality Requirements
| Requirement | Criteria |
|-------------|----------|
| Section Coverage | ALL sections in doc_sections present |
| Code References | Include file:line for code |
| Discovery Sharing | At least 2 discoveries shared |
| Context Usage | Reference prev_context findings |
| Cross-References | Link to related docs |
`
}
Phase 2: Results Aggregation
const tasks = parseCsv(Read(`${sessionFolder}/tasks.csv`))
const completed = tasks.filter(t => t.status === 'completed')
const byType = {}
for (const t of completed) {
const type = t.doc_type || 'other'
if (!byType[type]) byType[type] = []
byType[type].push(t)
}
let index = `# Project Documentation Index\n\n`
index += `**Generated**: ${getUtc8ISOString().substring(0, 10)}\n`
index += `**Total Documents**: ${completed.length}\n\n`
const typeLabels = {
overview: '๐ ๆฆ่ง',
architecture: '๐๏ธ ๆถๆ',
implementation: 'โ๏ธ ๅฎ็ฐ',
theory: '๐ ็่ฎบ',
feature: 'โจ ๅ่ฝ',
api: '๐ API',
usage: '๐ ไฝฟ็จ',
synthesis: '๐ก ็ปผๅ'
}
for (const [type, typeTasks] of Object.(byType)) {
label = typeLabels[type] || type
index +=
( t typeTasks) {
index +=
}
index +=
}
index +=
index +=
index +=
(, index)
()
projectInfo = .(())
contextMd =
contextMd +=
contextMd +=
contextMd +=
contextMd +=
contextMd +=
contextMd +=
statusCounts = {
: tasks.( t. === ).,
: tasks.( t. === ).,
: tasks.( t. === ).
}
contextMd +=
contextMd +=
contextMd +=
contextMd +=
contextMd +=
contextMd +=
maxWave = .(...tasks.( t.))
contextMd +=
( w = ; w <= maxWave; w++) {
waveTasks = tasks.( t. === w)
contextMd +=
( t waveTasks) {
icon = t. === ? : t. === ? :
contextMd +=
(t.) {
contextMd +=
}
(t.) {
contextMd +=
}
contextMd +=
}
}
(, contextMd)
.()
Optimized Output Structure
.workflow/.csv-wave/doc-{date}-{slug}/
โโโ project-info.json # ้กน็ฎๅๆ็ปๆ
โโโ tasks.csv # Master CSV (ๅจๆ็ๆ็ไปปๅก)
โโโ results.csv # ๆ็ป็ปๆ
โโโ discoveries.ndjson # ๅ็ฐๆฟ
โโโ context.md # ๆง่กๆฅๅ
โ
โโโ wave-summaries/ # NEW: ๆณขๆฌกๆ่ฆ
โ โโโ wave-1-summary.md
โ โโโ wave-2-summary.md
โ โโโ ...
โ
โโโ docs/
โโโ index.md # ๆๆกฃๅฏผ่ช
โโโ 01-overview/
โโโ 02-architecture/
โโโ 03-implementation/
โโโ 04-features/
โโโ 05-synthesis/
Optimization Summary
| ไผๅ็น | ๅ็ | ไผๅ็ |
|---|
| ไปปๅกๆฐ้ | ๅบๅฎ17ไปปๅก | ๅจๆ็ๆ (5-25ๅบไบ้กน็ฎ่งๆจก) |
| ๆณขๆฌก่ฎก็ฎ | ็กฌ็ผ็ 5ๆณข | ๆๆๆๅบๅจๆ่ฎก็ฎ |
| ไธไธๆไผ ๆญ | ไป
prev_context | prev_context + Wave Summary + Discoveries |
| ๅ็ฐๅฉ็จ | ไพ่ต่ช่ง | ๅผบๅถ็ฌฌไธๆญฅๆฃๆฅ |
| ๆๆกฃๅฏๅบฆ | ๅๅง findings | ็ปๆๅ Wave Summary |
Core Rules
- Dynamic First: ไปปๅกๅ่กจๅจๆ็ๆ๏ผไธ้ข่ฎพ
- Wave Order is Sacred: ๆณขๆฌก็ฑๆๆๆๅบๅณๅฎ
- Discovery Check Mandatory: ๅฟ
้กปๅ
ๆฃๆฅๅ็ฐๆฟ
- Wave Summary: ๆฏๆณขๆฌก็ปๆ็ๆๆ่ฆ
- Context Compound: ไธไธๆ็ดฏ็งฏไผ ๆญ
- Quality Gates: ๆฏๆๆกฃๅฟ
้กป่ฆ็ๆๆ doc_sections
- DO NOT STOP: ๆ็ปญๆง่ก็ดๅฐๆๆๆณขๆฌกๅฎๆ