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,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Manager
|
|
3
|
+
*
|
|
4
|
+
* Manages unified project state with atomic read/write operations.
|
|
5
|
+
* Replaces scattered file reads with single state.json access.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import path from 'path'
|
|
9
|
+
import * as fileHelper from '../utils/file-helper'
|
|
10
|
+
import pathManager from '../infrastructure/path-manager'
|
|
11
|
+
import type {
|
|
12
|
+
ProjectState,
|
|
13
|
+
CurrentTask,
|
|
14
|
+
QueuedTask,
|
|
15
|
+
ActiveFeature,
|
|
16
|
+
PerformanceStats,
|
|
17
|
+
RecentActivity,
|
|
18
|
+
StateUpdate,
|
|
19
|
+
} from './types'
|
|
20
|
+
import { DEFAULT_STATE } from './types'
|
|
21
|
+
|
|
22
|
+
const STATE_FILENAME = 'state.json'
|
|
23
|
+
const MAX_RECENT_ACTIVITY = 10
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* StateManager - Single source of truth for project state.
|
|
27
|
+
*/
|
|
28
|
+
export class StateManager {
|
|
29
|
+
private cache: Map<string, ProjectState> = new Map()
|
|
30
|
+
private cacheTimeout = 5000 // 5 seconds
|
|
31
|
+
private lastRead: Map<string, number> = new Map()
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get state file path for a project.
|
|
35
|
+
*/
|
|
36
|
+
private getStatePath(projectId: string): string {
|
|
37
|
+
const globalPath = pathManager.getGlobalProjectPath(projectId)
|
|
38
|
+
return path.join(globalPath, 'core', STATE_FILENAME)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Read project state.
|
|
43
|
+
* Uses cache if available and fresh.
|
|
44
|
+
*/
|
|
45
|
+
async read(projectId: string): Promise<ProjectState> {
|
|
46
|
+
const now = Date.now()
|
|
47
|
+
const lastReadTime = this.lastRead.get(projectId) || 0
|
|
48
|
+
|
|
49
|
+
// Return cached if fresh
|
|
50
|
+
if (now - lastReadTime < this.cacheTimeout && this.cache.has(projectId)) {
|
|
51
|
+
return this.cache.get(projectId)!
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const statePath = this.getStatePath(projectId)
|
|
55
|
+
const state = await fileHelper.readJson<ProjectState>(statePath, {
|
|
56
|
+
...DEFAULT_STATE,
|
|
57
|
+
projectId,
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Update cache
|
|
61
|
+
this.cache.set(projectId, state)
|
|
62
|
+
this.lastRead.set(projectId, now)
|
|
63
|
+
|
|
64
|
+
return state
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Write project state atomically.
|
|
69
|
+
*/
|
|
70
|
+
async write(projectId: string, state: ProjectState): Promise<void> {
|
|
71
|
+
const statePath = this.getStatePath(projectId)
|
|
72
|
+
|
|
73
|
+
// Ensure directory exists
|
|
74
|
+
await fileHelper.ensureDir(path.dirname(statePath))
|
|
75
|
+
|
|
76
|
+
// Update lastSync
|
|
77
|
+
const updatedState: ProjectState = {
|
|
78
|
+
...state,
|
|
79
|
+
lastSync: new Date().toISOString(),
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
await fileHelper.writeJson(statePath, updatedState)
|
|
83
|
+
|
|
84
|
+
// Update cache
|
|
85
|
+
this.cache.set(projectId, updatedState)
|
|
86
|
+
this.lastRead.set(projectId, Date.now())
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Apply an update to project state.
|
|
91
|
+
*/
|
|
92
|
+
async update(projectId: string, update: StateUpdate): Promise<ProjectState> {
|
|
93
|
+
const state = await this.read(projectId)
|
|
94
|
+
const newState = this.applyUpdate(state, update)
|
|
95
|
+
await this.write(projectId, newState)
|
|
96
|
+
return newState
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Apply multiple updates atomically.
|
|
101
|
+
*/
|
|
102
|
+
async batchUpdate(projectId: string, updates: StateUpdate[]): Promise<ProjectState> {
|
|
103
|
+
let state = await this.read(projectId)
|
|
104
|
+
for (const update of updates) {
|
|
105
|
+
state = this.applyUpdate(state, update)
|
|
106
|
+
}
|
|
107
|
+
await this.write(projectId, state)
|
|
108
|
+
return state
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Apply a single update to state.
|
|
113
|
+
*/
|
|
114
|
+
private applyUpdate(state: ProjectState, update: StateUpdate): ProjectState {
|
|
115
|
+
switch (update.type) {
|
|
116
|
+
case 'SET_CURRENT_TASK':
|
|
117
|
+
return { ...state, currentTask: update.task }
|
|
118
|
+
|
|
119
|
+
case 'ADD_TO_QUEUE':
|
|
120
|
+
return {
|
|
121
|
+
...state,
|
|
122
|
+
queue: [...state.queue, update.task].sort((a, b) => {
|
|
123
|
+
const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 }
|
|
124
|
+
return priorityOrder[a.priority] - priorityOrder[b.priority]
|
|
125
|
+
}),
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
case 'REMOVE_FROM_QUEUE':
|
|
129
|
+
return {
|
|
130
|
+
...state,
|
|
131
|
+
queue: state.queue.filter((t) => t.id !== update.taskId),
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
case 'UPDATE_QUEUE_TASK':
|
|
135
|
+
return {
|
|
136
|
+
...state,
|
|
137
|
+
queue: state.queue.map((t) =>
|
|
138
|
+
t.id === update.taskId ? { ...t, ...update.updates } : t
|
|
139
|
+
),
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
case 'SET_ACTIVE_FEATURE':
|
|
143
|
+
return { ...state, activeFeature: update.feature }
|
|
144
|
+
|
|
145
|
+
case 'UPDATE_STATS':
|
|
146
|
+
return {
|
|
147
|
+
...state,
|
|
148
|
+
stats: { ...state.stats, ...update.stats },
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
case 'ADD_ACTIVITY':
|
|
152
|
+
return {
|
|
153
|
+
...state,
|
|
154
|
+
recentActivity: [update.activity, ...state.recentActivity].slice(
|
|
155
|
+
0,
|
|
156
|
+
MAX_RECENT_ACTIVITY
|
|
157
|
+
),
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
case 'SYNC':
|
|
161
|
+
return { ...state, lastSync: new Date().toISOString() }
|
|
162
|
+
|
|
163
|
+
default:
|
|
164
|
+
return state
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// =========== Convenience Methods ===========
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Start a new task.
|
|
172
|
+
*/
|
|
173
|
+
async startTask(
|
|
174
|
+
projectId: string,
|
|
175
|
+
task: Omit<CurrentTask, 'startedAt'>
|
|
176
|
+
): Promise<ProjectState> {
|
|
177
|
+
const currentTask: CurrentTask = {
|
|
178
|
+
...task,
|
|
179
|
+
startedAt: new Date().toISOString(),
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return this.batchUpdate(projectId, [
|
|
183
|
+
{ type: 'SET_CURRENT_TASK', task: currentTask },
|
|
184
|
+
{
|
|
185
|
+
type: 'ADD_ACTIVITY',
|
|
186
|
+
activity: {
|
|
187
|
+
type: 'session_started',
|
|
188
|
+
description: task.description,
|
|
189
|
+
timestamp: new Date().toISOString(),
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
])
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Complete the current task.
|
|
197
|
+
*/
|
|
198
|
+
async completeTask(projectId: string, duration: string): Promise<ProjectState> {
|
|
199
|
+
const state = await this.read(projectId)
|
|
200
|
+
if (!state.currentTask) {
|
|
201
|
+
throw new Error('No active task to complete')
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const activity: RecentActivity = {
|
|
205
|
+
type: 'task_completed',
|
|
206
|
+
description: state.currentTask.description,
|
|
207
|
+
timestamp: new Date().toISOString(),
|
|
208
|
+
duration,
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Update feature progress if linked
|
|
212
|
+
let featureUpdate: StateUpdate | null = null
|
|
213
|
+
if (state.activeFeature && state.currentTask.featureId === state.activeFeature.id) {
|
|
214
|
+
featureUpdate = {
|
|
215
|
+
type: 'SET_ACTIVE_FEATURE',
|
|
216
|
+
feature: {
|
|
217
|
+
...state.activeFeature,
|
|
218
|
+
tasksCompleted: state.activeFeature.tasksCompleted + 1,
|
|
219
|
+
tasksRemaining: Math.max(0, state.activeFeature.tasksRemaining - 1),
|
|
220
|
+
},
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const updates: StateUpdate[] = [
|
|
225
|
+
{ type: 'SET_CURRENT_TASK', task: null },
|
|
226
|
+
{ type: 'ADD_ACTIVITY', activity },
|
|
227
|
+
{
|
|
228
|
+
type: 'UPDATE_STATS',
|
|
229
|
+
stats: { tasksToday: state.stats.tasksToday + 1 },
|
|
230
|
+
},
|
|
231
|
+
]
|
|
232
|
+
|
|
233
|
+
if (featureUpdate) {
|
|
234
|
+
updates.push(featureUpdate)
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return this.batchUpdate(projectId, updates)
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Pause the current task.
|
|
242
|
+
*/
|
|
243
|
+
async pauseTask(projectId: string, reason?: string): Promise<ProjectState> {
|
|
244
|
+
const state = await this.read(projectId)
|
|
245
|
+
if (!state.currentTask) {
|
|
246
|
+
throw new Error('No active task to pause')
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
const pausedTask: CurrentTask = {
|
|
250
|
+
...state.currentTask,
|
|
251
|
+
pausedAt: new Date().toISOString(),
|
|
252
|
+
pauseReason: reason,
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
return this.update(projectId, { type: 'SET_CURRENT_TASK', task: pausedTask })
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Resume a paused task.
|
|
260
|
+
*/
|
|
261
|
+
async resumeTask(projectId: string): Promise<ProjectState> {
|
|
262
|
+
const state = await this.read(projectId)
|
|
263
|
+
if (!state.currentTask || !state.currentTask.pausedAt) {
|
|
264
|
+
throw new Error('No paused task to resume')
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const resumedTask: CurrentTask = {
|
|
268
|
+
...state.currentTask,
|
|
269
|
+
pausedAt: undefined,
|
|
270
|
+
pauseReason: undefined,
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return this.update(projectId, { type: 'SET_CURRENT_TASK', task: resumedTask })
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/**
|
|
277
|
+
* Add a task to the queue.
|
|
278
|
+
*/
|
|
279
|
+
async addToQueue(
|
|
280
|
+
projectId: string,
|
|
281
|
+
task: Omit<QueuedTask, 'id' | 'createdAt'>
|
|
282
|
+
): Promise<ProjectState> {
|
|
283
|
+
const queuedTask: QueuedTask = {
|
|
284
|
+
...task,
|
|
285
|
+
id: `task_${Date.now()}`,
|
|
286
|
+
createdAt: new Date().toISOString(),
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return this.update(projectId, { type: 'ADD_TO_QUEUE', task: queuedTask })
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get the next task from queue.
|
|
294
|
+
*/
|
|
295
|
+
async getNextTask(projectId: string): Promise<QueuedTask | null> {
|
|
296
|
+
const state = await this.read(projectId)
|
|
297
|
+
return state.queue.find((t) => t.blockedReason === undefined) || null
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Start a feature.
|
|
302
|
+
*/
|
|
303
|
+
async startFeature(
|
|
304
|
+
projectId: string,
|
|
305
|
+
feature: Omit<ActiveFeature, 'startedAt' | 'tasksCompleted' | 'status'>
|
|
306
|
+
): Promise<ProjectState> {
|
|
307
|
+
const activeFeature: ActiveFeature = {
|
|
308
|
+
...feature,
|
|
309
|
+
status: 'in_progress',
|
|
310
|
+
tasksCompleted: 0,
|
|
311
|
+
startedAt: new Date().toISOString(),
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return this.update(projectId, { type: 'SET_ACTIVE_FEATURE', feature: activeFeature })
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Ship a feature.
|
|
319
|
+
*/
|
|
320
|
+
async shipFeature(projectId: string): Promise<ProjectState> {
|
|
321
|
+
const state = await this.read(projectId)
|
|
322
|
+
if (!state.activeFeature) {
|
|
323
|
+
throw new Error('No active feature to ship')
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const activity: RecentActivity = {
|
|
327
|
+
type: 'feature_shipped',
|
|
328
|
+
description: state.activeFeature.name,
|
|
329
|
+
timestamp: new Date().toISOString(),
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return this.batchUpdate(projectId, [
|
|
333
|
+
{ type: 'SET_ACTIVE_FEATURE', feature: null },
|
|
334
|
+
{ type: 'ADD_ACTIVITY', activity },
|
|
335
|
+
])
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Clear cache for a project.
|
|
340
|
+
*/
|
|
341
|
+
clearCache(projectId?: string): void {
|
|
342
|
+
if (projectId) {
|
|
343
|
+
this.cache.delete(projectId)
|
|
344
|
+
this.lastRead.delete(projectId)
|
|
345
|
+
} else {
|
|
346
|
+
this.cache.clear()
|
|
347
|
+
this.lastRead.clear()
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Check if project has state file.
|
|
353
|
+
*/
|
|
354
|
+
async exists(projectId: string): Promise<boolean> {
|
|
355
|
+
const statePath = this.getStatePath(projectId)
|
|
356
|
+
return fileHelper.fileExists(statePath)
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Initialize state for a new project.
|
|
361
|
+
*/
|
|
362
|
+
async initialize(projectId: string): Promise<ProjectState> {
|
|
363
|
+
const initialState: ProjectState = {
|
|
364
|
+
...DEFAULT_STATE,
|
|
365
|
+
projectId,
|
|
366
|
+
lastSync: new Date().toISOString(),
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
await this.write(projectId, initialState)
|
|
370
|
+
return initialState
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Singleton instance
|
|
375
|
+
const stateManager = new StateManager()
|
|
376
|
+
export default stateManager
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State Types
|
|
3
|
+
*
|
|
4
|
+
* Unified project state that replaces scattered files.
|
|
5
|
+
* This is the single source of truth for project status.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Priority levels for tasks.
|
|
10
|
+
*/
|
|
11
|
+
export type Priority = 'low' | 'medium' | 'high' | 'critical'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Task status values.
|
|
15
|
+
*/
|
|
16
|
+
export type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'blocked' | 'paused'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Feature status values.
|
|
20
|
+
*/
|
|
21
|
+
export type FeatureStatus = 'planned' | 'in_progress' | 'completed' | 'shipped'
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A task in the queue.
|
|
25
|
+
*/
|
|
26
|
+
export interface QueuedTask {
|
|
27
|
+
/** Unique task ID */
|
|
28
|
+
id: string
|
|
29
|
+
/** Task description */
|
|
30
|
+
description: string
|
|
31
|
+
/** Priority level */
|
|
32
|
+
priority: Priority
|
|
33
|
+
/** Related feature (if any) */
|
|
34
|
+
featureId?: string
|
|
35
|
+
/** Estimated duration (e.g., "2h", "30m") */
|
|
36
|
+
estimatedDuration?: string
|
|
37
|
+
/** Tags for categorization */
|
|
38
|
+
tags?: string[]
|
|
39
|
+
/** When task was added */
|
|
40
|
+
createdAt: string
|
|
41
|
+
/** Blocking reason if blocked */
|
|
42
|
+
blockedReason?: string
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The currently active task.
|
|
47
|
+
*/
|
|
48
|
+
export interface CurrentTask {
|
|
49
|
+
/** Unique task ID */
|
|
50
|
+
id: string
|
|
51
|
+
/** Task description */
|
|
52
|
+
description: string
|
|
53
|
+
/** When task started */
|
|
54
|
+
startedAt: string
|
|
55
|
+
/** Assigned agent */
|
|
56
|
+
agent?: string
|
|
57
|
+
/** Agent confidence (0-1) */
|
|
58
|
+
agentConfidence?: number
|
|
59
|
+
/** Estimated duration */
|
|
60
|
+
estimatedDuration?: string
|
|
61
|
+
/** Related feature */
|
|
62
|
+
featureId?: string
|
|
63
|
+
/** Paused state info */
|
|
64
|
+
pausedAt?: string
|
|
65
|
+
/** Reason for pause */
|
|
66
|
+
pauseReason?: string
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Active feature being worked on.
|
|
71
|
+
*/
|
|
72
|
+
export interface ActiveFeature {
|
|
73
|
+
/** Feature ID */
|
|
74
|
+
id: string
|
|
75
|
+
/** Feature name */
|
|
76
|
+
name: string
|
|
77
|
+
/** Current status */
|
|
78
|
+
status: FeatureStatus
|
|
79
|
+
/** Tasks completed for this feature */
|
|
80
|
+
tasksCompleted: number
|
|
81
|
+
/** Tasks remaining */
|
|
82
|
+
tasksRemaining: number
|
|
83
|
+
/** Total estimated effort */
|
|
84
|
+
estimatedEffort?: string
|
|
85
|
+
/** Actual effort so far */
|
|
86
|
+
actualEffort?: string
|
|
87
|
+
/** When feature was started */
|
|
88
|
+
startedAt: string
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Performance statistics.
|
|
93
|
+
*/
|
|
94
|
+
export interface PerformanceStats {
|
|
95
|
+
/** Tasks completed today */
|
|
96
|
+
tasksToday: number
|
|
97
|
+
/** Tasks completed this week */
|
|
98
|
+
tasksThisWeek: number
|
|
99
|
+
/** Average task duration */
|
|
100
|
+
avgDuration: string
|
|
101
|
+
/** Tasks per day velocity */
|
|
102
|
+
velocity: string
|
|
103
|
+
/** Estimate accuracy percentage (0-100) */
|
|
104
|
+
estimateAccuracy: number
|
|
105
|
+
/** Streak of consecutive productive days */
|
|
106
|
+
streak: number
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Recent activity entry.
|
|
111
|
+
*/
|
|
112
|
+
export interface RecentActivity {
|
|
113
|
+
/** Activity type */
|
|
114
|
+
type: 'task_completed' | 'feature_shipped' | 'idea_captured' | 'session_started'
|
|
115
|
+
/** Description */
|
|
116
|
+
description: string
|
|
117
|
+
/** When it happened */
|
|
118
|
+
timestamp: string
|
|
119
|
+
/** Duration if applicable */
|
|
120
|
+
duration?: string
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Unified project state.
|
|
125
|
+
* This replaces reading from now.md, next.md, roadmap.md, etc.
|
|
126
|
+
*/
|
|
127
|
+
export interface ProjectState {
|
|
128
|
+
/** Project ID */
|
|
129
|
+
projectId: string
|
|
130
|
+
|
|
131
|
+
/** Currently active task (null if none) */
|
|
132
|
+
currentTask: CurrentTask | null
|
|
133
|
+
|
|
134
|
+
/** Task queue (priority ordered) */
|
|
135
|
+
queue: QueuedTask[]
|
|
136
|
+
|
|
137
|
+
/** Active feature being worked on */
|
|
138
|
+
activeFeature: ActiveFeature | null
|
|
139
|
+
|
|
140
|
+
/** Performance statistics */
|
|
141
|
+
stats: PerformanceStats
|
|
142
|
+
|
|
143
|
+
/** Recent activity (last 10 items) */
|
|
144
|
+
recentActivity: RecentActivity[]
|
|
145
|
+
|
|
146
|
+
/** When state was last synced */
|
|
147
|
+
lastSync: string
|
|
148
|
+
|
|
149
|
+
/** State version for migrations */
|
|
150
|
+
version: number
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Default empty state.
|
|
155
|
+
*/
|
|
156
|
+
export const DEFAULT_STATE: ProjectState = {
|
|
157
|
+
projectId: '',
|
|
158
|
+
currentTask: null,
|
|
159
|
+
queue: [],
|
|
160
|
+
activeFeature: null,
|
|
161
|
+
stats: {
|
|
162
|
+
tasksToday: 0,
|
|
163
|
+
tasksThisWeek: 0,
|
|
164
|
+
avgDuration: '0h',
|
|
165
|
+
velocity: '0',
|
|
166
|
+
estimateAccuracy: 0,
|
|
167
|
+
streak: 0,
|
|
168
|
+
},
|
|
169
|
+
recentActivity: [],
|
|
170
|
+
lastSync: new Date().toISOString(),
|
|
171
|
+
version: 1,
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* State update operations.
|
|
176
|
+
*/
|
|
177
|
+
export type StateUpdate =
|
|
178
|
+
| { type: 'SET_CURRENT_TASK'; task: CurrentTask | null }
|
|
179
|
+
| { type: 'ADD_TO_QUEUE'; task: QueuedTask }
|
|
180
|
+
| { type: 'REMOVE_FROM_QUEUE'; taskId: string }
|
|
181
|
+
| { type: 'UPDATE_QUEUE_TASK'; taskId: string; updates: Partial<QueuedTask> }
|
|
182
|
+
| { type: 'SET_ACTIVE_FEATURE'; feature: ActiveFeature | null }
|
|
183
|
+
| { type: 'UPDATE_STATS'; stats: Partial<PerformanceStats> }
|
|
184
|
+
| { type: 'ADD_ACTIVITY'; activity: RecentActivity }
|
|
185
|
+
| { type: 'SYNC' }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "CommonJS",
|
|
5
|
+
"moduleResolution": "node",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"esModuleInterop": true,
|
|
11
|
+
"allowSyntheticDefaultImports": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"declaration": false,
|
|
14
|
+
"outDir": "./dist",
|
|
15
|
+
"rootDir": ".",
|
|
16
|
+
"types": ["bun-types"],
|
|
17
|
+
"allowJs": true,
|
|
18
|
+
"checkJs": false
|
|
19
|
+
},
|
|
20
|
+
"include": ["./**/*.ts", "./**/*.js"],
|
|
21
|
+
"exclude": ["node_modules", "dist"]
|
|
22
|
+
}
|