claude-code-workflow 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/action-planning-agent.md +778 -0
- package/.claude/agents/cli-execution-agent.md +270 -0
- package/.claude/agents/cli-explore-agent.md +182 -0
- package/.claude/agents/cli-lite-planning-agent.md +396 -0
- package/.claude/agents/cli-planning-agent.md +558 -0
- package/.claude/agents/code-developer.md +310 -0
- package/.claude/agents/conceptual-planning-agent.md +308 -0
- package/.claude/agents/context-search-agent.md +582 -0
- package/.claude/agents/doc-generator.md +330 -0
- package/.claude/agents/memory-bridge.md +94 -0
- package/.claude/agents/test-context-search-agent.md +399 -0
- package/.claude/agents/test-fix-agent.md +343 -0
- package/.claude/agents/ui-design-agent.md +593 -0
- package/.claude/agents/universal-executor.md +131 -0
- package/.claude/commands/cli/cli-init.md +440 -0
- package/.claude/commands/enhance-prompt.md +93 -0
- package/.claude/commands/memory/code-map-memory.md +687 -0
- package/.claude/commands/memory/docs-full-cli.md +471 -0
- package/.claude/commands/memory/docs-related-cli.md +386 -0
- package/.claude/commands/memory/docs.md +615 -0
- package/.claude/commands/memory/load-skill-memory.md +182 -0
- package/.claude/commands/memory/load.md +240 -0
- package/.claude/commands/memory/skill-memory.md +525 -0
- package/.claude/commands/memory/style-skill-memory.md +396 -0
- package/.claude/commands/memory/tech-research.md +477 -0
- package/.claude/commands/memory/update-full.md +332 -0
- package/.claude/commands/memory/update-related.md +332 -0
- package/.claude/commands/memory/workflow-skill-memory.md +517 -0
- package/.claude/commands/task/breakdown.md +204 -0
- package/.claude/commands/task/create.md +152 -0
- package/.claude/commands/task/execute.md +270 -0
- package/.claude/commands/task/replan.md +437 -0
- package/.claude/commands/version.md +254 -0
- package/.claude/commands/workflow/action-plan-verify.md +447 -0
- package/.claude/commands/workflow/brainstorm/api-designer.md +585 -0
- package/.claude/commands/workflow/brainstorm/artifacts.md +452 -0
- package/.claude/commands/workflow/brainstorm/auto-parallel.md +443 -0
- package/.claude/commands/workflow/brainstorm/data-architect.md +220 -0
- package/.claude/commands/workflow/brainstorm/product-manager.md +200 -0
- package/.claude/commands/workflow/brainstorm/product-owner.md +200 -0
- package/.claude/commands/workflow/brainstorm/scrum-master.md +200 -0
- package/.claude/commands/workflow/brainstorm/subject-matter-expert.md +200 -0
- package/.claude/commands/workflow/brainstorm/synthesis.md +398 -0
- package/.claude/commands/workflow/brainstorm/system-architect.md +387 -0
- package/.claude/commands/workflow/brainstorm/ui-designer.md +221 -0
- package/.claude/commands/workflow/brainstorm/ux-expert.md +221 -0
- package/.claude/commands/workflow/execute.md +460 -0
- package/.claude/commands/workflow/init.md +164 -0
- package/.claude/commands/workflow/lite-execute.md +686 -0
- package/.claude/commands/workflow/lite-fix.md +621 -0
- package/.claude/commands/workflow/lite-plan.md +592 -0
- package/.claude/commands/workflow/plan.md +551 -0
- package/.claude/commands/workflow/replan.md +515 -0
- package/.claude/commands/workflow/review-fix.md +646 -0
- package/.claude/commands/workflow/review-module-cycle.md +795 -0
- package/.claude/commands/workflow/review-session-cycle.md +805 -0
- package/.claude/commands/workflow/review.md +291 -0
- package/.claude/commands/workflow/session/complete.md +500 -0
- package/.claude/commands/workflow/session/list.md +96 -0
- package/.claude/commands/workflow/session/resume.md +61 -0
- package/.claude/commands/workflow/session/start.md +200 -0
- package/.claude/commands/workflow/status.md +352 -0
- package/.claude/commands/workflow/tdd-plan.md +460 -0
- package/.claude/commands/workflow/tdd-verify.md +386 -0
- package/.claude/commands/workflow/test-cycle-execute.md +498 -0
- package/.claude/commands/workflow/test-fix-gen.md +699 -0
- package/.claude/commands/workflow/test-gen.md +529 -0
- package/.claude/commands/workflow/tools/conflict-resolution.md +680 -0
- package/.claude/commands/workflow/tools/context-gather.md +434 -0
- package/.claude/commands/workflow/tools/task-generate-agent.md +291 -0
- package/.claude/commands/workflow/tools/task-generate-tdd.md +518 -0
- package/.claude/commands/workflow/tools/tdd-coverage-analysis.md +309 -0
- package/.claude/commands/workflow/tools/test-concept-enhanced.md +163 -0
- package/.claude/commands/workflow/tools/test-context-gather.md +235 -0
- package/.claude/commands/workflow/tools/test-task-generate.md +256 -0
- package/.claude/commands/workflow/ui-design/animation-extract.md +1150 -0
- package/.claude/commands/workflow/ui-design/codify-style.md +652 -0
- package/.claude/commands/workflow/ui-design/design-sync.md +454 -0
- package/.claude/commands/workflow/ui-design/explore-auto.md +678 -0
- package/.claude/commands/workflow/ui-design/generate.md +504 -0
- package/.claude/commands/workflow/ui-design/imitate-auto.md +745 -0
- package/.claude/commands/workflow/ui-design/import-from-code.md +537 -0
- package/.claude/commands/workflow/ui-design/layout-extract.md +788 -0
- package/.claude/commands/workflow/ui-design/reference-page-generator.md +356 -0
- package/.claude/commands/workflow/ui-design/style-extract.md +773 -0
- package/.claude/scripts/classify-folders.sh +35 -0
- package/.claude/scripts/convert_tokens_to_css.sh +225 -0
- package/.claude/scripts/detect_changed_modules.sh +157 -0
- package/.claude/scripts/discover-design-files.sh +83 -0
- package/.claude/scripts/extract-animations.js +243 -0
- package/.claude/scripts/extract-computed-styles.js +118 -0
- package/.claude/scripts/extract-layout-structure.js +411 -0
- package/.claude/scripts/generate_module_docs.sh +713 -0
- package/.claude/scripts/get_modules_by_depth.sh +166 -0
- package/.claude/scripts/ui-generate-preview.sh +391 -0
- package/.claude/scripts/ui-instantiate-prototypes.sh +811 -0
- package/.claude/scripts/update_module_claude.sh +333 -0
- package/.claude/skills/command-guide/SKILL.md +388 -0
- package/.claude/skills/command-guide/UPDATE-GUIDELINE.md +592 -0
- package/.claude/skills/command-guide/guides/cli-tools-guide.md +410 -0
- package/.claude/skills/command-guide/guides/examples.md +537 -0
- package/.claude/skills/command-guide/guides/getting-started.md +242 -0
- package/.claude/skills/command-guide/guides/implementation-details.md +1010 -0
- package/.claude/skills/command-guide/guides/index-structure.md +326 -0
- package/.claude/skills/command-guide/guides/troubleshooting.md +92 -0
- package/.claude/skills/command-guide/guides/ui-design-workflow-guide.md +316 -0
- package/.claude/skills/command-guide/guides/workflow-patterns.md +662 -0
- package/.claude/skills/command-guide/index/all-commands.json +783 -0
- package/.claude/skills/command-guide/index/by-category.json +811 -0
- package/.claude/skills/command-guide/index/by-use-case.json +797 -0
- package/.claude/skills/command-guide/index/command-relationships.json +307 -0
- package/.claude/skills/command-guide/index/essential-commands.json +123 -0
- package/.claude/skills/command-guide/reference/agents/action-planning-agent.md +722 -0
- package/.claude/skills/command-guide/reference/agents/cli-execution-agent.md +270 -0
- package/.claude/skills/command-guide/reference/agents/cli-explore-agent.md +182 -0
- package/.claude/skills/command-guide/reference/agents/cli-lite-planning-agent.md +396 -0
- package/.claude/skills/command-guide/reference/agents/cli-planning-agent.md +558 -0
- package/.claude/skills/command-guide/reference/agents/code-developer.md +310 -0
- package/.claude/skills/command-guide/reference/agents/conceptual-planning-agent.md +328 -0
- package/.claude/skills/command-guide/reference/agents/context-search-agent.md +577 -0
- package/.claude/skills/command-guide/reference/agents/doc-generator.md +330 -0
- package/.claude/skills/command-guide/reference/agents/memory-bridge.md +94 -0
- package/.claude/skills/command-guide/reference/agents/test-context-search-agent.md +399 -0
- package/.claude/skills/command-guide/reference/agents/test-fix-agent.md +343 -0
- package/.claude/skills/command-guide/reference/agents/ui-design-agent.md +593 -0
- package/.claude/skills/command-guide/reference/agents/universal-executor.md +131 -0
- package/.claude/skills/command-guide/reference/commands/cli/cli-init.md +440 -0
- package/.claude/skills/command-guide/reference/commands/enhance-prompt.md +93 -0
- package/.claude/skills/command-guide/reference/commands/memory/code-map-memory.md +687 -0
- package/.claude/skills/command-guide/reference/commands/memory/docs-full-cli.md +471 -0
- package/.claude/skills/command-guide/reference/commands/memory/docs-related-cli.md +386 -0
- package/.claude/skills/command-guide/reference/commands/memory/docs.md +610 -0
- package/.claude/skills/command-guide/reference/commands/memory/load-skill-memory.md +182 -0
- package/.claude/skills/command-guide/reference/commands/memory/load.md +240 -0
- package/.claude/skills/command-guide/reference/commands/memory/skill-memory.md +525 -0
- package/.claude/skills/command-guide/reference/commands/memory/style-skill-memory.md +396 -0
- package/.claude/skills/command-guide/reference/commands/memory/tech-research.md +477 -0
- package/.claude/skills/command-guide/reference/commands/memory/update-full.md +332 -0
- package/.claude/skills/command-guide/reference/commands/memory/update-related.md +332 -0
- package/.claude/skills/command-guide/reference/commands/memory/workflow-skill-memory.md +517 -0
- package/.claude/skills/command-guide/reference/commands/task/breakdown.md +204 -0
- package/.claude/skills/command-guide/reference/commands/task/create.md +152 -0
- package/.claude/skills/command-guide/reference/commands/task/execute.md +270 -0
- package/.claude/skills/command-guide/reference/commands/task/replan.md +437 -0
- package/.claude/skills/command-guide/reference/commands/version.md +254 -0
- package/.claude/skills/command-guide/reference/commands/workflow/action-plan-verify.md +447 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/api-designer.md +585 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/artifacts.md +604 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/auto-parallel.md +466 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/data-architect.md +220 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-manager.md +200 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/product-owner.md +200 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/scrum-master.md +200 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/subject-matter-expert.md +200 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/synthesis.md +496 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/system-architect.md +387 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ui-designer.md +221 -0
- package/.claude/skills/command-guide/reference/commands/workflow/brainstorm/ux-expert.md +221 -0
- package/.claude/skills/command-guide/reference/commands/workflow/execute.md +460 -0
- package/.claude/skills/command-guide/reference/commands/workflow/init.md +164 -0
- package/.claude/skills/command-guide/reference/commands/workflow/lite-execute.md +634 -0
- package/.claude/skills/command-guide/reference/commands/workflow/lite-fix.md +602 -0
- package/.claude/skills/command-guide/reference/commands/workflow/lite-plan.md +582 -0
- package/.claude/skills/command-guide/reference/commands/workflow/plan.md +551 -0
- package/.claude/skills/command-guide/reference/commands/workflow/replan.md +515 -0
- package/.claude/skills/command-guide/reference/commands/workflow/review-fix.md +646 -0
- package/.claude/skills/command-guide/reference/commands/workflow/review-module-cycle.md +795 -0
- package/.claude/skills/command-guide/reference/commands/workflow/review-session-cycle.md +805 -0
- package/.claude/skills/command-guide/reference/commands/workflow/review.md +291 -0
- package/.claude/skills/command-guide/reference/commands/workflow/session/complete.md +500 -0
- package/.claude/skills/command-guide/reference/commands/workflow/session/list.md +96 -0
- package/.claude/skills/command-guide/reference/commands/workflow/session/resume.md +61 -0
- package/.claude/skills/command-guide/reference/commands/workflow/session/start.md +180 -0
- package/.claude/skills/command-guide/reference/commands/workflow/status.md +352 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-plan.md +460 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tdd-verify.md +386 -0
- package/.claude/skills/command-guide/reference/commands/workflow/test-cycle-execute.md +498 -0
- package/.claude/skills/command-guide/reference/commands/workflow/test-fix-gen.md +699 -0
- package/.claude/skills/command-guide/reference/commands/workflow/test-gen.md +529 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/conflict-resolution.md +680 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/context-gather.md +434 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-agent.md +151 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/task-generate-tdd.md +518 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/tdd-coverage-analysis.md +309 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-concept-enhanced.md +163 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-context-gather.md +235 -0
- package/.claude/skills/command-guide/reference/commands/workflow/tools/test-task-generate.md +256 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/animation-extract.md +1150 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/codify-style.md +652 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/design-sync.md +454 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/explore-auto.md +678 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/generate.md +504 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/imitate-auto.md +745 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/import-from-code.md +537 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/layout-extract.md +788 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/reference-page-generator.md +356 -0
- package/.claude/skills/command-guide/reference/commands/workflow/ui-design/style-extract.md +773 -0
- package/.claude/skills/command-guide/scripts/analyze_commands.py +502 -0
- package/.claude/skills/command-guide/scripts/update-index.sh +130 -0
- package/.claude/skills/command-guide/templates/issue-bug.md +104 -0
- package/.claude/skills/command-guide/templates/issue-diagnosis.md +275 -0
- package/.claude/skills/command-guide/templates/issue-feature.md +97 -0
- package/.claude/skills/command-guide/templates/issue-question.md +141 -0
- package/.claude/skills/prompt-enhancer/SKILL.md +124 -0
- package/.claude/workflows/_template-compare-matrix.html +692 -0
- package/.claude/workflows/cli-templates/fix-plan-template.json +75 -0
- package/.claude/workflows/cli-templates/fix-progress-template.json +48 -0
- package/.claude/workflows/cli-templates/memory/style-skill-memory/skill-md-template.md +299 -0
- package/.claude/workflows/cli-templates/planning-roles/data-architect.md +120 -0
- package/.claude/workflows/cli-templates/planning-roles/product-manager.md +119 -0
- package/.claude/workflows/cli-templates/planning-roles/product-owner.md +261 -0
- package/.claude/workflows/cli-templates/planning-roles/scrum-master.md +186 -0
- package/.claude/workflows/cli-templates/planning-roles/subject-matter-expert.md +281 -0
- package/.claude/workflows/cli-templates/planning-roles/synthesis-role.md +414 -0
- package/.claude/workflows/cli-templates/planning-roles/system-architect.md +106 -0
- package/.claude/workflows/cli-templates/planning-roles/test-strategist.md +124 -0
- package/.claude/workflows/cli-templates/planning-roles/ui-designer.md +379 -0
- package/.claude/workflows/cli-templates/planning-roles/ux-expert.md +240 -0
- package/.claude/workflows/cli-templates/prompts/analysis/01-diagnose-bug-root-cause.txt +127 -0
- package/.claude/workflows/cli-templates/prompts/analysis/01-trace-code-execution.txt +115 -0
- package/.claude/workflows/cli-templates/prompts/analysis/02-analyze-code-patterns.txt +37 -0
- package/.claude/workflows/cli-templates/prompts/analysis/02-analyze-technical-document.txt +33 -0
- package/.claude/workflows/cli-templates/prompts/analysis/02-review-architecture.txt +29 -0
- package/.claude/workflows/cli-templates/prompts/analysis/02-review-code-quality.txt +28 -0
- package/.claude/workflows/cli-templates/prompts/analysis/03-analyze-performance.txt +29 -0
- package/.claude/workflows/cli-templates/prompts/analysis/03-assess-security-risks.txt +29 -0
- package/.claude/workflows/cli-templates/prompts/analysis/03-review-quality-standards.txt +29 -0
- package/.claude/workflows/cli-templates/prompts/development/02-generate-tests.txt +70 -0
- package/.claude/workflows/cli-templates/prompts/development/02-implement-component-ui.txt +55 -0
- package/.claude/workflows/cli-templates/prompts/development/02-implement-feature.txt +58 -0
- package/.claude/workflows/cli-templates/prompts/development/02-refactor-codebase.txt +55 -0
- package/.claude/workflows/cli-templates/prompts/development/03-debug-runtime-issues.txt +55 -0
- package/.claude/workflows/cli-templates/prompts/documentation/api.txt +15 -0
- package/.claude/workflows/cli-templates/prompts/documentation/folder-navigation.txt +27 -0
- package/.claude/workflows/cli-templates/prompts/documentation/module-readme.txt +49 -0
- package/.claude/workflows/cli-templates/prompts/documentation/project-architecture.txt +41 -0
- package/.claude/workflows/cli-templates/prompts/documentation/project-examples.txt +35 -0
- package/.claude/workflows/cli-templates/prompts/documentation/project-readme.txt +35 -0
- package/.claude/workflows/cli-templates/prompts/memory/02-document-module-structure.txt +165 -0
- package/.claude/workflows/cli-templates/prompts/planning/01-plan-architecture-design.txt +109 -0
- package/.claude/workflows/cli-templates/prompts/planning/02-breakdown-task-steps.txt +30 -0
- package/.claude/workflows/cli-templates/prompts/planning/02-design-component-spec.txt +28 -0
- package/.claude/workflows/cli-templates/prompts/planning/03-evaluate-concept-feasibility.txt +127 -0
- package/.claude/workflows/cli-templates/prompts/planning/03-plan-migration-strategy.txt +30 -0
- package/.claude/workflows/cli-templates/prompts/tech/tech-module-format.txt +359 -0
- package/.claude/workflows/cli-templates/prompts/tech/tech-skill-index.txt +185 -0
- package/.claude/workflows/cli-templates/prompts/test/test-concept-analysis.txt +179 -0
- package/.claude/workflows/cli-templates/prompts/universal/00-universal-creative-style.txt +95 -0
- package/.claude/workflows/cli-templates/prompts/universal/00-universal-rigorous-style.txt +92 -0
- package/.claude/workflows/cli-templates/prompts/verification/codex-technical.txt +28 -0
- package/.claude/workflows/cli-templates/prompts/verification/cross-validation.txt +28 -0
- package/.claude/workflows/cli-templates/prompts/verification/gemini-strategic.txt +27 -0
- package/.claude/workflows/cli-templates/prompts/workflow/analysis-results-structure.txt +224 -0
- package/.claude/workflows/cli-templates/prompts/workflow/codex-feasibility-validation.txt +176 -0
- package/.claude/workflows/cli-templates/prompts/workflow/gemini-solution-design.txt +131 -0
- package/.claude/workflows/cli-templates/prompts/workflow/impl-plan-template.txt +286 -0
- package/.claude/workflows/cli-templates/prompts/workflow/skill-aggregation.txt +172 -0
- package/.claude/workflows/cli-templates/prompts/workflow/skill-conflict-patterns.txt +98 -0
- package/.claude/workflows/cli-templates/prompts/workflow/skill-index.txt +224 -0
- package/.claude/workflows/cli-templates/prompts/workflow/skill-lessons-learned.txt +98 -0
- package/.claude/workflows/cli-templates/prompts/workflow/skill-sessions-timeline.txt +53 -0
- package/.claude/workflows/cli-templates/prompts/workflow/task-json-agent-mode.txt +123 -0
- package/.claude/workflows/cli-templates/prompts/workflow/task-json-cli-mode.txt +182 -0
- package/.claude/workflows/cli-templates/schemas/diagnosis-json-schema.json +234 -0
- package/.claude/workflows/cli-templates/schemas/explore-json-schema.json +124 -0
- package/.claude/workflows/cli-templates/schemas/fix-plan-json-schema.json +273 -0
- package/.claude/workflows/cli-templates/schemas/plan-json-schema.json +219 -0
- package/.claude/workflows/cli-templates/schemas/project-json-schema.json +221 -0
- package/.claude/workflows/cli-templates/schemas/review-deep-dive-results-schema.json +82 -0
- package/.claude/workflows/cli-templates/schemas/review-dimension-results-schema.json +51 -0
- package/.claude/workflows/cli-templates/tech-stacks/go-dev.md +91 -0
- package/.claude/workflows/cli-templates/tech-stacks/java-dev.md +107 -0
- package/.claude/workflows/cli-templates/tech-stacks/javascript-dev.md +58 -0
- package/.claude/workflows/cli-templates/tech-stacks/python-dev.md +79 -0
- package/.claude/workflows/cli-templates/tech-stacks/react-dev.md +103 -0
- package/.claude/workflows/cli-templates/tech-stacks/typescript-dev.md +83 -0
- package/.claude/workflows/cli-templates/ui-design/systems/animation-tokens.json +247 -0
- package/.claude/workflows/cli-templates/ui-design/systems/design-tokens.json +342 -0
- package/.claude/workflows/cli-templates/ui-design/systems/layout-templates.json +145 -0
- package/.claude/workflows/context-search-strategy.md +77 -0
- package/.claude/workflows/intelligent-tools-strategy.md +662 -0
- package/.claude/workflows/review-directory-specification.md +336 -0
- package/.claude/workflows/task-core.md +214 -0
- package/.claude/workflows/tool-strategy.md +71 -0
- package/.claude/workflows/workflow-architecture.md +942 -0
- package/.codex/AGENTS.md +330 -0
- package/.gemini/GEMINI.md +164 -0
- package/.qwen/QWEN.md +164 -0
- package/CLAUDE.md +91 -0
- package/LICENSE +21 -0
- package/README.md +219 -0
- package/ccw/README.md +121 -0
- package/ccw/bin/ccw.js +10 -0
- package/ccw/src/cli.js +100 -0
- package/ccw/src/commands/install.js +324 -0
- package/ccw/src/commands/list.js +37 -0
- package/ccw/src/commands/serve.js +67 -0
- package/ccw/src/commands/uninstall.js +238 -0
- package/ccw/src/commands/upgrade.js +307 -0
- package/ccw/src/commands/view.js +14 -0
- package/ccw/src/core/dashboard-generator-patch.js +29 -0
- package/ccw/src/core/dashboard-generator.js +667 -0
- package/ccw/src/core/data-aggregator.js +409 -0
- package/ccw/src/core/lite-scanner.js +290 -0
- package/ccw/src/core/manifest.js +201 -0
- package/ccw/src/core/server.js +1327 -0
- package/ccw/src/core/server.js.bak +385 -0
- package/ccw/src/core/server_original.bak +385 -0
- package/ccw/src/core/session-scanner.js +235 -0
- package/ccw/src/index.js +9 -0
- package/ccw/src/templates/dashboard-js/api.js +200 -0
- package/ccw/src/templates/dashboard-js/components/_conflict_tab.js +112 -0
- package/ccw/src/templates/dashboard-js/components/_exp_helpers.js +54 -0
- package/ccw/src/templates/dashboard-js/components/_review_tab.js +640 -0
- package/ccw/src/templates/dashboard-js/components/carousel.js +398 -0
- package/ccw/src/templates/dashboard-js/components/flowchart.js +493 -0
- package/ccw/src/templates/dashboard-js/components/hook-manager.js +273 -0
- package/ccw/src/templates/dashboard-js/components/mcp-manager.js +506 -0
- package/ccw/src/templates/dashboard-js/components/modals.js +260 -0
- package/ccw/src/templates/dashboard-js/components/navigation.js +239 -0
- package/ccw/src/templates/dashboard-js/components/notifications.js +194 -0
- package/ccw/src/templates/dashboard-js/components/sidebar.js +31 -0
- package/ccw/src/templates/dashboard-js/components/tabs-context.js +1093 -0
- package/ccw/src/templates/dashboard-js/components/tabs-other.js +273 -0
- package/ccw/src/templates/dashboard-js/components/task-drawer-core.js +477 -0
- package/ccw/src/templates/dashboard-js/components/task-drawer-renderers.js +447 -0
- package/ccw/src/templates/dashboard-js/components/theme.js +21 -0
- package/ccw/src/templates/dashboard-js/main.js +57 -0
- package/ccw/src/templates/dashboard-js/state.js +37 -0
- package/ccw/src/templates/dashboard-js/utils.js +153 -0
- package/ccw/src/templates/dashboard-js/views/fix-session.js +180 -0
- package/ccw/src/templates/dashboard-js/views/home.js +193 -0
- package/ccw/src/templates/dashboard-js/views/hook-manager.js +387 -0
- package/ccw/src/templates/dashboard-js/views/lite-tasks.js +390 -0
- package/ccw/src/templates/dashboard-js/views/mcp-manager.js +271 -0
- package/ccw/src/templates/dashboard-js/views/project-overview.js +246 -0
- package/ccw/src/templates/dashboard-js/views/review-session.js +711 -0
- package/ccw/src/templates/dashboard-js/views/session-detail.js +770 -0
- package/ccw/src/templates/dashboard.css +7660 -0
- package/ccw/src/templates/dashboard.html +630 -0
- package/ccw/src/templates/dashboard_tailwind.html +42 -0
- package/ccw/src/templates/dashboard_test.html +37 -0
- package/ccw/src/templates/review-cycle-dashboard.html +1930 -0
- package/ccw/src/templates/tailwind-base.css +212 -0
- package/ccw/src/templates/workflow-dashboard.html +401 -0
- package/ccw/src/utils/browser-launcher.js +49 -0
- package/ccw/src/utils/file-utils.js +48 -0
- package/ccw/src/utils/path-resolver.js +279 -0
- package/ccw/src/utils/ui.js +148 -0
- package/package.json +66 -0
|
@@ -0,0 +1,409 @@
|
|
|
1
|
+
import { glob } from 'glob';
|
|
2
|
+
import { readFileSync, existsSync } from 'fs';
|
|
3
|
+
import { join, basename } from 'path';
|
|
4
|
+
import { scanLiteTasks } from './lite-scanner.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Aggregate all data for dashboard rendering
|
|
8
|
+
* @param {Object} sessions - Scanned sessions from session-scanner
|
|
9
|
+
* @param {string} workflowDir - Path to .workflow directory
|
|
10
|
+
* @returns {Promise<Object>} - Aggregated dashboard data
|
|
11
|
+
*/
|
|
12
|
+
export async function aggregateData(sessions, workflowDir) {
|
|
13
|
+
const data = {
|
|
14
|
+
generatedAt: new Date().toISOString(),
|
|
15
|
+
activeSessions: [],
|
|
16
|
+
archivedSessions: [],
|
|
17
|
+
liteTasks: {
|
|
18
|
+
litePlan: [],
|
|
19
|
+
liteFix: []
|
|
20
|
+
},
|
|
21
|
+
reviewData: null,
|
|
22
|
+
projectOverview: null,
|
|
23
|
+
statistics: {
|
|
24
|
+
totalSessions: 0,
|
|
25
|
+
activeSessions: 0,
|
|
26
|
+
totalTasks: 0,
|
|
27
|
+
completedTasks: 0,
|
|
28
|
+
reviewFindings: 0,
|
|
29
|
+
litePlanCount: 0,
|
|
30
|
+
liteFixCount: 0
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
// Process active sessions
|
|
35
|
+
for (const session of sessions.active) {
|
|
36
|
+
const sessionData = await processSession(session, true);
|
|
37
|
+
data.activeSessions.push(sessionData);
|
|
38
|
+
data.statistics.totalTasks += sessionData.tasks.length;
|
|
39
|
+
data.statistics.completedTasks += sessionData.tasks.filter(t => t.status === 'completed').length;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Process archived sessions
|
|
43
|
+
for (const session of sessions.archived) {
|
|
44
|
+
const sessionData = await processSession(session, false);
|
|
45
|
+
data.archivedSessions.push(sessionData);
|
|
46
|
+
data.statistics.totalTasks += sessionData.taskCount || 0;
|
|
47
|
+
data.statistics.completedTasks += sessionData.taskCount || 0;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Aggregate review data if present
|
|
51
|
+
if (sessions.hasReviewData) {
|
|
52
|
+
data.reviewData = await aggregateReviewData(sessions.active);
|
|
53
|
+
data.statistics.reviewFindings = data.reviewData.totalFindings;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
data.statistics.totalSessions = sessions.active.length + sessions.archived.length;
|
|
57
|
+
data.statistics.activeSessions = sessions.active.length;
|
|
58
|
+
|
|
59
|
+
// Scan and include lite tasks
|
|
60
|
+
try {
|
|
61
|
+
const liteTasks = await scanLiteTasks(workflowDir);
|
|
62
|
+
data.liteTasks = liteTasks;
|
|
63
|
+
data.statistics.litePlanCount = liteTasks.litePlan.length;
|
|
64
|
+
data.statistics.liteFixCount = liteTasks.liteFix.length;
|
|
65
|
+
} catch (err) {
|
|
66
|
+
console.error('Error scanning lite tasks:', err.message);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Load project overview from project.json
|
|
70
|
+
try {
|
|
71
|
+
data.projectOverview = loadProjectOverview(workflowDir);
|
|
72
|
+
} catch (err) {
|
|
73
|
+
console.error('Error loading project overview:', err.message);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return data;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Process a single session, loading tasks and review info
|
|
81
|
+
* @param {Object} session - Session object from scanner
|
|
82
|
+
* @param {boolean} isActive - Whether session is active
|
|
83
|
+
* @returns {Promise<Object>} - Processed session data
|
|
84
|
+
*/
|
|
85
|
+
async function processSession(session, isActive) {
|
|
86
|
+
const result = {
|
|
87
|
+
session_id: session.session_id,
|
|
88
|
+
project: session.project || session.session_id,
|
|
89
|
+
status: session.status || (isActive ? 'active' : 'archived'),
|
|
90
|
+
type: session.type || 'workflow', // Session type (workflow, review, test, docs)
|
|
91
|
+
workflow_type: session.workflow_type || null, // Original workflow_type for reference
|
|
92
|
+
created_at: session.created_at || null, // Raw ISO string - let frontend format
|
|
93
|
+
archived_at: session.archived_at || null, // Raw ISO string - let frontend format
|
|
94
|
+
path: session.path,
|
|
95
|
+
tasks: [],
|
|
96
|
+
taskCount: 0,
|
|
97
|
+
hasReview: false,
|
|
98
|
+
reviewSummary: null,
|
|
99
|
+
reviewDimensions: []
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
// Load tasks for active sessions (full details)
|
|
103
|
+
if (isActive) {
|
|
104
|
+
const taskDir = join(session.path, '.task');
|
|
105
|
+
if (existsSync(taskDir)) {
|
|
106
|
+
const taskFiles = await safeGlob('IMPL-*.json', taskDir);
|
|
107
|
+
for (const taskFile of taskFiles) {
|
|
108
|
+
try {
|
|
109
|
+
const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8'));
|
|
110
|
+
result.tasks.push({
|
|
111
|
+
task_id: taskData.id || basename(taskFile, '.json'),
|
|
112
|
+
title: taskData.title || 'Untitled Task',
|
|
113
|
+
status: taskData.status || 'pending',
|
|
114
|
+
type: taskData.meta?.type || 'task',
|
|
115
|
+
meta: taskData.meta || {},
|
|
116
|
+
context: taskData.context || {},
|
|
117
|
+
flow_control: taskData.flow_control || {}
|
|
118
|
+
});
|
|
119
|
+
} catch {
|
|
120
|
+
// Skip invalid task files
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Sort tasks by ID
|
|
124
|
+
result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id));
|
|
125
|
+
}
|
|
126
|
+
result.taskCount = result.tasks.length;
|
|
127
|
+
|
|
128
|
+
// Check for review data
|
|
129
|
+
const reviewDir = join(session.path, '.review');
|
|
130
|
+
if (existsSync(reviewDir)) {
|
|
131
|
+
result.hasReview = true;
|
|
132
|
+
result.reviewSummary = loadReviewSummary(reviewDir);
|
|
133
|
+
// Load dimension data for review sessions
|
|
134
|
+
if (session.type === 'review') {
|
|
135
|
+
result.reviewDimensions = await loadDimensionData(reviewDir);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
// For archived, also load tasks (same as active)
|
|
140
|
+
const taskDir = join(session.path, '.task');
|
|
141
|
+
if (existsSync(taskDir)) {
|
|
142
|
+
const taskFiles = await safeGlob('IMPL-*.json', taskDir);
|
|
143
|
+
for (const taskFile of taskFiles) {
|
|
144
|
+
try {
|
|
145
|
+
const taskData = JSON.parse(readFileSync(join(taskDir, taskFile), 'utf8'));
|
|
146
|
+
result.tasks.push({
|
|
147
|
+
task_id: taskData.id || basename(taskFile, '.json'),
|
|
148
|
+
title: taskData.title || 'Untitled Task',
|
|
149
|
+
status: taskData.status || 'completed', // Archived tasks are usually completed
|
|
150
|
+
type: taskData.meta?.type || 'task'
|
|
151
|
+
});
|
|
152
|
+
} catch {
|
|
153
|
+
// Skip invalid task files
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
// Sort tasks by ID
|
|
157
|
+
result.tasks.sort((a, b) => sortTaskIds(a.task_id, b.task_id));
|
|
158
|
+
result.taskCount = result.tasks.length;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Check for review data in archived sessions too
|
|
162
|
+
const reviewDir = join(session.path, '.review');
|
|
163
|
+
if (existsSync(reviewDir)) {
|
|
164
|
+
result.hasReview = true;
|
|
165
|
+
result.reviewSummary = loadReviewSummary(reviewDir);
|
|
166
|
+
// Load dimension data for review sessions
|
|
167
|
+
if (session.type === 'review') {
|
|
168
|
+
result.reviewDimensions = await loadDimensionData(reviewDir);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return result;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Aggregate review data from all active sessions with reviews
|
|
178
|
+
* @param {Array} activeSessions - Active session objects
|
|
179
|
+
* @returns {Promise<Object>} - Aggregated review data
|
|
180
|
+
*/
|
|
181
|
+
async function aggregateReviewData(activeSessions) {
|
|
182
|
+
const reviewData = {
|
|
183
|
+
totalFindings: 0,
|
|
184
|
+
severityDistribution: { critical: 0, high: 0, medium: 0, low: 0 },
|
|
185
|
+
dimensionSummary: {},
|
|
186
|
+
sessions: []
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
for (const session of activeSessions) {
|
|
190
|
+
const reviewDir = join(session.path, '.review');
|
|
191
|
+
if (!existsSync(reviewDir)) continue;
|
|
192
|
+
|
|
193
|
+
const reviewProgress = loadReviewProgress(reviewDir);
|
|
194
|
+
const dimensionData = await loadDimensionData(reviewDir);
|
|
195
|
+
|
|
196
|
+
if (reviewProgress || dimensionData.length > 0) {
|
|
197
|
+
const sessionReview = {
|
|
198
|
+
session_id: session.session_id,
|
|
199
|
+
progress: reviewProgress,
|
|
200
|
+
dimensions: dimensionData,
|
|
201
|
+
findings: []
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
// Collect and count findings
|
|
205
|
+
for (const dim of dimensionData) {
|
|
206
|
+
if (dim.findings && Array.isArray(dim.findings)) {
|
|
207
|
+
for (const finding of dim.findings) {
|
|
208
|
+
const severity = (finding.severity || 'low').toLowerCase();
|
|
209
|
+
if (reviewData.severityDistribution.hasOwnProperty(severity)) {
|
|
210
|
+
reviewData.severityDistribution[severity]++;
|
|
211
|
+
}
|
|
212
|
+
reviewData.totalFindings++;
|
|
213
|
+
sessionReview.findings.push({
|
|
214
|
+
...finding,
|
|
215
|
+
dimension: dim.name
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Track dimension summary
|
|
221
|
+
if (!reviewData.dimensionSummary[dim.name]) {
|
|
222
|
+
reviewData.dimensionSummary[dim.name] = { count: 0, sessions: [] };
|
|
223
|
+
}
|
|
224
|
+
reviewData.dimensionSummary[dim.name].count += dim.findings?.length || 0;
|
|
225
|
+
reviewData.dimensionSummary[dim.name].sessions.push(session.session_id);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
reviewData.sessions.push(sessionReview);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return reviewData;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Load review progress from review-progress.json
|
|
237
|
+
* @param {string} reviewDir - Path to .review directory
|
|
238
|
+
* @returns {Object|null}
|
|
239
|
+
*/
|
|
240
|
+
function loadReviewProgress(reviewDir) {
|
|
241
|
+
const progressFile = join(reviewDir, 'review-progress.json');
|
|
242
|
+
if (!existsSync(progressFile)) return null;
|
|
243
|
+
try {
|
|
244
|
+
return JSON.parse(readFileSync(progressFile, 'utf8'));
|
|
245
|
+
} catch {
|
|
246
|
+
return null;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Load review summary from review-state.json
|
|
252
|
+
* @param {string} reviewDir - Path to .review directory
|
|
253
|
+
* @returns {Object|null}
|
|
254
|
+
*/
|
|
255
|
+
function loadReviewSummary(reviewDir) {
|
|
256
|
+
const stateFile = join(reviewDir, 'review-state.json');
|
|
257
|
+
if (!existsSync(stateFile)) return null;
|
|
258
|
+
try {
|
|
259
|
+
const state = JSON.parse(readFileSync(stateFile, 'utf8'));
|
|
260
|
+
return {
|
|
261
|
+
phase: state.phase || 'unknown',
|
|
262
|
+
severityDistribution: state.severity_distribution || {},
|
|
263
|
+
criticalFiles: (state.critical_files || []).slice(0, 3),
|
|
264
|
+
status: state.status || 'in_progress'
|
|
265
|
+
};
|
|
266
|
+
} catch {
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Load dimension data from .review/dimensions/
|
|
273
|
+
* @param {string} reviewDir - Path to .review directory
|
|
274
|
+
* @returns {Promise<Array>}
|
|
275
|
+
*/
|
|
276
|
+
async function loadDimensionData(reviewDir) {
|
|
277
|
+
const dimensionsDir = join(reviewDir, 'dimensions');
|
|
278
|
+
if (!existsSync(dimensionsDir)) return [];
|
|
279
|
+
|
|
280
|
+
const dimensions = [];
|
|
281
|
+
const dimFiles = await safeGlob('*.json', dimensionsDir);
|
|
282
|
+
|
|
283
|
+
for (const file of dimFiles) {
|
|
284
|
+
try {
|
|
285
|
+
const data = JSON.parse(readFileSync(join(dimensionsDir, file), 'utf8'));
|
|
286
|
+
// Handle array structure: [ { findings: [...], summary: {...} } ]
|
|
287
|
+
let findings = [];
|
|
288
|
+
let summary = null;
|
|
289
|
+
let status = 'completed';
|
|
290
|
+
|
|
291
|
+
if (Array.isArray(data) && data.length > 0) {
|
|
292
|
+
const dimData = data[0];
|
|
293
|
+
findings = dimData.findings || [];
|
|
294
|
+
summary = dimData.summary || null;
|
|
295
|
+
status = dimData.status || 'completed';
|
|
296
|
+
} else if (data.findings) {
|
|
297
|
+
findings = data.findings;
|
|
298
|
+
summary = data.summary || null;
|
|
299
|
+
status = data.status || 'completed';
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
dimensions.push({
|
|
303
|
+
name: basename(file, '.json'),
|
|
304
|
+
findings: findings,
|
|
305
|
+
summary: summary,
|
|
306
|
+
status: status
|
|
307
|
+
});
|
|
308
|
+
} catch {
|
|
309
|
+
// Skip invalid dimension files
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return dimensions;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Safe glob wrapper that returns empty array on error
|
|
318
|
+
* @param {string} pattern - Glob pattern
|
|
319
|
+
* @param {string} cwd - Current working directory
|
|
320
|
+
* @returns {Promise<string[]>}
|
|
321
|
+
*/
|
|
322
|
+
async function safeGlob(pattern, cwd) {
|
|
323
|
+
try {
|
|
324
|
+
return await glob(pattern, { cwd, absolute: false });
|
|
325
|
+
} catch {
|
|
326
|
+
return [];
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// formatDate removed - dates are now passed as raw ISO strings
|
|
331
|
+
// Frontend (dashboard.js) handles all date formatting
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Sort task IDs numerically (IMPL-1, IMPL-2, IMPL-1.1, etc.)
|
|
335
|
+
* @param {string} a - First task ID
|
|
336
|
+
* @param {string} b - Second task ID
|
|
337
|
+
* @returns {number}
|
|
338
|
+
*/
|
|
339
|
+
function sortTaskIds(a, b) {
|
|
340
|
+
const parseId = (id) => {
|
|
341
|
+
const match = id.match(/IMPL-(\d+)(?:\.(\d+))?/);
|
|
342
|
+
if (!match) return [0, 0];
|
|
343
|
+
return [parseInt(match[1]), parseInt(match[2] || 0)];
|
|
344
|
+
};
|
|
345
|
+
const [a1, a2] = parseId(a);
|
|
346
|
+
const [b1, b2] = parseId(b);
|
|
347
|
+
return a1 - b1 || a2 - b2;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Load project overview from project.json
|
|
352
|
+
* @param {string} workflowDir - Path to .workflow directory
|
|
353
|
+
* @returns {Object|null} - Project overview data or null if not found
|
|
354
|
+
*/
|
|
355
|
+
function loadProjectOverview(workflowDir) {
|
|
356
|
+
const projectFile = join(workflowDir, 'project.json');
|
|
357
|
+
|
|
358
|
+
if (!existsSync(projectFile)) {
|
|
359
|
+
console.log(`Project file not found at: ${projectFile}`);
|
|
360
|
+
return null;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
try {
|
|
364
|
+
const fileContent = readFileSync(projectFile, 'utf8');
|
|
365
|
+
const projectData = JSON.parse(fileContent);
|
|
366
|
+
|
|
367
|
+
console.log(`Successfully loaded project overview: ${projectData.project_name || 'Unknown'}`);
|
|
368
|
+
|
|
369
|
+
return {
|
|
370
|
+
projectName: projectData.project_name || 'Unknown',
|
|
371
|
+
description: projectData.overview?.description || '',
|
|
372
|
+
initializedAt: projectData.initialized_at || null,
|
|
373
|
+
technologyStack: projectData.overview?.technology_stack || {
|
|
374
|
+
languages: [],
|
|
375
|
+
frameworks: [],
|
|
376
|
+
build_tools: [],
|
|
377
|
+
test_frameworks: []
|
|
378
|
+
},
|
|
379
|
+
architecture: projectData.overview?.architecture || {
|
|
380
|
+
style: 'Unknown',
|
|
381
|
+
layers: [],
|
|
382
|
+
patterns: []
|
|
383
|
+
},
|
|
384
|
+
keyComponents: projectData.overview?.key_components || [],
|
|
385
|
+
features: projectData.features || [],
|
|
386
|
+
developmentIndex: projectData.development_index || {
|
|
387
|
+
feature: [],
|
|
388
|
+
enhancement: [],
|
|
389
|
+
bugfix: [],
|
|
390
|
+
refactor: [],
|
|
391
|
+
docs: []
|
|
392
|
+
},
|
|
393
|
+
statistics: projectData.statistics || {
|
|
394
|
+
total_features: 0,
|
|
395
|
+
total_sessions: 0,
|
|
396
|
+
last_updated: null
|
|
397
|
+
},
|
|
398
|
+
metadata: projectData._metadata || {
|
|
399
|
+
initialized_by: 'unknown',
|
|
400
|
+
analysis_timestamp: null,
|
|
401
|
+
analysis_mode: 'unknown'
|
|
402
|
+
}
|
|
403
|
+
};
|
|
404
|
+
} catch (err) {
|
|
405
|
+
console.error(`Failed to parse project.json at ${projectFile}:`, err.message);
|
|
406
|
+
console.error('Error stack:', err.stack);
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
import { existsSync, readdirSync, readFileSync, statSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Scan lite-plan and lite-fix directories for task sessions
|
|
6
|
+
* @param {string} workflowDir - Path to .workflow directory
|
|
7
|
+
* @returns {Promise<Object>} - Lite tasks data
|
|
8
|
+
*/
|
|
9
|
+
export async function scanLiteTasks(workflowDir) {
|
|
10
|
+
const litePlanDir = join(workflowDir, '.lite-plan');
|
|
11
|
+
const liteFixDir = join(workflowDir, '.lite-fix');
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
litePlan: scanLiteDir(litePlanDir, 'lite-plan'),
|
|
15
|
+
liteFix: scanLiteDir(liteFixDir, 'lite-fix')
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Scan a lite task directory
|
|
21
|
+
* @param {string} dir - Directory path
|
|
22
|
+
* @param {string} type - Task type ('lite-plan' or 'lite-fix')
|
|
23
|
+
* @returns {Array} - Array of lite task sessions
|
|
24
|
+
*/
|
|
25
|
+
function scanLiteDir(dir, type) {
|
|
26
|
+
if (!existsSync(dir)) return [];
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const sessions = readdirSync(dir, { withFileTypes: true })
|
|
30
|
+
.filter(d => d.isDirectory())
|
|
31
|
+
.map(d => {
|
|
32
|
+
const sessionPath = join(dir, d.name);
|
|
33
|
+
const session = {
|
|
34
|
+
id: d.name,
|
|
35
|
+
type,
|
|
36
|
+
path: sessionPath,
|
|
37
|
+
createdAt: getCreatedTime(sessionPath),
|
|
38
|
+
plan: loadPlanJson(sessionPath),
|
|
39
|
+
tasks: loadTaskJsons(sessionPath)
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
// Calculate progress
|
|
43
|
+
session.progress = calculateProgress(session.tasks);
|
|
44
|
+
|
|
45
|
+
return session;
|
|
46
|
+
})
|
|
47
|
+
.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
|
|
48
|
+
|
|
49
|
+
return sessions;
|
|
50
|
+
} catch (err) {
|
|
51
|
+
console.error(`Error scanning ${dir}:`, err.message);
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Load plan.json from session directory
|
|
58
|
+
* @param {string} sessionPath - Session directory path
|
|
59
|
+
* @returns {Object|null} - Plan data or null
|
|
60
|
+
*/
|
|
61
|
+
function loadPlanJson(sessionPath) {
|
|
62
|
+
const planPath = join(sessionPath, 'plan.json');
|
|
63
|
+
if (!existsSync(planPath)) return null;
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const content = readFileSync(planPath, 'utf8');
|
|
67
|
+
return JSON.parse(content);
|
|
68
|
+
} catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Load all task JSON files from session directory
|
|
75
|
+
* Supports multiple task formats:
|
|
76
|
+
* 1. .task/IMPL-*.json files
|
|
77
|
+
* 2. tasks array in plan.json
|
|
78
|
+
* 3. task-*.json files in session root
|
|
79
|
+
* @param {string} sessionPath - Session directory path
|
|
80
|
+
* @returns {Array} - Array of task objects
|
|
81
|
+
*/
|
|
82
|
+
function loadTaskJsons(sessionPath) {
|
|
83
|
+
let tasks = [];
|
|
84
|
+
|
|
85
|
+
// Method 1: Check .task/IMPL-*.json files
|
|
86
|
+
const taskDir = join(sessionPath, '.task');
|
|
87
|
+
if (existsSync(taskDir)) {
|
|
88
|
+
try {
|
|
89
|
+
const implTasks = readdirSync(taskDir)
|
|
90
|
+
.filter(f => f.endsWith('.json') && (
|
|
91
|
+
f.startsWith('IMPL-') ||
|
|
92
|
+
f.startsWith('TASK-') ||
|
|
93
|
+
f.startsWith('task-') ||
|
|
94
|
+
/^T\d+\.json$/i.test(f)
|
|
95
|
+
))
|
|
96
|
+
.map(f => {
|
|
97
|
+
const taskPath = join(taskDir, f);
|
|
98
|
+
try {
|
|
99
|
+
const content = readFileSync(taskPath, 'utf8');
|
|
100
|
+
return normalizeTask(JSON.parse(content));
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
})
|
|
105
|
+
.filter(Boolean);
|
|
106
|
+
tasks = tasks.concat(implTasks);
|
|
107
|
+
} catch {
|
|
108
|
+
// Continue to other methods
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Method 2: Check plan.json for embedded tasks array
|
|
113
|
+
if (tasks.length === 0) {
|
|
114
|
+
const planPath = join(sessionPath, 'plan.json');
|
|
115
|
+
if (existsSync(planPath)) {
|
|
116
|
+
try {
|
|
117
|
+
const plan = JSON.parse(readFileSync(planPath, 'utf8'));
|
|
118
|
+
if (Array.isArray(plan.tasks)) {
|
|
119
|
+
tasks = plan.tasks.map(t => normalizeTask(t));
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
// Continue to other methods
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Method 3: Check for task-*.json files in session root
|
|
128
|
+
if (tasks.length === 0) {
|
|
129
|
+
try {
|
|
130
|
+
const rootTasks = readdirSync(sessionPath)
|
|
131
|
+
.filter(f => f.endsWith('.json') && (
|
|
132
|
+
f.startsWith('task-') ||
|
|
133
|
+
f.startsWith('TASK-') ||
|
|
134
|
+
/^T\d+\.json$/i.test(f)
|
|
135
|
+
))
|
|
136
|
+
.map(f => {
|
|
137
|
+
const taskPath = join(sessionPath, f);
|
|
138
|
+
try {
|
|
139
|
+
const content = readFileSync(taskPath, 'utf8');
|
|
140
|
+
return normalizeTask(JSON.parse(content));
|
|
141
|
+
} catch {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
.filter(Boolean);
|
|
146
|
+
tasks = tasks.concat(rootTasks);
|
|
147
|
+
} catch {
|
|
148
|
+
// No tasks found
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Sort tasks by ID
|
|
153
|
+
return tasks.sort((a, b) => {
|
|
154
|
+
const aNum = parseInt(a.id?.replace(/\D/g, '') || '0');
|
|
155
|
+
const bNum = parseInt(b.id?.replace(/\D/g, '') || '0');
|
|
156
|
+
return aNum - bNum;
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Normalize task object to consistent structure
|
|
162
|
+
* @param {Object} task - Raw task object
|
|
163
|
+
* @returns {Object} - Normalized task
|
|
164
|
+
*/
|
|
165
|
+
function normalizeTask(task) {
|
|
166
|
+
if (!task) return null;
|
|
167
|
+
|
|
168
|
+
// Determine status - support various status formats
|
|
169
|
+
let status = task.status || 'pending';
|
|
170
|
+
if (typeof status === 'object') {
|
|
171
|
+
status = status.state || status.value || 'pending';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return {
|
|
175
|
+
id: task.id || task.task_id || 'unknown',
|
|
176
|
+
title: task.title || task.name || task.summary || 'Untitled Task',
|
|
177
|
+
status: status.toLowerCase(),
|
|
178
|
+
// Preserve original fields for flexible rendering
|
|
179
|
+
meta: task.meta || {
|
|
180
|
+
type: task.type || task.action || 'task',
|
|
181
|
+
agent: task.agent || null,
|
|
182
|
+
scope: task.scope || null,
|
|
183
|
+
module: task.module || null
|
|
184
|
+
},
|
|
185
|
+
context: task.context || {
|
|
186
|
+
requirements: task.requirements || task.description ? [task.description] : [],
|
|
187
|
+
focus_paths: task.focus_paths || task.modification_points?.map(m => m.file) || [],
|
|
188
|
+
acceptance: task.acceptance || [],
|
|
189
|
+
depends_on: task.depends_on || []
|
|
190
|
+
},
|
|
191
|
+
flow_control: task.flow_control || {
|
|
192
|
+
implementation_approach: task.implementation?.map((step, i) => ({
|
|
193
|
+
step: `Step ${i + 1}`,
|
|
194
|
+
action: step
|
|
195
|
+
})) || []
|
|
196
|
+
},
|
|
197
|
+
// Keep all original fields for raw JSON view
|
|
198
|
+
_raw: task
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Get directory creation time
|
|
204
|
+
* @param {string} dirPath - Directory path
|
|
205
|
+
* @returns {string} - ISO date string
|
|
206
|
+
*/
|
|
207
|
+
function getCreatedTime(dirPath) {
|
|
208
|
+
try {
|
|
209
|
+
const stat = statSync(dirPath);
|
|
210
|
+
return stat.birthtime.toISOString();
|
|
211
|
+
} catch {
|
|
212
|
+
return new Date().toISOString();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Calculate progress from tasks
|
|
218
|
+
* @param {Array} tasks - Array of task objects
|
|
219
|
+
* @returns {Object} - Progress info
|
|
220
|
+
*/
|
|
221
|
+
function calculateProgress(tasks) {
|
|
222
|
+
if (!tasks || tasks.length === 0) {
|
|
223
|
+
return { total: 0, completed: 0, percentage: 0 };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
const total = tasks.length;
|
|
227
|
+
const completed = tasks.filter(t => t.status === 'completed').length;
|
|
228
|
+
const percentage = Math.round((completed / total) * 100);
|
|
229
|
+
|
|
230
|
+
return { total, completed, percentage };
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Get detailed lite task info
|
|
235
|
+
* @param {string} workflowDir - Workflow directory
|
|
236
|
+
* @param {string} type - 'lite-plan' or 'lite-fix'
|
|
237
|
+
* @param {string} sessionId - Session ID
|
|
238
|
+
* @returns {Object|null} - Detailed task info
|
|
239
|
+
*/
|
|
240
|
+
export function getLiteTaskDetail(workflowDir, type, sessionId) {
|
|
241
|
+
const dir = type === 'lite-plan'
|
|
242
|
+
? join(workflowDir, '.lite-plan', sessionId)
|
|
243
|
+
: join(workflowDir, '.lite-fix', sessionId);
|
|
244
|
+
|
|
245
|
+
if (!existsSync(dir)) return null;
|
|
246
|
+
|
|
247
|
+
return {
|
|
248
|
+
id: sessionId,
|
|
249
|
+
type,
|
|
250
|
+
path: dir,
|
|
251
|
+
plan: loadPlanJson(dir),
|
|
252
|
+
tasks: loadTaskJsons(dir),
|
|
253
|
+
explorations: loadExplorations(dir),
|
|
254
|
+
clarifications: loadClarifications(dir)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Load exploration results
|
|
260
|
+
* @param {string} sessionPath - Session directory path
|
|
261
|
+
* @returns {Array} - Exploration results
|
|
262
|
+
*/
|
|
263
|
+
function loadExplorations(sessionPath) {
|
|
264
|
+
const explorePath = join(sessionPath, 'explorations.json');
|
|
265
|
+
if (!existsSync(explorePath)) return [];
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const content = readFileSync(explorePath, 'utf8');
|
|
269
|
+
return JSON.parse(content);
|
|
270
|
+
} catch {
|
|
271
|
+
return [];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Load clarification data
|
|
277
|
+
* @param {string} sessionPath - Session directory path
|
|
278
|
+
* @returns {Object|null} - Clarification data
|
|
279
|
+
*/
|
|
280
|
+
function loadClarifications(sessionPath) {
|
|
281
|
+
const clarifyPath = join(sessionPath, 'clarifications.json');
|
|
282
|
+
if (!existsSync(clarifyPath)) return null;
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const content = readFileSync(clarifyPath, 'utf8');
|
|
286
|
+
return JSON.parse(content);
|
|
287
|
+
} catch {
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
}
|