prjct-cli 0.11.5 → 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 +58 -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 +226 -50
- 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.js → date-helper.test.ts} +19 -30
- 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} +92 -81
- 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} +27 -16
- 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} +55 -19
- 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 +204 -163
- 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/{stats → BentoGrid}/BentoGrid.tsx +4 -8
- 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/{stats → EmptyState}/EmptyState.tsx +1 -10
- 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/{stats → IdeasCard}/IdeasCard.tsx +3 -14
- 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/{stats → ProgressRing}/ProgressRing.tsx +4 -27
- 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/{stats → RoadmapCard}/RoadmapCard.tsx +3 -23
- package/packages/web/components/RoadmapCard/RoadmapCard.types.ts +15 -0
- package/packages/web/components/RoadmapCard/index.ts +2 -0
- package/packages/web/components/{stats → ShipsCard}/ShipsCard.tsx +4 -22
- 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/{stats → SparklineChart}/SparklineChart.tsx +1 -7
- 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/{stats → StreakCard}/StreakCard.tsx +5 -11
- 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/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/package.json +10 -7
- 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 -140
- package/core/agentic/chain-of-thought.js +0 -578
- package/core/agentic/command-executor.js +0 -417
- 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 -845
- package/core/agentic/parallel-tools.js +0 -366
- package/core/agentic/plan-mode.js +0 -572
- package/core/agentic/prompt-builder.js +0 -352
- 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 -796
- 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/components/stats/ActivityTimeline.tsx +0 -201
- package/packages/web/components/stats/AgentsCard.tsx +0 -56
- package/packages/web/components/stats/BentoCard.tsx +0 -88
- package/packages/web/components/stats/HeroSection.tsx +0 -172
- package/packages/web/components/stats/NowCard.tsx +0 -71
- package/packages/web/components/stats/QueueCard.tsx +0 -58
- package/packages/web/components/stats/VelocityCard.tsx +0 -60
- package/packages/web/components/stats/index.ts +0 -17
- 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,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Roadmap Schema
|
|
3
|
+
*
|
|
4
|
+
* Defines the structure for roadmap.json - feature roadmap.
|
|
5
|
+
* Matches json-loader.ts types exactly.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type FeatureStatus = 'planned' | 'active' | 'completed' | 'shipped'
|
|
9
|
+
export type FeatureImpact = 'low' | 'medium' | 'high'
|
|
10
|
+
export type FeatureType = 'feature' | 'breaking_change' | 'refactor' | 'infrastructure'
|
|
11
|
+
|
|
12
|
+
export interface FeatureTask {
|
|
13
|
+
id: string // task_xxxxxxxx
|
|
14
|
+
description: string
|
|
15
|
+
completed: boolean
|
|
16
|
+
completedAt?: string // ISO8601
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface RoadmapPhase {
|
|
20
|
+
id: string // P0, P1, etc.
|
|
21
|
+
name: string
|
|
22
|
+
status: 'completed' | 'active' | 'planned'
|
|
23
|
+
completedAt?: string // ISO8601
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface RoadmapStrategy {
|
|
27
|
+
goal: string
|
|
28
|
+
phases: RoadmapPhase[]
|
|
29
|
+
successMetrics?: string[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Duration for completed sprints/features
|
|
33
|
+
export interface FeatureDuration {
|
|
34
|
+
hours: number
|
|
35
|
+
minutes: number
|
|
36
|
+
totalMinutes: number
|
|
37
|
+
display?: string // "~25m", "~1h"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface FeatureSchema {
|
|
41
|
+
id: string // feat_xxxxxxxx
|
|
42
|
+
name: string
|
|
43
|
+
description?: string
|
|
44
|
+
date: string // YYYY-MM-DD creation date
|
|
45
|
+
status: FeatureStatus
|
|
46
|
+
impact: FeatureImpact
|
|
47
|
+
effort?: string // "1-2 days" or similar
|
|
48
|
+
progress: number // 0-100
|
|
49
|
+
// Enriched fields from MD
|
|
50
|
+
type?: FeatureType
|
|
51
|
+
roi?: number // 1-5 from star count
|
|
52
|
+
why?: string[] // from ### Why This Feature? section
|
|
53
|
+
technicalNotes?: string[] // from ### Technical Notes section
|
|
54
|
+
compatibility?: string
|
|
55
|
+
phase?: string // P0, P1, etc.
|
|
56
|
+
tasks: FeatureTask[]
|
|
57
|
+
createdAt: string // ISO8601
|
|
58
|
+
shippedAt?: string // ISO8601
|
|
59
|
+
version?: string // Release version when shipped
|
|
60
|
+
// ZERO DATA LOSS - additional fields
|
|
61
|
+
duration?: FeatureDuration // "~25m", "~1h" parsed
|
|
62
|
+
taskCount?: number // "7 tasks" from MD header
|
|
63
|
+
agent?: string // "fe+be", "fe", "be"
|
|
64
|
+
sprintName?: string // "Sprint 6 - Reports + Audits"
|
|
65
|
+
completedDate?: string // "2025-12-09" from MD
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface RoadmapJson {
|
|
69
|
+
strategy?: RoadmapStrategy | null
|
|
70
|
+
features: FeatureSchema[]
|
|
71
|
+
backlog: string[]
|
|
72
|
+
lastUpdated: string
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Legacy type for backwards compatibility
|
|
76
|
+
export type RoadmapSchema = FeatureSchema[]
|
|
77
|
+
|
|
78
|
+
export const DEFAULT_FEATURE: Omit<FeatureSchema, 'id' | 'name'> = {
|
|
79
|
+
status: 'planned',
|
|
80
|
+
impact: 'medium',
|
|
81
|
+
progress: 0,
|
|
82
|
+
tasks: [],
|
|
83
|
+
createdAt: new Date().toISOString()
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export const DEFAULT_ROADMAP: RoadmapJson = {
|
|
87
|
+
features: [],
|
|
88
|
+
backlog: [],
|
|
89
|
+
lastUpdated: ''
|
|
90
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shipped Schema
|
|
3
|
+
*
|
|
4
|
+
* Defines the structure for shipped.json - completed/shipped items.
|
|
5
|
+
* ZERO DATA LOSS - captures ALL fields from MD files.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type ShipType = 'feature' | 'fix' | 'improvement' | 'refactor'
|
|
9
|
+
export type CheckStatus = 'pass' | 'warning' | 'fail' | 'skipped'
|
|
10
|
+
export type AgentType = 'fe' | 'be' | 'fe+be' | 'devops' | 'ai' | string
|
|
11
|
+
|
|
12
|
+
// Duration object for parsed time strings like "13h 38m"
|
|
13
|
+
export interface Duration {
|
|
14
|
+
hours: number
|
|
15
|
+
minutes: number
|
|
16
|
+
totalMinutes: number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Code metrics from "Files: 4 | +160/-31 | Commits: 0"
|
|
20
|
+
export interface CodeMetrics {
|
|
21
|
+
filesChanged?: number | null
|
|
22
|
+
linesAdded?: number | null
|
|
23
|
+
linesRemoved?: number | null
|
|
24
|
+
commits?: number | null
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface ShipChange {
|
|
28
|
+
description: string
|
|
29
|
+
type?: 'added' | 'changed' | 'fixed' | 'removed'
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface QualityMetrics {
|
|
33
|
+
lintStatus?: CheckStatus | null
|
|
34
|
+
lintDetails?: string
|
|
35
|
+
testStatus?: CheckStatus | null
|
|
36
|
+
testDetails?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Git commit information
|
|
40
|
+
export interface CommitInfo {
|
|
41
|
+
hash?: string // "0a7bbea"
|
|
42
|
+
message?: string // "feat(security): Multi-tenant..."
|
|
43
|
+
branch?: string // "main"
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface ShippedItemSchema {
|
|
47
|
+
id: string // ship_xxxxxxxx
|
|
48
|
+
name: string
|
|
49
|
+
version?: string | null // "0.11.6" extracted from MD
|
|
50
|
+
type: ShipType
|
|
51
|
+
// Agent who worked on this
|
|
52
|
+
agent?: AgentType // "fe+be", "be", "fe"
|
|
53
|
+
// Full description (narrative text, not just bullet points)
|
|
54
|
+
description?: string // "CRITICAL: Multi-tenant isolation hardening..."
|
|
55
|
+
// Changelog from bullet points
|
|
56
|
+
changes: ShipChange[]
|
|
57
|
+
// Code snippets if any
|
|
58
|
+
codeSnippets?: string[] // TypeScript/code examples from MD
|
|
59
|
+
// Git commit info
|
|
60
|
+
commit?: CommitInfo
|
|
61
|
+
// Enriched fields from MD
|
|
62
|
+
codeMetrics?: CodeMetrics
|
|
63
|
+
qualityMetrics?: QualityMetrics
|
|
64
|
+
quantitativeImpact?: string // "81% (1,079 → 204 lines)"
|
|
65
|
+
duration?: Duration // parsed from "13h 38m"
|
|
66
|
+
tasksCompleted?: number | null
|
|
67
|
+
shippedAt: string // ISO8601
|
|
68
|
+
featureId?: string
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface ShippedJson {
|
|
72
|
+
items: ShippedItemSchema[]
|
|
73
|
+
lastUpdated: string
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Legacy type for backwards compatibility
|
|
77
|
+
export type ShippedSchema = ShippedItemSchema[]
|
|
78
|
+
|
|
79
|
+
export const DEFAULT_SHIPPED: ShippedJson = {
|
|
80
|
+
items: [],
|
|
81
|
+
lastUpdated: ''
|
|
82
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Schema
|
|
3
|
+
*
|
|
4
|
+
* Defines the structure for state.json - current task state.
|
|
5
|
+
* Queue is now separate in queue.json.
|
|
6
|
+
*
|
|
7
|
+
* Matches json-loader.ts types exactly.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type Priority = 'low' | 'medium' | 'high' | 'critical'
|
|
11
|
+
export type TaskType = 'feature' | 'bug' | 'improvement' | 'chore'
|
|
12
|
+
export type TaskSection = 'active' | 'backlog' | 'previously_active'
|
|
13
|
+
|
|
14
|
+
export interface CurrentTask {
|
|
15
|
+
id: string // task_xxxxxxxx
|
|
16
|
+
description: string
|
|
17
|
+
startedAt: string // ISO8601
|
|
18
|
+
sessionId: string // sess_xxxxxxxx
|
|
19
|
+
featureId?: string // feat_xxxxxxxx
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface PreviousTask {
|
|
23
|
+
id: string
|
|
24
|
+
description: string
|
|
25
|
+
status: 'paused'
|
|
26
|
+
startedAt: string // ISO8601
|
|
27
|
+
pausedAt: string // ISO8601
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// StateJson is the wrapper for state.json file
|
|
31
|
+
export interface StateJson {
|
|
32
|
+
currentTask: CurrentTask | null
|
|
33
|
+
previousTask?: PreviousTask | null
|
|
34
|
+
lastUpdated: string
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// QueueJson is the wrapper for queue.json file
|
|
38
|
+
export interface QueueTask {
|
|
39
|
+
id: string // task_xxxxxxxx
|
|
40
|
+
description: string
|
|
41
|
+
priority: Priority
|
|
42
|
+
type: TaskType // detect from emoji 🐛=bug
|
|
43
|
+
featureId?: string
|
|
44
|
+
originFeature?: string // from "(from: Feature Name)" pattern
|
|
45
|
+
completed: boolean
|
|
46
|
+
completedAt?: string // ISO8601
|
|
47
|
+
createdAt: string // ISO8601
|
|
48
|
+
section: TaskSection // based on MD section
|
|
49
|
+
// Additional fields for ZERO DATA LOSS
|
|
50
|
+
agent?: string // "fe", "be", "fe + be"
|
|
51
|
+
groupName?: string // "Sales Reports", "Stock Audits"
|
|
52
|
+
groupId?: string // For grouping related tasks
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface QueueJson {
|
|
56
|
+
tasks: QueueTask[]
|
|
57
|
+
lastUpdated: string
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Legacy types for backwards compatibility
|
|
61
|
+
export type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'blocked' | 'paused'
|
|
62
|
+
export type ActivityType = 'task_completed' | 'feature_shipped' | 'idea_captured' | 'session_started'
|
|
63
|
+
|
|
64
|
+
export interface QueuedTask extends QueueTask {} // Alias
|
|
65
|
+
|
|
66
|
+
export interface Stats {
|
|
67
|
+
tasksToday: number
|
|
68
|
+
tasksThisWeek: number
|
|
69
|
+
streak: number
|
|
70
|
+
velocity: string
|
|
71
|
+
avgDuration: string
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface RecentActivity {
|
|
75
|
+
type: ActivityType
|
|
76
|
+
description: string
|
|
77
|
+
timestamp: string // ISO8601
|
|
78
|
+
duration?: string
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface StateSchema {
|
|
82
|
+
projectId: string
|
|
83
|
+
currentTask: CurrentTask | null
|
|
84
|
+
queue: QueuedTask[]
|
|
85
|
+
stats: Stats
|
|
86
|
+
recentActivity: RecentActivity[]
|
|
87
|
+
lastSync: string // ISO8601
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Defaults
|
|
91
|
+
export const DEFAULT_STATE: StateJson = {
|
|
92
|
+
currentTask: null,
|
|
93
|
+
lastUpdated: ''
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export const DEFAULT_QUEUE: QueueJson = {
|
|
97
|
+
tasks: [],
|
|
98
|
+
lastUpdated: ''
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const DEFAULT_STATS: Stats = {
|
|
102
|
+
tasksToday: 0,
|
|
103
|
+
tasksThisWeek: 0,
|
|
104
|
+
streak: 0,
|
|
105
|
+
velocity: '0/day',
|
|
106
|
+
avgDuration: '0m'
|
|
107
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionManager - Structured Session Tracking
|
|
3
|
+
*
|
|
4
|
+
* Tracks work sessions with metrics, timeline, and duration.
|
|
5
|
+
* Inspired by OpenCode's session system but simplified.
|
|
6
|
+
*
|
|
7
|
+
* Storage: ~/.prjct-cli/projects/{projectId}/sessions/
|
|
8
|
+
*
|
|
9
|
+
* @version 1.0.0
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export type { Session, SessionMetrics, TimelineEvent } from './types'
|
|
13
|
+
export { generateId, calculateDuration, formatDuration } from './utils'
|
|
14
|
+
export { SessionManager } from './session-manager'
|
|
15
|
+
|
|
16
|
+
import { SessionManager } from './session-manager'
|
|
17
|
+
export default SessionManager
|
|
@@ -6,21 +6,58 @@
|
|
|
6
6
|
* @version 1.0.0
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import fs from 'fs/promises'
|
|
10
|
+
import path from 'path'
|
|
11
|
+
import pathManager from '../infrastructure/path-manager'
|
|
12
|
+
|
|
13
|
+
interface Session {
|
|
14
|
+
id: string
|
|
15
|
+
status: 'active' | 'paused' | 'completed'
|
|
16
|
+
startedAt: string
|
|
17
|
+
completedAt?: string
|
|
18
|
+
duration: number
|
|
19
|
+
metrics?: {
|
|
20
|
+
filesChanged?: number
|
|
21
|
+
linesAdded?: number
|
|
22
|
+
linesRemoved?: number
|
|
23
|
+
commits?: number
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface DayMetrics {
|
|
28
|
+
sessions: number
|
|
29
|
+
duration: number
|
|
30
|
+
commits: number
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
interface AggregatedMetrics {
|
|
34
|
+
period: string
|
|
35
|
+
totalSessions: number
|
|
36
|
+
totalDuration: number
|
|
37
|
+
totalDurationFormatted: string
|
|
38
|
+
averageDuration: number
|
|
39
|
+
averageDurationFormatted: string
|
|
40
|
+
tasksCompleted: number
|
|
41
|
+
filesChanged: number
|
|
42
|
+
linesAdded: number
|
|
43
|
+
linesRemoved: number
|
|
44
|
+
commits: number
|
|
45
|
+
productivityScore: number
|
|
46
|
+
streak: number
|
|
47
|
+
byDay: Record<string, DayMetrics>
|
|
48
|
+
}
|
|
12
49
|
|
|
13
50
|
class SessionMetrics {
|
|
14
|
-
|
|
51
|
+
private projectId: string
|
|
52
|
+
|
|
53
|
+
constructor(projectId: string) {
|
|
15
54
|
this.projectId = projectId
|
|
16
55
|
}
|
|
17
56
|
|
|
18
57
|
/**
|
|
19
58
|
* Get aggregated metrics for a time period
|
|
20
|
-
* @param {'day'|'week'|'month'|'all'} period
|
|
21
|
-
* @returns {Promise<Object>}
|
|
22
59
|
*/
|
|
23
|
-
async getMetrics(period = 'week') {
|
|
60
|
+
async getMetrics(period: 'day' | 'week' | 'month' | 'all' = 'week'): Promise<AggregatedMetrics> {
|
|
24
61
|
const sessions = await this.getSessionsForPeriod(period)
|
|
25
62
|
|
|
26
63
|
return {
|
|
@@ -43,14 +80,12 @@ class SessionMetrics {
|
|
|
43
80
|
|
|
44
81
|
/**
|
|
45
82
|
* Get sessions for a given period
|
|
46
|
-
* @param {string} period
|
|
47
|
-
* @returns {Promise<Array>}
|
|
48
83
|
*/
|
|
49
|
-
async getSessionsForPeriod(period) {
|
|
84
|
+
async getSessionsForPeriod(period: string): Promise<Session[]> {
|
|
50
85
|
const globalPath = pathManager.getGlobalProjectPath(this.projectId)
|
|
51
86
|
const archiveDir = path.join(globalPath, 'sessions', 'archive')
|
|
52
87
|
|
|
53
|
-
const sessions = []
|
|
88
|
+
const sessions: Session[] = []
|
|
54
89
|
const cutoffDate = this.getCutoffDate(period)
|
|
55
90
|
|
|
56
91
|
try {
|
|
@@ -64,9 +99,9 @@ class SessionMetrics {
|
|
|
64
99
|
if (!file.endsWith('.json')) continue
|
|
65
100
|
|
|
66
101
|
const content = await fs.readFile(path.join(monthDir, file), 'utf-8')
|
|
67
|
-
const session = JSON.parse(content)
|
|
102
|
+
const session: Session = JSON.parse(content)
|
|
68
103
|
|
|
69
|
-
if (new Date(session.completedAt) >= cutoffDate) {
|
|
104
|
+
if (session.completedAt && new Date(session.completedAt) >= cutoffDate) {
|
|
70
105
|
sessions.push(session)
|
|
71
106
|
}
|
|
72
107
|
}
|
|
@@ -79,7 +114,7 @@ class SessionMetrics {
|
|
|
79
114
|
try {
|
|
80
115
|
const currentPath = path.join(globalPath, 'sessions', 'current.json')
|
|
81
116
|
const content = await fs.readFile(currentPath, 'utf-8')
|
|
82
|
-
const current = JSON.parse(content)
|
|
117
|
+
const current: Session = JSON.parse(content)
|
|
83
118
|
if (new Date(current.startedAt) >= cutoffDate) {
|
|
84
119
|
sessions.push(current)
|
|
85
120
|
}
|
|
@@ -92,10 +127,8 @@ class SessionMetrics {
|
|
|
92
127
|
|
|
93
128
|
/**
|
|
94
129
|
* Get cutoff date for period
|
|
95
|
-
* @param {string} period
|
|
96
|
-
* @returns {Date}
|
|
97
130
|
*/
|
|
98
|
-
getCutoffDate(period) {
|
|
131
|
+
getCutoffDate(period: string): Date {
|
|
99
132
|
const now = new Date()
|
|
100
133
|
|
|
101
134
|
switch (period) {
|
|
@@ -117,30 +150,23 @@ class SessionMetrics {
|
|
|
117
150
|
|
|
118
151
|
/**
|
|
119
152
|
* Sum durations from sessions
|
|
120
|
-
* @param {Array} sessions
|
|
121
|
-
* @returns {number} Total seconds
|
|
122
153
|
*/
|
|
123
|
-
sumDurations(sessions) {
|
|
154
|
+
sumDurations(sessions: Session[]): number {
|
|
124
155
|
return sessions.reduce((sum, s) => sum + (s.duration || 0), 0)
|
|
125
156
|
}
|
|
126
157
|
|
|
127
158
|
/**
|
|
128
159
|
* Calculate average duration
|
|
129
|
-
* @param {Array} sessions
|
|
130
|
-
* @returns {number} Average seconds
|
|
131
160
|
*/
|
|
132
|
-
averageDuration(sessions) {
|
|
161
|
+
averageDuration(sessions: Session[]): number {
|
|
133
162
|
if (sessions.length === 0) return 0
|
|
134
163
|
return Math.round(this.sumDurations(sessions) / sessions.length)
|
|
135
164
|
}
|
|
136
165
|
|
|
137
166
|
/**
|
|
138
167
|
* Sum a specific metric
|
|
139
|
-
* @param {Array} sessions
|
|
140
|
-
* @param {string} metric
|
|
141
|
-
* @returns {number}
|
|
142
168
|
*/
|
|
143
|
-
sumMetric(sessions, metric) {
|
|
169
|
+
sumMetric(sessions: Session[], metric: 'filesChanged' | 'linesAdded' | 'linesRemoved' | 'commits'): number {
|
|
144
170
|
return sessions.reduce((sum, s) => {
|
|
145
171
|
return sum + (s.metrics?.[metric] || 0)
|
|
146
172
|
}, 0)
|
|
@@ -149,10 +175,8 @@ class SessionMetrics {
|
|
|
149
175
|
/**
|
|
150
176
|
* Calculate productivity score (0-100)
|
|
151
177
|
* Based on consistency, duration, and output
|
|
152
|
-
* @param {Array} sessions
|
|
153
|
-
* @returns {number}
|
|
154
178
|
*/
|
|
155
|
-
calculateProductivityScore(sessions) {
|
|
179
|
+
calculateProductivityScore(sessions: Session[]): number {
|
|
156
180
|
if (sessions.length === 0) return 0
|
|
157
181
|
|
|
158
182
|
// Factors:
|
|
@@ -181,9 +205,8 @@ class SessionMetrics {
|
|
|
181
205
|
|
|
182
206
|
/**
|
|
183
207
|
* Calculate current streak (consecutive days with sessions)
|
|
184
|
-
* @returns {Promise<number>}
|
|
185
208
|
*/
|
|
186
|
-
async calculateStreak() {
|
|
209
|
+
async calculateStreak(): Promise<number> {
|
|
187
210
|
const sessions = await this.getSessionsForPeriod('month')
|
|
188
211
|
|
|
189
212
|
// Get unique dates with sessions
|
|
@@ -215,11 +238,9 @@ class SessionMetrics {
|
|
|
215
238
|
|
|
216
239
|
/**
|
|
217
240
|
* Group sessions by day
|
|
218
|
-
* @param {Array} sessions
|
|
219
|
-
* @returns {Object}
|
|
220
241
|
*/
|
|
221
|
-
groupByDay(sessions) {
|
|
222
|
-
const byDay = {}
|
|
242
|
+
groupByDay(sessions: Session[]): Record<string, DayMetrics> {
|
|
243
|
+
const byDay: Record<string, DayMetrics> = {}
|
|
223
244
|
|
|
224
245
|
for (const session of sessions) {
|
|
225
246
|
const date = new Date(session.completedAt || session.startedAt)
|
|
@@ -243,10 +264,8 @@ class SessionMetrics {
|
|
|
243
264
|
|
|
244
265
|
/**
|
|
245
266
|
* Format duration as human readable
|
|
246
|
-
* @param {number} seconds
|
|
247
|
-
* @returns {string}
|
|
248
267
|
*/
|
|
249
|
-
formatDuration(seconds) {
|
|
268
|
+
formatDuration(seconds: number): string {
|
|
250
269
|
if (seconds < 60) return `${seconds}s`
|
|
251
270
|
if (seconds < 3600) return `${Math.round(seconds / 60)}m`
|
|
252
271
|
|
|
@@ -259,21 +278,19 @@ class SessionMetrics {
|
|
|
259
278
|
|
|
260
279
|
/**
|
|
261
280
|
* Generate metrics summary for display
|
|
262
|
-
* @param {'day'|'week'|'month'} period
|
|
263
|
-
* @returns {Promise<string>}
|
|
264
281
|
*/
|
|
265
|
-
async generateSummary(period = 'week') {
|
|
282
|
+
async generateSummary(period: 'day' | 'week' | 'month' = 'week'): Promise<string> {
|
|
266
283
|
const m = await this.getMetrics(period)
|
|
267
284
|
|
|
268
|
-
const periodLabel = {
|
|
285
|
+
const periodLabel: Record<string, string> = {
|
|
269
286
|
day: 'Today',
|
|
270
287
|
week: 'This Week',
|
|
271
288
|
month: 'This Month',
|
|
272
289
|
all: 'All Time'
|
|
273
|
-
}
|
|
290
|
+
}
|
|
274
291
|
|
|
275
292
|
return `
|
|
276
|
-
## ${periodLabel}
|
|
293
|
+
## ${periodLabel[period]}
|
|
277
294
|
|
|
278
295
|
| Metric | Value |
|
|
279
296
|
|--------|-------|
|
|
@@ -290,4 +307,5 @@ class SessionMetrics {
|
|
|
290
307
|
}
|
|
291
308
|
}
|
|
292
309
|
|
|
293
|
-
|
|
310
|
+
export default SessionMetrics
|
|
311
|
+
export { SessionMetrics, AggregatedMetrics, DayMetrics }
|