@taskforcehq/taskforce 0.3.168
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/README.md +241 -0
- package/dist/Taskforce.d.ts +3 -0
- package/dist/Taskforce.js +3 -0
- package/dist/Taskforce.module.css +7587 -0
- package/dist/TaskforceCore.CategoryFallback.test.d.ts +1 -0
- package/dist/TaskforceCore.CategoryFallback.test.js +98 -0
- package/dist/TaskforceCore.d.ts +12 -0
- package/dist/TaskforceCore.js +729 -0
- package/dist/TaskforceCore.test.d.ts +1 -0
- package/dist/TaskforceCore.test.js +2132 -0
- package/dist/TaskforceScreenshot.d.ts +11 -0
- package/dist/TaskforceScreenshot.js +113 -0
- package/dist/TaskforceWidget.d.ts +6 -0
- package/dist/TaskforceWidget.js +101 -0
- package/dist/TaskforceWidget.test.d.ts +1 -0
- package/dist/TaskforceWidget.test.js +92 -0
- package/dist/UnsavedChangesRelaxed.test.d.ts +1 -0
- package/dist/UnsavedChangesRelaxed.test.js +16 -0
- package/dist/__tests__/localizationCatalogs.test.d.ts +1 -0
- package/dist/__tests__/localizationCatalogs.test.js +37 -0
- package/dist/__tests__/planParser.test.d.ts +1 -0
- package/dist/__tests__/planParser.test.js +183 -0
- package/dist/__tests__/releaseVersion.test.d.ts +1 -0
- package/dist/__tests__/releaseVersion.test.js +32 -0
- package/dist/__tests__/structuredCommentValidation.test.d.ts +1 -0
- package/dist/__tests__/structuredCommentValidation.test.js +31 -0
- package/dist/__tests__/structuredDocValidation.test.d.ts +1 -0
- package/dist/__tests__/structuredDocValidation.test.js +30 -0
- package/dist/__tests__/templateEngine.test.d.ts +1 -0
- package/dist/__tests__/templateEngine.test.js +150 -0
- package/dist/__tests__/templates.test.d.ts +1 -0
- package/dist/__tests__/templates.test.js +45 -0
- package/dist/__tests__/workflowDocumentFixtures.test.d.ts +1 -0
- package/dist/__tests__/workflowDocumentFixtures.test.js +78 -0
- package/dist/__tests__/workflowExportMatrix.test.d.ts +1 -0
- package/dist/__tests__/workflowExportMatrix.test.js +113 -0
- package/dist/__tests__/workflowExportSnapshots.test.d.ts +1 -0
- package/dist/__tests__/workflowExportSnapshots.test.js +28 -0
- package/dist/__tests__/workflowGeneration.test.d.ts +1 -0
- package/dist/__tests__/workflowGeneration.test.js +12 -0
- package/dist/__tests__/workflowSimulation.test.d.ts +1 -0
- package/dist/__tests__/workflowSimulation.test.js +113 -0
- package/dist/__tests__/workflowV2Policy.test.d.ts +1 -0
- package/dist/__tests__/workflowV2Policy.test.js +80 -0
- package/dist/api.d.ts +30 -0
- package/dist/api.js +85 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +217 -0
- package/dist/compat/priorityCompat.d.ts +2 -0
- package/dist/compat/priorityCompat.js +24 -0
- package/dist/components/features/DocumentGenerateModal.d.ts +9 -0
- package/dist/components/features/DocumentGenerateModal.js +114 -0
- package/dist/components/features/DocumentIndex.d.ts +19 -0
- package/dist/components/features/DocumentIndex.js +51 -0
- package/dist/components/features/DocumentViewer.d.ts +9 -0
- package/dist/components/features/DocumentViewer.js +253 -0
- package/dist/components/features/DocumentWorkspace.d.ts +21 -0
- package/dist/components/features/DocumentWorkspace.js +88 -0
- package/dist/components/features/TaskSettings.d.ts +209 -0
- package/dist/components/features/TaskSettings.js +500 -0
- package/dist/components/features/TaskSettings.test.d.ts +1 -0
- package/dist/components/features/TaskSettings.test.js +308 -0
- package/dist/components/features/settings/CategoryManager.d.ts +19 -0
- package/dist/components/features/settings/CategoryManager.js +113 -0
- package/dist/components/features/settings/TaxonomyEditor.d.ts +8 -0
- package/dist/components/features/settings/TaxonomyEditor.js +98 -0
- package/dist/components/features/settings/TaxonomyManager 2.d.ts +52 -0
- package/dist/components/features/settings/TaxonomyManager 2.js +75 -0
- package/dist/components/features/settings/TaxonomyManager.d.ts +54 -0
- package/dist/components/features/settings/TaxonomyManager.js +77 -0
- package/dist/components/features/settings/TypeManager.d.ts +10 -0
- package/dist/components/features/settings/TypeManager.js +50 -0
- package/dist/components/features/settings/WorkflowEditorPrototype.d.ts +15 -0
- package/dist/components/features/settings/WorkflowEditorPrototype.js +245 -0
- package/dist/components/task/TaskActionHeader.d.ts +20 -0
- package/dist/components/task/TaskActionHeader.js +13 -0
- package/dist/components/task/TaskCard.d.ts +47 -0
- package/dist/components/task/TaskCard.js +326 -0
- package/dist/components/task/TaskCard.test.d.ts +1 -0
- package/dist/components/task/TaskCard.test.js +95 -0
- package/dist/components/task/TaskContextUpload.d.ts +12 -0
- package/dist/components/task/TaskContextUpload.js +393 -0
- package/dist/components/task/TaskContextUpload.test.d.ts +1 -0
- package/dist/components/task/TaskContextUpload.test.js +189 -0
- package/dist/components/task/TaskForm.d.ts +105 -0
- package/dist/components/task/TaskForm.js +241 -0
- package/dist/components/task/TaskForm.test.d.ts +1 -0
- package/dist/components/task/TaskForm.test.js +288 -0
- package/dist/components/task/TaskKanban 2.d.ts +76 -0
- package/dist/components/task/TaskKanban 2.js +1004 -0
- package/dist/components/task/TaskKanban.d.ts +76 -0
- package/dist/components/task/TaskKanban.empty-column-drop.test.d.ts +1 -0
- package/dist/components/task/TaskKanban.empty-column-drop.test.js +66 -0
- package/dist/components/task/TaskKanban.js +1026 -0
- package/dist/components/task/TaskKanban.test.d.ts +1 -0
- package/dist/components/task/TaskKanban.test.js +46 -0
- package/dist/components/task/TaskList.d.ts +74 -0
- package/dist/components/task/TaskList.js +38 -0
- package/dist/components/task/TaskList.test.d.ts +1 -0
- package/dist/components/task/TaskList.test.js +270 -0
- package/dist/components/task/TaskScreenshotSection.d.ts +15 -0
- package/dist/components/task/TaskScreenshotSection.js +22 -0
- package/dist/components/ui/LevelSelector.d.ts +13 -0
- package/dist/components/ui/LevelSelector.js +25 -0
- package/dist/components/ui/LevelSelector.test.d.ts +1 -0
- package/dist/components/ui/LevelSelector.test.js +55 -0
- package/dist/components/ui/Markdown.d.ts +6 -0
- package/dist/components/ui/Markdown.js +94 -0
- package/dist/components/ui/Markdown.test.d.ts +1 -0
- package/dist/components/ui/Markdown.test.js +38 -0
- package/dist/components/ui/Modal.d.ts +16 -0
- package/dist/components/ui/Modal.js +49 -0
- package/dist/components/ui/MultiSelectFilter.d.ts +10 -0
- package/dist/components/ui/MultiSelectFilter.js +71 -0
- package/dist/components/ui/MultiSelectFilter.test.d.ts +1 -0
- package/dist/components/ui/MultiSelectFilter.test.js +74 -0
- package/dist/components/ui/TaxonomyDropdown.d.ts +17 -0
- package/dist/components/ui/TaxonomyDropdown.js +145 -0
- package/dist/components/ui/TaxonomyDropdown.test.d.ts +1 -0
- package/dist/components/ui/TaxonomyDropdown.test.js +130 -0
- package/dist/components/views/StandaloneLayout 2.d.ts +8 -0
- package/dist/components/views/StandaloneLayout 2.js +1660 -0
- package/dist/components/views/StandaloneLayout.d.ts +8 -0
- package/dist/components/views/StandaloneLayout.js +2117 -0
- package/dist/components/views/WidgetView.d.ts +8 -0
- package/dist/components/views/WidgetView.js +221 -0
- package/dist/config/envSchema.d.ts +28 -0
- package/dist/config/envSchema.js +374 -0
- package/dist/config/envSchema.test.d.ts +1 -0
- package/dist/config/envSchema.test.js +97 -0
- package/dist/config/surfaceBase.d.ts +2 -0
- package/dist/config/surfaceBase.js +8 -0
- package/dist/core/BulkUpdateFieldsPreview.test.d.ts +1 -0
- package/dist/core/BulkUpdateFieldsPreview.test.js +62 -0
- package/dist/core/CompletedAt.test.d.ts +1 -0
- package/dist/core/CompletedAt.test.js +44 -0
- package/dist/core/CreatedBy.test.d.ts +1 -0
- package/dist/core/CreatedBy.test.js +60 -0
- package/dist/core/EntitlementsPolicy.test.d.ts +1 -0
- package/dist/core/EntitlementsPolicy.test.js +145 -0
- package/dist/core/InitiativeTemplates.test.d.ts +1 -0
- package/dist/core/InitiativeTemplates.test.js +50 -0
- package/dist/core/ParentLifecycle.test.d.ts +1 -0
- package/dist/core/ParentLifecycle.test.js +98 -0
- package/dist/core/ScheduleFields.test.d.ts +1 -0
- package/dist/core/ScheduleFields.test.js +197 -0
- package/dist/core/SetupState.test.d.ts +1 -0
- package/dist/core/SetupState.test.js +113 -0
- package/dist/core/SystemAdmin.test.d.ts +1 -0
- package/dist/core/SystemAdmin.test.js +295 -0
- package/dist/core/TaskTaxonomyValidation.test.d.ts +1 -0
- package/dist/core/TaskTaxonomyValidation.test.js +64 -0
- package/dist/core/Taskforce.d.ts +1063 -0
- package/dist/core/Taskforce.ids.test.d.ts +1 -0
- package/dist/core/Taskforce.ids.test.js +168 -0
- package/dist/core/Taskforce.js +5981 -0
- package/dist/core/Taskforce.realtimeMutation.test.d.ts +1 -0
- package/dist/core/Taskforce.realtimeMutation.test.js +76 -0
- package/dist/core/WorkspaceDelete.test.d.ts +1 -0
- package/dist/core/WorkspaceDelete.test.js +140 -0
- package/dist/core/WorkspacePermissions.test.d.ts +1 -0
- package/dist/core/WorkspacePermissions.test.js +151 -0
- package/dist/core/WorkspacePlanMode.test.d.ts +1 -0
- package/dist/core/WorkspacePlanMode.test.js +104 -0
- package/dist/hooks/authGuardPolicy.d.ts +26 -0
- package/dist/hooks/authGuardPolicy.js +32 -0
- package/dist/hooks/authGuardPolicy.test.d.ts +1 -0
- package/dist/hooks/authGuardPolicy.test.js +76 -0
- package/dist/hooks/useDraggable.d.ts +12 -0
- package/dist/hooks/useDraggable.js +65 -0
- package/dist/hooks/useRealtimeSync.d.ts +24 -0
- package/dist/hooks/useRealtimeSync.js +275 -0
- package/dist/hooks/useRealtimeSync.test.d.ts +1 -0
- package/dist/hooks/useRealtimeSync.test.js +284 -0
- package/dist/hooks/useSyncOrchestrator.d.ts +164 -0
- package/dist/hooks/useSyncOrchestrator.js +1427 -0
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.d.ts +1 -0
- package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +367 -0
- package/dist/hooks/useTaskforce.d.ts +727 -0
- package/dist/hooks/useTaskforce.js +4396 -0
- package/dist/hooks/useTaskforce.priority-filters.test.d.ts +1 -0
- package/dist/hooks/useTaskforce.priority-filters.test.js +33 -0
- package/dist/hooks/useWorkspaceSyncController.d.ts +80 -0
- package/dist/hooks/useWorkspaceSyncController.js +598 -0
- package/dist/hooks/useWorkspaceSyncController.test.d.ts +1 -0
- package/dist/hooks/useWorkspaceSyncController.test.js +236 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +11 -0
- package/dist/localization/index.d.ts +8 -0
- package/dist/localization/index.js +81 -0
- package/dist/localization/locales/en-US.d.ts +151 -0
- package/dist/localization/locales/en-US.js +150 -0
- package/dist/localization/locales/es-419.d.ts +2 -0
- package/dist/localization/locales/es-419.js +150 -0
- package/dist/localization/locales/pt-BR.d.ts +2 -0
- package/dist/localization/locales/pt-BR.js +150 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +33 -0
- package/dist/mcp/optionResolution.d.ts +14 -0
- package/dist/mcp/optionResolution.js +126 -0
- package/dist/mcp/optionResolution.test.d.ts +1 -0
- package/dist/mcp/optionResolution.test.js +39 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +1793 -0
- package/dist/mcp/structuredCommentValidation.d.ts +6 -0
- package/dist/mcp/structuredCommentValidation.js +56 -0
- package/dist/mcp/structuredDocValidation.d.ts +6 -0
- package/dist/mcp/structuredDocValidation.js +75 -0
- package/dist/migrations/billingSchemaParity.test.d.ts +1 -0
- package/dist/migrations/billingSchemaParity.test.js +46 -0
- package/dist/migrations/clientMigrations.d.ts +9 -0
- package/dist/migrations/clientMigrations.js +74 -0
- package/dist/migrations/flags.d.ts +6 -0
- package/dist/migrations/flags.js +8 -0
- package/dist/migrations/taskMigrations.d.ts +71 -0
- package/dist/migrations/taskMigrations.js +236 -0
- package/dist/migrations/taskMigrations.test.d.ts +1 -0
- package/dist/migrations/taskMigrations.test.js +34 -0
- package/dist/migrations/taskSchemaMigrations.d.ts +11 -0
- package/dist/migrations/taskSchemaMigrations.js +453 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.js +10 -0
- package/dist/plugins/vite.d.ts +19 -0
- package/dist/plugins/vite.js +271 -0
- package/dist/public/android-chrome-192x192.png +0 -0
- package/dist/public/android-chrome-512x512.png +0 -0
- package/dist/public/apple-touch-icon.png +0 -0
- package/dist/public/favicon-16x16.png +0 -0
- package/dist/public/favicon-32x32.png +0 -0
- package/dist/public/favicon.ico +0 -0
- package/dist/public/favicon.png +0 -0
- package/dist/public/site.webmanifest +1 -0
- package/dist/public/taskforce.png +0 -0
- package/dist/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
- package/dist/resources/templates/environments/aider.yaml +14 -0
- package/dist/resources/templates/environments/antigravity.yaml +10 -0
- package/dist/resources/templates/environments/claude.yaml +10 -0
- package/dist/resources/templates/environments/cline.yaml +10 -0
- package/dist/resources/templates/environments/codex.yaml +13 -0
- package/dist/resources/templates/environments/copilot.yaml +10 -0
- package/dist/resources/templates/environments/cursor.yaml +9 -0
- package/dist/resources/templates/environments/gemini.yaml +9 -0
- package/dist/resources/templates/environments/windsurf.yaml +10 -0
- package/dist/resources/templates/workflow-sources/README.md +9 -0
- package/dist/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
- package/dist/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
- package/dist/resources/templates/workflows/collaborate.yaml +104 -0
- package/dist/resources/templates/workflows/do.yaml +82 -0
- package/dist/resources/templates/workflows/evaluate.yaml +111 -0
- package/dist/resources/templates/workflows/execute.yaml +142 -0
- package/dist/resources/templates/workflows/plan.yaml +112 -0
- package/dist/resources/templates/workflows/review.yaml +109 -0
- package/dist/runtime/capabilities.d.ts +8 -0
- package/dist/runtime/capabilities.js +16 -0
- package/dist/security/virusScan.d.ts +16 -0
- package/dist/security/virusScan.js +83 -0
- package/dist/server/auth.d.ts +51 -0
- package/dist/server/auth.js +266 -0
- package/dist/server/auth.test.d.ts +1 -0
- package/dist/server/auth.test.js +111 -0
- package/dist/server/buildInfo.d.ts +7 -0
- package/dist/server/buildInfo.js +100 -0
- package/dist/server/buildInfo.test.d.ts +1 -0
- package/dist/server/buildInfo.test.js +29 -0
- package/dist/server/cors.d.ts +7 -0
- package/dist/server/cors.js +76 -0
- package/dist/server/cors.test.d.ts +1 -0
- package/dist/server/cors.test.js +71 -0
- package/dist/server/email.d.ts +28 -0
- package/dist/server/email.js +138 -0
- package/dist/server/email.test.d.ts +1 -0
- package/dist/server/email.test.js +113 -0
- package/dist/server/index.cookieProxy.test.d.ts +1 -0
- package/dist/server/index.cookieProxy.test.js +19 -0
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.js +757 -0
- package/dist/server/index.rateLimit.test.d.ts +1 -0
- package/dist/server/index.rateLimit.test.js +13 -0
- package/dist/server/index.test.d.ts +1 -0
- package/dist/server/index.test.js +19 -0
- package/dist/server/rateLimit.d.ts +29 -0
- package/dist/server/rateLimit.js +99 -0
- package/dist/server/rateLimit.test.d.ts +1 -0
- package/dist/server/rateLimit.test.js +107 -0
- package/dist/server/realtimeSync.auth.test.d.ts +1 -0
- package/dist/server/realtimeSync.auth.test.js +62 -0
- package/dist/server/realtimeSync.replay.test.d.ts +1 -0
- package/dist/server/realtimeSync.replay.test.js +192 -0
- package/dist/server/realtimeSync.workspaceIsolation.test.d.ts +1 -0
- package/dist/server/realtimeSync.workspaceIsolation.test.js +101 -0
- package/dist/server/realtimeSyncWs.d.ts +30 -0
- package/dist/server/realtimeSyncWs.js +257 -0
- package/dist/server/routes.billing.d.ts +15 -0
- package/dist/server/routes.billing.js +991 -0
- package/dist/server/routes.billing.test.d.ts +1 -0
- package/dist/server/routes.billing.test.js +387 -0
- package/dist/server/routes.d.ts +72 -0
- package/dist/server/routes.js +4820 -0
- package/dist/server/routes.sync.d.ts +17 -0
- package/dist/server/routes.sync.integration.test.d.ts +1 -0
- package/dist/server/routes.sync.integration.test.js +470 -0
- package/dist/server/routes.sync.js +1141 -0
- package/dist/server/routes.test.d.ts +1 -0
- package/dist/server/routes.test.js +4945 -0
- package/dist/server/runtimeMode.d.ts +4 -0
- package/dist/server/runtimeMode.js +25 -0
- package/dist/server/runtimeMode.test.d.ts +1 -0
- package/dist/server/runtimeMode.test.js +26 -0
- package/dist/server/securityHeaders.d.ts +3 -0
- package/dist/server/securityHeaders.js +25 -0
- package/dist/server/securityHeaders.test.d.ts +1 -0
- package/dist/server/securityHeaders.test.js +32 -0
- package/dist/server/smtpTransport.d.ts +21 -0
- package/dist/server/smtpTransport.js +11 -0
- package/dist/server/start.d.ts +1 -0
- package/dist/server/start.js +17 -0
- package/dist/services/formatTransformers.d.ts +29 -0
- package/dist/services/formatTransformers.js +56 -0
- package/dist/services/templateEngine.d.ts +46 -0
- package/dist/services/templateEngine.js +148 -0
- package/dist/shared/runtimeContract.d.ts +12 -0
- package/dist/shared/runtimeContract.js +23 -0
- package/dist/shared/runtimeContract.test.d.ts +1 -0
- package/dist/shared/runtimeContract.test.js +23 -0
- package/dist/soak/preflight.cli.d.ts +1 -0
- package/dist/soak/preflight.cli.js +28 -0
- package/dist/soak/preflight.d.ts +26 -0
- package/dist/soak/preflight.js +113 -0
- package/dist/soak/preflight.test.d.ts +1 -0
- package/dist/soak/preflight.test.js +39 -0
- package/dist/soak/syncSoakHarness.d.ts +6 -0
- package/dist/soak/syncSoakHarness.js +10 -0
- package/dist/storage/createDatabaseAdapter.d.ts +2 -0
- package/dist/storage/createDatabaseAdapter.js +9 -0
- package/dist/storage/databaseAdapter.d.ts +22 -0
- package/dist/storage/databaseAdapter.js +1 -0
- package/dist/storage/documentIntegrity.d.ts +28 -0
- package/dist/storage/documentIntegrity.js +103 -0
- package/dist/storage/documentPurge.d.ts +14 -0
- package/dist/storage/documentPurge.js +46 -0
- package/dist/storage/documentRegistry.d.ts +39 -0
- package/dist/storage/documentRegistry.js +115 -0
- package/dist/storage/integritySchedule.d.ts +17 -0
- package/dist/storage/integritySchedule.js +62 -0
- package/dist/storage/objectStorage.d.ts +20 -0
- package/dist/storage/objectStorage.js +15 -0
- package/dist/storage/objectStorageClient.d.ts +18 -0
- package/dist/storage/objectStorageClient.js +301 -0
- package/dist/storage/objectStorageConfig.d.ts +2 -0
- package/dist/storage/objectStorageConfig.js +45 -0
- package/dist/storage/postgresAdapter.d.ts +20 -0
- package/dist/storage/postgresAdapter.js +204 -0
- package/dist/storage/postgresWorker.d.ts +1 -0
- package/dist/storage/postgresWorker.js +110 -0
- package/dist/storage/providerConfig.d.ts +6 -0
- package/dist/storage/providerConfig.js +11 -0
- package/dist/storage/sqliteAdapter.d.ts +14 -0
- package/dist/storage/sqliteAdapter.js +28 -0
- package/dist/storage/taskAssetStore.d.ts +56 -0
- package/dist/storage/taskAssetStore.js +297 -0
- package/dist/sync/cloudSyncApi.d.ts +47 -0
- package/dist/sync/cloudSyncApi.js +138 -0
- package/dist/sync/cloudSyncApi.test.d.ts +1 -0
- package/dist/sync/cloudSyncApi.test.js +54 -0
- package/dist/sync/encryptionService.d.ts +11 -0
- package/dist/sync/encryptionService.js +61 -0
- package/dist/sync/encryptionService.test.d.ts +1 -0
- package/dist/sync/encryptionService.test.js +52 -0
- package/dist/sync/realtimeFeature.d.ts +6 -0
- package/dist/sync/realtimeFeature.js +20 -0
- package/dist/sync/realtimeFeature.test.d.ts +1 -0
- package/dist/sync/realtimeFeature.test.js +30 -0
- package/dist/sync/realtimeReconcile.d.ts +30 -0
- package/dist/sync/realtimeReconcile.js +90 -0
- package/dist/sync/realtimeReconcile.test.d.ts +1 -0
- package/dist/sync/realtimeReconcile.test.js +43 -0
- package/dist/sync/syncService.d.ts +96 -0
- package/dist/sync/syncService.js +423 -0
- package/dist/sync/syncService.test.d.ts +1 -0
- package/dist/sync/syncService.test.js +484 -0
- package/dist/sync/workspaceSyncModel.d.ts +61 -0
- package/dist/sync/workspaceSyncModel.js +136 -0
- package/dist/sync/workspaceSyncModel.test.d.ts +1 -0
- package/dist/sync/workspaceSyncModel.test.js +73 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +15 -0
- package/dist/types.d.ts +157 -0
- package/dist/types.js +41 -0
- package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
- package/dist/ui/assets/index-0W5vyCpn.css +1 -0
- package/dist/ui/assets/index-MCZuNNfn.js +23 -0
- package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
- package/dist/ui/assets/taskforce-BxLPokNB.png +0 -0
- package/dist/ui/assets/vendor-dnd-BI1K77C1.js +5 -0
- package/dist/ui/assets/vendor-icons-ZFG3SGwo.js +1 -0
- package/dist/ui/assets/vendor-markdown-CKYkQHfj.js +29 -0
- package/dist/ui/assets/vendor-react-DdIDsh7f.js +9 -0
- package/dist/ui/assets/vendor-router-BtiNU7Dl.js +3 -0
- package/dist/ui/branding/logos/logo_black_01.png +0 -0
- package/dist/ui/branding/logos/logo_black_02.png +0 -0
- package/dist/ui/branding/logos/logo_white_01.png +0 -0
- package/dist/ui/branding/logos/logo_white_02.png +0 -0
- package/dist/ui/favicon/android-chrome-192x192.png +0 -0
- package/dist/ui/favicon/android-chrome-512x512.png +0 -0
- package/dist/ui/favicon/apple-touch-icon.png +0 -0
- package/dist/ui/favicon/favicon-16x16.png +0 -0
- package/dist/ui/favicon/favicon-32x32.png +0 -0
- package/dist/ui/favicon/favicon.ico +0 -0
- package/dist/ui/favicon/favicon.png +0 -0
- package/dist/ui/favicon/site.webmanifest +1 -0
- package/dist/ui/fonts/RussoOne-Regular.ttf +0 -0
- package/dist/ui/images/taskforce.png +0 -0
- package/dist/ui/index.html +19 -0
- package/dist/utils/checklistMarkdown.d.ts +9 -0
- package/dist/utils/checklistMarkdown.js +46 -0
- package/dist/utils/constants.d.ts +21 -0
- package/dist/utils/constants.icons.test.d.ts +1 -0
- package/dist/utils/constants.icons.test.js +40 -0
- package/dist/utils/constants.js +100 -0
- package/dist/utils/contextFiles.d.ts +8 -0
- package/dist/utils/contextFiles.js +54 -0
- package/dist/utils/formatting.d.ts +5 -0
- package/dist/utils/formatting.js +30 -0
- package/dist/utils/planParser.d.ts +22 -0
- package/dist/utils/planParser.js +151 -0
- package/dist/utils/taskDragZones.d.ts +8 -0
- package/dist/utils/taskDragZones.js +14 -0
- package/dist/utils/taskDragZones.test.d.ts +1 -0
- package/dist/utils/taskDragZones.test.js +14 -0
- package/dist/utils/taskHierarchy.d.ts +4 -0
- package/dist/utils/taskHierarchy.js +69 -0
- package/dist/utils/taskHierarchy.test.d.ts +1 -0
- package/dist/utils/taskHierarchy.test.js +38 -0
- package/dist/utils/taskParenting.d.ts +3 -0
- package/dist/utils/taskParenting.js +24 -0
- package/dist/utils/taskParenting.test.d.ts +1 -0
- package/dist/utils/taskParenting.test.js +21 -0
- package/dist/utils/taskRelations.d.ts +6 -0
- package/dist/utils/taskRelations.js +24 -0
- package/dist/utils/taskRelations.test.d.ts +1 -0
- package/dist/utils/taskRelations.test.js +34 -0
- package/dist/utils/taskUtils.d.ts +2 -0
- package/dist/utils/taskUtils.js +20 -0
- package/dist/utils/taskforceApiClient.d.ts +7 -0
- package/dist/utils/taskforceApiClient.js +42 -0
- package/dist/utils/workspaceIdentity.d.ts +8 -0
- package/dist/utils/workspaceIdentity.js +47 -0
- package/dist/utils/workspaceIdentity.test.d.ts +1 -0
- package/dist/utils/workspaceIdentity.test.js +32 -0
- package/dist/utils/workspaceLifecycle.d.ts +26 -0
- package/dist/utils/workspaceLifecycle.js +69 -0
- package/dist/utils/workspaceLifecycle.test.d.ts +1 -0
- package/dist/utils/workspaceLifecycle.test.js +64 -0
- package/package.json +133 -0
- package/scripts/check-compat-boundaries.js +48 -0
- package/scripts/check-env.ts +24 -0
- package/scripts/check-localization-strings.mjs +49 -0
- package/scripts/check-runtime-boundaries.mjs +44 -0
- package/scripts/debug-global.mjs +34 -0
- package/scripts/debug-server.mjs +36 -0
- package/scripts/export-sqlite-to-postgres.mjs +125 -0
- package/scripts/generate-env-example.ts +8 -0
- package/scripts/generate-workflow-templates.mjs +134 -0
- package/scripts/mcp-stdio-adapter.mjs +160 -0
- package/scripts/postinstall.js +60 -0
- package/scripts/release-version-lib.mjs +88 -0
- package/scripts/release-version.mjs +72 -0
- package/scripts/run-dev-proxy.sh +49 -0
- package/scripts/run-e2e-realtime.sh +16 -0
- package/scripts/run-smoke.sh +23 -0
- package/scripts/run-soak.sh +29 -0
- package/scripts/test-global.js +143 -0
- package/scripts/update-homebrew-formula.sh +38 -0
- package/src/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
- package/src/resources/templates/environments/aider.yaml +14 -0
- package/src/resources/templates/environments/antigravity.yaml +10 -0
- package/src/resources/templates/environments/claude.yaml +10 -0
- package/src/resources/templates/environments/cline.yaml +10 -0
- package/src/resources/templates/environments/codex.yaml +13 -0
- package/src/resources/templates/environments/copilot.yaml +10 -0
- package/src/resources/templates/environments/cursor.yaml +9 -0
- package/src/resources/templates/environments/gemini.yaml +9 -0
- package/src/resources/templates/environments/windsurf.yaml +10 -0
- package/src/resources/templates/workflow-sources/README.md +9 -0
- package/src/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
- package/src/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
- package/src/resources/templates/workflows/collaborate.yaml +104 -0
- package/src/resources/templates/workflows/do.yaml +82 -0
- package/src/resources/templates/workflows/evaluate.yaml +111 -0
- package/src/resources/templates/workflows/execute.yaml +142 -0
- package/src/resources/templates/workflows/plan.yaml +112 -0
- package/src/resources/templates/workflows/review.yaml +109 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const RULES = [
|
|
2
|
+
{
|
|
3
|
+
heading: '## Plan Summary',
|
|
4
|
+
requiredHeadings: [
|
|
5
|
+
'## Plan Summary',
|
|
6
|
+
'### Goal',
|
|
7
|
+
'### Scope',
|
|
8
|
+
'### Next Action'
|
|
9
|
+
],
|
|
10
|
+
label: 'plan summary'
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
heading: '## Collaboration Summary',
|
|
14
|
+
requiredHeadings: [
|
|
15
|
+
'## Collaboration Summary',
|
|
16
|
+
'### Architecture Direction',
|
|
17
|
+
'### Key Constraints',
|
|
18
|
+
'### Next Step'
|
|
19
|
+
],
|
|
20
|
+
label: 'collaboration summary'
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
heading: '## Evaluation Summary',
|
|
24
|
+
requiredHeadings: [
|
|
25
|
+
'## Evaluation Summary',
|
|
26
|
+
'### Recommendation (Proceed | Pivot | Kill)',
|
|
27
|
+
'### Value Score (1-5)',
|
|
28
|
+
'### Risk Score (1-5)',
|
|
29
|
+
'### Next Step'
|
|
30
|
+
],
|
|
31
|
+
label: 'evaluation summary'
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
heading: '## Review Summary',
|
|
35
|
+
requiredHeadings: [
|
|
36
|
+
'## Review Summary',
|
|
37
|
+
'### Verdict (PASS | WARN | FAIL)',
|
|
38
|
+
'### Findings',
|
|
39
|
+
'### Next Status'
|
|
40
|
+
],
|
|
41
|
+
label: 'review summary'
|
|
42
|
+
}
|
|
43
|
+
];
|
|
44
|
+
export function validateStructuredCommentForAdd(text) {
|
|
45
|
+
const trimmed = text.trim();
|
|
46
|
+
const activeRule = RULES.find((rule) => trimmed.startsWith(rule.heading));
|
|
47
|
+
if (!activeRule)
|
|
48
|
+
return { ok: true };
|
|
49
|
+
const missing = activeRule.requiredHeadings.filter((heading) => !trimmed.includes(heading));
|
|
50
|
+
if (missing.length === 0)
|
|
51
|
+
return { ok: true };
|
|
52
|
+
return {
|
|
53
|
+
ok: false,
|
|
54
|
+
message: `Structured ${activeRule.label} comment is missing required sections: ${missing.join(', ')}`
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
const RULES = [
|
|
3
|
+
{
|
|
4
|
+
dirSegment: '/evaluations/',
|
|
5
|
+
filenameSuffixes: ['evaluation.md', '--evaluation.md'],
|
|
6
|
+
headings: [
|
|
7
|
+
'## Evaluation Summary',
|
|
8
|
+
'### Recommendation (Proceed | Pivot | Kill)',
|
|
9
|
+
'### Value Score (1-5)',
|
|
10
|
+
'### Risk Score (1-5)',
|
|
11
|
+
'### Alternatives Considered',
|
|
12
|
+
'### Key Tradeoffs',
|
|
13
|
+
'### Next Step'
|
|
14
|
+
],
|
|
15
|
+
label: 'evaluation'
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
dirSegment: '/reviews/',
|
|
19
|
+
filenameSuffixes: ['review.md', '--review.md'],
|
|
20
|
+
headings: [
|
|
21
|
+
'## Review Verdict',
|
|
22
|
+
'### Verdict (PASS | WARN | FAIL)',
|
|
23
|
+
'### Findings',
|
|
24
|
+
'### Regression Risks',
|
|
25
|
+
'### Required Fixes',
|
|
26
|
+
'### Recommended Next Status'
|
|
27
|
+
],
|
|
28
|
+
label: 'review'
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
dirSegment: '/collaborations/',
|
|
32
|
+
filenameSuffixes: ['collaboration-blueprint.md', '--collaboration-blueprint.md'],
|
|
33
|
+
headings: [
|
|
34
|
+
'## Collaboration Blueprint',
|
|
35
|
+
'### Problem Statement',
|
|
36
|
+
'### Constraints',
|
|
37
|
+
'### Proposed Architecture',
|
|
38
|
+
'### Must-Haves',
|
|
39
|
+
'### Non-Goals',
|
|
40
|
+
'### Risks & Open Questions',
|
|
41
|
+
'### Recommended Next Step'
|
|
42
|
+
],
|
|
43
|
+
label: 'collaboration blueprint'
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
dirSegment: '/implementation_plans/',
|
|
47
|
+
filenameSuffixes: ['implementation-plan.md', '--implementation-plan.md'],
|
|
48
|
+
headings: [
|
|
49
|
+
'## Implementation Plan',
|
|
50
|
+
'### Goal',
|
|
51
|
+
'### Change Plan',
|
|
52
|
+
'### Risk Analysis',
|
|
53
|
+
'### Verification Checklist'
|
|
54
|
+
],
|
|
55
|
+
label: 'implementation plan'
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
export function validateStructuredDocForAttach(relativePath, content) {
|
|
59
|
+
const normalizedPath = relativePath.split(path.sep).join('/');
|
|
60
|
+
const isLegacyDocPath = normalizedPath.startsWith('.taskforce/docs/');
|
|
61
|
+
const isTaskDataPath = normalizedPath.startsWith('.taskforce/task-data/');
|
|
62
|
+
if (!isLegacyDocPath && !isTaskDataPath)
|
|
63
|
+
return { ok: true };
|
|
64
|
+
const rule = RULES.find((r) => normalizedPath.includes(r.dirSegment) &&
|
|
65
|
+
r.filenameSuffixes.some((suffix) => normalizedPath.endsWith(suffix)));
|
|
66
|
+
if (!rule)
|
|
67
|
+
return { ok: true };
|
|
68
|
+
const missing = rule.headings.filter((heading) => !content.includes(heading));
|
|
69
|
+
if (missing.length === 0)
|
|
70
|
+
return { ok: true };
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
message: `Structured ${rule.label} doc is missing required sections: ${missing.join(', ')}`
|
|
74
|
+
};
|
|
75
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { TaskforceCore } from '../core/Taskforce.js';
|
|
6
|
+
function makeProjectRoot() {
|
|
7
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'taskforce-billing-schema-'));
|
|
8
|
+
}
|
|
9
|
+
describe('billing schema parity', () => {
|
|
10
|
+
it('initializes sqlite billing tables and indexes', () => {
|
|
11
|
+
const projectRoot = makeProjectRoot();
|
|
12
|
+
const core = new TaskforceCore({
|
|
13
|
+
projectRoot,
|
|
14
|
+
storagePath: path.join(projectRoot, '.taskforce')
|
|
15
|
+
});
|
|
16
|
+
try {
|
|
17
|
+
const db = core.db;
|
|
18
|
+
const tables = db.prepare(`
|
|
19
|
+
SELECT name
|
|
20
|
+
FROM sqlite_master
|
|
21
|
+
WHERE type = 'table'
|
|
22
|
+
`).all();
|
|
23
|
+
const names = new Set(tables.map((row) => row.name));
|
|
24
|
+
expect(names.has('user_billing')).toBe(true);
|
|
25
|
+
expect(names.has('stripe_webhook_events')).toBe(true);
|
|
26
|
+
expect(names.has('stripe_webhook_failures')).toBe(true);
|
|
27
|
+
expect(names.has('billing_config')).toBe(true);
|
|
28
|
+
expect(names.has('billing_price_mappings')).toBe(true);
|
|
29
|
+
}
|
|
30
|
+
finally {
|
|
31
|
+
core.close();
|
|
32
|
+
fs.rmSync(projectRoot, { recursive: true, force: true });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
it('postgres bootstrap contains billing tables and indexes', () => {
|
|
36
|
+
const sqlPath = path.resolve(process.cwd(), 'src/migrations/postgres/001_init.sql');
|
|
37
|
+
const sql = fs.readFileSync(sqlPath, 'utf8');
|
|
38
|
+
expect(sql).toContain('CREATE TABLE IF NOT EXISTS user_billing');
|
|
39
|
+
expect(sql).toContain('CREATE TABLE IF NOT EXISTS stripe_webhook_events');
|
|
40
|
+
expect(sql).toContain('CREATE TABLE IF NOT EXISTS stripe_webhook_failures');
|
|
41
|
+
expect(sql).toContain('CREATE TABLE IF NOT EXISTS billing_config');
|
|
42
|
+
expect(sql).toContain('CREATE TABLE IF NOT EXISTS billing_price_mappings');
|
|
43
|
+
expect(sql).toContain('CREATE INDEX IF NOT EXISTS idx_stripe_webhook_failures_purge_after');
|
|
44
|
+
expect(sql).toContain('CREATE INDEX IF NOT EXISTS idx_billing_price_mappings_plan');
|
|
45
|
+
});
|
|
46
|
+
});
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { CategoryConfig, TaskItem } from '../types';
|
|
2
|
+
export declare function normalizeTaskFromApi(task: any, options?: {
|
|
3
|
+
mapLegacyTodoStatus?: boolean;
|
|
4
|
+
}): TaskItem;
|
|
5
|
+
export declare function migrateCategoryFilterLabels(filterCategories: string[], activeCategories: CategoryConfig[]): string[];
|
|
6
|
+
export declare function normalizePriorityFilterValues(filterPriorities: Array<string | number>, priorities: Array<{
|
|
7
|
+
value: number;
|
|
8
|
+
}>): number[];
|
|
9
|
+
export declare function matchesPriorityFilter(taskPriority: string | number | null | undefined, filterPriorities: Array<string | number>): boolean;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { PRIORITY_LOGIC } from '../compat/priorityCompat';
|
|
2
|
+
import { MIGRATION_COMPAT_ENABLED } from './flags.js';
|
|
3
|
+
export function normalizeTaskFromApi(task, options) {
|
|
4
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
5
|
+
// COMPAT_TRACK: legacy-status-todo
|
|
6
|
+
const mapLegacyTodoStatus = MIGRATION_COMPAT_ENABLED && (options?.mapLegacyTodoStatus ?? false);
|
|
7
|
+
return {
|
|
8
|
+
...task,
|
|
9
|
+
assignee: (() => {
|
|
10
|
+
const normalized = String(task.assignee || '').trim().toLowerCase();
|
|
11
|
+
if (normalized === 'agent' || normalized === 'ai')
|
|
12
|
+
return 'agent';
|
|
13
|
+
if (normalized === 'user')
|
|
14
|
+
return 'user';
|
|
15
|
+
if (normalized === 'unassigned')
|
|
16
|
+
return 'unassigned';
|
|
17
|
+
return 'unassigned';
|
|
18
|
+
})(),
|
|
19
|
+
category: typeof task.category === 'string' ? task.category : task.category?.value || 'default',
|
|
20
|
+
type: (typeof task.type === 'string' ? task.type : task.type?.label || 'feature').toLowerCase(),
|
|
21
|
+
priority: typeof task.priority === 'number' ? task.priority : (PRIORITY_LOGIC[task.priority] ?? 2),
|
|
22
|
+
complexity: typeof task.complexity === 'number' ? task.complexity : 3,
|
|
23
|
+
parentTaskId: typeof task.parentTaskId === 'string' && task.parentTaskId.trim().length > 0 ? task.parentTaskId.trim() : null,
|
|
24
|
+
...(() => {
|
|
25
|
+
const normalizedStatus = task.status === 'blocked' || task.status === 'on hold'
|
|
26
|
+
? 'on-hold'
|
|
27
|
+
: task.status;
|
|
28
|
+
if (mapLegacyTodoStatus) {
|
|
29
|
+
return { status: normalizedStatus === 'todo' ? 'task' : normalizedStatus };
|
|
30
|
+
}
|
|
31
|
+
return { status: normalizedStatus };
|
|
32
|
+
})()
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function migrateCategoryFilterLabels(filterCategories, activeCategories) {
|
|
36
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
37
|
+
// COMPAT_TRACK: category-label-filter-migration
|
|
38
|
+
if (!MIGRATION_COMPAT_ENABLED)
|
|
39
|
+
return filterCategories;
|
|
40
|
+
if (!filterCategories.length || !activeCategories.length)
|
|
41
|
+
return filterCategories;
|
|
42
|
+
return Array.from(new Set(filterCategories.map(filterValue => {
|
|
43
|
+
const matched = activeCategories.find(category => category.label === filterValue);
|
|
44
|
+
return matched ? matched.value : filterValue;
|
|
45
|
+
})));
|
|
46
|
+
}
|
|
47
|
+
export function normalizePriorityFilterValues(filterPriorities, priorities) {
|
|
48
|
+
if (!priorities.length || !filterPriorities.length)
|
|
49
|
+
return [];
|
|
50
|
+
const available = new Set(priorities.map(p => Number(p.value)));
|
|
51
|
+
const targetIsOneToFive = available.has(5) && !available.has(0);
|
|
52
|
+
const targetIsOneToFour = available.has(4) && !available.has(5) && !available.has(0);
|
|
53
|
+
const rawNumeric = filterPriorities
|
|
54
|
+
.map(p => Number(p))
|
|
55
|
+
.filter(n => Number.isFinite(n));
|
|
56
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
57
|
+
// COMPAT_TRACK: priority-scale-0-to-4
|
|
58
|
+
const shouldShiftLegacyScale = MIGRATION_COMPAT_ENABLED && targetIsOneToFive && rawNumeric.includes(0);
|
|
59
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
60
|
+
// COMPAT_TRACK: priority-on-hold-to-status
|
|
61
|
+
const shouldConvertOldFiveScale = MIGRATION_COMPAT_ENABLED && targetIsOneToFour && rawNumeric.includes(5);
|
|
62
|
+
return Array.from(new Set(rawNumeric
|
|
63
|
+
.map(n => {
|
|
64
|
+
if (shouldShiftLegacyScale && n >= 0 && n <= 4)
|
|
65
|
+
return n + 1;
|
|
66
|
+
if (shouldConvertOldFiveScale && n >= 2 && n <= 5)
|
|
67
|
+
return n - 1;
|
|
68
|
+
return n;
|
|
69
|
+
})
|
|
70
|
+
.filter(n => available.has(n))));
|
|
71
|
+
}
|
|
72
|
+
export function matchesPriorityFilter(taskPriority, filterPriorities) {
|
|
73
|
+
return filterPriorities.some(filterPriority => String(filterPriority) === String(taskPriority));
|
|
74
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { DatabaseAdapter } from '../storage/databaseAdapter.js';
|
|
2
|
+
export interface PriorityDefinition {
|
|
3
|
+
value: number;
|
|
4
|
+
label: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
icon?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TaskMigrationComment {
|
|
9
|
+
id: string;
|
|
10
|
+
text: string;
|
|
11
|
+
author: 'user' | 'ai';
|
|
12
|
+
timestamp: string;
|
|
13
|
+
}
|
|
14
|
+
export interface TaskMigrationScreenshot {
|
|
15
|
+
path: string;
|
|
16
|
+
fsPath?: string;
|
|
17
|
+
caption?: string;
|
|
18
|
+
timestamp?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface TaskMigrationItem {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
description?: string | null;
|
|
24
|
+
status: string;
|
|
25
|
+
priority?: number | string;
|
|
26
|
+
complexity?: number | string;
|
|
27
|
+
type?: string;
|
|
28
|
+
category?: string;
|
|
29
|
+
approach?: string;
|
|
30
|
+
createdAt?: string;
|
|
31
|
+
updatedAt?: string;
|
|
32
|
+
completedAt?: string | null;
|
|
33
|
+
scheduledDate?: string | null;
|
|
34
|
+
dueDate?: string | null;
|
|
35
|
+
scheduledWeekKey?: string | null;
|
|
36
|
+
orderInDay?: number | null;
|
|
37
|
+
canceledReason?: string;
|
|
38
|
+
isArchived?: boolean;
|
|
39
|
+
specialists?: string[];
|
|
40
|
+
taxonomies?: Record<string, string | string[]>;
|
|
41
|
+
createdBy?: string;
|
|
42
|
+
comments?: TaskMigrationComment[];
|
|
43
|
+
screenshots?: Array<string | TaskMigrationScreenshot>;
|
|
44
|
+
}
|
|
45
|
+
export declare function normalizePriorityValue(priority: unknown, legacyScale?: boolean): number;
|
|
46
|
+
export declare function normalizePriorityDefinitions(priorities: PriorityDefinition[]): {
|
|
47
|
+
priorities: PriorityDefinition[];
|
|
48
|
+
changed: boolean;
|
|
49
|
+
};
|
|
50
|
+
export declare function migratePriorityScaleIfNeeded(args: {
|
|
51
|
+
db: DatabaseAdapter;
|
|
52
|
+
tenantId: string;
|
|
53
|
+
readConfig: () => {
|
|
54
|
+
priorities?: PriorityDefinition[];
|
|
55
|
+
} | undefined;
|
|
56
|
+
writeConfig: (config: any) => void;
|
|
57
|
+
}): void;
|
|
58
|
+
export declare function migrateOnHoldPriorityToStatusIfNeeded(args: {
|
|
59
|
+
db: DatabaseAdapter;
|
|
60
|
+
tenantId: string;
|
|
61
|
+
readConfig: () => {
|
|
62
|
+
priorities?: PriorityDefinition[];
|
|
63
|
+
} | undefined;
|
|
64
|
+
writeConfig: (config: any) => void;
|
|
65
|
+
}): void;
|
|
66
|
+
export declare function performLegacyTaskFileMigrationIfNeeded(args: {
|
|
67
|
+
db: DatabaseAdapter;
|
|
68
|
+
basePath: string;
|
|
69
|
+
tenantId: string;
|
|
70
|
+
normalizePriority: (priority: unknown, legacyScale?: boolean) => number;
|
|
71
|
+
}): void;
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { MIGRATION_COMPAT_ENABLED } from './flags.js';
|
|
4
|
+
const DEFAULT_PRIORITY_DEFINITIONS = [
|
|
5
|
+
{ value: 1, label: 'Low', color: 'teal-500', icon: 'ArrowDown' },
|
|
6
|
+
{ value: 2, label: 'Medium', color: 'blue-500', icon: 'Minus' },
|
|
7
|
+
{ value: 3, label: 'High', color: 'amber-500', icon: 'ArrowUp' },
|
|
8
|
+
{ value: 4, label: 'Critical', color: 'red-500', icon: 'AlertTriangle' },
|
|
9
|
+
];
|
|
10
|
+
function normalizeStatusValue(status) {
|
|
11
|
+
const normalized = String(status || '').trim().toLowerCase();
|
|
12
|
+
if (normalized === 'blocked' || normalized === 'on hold' || normalized === 'on-hold')
|
|
13
|
+
return 'on-hold';
|
|
14
|
+
if (normalized === 'task' || normalized === 'in-progress' || normalized === 'review' || normalized === 'done' || normalized === 'cancelled') {
|
|
15
|
+
return normalized;
|
|
16
|
+
}
|
|
17
|
+
return 'task';
|
|
18
|
+
}
|
|
19
|
+
export function normalizePriorityValue(priority, legacyScale = false) {
|
|
20
|
+
const numeric = typeof priority === 'number' ? priority : Number(priority);
|
|
21
|
+
if (!Number.isFinite(numeric))
|
|
22
|
+
return 2;
|
|
23
|
+
const rounded = Math.round(numeric);
|
|
24
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
25
|
+
// COMPAT_TRACK: priority-scale-0-to-4
|
|
26
|
+
if (MIGRATION_COMPAT_ENABLED && legacyScale && rounded >= 0 && rounded <= 4) {
|
|
27
|
+
return Math.max(1, Math.min(4, rounded + 1));
|
|
28
|
+
}
|
|
29
|
+
return Math.max(1, Math.min(4, rounded));
|
|
30
|
+
}
|
|
31
|
+
export function normalizePriorityDefinitions(priorities) {
|
|
32
|
+
if (!Array.isArray(priorities) || priorities.length === 0) {
|
|
33
|
+
return { priorities: DEFAULT_PRIORITY_DEFINITIONS.map(p => ({ ...p })), changed: true };
|
|
34
|
+
}
|
|
35
|
+
const hasLegacyScale = priorities.some(p => Number(p.value) === 0);
|
|
36
|
+
let changed = false;
|
|
37
|
+
const byValue = new Map();
|
|
38
|
+
for (const p of priorities) {
|
|
39
|
+
const nextValue = normalizePriorityValue(p.value, hasLegacyScale);
|
|
40
|
+
if (nextValue !== p.value)
|
|
41
|
+
changed = true;
|
|
42
|
+
if (byValue.has(nextValue)) {
|
|
43
|
+
changed = true;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
byValue.set(nextValue, { ...p, value: nextValue });
|
|
47
|
+
}
|
|
48
|
+
for (const fallback of DEFAULT_PRIORITY_DEFINITIONS) {
|
|
49
|
+
if (!byValue.has(fallback.value)) {
|
|
50
|
+
byValue.set(fallback.value, { ...fallback });
|
|
51
|
+
changed = true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const normalized = Array.from(byValue.values()).sort((a, b) => a.value - b.value);
|
|
55
|
+
return { priorities: normalized, changed };
|
|
56
|
+
}
|
|
57
|
+
export function migratePriorityScaleIfNeeded(args) {
|
|
58
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
59
|
+
// COMPAT_TRACK: priority-scale-0-to-4
|
|
60
|
+
if (!MIGRATION_COMPAT_ENABLED)
|
|
61
|
+
return;
|
|
62
|
+
const { db, tenantId, readConfig, writeConfig } = args;
|
|
63
|
+
const hasLegacyTaskPriorities = !!db.prepare('SELECT 1 FROM tasks WHERE tenant_id = ? AND priority = 0 LIMIT 1').get(tenantId);
|
|
64
|
+
if (hasLegacyTaskPriorities) {
|
|
65
|
+
db.prepare('UPDATE tasks SET priority = priority + 1 WHERE tenant_id = ? AND priority >= 0 AND priority <= 4').run(tenantId);
|
|
66
|
+
}
|
|
67
|
+
const config = readConfig() || {};
|
|
68
|
+
if (Array.isArray(config.priorities)) {
|
|
69
|
+
const normalized = normalizePriorityDefinitions(config.priorities);
|
|
70
|
+
if (normalized.changed) {
|
|
71
|
+
config.priorities = normalized.priorities;
|
|
72
|
+
writeConfig(config);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function isOnHoldPriorityLabel(label) {
|
|
77
|
+
const normalized = String(label || '').trim().toLowerCase();
|
|
78
|
+
return normalized === 'on hold' || normalized === 'on-hold';
|
|
79
|
+
}
|
|
80
|
+
export function migrateOnHoldPriorityToStatusIfNeeded(args) {
|
|
81
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
82
|
+
// COMPAT_TRACK: priority-on-hold-to-status
|
|
83
|
+
if (!MIGRATION_COMPAT_ENABLED)
|
|
84
|
+
return;
|
|
85
|
+
const { db, tenantId, readConfig, writeConfig } = args;
|
|
86
|
+
const hasLegacyFiveScale = !!db.prepare('SELECT 1 FROM tasks WHERE tenant_id = ? AND priority = 5 LIMIT 1').get(tenantId);
|
|
87
|
+
const config = readConfig() || {};
|
|
88
|
+
const hasConfigOnHold = Array.isArray(config.priorities)
|
|
89
|
+
&& config.priorities.some((p) => Number(p.value) === 1 && isOnHoldPriorityLabel(p.label));
|
|
90
|
+
const hasConfigFiveScale = Array.isArray(config.priorities)
|
|
91
|
+
&& config.priorities.some((p) => Number(p.value) === 5);
|
|
92
|
+
// Guard: do not infer legacy "on-hold" from tasks with priority=1, because 1 is now valid "Low".
|
|
93
|
+
const shouldMigrateDb = hasLegacyFiveScale || hasConfigOnHold || hasConfigFiveScale;
|
|
94
|
+
if (!shouldMigrateDb)
|
|
95
|
+
return;
|
|
96
|
+
if (hasConfigOnHold) {
|
|
97
|
+
db.prepare("UPDATE tasks SET status = 'on-hold' WHERE tenant_id = ? AND priority = 1 AND status IN ('task', 'in-progress', 'review')").run(tenantId);
|
|
98
|
+
}
|
|
99
|
+
if (hasLegacyFiveScale || hasConfigOnHold || hasConfigFiveScale) {
|
|
100
|
+
db.prepare('UPDATE tasks SET priority = priority - 1 WHERE tenant_id = ? AND priority >= 2 AND priority <= 5').run(tenantId);
|
|
101
|
+
db.prepare('UPDATE tasks SET priority = 1 WHERE tenant_id = ? AND priority < 1').run(tenantId);
|
|
102
|
+
db.prepare('UPDATE tasks SET priority = 4 WHERE tenant_id = ? AND priority > 4').run(tenantId);
|
|
103
|
+
}
|
|
104
|
+
if (!Array.isArray(config.priorities))
|
|
105
|
+
return;
|
|
106
|
+
const transformed = config.priorities
|
|
107
|
+
.filter((p) => !(Number(p.value) === 1 && isOnHoldPriorityLabel(p.label)))
|
|
108
|
+
.map((p) => {
|
|
109
|
+
const value = Number(p.value);
|
|
110
|
+
const nextValue = value >= 2 && value <= 5 ? value - 1 : value;
|
|
111
|
+
return { ...p, value: normalizePriorityValue(nextValue, false) };
|
|
112
|
+
})
|
|
113
|
+
.sort((a, b) => a.value - b.value);
|
|
114
|
+
config.priorities = transformed;
|
|
115
|
+
writeConfig(config);
|
|
116
|
+
}
|
|
117
|
+
export function performLegacyTaskFileMigrationIfNeeded(args) {
|
|
118
|
+
// COMPAT_REMOVE_AFTER: v1.0.0
|
|
119
|
+
// COMPAT_TRACK: legacy-task-files-to-sqlite
|
|
120
|
+
if (!MIGRATION_COMPAT_ENABLED)
|
|
121
|
+
return;
|
|
122
|
+
const { db, basePath, tenantId, normalizePriority } = args;
|
|
123
|
+
const count = db.prepare('SELECT count(*) as count FROM tasks WHERE tenant_id = ?').get(tenantId);
|
|
124
|
+
if (count.count > 0)
|
|
125
|
+
return;
|
|
126
|
+
const taskFile = path.resolve(basePath, 'tasks.json');
|
|
127
|
+
const tasksToMigrate = [];
|
|
128
|
+
if (fs.existsSync(taskFile)) {
|
|
129
|
+
try {
|
|
130
|
+
const data = JSON.parse(fs.readFileSync(taskFile, 'utf-8'));
|
|
131
|
+
if (data.tasks)
|
|
132
|
+
tasksToMigrate.push(...data.tasks);
|
|
133
|
+
if (data.archived)
|
|
134
|
+
tasksToMigrate.push(...data.archived);
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error('[Taskforce] Failed to read tasks.json for migration', e);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (tasksToMigrate.length === 0)
|
|
141
|
+
return;
|
|
142
|
+
console.log(`[Taskforce] Migrating ${tasksToMigrate.length} tasks to SQLite...`);
|
|
143
|
+
const hasLegacyPriorityScale = tasksToMigrate.some(task => Number(task.priority) === 0);
|
|
144
|
+
const insertTask = db.prepare(`
|
|
145
|
+
INSERT OR REPLACE INTO tasks (
|
|
146
|
+
id, tenant_id, title, description, status, priority, complexity, type, category,
|
|
147
|
+
approach, created_at, updated_at, completed_at, canceled_reason,
|
|
148
|
+
scheduled_date, due_date, scheduled_week_key, order_in_day,
|
|
149
|
+
is_archived, specialists, taxonomies, created_by
|
|
150
|
+
) VALUES (
|
|
151
|
+
@id, @tenant_id, @title, @description, @status, @priority, @complexity, @type, @category,
|
|
152
|
+
@approach, @created_at, @updated_at, @completed_at, @canceled_reason,
|
|
153
|
+
@scheduled_date, @due_date, @scheduled_week_key, @order_in_day,
|
|
154
|
+
@is_archived, @specialists, @taxonomies, @created_by
|
|
155
|
+
)
|
|
156
|
+
`);
|
|
157
|
+
const insertComment = db.prepare(`
|
|
158
|
+
INSERT OR REPLACE INTO comments (id, tenant_id, task_id, text, author, timestamp)
|
|
159
|
+
VALUES (@id, @tenant_id, @task_id, @text, @author, @timestamp)
|
|
160
|
+
`);
|
|
161
|
+
const insertScreenshot = db.prepare(`
|
|
162
|
+
INSERT OR REPLACE INTO screenshots (id, tenant_id, task_id, path, fs_path, caption, timestamp)
|
|
163
|
+
VALUES (@id, @tenant_id, @task_id, @path, @fs_path, @caption, @timestamp)
|
|
164
|
+
`);
|
|
165
|
+
const transaction = db.transaction((tasks) => {
|
|
166
|
+
for (const task of tasks) {
|
|
167
|
+
const isArchived = task.isArchived !== undefined
|
|
168
|
+
? (task.isArchived ? 1 : 0)
|
|
169
|
+
: (task.status === 'done' || task.status === 'cancelled' ? 1 : 0);
|
|
170
|
+
insertTask.run({
|
|
171
|
+
id: task.id,
|
|
172
|
+
tenant_id: tenantId,
|
|
173
|
+
title: task.title,
|
|
174
|
+
description: task.description || null,
|
|
175
|
+
status: normalizeStatusValue(task.status),
|
|
176
|
+
priority: normalizePriority(task.priority, hasLegacyPriorityScale),
|
|
177
|
+
complexity: typeof task.complexity === 'string' ? 3 : (task.complexity ?? 3),
|
|
178
|
+
type: task.type || 'feature',
|
|
179
|
+
category: task.category || 'default',
|
|
180
|
+
approach: task.approach || null,
|
|
181
|
+
created_at: task.createdAt || new Date().toISOString(),
|
|
182
|
+
updated_at: task.updatedAt || null,
|
|
183
|
+
completed_at: task.completedAt || null,
|
|
184
|
+
canceled_reason: task.canceledReason || null,
|
|
185
|
+
scheduled_date: task.scheduledDate || null,
|
|
186
|
+
due_date: task.dueDate || null,
|
|
187
|
+
scheduled_week_key: task.scheduledWeekKey || null,
|
|
188
|
+
order_in_day: typeof task.orderInDay === 'number' ? Math.max(0, Math.round(task.orderInDay)) : null,
|
|
189
|
+
is_archived: isArchived,
|
|
190
|
+
specialists: JSON.stringify(task.specialists || []),
|
|
191
|
+
taxonomies: JSON.stringify(task.taxonomies || {}),
|
|
192
|
+
created_by: task.createdBy || null
|
|
193
|
+
});
|
|
194
|
+
if (task.comments && Array.isArray(task.comments)) {
|
|
195
|
+
for (const comment of task.comments) {
|
|
196
|
+
insertComment.run({
|
|
197
|
+
id: comment.id,
|
|
198
|
+
tenant_id: tenantId,
|
|
199
|
+
task_id: task.id,
|
|
200
|
+
text: comment.text,
|
|
201
|
+
author: comment.author,
|
|
202
|
+
timestamp: comment.timestamp
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
if (task.screenshots && Array.isArray(task.screenshots)) {
|
|
207
|
+
for (const s of task.screenshots) {
|
|
208
|
+
if (typeof s === 'string') {
|
|
209
|
+
insertScreenshot.run({
|
|
210
|
+
id: `scr-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
|
|
211
|
+
tenant_id: tenantId,
|
|
212
|
+
task_id: task.id,
|
|
213
|
+
path: s,
|
|
214
|
+
fs_path: null,
|
|
215
|
+
caption: null,
|
|
216
|
+
timestamp: new Date().toISOString()
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
insertScreenshot.run({
|
|
221
|
+
id: `scr-${Date.now()}-${Math.random().toString(36).substr(2, 5)}`,
|
|
222
|
+
tenant_id: tenantId,
|
|
223
|
+
task_id: task.id,
|
|
224
|
+
path: s.path,
|
|
225
|
+
fs_path: s.fsPath || null,
|
|
226
|
+
caption: s.caption || null,
|
|
227
|
+
timestamp: s.timestamp || new Date().toISOString()
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
transaction(tasksToMigrate);
|
|
235
|
+
console.log('[Taskforce] Migration complete.');
|
|
236
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { normalizePriorityDefinitions } from './taskMigrations';
|
|
3
|
+
describe('normalizePriorityDefinitions', () => {
|
|
4
|
+
it('repairs duplicate and missing values to canonical 1..4', () => {
|
|
5
|
+
const input = [
|
|
6
|
+
{ value: 1, label: 'Low' },
|
|
7
|
+
{ value: 2, label: 'Medium' },
|
|
8
|
+
{ value: 3, label: 'High' },
|
|
9
|
+
{ value: 3, label: 'Critical' }
|
|
10
|
+
];
|
|
11
|
+
const result = normalizePriorityDefinitions(input);
|
|
12
|
+
expect(result.changed).toBe(true);
|
|
13
|
+
expect(result.priorities.map(p => p.value)).toEqual([1, 2, 3, 4]);
|
|
14
|
+
expect(result.priorities.find(p => p.value === 4)?.label).toBe('Critical');
|
|
15
|
+
});
|
|
16
|
+
it('returns canonical defaults when input is empty', () => {
|
|
17
|
+
const result = normalizePriorityDefinitions([]);
|
|
18
|
+
expect(result.changed).toBe(true);
|
|
19
|
+
expect(result.priorities.map(p => p.value)).toEqual([1, 2, 3, 4]);
|
|
20
|
+
expect(result.priorities.map(p => p.label)).toEqual(['Low', 'Medium', 'High', 'Critical']);
|
|
21
|
+
});
|
|
22
|
+
it('normalizes legacy 0..4 scale and clamps to current 1..4', () => {
|
|
23
|
+
const input = [
|
|
24
|
+
{ value: 0, label: 'Legacy 0' },
|
|
25
|
+
{ value: 1, label: 'Legacy 1' },
|
|
26
|
+
{ value: 2, label: 'Legacy 2' },
|
|
27
|
+
{ value: 3, label: 'Legacy 3' },
|
|
28
|
+
{ value: 4, label: 'Legacy 4' }
|
|
29
|
+
];
|
|
30
|
+
const result = normalizePriorityDefinitions(input);
|
|
31
|
+
expect(result.changed).toBe(true);
|
|
32
|
+
expect(result.priorities.map(p => p.value)).toEqual([1, 2, 3, 4]);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DatabaseAdapter } from '../storage/databaseAdapter.js';
|
|
2
|
+
export declare function ensureTenantSchema(db: DatabaseAdapter): void;
|
|
3
|
+
export declare function ensureParentTaskSchema(db: DatabaseAdapter): void;
|
|
4
|
+
export declare function ensureScheduleTaskSchema(db: DatabaseAdapter): void;
|
|
5
|
+
export declare function ensureAssigneeTaskSchema(db: DatabaseAdapter): void;
|
|
6
|
+
export declare function ensureWorkspaceSchema(db: DatabaseAdapter): void;
|
|
7
|
+
export declare function ensureBillingSchema(db: DatabaseAdapter): void;
|
|
8
|
+
export declare function ensureEntitlementsSchema(db: DatabaseAdapter): void;
|
|
9
|
+
export declare function ensureTaskAssetsSchema(db: DatabaseAdapter): void;
|
|
10
|
+
export declare function ensureSyncEventsSchema(db: DatabaseAdapter): void;
|
|
11
|
+
export declare function ensureWorkspaceDocumentsSchema(db: DatabaseAdapter): void;
|