@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,47 @@
1
+ import React from 'react';
2
+ import type { TaskItem, TaxonomyDefinition, CategoryConfig } from '../../types';
3
+ interface TaskCardProps {
4
+ task: TaskItem;
5
+ searchQuery?: string;
6
+ copiedId?: string | null;
7
+ availableSpecialists?: {
8
+ value: string;
9
+ label: string;
10
+ }[];
11
+ taxonomies?: TaxonomyDefinition[];
12
+ priorities?: Array<{
13
+ value: number | string;
14
+ label: string;
15
+ color?: string;
16
+ icon?: string;
17
+ }>;
18
+ approaches?: Array<{
19
+ value: string;
20
+ label: string;
21
+ color?: string;
22
+ icon?: string;
23
+ }>;
24
+ categories?: CategoryConfig[];
25
+ isOverlay?: boolean;
26
+ isArchived?: boolean;
27
+ isRecentlyChanged?: boolean;
28
+ linkedParentIdSet?: Set<string>;
29
+ parentDropTargetId?: string | null;
30
+ onClick?: (task: TaskItem) => void;
31
+ onCopyId?: (e: React.MouseEvent, id: string) => void;
32
+ onToggleInProgress?: (task: TaskItem) => void;
33
+ onToggleReview?: (task: TaskItem) => void;
34
+ onToggleComplete?: (task: TaskItem) => void;
35
+ onToggleCancel?: (task: TaskItem) => void;
36
+ onArchiveTask?: (task: TaskItem) => void;
37
+ onUnarchive?: (taskId: string) => void;
38
+ onDelete?: (taskId: string) => void;
39
+ onUnlinkChildTask?: (taskId: string) => void;
40
+ onClearParentTask?: (taskId: string) => void;
41
+ onOpenTaskById?: (taskId: string) => void;
42
+ showParentRelationship?: boolean;
43
+ compressed?: boolean;
44
+ allTasks?: TaskItem[];
45
+ }
46
+ export declare const TaskCard: React.FC<TaskCardProps>;
47
+ export {};
@@ -0,0 +1,326 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import React from 'react';
3
+ import * as Icons from 'lucide-react';
4
+ const { Copy, Check, Play, Pause, Sparkles, Ban, Archive, MessageSquare, User, Layers, Bot, Gauge, X, ChevronDown, ChevronRight, ClipboardList, HelpCircle } = Icons;
5
+ import styles from '../../Taskforce.module.css';
6
+ import { Markdown } from '../ui/Markdown';
7
+ import { getIconForType, renderHighlighted } from '../../utils/taskUtils';
8
+ import { resolveColor, TypeMeta } from '../../utils/constants';
9
+ import { getLegacyPriorityClass } from '../../compat/priorityCompat';
10
+ import { sortChildTasksForDisplay } from '../../utils/taskRelations';
11
+ import { parseChecklistLines } from '../../utils/checklistMarkdown';
12
+ import { dispatchOpenMarkdownDocument } from '../../utils/contextFiles';
13
+ export const TaskCard = ({ task, searchQuery = '', copiedId = null, availableSpecialists = [], taxonomies = [], priorities = [], approaches = [], categories = [], isOverlay = false, isArchived = false, isRecentlyChanged = false, linkedParentIdSet, parentDropTargetId = null, onClick, onCopyId, onToggleInProgress, onToggleReview, onToggleComplete, onToggleCancel, onArchiveTask, onUnarchive, onDelete, onUnlinkChildTask, onClearParentTask, onOpenTaskById, showParentRelationship = true, compressed = false, allTasks = [] }) => {
14
+ const priorityConfig = priorities.find(p => String(p.value) === String(task.priority));
15
+ const priorityName = priorityConfig ? priorityConfig.label.toLowerCase().replace(/\s+/g, '-') : String(task.priority);
16
+ const categoryConfig = categories.find(c => c.value === task.category || c.label === task.category);
17
+ const rawComplexity = typeof task.complexity === 'number' ? task.complexity : Number(task.complexity ?? 3);
18
+ const normalizedComplexity = Number.isFinite(rawComplexity) ? Math.max(1, Math.min(5, Math.round(rawComplexity))) : 3;
19
+ const complexityLabels = {
20
+ 1: 'Tiny',
21
+ 2: 'Low',
22
+ 3: 'Mid',
23
+ 4: 'High',
24
+ 5: 'Epic'
25
+ };
26
+ const complexityKeys = {
27
+ 1: 'tiny',
28
+ 2: 'low',
29
+ 3: 'medium',
30
+ 4: 'high',
31
+ 5: 'epic'
32
+ };
33
+ const complexityLabel = complexityLabels[normalizedComplexity];
34
+ const complexityColor = `var(--complexity-${complexityKeys[normalizedComplexity]})`;
35
+ const displayPriority = getLegacyPriorityClass(task.priority, priorityName);
36
+ const hasLegacyClass = !!styles[`priorityItem_${displayPriority}`];
37
+ const showLinkedFeedback = !!linkedParentIdSet?.has(task.id);
38
+ const showDropTargetFeedback = parentDropTargetId === task.id;
39
+ const cardClasses = [
40
+ styles.taskItem,
41
+ task.status === 'in-progress' ? styles.inProgress : '',
42
+ task.status === 'review' ? styles.readyForReview : '',
43
+ task.status === 'done' ? styles.completed : '',
44
+ task.status === 'cancelled' ? styles.cancelled : '',
45
+ (isRecentlyChanged || showDropTargetFeedback) ? styles.taskItemRecentlyChanged : '',
46
+ showDropTargetFeedback ? styles.taskItemGlowPersistent : '',
47
+ styles[`priorityItem_${displayPriority}`] || '',
48
+ isOverlay ? styles.kanbanCardOverlay : '',
49
+ isArchived ? styles.archived : '',
50
+ compressed ? styles.compressed : ''
51
+ ].filter(Boolean).join(' ');
52
+ const priorityColor = resolveColor(priorityConfig?.color);
53
+ const typeMeta = TypeMeta[task.type?.toLowerCase()];
54
+ const typeColor = resolveColor(typeMeta?.color) || '#8b5cf6';
55
+ const isImagePath = (filePath) => /\.(png|jpe?g|webp|gif)(\?|#|$)/i.test(filePath);
56
+ const getContextName = (item) => {
57
+ const path = typeof item === 'string' ? item : item.path;
58
+ const caption = typeof item === 'string' ? '' : (item.caption || '').trim();
59
+ if (caption)
60
+ return caption;
61
+ const withoutQuery = path.split('?')[0].split('#')[0];
62
+ const filename = withoutQuery.split('/').pop();
63
+ return filename || 'Context file';
64
+ };
65
+ const getContextType = (item) => {
66
+ const sourcePath = typeof item === 'string' ? item : item.path;
67
+ const fsPath = typeof item === 'string' ? '' : (item.fsPath || '').trim();
68
+ const caption = typeof item === 'string' ? '' : (item.caption || '').trim();
69
+ const candidates = [];
70
+ if (fsPath)
71
+ candidates.push(fsPath);
72
+ if (caption)
73
+ candidates.push(caption);
74
+ if (sourcePath.includes('/api/taskforce/context-link?path=')) {
75
+ try {
76
+ const parsed = new URL(sourcePath, 'http://localhost');
77
+ const linkedPath = parsed.searchParams.get('path');
78
+ if (linkedPath)
79
+ candidates.push(linkedPath);
80
+ }
81
+ catch {
82
+ // Ignore malformed URLs and continue fallback checks.
83
+ }
84
+ }
85
+ candidates.push(sourcePath);
86
+ for (const candidate of candidates) {
87
+ const withoutQuery = candidate.split('?')[0].split('#')[0];
88
+ const filename = withoutQuery.split('/').pop() || '';
89
+ const dotIndex = filename.lastIndexOf('.');
90
+ if (dotIndex <= 0 || dotIndex === filename.length - 1)
91
+ continue;
92
+ const ext = filename.slice(dotIndex + 1);
93
+ if (ext)
94
+ return ext.slice(0, 5).toUpperCase();
95
+ }
96
+ return 'FILE';
97
+ };
98
+ const getContextTypeAccent = (fileType) => {
99
+ const type = fileType.toUpperCase();
100
+ if (type === 'PDF')
101
+ return '#ef4444';
102
+ if (type === 'DOC' || type === 'DOCX')
103
+ return '#3b82f6';
104
+ if (type === 'CSV')
105
+ return '#14b8a6';
106
+ if (type === 'JSON')
107
+ return '#f59e0b';
108
+ if (type === 'TXT' || type === 'MD')
109
+ return '#a78bfa';
110
+ return '#64748b';
111
+ };
112
+ const cardStyle = {
113
+ '--task-change-glow-color': priorityColor || `var(--priority-${displayPriority})`,
114
+ ...(priorityColor ? {
115
+ borderLeftColor: priorityColor,
116
+ [`--priority-${displayPriority}`]: priorityColor
117
+ } : {}),
118
+ ...(!hasLegacyClass && priorityColor ? { borderLeft: `4px solid ${priorityColor}` } : {})
119
+ };
120
+ // Helper for title case
121
+ const toTitleCase = (str) => str.replace(/\b\w/g, t => t.toUpperCase());
122
+ const taskById = React.useMemo(() => {
123
+ const map = new Map();
124
+ allTasks.forEach((item) => map.set(item.id, item));
125
+ return map;
126
+ }, [allTasks]);
127
+ const ancestors = React.useMemo(() => {
128
+ const chain = [];
129
+ const visited = new Set();
130
+ let parentId = task.parentTaskId || null;
131
+ while (parentId && !visited.has(parentId)) {
132
+ visited.add(parentId);
133
+ const ancestorTask = taskById.get(parentId) || null;
134
+ chain.push({ id: parentId, task: ancestorTask });
135
+ parentId = ancestorTask?.parentTaskId || null;
136
+ }
137
+ return chain;
138
+ }, [task.parentTaskId, taskById]);
139
+ const orderedAncestors = React.useMemo(() => [...ancestors].reverse(), [ancestors]);
140
+ const directChildren = sortChildTasksForDisplay(allTasks.filter(t => t.parentTaskId === task.id));
141
+ const directChildCount = directChildren.length;
142
+ const completedChildCount = directChildren.filter((t) => t.isArchived || t.status === 'done' || t.status === 'cancelled').length;
143
+ const childProgressPercent = directChildCount > 0
144
+ ? Math.round((completedChildCount / directChildCount) * 100)
145
+ : 0;
146
+ const checklistItems = React.useMemo(() => parseChecklistLines(task.description || ''), [task.description]);
147
+ const checklistTotal = checklistItems.length;
148
+ const checklistCompleted = checklistTotal > 0
149
+ ? checklistItems.filter(item => item.completed).length
150
+ : 0;
151
+ const isParentTask = directChildCount > 0;
152
+ const [showChildCards, setShowChildCards] = React.useState(false);
153
+ const handleToggleChildCards = (e) => {
154
+ e.stopPropagation();
155
+ setShowChildCards(prev => !prev);
156
+ };
157
+ return (_jsxs("div", { className: `${cardClasses} ${showLinkedFeedback ? styles.taskItemLinkedFeedback : ''}`, onClick: () => onClick?.(task), style: cardStyle, children: [showLinkedFeedback && (_jsx("div", { className: styles.taskLinkFeedbackPill, children: "Linked as child" })), showParentRelationship && ancestors.length > 0 && (compressed ? (_jsxs("div", { className: styles.taskParentCompact, title: `Ancestors: ${orderedAncestors.map((ancestor) => ancestor.task?.title || ancestor.id).join(' > ')}`, children: [_jsx(Icons.CornerUpLeft, { size: 11 }), _jsx("span", { children: `Ancestors: ${orderedAncestors.map((ancestor) => ancestor.id.split('-').slice(-1)[0]).join(' > ')}` })] })) : (orderedAncestors.map((ancestor) => {
158
+ const ancestorTask = ancestor.task;
159
+ const ancestorPriorityConfig = ancestorTask ? priorities.find(p => String(p.value) === String(ancestorTask.priority)) : null;
160
+ const ancestorPriorityName = ancestorPriorityConfig
161
+ ? ancestorPriorityConfig.label.toLowerCase().replace(/\s+/g, '-')
162
+ : String(ancestorTask?.priority ?? '');
163
+ const ancestorDisplayPriority = ancestorTask ? getLegacyPriorityClass(ancestorTask.priority, ancestorPriorityName) : '';
164
+ const ancestorPriorityColor = resolveColor(ancestorPriorityConfig?.color);
165
+ const ancestorHasLegacyClass = !!(ancestorDisplayPriority && styles[`priorityItem_${ancestorDisplayPriority}`]);
166
+ const ancestorCardStyle = {
167
+ ...(ancestorPriorityColor ? {
168
+ borderLeftColor: ancestorPriorityColor,
169
+ [`--priority-${ancestorDisplayPriority}`]: ancestorPriorityColor
170
+ } : {}),
171
+ ...(!ancestorHasLegacyClass && ancestorPriorityColor ? { borderLeft: `4px solid ${ancestorPriorityColor}` } : {})
172
+ };
173
+ return (_jsx("div", { className: `${styles.taskItem} ${styles.compressed} ${styles.taskChildMiniTask} ${styles.taskParentMiniTask} ${ancestorTask?.isArchived ? styles.taskChildMiniTaskArchived : ''} ${styles[`priorityItem_${ancestorDisplayPriority}`] || ''}`, style: ancestorCardStyle, title: ancestorTask ? ancestorTask.title : `Ancestor: ${ancestor.id}`, onClick: (e) => {
174
+ e.stopPropagation();
175
+ if (ancestorTask)
176
+ onClick?.(ancestorTask);
177
+ else
178
+ onOpenTaskById?.(ancestor.id);
179
+ }, children: _jsxs("div", { className: styles.taskChildMiniRow, children: [_jsxs("button", { type: "button", className: `${styles.taskIdBadge} ${styles.taskParentIdBtn} ${copiedId === ancestor.id ? styles.copiedId : ''}`, onClick: (e) => onCopyId?.(e, ancestor.id), title: "Copy ancestor task ID", children: [copiedId === ancestor.id ? _jsx(Check, { size: 13 }) : _jsx(Copy, { size: 13 }), _jsxs("span", { children: ["ID", _jsxs("span", { className: styles.taskIdText, children: [": ", ancestor.id.split('-').slice(-1)[0]] })] })] }), _jsx("div", { className: styles.taskParentTitle, children: ancestorTask?.title || `Ancestor: ${ancestor.id}` }), ancestor.id === (task.parentTaskId || '') && onClearParentTask && (_jsx("button", { type: "button", className: `${styles.actionBtn} ${styles.taskChildUnlinkBtn}`, onClick: (e) => {
180
+ e.stopPropagation();
181
+ onClearParentTask(task.id);
182
+ }, title: "Unlink parent", "aria-label": `Unlink parent for ${task.id}`, children: _jsx(X, { size: 12 }) }))] }) }, ancestor.id));
183
+ }))), _jsxs("div", { className: styles.taskHeader, children: [_jsxs("button", { type: "button", className: `${styles.taskIdBadge} ${copiedId === task.id ? styles.copiedId : ''} ${isArchived ? styles.archiveBadge : ''}`, onClick: (e) => onCopyId?.(e, task.id), title: "Click to copy Task ID", children: [copiedId === task.id ? _jsx(Check, { size: 13 }) : _jsx(Copy, { size: 13 }), _jsxs("span", { children: ["ID", _jsxs("span", { className: styles.taskIdText, children: [": ", renderHighlighted(task.id.split('-').slice(-1)[0], searchQuery)] })] })] }), _jsx("div", { className: styles.taskActions, onClick: (e) => e.stopPropagation(), children: !isArchived ? (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: `${styles.actionBtn} ${task.status === 'in-progress' ? styles.workingBtn : styles.startWorkBtn}`, style: compressed ? { width: '24px', height: '24px', padding: 0 } : {}, onClick: () => onToggleInProgress?.(task), title: task.status === 'in-progress' ? 'Stop Working' : 'Start Working', children: task.status === 'in-progress' ? _jsx(Pause, { size: compressed ? 12 : 16 }) : _jsx(Play, { size: compressed ? 12 : 16 }) }), _jsx("button", { type: "button", className: `${styles.actionBtn} ${task.status === 'review' ? styles.reviewActiveBtn : styles.reviewBtn}`, style: compressed ? { width: '24px', height: '24px', padding: 0 } : {}, onClick: () => onToggleReview?.(task), title: task.status === 'review' ? 'Unlock & Continue Work' : 'Ready for Review', children: _jsx(Sparkles, { size: compressed ? 12 : 16 }) }), _jsx("button", { type: "button", className: `${styles.actionBtn} ${task.status === 'done' ? styles.completeActiveBtn : styles.completeBtn}`, style: compressed ? { width: '24px', height: '24px', padding: 0 } : {}, onClick: () => onToggleComplete?.(task), title: task.status === 'done' ? 'Unmark Complete' : 'Mark Complete', children: _jsx(Check, { size: compressed ? 12 : 16 }) }), _jsx("button", { type: "button", className: `${styles.actionBtn} ${task.status === 'cancelled' ? styles.deleteActiveBtn : styles.deleteBtn}`, style: compressed ? { width: '24px', height: '24px', padding: 0 } : {}, onClick: () => onToggleCancel?.(task), title: task.status === 'cancelled' ? 'Unmark Cancelled' : 'Cancel Task', children: _jsx(Ban, { size: compressed ? 12 : 16 }) }), _jsx("button", { type: "button", className: `${styles.actionBtn} ${styles.archiveTaskBtn} ${!(task.status === 'done' || task.status === 'cancelled') ? styles.disabledBtn : ''}`, style: compressed ? { width: '24px', height: '24px', padding: 0 } : {}, onClick: () => (task.status === 'done' || task.status === 'cancelled') && onArchiveTask?.(task), disabled: !(task.status === 'done' || task.status === 'cancelled'), title: task.status === 'done' || task.status === 'cancelled' ? "Archive Now" : "Complete task to archive", children: _jsx(Archive, { size: compressed ? 12 : 16 }) })] })) : ((onUnarchive || onDelete) ? (_jsxs(_Fragment, { children: [onUnarchive && (_jsx("button", { type: "button", className: styles.actionBtn, onClick: () => onUnarchive(task.id), title: "Restore", children: _jsx(Icons.RotateCcw, { size: 16 }) })), onDelete && (_jsx("button", { type: "button", className: `${styles.actionBtn} ${styles.deleteBtn}`, onClick: () => onDelete(task.id), title: "Delete Permanently", children: _jsx(Icons.Trash2, { size: 16 }) }))] })) : null) })] }), _jsxs("div", { className: styles.taskContent, children: [/* Meta Badges moved to bottom */ isArchived && (_jsx("div", { className: styles.taskMeta, style: { marginBottom: '8px', marginTop: 0 } })), _jsxs("div", { children: [_jsxs("div", { className: styles.taskTitle, style: compressed ? { fontSize: '13px', lineHeight: '1.4' } : {}, children: [isArchived && '✓ ', renderHighlighted(task.title, searchQuery)] }), task.description && !isArchived && !compressed && (_jsx("div", { className: styles.taskDescription, children: _jsx(Markdown, { onTaskIdClick: onOpenTaskById, children: task.description }) }))] }), (task.attachments || task.screenshots) && (task.attachments || task.screenshots).length > 0 && !isArchived && !compressed && (_jsx("div", { className: styles.screenshotThumbnails, children: (task.attachments || task.screenshots || []).map((screenshot, idx) => {
184
+ const path = typeof screenshot === 'string' ? screenshot : screenshot.path;
185
+ const fsPath = typeof screenshot === 'string' ? undefined : screenshot.fsPath;
186
+ const name = getContextName(screenshot);
187
+ if (!isImagePath(path)) {
188
+ const fileType = getContextType(screenshot);
189
+ return (_jsx("button", { type: "button", className: styles.contextDocThumb, onClick: (e) => {
190
+ e.stopPropagation();
191
+ if (dispatchOpenMarkdownDocument(path, fsPath))
192
+ return;
193
+ window.open(path, '_blank');
194
+ }, title: name, style: { '--context-doc-accent': getContextTypeAccent(fileType) }, children: _jsx("span", { className: styles.contextDocType, children: fileType }) }, idx));
195
+ }
196
+ return (_jsx("div", { className: styles.screenshotThumbnail, onClick: (e) => {
197
+ e.stopPropagation();
198
+ window.open(path, '_blank');
199
+ }, children: _jsx("img", { src: path, alt: `Screenshot ${idx}` }) }, idx));
200
+ }) })), task.status === 'cancelled' && task.canceledReason && !compressed && (_jsxs("div", { className: styles.taskCancellationReason, children: [_jsx("strong", { children: "Cancellation Reason:" }), " ", renderHighlighted(task.canceledReason, searchQuery)] })), task.comments && task.comments.length > 0 && !isArchived && !compressed && (_jsxs("div", { className: styles.taskLatestComment, children: [_jsx("strong", { children: "Latest Activity:" }), " ", renderHighlighted(task.comments[task.comments.length - 1].text.length > 120
201
+ ? task.comments[task.comments.length - 1].text.substring(0, 120) + '...'
202
+ : task.comments[task.comments.length - 1].text, searchQuery)] })), task.specialists && task.specialists.length > 0 && !isArchived && !compressed && (_jsx("div", { className: styles.taskSpecialists, children: task.specialists.map(p => {
203
+ const specialist = availableSpecialists.find(ap => ap.value === p);
204
+ return (_jsxs("span", { className: styles.specialistBadge, title: specialist?.label || p, children: [_jsx(User, { size: 10 }), specialist?.label || p] }, p));
205
+ }) })), !isArchived && taxonomies.length > 0 && !compressed && (_jsx("div", { className: `${styles.taskSpecialists} ${styles.taxonomiesList}`, children: taxonomies.map(tax => {
206
+ const val = task.taxonomies?.[tax.id];
207
+ if (!val)
208
+ return null;
209
+ const values = Array.isArray(val) ? val : [val];
210
+ return values.map(v => {
211
+ const opt = tax.options.find(o => o.value === v);
212
+ if (!opt)
213
+ return null;
214
+ const IconComp = Icons[opt.icon || 'Layer'] || Layers;
215
+ const color = resolveColor(opt.color) || 'var(--text-primary)';
216
+ return (_jsx("span", { className: styles.specialistBadge, style: {
217
+ borderColor: `${color}50`,
218
+ backgroundColor: `${color}15`,
219
+ color: color
220
+ }, title: toTitleCase(opt.label), children: _jsx(IconComp, { size: 10 }) }, `${tax.id}-${v}`));
221
+ });
222
+ }) })), isParentTask && (compressed ? (_jsxs("div", { className: styles.taskChildrenSummaryBadges, children: [_jsxs("div", { className: styles.taskChildrenCountBadge, title: `${directChildCount} child tasks`, children: [_jsx(Layers, { size: 12 }), _jsx("span", { children: `Child Tasks: ${directChildCount}` })] }), _jsx("div", { className: styles.taskChildrenProgressBar, title: `${completedChildCount} of ${directChildCount} child tasks are done/cancelled (${childProgressPercent}%)`, children: _jsx("div", { className: styles.taskChildrenProgressBarFill, style: { width: `${childProgressPercent}%` } }) }), _jsx("div", { className: styles.taskChildrenProgressText, children: `${completedChildCount}/${directChildCount} • ${childProgressPercent}%` })] })) : (_jsxs("div", { className: styles.taskChildrenList, children: [_jsxs("div", { className: styles.taskChildrenSummaryBadges, children: [_jsx("div", { className: styles.taskChildrenProgressBar, title: `${completedChildCount} of ${directChildCount} child tasks are done/cancelled (${childProgressPercent}%)`, children: _jsx("div", { className: styles.taskChildrenProgressBarFill, style: { width: `${childProgressPercent}%` } }) }), _jsxs("div", { className: styles.taskChildrenMetaRow, children: [_jsxs("button", { type: "button", className: styles.taskChildrenToggleBtn, onClick: handleToggleChildCards, title: showChildCards ? 'Hide child tasks' : 'Show child tasks', children: [showChildCards ? _jsx(ChevronDown, { size: 12 }) : _jsx(ChevronRight, { size: 12 }), _jsx("span", { children: `Child Tasks: ${directChildCount}` })] }), _jsx("div", { className: styles.taskChildrenProgressText, children: `${completedChildCount}/${directChildCount} • ${childProgressPercent}%` })] })] }), showChildCards && (_jsx("div", { className: `${styles.taskChildrenItems} ${directChildCount > 5 ? styles.taskChildrenItemsScrollable : ''}`, children: directChildren.map((child) => {
223
+ const childPriorityConfig = priorities.find(p => String(p.value) === String(child.priority));
224
+ const childPriorityName = childPriorityConfig ? childPriorityConfig.label.toLowerCase().replace(/\s+/g, '-') : String(child.priority);
225
+ const childDisplayPriority = getLegacyPriorityClass(child.priority, childPriorityName);
226
+ const childPriorityColor = resolveColor(childPriorityConfig?.color);
227
+ const childHasLegacyClass = !!styles[`priorityItem_${childDisplayPriority}`];
228
+ const childCardStyle = {
229
+ ...(childPriorityColor ? {
230
+ borderLeftColor: childPriorityColor,
231
+ [`--priority-${childDisplayPriority}`]: childPriorityColor
232
+ } : {}),
233
+ ...(!childHasLegacyClass && childPriorityColor ? { borderLeft: `4px solid ${childPriorityColor}` } : {})
234
+ };
235
+ return (_jsx("div", { className: `${styles.taskItem} ${styles.compressed} ${styles.taskChildMiniTask} ${child.isArchived ? styles.taskChildMiniTaskArchived : ''} ${styles[`priorityItem_${childDisplayPriority}`] || ''}`, style: childCardStyle, onClick: (e) => {
236
+ e.stopPropagation();
237
+ onClick?.(child);
238
+ }, children: _jsxs("div", { className: styles.taskChildMiniRow, children: [_jsxs("button", { type: "button", className: `${styles.taskIdBadge} ${styles.childTaskIdButton} ${copiedId === child.id ? styles.copiedId : ''}`, onClick: (e) => {
239
+ e.stopPropagation();
240
+ onCopyId?.(e, child.id);
241
+ }, title: "Click to copy Child Task ID", children: [copiedId === child.id ? _jsx(Check, { size: 13 }) : _jsx(Copy, { size: 13 }), _jsxs("span", { children: ["ID", _jsxs("span", { className: styles.taskIdText, children: [": ", child.id.split('-').slice(-1)[0]] })] })] }), _jsx("div", { className: styles.taskChildMiniTitle, title: child.title, children: child.title }), onUnlinkChildTask && (_jsx("button", { type: "button", className: `${styles.actionBtn} ${styles.taskChildUnlinkBtn}`, onClick: (e) => {
242
+ e.stopPropagation();
243
+ onUnlinkChildTask(child.id);
244
+ }, title: "Unlink child", "aria-label": `Remove child ${child.id}`, children: _jsx(X, { size: 12 }) }))] }) }, child.id));
245
+ }) }))] }))), _jsx("div", { className: styles.taskMeta, children: isArchived ? (_jsx("span", { children: task.category })) : (_jsx(_Fragment, { children: _jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', width: '100%', marginBottom: compressed ? '0px' : '4px' }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '4px' }, children: [(() => {
246
+ const color = resolveColor(categoryConfig?.color);
247
+ const iconName = categoryConfig?.icon || 'Folder';
248
+ const IconComp = Icons[iconName] || Icons.Folder;
249
+ return (_jsx("span", { className: styles.metaBadge, title: toTitleCase(task.category), style: {
250
+ color: color || 'var(--text-secondary)',
251
+ backgroundColor: color ? `${color}15` : 'var(--bg-tertiary)',
252
+ borderColor: color ? `${color}40` : 'transparent'
253
+ }, children: _jsx(IconComp, { size: 14 }) }));
254
+ })(), _jsx("span", { className: `${styles.metaBadge} ${styles[`type_${task.type}`] || ''}`, title: toTitleCase(task.type || 'feature'), style: {
255
+ color: `var(--type-color, ${typeColor})`,
256
+ backgroundColor: `color-mix(in srgb, var(--type-color, ${typeColor}), transparent 90%)`,
257
+ borderColor: `color-mix(in srgb, var(--type-color, ${typeColor}), transparent 75%)`
258
+ }, children: getIconForType(task.type, 14) }), (() => {
259
+ const approachConfig = approaches.find(a => a.value === task.approach);
260
+ const color = resolveColor(approachConfig?.color);
261
+ const iconName = approachConfig?.icon || 'HelpCircle';
262
+ const IconComp = Icons[iconName] || Icons.HelpCircle;
263
+ return (_jsx("span", { className: `${styles.metaBadge} ${styles[`approach_${task.approach || 'default'}`] || ''}`, title: toTitleCase(task.approach || 'Default'), style: {
264
+ color: color || 'var(--text-muted)',
265
+ backgroundColor: color ? `${color}15` : 'var(--bg-tertiary)',
266
+ borderColor: color ? `${color}40` : 'var(--border-primary)'
267
+ }, children: _jsx(IconComp, { size: 14 }) }));
268
+ })(), priorityConfig && (_jsx("span", { className: styles.metaBadge, style: {
269
+ color: priorityColor || 'var(--text-secondary)',
270
+ backgroundColor: priorityColor ? `${priorityColor}15` : 'var(--bg-tertiary)',
271
+ borderColor: priorityColor ? `${priorityColor}40` : 'var(--border-color)'
272
+ }, title: `${priorityConfig.label}`, children: (() => {
273
+ const iconName = priorityConfig.icon || 'AlertCircle';
274
+ const IconComp = Icons[iconName] || Icons.AlertCircle;
275
+ return _jsx(IconComp, { size: 14 });
276
+ })() })), task.comments && task.comments.length > 0 && (_jsxs("span", { className: styles.metaBadge, title: `${task.comments.length} comments`, style: {
277
+ color: 'var(--text-muted)',
278
+ backgroundColor: 'var(--bg-tertiary)',
279
+ borderColor: 'var(--border-primary)',
280
+ gap: '4px',
281
+ padding: '0 8px'
282
+ }, children: [_jsx(MessageSquare, { size: 14 }), _jsx("span", { children: task.comments.length })] })), checklistTotal > 0 && (_jsxs("span", { className: styles.metaBadge, title: `${checklistCompleted}/${checklistTotal} checklist items complete`, style: {
283
+ color: 'var(--text-muted)',
284
+ backgroundColor: 'var(--bg-tertiary)',
285
+ borderColor: 'var(--border-primary)',
286
+ gap: '4px',
287
+ padding: '0 8px'
288
+ }, children: [_jsx(ClipboardList, { size: 14 }), _jsx("span", { children: `${checklistCompleted}/${checklistTotal}` })] }))] }), _jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsxs("span", { className: styles.metaBadge, title: `AI-estimated complexity: ${complexityLabel} (${normalizedComplexity}/5)`, style: {
289
+ color: complexityColor,
290
+ backgroundColor: `color-mix(in srgb, ${complexityColor}, transparent 88%)`,
291
+ borderColor: `color-mix(in srgb, ${complexityColor}, transparent 72%)`,
292
+ gap: '4px',
293
+ padding: '0 8px'
294
+ }, children: [_jsx(Gauge, { size: 14 }), !compressed && _jsx("span", { children: complexityLabel })] }), _jsx("span", { className: styles.metaBadge, title: task.assignee === 'agent'
295
+ ? 'Assigned to: AI'
296
+ : task.assignee === 'user'
297
+ ? 'Assigned to: User'
298
+ : 'Assigned to: Unassigned', "aria-label": task.assignee === 'agent'
299
+ ? 'Assigned to AI'
300
+ : task.assignee === 'user'
301
+ ? 'Assigned to User'
302
+ : 'Unassigned', style: {
303
+ backgroundColor: task.assignee === 'agent'
304
+ ? 'color-mix(in srgb, var(--color-violet-500, #8b5cf6), transparent 88%)'
305
+ : task.assignee === 'user'
306
+ ? 'color-mix(in srgb, var(--color-green-500, #22c55e), transparent 88%)'
307
+ : 'color-mix(in srgb, var(--text-secondary, #888), transparent 88%)',
308
+ padding: '0 8px',
309
+ color: task.assignee === 'agent'
310
+ ? 'var(--color-violet-500, #8b5cf6)'
311
+ : task.assignee === 'user'
312
+ ? 'var(--color-green-500, #22c55e)'
313
+ : 'var(--text-secondary, #888)',
314
+ borderColor: task.assignee === 'agent'
315
+ ? 'color-mix(in srgb, var(--color-violet-500, #8b5cf6), transparent 72%)'
316
+ : task.assignee === 'user'
317
+ ? 'color-mix(in srgb, var(--color-green-500, #22c55e), transparent 72%)'
318
+ : 'color-mix(in srgb, var(--text-secondary, #888), transparent 70%)',
319
+ display: 'flex',
320
+ alignItems: 'center'
321
+ }, children: task.assignee === 'agent'
322
+ ? _jsx(Bot, { size: compressed ? 14 : 16 })
323
+ : task.assignee === 'user'
324
+ ? _jsx(User, { size: compressed ? 14 : 16 })
325
+ : _jsx(HelpCircle, { size: compressed ? 14 : 16 }) })] })] }) })) })] })] }));
326
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,95 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+ import { describe, it, expect } from 'vitest';
5
+ import { TaskCard } from './TaskCard';
6
+ const baseTask = (overrides) => ({
7
+ id: 'task-default',
8
+ title: 'Task',
9
+ description: null,
10
+ category: 'general',
11
+ type: 'feature',
12
+ priority: 2,
13
+ status: 'task',
14
+ createdAt: '2026-02-13T00:00:00.000Z',
15
+ ...overrides
16
+ });
17
+ describe('TaskCard parent/child progress', () => {
18
+ it('counts archived children as completed in progress percent', () => {
19
+ const parent = baseTask({ id: 'task-parent', title: 'Parent Task' });
20
+ const childDone = baseTask({
21
+ id: 'task-child-done',
22
+ title: 'Done Child',
23
+ parentTaskId: parent.id,
24
+ status: 'done'
25
+ });
26
+ const childArchived = baseTask({
27
+ id: 'task-child-archived',
28
+ title: 'Archived Child',
29
+ parentTaskId: parent.id,
30
+ status: 'task',
31
+ isArchived: true
32
+ });
33
+ render(_jsx(TaskCard, { task: parent, allTasks: [parent, childDone, childArchived], onClick: () => { }, onCopyId: () => { } }));
34
+ const progressBar = screen.getByTitle('2 of 2 child tasks are done/cancelled (100%)');
35
+ expect(progressBar).toBeInTheDocument();
36
+ const fill = progressBar.firstElementChild;
37
+ expect(fill).toBeTruthy();
38
+ expect(fill?.style.width).toBe('100%');
39
+ });
40
+ it('renders archived child tasks after non-archived child tasks', async () => {
41
+ const user = userEvent.setup();
42
+ const parent = baseTask({ id: 'task-parent-2', title: 'Parent Task 2' });
43
+ const activeChild = baseTask({
44
+ id: 'task-child-active',
45
+ title: 'Active Child',
46
+ parentTaskId: parent.id,
47
+ status: 'task',
48
+ isArchived: false,
49
+ createdAt: '2026-02-13T02:00:00.000Z'
50
+ });
51
+ const archivedChild = baseTask({
52
+ id: 'task-child-archived-2',
53
+ title: 'Archived Child',
54
+ parentTaskId: parent.id,
55
+ status: 'done',
56
+ isArchived: true,
57
+ createdAt: '2026-02-13T03:00:00.000Z'
58
+ });
59
+ const { container } = render(_jsx(TaskCard, { task: parent, allTasks: [parent, archivedChild, activeChild], onClick: () => { }, onCopyId: () => { } }));
60
+ await user.click(screen.getByRole('button', { name: /child tasks: 2/i }));
61
+ const text = container.textContent || '';
62
+ const activeIndex = text.indexOf('Active Child');
63
+ const archivedIndex = text.indexOf('Archived Child');
64
+ expect(activeIndex).toBeGreaterThanOrEqual(0);
65
+ expect(archivedIndex).toBeGreaterThanOrEqual(0);
66
+ expect(activeIndex).toBeLessThan(archivedIndex);
67
+ });
68
+ it('renders markdown context attachments with MD type badge', () => {
69
+ const task = baseTask({
70
+ id: 'task-md-context',
71
+ title: 'Task with markdown context',
72
+ screenshots: [
73
+ {
74
+ path: '/api/taskforce/context/task-data%2Ftask-md-context%2Fattachments%2Fnotes-123.bin',
75
+ fsPath: '.taskforce/task-data/task-md-context/attachments/notes.md',
76
+ caption: 'notes.md'
77
+ }
78
+ ]
79
+ });
80
+ render(_jsx(TaskCard, { task: task, allTasks: [task], onClick: () => { }, onCopyId: () => { } }));
81
+ expect(screen.getByText('MD')).toBeInTheDocument();
82
+ });
83
+ it('renders full ancestor chain (parent, grandparent, great-grandparent and above)', () => {
84
+ const root = baseTask({ id: 'task-root', title: 'Root' });
85
+ const greatGrand = baseTask({ id: 'task-great-grand', title: 'Great Grand', parentTaskId: root.id });
86
+ const grand = baseTask({ id: 'task-grand', title: 'Grand', parentTaskId: greatGrand.id });
87
+ const parent = baseTask({ id: 'task-parent-chain', title: 'Parent', parentTaskId: grand.id });
88
+ const leaf = baseTask({ id: 'task-leaf', title: 'Leaf', parentTaskId: parent.id });
89
+ render(_jsx(TaskCard, { task: leaf, allTasks: [leaf, parent, grand, greatGrand, root], onClick: () => { }, onCopyId: () => { } }));
90
+ expect(screen.getByText('Parent')).toBeInTheDocument();
91
+ expect(screen.getByText('Grand')).toBeInTheDocument();
92
+ expect(screen.getByText('Great Grand')).toBeInTheDocument();
93
+ expect(screen.getByText('Root')).toBeInTheDocument();
94
+ });
95
+ });
@@ -0,0 +1,12 @@
1
+ import type { ScreenshotItem } from '../../types';
2
+ interface TaskContextUploadProps {
3
+ taskId?: string | null;
4
+ contextFiles: Array<string | ScreenshotItem>;
5
+ browsedPath?: string;
6
+ onBrowseLinkPath?: () => void;
7
+ onAddContextFile: (file: ScreenshotItem) => void;
8
+ onRemoveContextFile: (index: number) => void;
9
+ onUpdateContextCaption: (index: number, caption: string) => void;
10
+ }
11
+ export declare function TaskContextUpload(props: TaskContextUploadProps): import("react/jsx-runtime").JSX.Element;
12
+ export {};