@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,110 @@
1
+ import { createRequire } from 'module';
2
+ import { parentPort, workerData } from 'worker_threads';
3
+ const RESPONSE_STATUS_INDEX = 0;
4
+ const RESPONSE_LENGTH_INDEX = 1;
5
+ const RESPONSE_READY = 1;
6
+ const encoder = new TextEncoder();
7
+ function createPool(connectionString) {
8
+ const require = createRequire(import.meta.url);
9
+ try {
10
+ const pg = require('pg');
11
+ return new pg.Pool({ connectionString });
12
+ }
13
+ catch (error) {
14
+ const detail = error instanceof Error ? ` (${error.message})` : '';
15
+ throw new Error(`[Taskforce] Missing "pg" dependency in worker${detail}`);
16
+ }
17
+ }
18
+ function writeResponse(statusBuffer, responseBuffer, payload) {
19
+ const status = new Int32Array(statusBuffer);
20
+ const responseBytes = new Uint8Array(responseBuffer);
21
+ const serialized = JSON.stringify(payload);
22
+ const encoded = encoder.encode(serialized);
23
+ if (encoded.length > responseBytes.length) {
24
+ const fallback = encoder.encode(JSON.stringify({
25
+ ok: false,
26
+ error: '[Taskforce] Postgres worker response exceeded buffer capacity.'
27
+ }));
28
+ responseBytes.fill(0);
29
+ responseBytes.set(fallback.subarray(0, responseBytes.length));
30
+ status[RESPONSE_LENGTH_INDEX] = Math.min(fallback.length, responseBytes.length);
31
+ }
32
+ else {
33
+ responseBytes.fill(0);
34
+ responseBytes.set(encoded);
35
+ status[RESPONSE_LENGTH_INDEX] = encoded.length;
36
+ }
37
+ Atomics.store(status, RESPONSE_STATUS_INDEX, RESPONSE_READY);
38
+ Atomics.notify(status, RESPONSE_STATUS_INDEX, 1);
39
+ }
40
+ const connectionString = String(workerData?.connectionString || '').trim();
41
+ if (!connectionString) {
42
+ throw new Error('[Taskforce] Postgres worker requires connection string.');
43
+ }
44
+ const pool = createPool(connectionString);
45
+ const txClients = new Map();
46
+ async function handleMessage(message) {
47
+ const { payload } = message;
48
+ const txId = payload.txId ? String(payload.txId) : null;
49
+ if (payload.op === 'close') {
50
+ for (const [, client] of txClients) {
51
+ try {
52
+ await client.query('ROLLBACK');
53
+ }
54
+ catch {
55
+ // Ignore rollback failures during shutdown.
56
+ }
57
+ client.release();
58
+ }
59
+ txClients.clear();
60
+ await pool.end();
61
+ return { ok: true, result: { rows: [], rowCount: 0 } };
62
+ }
63
+ if (payload.op === 'begin') {
64
+ if (!txId)
65
+ throw new Error('[Taskforce] begin requires txId');
66
+ if (txClients.has(txId))
67
+ throw new Error(`[Taskforce] transaction already exists: ${txId}`);
68
+ const client = await pool.connect();
69
+ await client.query('BEGIN');
70
+ txClients.set(txId, client);
71
+ return { ok: true, result: { rows: [], rowCount: 0 } };
72
+ }
73
+ if (payload.op === 'commit' || payload.op === 'rollback') {
74
+ if (!txId)
75
+ throw new Error(`[Taskforce] ${payload.op} requires txId`);
76
+ const client = txClients.get(txId);
77
+ if (!client)
78
+ throw new Error(`[Taskforce] unknown transaction: ${txId}`);
79
+ try {
80
+ await client.query(payload.op === 'commit' ? 'COMMIT' : 'ROLLBACK');
81
+ }
82
+ finally {
83
+ client.release();
84
+ txClients.delete(txId);
85
+ }
86
+ return { ok: true, result: { rows: [], rowCount: 0 } };
87
+ }
88
+ if (payload.op === 'query') {
89
+ const sql = String(payload.sql || '').trim();
90
+ const values = Array.isArray(payload.values) ? payload.values : [];
91
+ const client = txId ? txClients.get(txId) : null;
92
+ const executor = client || pool;
93
+ const result = await executor.query(sql, values);
94
+ return { ok: true, result };
95
+ }
96
+ throw new Error(`[Taskforce] unknown worker op: ${payload.op}`);
97
+ }
98
+ if (!parentPort) {
99
+ throw new Error('[Taskforce] Postgres worker missing parent port.');
100
+ }
101
+ parentPort.on('message', async (message) => {
102
+ try {
103
+ const response = await handleMessage(message);
104
+ writeResponse(message.statusBuffer, message.responseBuffer, response);
105
+ }
106
+ catch (error) {
107
+ const messageText = error instanceof Error ? error.message : String(error);
108
+ writeResponse(message.statusBuffer, message.responseBuffer, { ok: false, error: messageText });
109
+ }
110
+ });
@@ -0,0 +1,6 @@
1
+ import type { DatabaseProvider } from './databaseAdapter.js';
2
+ export interface ResolvedDatabaseConfig {
3
+ provider: DatabaseProvider;
4
+ connectionString?: string;
5
+ }
6
+ export declare function resolveDatabaseConfigFromEnv(env?: NodeJS.ProcessEnv): ResolvedDatabaseConfig;
@@ -0,0 +1,11 @@
1
+ export function resolveDatabaseConfigFromEnv(env = process.env) {
2
+ const provider = env.TASKFORCE_DB_PROVIDER === 'postgres' ? 'postgres' : 'sqlite';
3
+ const connectionString = env.TASKFORCE_DATABASE_URL;
4
+ if (provider === 'postgres' && !connectionString) {
5
+ throw new Error('[Taskforce] TASKFORCE_DB_PROVIDER=postgres requires TASKFORCE_DATABASE_URL to be set.');
6
+ }
7
+ return {
8
+ provider,
9
+ connectionString
10
+ };
11
+ }
@@ -0,0 +1,14 @@
1
+ import type { DatabaseAdapter, DatabaseStatement } from './databaseAdapter.js';
2
+ export declare class SqliteAdapter implements DatabaseAdapter {
3
+ readonly provider: "sqlite";
4
+ private readonly db;
5
+ constructor(dbPath: string);
6
+ get open(): boolean;
7
+ prepare(sql: string): DatabaseStatement;
8
+ exec(sql: string): void;
9
+ transaction<T extends (...args: any[]) => any>(fn: T): T;
10
+ pragma(name: string, options?: {
11
+ simple?: boolean;
12
+ }): unknown;
13
+ close(): void;
14
+ }
@@ -0,0 +1,28 @@
1
+ import Database from 'better-sqlite3';
2
+ export class SqliteAdapter {
3
+ provider = 'sqlite';
4
+ db;
5
+ constructor(dbPath) {
6
+ this.db = new Database(dbPath);
7
+ }
8
+ get open() {
9
+ return this.db.open;
10
+ }
11
+ prepare(sql) {
12
+ return this.db.prepare(sql);
13
+ }
14
+ exec(sql) {
15
+ this.db.exec(sql);
16
+ }
17
+ transaction(fn) {
18
+ return this.db.transaction(fn);
19
+ }
20
+ pragma(name, options) {
21
+ return this.db.pragma(name, options);
22
+ }
23
+ close() {
24
+ if (this.db.open) {
25
+ this.db.close();
26
+ }
27
+ }
28
+ }
@@ -0,0 +1,56 @@
1
+ import type { DatabaseAdapter } from './databaseAdapter.js';
2
+ import type { ObjectStorageProvider } from './objectStorage.js';
3
+ import { DocumentRegistry } from './documentRegistry.js';
4
+ import type { VirusScanResult } from '../security/virusScan.js';
5
+ export type TaskAssetQuarantineStatus = 'none' | 'quarantined' | 'released';
6
+ export interface TaskAssetEntry {
7
+ tenantId: string;
8
+ workspaceId: string;
9
+ path: string;
10
+ provider: ObjectStorageProvider;
11
+ version: number;
12
+ contentType: string;
13
+ sizeBytes: number;
14
+ sha256: string;
15
+ uploadedAt: string;
16
+ scan: VirusScanResult & {
17
+ scannedAt: string;
18
+ };
19
+ quarantineStatus: TaskAssetQuarantineStatus;
20
+ deletedAt?: string | null;
21
+ purgeAfter?: string | null;
22
+ updatedAt: string;
23
+ }
24
+ export declare class TaskAssetStore {
25
+ private readonly db;
26
+ private readonly tenantId;
27
+ private readonly fallbackRegistry;
28
+ constructor(db: DatabaseAdapter, tenantId: string, basePath: string, fallbackRegistry?: DocumentRegistry);
29
+ private backfillFromRegistry;
30
+ private upsertEntry;
31
+ get(pathValue: string, workspaceIdRaw?: string): TaskAssetEntry | null;
32
+ isDeleted(pathValue: string, workspaceIdRaw?: string): boolean;
33
+ recordUpload(input: {
34
+ path: string;
35
+ workspaceId?: string;
36
+ provider: ObjectStorageProvider;
37
+ contentType: string;
38
+ sizeBytes: number;
39
+ sha256: string;
40
+ uploadedAt?: string;
41
+ scan: VirusScanResult;
42
+ }): TaskAssetEntry;
43
+ markDeleted(pathValue: string, retentionDays: number, workspaceIdRaw?: string): TaskAssetEntry | null;
44
+ clearDeleted(pathValue: string, workspaceIdRaw?: string): TaskAssetEntry | null;
45
+ remove(pathValue: string, workspaceIdRaw?: string): boolean;
46
+ listPurgeCandidates(now?: Date): TaskAssetEntry[];
47
+ listAll(limit?: number): TaskAssetEntry[];
48
+ updateQuarantineStatus(pathValue: string, quarantineStatus: TaskAssetQuarantineStatus, workspaceIdRaw?: string): TaskAssetEntry | null;
49
+ updateScanResult(input: {
50
+ path: string;
51
+ workspaceId?: string;
52
+ scan: VirusScanResult;
53
+ quarantineStatus?: TaskAssetQuarantineStatus;
54
+ }): TaskAssetEntry | null;
55
+ listQuarantined(limit?: number): TaskAssetEntry[];
56
+ }
@@ -0,0 +1,297 @@
1
+ import { DocumentRegistry } from './documentRegistry.js';
2
+ function normalizeLimit(limitRaw, fallback) {
3
+ return Number.isFinite(limitRaw) ? Math.max(1, Math.floor(Number(limitRaw))) : fallback;
4
+ }
5
+ function normalizePath(rawPath) {
6
+ return String(rawPath || '').trim().replace(/\\/g, '/');
7
+ }
8
+ function normalizeWorkspaceId(rawWorkspaceId) {
9
+ const trimmed = String(rawWorkspaceId || '').trim();
10
+ return trimmed || 'default';
11
+ }
12
+ function inferWorkspaceIdFromPath(rawPath) {
13
+ const normalized = normalizePath(rawPath);
14
+ const match = normalized.match(/^workspaces\/([^/]+)\//);
15
+ if (match && match[1])
16
+ return match[1];
17
+ return 'default';
18
+ }
19
+ function mapRegistryEntry(tenantId, workspaceId, entry) {
20
+ return {
21
+ tenantId,
22
+ workspaceId,
23
+ path: entry.path,
24
+ provider: entry.provider,
25
+ version: entry.version,
26
+ contentType: entry.contentType,
27
+ sizeBytes: entry.sizeBytes,
28
+ sha256: entry.sha256,
29
+ uploadedAt: entry.uploadedAt,
30
+ scan: entry.scan,
31
+ quarantineStatus: entry.scan.verdict === 'infected' ? 'quarantined' : 'none',
32
+ deletedAt: entry.deletedAt || null,
33
+ purgeAfter: entry.purgeAfter || null,
34
+ updatedAt: entry.uploadedAt
35
+ };
36
+ }
37
+ function mapRow(row) {
38
+ return {
39
+ tenantId: String(row.tenant_id || 'default'),
40
+ workspaceId: String(row.workspace_id || 'default'),
41
+ path: String(row.path || ''),
42
+ provider: String(row.provider || 'local') === 'r2' ? 'r2' : 'local',
43
+ version: Number(row.version || 1),
44
+ contentType: String(row.content_type || 'application/octet-stream'),
45
+ sizeBytes: Number(row.size_bytes || 0),
46
+ sha256: String(row.sha256 || ''),
47
+ uploadedAt: String(row.uploaded_at || ''),
48
+ scan: {
49
+ engine: String(row.scan_engine || 'none'),
50
+ verdict: String(row.scan_verdict || 'clean'),
51
+ details: row.scan_details ? String(row.scan_details) : undefined,
52
+ scannedAt: String(row.scan_scanned_at || row.uploaded_at || new Date().toISOString())
53
+ },
54
+ quarantineStatus: String(row.quarantine_status || 'none'),
55
+ deletedAt: row.deleted_at ? String(row.deleted_at) : null,
56
+ purgeAfter: row.purge_after ? String(row.purge_after) : null,
57
+ updatedAt: String(row.updated_at || row.uploaded_at || new Date().toISOString())
58
+ };
59
+ }
60
+ export class TaskAssetStore {
61
+ db;
62
+ tenantId;
63
+ fallbackRegistry;
64
+ constructor(db, tenantId, basePath, fallbackRegistry) {
65
+ this.db = db;
66
+ this.tenantId = tenantId;
67
+ this.fallbackRegistry = fallbackRegistry || new DocumentRegistry(basePath);
68
+ }
69
+ backfillFromRegistry(pathValue) {
70
+ const fallback = this.fallbackRegistry.get(pathValue);
71
+ if (!fallback)
72
+ return null;
73
+ const workspaceId = inferWorkspaceIdFromPath(fallback.path);
74
+ const entry = mapRegistryEntry(this.tenantId, workspaceId, fallback);
75
+ this.upsertEntry(entry);
76
+ return this.get(entry.path, entry.workspaceId);
77
+ }
78
+ upsertEntry(entry) {
79
+ this.db.prepare(`
80
+ INSERT INTO task_assets (
81
+ tenant_id,
82
+ workspace_id,
83
+ path,
84
+ provider,
85
+ version,
86
+ content_type,
87
+ size_bytes,
88
+ sha256,
89
+ uploaded_at,
90
+ scan_engine,
91
+ scan_verdict,
92
+ scan_details,
93
+ scan_scanned_at,
94
+ quarantine_status,
95
+ deleted_at,
96
+ purge_after,
97
+ updated_at
98
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
99
+ ON CONFLICT(tenant_id, workspace_id, path) DO UPDATE SET
100
+ provider = excluded.provider,
101
+ version = excluded.version,
102
+ content_type = excluded.content_type,
103
+ size_bytes = excluded.size_bytes,
104
+ sha256 = excluded.sha256,
105
+ uploaded_at = excluded.uploaded_at,
106
+ scan_engine = excluded.scan_engine,
107
+ scan_verdict = excluded.scan_verdict,
108
+ scan_details = excluded.scan_details,
109
+ scan_scanned_at = excluded.scan_scanned_at,
110
+ quarantine_status = excluded.quarantine_status,
111
+ deleted_at = excluded.deleted_at,
112
+ purge_after = excluded.purge_after,
113
+ updated_at = excluded.updated_at
114
+ `).run(entry.tenantId, entry.workspaceId, entry.path, entry.provider, entry.version, entry.contentType, entry.sizeBytes, entry.sha256, entry.uploadedAt, entry.scan.engine, entry.scan.verdict, entry.scan.details || null, entry.scan.scannedAt, entry.quarantineStatus, entry.deletedAt || null, entry.purgeAfter || null, entry.updatedAt);
115
+ }
116
+ get(pathValue, workspaceIdRaw) {
117
+ const normalizedPath = normalizePath(pathValue);
118
+ const workspaceId = normalizeWorkspaceId(workspaceIdRaw || inferWorkspaceIdFromPath(normalizedPath));
119
+ const row = this.db.prepare(`
120
+ SELECT *
121
+ FROM task_assets
122
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
123
+ LIMIT 1
124
+ `).get(this.tenantId, workspaceId, normalizedPath);
125
+ if (row)
126
+ return mapRow(row);
127
+ return this.backfillFromRegistry(normalizedPath);
128
+ }
129
+ isDeleted(pathValue, workspaceIdRaw) {
130
+ const entry = this.get(pathValue, workspaceIdRaw);
131
+ return Boolean(entry?.deletedAt);
132
+ }
133
+ recordUpload(input) {
134
+ const normalizedPath = normalizePath(input.path);
135
+ const workspaceId = normalizeWorkspaceId(input.workspaceId || inferWorkspaceIdFromPath(normalizedPath));
136
+ const existing = this.db.prepare(`
137
+ SELECT version
138
+ FROM task_assets
139
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
140
+ LIMIT 1
141
+ `).get(this.tenantId, workspaceId, normalizedPath);
142
+ const nowIso = new Date().toISOString();
143
+ const entry = {
144
+ tenantId: this.tenantId,
145
+ workspaceId,
146
+ path: normalizedPath,
147
+ provider: input.provider,
148
+ version: Number(existing?.version || 0) + 1,
149
+ contentType: input.contentType || 'application/octet-stream',
150
+ sizeBytes: input.sizeBytes,
151
+ sha256: input.sha256,
152
+ uploadedAt: input.uploadedAt || nowIso,
153
+ scan: {
154
+ ...input.scan,
155
+ scannedAt: nowIso
156
+ },
157
+ quarantineStatus: input.scan.verdict === 'infected' ? 'quarantined' : 'none',
158
+ deletedAt: null,
159
+ purgeAfter: null,
160
+ updatedAt: nowIso
161
+ };
162
+ this.upsertEntry(entry);
163
+ // One-release compatibility mirror.
164
+ this.fallbackRegistry.recordUpload({
165
+ path: normalizedPath,
166
+ provider: input.provider,
167
+ contentType: entry.contentType,
168
+ sizeBytes: entry.sizeBytes,
169
+ sha256: entry.sha256,
170
+ uploadedAt: entry.uploadedAt,
171
+ scan: input.scan
172
+ });
173
+ return entry;
174
+ }
175
+ markDeleted(pathValue, retentionDays, workspaceIdRaw) {
176
+ const entry = this.get(pathValue, workspaceIdRaw);
177
+ if (!entry)
178
+ return null;
179
+ const now = new Date();
180
+ const safeDays = Number.isFinite(retentionDays) ? Math.max(1, Math.floor(retentionDays)) : 7;
181
+ const purgeAt = new Date(now.getTime() + safeDays * 24 * 60 * 60 * 1000).toISOString();
182
+ const nowIso = now.toISOString();
183
+ this.db.prepare(`
184
+ UPDATE task_assets
185
+ SET deleted_at = ?, purge_after = ?, updated_at = ?
186
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
187
+ `).run(nowIso, purgeAt, nowIso, this.tenantId, entry.workspaceId, entry.path);
188
+ this.fallbackRegistry.markDeleted(entry.path, safeDays);
189
+ return this.get(entry.path, entry.workspaceId);
190
+ }
191
+ clearDeleted(pathValue, workspaceIdRaw) {
192
+ const entry = this.get(pathValue, workspaceIdRaw);
193
+ if (!entry)
194
+ return null;
195
+ const nowIso = new Date().toISOString();
196
+ this.db.prepare(`
197
+ UPDATE task_assets
198
+ SET deleted_at = NULL, purge_after = NULL, updated_at = ?
199
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
200
+ `).run(nowIso, this.tenantId, entry.workspaceId, entry.path);
201
+ this.fallbackRegistry.clearDeleted(entry.path);
202
+ return this.get(entry.path, entry.workspaceId);
203
+ }
204
+ remove(pathValue, workspaceIdRaw) {
205
+ const entry = this.get(pathValue, workspaceIdRaw);
206
+ if (!entry)
207
+ return false;
208
+ const result = this.db.prepare(`
209
+ DELETE FROM task_assets
210
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
211
+ `).run(this.tenantId, entry.workspaceId, entry.path);
212
+ this.fallbackRegistry.remove(entry.path);
213
+ return Number(result?.changes || 0) > 0;
214
+ }
215
+ listPurgeCandidates(now = new Date()) {
216
+ const nowIso = now.toISOString();
217
+ const rows = this.db.prepare(`
218
+ SELECT *
219
+ FROM task_assets
220
+ WHERE tenant_id = ?
221
+ AND deleted_at IS NOT NULL
222
+ AND purge_after IS NOT NULL
223
+ AND purge_after <= ?
224
+ ORDER BY purge_after ASC
225
+ `).all(this.tenantId, nowIso);
226
+ return rows.map(mapRow);
227
+ }
228
+ listAll(limit = 500) {
229
+ const safeLimit = normalizeLimit(limit, 500);
230
+ const rows = this.db.prepare(`
231
+ SELECT *
232
+ FROM task_assets
233
+ WHERE tenant_id = ?
234
+ ORDER BY path ASC
235
+ LIMIT ?
236
+ `).all(this.tenantId, safeLimit);
237
+ // Opportunistic backfill for compatibility records.
238
+ for (const legacy of this.fallbackRegistry.listAll()) {
239
+ const workspaceId = inferWorkspaceIdFromPath(legacy.path);
240
+ const exists = rows.find((row) => String(row.path || '') === legacy.path && String(row.workspace_id || '') === workspaceId);
241
+ if (!exists) {
242
+ this.upsertEntry(mapRegistryEntry(this.tenantId, workspaceId, legacy));
243
+ }
244
+ }
245
+ const refreshed = this.db.prepare(`
246
+ SELECT *
247
+ FROM task_assets
248
+ WHERE tenant_id = ?
249
+ ORDER BY path ASC
250
+ LIMIT ?
251
+ `).all(this.tenantId, safeLimit);
252
+ return refreshed.map(mapRow);
253
+ }
254
+ updateQuarantineStatus(pathValue, quarantineStatus, workspaceIdRaw) {
255
+ const entry = this.get(pathValue, workspaceIdRaw);
256
+ if (!entry)
257
+ return null;
258
+ const nowIso = new Date().toISOString();
259
+ this.db.prepare(`
260
+ UPDATE task_assets
261
+ SET quarantine_status = ?, updated_at = ?
262
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
263
+ `).run(quarantineStatus, nowIso, this.tenantId, entry.workspaceId, entry.path);
264
+ return this.get(entry.path, entry.workspaceId);
265
+ }
266
+ updateScanResult(input) {
267
+ const entry = this.get(input.path, input.workspaceId);
268
+ if (!entry)
269
+ return null;
270
+ const nowIso = new Date().toISOString();
271
+ const nextQuarantineStatus = input.quarantineStatus
272
+ || (input.scan.verdict === 'infected' ? 'quarantined' : 'none');
273
+ this.db.prepare(`
274
+ UPDATE task_assets
275
+ SET scan_engine = ?,
276
+ scan_verdict = ?,
277
+ scan_details = ?,
278
+ scan_scanned_at = ?,
279
+ quarantine_status = ?,
280
+ updated_at = ?
281
+ WHERE tenant_id = ? AND workspace_id = ? AND path = ?
282
+ `).run(input.scan.engine, input.scan.verdict, input.scan.details || null, nowIso, nextQuarantineStatus, nowIso, this.tenantId, entry.workspaceId, entry.path);
283
+ return this.get(entry.path, entry.workspaceId);
284
+ }
285
+ listQuarantined(limit = 200) {
286
+ const safeLimit = normalizeLimit(limit, 200);
287
+ const rows = this.db.prepare(`
288
+ SELECT *
289
+ FROM task_assets
290
+ WHERE tenant_id = ?
291
+ AND quarantine_status = 'quarantined'
292
+ ORDER BY updated_at DESC
293
+ LIMIT ?
294
+ `).all(this.tenantId, safeLimit);
295
+ return rows.map(mapRow);
296
+ }
297
+ }
@@ -0,0 +1,47 @@
1
+ import type { WorkspaceSyncChange } from './workspaceSyncModel';
2
+ export interface SyncHttpResult<T = unknown> {
3
+ ok: boolean;
4
+ status: number;
5
+ data: T;
6
+ retryAfterMs?: number;
7
+ }
8
+ export declare function pullUserSettings(resolveCloudAuthUrl: (path: string) => string): Promise<SyncHttpResult>;
9
+ export declare function pushUserSettings(resolveCloudAuthUrl: (path: string) => string, payload: {
10
+ settings: Record<string, unknown>;
11
+ updatedAt: string;
12
+ }): Promise<SyncHttpResult>;
13
+ export declare function handshakeWorkspace(resolveCloudAuthUrl: (path: string) => string, workspaceId: string): Promise<SyncHttpResult>;
14
+ export declare function provisionWorkspace(resolveCloudAuthUrl: (path: string) => string, input: {
15
+ workspaceId: string;
16
+ name: string;
17
+ }): Promise<SyncHttpResult>;
18
+ export declare function pullWorkspaceChanges(resolveCloudAuthUrl: (path: string) => string, input: {
19
+ workspaceId: string;
20
+ cursor?: string | null;
21
+ limit: number;
22
+ }): Promise<SyncHttpResult<{
23
+ changes?: WorkspaceSyncChange[];
24
+ nextCursor?: string | null;
25
+ hasMore?: boolean;
26
+ }>>;
27
+ export declare function pushWorkspaceChanges(resolveCloudAuthUrl: (path: string) => string, input: {
28
+ workspaceId: string;
29
+ idempotencyKey: string;
30
+ changes: WorkspaceSyncChange[];
31
+ }): Promise<SyncHttpResult>;
32
+ export declare function bootstrapPushWorkspaceSnapshot(resolveCloudAuthUrl: (path: string) => string, input: {
33
+ workspaceId: string;
34
+ tasks: Array<Record<string, unknown>>;
35
+ archived: Array<Record<string, unknown>>;
36
+ taxonomies?: unknown[];
37
+ documents?: Array<{
38
+ path: string;
39
+ updatedAt: string;
40
+ content: string;
41
+ }>;
42
+ }): Promise<SyncHttpResult>;
43
+ export declare function applyLocalWorkspaceChanges(workspaceId: string, changes: WorkspaceSyncChange[]): Promise<{
44
+ ok: boolean;
45
+ data: unknown;
46
+ failures: string[];
47
+ }>;