prjct-cli 0.11.4 → 0.12.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/CHANGELOG.md +72 -0
- package/README.md +81 -25
- package/bin/dev.js +1 -1
- package/bin/generate-views.js +209 -0
- package/bin/migrate-to-json.js +742 -0
- package/bin/prjct +5 -5
- package/bin/serve.js +246 -54
- package/core/__tests__/agentic/{memory-system.test.js → memory-system.test.ts} +12 -23
- package/core/__tests__/agentic/{plan-mode.test.js → plan-mode.test.ts} +26 -24
- package/core/__tests__/agentic/{prompt-builder.test.js → prompt-builder.test.ts} +3 -8
- package/core/__tests__/utils/date-helper.test.ts +405 -0
- package/core/__tests__/utils/{output.test.js → output.test.ts} +12 -24
- package/core/agentic/agent-router.ts +137 -0
- package/core/agentic/chain-of-thought.ts +228 -0
- package/core/agentic/command-executor/command-executor.ts +384 -0
- package/core/agentic/command-executor/index.ts +16 -0
- package/core/agentic/command-executor/status-signal.ts +38 -0
- package/core/agentic/command-executor/types.ts +79 -0
- package/core/agentic/command-executor.ts +8 -0
- package/core/agentic/{context-builder.js → context-builder.ts} +99 -89
- package/core/agentic/context-filter.ts +365 -0
- package/core/agentic/ground-truth/index.ts +76 -0
- package/core/agentic/ground-truth/types.ts +33 -0
- package/core/agentic/ground-truth/utils.ts +48 -0
- package/core/agentic/ground-truth/verifiers/analyze.ts +54 -0
- package/core/agentic/ground-truth/verifiers/done.ts +75 -0
- package/core/agentic/ground-truth/verifiers/feature.ts +70 -0
- package/core/agentic/ground-truth/verifiers/index.ts +37 -0
- package/core/agentic/ground-truth/verifiers/init.ts +52 -0
- package/core/agentic/ground-truth/verifiers/now.ts +57 -0
- package/core/agentic/ground-truth/verifiers/ship.ts +85 -0
- package/core/agentic/ground-truth/verifiers/spec.ts +45 -0
- package/core/agentic/ground-truth/verifiers/sync.ts +47 -0
- package/core/agentic/ground-truth/verifiers.ts +6 -0
- package/core/agentic/ground-truth.ts +8 -0
- package/core/agentic/loop-detector/error-analysis.ts +97 -0
- package/core/agentic/loop-detector/hallucination.ts +71 -0
- package/core/agentic/loop-detector/index.ts +41 -0
- package/core/agentic/loop-detector/loop-detector.ts +222 -0
- package/core/agentic/loop-detector/types.ts +66 -0
- package/core/agentic/loop-detector.ts +8 -0
- package/core/agentic/memory-system/history.ts +53 -0
- package/core/agentic/memory-system/index.ts +192 -0
- package/core/agentic/memory-system/patterns.ts +156 -0
- package/core/agentic/memory-system/semantic-memories.ts +277 -0
- package/core/agentic/memory-system/session.ts +21 -0
- package/core/agentic/memory-system/types.ts +159 -0
- package/core/agentic/memory-system.ts +8 -0
- package/core/agentic/parallel-tools.ts +165 -0
- package/core/agentic/plan-mode/approval.ts +57 -0
- package/core/agentic/plan-mode/constants.ts +44 -0
- package/core/agentic/plan-mode/index.ts +28 -0
- package/core/agentic/plan-mode/plan-mode.ts +406 -0
- package/core/agentic/plan-mode/types.ts +193 -0
- package/core/agentic/plan-mode.ts +8 -0
- package/core/agentic/prompt-builder.ts +566 -0
- package/core/agentic/response-templates.ts +164 -0
- package/core/agentic/semantic-compression.ts +273 -0
- package/core/agentic/services.ts +206 -0
- package/core/agentic/smart-context.ts +476 -0
- package/core/agentic/{template-loader.js → template-loader.ts} +35 -18
- package/core/agentic/think-blocks.ts +202 -0
- package/core/agentic/tool-registry.ts +119 -0
- package/core/agentic/validation-rules.ts +313 -0
- package/core/agents/index.ts +28 -0
- package/core/agents/performance.ts +444 -0
- package/core/agents/types.ts +126 -0
- package/core/bus/{index.js → index.ts} +57 -61
- package/core/command-registry/categories.ts +23 -0
- package/core/command-registry/commands.ts +15 -0
- package/core/command-registry/core-commands.ts +319 -0
- package/core/command-registry/index.ts +158 -0
- package/core/command-registry/optional-commands.ts +119 -0
- package/core/command-registry/setup-commands.ts +53 -0
- package/core/command-registry/types.ts +59 -0
- package/core/command-registry.ts +9 -0
- package/core/commands/analysis.ts +298 -0
- package/core/commands/analytics.ts +288 -0
- package/core/commands/base.ts +273 -0
- package/core/commands/index.ts +211 -0
- package/core/commands/maintenance.ts +226 -0
- package/core/commands/planning.ts +311 -0
- package/core/commands/setup.ts +309 -0
- package/core/commands/shipping.ts +188 -0
- package/core/commands/types.ts +183 -0
- package/core/commands/workflow.ts +226 -0
- package/core/commands.ts +11 -0
- package/core/constants/formats.ts +187 -0
- package/core/constants/index.ts +7 -0
- package/core/{context-sync.js → context-sync.ts} +59 -26
- package/core/data/agents-manager.ts +76 -0
- package/core/data/analysis-manager.ts +83 -0
- package/core/data/base-manager.ts +156 -0
- package/core/data/ideas-manager.ts +81 -0
- package/core/data/index.ts +32 -0
- package/core/data/outcomes-manager.ts +96 -0
- package/core/data/project-manager.ts +75 -0
- package/core/data/roadmap-manager.ts +118 -0
- package/core/data/shipped-manager.ts +65 -0
- package/core/data/state-manager.ts +214 -0
- package/core/domain/{agent-generator.js → agent-generator.ts} +77 -57
- package/core/domain/{agent-loader.js → agent-loader.ts} +65 -56
- package/core/domain/{agent-matcher.js → agent-matcher.ts} +51 -24
- package/core/domain/{agent-validator.js → agent-validator.ts} +70 -37
- package/core/domain/{analyzer.js → analyzer.ts} +91 -85
- package/core/domain/{architect-session.js → architect-session.ts} +49 -34
- package/core/domain/{architecture-generator.js → architecture-generator.ts} +25 -13
- package/core/domain/{context-estimator.js → context-estimator.ts} +57 -36
- package/core/domain/{product-standards.js → product-standards.ts} +40 -26
- package/core/domain/{smart-cache.js → smart-cache.ts} +39 -30
- package/core/domain/{snapshot-manager.js → snapshot-manager.ts} +103 -100
- package/core/domain/{task-analyzer.js → task-analyzer.ts} +82 -43
- package/core/domain/task-stack/index.ts +19 -0
- package/core/domain/task-stack/parser.ts +86 -0
- package/core/domain/task-stack/storage.ts +123 -0
- package/core/domain/task-stack/task-stack.ts +340 -0
- package/core/domain/task-stack/types.ts +51 -0
- package/core/domain/task-stack.ts +8 -0
- package/core/{index.js → index.ts} +61 -18
- package/core/infrastructure/{agent-detector.js → agent-detector.ts} +62 -23
- package/core/infrastructure/agents/{claude-agent.js → claude-agent.ts} +61 -21
- package/core/infrastructure/{author-detector.js → author-detector.ts} +42 -49
- package/core/infrastructure/{capability-installer.js → capability-installer.ts} +51 -27
- package/core/infrastructure/{command-installer.js → command-installer/command-installer.ts} +43 -144
- package/core/infrastructure/command-installer/global-config.ts +106 -0
- package/core/infrastructure/command-installer/index.ts +25 -0
- package/core/infrastructure/command-installer/types.ts +41 -0
- package/core/infrastructure/command-installer.ts +8 -0
- package/core/infrastructure/{config-manager.js → config-manager.ts} +60 -80
- package/core/infrastructure/{editors-config.js → editors-config.ts} +33 -31
- package/core/infrastructure/legacy-installer-detector/cleanup.ts +216 -0
- package/core/infrastructure/legacy-installer-detector/detection.ts +95 -0
- package/core/infrastructure/legacy-installer-detector/index.ts +171 -0
- package/core/infrastructure/legacy-installer-detector/migration.ts +87 -0
- package/core/infrastructure/legacy-installer-detector/types.ts +42 -0
- package/core/infrastructure/legacy-installer-detector.ts +7 -0
- package/core/infrastructure/migrator/file-operations.ts +125 -0
- package/core/infrastructure/migrator/index.ts +288 -0
- package/core/infrastructure/migrator/project-scanner.ts +89 -0
- package/core/infrastructure/migrator/reports.ts +117 -0
- package/core/infrastructure/migrator/types.ts +124 -0
- package/core/infrastructure/migrator/validation.ts +94 -0
- package/core/infrastructure/migrator/version-migration.ts +117 -0
- package/core/infrastructure/migrator.ts +10 -0
- package/core/infrastructure/{path-manager.js → path-manager.ts} +51 -91
- package/core/infrastructure/session-manager/index.ts +23 -0
- package/core/infrastructure/session-manager/migration.ts +88 -0
- package/core/infrastructure/session-manager/session-manager.ts +307 -0
- package/core/infrastructure/session-manager/types.ts +45 -0
- package/core/infrastructure/session-manager.ts +8 -0
- package/core/infrastructure/{setup.js → setup.ts} +29 -21
- package/core/infrastructure/{update-checker.js → update-checker.ts} +40 -18
- package/core/outcomes/analyzer.ts +333 -0
- package/core/outcomes/index.ts +34 -0
- package/core/outcomes/recorder.ts +194 -0
- package/core/outcomes/types.ts +145 -0
- package/core/plugin/{hooks.js → hooks.ts} +56 -58
- package/core/plugin/{index.js → index.ts} +19 -8
- package/core/plugin/{loader.js → loader.ts} +87 -69
- package/core/plugin/{registry.js → registry.ts} +49 -45
- package/core/plugins/{webhook.js → webhook.ts} +43 -27
- package/core/schemas/agents.ts +27 -0
- package/core/schemas/analysis.ts +41 -0
- package/core/schemas/ideas.ts +83 -0
- package/core/schemas/index.ts +73 -0
- package/core/schemas/outcomes.ts +22 -0
- package/core/schemas/project.ts +26 -0
- package/core/schemas/roadmap.ts +90 -0
- package/core/schemas/shipped.ts +82 -0
- package/core/schemas/state.ts +107 -0
- package/core/session/index.ts +17 -0
- package/core/session/{metrics.js → metrics.ts} +64 -46
- package/core/session/{index.js → session-manager.ts} +51 -117
- package/core/session/types.ts +29 -0
- package/core/session/utils.ts +57 -0
- package/core/state/index.ts +25 -0
- package/core/state/manager.ts +376 -0
- package/core/state/types.ts +185 -0
- package/core/tsconfig.json +22 -0
- package/core/types/index.ts +506 -0
- package/core/utils/{animations.js → animations.ts} +74 -28
- package/core/utils/{branding.js → branding.ts} +29 -4
- package/core/utils/{date-helper.js → date-helper.ts} +31 -74
- package/core/utils/file-helper.ts +262 -0
- package/core/utils/{jsonl-helper.js → jsonl-helper.ts} +71 -107
- package/core/utils/{logger.js → logger.ts} +24 -12
- package/core/utils/{output.js → output.ts} +25 -13
- package/core/utils/{project-capabilities.js → project-capabilities.ts} +31 -18
- package/core/utils/{session-helper.js → session-helper.ts} +79 -66
- package/core/utils/{version.js → version.ts} +23 -31
- package/core/view-generator.ts +536 -0
- package/package.json +23 -17
- package/packages/shared/.turbo/turbo-build.log +14 -0
- package/packages/shared/dist/index.d.ts +8 -613
- package/packages/shared/dist/index.d.ts.map +1 -0
- package/packages/shared/dist/index.js +4110 -118
- package/packages/shared/dist/schemas.d.ts +408 -0
- package/packages/shared/dist/schemas.d.ts.map +1 -0
- package/packages/shared/dist/types.d.ts +144 -0
- package/packages/shared/dist/types.d.ts.map +1 -0
- package/packages/shared/dist/unified.d.ts +139 -0
- package/packages/shared/dist/unified.d.ts.map +1 -0
- package/packages/shared/dist/utils.d.ts +60 -0
- package/packages/shared/dist/utils.d.ts.map +1 -0
- package/packages/shared/package.json +4 -4
- package/packages/shared/src/index.ts +1 -0
- package/packages/shared/src/unified.ts +174 -0
- package/packages/web/app/api/claude/sessions/route.ts +1 -1
- package/packages/web/app/api/claude/status/route.ts +1 -1
- package/packages/web/app/api/migrate/route.ts +46 -0
- package/packages/web/app/api/projects/[id]/route.ts +1 -1
- package/packages/web/app/api/projects/[id]/stats/route.ts +30 -2
- package/packages/web/app/api/projects/[id]/status/route.ts +1 -1
- package/packages/web/app/api/projects/route.ts +1 -1
- package/packages/web/app/api/settings/route.ts +97 -0
- package/packages/web/app/api/v2/projects/[id]/unified/route.ts +57 -0
- package/packages/web/app/globals.css +38 -0
- package/packages/web/app/layout.tsx +10 -2
- package/packages/web/app/page.tsx +9 -224
- package/packages/web/app/project/[id]/page.tsx +191 -63
- package/packages/web/app/project/[id]/stats/loading.tsx +43 -0
- package/packages/web/app/project/[id]/stats/page.tsx +203 -403
- package/packages/web/app/settings/page.tsx +222 -2
- package/packages/web/components/ActivityTimeline/ActivityTimeline.constants.ts +2 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.tsx +50 -0
- package/packages/web/components/ActivityTimeline/ActivityTimeline.types.ts +8 -0
- package/packages/web/components/ActivityTimeline/hooks/index.ts +2 -0
- package/packages/web/components/ActivityTimeline/hooks/useExpandable.ts +9 -0
- package/packages/web/components/ActivityTimeline/hooks/useGroupedEvents.ts +23 -0
- package/packages/web/components/ActivityTimeline/index.ts +2 -0
- package/packages/web/components/AgentsCard/AgentsCard.tsx +63 -0
- package/packages/web/components/AgentsCard/AgentsCard.types.ts +13 -0
- package/packages/web/components/AgentsCard/index.ts +2 -0
- package/packages/web/components/AppSidebar/AppSidebar.tsx +134 -0
- package/packages/web/components/AppSidebar/index.ts +1 -0
- package/packages/web/components/BackLink/BackLink.tsx +18 -0
- package/packages/web/components/BackLink/BackLink.types.ts +5 -0
- package/packages/web/components/BackLink/index.ts +2 -0
- package/packages/web/components/BentoCard/BentoCard.constants.ts +16 -0
- package/packages/web/components/BentoCard/BentoCard.tsx +47 -0
- package/packages/web/components/BentoCard/BentoCard.types.ts +15 -0
- package/packages/web/components/BentoCard/index.ts +2 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.constants.ts +9 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.tsx +18 -0
- package/packages/web/components/BentoCardSkeleton/BentoCardSkeleton.types.ts +5 -0
- package/packages/web/components/BentoCardSkeleton/index.ts +2 -0
- package/packages/web/components/BentoGrid/BentoGrid.tsx +18 -0
- package/packages/web/components/BentoGrid/BentoGrid.types.ts +4 -0
- package/packages/web/components/BentoGrid/index.ts +2 -0
- package/packages/web/components/CommandButton/index.ts +1 -0
- package/packages/web/components/ConnectionStatus/index.ts +1 -0
- package/packages/web/components/DashboardContent/DashboardContent.tsx +254 -0
- package/packages/web/components/DashboardContent/index.ts +1 -0
- package/packages/web/components/DateGroup/DateGroup.tsx +18 -0
- package/packages/web/components/DateGroup/DateGroup.types.ts +6 -0
- package/packages/web/components/DateGroup/DateGroup.utils.ts +11 -0
- package/packages/web/components/DateGroup/index.ts +2 -0
- package/packages/web/components/EmptyState/EmptyState.tsx +58 -0
- package/packages/web/components/EmptyState/EmptyState.types.ts +10 -0
- package/packages/web/components/EmptyState/index.ts +2 -0
- package/packages/web/components/EventRow/EventRow.constants.ts +10 -0
- package/packages/web/components/EventRow/EventRow.tsx +49 -0
- package/packages/web/components/EventRow/EventRow.types.ts +7 -0
- package/packages/web/components/EventRow/EventRow.utils.ts +49 -0
- package/packages/web/components/EventRow/index.ts +2 -0
- package/packages/web/components/ExpandButton/ExpandButton.tsx +18 -0
- package/packages/web/components/ExpandButton/ExpandButton.types.ts +6 -0
- package/packages/web/components/ExpandButton/index.ts +2 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.tsx +14 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.types.ts +5 -0
- package/packages/web/components/HealthGradientBackground/HealthGradientBackground.utils.ts +13 -0
- package/packages/web/components/HealthGradientBackground/index.ts +2 -0
- package/packages/web/components/HeroSection/HeroSection.tsx +55 -0
- package/packages/web/components/HeroSection/HeroSection.types.ts +14 -0
- package/packages/web/components/HeroSection/HeroSection.utils.ts +7 -0
- package/packages/web/components/HeroSection/hooks/index.ts +2 -0
- package/packages/web/components/HeroSection/hooks/useCountUp.ts +45 -0
- package/packages/web/components/HeroSection/hooks/useWeeklyActivity.ts +18 -0
- package/packages/web/components/HeroSection/index.ts +2 -0
- package/packages/web/components/IdeasCard/IdeasCard.tsx +48 -0
- package/packages/web/components/IdeasCard/IdeasCard.types.ts +9 -0
- package/packages/web/components/IdeasCard/index.ts +2 -0
- package/packages/web/components/InsightMessage/InsightMessage.tsx +9 -0
- package/packages/web/components/InsightMessage/InsightMessage.types.ts +3 -0
- package/packages/web/components/InsightMessage/index.ts +2 -0
- package/packages/web/components/Logo/index.ts +1 -0
- package/packages/web/components/MarkdownContent/index.ts +1 -0
- package/packages/web/components/NowCard/NowCard.tsx +93 -0
- package/packages/web/components/NowCard/NowCard.types.ts +15 -0
- package/packages/web/components/NowCard/index.ts +2 -0
- package/packages/web/components/ProgressRing/ProgressRing.constants.ts +20 -0
- package/packages/web/components/ProgressRing/ProgressRing.tsx +51 -0
- package/packages/web/components/ProgressRing/ProgressRing.types.ts +11 -0
- package/packages/web/components/ProgressRing/index.ts +2 -0
- package/packages/web/components/ProjectAvatar/index.ts +1 -0
- package/packages/web/components/Providers/index.ts +1 -0
- package/packages/web/components/QueueCard/QueueCard.tsx +72 -0
- package/packages/web/components/QueueCard/QueueCard.types.ts +11 -0
- package/packages/web/components/QueueCard/QueueCard.utils.ts +12 -0
- package/packages/web/components/QueueCard/index.ts +2 -0
- package/packages/web/components/RoadmapCard/RoadmapCard.tsx +77 -0
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
- package/packages/web/components/RoadmapCard/index.ts +2 -0
- package/packages/web/components/ShipsCard/ShipsCard.tsx +52 -0
- package/packages/web/components/ShipsCard/ShipsCard.types.ts +12 -0
- package/packages/web/components/ShipsCard/ShipsCard.utils.ts +4 -0
- package/packages/web/components/ShipsCard/index.ts +2 -0
- package/packages/web/components/SparklineChart/SparklineChart.tsx +38 -0
- package/packages/web/components/SparklineChart/SparklineChart.types.ts +6 -0
- package/packages/web/components/SparklineChart/index.ts +2 -0
- package/packages/web/components/StreakCard/StreakCard.constants.ts +2 -0
- package/packages/web/components/StreakCard/StreakCard.tsx +53 -0
- package/packages/web/components/StreakCard/StreakCard.types.ts +4 -0
- package/packages/web/components/StreakCard/index.ts +2 -0
- package/packages/web/components/TasksCounter/TasksCounter.tsx +14 -0
- package/packages/web/components/TasksCounter/TasksCounter.types.ts +3 -0
- package/packages/web/components/TasksCounter/index.ts +2 -0
- package/packages/web/components/TechStackBadges/index.ts +1 -0
- package/packages/web/components/{TerminalTab.tsx → TerminalTabs/TerminalTab.tsx} +11 -0
- package/packages/web/components/{TerminalTabs.tsx → TerminalTabs/TerminalTabs.tsx} +29 -28
- package/packages/web/components/TerminalTabs/index.ts +1 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.tsx +27 -0
- package/packages/web/components/VelocityBadge/VelocityBadge.types.ts +3 -0
- package/packages/web/components/VelocityBadge/index.ts +2 -0
- package/packages/web/components/VelocityCard/VelocityCard.tsx +71 -0
- package/packages/web/components/VelocityCard/VelocityCard.types.ts +7 -0
- package/packages/web/components/VelocityCard/index.ts +2 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.tsx +13 -0
- package/packages/web/components/WeeklySparkline/WeeklySparkline.types.ts +3 -0
- package/packages/web/components/WeeklySparkline/index.ts +2 -0
- package/packages/web/components/ui/input.tsx +21 -0
- package/packages/web/components/ui/tooltip.tsx +2 -2
- package/packages/web/context/TerminalTabsContext.tsx +46 -1
- package/packages/web/hooks/useClaudeTerminal.ts +71 -21
- package/packages/web/hooks/useProjectStats.ts +55 -0
- package/packages/web/hooks/useProjects.ts +6 -6
- package/packages/web/lib/actions/projects.ts +15 -0
- package/packages/web/lib/json-loader.ts +630 -0
- package/packages/web/lib/services/index.ts +9 -0
- package/packages/web/lib/services/migration.server.ts +598 -0
- package/packages/web/lib/services/projects.server.ts +52 -0
- package/packages/web/lib/services/stats.server.ts +264 -0
- package/packages/web/lib/unified-loader.ts +396 -0
- package/packages/web/next-env.d.ts +1 -1
- package/packages/web/package.json +10 -6
- package/packages/web/server.ts +36 -6
- package/templates/commands/done.md +76 -32
- package/templates/commands/feature.md +121 -47
- package/templates/commands/idea.md +81 -8
- package/templates/commands/now.md +41 -17
- package/templates/commands/ship.md +64 -25
- package/templates/commands/sync.md +28 -3
- package/core/agentic/agent-router.js +0 -128
- package/core/agentic/chain-of-thought.js +0 -578
- package/core/agentic/command-executor.js +0 -421
- package/core/agentic/context-filter.js +0 -354
- package/core/agentic/ground-truth.js +0 -591
- package/core/agentic/loop-detector.js +0 -406
- package/core/agentic/memory-system.js +0 -850
- package/core/agentic/parallel-tools.js +0 -366
- package/core/agentic/plan-mode.js +0 -572
- package/core/agentic/prompt-builder.js +0 -338
- package/core/agentic/response-templates.js +0 -290
- package/core/agentic/semantic-compression.js +0 -517
- package/core/agentic/think-blocks.js +0 -657
- package/core/agentic/tool-registry.js +0 -184
- package/core/agentic/validation-rules.js +0 -380
- package/core/command-registry.js +0 -698
- package/core/commands.js +0 -2237
- package/core/domain/task-stack.js +0 -497
- package/core/infrastructure/legacy-installer-detector.js +0 -546
- package/core/infrastructure/migrator.js +0 -799
- package/core/infrastructure/session-manager.js +0 -390
- package/core/utils/file-helper.js +0 -329
- package/packages/web/app/api/projects/[id]/delete/route.ts +0 -21
- package/packages/web/app/api/stats/route.ts +0 -38
- package/packages/web/components/AppSidebar.tsx +0 -113
- package/packages/web/hooks/useStats.ts +0 -28
- /package/packages/web/components/{CommandButton.tsx → CommandButton/CommandButton.tsx} +0 -0
- /package/packages/web/components/{ConnectionStatus.tsx → ConnectionStatus/ConnectionStatus.tsx} +0 -0
- /package/packages/web/components/{Logo.tsx → Logo/Logo.tsx} +0 -0
- /package/packages/web/components/{MarkdownContent.tsx → MarkdownContent/MarkdownContent.tsx} +0 -0
- /package/packages/web/components/{ProjectAvatar.tsx → ProjectAvatar/ProjectAvatar.tsx} +0 -0
- /package/packages/web/components/{providers.tsx → Providers/Providers.tsx} +0 -0
- /package/packages/web/components/{TechStackBadges.tsx → TechStackBadges/TechStackBadges.tsx} +0 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics Commands: context, recap, progress, status, roadmap, stuck
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import path from 'path'
|
|
6
|
+
|
|
7
|
+
import type { CommandResult, Context } from './types'
|
|
8
|
+
import {
|
|
9
|
+
PrjctCommandsBase,
|
|
10
|
+
contextBuilder,
|
|
11
|
+
toolRegistry,
|
|
12
|
+
pathManager,
|
|
13
|
+
configManager,
|
|
14
|
+
jsonlHelper,
|
|
15
|
+
dateHelper,
|
|
16
|
+
out
|
|
17
|
+
} from './base'
|
|
18
|
+
|
|
19
|
+
interface MemoryEntry {
|
|
20
|
+
timestamp: string
|
|
21
|
+
action: string
|
|
22
|
+
data?: Record<string, unknown>
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export class AnalyticsCommands extends PrjctCommandsBase {
|
|
26
|
+
/**
|
|
27
|
+
* /p:context - Show project context and recent activity
|
|
28
|
+
*/
|
|
29
|
+
async context(projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
30
|
+
try {
|
|
31
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
32
|
+
if (!initResult.success) return initResult
|
|
33
|
+
|
|
34
|
+
out.spin('loading context...')
|
|
35
|
+
const context = await contextBuilder.build(projectPath) as Context
|
|
36
|
+
|
|
37
|
+
const nowContent = (await toolRegistry.get('Read')!(context.paths.now)) as string | null
|
|
38
|
+
const nextContent = (await toolRegistry.get('Read')!(context.paths.next)) as string | null
|
|
39
|
+
|
|
40
|
+
let task = 'none'
|
|
41
|
+
if (nowContent && !nowContent.includes('No current task')) {
|
|
42
|
+
const taskMatch = nowContent.match(/\*\*(.+?)\*\*/)
|
|
43
|
+
task = taskMatch ? taskMatch[1] : 'active'
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const nextLines = nextContent?.split('\n').filter((line) => line.trim() && !line.startsWith('#')) || []
|
|
47
|
+
const queueCount = nextLines.length
|
|
48
|
+
|
|
49
|
+
await this.logToMemory(projectPath, 'context_viewed', { timestamp: dateHelper.getTimestamp() })
|
|
50
|
+
|
|
51
|
+
out.done(`task: ${task} | queue: ${queueCount}`)
|
|
52
|
+
return { success: true }
|
|
53
|
+
} catch (error) {
|
|
54
|
+
out.fail((error as Error).message)
|
|
55
|
+
return { success: false, error: (error as Error).message }
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* /p:recap - Show project overview with progress
|
|
61
|
+
*/
|
|
62
|
+
async recap(projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
63
|
+
try {
|
|
64
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
65
|
+
if (!initResult.success) return initResult
|
|
66
|
+
|
|
67
|
+
out.spin('loading recap...')
|
|
68
|
+
const context = await contextBuilder.build(projectPath) as Context
|
|
69
|
+
|
|
70
|
+
const shippedContent = (await toolRegistry.get('Read')!(context.paths.shipped)) as string | null
|
|
71
|
+
const shippedFeatures = shippedContent?.split('##').filter((s) => s.trim() && !s.includes('SHIPPED')) || []
|
|
72
|
+
|
|
73
|
+
const nextContent = (await toolRegistry.get('Read')!(context.paths.next)) as string | null
|
|
74
|
+
const nextTasks = nextContent?.split('\n').filter((l) => l.match(/^\d+\./) || l.includes('[ ]')).length || 0
|
|
75
|
+
|
|
76
|
+
const ideasContent = (await toolRegistry.get('Read')!(context.paths.ideas)) as string | null
|
|
77
|
+
const ideas = ideasContent?.split('##').filter((s) => s.trim() && !s.includes('IDEAS') && !s.includes('Brain')).length || 0
|
|
78
|
+
|
|
79
|
+
await this.logToMemory(projectPath, 'recap_viewed', {
|
|
80
|
+
shipped: shippedFeatures.length,
|
|
81
|
+
tasks: nextTasks,
|
|
82
|
+
timestamp: dateHelper.getTimestamp(),
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
out.done(`shipped: ${shippedFeatures.length} | queue: ${nextTasks} | ideas: ${ideas}`)
|
|
86
|
+
return { success: true, stats: { shipped: shippedFeatures.length, tasks: nextTasks, ideas } }
|
|
87
|
+
} catch (error) {
|
|
88
|
+
out.fail((error as Error).message)
|
|
89
|
+
return { success: false, error: (error as Error).message }
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* /p:stuck - Get contextual help with problems
|
|
95
|
+
*/
|
|
96
|
+
async stuck(issue: string, projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
97
|
+
try {
|
|
98
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
99
|
+
if (!initResult.success) return initResult
|
|
100
|
+
|
|
101
|
+
if (!issue) {
|
|
102
|
+
out.fail('issue description required')
|
|
103
|
+
return { success: false, error: 'Issue description required' }
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
out.spin('logging issue...')
|
|
107
|
+
|
|
108
|
+
const analyzer = require('../domain/analyzer')
|
|
109
|
+
analyzer.init(projectPath)
|
|
110
|
+
const packageJson = await analyzer.readPackageJson()
|
|
111
|
+
const detectedStack = packageJson?.name || 'project'
|
|
112
|
+
|
|
113
|
+
await this.logToMemory(projectPath, 'help_requested', {
|
|
114
|
+
issue,
|
|
115
|
+
stack: detectedStack,
|
|
116
|
+
timestamp: dateHelper.getTimestamp(),
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
out.done(`issue logged: ${issue.slice(0, 40)}`)
|
|
120
|
+
return { success: true, issue, stack: detectedStack }
|
|
121
|
+
} catch (error) {
|
|
122
|
+
out.fail((error as Error).message)
|
|
123
|
+
return { success: false, error: (error as Error).message }
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* /p:progress - Show metrics for period
|
|
129
|
+
*/
|
|
130
|
+
async progress(period: string = 'week', projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
131
|
+
try {
|
|
132
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
133
|
+
if (!initResult.success) return initResult
|
|
134
|
+
|
|
135
|
+
const validPeriods = ['day', 'week', 'month', 'all']
|
|
136
|
+
if (!validPeriods.includes(period)) period = 'week'
|
|
137
|
+
|
|
138
|
+
out.spin(`loading ${period} progress...`)
|
|
139
|
+
|
|
140
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
141
|
+
const memoryPath = pathManager.getFilePath(projectId!, 'memory', 'context.jsonl')
|
|
142
|
+
|
|
143
|
+
const startDate = period === 'day' ? dateHelper.getDaysAgo(1) :
|
|
144
|
+
period === 'week' ? dateHelper.getDaysAgo(7) :
|
|
145
|
+
period === 'month' ? dateHelper.getDaysAgo(30) : new Date(0)
|
|
146
|
+
|
|
147
|
+
let entries: MemoryEntry[] = []
|
|
148
|
+
try {
|
|
149
|
+
const allEntries = await jsonlHelper.readJsonLines(memoryPath) as MemoryEntry[]
|
|
150
|
+
entries = allEntries.filter((e) => new Date(e.timestamp) >= startDate)
|
|
151
|
+
} catch { entries = [] }
|
|
152
|
+
|
|
153
|
+
const metrics = {
|
|
154
|
+
tasksCompleted: entries.filter((e) => e.action === 'task_completed').length,
|
|
155
|
+
featuresShipped: entries.filter((e) => e.action === 'feature_shipped').length,
|
|
156
|
+
totalActions: entries.length,
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
await this.logToMemory(projectPath, 'progress_viewed', { period, metrics, timestamp: dateHelper.getTimestamp() })
|
|
160
|
+
|
|
161
|
+
out.done(`${period}: ${metrics.tasksCompleted} tasks | ${metrics.featuresShipped} shipped`)
|
|
162
|
+
return { success: true, period, metrics }
|
|
163
|
+
} catch (error) {
|
|
164
|
+
out.fail((error as Error).message)
|
|
165
|
+
return { success: false, error: (error as Error).message }
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* /p:roadmap - Show roadmap with ASCII logic maps
|
|
171
|
+
*/
|
|
172
|
+
async roadmap(projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
173
|
+
try {
|
|
174
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
175
|
+
if (!initResult.success) return initResult
|
|
176
|
+
|
|
177
|
+
out.spin('loading roadmap...')
|
|
178
|
+
const context = await contextBuilder.build(projectPath) as Context
|
|
179
|
+
const roadmapContent = (await toolRegistry.get('Read')!(context.paths.roadmap)) as string | null
|
|
180
|
+
|
|
181
|
+
if (!roadmapContent || roadmapContent.trim() === '# ROADMAP') {
|
|
182
|
+
out.warn('no roadmap yet')
|
|
183
|
+
return { success: true, message: 'No roadmap' }
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const features = (roadmapContent.match(/##/g) || []).length
|
|
187
|
+
|
|
188
|
+
await this.logToMemory(projectPath, 'roadmap_viewed', { timestamp: dateHelper.getTimestamp() })
|
|
189
|
+
|
|
190
|
+
out.done(`${features} features in roadmap`)
|
|
191
|
+
return { success: true, content: roadmapContent }
|
|
192
|
+
} catch (error) {
|
|
193
|
+
out.fail((error as Error).message)
|
|
194
|
+
return { success: false, error: (error as Error).message }
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* /p:status - KPI dashboard with ASCII graphics
|
|
200
|
+
*/
|
|
201
|
+
async status(projectPath: string = process.cwd()): Promise<CommandResult> {
|
|
202
|
+
try {
|
|
203
|
+
const initResult = await this.ensureProjectInit(projectPath)
|
|
204
|
+
if (!initResult.success) return initResult
|
|
205
|
+
|
|
206
|
+
console.log('📊 Project Status Dashboard\n')
|
|
207
|
+
|
|
208
|
+
const context = await contextBuilder.build(projectPath) as Context
|
|
209
|
+
|
|
210
|
+
const nowContent = (await toolRegistry.get('Read')!(context.paths.now)) as string | null
|
|
211
|
+
const nextContent = (await toolRegistry.get('Read')!(context.paths.next)) as string | null
|
|
212
|
+
const shippedContent = (await toolRegistry.get('Read')!(context.paths.shipped)) as string | null
|
|
213
|
+
const ideasContent = (await toolRegistry.get('Read')!(context.paths.ideas)) as string | null
|
|
214
|
+
|
|
215
|
+
const stats = {
|
|
216
|
+
activeTask: !!(nowContent && !nowContent.includes('No current task')),
|
|
217
|
+
tasksInQueue:
|
|
218
|
+
nextContent
|
|
219
|
+
?.split('\n')
|
|
220
|
+
.filter((line) => line.trim().match(/^\d+\./) || line.includes('[ ]')).length || 0,
|
|
221
|
+
featuresShipped:
|
|
222
|
+
shippedContent
|
|
223
|
+
?.split('##')
|
|
224
|
+
.filter((section) => section.trim() && !section.includes('SHIPPED 🚀')).length || 0,
|
|
225
|
+
ideasCaptured:
|
|
226
|
+
ideasContent
|
|
227
|
+
?.split('##')
|
|
228
|
+
.filter(
|
|
229
|
+
(section) =>
|
|
230
|
+
section.trim() && !section.includes('IDEAS 💡') && !section.includes('Brain Dump')
|
|
231
|
+
).length || 0,
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
console.log('═══════════════════════════════════════════════════')
|
|
235
|
+
console.log(` ${path.basename(projectPath)} - Status Overview`)
|
|
236
|
+
console.log('═══════════════════════════════════════════════════\n')
|
|
237
|
+
|
|
238
|
+
console.log('## 🎯 Current Focus\n')
|
|
239
|
+
if (stats.activeTask && nowContent) {
|
|
240
|
+
const taskMatch = nowContent.match(/\*\*(.+?)\*\*/)
|
|
241
|
+
const task = taskMatch ? taskMatch[1] : 'Active task'
|
|
242
|
+
const startedMatch = nowContent.match(/Started: (.+)/)
|
|
243
|
+
const started = startedMatch ? startedMatch[1] : 'Unknown'
|
|
244
|
+
console.log(` 📌 ${task}`)
|
|
245
|
+
console.log(` ⏱️ Started: ${started}\n`)
|
|
246
|
+
} else {
|
|
247
|
+
console.log(' No active task\n')
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
console.log('## 📋 Queue Status\n')
|
|
251
|
+
console.log(` Tasks in Queue: ${stats.tasksInQueue}`)
|
|
252
|
+
this._renderProgressBar('Queue Load', stats.tasksInQueue, 20)
|
|
253
|
+
console.log('')
|
|
254
|
+
|
|
255
|
+
console.log('## 🚀 Shipped Features\n')
|
|
256
|
+
console.log(` Features Shipped: ${stats.featuresShipped}`)
|
|
257
|
+
this._renderProgressBar('Progress', stats.featuresShipped, 10)
|
|
258
|
+
console.log('')
|
|
259
|
+
|
|
260
|
+
console.log('## 💡 Ideas Backlog\n')
|
|
261
|
+
console.log(` Ideas Captured: ${stats.ideasCaptured}`)
|
|
262
|
+
this._renderProgressBar('Backlog', stats.ideasCaptured, 15)
|
|
263
|
+
console.log('')
|
|
264
|
+
|
|
265
|
+
console.log('## 💚 Overall Health\n')
|
|
266
|
+
const health = this._calculateHealth(stats)
|
|
267
|
+
console.log(` Health Score: ${health.score}/100`)
|
|
268
|
+
this._renderProgressBar('Health', health.score, 100)
|
|
269
|
+
console.log(` ${health.message}\n`)
|
|
270
|
+
|
|
271
|
+
console.log('💡 Next steps:')
|
|
272
|
+
console.log('• /p:now → Start working on a task')
|
|
273
|
+
console.log('• /p:feature → Add new feature')
|
|
274
|
+
console.log('• /p:ship → Ship completed work')
|
|
275
|
+
|
|
276
|
+
await this.logToMemory(projectPath, 'status_viewed', {
|
|
277
|
+
stats,
|
|
278
|
+
health: health.score,
|
|
279
|
+
timestamp: dateHelper.getTimestamp(),
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
return { success: true, stats, health }
|
|
283
|
+
} catch (error) {
|
|
284
|
+
console.error('❌ Error:', (error as Error).message)
|
|
285
|
+
return { success: false, error: (error as Error).message }
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base class and helpers for PrjctCommands
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import path from 'path'
|
|
6
|
+
|
|
7
|
+
import commandExecutor from '../agentic/command-executor'
|
|
8
|
+
import contextBuilder from '../agentic/context-builder'
|
|
9
|
+
import toolRegistry from '../agentic/tool-registry'
|
|
10
|
+
import AgentRouter from '../agentic/agent-router'
|
|
11
|
+
import pathManager from '../infrastructure/path-manager'
|
|
12
|
+
import configManager from '../infrastructure/config-manager'
|
|
13
|
+
import authorDetector from '../infrastructure/author-detector'
|
|
14
|
+
import agentDetector from '../infrastructure/agent-detector'
|
|
15
|
+
import migrator from '../infrastructure/migrator'
|
|
16
|
+
import UpdateChecker from '../infrastructure/update-checker'
|
|
17
|
+
import dateHelper from '../utils/date-helper'
|
|
18
|
+
import jsonlHelper from '../utils/jsonl-helper'
|
|
19
|
+
import * as fileHelper from '../utils/file-helper'
|
|
20
|
+
import out from '../utils/output'
|
|
21
|
+
|
|
22
|
+
import type {
|
|
23
|
+
CommandResult,
|
|
24
|
+
AgentInfo,
|
|
25
|
+
Author,
|
|
26
|
+
AgentAssignmentResult,
|
|
27
|
+
ComplexityResult,
|
|
28
|
+
HealthResult,
|
|
29
|
+
Context
|
|
30
|
+
} from './types'
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Base class with shared state and utilities
|
|
34
|
+
*/
|
|
35
|
+
export class PrjctCommandsBase {
|
|
36
|
+
agent: unknown
|
|
37
|
+
agentInfo: AgentInfo | null
|
|
38
|
+
currentAuthor: Author | null
|
|
39
|
+
prjctDir: string
|
|
40
|
+
updateChecker: UpdateChecker
|
|
41
|
+
updateNotificationShown: boolean
|
|
42
|
+
commandExecutor: typeof commandExecutor
|
|
43
|
+
agentRouter: AgentRouter
|
|
44
|
+
|
|
45
|
+
constructor() {
|
|
46
|
+
this.agent = null
|
|
47
|
+
this.agentInfo = null
|
|
48
|
+
this.currentAuthor = null
|
|
49
|
+
this.prjctDir = '.prjct'
|
|
50
|
+
this.updateChecker = new UpdateChecker()
|
|
51
|
+
this.updateNotificationShown = false
|
|
52
|
+
this.commandExecutor = commandExecutor
|
|
53
|
+
this.agentRouter = new AgentRouter()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Initialize agent (Claude Code, Desktop, or Terminal)
|
|
58
|
+
*/
|
|
59
|
+
async initializeAgent(): Promise<unknown> {
|
|
60
|
+
if (this.agent) return this.agent
|
|
61
|
+
|
|
62
|
+
this.agentInfo = await agentDetector.detect()
|
|
63
|
+
|
|
64
|
+
if (!this.agentInfo.isSupported) {
|
|
65
|
+
throw new Error('Unsupported agent. Please use Claude Code, Claude Desktop, or Terminal.')
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const Agent = require(`../infrastructure/agents/${this.agentInfo.type}-agent`)
|
|
69
|
+
this.agent = new Agent()
|
|
70
|
+
|
|
71
|
+
return this.agent
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Ensure project is initialized
|
|
76
|
+
*/
|
|
77
|
+
async ensureProjectInit(projectPath: string): Promise<CommandResult> {
|
|
78
|
+
if (await configManager.isConfigured(projectPath)) {
|
|
79
|
+
return { success: true }
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
out.spin('initializing project...')
|
|
83
|
+
// Note: init() will be implemented in planning module
|
|
84
|
+
const initResult = await (this as unknown as { init: (idea: string | null, projectPath: string) => Promise<CommandResult> }).init(null, projectPath)
|
|
85
|
+
if (!initResult.success) {
|
|
86
|
+
return initResult
|
|
87
|
+
}
|
|
88
|
+
return { success: true }
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Ensure author information is loaded
|
|
93
|
+
*/
|
|
94
|
+
async ensureAuthor(): Promise<Author> {
|
|
95
|
+
if (this.currentAuthor) return this.currentAuthor
|
|
96
|
+
// detectAuthorForLogs returns a string (username), detect() returns full Author
|
|
97
|
+
const authorObj = await authorDetector.detect()
|
|
98
|
+
this.currentAuthor = {
|
|
99
|
+
name: authorObj.name,
|
|
100
|
+
email: authorObj.email,
|
|
101
|
+
github: authorObj.github
|
|
102
|
+
}
|
|
103
|
+
return this.currentAuthor
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get global project path
|
|
108
|
+
*/
|
|
109
|
+
async getGlobalProjectPath(projectPath: string): Promise<string> {
|
|
110
|
+
if (await migrator.needsMigration(projectPath)) {
|
|
111
|
+
throw new Error('Project needs migration. Run /p:migrate first.')
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
115
|
+
await pathManager.ensureProjectStructure(projectId!)
|
|
116
|
+
return pathManager.getGlobalProjectPath(projectId!)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Log to memory
|
|
121
|
+
*/
|
|
122
|
+
async logToMemory(projectPath: string, action: string, data: Record<string, unknown>): Promise<void> {
|
|
123
|
+
try {
|
|
124
|
+
const author = await this.ensureAuthor()
|
|
125
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
126
|
+
const memoryPath = pathManager.getFilePath(projectId!, 'memory', 'context.jsonl')
|
|
127
|
+
|
|
128
|
+
const entry = {
|
|
129
|
+
timestamp: dateHelper.getTimestamp(),
|
|
130
|
+
action,
|
|
131
|
+
data,
|
|
132
|
+
author: author.name,
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
await jsonlHelper.appendJsonLine(memoryPath, entry)
|
|
136
|
+
} catch {
|
|
137
|
+
// Non-critical - don't fail the command
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Detect if directory is empty (excluding common files)
|
|
143
|
+
*/
|
|
144
|
+
async _detectEmptyDirectory(projectPath: string): Promise<boolean> {
|
|
145
|
+
try {
|
|
146
|
+
const entries = await fileHelper.listFiles(projectPath)
|
|
147
|
+
const meaningfulFiles = entries.filter(
|
|
148
|
+
(name) =>
|
|
149
|
+
!name.startsWith('.') &&
|
|
150
|
+
name !== 'node_modules' &&
|
|
151
|
+
name !== 'package.json' &&
|
|
152
|
+
name !== 'package-lock.json' &&
|
|
153
|
+
name !== 'README.md'
|
|
154
|
+
)
|
|
155
|
+
return meaningfulFiles.length === 0
|
|
156
|
+
} catch {
|
|
157
|
+
return true
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Detect if directory has existing code
|
|
163
|
+
*/
|
|
164
|
+
async _detectExistingCode(projectPath: string): Promise<boolean> {
|
|
165
|
+
try {
|
|
166
|
+
const codePatterns = [
|
|
167
|
+
'src', 'lib', 'app', 'components', 'pages', 'api',
|
|
168
|
+
'main.go', 'main.rs', 'main.py',
|
|
169
|
+
]
|
|
170
|
+
const entries = await fileHelper.listFiles(projectPath)
|
|
171
|
+
return entries.some((name) => codePatterns.includes(name))
|
|
172
|
+
} catch {
|
|
173
|
+
return false
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Assign agent for a task
|
|
179
|
+
*/
|
|
180
|
+
async _assignAgentForTask(taskDescription: string, projectPath: string, _context: Context): Promise<AgentAssignmentResult> {
|
|
181
|
+
try {
|
|
182
|
+
const projectId = await configManager.getProjectId(projectPath)
|
|
183
|
+
const agentsPath = pathManager.getFilePath(projectId!, 'agents', '')
|
|
184
|
+
const agentFiles = await fileHelper.listFiles(agentsPath, { extension: '.md' })
|
|
185
|
+
const agents = agentFiles.map(f => f.replace('.md', ''))
|
|
186
|
+
|
|
187
|
+
return {
|
|
188
|
+
agent: { name: agents[0] || 'generalist', domain: 'auto' },
|
|
189
|
+
routing: {
|
|
190
|
+
confidence: 0.8,
|
|
191
|
+
reason: 'Claude assigns via templates/agent-assignment.md',
|
|
192
|
+
availableAgents: agents
|
|
193
|
+
},
|
|
194
|
+
_agenticNote: 'Use templates/agent-assignment.md for actual assignment'
|
|
195
|
+
}
|
|
196
|
+
} catch {
|
|
197
|
+
return {
|
|
198
|
+
agent: { name: 'generalist', domain: 'general' },
|
|
199
|
+
routing: { confidence: 0.5, reason: 'Fallback - no agents found' }
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Detect task complexity
|
|
206
|
+
*/
|
|
207
|
+
_detectComplexity(_task: string): ComplexityResult {
|
|
208
|
+
return { level: 'medium', hours: 4, type: 'feature' }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Calculate project health score
|
|
213
|
+
*/
|
|
214
|
+
_calculateHealth(stats: { activeTask: boolean; featuresShipped: number }): HealthResult {
|
|
215
|
+
const hasActivity = stats.activeTask || stats.featuresShipped > 0
|
|
216
|
+
return {
|
|
217
|
+
score: hasActivity ? 70 : 50,
|
|
218
|
+
message: hasActivity ? '🟢 Active' : '🟡 Ready to start',
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Render ASCII progress bar
|
|
224
|
+
*/
|
|
225
|
+
_renderProgressBar(label: string, value: number, max: number): void {
|
|
226
|
+
const percentage = Math.min(100, Math.round((value / max) * 100))
|
|
227
|
+
const barLength = 30
|
|
228
|
+
const filled = Math.round((percentage / 100) * barLength)
|
|
229
|
+
const empty = barLength - filled
|
|
230
|
+
|
|
231
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty)
|
|
232
|
+
console.log(` ${label}: [${bar}] ${percentage}%`)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Breakdown feature into tasks
|
|
237
|
+
*/
|
|
238
|
+
_breakdownFeatureTasks(description: string): string[] {
|
|
239
|
+
return [
|
|
240
|
+
`Analyze and plan: ${description}`,
|
|
241
|
+
'Implement core functionality',
|
|
242
|
+
'Test and validate',
|
|
243
|
+
'Document changes',
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Detect bug severity from description
|
|
249
|
+
*/
|
|
250
|
+
_detectBugSeverity(_description: string): string {
|
|
251
|
+
return 'medium'
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Auto-assign agent based on task (deprecated)
|
|
256
|
+
*/
|
|
257
|
+
_autoAssignAgent(_task: string): string {
|
|
258
|
+
console.warn('DEPRECATED: Use _assignAgentForTask() for proper agent routing')
|
|
259
|
+
return 'generalist'
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Re-export dependencies for use by other modules
|
|
264
|
+
export {
|
|
265
|
+
contextBuilder,
|
|
266
|
+
toolRegistry,
|
|
267
|
+
pathManager,
|
|
268
|
+
configManager,
|
|
269
|
+
fileHelper,
|
|
270
|
+
jsonlHelper,
|
|
271
|
+
dateHelper,
|
|
272
|
+
out
|
|
273
|
+
}
|