@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.
Files changed (492) hide show
  1. package/README.md +241 -0
  2. package/dist/Taskforce.d.ts +3 -0
  3. package/dist/Taskforce.js +3 -0
  4. package/dist/Taskforce.module.css +7587 -0
  5. package/dist/TaskforceCore.CategoryFallback.test.d.ts +1 -0
  6. package/dist/TaskforceCore.CategoryFallback.test.js +98 -0
  7. package/dist/TaskforceCore.d.ts +12 -0
  8. package/dist/TaskforceCore.js +729 -0
  9. package/dist/TaskforceCore.test.d.ts +1 -0
  10. package/dist/TaskforceCore.test.js +2132 -0
  11. package/dist/TaskforceScreenshot.d.ts +11 -0
  12. package/dist/TaskforceScreenshot.js +113 -0
  13. package/dist/TaskforceWidget.d.ts +6 -0
  14. package/dist/TaskforceWidget.js +101 -0
  15. package/dist/TaskforceWidget.test.d.ts +1 -0
  16. package/dist/TaskforceWidget.test.js +92 -0
  17. package/dist/UnsavedChangesRelaxed.test.d.ts +1 -0
  18. package/dist/UnsavedChangesRelaxed.test.js +16 -0
  19. package/dist/__tests__/localizationCatalogs.test.d.ts +1 -0
  20. package/dist/__tests__/localizationCatalogs.test.js +37 -0
  21. package/dist/__tests__/planParser.test.d.ts +1 -0
  22. package/dist/__tests__/planParser.test.js +183 -0
  23. package/dist/__tests__/releaseVersion.test.d.ts +1 -0
  24. package/dist/__tests__/releaseVersion.test.js +32 -0
  25. package/dist/__tests__/structuredCommentValidation.test.d.ts +1 -0
  26. package/dist/__tests__/structuredCommentValidation.test.js +31 -0
  27. package/dist/__tests__/structuredDocValidation.test.d.ts +1 -0
  28. package/dist/__tests__/structuredDocValidation.test.js +30 -0
  29. package/dist/__tests__/templateEngine.test.d.ts +1 -0
  30. package/dist/__tests__/templateEngine.test.js +150 -0
  31. package/dist/__tests__/templates.test.d.ts +1 -0
  32. package/dist/__tests__/templates.test.js +45 -0
  33. package/dist/__tests__/workflowDocumentFixtures.test.d.ts +1 -0
  34. package/dist/__tests__/workflowDocumentFixtures.test.js +78 -0
  35. package/dist/__tests__/workflowExportMatrix.test.d.ts +1 -0
  36. package/dist/__tests__/workflowExportMatrix.test.js +113 -0
  37. package/dist/__tests__/workflowExportSnapshots.test.d.ts +1 -0
  38. package/dist/__tests__/workflowExportSnapshots.test.js +28 -0
  39. package/dist/__tests__/workflowGeneration.test.d.ts +1 -0
  40. package/dist/__tests__/workflowGeneration.test.js +12 -0
  41. package/dist/__tests__/workflowSimulation.test.d.ts +1 -0
  42. package/dist/__tests__/workflowSimulation.test.js +113 -0
  43. package/dist/__tests__/workflowV2Policy.test.d.ts +1 -0
  44. package/dist/__tests__/workflowV2Policy.test.js +80 -0
  45. package/dist/api.d.ts +30 -0
  46. package/dist/api.js +85 -0
  47. package/dist/cli.d.ts +2 -0
  48. package/dist/cli.js +217 -0
  49. package/dist/compat/priorityCompat.d.ts +2 -0
  50. package/dist/compat/priorityCompat.js +24 -0
  51. package/dist/components/features/DocumentGenerateModal.d.ts +9 -0
  52. package/dist/components/features/DocumentGenerateModal.js +114 -0
  53. package/dist/components/features/DocumentIndex.d.ts +19 -0
  54. package/dist/components/features/DocumentIndex.js +51 -0
  55. package/dist/components/features/DocumentViewer.d.ts +9 -0
  56. package/dist/components/features/DocumentViewer.js +253 -0
  57. package/dist/components/features/DocumentWorkspace.d.ts +21 -0
  58. package/dist/components/features/DocumentWorkspace.js +88 -0
  59. package/dist/components/features/TaskSettings.d.ts +209 -0
  60. package/dist/components/features/TaskSettings.js +500 -0
  61. package/dist/components/features/TaskSettings.test.d.ts +1 -0
  62. package/dist/components/features/TaskSettings.test.js +308 -0
  63. package/dist/components/features/settings/CategoryManager.d.ts +19 -0
  64. package/dist/components/features/settings/CategoryManager.js +113 -0
  65. package/dist/components/features/settings/TaxonomyEditor.d.ts +8 -0
  66. package/dist/components/features/settings/TaxonomyEditor.js +98 -0
  67. package/dist/components/features/settings/TaxonomyManager 2.d.ts +52 -0
  68. package/dist/components/features/settings/TaxonomyManager 2.js +75 -0
  69. package/dist/components/features/settings/TaxonomyManager.d.ts +54 -0
  70. package/dist/components/features/settings/TaxonomyManager.js +77 -0
  71. package/dist/components/features/settings/TypeManager.d.ts +10 -0
  72. package/dist/components/features/settings/TypeManager.js +50 -0
  73. package/dist/components/features/settings/WorkflowEditorPrototype.d.ts +15 -0
  74. package/dist/components/features/settings/WorkflowEditorPrototype.js +245 -0
  75. package/dist/components/task/TaskActionHeader.d.ts +20 -0
  76. package/dist/components/task/TaskActionHeader.js +13 -0
  77. package/dist/components/task/TaskCard.d.ts +47 -0
  78. package/dist/components/task/TaskCard.js +326 -0
  79. package/dist/components/task/TaskCard.test.d.ts +1 -0
  80. package/dist/components/task/TaskCard.test.js +95 -0
  81. package/dist/components/task/TaskContextUpload.d.ts +12 -0
  82. package/dist/components/task/TaskContextUpload.js +393 -0
  83. package/dist/components/task/TaskContextUpload.test.d.ts +1 -0
  84. package/dist/components/task/TaskContextUpload.test.js +189 -0
  85. package/dist/components/task/TaskForm.d.ts +105 -0
  86. package/dist/components/task/TaskForm.js +241 -0
  87. package/dist/components/task/TaskForm.test.d.ts +1 -0
  88. package/dist/components/task/TaskForm.test.js +288 -0
  89. package/dist/components/task/TaskKanban 2.d.ts +76 -0
  90. package/dist/components/task/TaskKanban 2.js +1004 -0
  91. package/dist/components/task/TaskKanban.d.ts +76 -0
  92. package/dist/components/task/TaskKanban.empty-column-drop.test.d.ts +1 -0
  93. package/dist/components/task/TaskKanban.empty-column-drop.test.js +66 -0
  94. package/dist/components/task/TaskKanban.js +1026 -0
  95. package/dist/components/task/TaskKanban.test.d.ts +1 -0
  96. package/dist/components/task/TaskKanban.test.js +46 -0
  97. package/dist/components/task/TaskList.d.ts +74 -0
  98. package/dist/components/task/TaskList.js +38 -0
  99. package/dist/components/task/TaskList.test.d.ts +1 -0
  100. package/dist/components/task/TaskList.test.js +270 -0
  101. package/dist/components/task/TaskScreenshotSection.d.ts +15 -0
  102. package/dist/components/task/TaskScreenshotSection.js +22 -0
  103. package/dist/components/ui/LevelSelector.d.ts +13 -0
  104. package/dist/components/ui/LevelSelector.js +25 -0
  105. package/dist/components/ui/LevelSelector.test.d.ts +1 -0
  106. package/dist/components/ui/LevelSelector.test.js +55 -0
  107. package/dist/components/ui/Markdown.d.ts +6 -0
  108. package/dist/components/ui/Markdown.js +94 -0
  109. package/dist/components/ui/Markdown.test.d.ts +1 -0
  110. package/dist/components/ui/Markdown.test.js +38 -0
  111. package/dist/components/ui/Modal.d.ts +16 -0
  112. package/dist/components/ui/Modal.js +49 -0
  113. package/dist/components/ui/MultiSelectFilter.d.ts +10 -0
  114. package/dist/components/ui/MultiSelectFilter.js +71 -0
  115. package/dist/components/ui/MultiSelectFilter.test.d.ts +1 -0
  116. package/dist/components/ui/MultiSelectFilter.test.js +74 -0
  117. package/dist/components/ui/TaxonomyDropdown.d.ts +17 -0
  118. package/dist/components/ui/TaxonomyDropdown.js +145 -0
  119. package/dist/components/ui/TaxonomyDropdown.test.d.ts +1 -0
  120. package/dist/components/ui/TaxonomyDropdown.test.js +130 -0
  121. package/dist/components/views/StandaloneLayout 2.d.ts +8 -0
  122. package/dist/components/views/StandaloneLayout 2.js +1660 -0
  123. package/dist/components/views/StandaloneLayout.d.ts +8 -0
  124. package/dist/components/views/StandaloneLayout.js +2117 -0
  125. package/dist/components/views/WidgetView.d.ts +8 -0
  126. package/dist/components/views/WidgetView.js +221 -0
  127. package/dist/config/envSchema.d.ts +28 -0
  128. package/dist/config/envSchema.js +374 -0
  129. package/dist/config/envSchema.test.d.ts +1 -0
  130. package/dist/config/envSchema.test.js +97 -0
  131. package/dist/config/surfaceBase.d.ts +2 -0
  132. package/dist/config/surfaceBase.js +8 -0
  133. package/dist/core/BulkUpdateFieldsPreview.test.d.ts +1 -0
  134. package/dist/core/BulkUpdateFieldsPreview.test.js +62 -0
  135. package/dist/core/CompletedAt.test.d.ts +1 -0
  136. package/dist/core/CompletedAt.test.js +44 -0
  137. package/dist/core/CreatedBy.test.d.ts +1 -0
  138. package/dist/core/CreatedBy.test.js +60 -0
  139. package/dist/core/EntitlementsPolicy.test.d.ts +1 -0
  140. package/dist/core/EntitlementsPolicy.test.js +145 -0
  141. package/dist/core/InitiativeTemplates.test.d.ts +1 -0
  142. package/dist/core/InitiativeTemplates.test.js +50 -0
  143. package/dist/core/ParentLifecycle.test.d.ts +1 -0
  144. package/dist/core/ParentLifecycle.test.js +98 -0
  145. package/dist/core/ScheduleFields.test.d.ts +1 -0
  146. package/dist/core/ScheduleFields.test.js +197 -0
  147. package/dist/core/SetupState.test.d.ts +1 -0
  148. package/dist/core/SetupState.test.js +113 -0
  149. package/dist/core/SystemAdmin.test.d.ts +1 -0
  150. package/dist/core/SystemAdmin.test.js +295 -0
  151. package/dist/core/TaskTaxonomyValidation.test.d.ts +1 -0
  152. package/dist/core/TaskTaxonomyValidation.test.js +64 -0
  153. package/dist/core/Taskforce.d.ts +1063 -0
  154. package/dist/core/Taskforce.ids.test.d.ts +1 -0
  155. package/dist/core/Taskforce.ids.test.js +168 -0
  156. package/dist/core/Taskforce.js +5981 -0
  157. package/dist/core/Taskforce.realtimeMutation.test.d.ts +1 -0
  158. package/dist/core/Taskforce.realtimeMutation.test.js +76 -0
  159. package/dist/core/WorkspaceDelete.test.d.ts +1 -0
  160. package/dist/core/WorkspaceDelete.test.js +140 -0
  161. package/dist/core/WorkspacePermissions.test.d.ts +1 -0
  162. package/dist/core/WorkspacePermissions.test.js +151 -0
  163. package/dist/core/WorkspacePlanMode.test.d.ts +1 -0
  164. package/dist/core/WorkspacePlanMode.test.js +104 -0
  165. package/dist/hooks/authGuardPolicy.d.ts +26 -0
  166. package/dist/hooks/authGuardPolicy.js +32 -0
  167. package/dist/hooks/authGuardPolicy.test.d.ts +1 -0
  168. package/dist/hooks/authGuardPolicy.test.js +76 -0
  169. package/dist/hooks/useDraggable.d.ts +12 -0
  170. package/dist/hooks/useDraggable.js +65 -0
  171. package/dist/hooks/useRealtimeSync.d.ts +24 -0
  172. package/dist/hooks/useRealtimeSync.js +275 -0
  173. package/dist/hooks/useRealtimeSync.test.d.ts +1 -0
  174. package/dist/hooks/useRealtimeSync.test.js +284 -0
  175. package/dist/hooks/useSyncOrchestrator.d.ts +164 -0
  176. package/dist/hooks/useSyncOrchestrator.js +1427 -0
  177. package/dist/hooks/useSyncOrchestrator.retry-closure.test.d.ts +1 -0
  178. package/dist/hooks/useSyncOrchestrator.retry-closure.test.js +367 -0
  179. package/dist/hooks/useTaskforce.d.ts +727 -0
  180. package/dist/hooks/useTaskforce.js +4396 -0
  181. package/dist/hooks/useTaskforce.priority-filters.test.d.ts +1 -0
  182. package/dist/hooks/useTaskforce.priority-filters.test.js +33 -0
  183. package/dist/hooks/useWorkspaceSyncController.d.ts +80 -0
  184. package/dist/hooks/useWorkspaceSyncController.js +598 -0
  185. package/dist/hooks/useWorkspaceSyncController.test.d.ts +1 -0
  186. package/dist/hooks/useWorkspaceSyncController.test.js +236 -0
  187. package/dist/index.d.ts +12 -0
  188. package/dist/index.js +11 -0
  189. package/dist/localization/index.d.ts +8 -0
  190. package/dist/localization/index.js +81 -0
  191. package/dist/localization/locales/en-US.d.ts +151 -0
  192. package/dist/localization/locales/en-US.js +150 -0
  193. package/dist/localization/locales/es-419.d.ts +2 -0
  194. package/dist/localization/locales/es-419.js +150 -0
  195. package/dist/localization/locales/pt-BR.d.ts +2 -0
  196. package/dist/localization/locales/pt-BR.js +150 -0
  197. package/dist/main.d.ts +1 -0
  198. package/dist/main.js +33 -0
  199. package/dist/mcp/optionResolution.d.ts +14 -0
  200. package/dist/mcp/optionResolution.js +126 -0
  201. package/dist/mcp/optionResolution.test.d.ts +1 -0
  202. package/dist/mcp/optionResolution.test.js +39 -0
  203. package/dist/mcp/server.d.ts +1 -0
  204. package/dist/mcp/server.js +1793 -0
  205. package/dist/mcp/structuredCommentValidation.d.ts +6 -0
  206. package/dist/mcp/structuredCommentValidation.js +56 -0
  207. package/dist/mcp/structuredDocValidation.d.ts +6 -0
  208. package/dist/mcp/structuredDocValidation.js +75 -0
  209. package/dist/migrations/billingSchemaParity.test.d.ts +1 -0
  210. package/dist/migrations/billingSchemaParity.test.js +46 -0
  211. package/dist/migrations/clientMigrations.d.ts +9 -0
  212. package/dist/migrations/clientMigrations.js +74 -0
  213. package/dist/migrations/flags.d.ts +6 -0
  214. package/dist/migrations/flags.js +8 -0
  215. package/dist/migrations/taskMigrations.d.ts +71 -0
  216. package/dist/migrations/taskMigrations.js +236 -0
  217. package/dist/migrations/taskMigrations.test.d.ts +1 -0
  218. package/dist/migrations/taskMigrations.test.js +34 -0
  219. package/dist/migrations/taskSchemaMigrations.d.ts +11 -0
  220. package/dist/migrations/taskSchemaMigrations.js +453 -0
  221. package/dist/plugins/index.d.ts +10 -0
  222. package/dist/plugins/index.js +10 -0
  223. package/dist/plugins/vite.d.ts +19 -0
  224. package/dist/plugins/vite.js +271 -0
  225. package/dist/public/android-chrome-192x192.png +0 -0
  226. package/dist/public/android-chrome-512x512.png +0 -0
  227. package/dist/public/apple-touch-icon.png +0 -0
  228. package/dist/public/favicon-16x16.png +0 -0
  229. package/dist/public/favicon-32x32.png +0 -0
  230. package/dist/public/favicon.ico +0 -0
  231. package/dist/public/favicon.png +0 -0
  232. package/dist/public/site.webmanifest +1 -0
  233. package/dist/public/taskforce.png +0 -0
  234. package/dist/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
  235. package/dist/resources/templates/environments/aider.yaml +14 -0
  236. package/dist/resources/templates/environments/antigravity.yaml +10 -0
  237. package/dist/resources/templates/environments/claude.yaml +10 -0
  238. package/dist/resources/templates/environments/cline.yaml +10 -0
  239. package/dist/resources/templates/environments/codex.yaml +13 -0
  240. package/dist/resources/templates/environments/copilot.yaml +10 -0
  241. package/dist/resources/templates/environments/cursor.yaml +9 -0
  242. package/dist/resources/templates/environments/gemini.yaml +9 -0
  243. package/dist/resources/templates/environments/windsurf.yaml +10 -0
  244. package/dist/resources/templates/workflow-sources/README.md +9 -0
  245. package/dist/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
  246. package/dist/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
  247. package/dist/resources/templates/workflows/collaborate.yaml +104 -0
  248. package/dist/resources/templates/workflows/do.yaml +82 -0
  249. package/dist/resources/templates/workflows/evaluate.yaml +111 -0
  250. package/dist/resources/templates/workflows/execute.yaml +142 -0
  251. package/dist/resources/templates/workflows/plan.yaml +112 -0
  252. package/dist/resources/templates/workflows/review.yaml +109 -0
  253. package/dist/runtime/capabilities.d.ts +8 -0
  254. package/dist/runtime/capabilities.js +16 -0
  255. package/dist/security/virusScan.d.ts +16 -0
  256. package/dist/security/virusScan.js +83 -0
  257. package/dist/server/auth.d.ts +51 -0
  258. package/dist/server/auth.js +266 -0
  259. package/dist/server/auth.test.d.ts +1 -0
  260. package/dist/server/auth.test.js +111 -0
  261. package/dist/server/buildInfo.d.ts +7 -0
  262. package/dist/server/buildInfo.js +100 -0
  263. package/dist/server/buildInfo.test.d.ts +1 -0
  264. package/dist/server/buildInfo.test.js +29 -0
  265. package/dist/server/cors.d.ts +7 -0
  266. package/dist/server/cors.js +76 -0
  267. package/dist/server/cors.test.d.ts +1 -0
  268. package/dist/server/cors.test.js +71 -0
  269. package/dist/server/email.d.ts +28 -0
  270. package/dist/server/email.js +138 -0
  271. package/dist/server/email.test.d.ts +1 -0
  272. package/dist/server/email.test.js +113 -0
  273. package/dist/server/index.cookieProxy.test.d.ts +1 -0
  274. package/dist/server/index.cookieProxy.test.js +19 -0
  275. package/dist/server/index.d.ts +17 -0
  276. package/dist/server/index.js +757 -0
  277. package/dist/server/index.rateLimit.test.d.ts +1 -0
  278. package/dist/server/index.rateLimit.test.js +13 -0
  279. package/dist/server/index.test.d.ts +1 -0
  280. package/dist/server/index.test.js +19 -0
  281. package/dist/server/rateLimit.d.ts +29 -0
  282. package/dist/server/rateLimit.js +99 -0
  283. package/dist/server/rateLimit.test.d.ts +1 -0
  284. package/dist/server/rateLimit.test.js +107 -0
  285. package/dist/server/realtimeSync.auth.test.d.ts +1 -0
  286. package/dist/server/realtimeSync.auth.test.js +62 -0
  287. package/dist/server/realtimeSync.replay.test.d.ts +1 -0
  288. package/dist/server/realtimeSync.replay.test.js +192 -0
  289. package/dist/server/realtimeSync.workspaceIsolation.test.d.ts +1 -0
  290. package/dist/server/realtimeSync.workspaceIsolation.test.js +101 -0
  291. package/dist/server/realtimeSyncWs.d.ts +30 -0
  292. package/dist/server/realtimeSyncWs.js +257 -0
  293. package/dist/server/routes.billing.d.ts +15 -0
  294. package/dist/server/routes.billing.js +991 -0
  295. package/dist/server/routes.billing.test.d.ts +1 -0
  296. package/dist/server/routes.billing.test.js +387 -0
  297. package/dist/server/routes.d.ts +72 -0
  298. package/dist/server/routes.js +4820 -0
  299. package/dist/server/routes.sync.d.ts +17 -0
  300. package/dist/server/routes.sync.integration.test.d.ts +1 -0
  301. package/dist/server/routes.sync.integration.test.js +470 -0
  302. package/dist/server/routes.sync.js +1141 -0
  303. package/dist/server/routes.test.d.ts +1 -0
  304. package/dist/server/routes.test.js +4945 -0
  305. package/dist/server/runtimeMode.d.ts +4 -0
  306. package/dist/server/runtimeMode.js +25 -0
  307. package/dist/server/runtimeMode.test.d.ts +1 -0
  308. package/dist/server/runtimeMode.test.js +26 -0
  309. package/dist/server/securityHeaders.d.ts +3 -0
  310. package/dist/server/securityHeaders.js +25 -0
  311. package/dist/server/securityHeaders.test.d.ts +1 -0
  312. package/dist/server/securityHeaders.test.js +32 -0
  313. package/dist/server/smtpTransport.d.ts +21 -0
  314. package/dist/server/smtpTransport.js +11 -0
  315. package/dist/server/start.d.ts +1 -0
  316. package/dist/server/start.js +17 -0
  317. package/dist/services/formatTransformers.d.ts +29 -0
  318. package/dist/services/formatTransformers.js +56 -0
  319. package/dist/services/templateEngine.d.ts +46 -0
  320. package/dist/services/templateEngine.js +148 -0
  321. package/dist/shared/runtimeContract.d.ts +12 -0
  322. package/dist/shared/runtimeContract.js +23 -0
  323. package/dist/shared/runtimeContract.test.d.ts +1 -0
  324. package/dist/shared/runtimeContract.test.js +23 -0
  325. package/dist/soak/preflight.cli.d.ts +1 -0
  326. package/dist/soak/preflight.cli.js +28 -0
  327. package/dist/soak/preflight.d.ts +26 -0
  328. package/dist/soak/preflight.js +113 -0
  329. package/dist/soak/preflight.test.d.ts +1 -0
  330. package/dist/soak/preflight.test.js +39 -0
  331. package/dist/soak/syncSoakHarness.d.ts +6 -0
  332. package/dist/soak/syncSoakHarness.js +10 -0
  333. package/dist/storage/createDatabaseAdapter.d.ts +2 -0
  334. package/dist/storage/createDatabaseAdapter.js +9 -0
  335. package/dist/storage/databaseAdapter.d.ts +22 -0
  336. package/dist/storage/databaseAdapter.js +1 -0
  337. package/dist/storage/documentIntegrity.d.ts +28 -0
  338. package/dist/storage/documentIntegrity.js +103 -0
  339. package/dist/storage/documentPurge.d.ts +14 -0
  340. package/dist/storage/documentPurge.js +46 -0
  341. package/dist/storage/documentRegistry.d.ts +39 -0
  342. package/dist/storage/documentRegistry.js +115 -0
  343. package/dist/storage/integritySchedule.d.ts +17 -0
  344. package/dist/storage/integritySchedule.js +62 -0
  345. package/dist/storage/objectStorage.d.ts +20 -0
  346. package/dist/storage/objectStorage.js +15 -0
  347. package/dist/storage/objectStorageClient.d.ts +18 -0
  348. package/dist/storage/objectStorageClient.js +301 -0
  349. package/dist/storage/objectStorageConfig.d.ts +2 -0
  350. package/dist/storage/objectStorageConfig.js +45 -0
  351. package/dist/storage/postgresAdapter.d.ts +20 -0
  352. package/dist/storage/postgresAdapter.js +204 -0
  353. package/dist/storage/postgresWorker.d.ts +1 -0
  354. package/dist/storage/postgresWorker.js +110 -0
  355. package/dist/storage/providerConfig.d.ts +6 -0
  356. package/dist/storage/providerConfig.js +11 -0
  357. package/dist/storage/sqliteAdapter.d.ts +14 -0
  358. package/dist/storage/sqliteAdapter.js +28 -0
  359. package/dist/storage/taskAssetStore.d.ts +56 -0
  360. package/dist/storage/taskAssetStore.js +297 -0
  361. package/dist/sync/cloudSyncApi.d.ts +47 -0
  362. package/dist/sync/cloudSyncApi.js +138 -0
  363. package/dist/sync/cloudSyncApi.test.d.ts +1 -0
  364. package/dist/sync/cloudSyncApi.test.js +54 -0
  365. package/dist/sync/encryptionService.d.ts +11 -0
  366. package/dist/sync/encryptionService.js +61 -0
  367. package/dist/sync/encryptionService.test.d.ts +1 -0
  368. package/dist/sync/encryptionService.test.js +52 -0
  369. package/dist/sync/realtimeFeature.d.ts +6 -0
  370. package/dist/sync/realtimeFeature.js +20 -0
  371. package/dist/sync/realtimeFeature.test.d.ts +1 -0
  372. package/dist/sync/realtimeFeature.test.js +30 -0
  373. package/dist/sync/realtimeReconcile.d.ts +30 -0
  374. package/dist/sync/realtimeReconcile.js +90 -0
  375. package/dist/sync/realtimeReconcile.test.d.ts +1 -0
  376. package/dist/sync/realtimeReconcile.test.js +43 -0
  377. package/dist/sync/syncService.d.ts +96 -0
  378. package/dist/sync/syncService.js +423 -0
  379. package/dist/sync/syncService.test.d.ts +1 -0
  380. package/dist/sync/syncService.test.js +484 -0
  381. package/dist/sync/workspaceSyncModel.d.ts +61 -0
  382. package/dist/sync/workspaceSyncModel.js +136 -0
  383. package/dist/sync/workspaceSyncModel.test.d.ts +1 -0
  384. package/dist/sync/workspaceSyncModel.test.js +73 -0
  385. package/dist/test/setup.d.ts +1 -0
  386. package/dist/test/setup.js +15 -0
  387. package/dist/types.d.ts +157 -0
  388. package/dist/types.js +41 -0
  389. package/dist/ui/assets/RussoOne-Regular-C3BxZIj7.ttf +0 -0
  390. package/dist/ui/assets/index-0W5vyCpn.css +1 -0
  391. package/dist/ui/assets/index-MCZuNNfn.js +23 -0
  392. package/dist/ui/assets/logo_white_01-0Vx-iIIv.png +0 -0
  393. package/dist/ui/assets/taskforce-BxLPokNB.png +0 -0
  394. package/dist/ui/assets/vendor-dnd-BI1K77C1.js +5 -0
  395. package/dist/ui/assets/vendor-icons-ZFG3SGwo.js +1 -0
  396. package/dist/ui/assets/vendor-markdown-CKYkQHfj.js +29 -0
  397. package/dist/ui/assets/vendor-react-DdIDsh7f.js +9 -0
  398. package/dist/ui/assets/vendor-router-BtiNU7Dl.js +3 -0
  399. package/dist/ui/branding/logos/logo_black_01.png +0 -0
  400. package/dist/ui/branding/logos/logo_black_02.png +0 -0
  401. package/dist/ui/branding/logos/logo_white_01.png +0 -0
  402. package/dist/ui/branding/logos/logo_white_02.png +0 -0
  403. package/dist/ui/favicon/android-chrome-192x192.png +0 -0
  404. package/dist/ui/favicon/android-chrome-512x512.png +0 -0
  405. package/dist/ui/favicon/apple-touch-icon.png +0 -0
  406. package/dist/ui/favicon/favicon-16x16.png +0 -0
  407. package/dist/ui/favicon/favicon-32x32.png +0 -0
  408. package/dist/ui/favicon/favicon.ico +0 -0
  409. package/dist/ui/favicon/favicon.png +0 -0
  410. package/dist/ui/favicon/site.webmanifest +1 -0
  411. package/dist/ui/fonts/RussoOne-Regular.ttf +0 -0
  412. package/dist/ui/images/taskforce.png +0 -0
  413. package/dist/ui/index.html +19 -0
  414. package/dist/utils/checklistMarkdown.d.ts +9 -0
  415. package/dist/utils/checklistMarkdown.js +46 -0
  416. package/dist/utils/constants.d.ts +21 -0
  417. package/dist/utils/constants.icons.test.d.ts +1 -0
  418. package/dist/utils/constants.icons.test.js +40 -0
  419. package/dist/utils/constants.js +100 -0
  420. package/dist/utils/contextFiles.d.ts +8 -0
  421. package/dist/utils/contextFiles.js +54 -0
  422. package/dist/utils/formatting.d.ts +5 -0
  423. package/dist/utils/formatting.js +30 -0
  424. package/dist/utils/planParser.d.ts +22 -0
  425. package/dist/utils/planParser.js +151 -0
  426. package/dist/utils/taskDragZones.d.ts +8 -0
  427. package/dist/utils/taskDragZones.js +14 -0
  428. package/dist/utils/taskDragZones.test.d.ts +1 -0
  429. package/dist/utils/taskDragZones.test.js +14 -0
  430. package/dist/utils/taskHierarchy.d.ts +4 -0
  431. package/dist/utils/taskHierarchy.js +69 -0
  432. package/dist/utils/taskHierarchy.test.d.ts +1 -0
  433. package/dist/utils/taskHierarchy.test.js +38 -0
  434. package/dist/utils/taskParenting.d.ts +3 -0
  435. package/dist/utils/taskParenting.js +24 -0
  436. package/dist/utils/taskParenting.test.d.ts +1 -0
  437. package/dist/utils/taskParenting.test.js +21 -0
  438. package/dist/utils/taskRelations.d.ts +6 -0
  439. package/dist/utils/taskRelations.js +24 -0
  440. package/dist/utils/taskRelations.test.d.ts +1 -0
  441. package/dist/utils/taskRelations.test.js +34 -0
  442. package/dist/utils/taskUtils.d.ts +2 -0
  443. package/dist/utils/taskUtils.js +20 -0
  444. package/dist/utils/taskforceApiClient.d.ts +7 -0
  445. package/dist/utils/taskforceApiClient.js +42 -0
  446. package/dist/utils/workspaceIdentity.d.ts +8 -0
  447. package/dist/utils/workspaceIdentity.js +47 -0
  448. package/dist/utils/workspaceIdentity.test.d.ts +1 -0
  449. package/dist/utils/workspaceIdentity.test.js +32 -0
  450. package/dist/utils/workspaceLifecycle.d.ts +26 -0
  451. package/dist/utils/workspaceLifecycle.js +69 -0
  452. package/dist/utils/workspaceLifecycle.test.d.ts +1 -0
  453. package/dist/utils/workspaceLifecycle.test.js +64 -0
  454. package/package.json +133 -0
  455. package/scripts/check-compat-boundaries.js +48 -0
  456. package/scripts/check-env.ts +24 -0
  457. package/scripts/check-localization-strings.mjs +49 -0
  458. package/scripts/check-runtime-boundaries.mjs +44 -0
  459. package/scripts/debug-global.mjs +34 -0
  460. package/scripts/debug-server.mjs +36 -0
  461. package/scripts/export-sqlite-to-postgres.mjs +125 -0
  462. package/scripts/generate-env-example.ts +8 -0
  463. package/scripts/generate-workflow-templates.mjs +134 -0
  464. package/scripts/mcp-stdio-adapter.mjs +160 -0
  465. package/scripts/postinstall.js +60 -0
  466. package/scripts/release-version-lib.mjs +88 -0
  467. package/scripts/release-version.mjs +72 -0
  468. package/scripts/run-dev-proxy.sh +49 -0
  469. package/scripts/run-e2e-realtime.sh +16 -0
  470. package/scripts/run-smoke.sh +23 -0
  471. package/scripts/run-soak.sh +29 -0
  472. package/scripts/test-global.js +143 -0
  473. package/scripts/update-homebrew-formula.sh +38 -0
  474. package/src/resources/templates/WORKFLOW_V2_POLICY.md +55 -0
  475. package/src/resources/templates/environments/aider.yaml +14 -0
  476. package/src/resources/templates/environments/antigravity.yaml +10 -0
  477. package/src/resources/templates/environments/claude.yaml +10 -0
  478. package/src/resources/templates/environments/cline.yaml +10 -0
  479. package/src/resources/templates/environments/codex.yaml +13 -0
  480. package/src/resources/templates/environments/copilot.yaml +10 -0
  481. package/src/resources/templates/environments/cursor.yaml +9 -0
  482. package/src/resources/templates/environments/gemini.yaml +9 -0
  483. package/src/resources/templates/environments/windsurf.yaml +10 -0
  484. package/src/resources/templates/workflow-sources/README.md +9 -0
  485. package/src/resources/templates/workflow-sources/workflowDocs.mjs +520 -0
  486. package/src/resources/templates/workflow-sources/workflowEditorOverrides.json +1 -0
  487. package/src/resources/templates/workflows/collaborate.yaml +104 -0
  488. package/src/resources/templates/workflows/do.yaml +82 -0
  489. package/src/resources/templates/workflows/evaluate.yaml +111 -0
  490. package/src/resources/templates/workflows/execute.yaml +142 -0
  491. package/src/resources/templates/workflows/plan.yaml +112 -0
  492. package/src/resources/templates/workflows/review.yaml +109 -0
@@ -0,0 +1,80 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import yaml from 'js-yaml';
5
+ const WORKFLOW_DIR = path.resolve(process.cwd(), 'src/resources/templates/workflows');
6
+ const semverLike = (value) => /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/.test(value);
7
+ describe('Workflow v2 policy', () => {
8
+ const files = fs.readdirSync(WORKFLOW_DIR).filter((f) => f.endsWith('.yaml'));
9
+ const docs = files.map((file) => {
10
+ const full = path.join(WORKFLOW_DIR, file);
11
+ const parsed = yaml.load(fs.readFileSync(full, 'utf8'));
12
+ return { file, parsed };
13
+ });
14
+ it('all workflows are v2 with required top-level policy blocks', () => {
15
+ for (const { file, parsed } of docs) {
16
+ expect(parsed.version, `${file} should be version 2`).toBe(2);
17
+ expect(parsed.type, `${file} should be workflow type`).toBe('workflow');
18
+ expect(parsed.dispatch, `${file} missing dispatch`).toBeTruthy();
19
+ expect(parsed.compat, `${file} missing compat`).toBeTruthy();
20
+ expect(parsed.toolPolicy, `${file} missing toolPolicy`).toBeTruthy();
21
+ expect(parsed.contextPolicy, `${file} missing contextPolicy`).toBeTruthy();
22
+ expect(parsed.content?.default, `${file} missing content.default`).toBeTruthy();
23
+ }
24
+ });
25
+ it('uses semver-like minTaskforceVersion', () => {
26
+ for (const { file, parsed } of docs) {
27
+ const version = parsed.compat?.minTaskforceVersion || '';
28
+ expect(semverLike(version), `${file} has invalid minTaskforceVersion: ${version}`).toBe(true);
29
+ }
30
+ });
31
+ it('splits required tools into critical and optional lists', () => {
32
+ for (const { file, parsed } of docs) {
33
+ const critical = parsed.compat?.requiredToolsCritical || [];
34
+ const optional = parsed.compat?.requiredToolsOptional || [];
35
+ expect(Array.isArray(critical), `${file} missing requiredToolsCritical`).toBe(true);
36
+ expect(Array.isArray(optional), `${file} missing requiredToolsOptional`).toBe(true);
37
+ expect(critical.length > 0, `${file} requiredToolsCritical should not be empty`).toBe(true);
38
+ expect(new Set(critical).size === critical.length, `${file} requiredToolsCritical has duplicates`).toBe(true);
39
+ expect(new Set(optional).size === optional.length, `${file} requiredToolsOptional has duplicates`).toBe(true);
40
+ for (const tool of critical) {
41
+ expect(optional.includes(tool), `${file} tool listed as both critical and optional: ${tool}`).toBe(false);
42
+ }
43
+ }
44
+ });
45
+ it('enforces requiredToolsPolicy and status safety defaults', () => {
46
+ for (const { file, parsed } of docs) {
47
+ expect(parsed.toolPolicy?.requiredToolsPolicy?.critical, `${file} critical policy`).toBe('strict-fail');
48
+ expect(parsed.toolPolicy?.requiredToolsPolicy?.nonCritical, `${file} nonCritical policy`).toBe('warn-and-fallback');
49
+ expect(parsed.toolPolicy?.statusTransitions?.allowedStatuses).toEqual(expect.arrayContaining(['task', 'on-hold', 'in-progress', 'review']));
50
+ expect(parsed.toolPolicy?.statusTransitions?.forbiddenStatuses).toEqual(expect.arrayContaining(['done', 'cancelled']));
51
+ }
52
+ });
53
+ it('uses explicit MCP unavailable action', () => {
54
+ for (const { file, parsed } of docs) {
55
+ expect(parsed.contextPolicy?.mcpUnavailableAction, `${file} missing mcpUnavailableAction`).toBeTruthy();
56
+ }
57
+ });
58
+ it('keeps artifact paths project-root-relative', () => {
59
+ for (const { file, parsed } of docs) {
60
+ const artifacts = parsed.artifacts || {};
61
+ for (const [artifactName, def] of Object.entries(artifacts)) {
62
+ expect(path.isAbsolute(def.path), `${file} ${artifactName} path must be relative`).toBe(false);
63
+ expect(def.path.includes('..'), `${file} ${artifactName} path must not escape project root`).toBe(false);
64
+ }
65
+ }
66
+ });
67
+ it('defines global approach routing in do workflow', () => {
68
+ const doDoc = docs.find((d) => d.parsed.name === 'do');
69
+ expect(doDoc, 'do workflow is missing').toBeTruthy();
70
+ expect(doDoc?.parsed.dispatch?.routeByApproach).toBe(true);
71
+ expect(doDoc?.parsed.dispatch?.approachMap).toEqual(expect.objectContaining({
72
+ evaluate: 'evaluate',
73
+ collaborate: 'collaborate',
74
+ plan: 'plan',
75
+ review: 'review',
76
+ implement: 'execute'
77
+ }));
78
+ expect(doDoc?.parsed.dispatch?.default).toBe('execute');
79
+ });
80
+ });
package/dist/api.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Taskforce Manager - API Client
3
+ *
4
+ * Backend-first API helpers.
5
+ */
6
+ import type { TaskItem } from './types';
7
+ /**
8
+ * Submit a task item to the backend
9
+ */
10
+ export declare function submitTask(task: Omit<TaskItem, 'id' | 'completedAt'>, apiEndpoint: string): Promise<{
11
+ success: boolean;
12
+ fallback?: boolean;
13
+ error?: string;
14
+ }>;
15
+ /**
16
+ * Pending queue is deprecated; returns empty for compatibility.
17
+ */
18
+ export declare function getPendingTasks(): TaskItem[];
19
+ /**
20
+ * Pending queue is deprecated; no-op for compatibility.
21
+ */
22
+ export declare function clearPendingTasks(): void;
23
+ /**
24
+ * Export pending tasks as markdown string
25
+ */
26
+ export declare function exportTasksAsMarkdown(): string;
27
+ /**
28
+ * Copy pending tasks to clipboard as markdown
29
+ */
30
+ export declare function copyTasksToClipboard(): Promise<boolean>;
package/dist/api.js ADDED
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Taskforce Manager - API Client
3
+ *
4
+ * Backend-first API helpers.
5
+ */
6
+ /**
7
+ * Submit a task item to the backend
8
+ */
9
+ export async function submitTask(task, apiEndpoint) {
10
+ const taskWithId = {
11
+ ...task,
12
+ id: crypto.randomUUID(),
13
+ };
14
+ try {
15
+ const response = await fetch(apiEndpoint, {
16
+ method: 'POST',
17
+ headers: {
18
+ 'Content-Type': 'application/json',
19
+ },
20
+ body: JSON.stringify(taskWithId),
21
+ });
22
+ if (!response.ok) {
23
+ throw new Error(`HTTP ${response.status}`);
24
+ }
25
+ return { success: true };
26
+ }
27
+ catch (error) {
28
+ return { success: false, error: error?.message || 'Network error' };
29
+ }
30
+ }
31
+ /**
32
+ * Pending queue is deprecated; returns empty for compatibility.
33
+ */
34
+ export function getPendingTasks() {
35
+ return [];
36
+ }
37
+ /**
38
+ * Pending queue is deprecated; no-op for compatibility.
39
+ */
40
+ export function clearPendingTasks() {
41
+ // no-op
42
+ }
43
+ /**
44
+ * Export pending tasks as markdown string
45
+ */
46
+ export function exportTasksAsMarkdown() {
47
+ const tasks = getPendingTasks();
48
+ if (tasks.length === 0)
49
+ return '';
50
+ const grouped = tasks.reduce((acc, task) => {
51
+ if (!acc[task.category])
52
+ acc[task.category] = [];
53
+ acc[task.category].push(task);
54
+ return acc;
55
+ }, {});
56
+ let markdown = '# Pending Taskforce Tasks\n\n';
57
+ for (const [category, items] of Object.entries(grouped)) {
58
+ markdown += `## ${category}\n\n`;
59
+ for (const item of items) {
60
+ const checkbox = item.completedAt ? '[x]' : '[ ]';
61
+ const priority = String(item.priority);
62
+ markdown += `- ${checkbox} **${item.title}** [P${priority}]\n`;
63
+ if (item.description) {
64
+ markdown += ` - ${item.description}\n`;
65
+ }
66
+ markdown += ` - Added: ${item.createdAt}\n\n`;
67
+ }
68
+ }
69
+ return markdown;
70
+ }
71
+ /**
72
+ * Copy pending tasks to clipboard as markdown
73
+ */
74
+ export async function copyTasksToClipboard() {
75
+ const markdown = exportTasksAsMarkdown();
76
+ if (!markdown)
77
+ return false;
78
+ try {
79
+ await navigator.clipboard.writeText(markdown);
80
+ return true;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+ import { exec } from 'child_process';
3
+ import { platform } from 'os';
4
+ import { readFileSync, existsSync, realpathSync } from 'fs';
5
+ import { join, dirname } from 'path';
6
+ /**
7
+ * Taskforce CLI
8
+ *
9
+ * Usage:
10
+ * npx taskforce open [port]
11
+ */
12
+ const args = process.argv.slice(2);
13
+ const command = args[0] || 'open';
14
+ function normalizeOpenEnvironmentPreset(raw) {
15
+ const normalized = String(raw || '').trim().toLowerCase();
16
+ if (normalized === 'production')
17
+ return 'production';
18
+ if (normalized === 'staging')
19
+ return 'staging';
20
+ if (normalized === 'performance')
21
+ return 'performance';
22
+ return null;
23
+ }
24
+ function parseOpenCommandOptions(argv) {
25
+ const fallbackPort = 5174;
26
+ const arg1 = String(argv[1] || '').trim();
27
+ const arg2 = String(argv[2] || '').trim();
28
+ if (!arg1)
29
+ return { preferredPort: fallbackPort, preset: null };
30
+ const arg1AsPort = parseInt(arg1, 10);
31
+ if (!isNaN(arg1AsPort)) {
32
+ return { preferredPort: arg1AsPort, preset: null };
33
+ }
34
+ const preset = normalizeOpenEnvironmentPreset(arg1);
35
+ if (!preset) {
36
+ console.error('\x1b[31m❌ Invalid open target.\x1b[0m Use a port or one of: production, staging, performance');
37
+ process.exit(1);
38
+ }
39
+ if (!arg2)
40
+ return { preferredPort: fallbackPort, preset };
41
+ const arg2AsPort = parseInt(arg2, 10);
42
+ if (isNaN(arg2AsPort)) {
43
+ console.error('\x1b[31m❌ Invalid port.\x1b[0m Example: taskforce open staging 5178');
44
+ process.exit(1);
45
+ }
46
+ return { preferredPort: arg2AsPort, preset };
47
+ }
48
+ /**
49
+ * Find project root by traversing up to find package.json with taskforce
50
+ */
51
+ function findProjectRoot() {
52
+ let currentDir = process.cwd();
53
+ const root = dirname(currentDir);
54
+ let depth = 0;
55
+ while (currentDir !== root && depth < 10) {
56
+ const packageJsonPath = join(currentDir, 'package.json');
57
+ if (existsSync(packageJsonPath)) {
58
+ try {
59
+ const pkg = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
60
+ const hasDep = pkg.dependencies?.['@taskforcehq/taskforce'] || pkg.dependencies?.taskforce || pkg.dependencies?.Taskforce;
61
+ const hasDevDep = pkg.devDependencies?.['@taskforcehq/taskforce'] || pkg.devDependencies?.taskforce || pkg.devDependencies?.Taskforce;
62
+ const isSelf = pkg.name === '@taskforcehq/taskforce' || pkg.name === 'taskforce' || pkg.name === 'Taskforce';
63
+ if (hasDep || hasDevDep || isSelf) {
64
+ try {
65
+ return realpathSync(currentDir);
66
+ }
67
+ catch {
68
+ return currentDir;
69
+ }
70
+ }
71
+ }
72
+ catch (e) {
73
+ // Invalid package.json, continue searching
74
+ }
75
+ }
76
+ currentDir = dirname(currentDir);
77
+ depth++;
78
+ }
79
+ return null;
80
+ }
81
+ /**
82
+ * Open browser to the given URL
83
+ */
84
+ function openBrowser(url) {
85
+ const browserEnv = String(process.env.BROWSER || '').trim().toLowerCase();
86
+ if (browserEnv === 'none' || browserEnv === 'false' || browserEnv === '0') {
87
+ console.log('\x1b[36m[Taskforce] Browser auto-open disabled by BROWSER env\x1b[0m');
88
+ return;
89
+ }
90
+ const start = (platform() === 'darwin' ? 'open' : platform() === 'win32' ? 'start' : 'xdg-open');
91
+ exec(`${start} ${url}`);
92
+ }
93
+ /**
94
+ * Main CLI logic
95
+ */
96
+ async function main() {
97
+ if (command === 'help' || (command !== 'open' && command !== 'mcp')) {
98
+ console.log('\x1b[35mTaskforce CLI\x1b[0m');
99
+ console.log('\nUsage:');
100
+ console.log(' taskforce <command> [options]');
101
+ console.log('\nAvailable commands:');
102
+ console.log(' open [port] - Starts Taskforce on an unused port and opens it (default start port 5174)');
103
+ console.log(' open <production|staging|performance> [port] - Starts Taskforce with preset cloud endpoints');
104
+ console.log(' mcp [path] - Starts the Model Context Protocol (MCP) server for the specified project');
105
+ console.log(' help - Shows this help message');
106
+ return;
107
+ }
108
+ // 1. Handle MCP Command
109
+ if (command === 'mcp') {
110
+ const projectPath = args[1] || process.cwd();
111
+ // Set the path in argv so the mcp server can pick it up
112
+ process.argv[2] = projectPath;
113
+ try {
114
+ console.error(`\x1b[32m✓ Starting Taskforce MCP server for ${projectPath}\x1b[0m`);
115
+ // Import the MCP server - it will start automatically via its top-level await
116
+ await import('./mcp/server.js');
117
+ }
118
+ catch (e) {
119
+ console.error('\x1b[31m❌ Failed to start MCP server:\x1b[0m', e);
120
+ process.exit(1);
121
+ }
122
+ return;
123
+ }
124
+ // 2. Handle Open Command
125
+ const { preferredPort, preset: openPreset } = parseOpenCommandOptions(args);
126
+ // Check if Taskforce is installed in the project
127
+ let projectRoot = findProjectRoot();
128
+ if (!projectRoot) {
129
+ // Fallback to CWD for global/npx usage
130
+ // We don't exit anymore, enabling "npx taskforce open" or global install usage
131
+ projectRoot = process.cwd();
132
+ // Optional: warn if no package.json found at all?
133
+ // For now, silent fallback is better for "just works" experience
134
+ }
135
+ console.log(`\x1b[32m✓ Found Taskforce in ${projectRoot}\x1b[0m`);
136
+ // 2. Always start a new server on an unused port
137
+ console.log(`\x1b[36m✨ Starting Taskforce server on an unused port...\x1b[0m`);
138
+ try {
139
+ // Local CLI launches should default to local runtime unless explicitly overridden.
140
+ // This prevents ambient TASKFORCE_DB_PROVIDER=postgres from flipping runtime to cloud.
141
+ if (!process.env.TASKFORCE_RUNTIME_MODE) {
142
+ process.env.TASKFORCE_RUNTIME_MODE = 'local';
143
+ }
144
+ const hasExternalCloudEndpoint = Boolean(String(process.env.VITE_TASKFORCE_BASE_URL || '').trim()
145
+ || String(process.env.TASKFORCE_BASE_URL || '').trim()
146
+ || String(process.env.VITE_TASKFORCE_API_BASE_URL || '').trim()
147
+ || String(process.env.VITE_TASKFORCE_CLOUD_AUTH_BASE_URL || '').trim());
148
+ const effectivePreset = openPreset || (hasExternalCloudEndpoint ? null : 'production');
149
+ if (effectivePreset === 'production') {
150
+ process.env.VITE_TASKFORCE_BASE_URL = 'https://app.taskforcehq.ai';
151
+ process.env.VITE_TASKFORCE_API_BASE_URL = 'https://app.taskforcehq.ai';
152
+ process.env.VITE_TASKFORCE_CLOUD_AUTH_BASE_URL = 'https://app.taskforcehq.ai';
153
+ console.log('\x1b[36m[Taskforce] Using production cloud endpoint preset\x1b[0m');
154
+ }
155
+ else if (effectivePreset === 'staging') {
156
+ process.env.VITE_TASKFORCE_BASE_URL = 'https://staging-app.taskforcehq.ai';
157
+ process.env.VITE_TASKFORCE_API_BASE_URL = 'https://staging-app.taskforcehq.ai';
158
+ process.env.VITE_TASKFORCE_CLOUD_AUTH_BASE_URL = 'https://staging-app.taskforcehq.ai';
159
+ console.log('\x1b[36m[Taskforce] Using staging cloud endpoint preset\x1b[0m');
160
+ }
161
+ else if (effectivePreset === 'performance') {
162
+ process.env.VITE_TASKFORCE_BASE_URL = 'https://performance-app.taskforcehq.ai';
163
+ process.env.VITE_TASKFORCE_API_BASE_URL = 'https://performance-app.taskforcehq.ai';
164
+ process.env.VITE_TASKFORCE_CLOUD_AUTH_BASE_URL = 'https://performance-app.taskforcehq.ai';
165
+ console.log('\x1b[36m[Taskforce] Using performance cloud endpoint preset\x1b[0m');
166
+ }
167
+ else if (hasExternalCloudEndpoint) {
168
+ console.log('\x1b[36m[Taskforce] Using cloud endpoint from environment variables\x1b[0m');
169
+ }
170
+ const { createStandaloneServer } = await import('./server/index.js');
171
+ const { createServer } = await import('net');
172
+ /**
173
+ * Find a free port starting from preferredPort
174
+ */
175
+ const findPort = (port, maxPort) => {
176
+ return new Promise((resolve, reject) => {
177
+ const s = createServer();
178
+ s.on('error', (err) => {
179
+ const retryable = err?.code === 'EADDRINUSE' || err?.code === 'EACCES' || err?.code === 'EPERM';
180
+ if (retryable) {
181
+ if (port < maxPort) {
182
+ resolve(findPort(port + 1, maxPort));
183
+ }
184
+ else {
185
+ reject(new Error(`No available ports found between ${preferredPort} and ${maxPort}`));
186
+ }
187
+ }
188
+ else {
189
+ reject(err);
190
+ }
191
+ });
192
+ s.listen(port, () => {
193
+ s.close(() => resolve(port));
194
+ });
195
+ });
196
+ };
197
+ const targetPort = await findPort(preferredPort, preferredPort + 10);
198
+ const server = createStandaloneServer({
199
+ projectRoot,
200
+ port: targetPort
201
+ });
202
+ server.listen(targetPort, () => {
203
+ const url = `http://localhost:${targetPort}/taskforce/`;
204
+ console.log(`\x1b[32m✓ Server started on port ${targetPort}\x1b[0m`);
205
+ console.log(`\x1b[35m🚀 Opening ${url}...\x1b[0m`);
206
+ openBrowser(url);
207
+ });
208
+ }
209
+ catch (e) {
210
+ console.error('\x1b[31m❌ Failed to start server:\x1b[0m', e.message);
211
+ process.exit(1);
212
+ }
213
+ }
214
+ main().catch((err) => {
215
+ console.error('\x1b[31mError:\x1b[0m', err.message);
216
+ process.exit(1);
217
+ });
@@ -0,0 +1,2 @@
1
+ export declare const PRIORITY_LOGIC: Record<string, number>;
2
+ export declare function getLegacyPriorityClass(priority: string | number, fallbackLabel: string): string;
@@ -0,0 +1,24 @@
1
+ import { MIGRATION_COMPAT_ENABLED } from '../migrations/flags';
2
+ export const PRIORITY_LOGIC = {
3
+ 'on-hold': 1,
4
+ low: 1,
5
+ medium: 2,
6
+ high: 3,
7
+ critical: 4
8
+ };
9
+ const LEGACY_PRIORITY_CLASS_MAP = {
10
+ '0': 'low',
11
+ '1': 'low',
12
+ '2': 'medium',
13
+ '3': 'high',
14
+ '4': 'critical',
15
+ '5': 'critical'
16
+ };
17
+ export function getLegacyPriorityClass(priority, fallbackLabel) {
18
+ // COMPAT_REMOVE_AFTER: v1.0.0
19
+ // COMPAT_TRACK: priority-scale-0-to-4
20
+ if (!MIGRATION_COMPAT_ENABLED && Number(priority) === 0) {
21
+ return fallbackLabel;
22
+ }
23
+ return LEGACY_PRIORITY_CLASS_MAP[String(priority)] || fallbackLabel;
24
+ }
@@ -0,0 +1,9 @@
1
+ interface Props {
2
+ content: string;
3
+ docTitle: string;
4
+ apiBaseUrl?: string;
5
+ onClose: () => void;
6
+ onGenerated: (count: number) => void;
7
+ }
8
+ export declare function DocumentGenerateModal({ content, docTitle, apiBaseUrl, onClose, onGenerated }: Props): import("react/jsx-runtime").JSX.Element;
9
+ export {};
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useCallback, useEffect } from 'react';
3
+ import { Zap, ChevronRight, ChevronDown, CheckSquare, Square, X, Loader, CheckCircle, AlertCircle } from 'lucide-react';
4
+ import styles from '../../Taskforce.module.css';
5
+ import { fetchTaskforceApi } from '../../utils/taskforceApiClient';
6
+ const TYPE_COLORS = {
7
+ feature: '#a78bfa',
8
+ bug: '#f87171',
9
+ chore: '#94a3b8',
10
+ refactor: '#fbbf24',
11
+ documentation: '#34d399',
12
+ };
13
+ const PRIORITY_LABELS = { 1: 'Low', 2: 'Medium', 3: 'High', 4: 'Critical' };
14
+ const PRIORITY_COLORS = {
15
+ 1: '#64748b', 2: '#94a3b8', 3: '#f97316', 4: '#ef4444',
16
+ };
17
+ // ─── Task tree node (UI-mutable copy) ────────────────────────────────────────
18
+ function toggleAll(nodes, selected) {
19
+ return nodes.map(n => ({ ...n, selected, children: toggleAll(n.children, selected) }));
20
+ }
21
+ function toggleNode(nodes, key, selected) {
22
+ return nodes.map(n => {
23
+ if (n.idempotencyKey === key) {
24
+ return { ...n, selected, children: toggleAll(n.children, selected) };
25
+ }
26
+ return { ...n, children: toggleNode(n.children, key, selected) };
27
+ });
28
+ }
29
+ function countSelected(nodes) {
30
+ let count = 0;
31
+ for (const n of nodes) {
32
+ if (n.selected)
33
+ count++;
34
+ count += countSelected(n.children);
35
+ }
36
+ return count;
37
+ }
38
+ function TreeNode({ node, depth, onToggle }) {
39
+ const [expanded, setExpanded] = useState(true);
40
+ const hasChildren = node.children.length > 0;
41
+ const indentPx = depth * 20;
42
+ return (_jsxs("div", { children: [_jsxs("div", { className: `${styles.genTaskRow} ${!node.selected ? styles.genTaskRowDimmed : ''}`, style: { paddingLeft: `${12 + indentPx}px` }, children: [_jsx("button", { className: styles.genTaskCheck, onClick: () => onToggle(node.idempotencyKey, !node.selected), title: node.selected ? 'Deselect' : 'Select', children: node.selected
43
+ ? _jsx(CheckSquare, { size: 14, style: { color: '#a78bfa' } })
44
+ : _jsx(Square, { size: 14, style: { color: '#64748b' } }) }), hasChildren ? (_jsx("button", { className: styles.genTaskExpandBtn, onClick: () => setExpanded(e => !e), children: expanded ? _jsx(ChevronDown, { size: 12 }) : _jsx(ChevronRight, { size: 12 }) })) : (_jsx("span", { className: styles.genTaskExpandSpacer })), _jsx("span", { className: styles.genTaskTitle, title: node.description || undefined, children: node.title }), _jsx("span", { className: styles.genTaskBadge, style: { color: TYPE_COLORS[node.type] ?? '#a78bfa', borderColor: TYPE_COLORS[node.type] ?? '#a78bfa' }, children: node.type }), _jsx("span", { className: styles.genTaskBadge, style: { color: PRIORITY_COLORS[node.priority] ?? '#94a3b8', borderColor: PRIORITY_COLORS[node.priority] ?? '#94a3b8' }, children: PRIORITY_LABELS[node.priority] })] }), hasChildren && expanded && (_jsx("div", { children: node.children.map(child => (_jsx(TreeNode, { node: child, depth: depth + 1, onToggle: onToggle }, child.idempotencyKey))) }))] }));
45
+ }
46
+ // ─── Modal ────────────────────────────────────────────────────────────────────
47
+ export function DocumentGenerateModal({ content, docTitle, apiBaseUrl = '', onClose, onGenerated }) {
48
+ const [state, setState] = useState('preview');
49
+ const [loadError, setLoadError] = useState(null);
50
+ const [tasks, setTasks] = useState([]);
51
+ const [loading, setLoading] = useState(true);
52
+ const [generatedCount, setGeneratedCount] = useState(0);
53
+ const [genError, setGenError] = useState(null);
54
+ // Fetch preview on mount
55
+ useEffect(() => {
56
+ let cancelled = false;
57
+ setLoading(true);
58
+ setLoadError(null);
59
+ fetchTaskforceApi('/api/taskforce/documents/generate-tasks/preview', {
60
+ method: 'POST',
61
+ credentials: 'include',
62
+ headers: { 'Content-Type': 'application/json' },
63
+ body: JSON.stringify({ content }),
64
+ }, apiBaseUrl)
65
+ .then(r => r.json())
66
+ .then(data => {
67
+ if (cancelled)
68
+ return;
69
+ if (data.error)
70
+ throw new Error(data.error);
71
+ setTasks(data.tasks || []);
72
+ setState('preview');
73
+ })
74
+ .catch(e => {
75
+ if (cancelled)
76
+ return;
77
+ setLoadError(e?.message || 'Failed to parse plan');
78
+ setState('error');
79
+ })
80
+ .finally(() => { if (!cancelled)
81
+ setLoading(false); });
82
+ return () => { cancelled = true; };
83
+ }, [content, apiBaseUrl]);
84
+ const handleToggle = useCallback((key, selected) => {
85
+ setTasks(prev => toggleNode(prev, key, selected));
86
+ }, []);
87
+ const handleSelectAll = () => setTasks(prev => toggleAll(prev, true));
88
+ const handleSelectNone = () => setTasks(prev => toggleAll(prev, false));
89
+ const selectedCount = countSelected(tasks);
90
+ const handleGenerate = async () => {
91
+ setState('generating');
92
+ setGenError(null);
93
+ try {
94
+ const res = await fetchTaskforceApi('/api/taskforce/documents/generate-tasks/commit', {
95
+ method: 'POST',
96
+ credentials: 'include',
97
+ headers: { 'Content-Type': 'application/json' },
98
+ body: JSON.stringify({ tasks }),
99
+ }, apiBaseUrl);
100
+ const data = await res.json().catch(() => ({}));
101
+ if (!res.ok)
102
+ throw new Error(data.error || `Generation failed (${res.status})`);
103
+ setGeneratedCount(data.created ?? 0);
104
+ setState('done');
105
+ onGenerated(data.created ?? 0);
106
+ }
107
+ catch (e) {
108
+ setGenError(e?.message || 'Generation failed');
109
+ setState('error');
110
+ }
111
+ };
112
+ return (_jsx("div", { className: styles.genModalOverlay, onClick: e => { if (e.target === e.currentTarget)
113
+ onClose(); }, children: _jsxs("div", { className: styles.genModal, children: [_jsxs("div", { className: styles.genModalHeader, children: [_jsxs("div", { className: styles.genModalTitle, children: [_jsx(Zap, { size: 16, style: { color: '#a78bfa' } }), "Generate Tasks from Plan"] }), _jsx("span", { className: styles.genModalDocName, children: docTitle }), _jsx("button", { className: styles.genModalClose, onClick: onClose, title: "Close", children: _jsx(X, { size: 16 }) })] }), _jsxs("div", { className: styles.genModalBody, children: [loading && (_jsxs("div", { className: styles.genModalState, children: [_jsx(Loader, { size: 20, className: styles.docSpinning }), "Parsing plan\u2026"] })), !loading && state === 'error' && (_jsxs("div", { className: styles.genModalStateError, children: [_jsx(AlertCircle, { size: 16 }), loadError || genError || 'An error occurred'] })), !loading && state === 'done' && (_jsxs("div", { className: styles.genModalStateDone, children: [_jsx(CheckCircle, { size: 24, style: { color: '#4ade80' } }), _jsxs("strong", { children: [generatedCount, " task", generatedCount !== 1 ? 's' : '', " created"] }), _jsx("p", { children: "Tasks are now in your board. Switch to the Kanban or Hierarchy view to see them." })] })), !loading && (state === 'preview' || state === 'confirm' || state === 'generating') && (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.genToolbar, children: [_jsxs("span", { className: styles.genToolbarCount, children: [selectedCount, " of ", countSelected(toggleAll(tasks, true)), " tasks selected"] }), _jsx("button", { className: styles.genToolbarBtn, onClick: handleSelectAll, children: "Select all" }), _jsx("button", { className: styles.genToolbarBtn, onClick: handleSelectNone, children: "Deselect all" })] }), tasks.length === 0 ? (_jsx("div", { className: styles.genModalState, children: "No tasks could be parsed from this document. Make sure the document uses ## H2 headings for phases and bullet points for tasks." })) : (_jsx("div", { className: styles.genTaskTree, children: tasks.map(task => (_jsx(TreeNode, { node: task, depth: 0, onToggle: handleToggle }, task.idempotencyKey))) }))] }))] }), !loading && state !== 'done' && state !== 'error' && (_jsxs("div", { className: styles.genModalFooter, children: [_jsx("button", { className: styles.genCancelBtn, onClick: onClose, children: "Cancel" }), _jsx("button", { className: styles.genCommitBtn, onClick: handleGenerate, disabled: selectedCount === 0 || state === 'generating', children: state === 'generating' ? (_jsxs(_Fragment, { children: [_jsx(Loader, { size: 13, className: styles.docSpinning }), " Generating\u2026"] })) : (_jsxs(_Fragment, { children: [_jsx(Zap, { size: 13 }), " Generate ", selectedCount, " task", selectedCount !== 1 ? 's' : ''] })) })] })), !loading && state === 'done' && (_jsx("div", { className: styles.genModalFooter, children: _jsx("button", { className: styles.genCommitBtn, onClick: onClose, children: "Done" }) }))] }) }));
114
+ }
@@ -0,0 +1,19 @@
1
+ import type { DocMeta } from './DocumentWorkspace';
2
+ interface Props {
3
+ documents: DocMeta[];
4
+ selectedDocId: string | null;
5
+ loading: boolean;
6
+ error: string | null;
7
+ searchQuery: string;
8
+ typeFilter: DocMeta['docType'] | 'all';
9
+ taskById: Map<string, {
10
+ id: string;
11
+ title: string;
12
+ }>;
13
+ onSearchChange: (q: string) => void;
14
+ onTypeFilterChange: (t: DocMeta['docType'] | 'all') => void;
15
+ onSelect: (doc: DocMeta) => void;
16
+ onRefresh: () => void;
17
+ }
18
+ export declare function DocumentIndex({ documents, selectedDocId, loading, error, searchQuery, typeFilter, taskById, onSearchChange, onTypeFilterChange, onSelect, onRefresh, }: Props): import("react/jsx-runtime").JSX.Element;
19
+ export {};
@@ -0,0 +1,51 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { Search, RefreshCw, FileText, ClipboardList, Eye, BookOpen, File } from 'lucide-react';
3
+ import styles from '../../Taskforce.module.css';
4
+ const DOC_TYPE_OPTIONS = [
5
+ { value: 'all', label: 'All' },
6
+ { value: 'implementation-plan', label: 'Plans' },
7
+ { value: 'review', label: 'Reviews' },
8
+ { value: 'walkthrough', label: 'Walkthroughs' },
9
+ { value: 'other', label: 'Other' },
10
+ ];
11
+ function DocTypeIcon({ docType }) {
12
+ switch (docType) {
13
+ case 'implementation-plan': return _jsx(ClipboardList, { size: 13 });
14
+ case 'review': return _jsx(Eye, { size: 13 });
15
+ case 'walkthrough': return _jsx(BookOpen, { size: 13 });
16
+ default: return _jsx(File, { size: 13 });
17
+ }
18
+ }
19
+ function formatFileSize(bytes) {
20
+ if (bytes < 1024)
21
+ return `${bytes}B`;
22
+ if (bytes < 1024 * 1024)
23
+ return `${(bytes / 1024).toFixed(1)}KB`;
24
+ return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;
25
+ }
26
+ function formatRelativeDate(isoDate) {
27
+ if (!isoDate)
28
+ return '';
29
+ const d = new Date(isoDate);
30
+ const now = new Date();
31
+ const diffMs = now.getTime() - d.getTime();
32
+ const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
33
+ if (diffDays === 0)
34
+ return 'Today';
35
+ if (diffDays === 1)
36
+ return 'Yesterday';
37
+ if (diffDays < 7)
38
+ return `${diffDays}d ago`;
39
+ if (diffDays < 30)
40
+ return `${Math.floor(diffDays / 7)}w ago`;
41
+ return d.toLocaleDateString();
42
+ }
43
+ export function DocumentIndex({ documents, selectedDocId, loading, error, searchQuery, typeFilter, taskById, onSearchChange, onTypeFilterChange, onSelect, onRefresh, }) {
44
+ return (_jsxs("div", { className: styles.docIndex, children: [_jsxs("div", { className: styles.docIndexHeader, children: [_jsxs("span", { className: styles.docIndexTitle, children: [_jsx(FileText, { size: 14 }), "Documents"] }), _jsx("button", { className: styles.docIndexRefreshBtn, onClick: onRefresh, title: "Refresh document list", disabled: loading, children: _jsx(RefreshCw, { size: 13, className: loading ? styles.docSpinning : undefined }) })] }), _jsxs("div", { className: styles.docIndexSearch, children: [_jsx(Search, { size: 12, className: styles.docIndexSearchIcon }), _jsx("input", { type: "text", placeholder: "Search documents\u2026", value: searchQuery, onChange: e => onSearchChange(e.target.value), className: styles.docIndexSearchInput })] }), _jsx("div", { className: styles.docIndexFilters, children: DOC_TYPE_OPTIONS.map(opt => (_jsx("button", { className: `${styles.docIndexFilterBtn} ${typeFilter === opt.value ? styles.docIndexFilterBtnActive : ''}`, onClick: () => onTypeFilterChange(opt.value), children: opt.label }, opt.value))) }), _jsxs("div", { className: styles.docIndexList, children: [loading && (_jsx("div", { className: styles.docIndexState, children: "Loading documents\u2026" })), !loading && error && (_jsx("div", { className: styles.docIndexStateError, children: error })), !loading && !error && documents.length === 0 && (_jsx("div", { className: styles.docIndexState, children: searchQuery || typeFilter !== 'all'
45
+ ? 'No documents match your filters.'
46
+ : 'No documents found. Documents added as task attachments will appear here.' })), !loading && documents.map(doc => {
47
+ const task = doc.taskId ? taskById.get(doc.taskId) : null;
48
+ const isSelected = doc.id === selectedDocId;
49
+ return (_jsxs("button", { className: `${styles.docIndexItem} ${isSelected ? styles.docIndexItemActive : ''}`, onClick: () => onSelect(doc), children: [_jsx("div", { className: styles.docIndexItemIcon, children: _jsx(DocTypeIcon, { docType: doc.docType }) }), _jsxs("div", { className: styles.docIndexItemBody, children: [_jsx("span", { className: styles.docIndexItemTitle, children: doc.title }), task && (_jsx("span", { className: styles.docIndexItemTask, children: task.title })), _jsxs("span", { className: styles.docIndexItemMeta, children: [formatFileSize(doc.sizeBytes), doc.updatedAt && _jsxs(_Fragment, { children: [" \u00B7 ", formatRelativeDate(doc.updatedAt)] })] })] })] }, doc.id));
50
+ })] })] }));
51
+ }
@@ -0,0 +1,9 @@
1
+ import type { DocMeta } from './DocumentWorkspace';
2
+ interface Props {
3
+ doc: DocMeta;
4
+ taskTitle: string | null;
5
+ apiBaseUrl?: string;
6
+ onSaved?: (updatedAt: string) => void;
7
+ }
8
+ export declare function DocumentViewer({ doc, taskTitle, apiBaseUrl, onSaved }: Props): import("react/jsx-runtime").JSX.Element;
9
+ export {};