wood-fired-tasks 1.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (553) hide show
  1. package/AGENTS.md +112 -0
  2. package/CHANGELOG.md +271 -0
  3. package/CLAUDE.md +21 -0
  4. package/LICENSE +21 -0
  5. package/README.md +687 -0
  6. package/SECURITY.md +299 -0
  7. package/dist/api/hooks/error-handler.d.ts +6 -0
  8. package/dist/api/hooks/error-handler.js +128 -0
  9. package/dist/api/hooks/error-handler.js.map +1 -0
  10. package/dist/api/plugins/auth/index.d.ts +78 -0
  11. package/dist/api/plugins/auth/index.js +300 -0
  12. package/dist/api/plugins/auth/index.js.map +1 -0
  13. package/dist/api/plugins/auth/keys.d.ts +23 -0
  14. package/dist/api/plugins/auth/keys.js +100 -0
  15. package/dist/api/plugins/auth/keys.js.map +1 -0
  16. package/dist/api/plugins/auth/strategies/legacy.d.ts +46 -0
  17. package/dist/api/plugins/auth/strategies/legacy.js +87 -0
  18. package/dist/api/plugins/auth/strategies/legacy.js.map +1 -0
  19. package/dist/api/plugins/auth/strategies/pat.d.ts +37 -0
  20. package/dist/api/plugins/auth/strategies/pat.js +99 -0
  21. package/dist/api/plugins/auth/strategies/pat.js.map +1 -0
  22. package/dist/api/plugins/auth/strategies/session.d.ts +37 -0
  23. package/dist/api/plugins/auth/strategies/session.js +30 -0
  24. package/dist/api/plugins/auth/strategies/session.js.map +1 -0
  25. package/dist/api/plugins/auth/strategies/types.d.ts +12 -0
  26. package/dist/api/plugins/auth/strategies/types.js +2 -0
  27. package/dist/api/plugins/auth/strategies/types.js.map +1 -0
  28. package/dist/api/plugins/auth.d.ts +29 -0
  29. package/dist/api/plugins/auth.js +30 -0
  30. package/dist/api/plugins/auth.js.map +1 -0
  31. package/dist/api/plugins/swagger.d.ts +31 -0
  32. package/dist/api/plugins/swagger.js +83 -0
  33. package/dist/api/plugins/swagger.js.map +1 -0
  34. package/dist/api/routes/auth/auth-error.d.ts +23 -0
  35. package/dist/api/routes/auth/auth-error.js +68 -0
  36. package/dist/api/routes/auth/auth-error.js.map +1 -0
  37. package/dist/api/routes/auth/callback.d.ts +44 -0
  38. package/dist/api/routes/auth/callback.js +175 -0
  39. package/dist/api/routes/auth/callback.js.map +1 -0
  40. package/dist/api/routes/auth/csrf.d.ts +24 -0
  41. package/dist/api/routes/auth/csrf.js +75 -0
  42. package/dist/api/routes/auth/csrf.js.map +1 -0
  43. package/dist/api/routes/auth/device-code.d.ts +41 -0
  44. package/dist/api/routes/auth/device-code.js +51 -0
  45. package/dist/api/routes/auth/device-code.js.map +1 -0
  46. package/dist/api/routes/auth/device-disabled-stub.d.ts +33 -0
  47. package/dist/api/routes/auth/device-disabled-stub.js +16 -0
  48. package/dist/api/routes/auth/device-disabled-stub.js.map +1 -0
  49. package/dist/api/routes/auth/device-html.d.ts +41 -0
  50. package/dist/api/routes/auth/device-html.js +243 -0
  51. package/dist/api/routes/auth/device-html.js.map +1 -0
  52. package/dist/api/routes/auth/device-token.d.ts +38 -0
  53. package/dist/api/routes/auth/device-token.js +153 -0
  54. package/dist/api/routes/auth/device-token.js.map +1 -0
  55. package/dist/api/routes/auth/disabled-stub.d.ts +31 -0
  56. package/dist/api/routes/auth/disabled-stub.js +21 -0
  57. package/dist/api/routes/auth/disabled-stub.js.map +1 -0
  58. package/dist/api/routes/auth/index.d.ts +65 -0
  59. package/dist/api/routes/auth/index.js +47 -0
  60. package/dist/api/routes/auth/index.js.map +1 -0
  61. package/dist/api/routes/auth/login.d.ts +27 -0
  62. package/dist/api/routes/auth/login.js +91 -0
  63. package/dist/api/routes/auth/login.js.map +1 -0
  64. package/dist/api/routes/auth/logout.d.ts +29 -0
  65. package/dist/api/routes/auth/logout.js +43 -0
  66. package/dist/api/routes/auth/logout.js.map +1 -0
  67. package/dist/api/routes/comments/index.d.ts +3 -0
  68. package/dist/api/routes/comments/index.js +74 -0
  69. package/dist/api/routes/comments/index.js.map +1 -0
  70. package/dist/api/routes/comments/schemas.d.ts +37 -0
  71. package/dist/api/routes/comments/schemas.js +24 -0
  72. package/dist/api/routes/comments/schemas.js.map +1 -0
  73. package/dist/api/routes/dependencies/index.d.ts +3 -0
  74. package/dist/api/routes/dependencies/index.js +60 -0
  75. package/dist/api/routes/dependencies/index.js.map +1 -0
  76. package/dist/api/routes/dependencies/schemas.d.ts +24 -0
  77. package/dist/api/routes/dependencies/schemas.js +15 -0
  78. package/dist/api/routes/dependencies/schemas.js.map +1 -0
  79. package/dist/api/routes/events.d.ts +3 -0
  80. package/dist/api/routes/events.js +157 -0
  81. package/dist/api/routes/events.js.map +1 -0
  82. package/dist/api/routes/health.d.ts +27 -0
  83. package/dist/api/routes/health.js +231 -0
  84. package/dist/api/routes/health.js.map +1 -0
  85. package/dist/api/routes/me/index.d.ts +3 -0
  86. package/dist/api/routes/me/index.js +8 -0
  87. package/dist/api/routes/me/index.js.map +1 -0
  88. package/dist/api/routes/me/profile.d.ts +3 -0
  89. package/dist/api/routes/me/profile.js +58 -0
  90. package/dist/api/routes/me/profile.js.map +1 -0
  91. package/dist/api/routes/me/tokens.d.ts +3 -0
  92. package/dist/api/routes/me/tokens.js +410 -0
  93. package/dist/api/routes/me/tokens.js.map +1 -0
  94. package/dist/api/routes/projects/dependency-graph.d.ts +26 -0
  95. package/dist/api/routes/projects/dependency-graph.js +56 -0
  96. package/dist/api/routes/projects/dependency-graph.js.map +1 -0
  97. package/dist/api/routes/projects/index.d.ts +3 -0
  98. package/dist/api/routes/projects/index.js +96 -0
  99. package/dist/api/routes/projects/index.js.map +1 -0
  100. package/dist/api/routes/projects/schemas.d.ts +37 -0
  101. package/dist/api/routes/projects/schemas.js +27 -0
  102. package/dist/api/routes/projects/schemas.js.map +1 -0
  103. package/dist/api/routes/projects/topology.d.ts +27 -0
  104. package/dist/api/routes/projects/topology.js +51 -0
  105. package/dist/api/routes/projects/topology.js.map +1 -0
  106. package/dist/api/routes/tasks/index.d.ts +3 -0
  107. package/dist/api/routes/tasks/index.js +330 -0
  108. package/dist/api/routes/tasks/index.js.map +1 -0
  109. package/dist/api/routes/tasks/schemas.d.ts +316 -0
  110. package/dist/api/routes/tasks/schemas.js +129 -0
  111. package/dist/api/routes/tasks/schemas.js.map +1 -0
  112. package/dist/api/routes/web/index.d.ts +23 -0
  113. package/dist/api/routes/web/index.js +30 -0
  114. package/dist/api/routes/web/index.js.map +1 -0
  115. package/dist/api/routes/web/login.d.ts +20 -0
  116. package/dist/api/routes/web/login.js +20 -0
  117. package/dist/api/routes/web/login.js.map +1 -0
  118. package/dist/api/routes/web/me.d.ts +23 -0
  119. package/dist/api/routes/web/me.js +31 -0
  120. package/dist/api/routes/web/me.js.map +1 -0
  121. package/dist/api/routes/web/tokens.d.ts +29 -0
  122. package/dist/api/routes/web/tokens.js +65 -0
  123. package/dist/api/routes/web/tokens.js.map +1 -0
  124. package/dist/api/server.d.ts +44 -0
  125. package/dist/api/server.js +521 -0
  126. package/dist/api/server.js.map +1 -0
  127. package/dist/api/start.d.ts +1 -0
  128. package/dist/api/start.js +79 -0
  129. package/dist/api/start.js.map +1 -0
  130. package/dist/cli/api/client.d.ts +126 -0
  131. package/dist/cli/api/client.js +408 -0
  132. package/dist/cli/api/client.js.map +1 -0
  133. package/dist/cli/api/errors.d.ts +16 -0
  134. package/dist/cli/api/errors.js +20 -0
  135. package/dist/cli/api/errors.js.map +1 -0
  136. package/dist/cli/api/types.d.ts +205 -0
  137. package/dist/cli/api/types.js +15 -0
  138. package/dist/cli/api/types.js.map +1 -0
  139. package/dist/cli/auth/browser-open.d.ts +1 -0
  140. package/dist/cli/auth/browser-open.js +116 -0
  141. package/dist/cli/auth/browser-open.js.map +1 -0
  142. package/dist/cli/auth/credentials.d.ts +27 -0
  143. package/dist/cli/auth/credentials.js +179 -0
  144. package/dist/cli/auth/credentials.js.map +1 -0
  145. package/dist/cli/auth/device-flow.d.ts +75 -0
  146. package/dist/cli/auth/device-flow.js +149 -0
  147. package/dist/cli/auth/device-flow.js.map +1 -0
  148. package/dist/cli/bin/tasks-client.d.ts +2 -0
  149. package/dist/cli/bin/tasks-client.js +86 -0
  150. package/dist/cli/bin/tasks-client.js.map +1 -0
  151. package/dist/cli/bin/tasks.d.ts +3 -0
  152. package/dist/cli/bin/tasks.js +127 -0
  153. package/dist/cli/bin/tasks.js.map +1 -0
  154. package/dist/cli/commands/backup.d.ts +3 -0
  155. package/dist/cli/commands/backup.js +65 -0
  156. package/dist/cli/commands/backup.js.map +1 -0
  157. package/dist/cli/commands/claim.d.ts +2 -0
  158. package/dist/cli/commands/claim.js +37 -0
  159. package/dist/cli/commands/claim.js.map +1 -0
  160. package/dist/cli/commands/comment-add.d.ts +2 -0
  161. package/dist/cli/commands/comment-add.js +45 -0
  162. package/dist/cli/commands/comment-add.js.map +1 -0
  163. package/dist/cli/commands/comment-delete.d.ts +2 -0
  164. package/dist/cli/commands/comment-delete.js +56 -0
  165. package/dist/cli/commands/comment-delete.js.map +1 -0
  166. package/dist/cli/commands/comment-list.d.ts +2 -0
  167. package/dist/cli/commands/comment-list.js +56 -0
  168. package/dist/cli/commands/comment-list.js.map +1 -0
  169. package/dist/cli/commands/completed.d.ts +10 -0
  170. package/dist/cli/commands/completed.js +168 -0
  171. package/dist/cli/commands/completed.js.map +1 -0
  172. package/dist/cli/commands/completions.d.ts +10 -0
  173. package/dist/cli/commands/completions.js +179 -0
  174. package/dist/cli/commands/completions.js.map +1 -0
  175. package/dist/cli/commands/create.d.ts +2 -0
  176. package/dist/cli/commands/create.js +99 -0
  177. package/dist/cli/commands/create.js.map +1 -0
  178. package/dist/cli/commands/db-check.d.ts +3 -0
  179. package/dist/cli/commands/db-check.js +63 -0
  180. package/dist/cli/commands/db-check.js.map +1 -0
  181. package/dist/cli/commands/db-migrate-identities.d.ts +37 -0
  182. package/dist/cli/commands/db-migrate-identities.js +352 -0
  183. package/dist/cli/commands/db-migrate-identities.js.map +1 -0
  184. package/dist/cli/commands/db-mint-token.d.ts +33 -0
  185. package/dist/cli/commands/db-mint-token.js +150 -0
  186. package/dist/cli/commands/db-mint-token.js.map +1 -0
  187. package/dist/cli/commands/db.d.ts +10 -0
  188. package/dist/cli/commands/db.js +16 -0
  189. package/dist/cli/commands/db.js.map +1 -0
  190. package/dist/cli/commands/delete.d.ts +2 -0
  191. package/dist/cli/commands/delete.js +54 -0
  192. package/dist/cli/commands/delete.js.map +1 -0
  193. package/dist/cli/commands/dep-add.d.ts +2 -0
  194. package/dist/cli/commands/dep-add.js +43 -0
  195. package/dist/cli/commands/dep-add.js.map +1 -0
  196. package/dist/cli/commands/dep-list.d.ts +2 -0
  197. package/dist/cli/commands/dep-list.js +36 -0
  198. package/dist/cli/commands/dep-list.js.map +1 -0
  199. package/dist/cli/commands/dep-remove.d.ts +2 -0
  200. package/dist/cli/commands/dep-remove.js +55 -0
  201. package/dist/cli/commands/dep-remove.js.map +1 -0
  202. package/dist/cli/commands/doctor.d.ts +3 -0
  203. package/dist/cli/commands/doctor.js +139 -0
  204. package/dist/cli/commands/doctor.js.map +1 -0
  205. package/dist/cli/commands/health.d.ts +2 -0
  206. package/dist/cli/commands/health.js +28 -0
  207. package/dist/cli/commands/health.js.map +1 -0
  208. package/dist/cli/commands/list.d.ts +2 -0
  209. package/dist/cli/commands/list.js +103 -0
  210. package/dist/cli/commands/list.js.map +1 -0
  211. package/dist/cli/commands/login.d.ts +2 -0
  212. package/dist/cli/commands/login.js +210 -0
  213. package/dist/cli/commands/login.js.map +1 -0
  214. package/dist/cli/commands/logout.d.ts +31 -0
  215. package/dist/cli/commands/logout.js +184 -0
  216. package/dist/cli/commands/logout.js.map +1 -0
  217. package/dist/cli/commands/project-create.d.ts +2 -0
  218. package/dist/cli/commands/project-create.js +44 -0
  219. package/dist/cli/commands/project-create.js.map +1 -0
  220. package/dist/cli/commands/project-delete.d.ts +2 -0
  221. package/dist/cli/commands/project-delete.js +54 -0
  222. package/dist/cli/commands/project-delete.js.map +1 -0
  223. package/dist/cli/commands/project-list.d.ts +2 -0
  224. package/dist/cli/commands/project-list.js +55 -0
  225. package/dist/cli/commands/project-list.js.map +1 -0
  226. package/dist/cli/commands/project-show.d.ts +2 -0
  227. package/dist/cli/commands/project-show.js +38 -0
  228. package/dist/cli/commands/project-show.js.map +1 -0
  229. package/dist/cli/commands/project-update.d.ts +2 -0
  230. package/dist/cli/commands/project-update.js +56 -0
  231. package/dist/cli/commands/project-update.js.map +1 -0
  232. package/dist/cli/commands/show.d.ts +2 -0
  233. package/dist/cli/commands/show.js +38 -0
  234. package/dist/cli/commands/show.js.map +1 -0
  235. package/dist/cli/commands/stats.d.ts +3 -0
  236. package/dist/cli/commands/stats.js +81 -0
  237. package/dist/cli/commands/stats.js.map +1 -0
  238. package/dist/cli/commands/subtask-create.d.ts +2 -0
  239. package/dist/cli/commands/subtask-create.js +85 -0
  240. package/dist/cli/commands/subtask-create.js.map +1 -0
  241. package/dist/cli/commands/subtask-list.d.ts +2 -0
  242. package/dist/cli/commands/subtask-list.js +61 -0
  243. package/dist/cli/commands/subtask-list.js.map +1 -0
  244. package/dist/cli/commands/topology.d.ts +16 -0
  245. package/dist/cli/commands/topology.js +52 -0
  246. package/dist/cli/commands/topology.js.map +1 -0
  247. package/dist/cli/commands/update.d.ts +2 -0
  248. package/dist/cli/commands/update.js +90 -0
  249. package/dist/cli/commands/update.js.map +1 -0
  250. package/dist/cli/commands/whoami.d.ts +30 -0
  251. package/dist/cli/commands/whoami.js +201 -0
  252. package/dist/cli/commands/whoami.js.map +1 -0
  253. package/dist/cli/config/env.d.ts +4 -0
  254. package/dist/cli/config/env.js +25 -0
  255. package/dist/cli/config/env.js.map +1 -0
  256. package/dist/cli/output/error-handler.d.ts +5 -0
  257. package/dist/cli/output/error-handler.js +41 -0
  258. package/dist/cli/output/error-handler.js.map +1 -0
  259. package/dist/cli/output/formatters.d.ts +86 -0
  260. package/dist/cli/output/formatters.js +352 -0
  261. package/dist/cli/output/formatters.js.map +1 -0
  262. package/dist/cli/output/json-output.d.ts +39 -0
  263. package/dist/cli/output/json-output.js +50 -0
  264. package/dist/cli/output/json-output.js.map +1 -0
  265. package/dist/cli/output/spinner.d.ts +14 -0
  266. package/dist/cli/output/spinner.js +48 -0
  267. package/dist/cli/output/spinner.js.map +1 -0
  268. package/dist/cli/prompts/interactive.d.ts +25 -0
  269. package/dist/cli/prompts/interactive.js +80 -0
  270. package/dist/cli/prompts/interactive.js.map +1 -0
  271. package/dist/config/env.d.ts +182 -0
  272. package/dist/config/env.js +311 -0
  273. package/dist/config/env.js.map +1 -0
  274. package/dist/db/database.d.ts +11 -0
  275. package/dist/db/database.js +25 -0
  276. package/dist/db/database.js.map +1 -0
  277. package/dist/db/migrate.d.ts +10 -0
  278. package/dist/db/migrate.js +137 -0
  279. package/dist/db/migrate.js.map +1 -0
  280. package/dist/db/migrations/001-initial-schema.d.ts +3 -0
  281. package/dist/db/migrations/001-initial-schema.js +100 -0
  282. package/dist/db/migrations/001-initial-schema.js.map +1 -0
  283. package/dist/db/migrations/002-task-hierarchy-and-dependencies.d.ts +3 -0
  284. package/dist/db/migrations/002-task-hierarchy-and-dependencies.js +42 -0
  285. package/dist/db/migrations/002-task-hierarchy-and-dependencies.js.map +1 -0
  286. package/dist/db/migrations/003-comments-and-estimates.d.ts +3 -0
  287. package/dist/db/migrations/003-comments-and-estimates.js +36 -0
  288. package/dist/db/migrations/003-comments-and-estimates.js.map +1 -0
  289. package/dist/db/migrations/004-claim-protocol.d.ts +3 -0
  290. package/dist/db/migrations/004-claim-protocol.js +41 -0
  291. package/dist/db/migrations/004-claim-protocol.js.map +1 -0
  292. package/dist/db/migrations/005-backlogged-status.d.ts +3 -0
  293. package/dist/db/migrations/005-backlogged-status.js +156 -0
  294. package/dist/db/migrations/005-backlogged-status.js.map +1 -0
  295. package/dist/db/migrations/006-slack-channel-subscriptions.d.ts +3 -0
  296. package/dist/db/migrations/006-slack-channel-subscriptions.js +23 -0
  297. package/dist/db/migrations/006-slack-channel-subscriptions.js.map +1 -0
  298. package/dist/db/migrations/007-completed-at.d.ts +19 -0
  299. package/dist/db/migrations/007-completed-at.js +36 -0
  300. package/dist/db/migrations/007-completed-at.js.map +1 -0
  301. package/dist/db/migrations/008-identity-tables.d.ts +21 -0
  302. package/dist/db/migrations/008-identity-tables.js +84 -0
  303. package/dist/db/migrations/008-identity-tables.js.map +1 -0
  304. package/dist/db/migrations/009-parallel-fk-columns.d.ts +33 -0
  305. package/dist/db/migrations/009-parallel-fk-columns.js +62 -0
  306. package/dist/db/migrations/009-parallel-fk-columns.js.map +1 -0
  307. package/dist/db/migrations/010-identity-uniqueness-indexes.d.ts +47 -0
  308. package/dist/db/migrations/010-identity-uniqueness-indexes.js +65 -0
  309. package/dist/db/migrations/010-identity-uniqueness-indexes.js.map +1 -0
  310. package/dist/db/migrations/011-acceptance-criteria.d.ts +30 -0
  311. package/dist/db/migrations/011-acceptance-criteria.js +41 -0
  312. package/dist/db/migrations/011-acceptance-criteria.js.map +1 -0
  313. package/dist/db/migrations/012-verification-evidence.d.ts +41 -0
  314. package/dist/db/migrations/012-verification-evidence.js +49 -0
  315. package/dist/db/migrations/012-verification-evidence.js.map +1 -0
  316. package/dist/events/event-bus.d.ts +101 -0
  317. package/dist/events/event-bus.js +184 -0
  318. package/dist/events/event-bus.js.map +1 -0
  319. package/dist/events/sse-manager.d.ts +79 -0
  320. package/dist/events/sse-manager.js +220 -0
  321. package/dist/events/sse-manager.js.map +1 -0
  322. package/dist/events/types.d.ts +43 -0
  323. package/dist/events/types.js +22 -0
  324. package/dist/events/types.js.map +1 -0
  325. package/dist/index.d.ts +110 -0
  326. package/dist/index.js +209 -0
  327. package/dist/index.js.map +1 -0
  328. package/dist/lib/audit/schema.d.ts +201 -0
  329. package/dist/lib/audit/schema.js +141 -0
  330. package/dist/lib/audit/schema.js.map +1 -0
  331. package/dist/lib/decompose/schema.d.ts +157 -0
  332. package/dist/lib/decompose/schema.js +138 -0
  333. package/dist/lib/decompose/schema.js.map +1 -0
  334. package/dist/lib/loop-run/integration-audit-schema.d.ts +78 -0
  335. package/dist/lib/loop-run/integration-audit-schema.js +68 -0
  336. package/dist/lib/loop-run/integration-audit-schema.js.map +1 -0
  337. package/dist/lib/loop-run/schema.d.ts +49 -0
  338. package/dist/lib/loop-run/schema.js +67 -0
  339. package/dist/lib/loop-run/schema.js.map +1 -0
  340. package/dist/mcp/errors.d.ts +11 -0
  341. package/dist/mcp/errors.js +29 -0
  342. package/dist/mcp/errors.js.map +1 -0
  343. package/dist/mcp/identity-resolution.d.ts +76 -0
  344. package/dist/mcp/identity-resolution.js +189 -0
  345. package/dist/mcp/identity-resolution.js.map +1 -0
  346. package/dist/mcp/index.d.ts +1 -0
  347. package/dist/mcp/index.js +126 -0
  348. package/dist/mcp/index.js.map +1 -0
  349. package/dist/mcp/remote/index.d.ts +21 -0
  350. package/dist/mcp/remote/index.js +95 -0
  351. package/dist/mcp/remote/index.js.map +1 -0
  352. package/dist/mcp/remote/register-tools.d.ts +26 -0
  353. package/dist/mcp/remote/register-tools.js +751 -0
  354. package/dist/mcp/remote/register-tools.js.map +1 -0
  355. package/dist/mcp/remote/rest-client.d.ts +66 -0
  356. package/dist/mcp/remote/rest-client.js +300 -0
  357. package/dist/mcp/remote/rest-client.js.map +1 -0
  358. package/dist/mcp/resources/events.d.ts +28 -0
  359. package/dist/mcp/resources/events.js +98 -0
  360. package/dist/mcp/resources/events.js.map +1 -0
  361. package/dist/mcp/server.d.ts +59 -0
  362. package/dist/mcp/server.js +72 -0
  363. package/dist/mcp/server.js.map +1 -0
  364. package/dist/mcp/tools/comment-tools.d.ts +12 -0
  365. package/dist/mcp/tools/comment-tools.js +115 -0
  366. package/dist/mcp/tools/comment-tools.js.map +1 -0
  367. package/dist/mcp/tools/dependency-tools.d.ts +3 -0
  368. package/dist/mcp/tools/dependency-tools.js +91 -0
  369. package/dist/mcp/tools/dependency-tools.js.map +1 -0
  370. package/dist/mcp/tools/health-tools.d.ts +9 -0
  371. package/dist/mcp/tools/health-tools.js +82 -0
  372. package/dist/mcp/tools/health-tools.js.map +1 -0
  373. package/dist/mcp/tools/project-tools.d.ts +13 -0
  374. package/dist/mcp/tools/project-tools.js +167 -0
  375. package/dist/mcp/tools/project-tools.js.map +1 -0
  376. package/dist/mcp/tools/task-tools.d.ts +41 -0
  377. package/dist/mcp/tools/task-tools.js +434 -0
  378. package/dist/mcp/tools/task-tools.js.map +1 -0
  379. package/dist/mcp/tools/topology-tools.d.ts +14 -0
  380. package/dist/mcp/tools/topology-tools.js +46 -0
  381. package/dist/mcp/tools/topology-tools.js.map +1 -0
  382. package/dist/repositories/api-token.repository.d.ts +40 -0
  383. package/dist/repositories/api-token.repository.js +63 -0
  384. package/dist/repositories/api-token.repository.js.map +1 -0
  385. package/dist/repositories/comment.repository.d.ts +17 -0
  386. package/dist/repositories/comment.repository.js +73 -0
  387. package/dist/repositories/comment.repository.js.map +1 -0
  388. package/dist/repositories/dependency.repository.d.ts +19 -0
  389. package/dist/repositories/dependency.repository.js +55 -0
  390. package/dist/repositories/dependency.repository.js.map +1 -0
  391. package/dist/repositories/errors.d.ts +29 -0
  392. package/dist/repositories/errors.js +48 -0
  393. package/dist/repositories/errors.js.map +1 -0
  394. package/dist/repositories/interfaces.d.ts +200 -0
  395. package/dist/repositories/interfaces.js +2 -0
  396. package/dist/repositories/interfaces.js.map +1 -0
  397. package/dist/repositories/project.repository.d.ts +21 -0
  398. package/dist/repositories/project.repository.js +97 -0
  399. package/dist/repositories/project.repository.js.map +1 -0
  400. package/dist/repositories/row-mapper.d.ts +40 -0
  401. package/dist/repositories/row-mapper.js +38 -0
  402. package/dist/repositories/row-mapper.js.map +1 -0
  403. package/dist/repositories/task.repository.d.ts +45 -0
  404. package/dist/repositories/task.repository.js +612 -0
  405. package/dist/repositories/task.repository.js.map +1 -0
  406. package/dist/repositories/types.d.ts +20 -0
  407. package/dist/repositories/types.js +11 -0
  408. package/dist/repositories/types.js.map +1 -0
  409. package/dist/repositories/user.repository.d.ts +121 -0
  410. package/dist/repositories/user.repository.js +209 -0
  411. package/dist/repositories/user.repository.js.map +1 -0
  412. package/dist/schemas/comment.schema.d.ts +24 -0
  413. package/dist/schemas/comment.schema.js +27 -0
  414. package/dist/schemas/comment.schema.js.map +1 -0
  415. package/dist/schemas/dependency-graph.schema.d.ts +181 -0
  416. package/dist/schemas/dependency-graph.schema.js +98 -0
  417. package/dist/schemas/dependency-graph.schema.js.map +1 -0
  418. package/dist/schemas/dependency.schema.d.ts +9 -0
  419. package/dist/schemas/dependency.schema.js +16 -0
  420. package/dist/schemas/dependency.schema.js.map +1 -0
  421. package/dist/schemas/idempotency.schema.d.ts +18 -0
  422. package/dist/schemas/idempotency.schema.js +22 -0
  423. package/dist/schemas/idempotency.schema.js.map +1 -0
  424. package/dist/schemas/task.schema.d.ts +369 -0
  425. package/dist/schemas/task.schema.js +276 -0
  426. package/dist/schemas/task.schema.js.map +1 -0
  427. package/dist/schemas/topology.schema.d.ts +56 -0
  428. package/dist/schemas/topology.schema.js +48 -0
  429. package/dist/schemas/topology.schema.js.map +1 -0
  430. package/dist/services/auth-audit.d.ts +46 -0
  431. package/dist/services/auth-audit.js +28 -0
  432. package/dist/services/auth-audit.js.map +1 -0
  433. package/dist/services/claim-release.service.d.ts +42 -0
  434. package/dist/services/claim-release.service.js +90 -0
  435. package/dist/services/claim-release.service.js.map +1 -0
  436. package/dist/services/comment.service.d.ts +44 -0
  437. package/dist/services/comment.service.js +96 -0
  438. package/dist/services/comment.service.js.map +1 -0
  439. package/dist/services/dependency-graph.service.d.ts +33 -0
  440. package/dist/services/dependency-graph.service.js +453 -0
  441. package/dist/services/dependency-graph.service.js.map +1 -0
  442. package/dist/services/dependency.service.d.ts +32 -0
  443. package/dist/services/dependency.service.js +79 -0
  444. package/dist/services/dependency.service.js.map +1 -0
  445. package/dist/services/device-flow-store.d.ts +155 -0
  446. package/dist/services/device-flow-store.js +323 -0
  447. package/dist/services/device-flow-store.js.map +1 -0
  448. package/dist/services/errors.d.ts +28 -0
  449. package/dist/services/errors.js +44 -0
  450. package/dist/services/errors.js.map +1 -0
  451. package/dist/services/idempotency.service.d.ts +37 -0
  452. package/dist/services/idempotency.service.js +54 -0
  453. package/dist/services/idempotency.service.js.map +1 -0
  454. package/dist/services/identity-seeder.d.ts +56 -0
  455. package/dist/services/identity-seeder.js +131 -0
  456. package/dist/services/identity-seeder.js.map +1 -0
  457. package/dist/services/oidc-boot.d.ts +73 -0
  458. package/dist/services/oidc-boot.js +66 -0
  459. package/dist/services/oidc-boot.js.map +1 -0
  460. package/dist/services/oidc-client.d.ts +99 -0
  461. package/dist/services/oidc-client.js +108 -0
  462. package/dist/services/oidc-client.js.map +1 -0
  463. package/dist/services/pat-hash.d.ts +23 -0
  464. package/dist/services/pat-hash.js +73 -0
  465. package/dist/services/pat-hash.js.map +1 -0
  466. package/dist/services/pat-touch-debounce.d.ts +65 -0
  467. package/dist/services/pat-touch-debounce.js +82 -0
  468. package/dist/services/pat-touch-debounce.js.map +1 -0
  469. package/dist/services/project.service.d.ts +41 -0
  470. package/dist/services/project.service.js +133 -0
  471. package/dist/services/project.service.js.map +1 -0
  472. package/dist/services/slack.service.d.ts +31 -0
  473. package/dist/services/slack.service.js +52 -0
  474. package/dist/services/slack.service.js.map +1 -0
  475. package/dist/services/task.service.d.ts +151 -0
  476. package/dist/services/task.service.js +425 -0
  477. package/dist/services/task.service.js.map +1 -0
  478. package/dist/services/topology.service.d.ts +65 -0
  479. package/dist/services/topology.service.js +170 -0
  480. package/dist/services/topology.service.js.map +1 -0
  481. package/dist/services/user-upsert.d.ts +43 -0
  482. package/dist/services/user-upsert.js +53 -0
  483. package/dist/services/user-upsert.js.map +1 -0
  484. package/dist/services/workflow-engine.d.ts +93 -0
  485. package/dist/services/workflow-engine.js +250 -0
  486. package/dist/services/workflow-engine.js.map +1 -0
  487. package/dist/slack/commands/tasks-command.d.ts +88 -0
  488. package/dist/slack/commands/tasks-command.js +920 -0
  489. package/dist/slack/commands/tasks-command.js.map +1 -0
  490. package/dist/slack/formatters/project-formatter.d.ts +19 -0
  491. package/dist/slack/formatters/project-formatter.js +94 -0
  492. package/dist/slack/formatters/project-formatter.js.map +1 -0
  493. package/dist/slack/notifier.d.ts +41 -0
  494. package/dist/slack/notifier.js +111 -0
  495. package/dist/slack/notifier.js.map +1 -0
  496. package/dist/slack/repositories/channel-subscription.repository.d.ts +25 -0
  497. package/dist/slack/repositories/channel-subscription.repository.js +51 -0
  498. package/dist/slack/repositories/channel-subscription.repository.js.map +1 -0
  499. package/dist/slack/task-formatter.d.ts +31 -0
  500. package/dist/slack/task-formatter.js +151 -0
  501. package/dist/slack/task-formatter.js.map +1 -0
  502. package/dist/slack/user-identity.d.ts +37 -0
  503. package/dist/slack/user-identity.js +70 -0
  504. package/dist/slack/user-identity.js.map +1 -0
  505. package/dist/types/identity.d.ts +84 -0
  506. package/dist/types/identity.js +6 -0
  507. package/dist/types/identity.js.map +1 -0
  508. package/dist/types/task.d.ts +202 -0
  509. package/dist/types/task.js +17 -0
  510. package/dist/types/task.js.map +1 -0
  511. package/dist/utils/cycle-detector.d.ts +25 -0
  512. package/dist/utils/cycle-detector.js +86 -0
  513. package/dist/utils/cycle-detector.js.map +1 -0
  514. package/dist/utils/exit-codes.d.ts +64 -0
  515. package/dist/utils/exit-codes.js +57 -0
  516. package/dist/utils/exit-codes.js.map +1 -0
  517. package/dist/utils/is-main.d.ts +12 -0
  518. package/dist/utils/is-main.js +24 -0
  519. package/dist/utils/is-main.js.map +1 -0
  520. package/dist/utils/version.d.ts +1 -0
  521. package/dist/utils/version.js +22 -0
  522. package/dist/utils/version.js.map +1 -0
  523. package/dist/web/html.d.ts +73 -0
  524. package/dist/web/html.js +154 -0
  525. package/dist/web/html.js.map +1 -0
  526. package/dist/web/pages/device.d.ts +19 -0
  527. package/dist/web/pages/device.js +76 -0
  528. package/dist/web/pages/device.js.map +1 -0
  529. package/dist/web/pages/error.d.ts +6 -0
  530. package/dist/web/pages/error.js +23 -0
  531. package/dist/web/pages/error.js.map +1 -0
  532. package/dist/web/pages/login.d.ts +5 -0
  533. package/dist/web/pages/login.js +22 -0
  534. package/dist/web/pages/login.js.map +1 -0
  535. package/dist/web/pages/me.d.ts +9 -0
  536. package/dist/web/pages/me.js +37 -0
  537. package/dist/web/pages/me.js.map +1 -0
  538. package/dist/web/pages/tokens.d.ts +20 -0
  539. package/dist/web/pages/tokens.js +89 -0
  540. package/dist/web/pages/tokens.js.map +1 -0
  541. package/dist/web/session-constants.d.ts +21 -0
  542. package/dist/web/session-constants.js +22 -0
  543. package/dist/web/session-constants.js.map +1 -0
  544. package/dist/web/session-flash.d.ts +15 -0
  545. package/dist/web/session-flash.js +11 -0
  546. package/dist/web/session-flash.js.map +1 -0
  547. package/dist/web/session-user.d.ts +59 -0
  548. package/dist/web/session-user.js +44 -0
  549. package/dist/web/session-user.js.map +1 -0
  550. package/docs/AGENT_CONTEXT.md +280 -0
  551. package/docs/README.md +49 -0
  552. package/llms.txt +33 -0
  553. package/package.json +129 -0
@@ -0,0 +1,276 @@
1
+ import { z } from 'zod';
2
+ import { TASK_STATUSES, TASK_PRIORITIES } from '../types/task.js';
3
+ /**
4
+ * Wave 1.4 (task #312): verdict enum for the verification_evidence envelope.
5
+ *
6
+ * - PASS — verifier confirmed the task's acceptance criteria.
7
+ * - FAIL — verifier ran the checks and at least one failed.
8
+ * - PARTIAL — some checks passed, some failed/skipped.
9
+ * - NOT_VERIFIED — task closed without verification (auto-materialized by the
10
+ * service layer when status -> done/closed and no evidence
11
+ * was supplied). Explicitly distinct from "evidence absent
12
+ * because the column is NULL" — see service updateTask.
13
+ */
14
+ export const VERIFICATION_VERDICTS = [
15
+ 'PASS',
16
+ 'FAIL',
17
+ 'PARTIAL',
18
+ 'NOT_VERIFIED',
19
+ ];
20
+ /**
21
+ * Per-check status — tighter than the top-level verdict because a single
22
+ * check is a leaf (it either ran, or was skipped). Kept narrow on purpose so
23
+ * the boundary rejects free-form strings ("ok", "good", etc.) and forces
24
+ * verifier subagents to pick one of the three values.
25
+ */
26
+ export const VERIFICATION_CHECK_STATUSES = ['PASS', 'FAIL', 'SKIP'];
27
+ /**
28
+ * Structured verification evidence stored in `tasks.verification_evidence`
29
+ * as a JSON string (write: JSON.stringify; read: JSON.parse — both happen
30
+ * inside the repository).
31
+ *
32
+ * Only `verdict` is required. Every other field is optional so the
33
+ * auto-NOT_VERIFIED materialization on close (service-layer behavior — see
34
+ * task.service.ts updateTask) can emit `{verdict: "NOT_VERIFIED"}` without
35
+ * lying about a verified_at timestamp or fabricating a session id.
36
+ *
37
+ * Bounds:
38
+ * - `checks` capped at 50 entries (a single task does not realistically
39
+ * accumulate more verification gates than that; the cap bounds row size).
40
+ * - `evidence_url_or_text` capped at 2000 chars per entry.
41
+ * - identifier strings capped at 200 chars.
42
+ */
43
+ export const VerificationEvidenceSchema = z.object({
44
+ verdict: z.enum(VERIFICATION_VERDICTS),
45
+ checks: z
46
+ .array(z.object({
47
+ name: z.string().min(1).max(200),
48
+ status: z.enum(VERIFICATION_CHECK_STATUSES),
49
+ evidence_url_or_text: z.string().max(2000),
50
+ }))
51
+ .max(50)
52
+ .optional(),
53
+ verifier_session_id: z.string().min(1).max(200).optional(),
54
+ verifier_request_id: z.string().min(1).max(200).optional(),
55
+ verified_at: z.string().datetime().optional(),
56
+ }).strict();
57
+ /**
58
+ * CreateTaskSchema - validation for creating new tasks
59
+ * Note: status is NOT included - new tasks always start as 'open'
60
+ */
61
+ export const CreateTaskSchema = z.object({
62
+ title: z.string().min(1, 'Title is required').max(255, 'Title must be 255 characters or less'),
63
+ description: z.string().max(5000).optional().nullable(),
64
+ priority: z.enum(TASK_PRIORITIES).default('medium'),
65
+ project_id: z.number().int().positive('Project ID must be a positive integer'),
66
+ parent_task_id: z.number().int().positive().optional().nullable(),
67
+ estimated_minutes: z.number().int().min(0).max(10080).optional().nullable(),
68
+ assignee: z.string().max(100).optional().nullable(),
69
+ created_by: z.string().min(1, 'Created by is required').max(100),
70
+ due_date: z.string().datetime({ message: 'Due date must be ISO8601 format' }).optional().nullable(),
71
+ tags: z.array(z.string().min(1).max(50)).max(20).optional().default([]),
72
+ // Wave 1.3 (task #311): free-form plain-text acceptance criteria. Clients
73
+ // supply this on create to make "what would prove this is done?" structured
74
+ // rather than buried in the description field. Multi-line markdown is fine.
75
+ // No DB constraint — the 5000-char cap is a schema-layer business rule.
76
+ acceptance_criteria: z.string().max(5000).optional().nullable(),
77
+ // Phase 31 (Plan 31-01): optional FK fields. NOTE — these are server-derived
78
+ // at route boundaries (T-31-02 of 31-01-PLAN threat register): downstream
79
+ // plans STRIP body-supplied values and set them from request.user / Slack
80
+ // lookup / MCP boot. They are accepted here only so service/repository
81
+ // call sites can pass them through.
82
+ created_by_user_id: z.number().int().positive().optional().nullable(),
83
+ assignee_user_id: z.number().int().positive().optional().nullable(),
84
+ });
85
+ /**
86
+ * Client-facing variant of CreateTaskSchema for MCP tool registration
87
+ * (Phase 31 review WR-04). Omits the server-derived FK fields
88
+ * (`created_by_user_id`, `assignee_user_id`) so a client supplying them
89
+ * gets a clear validation error instead of having the values silently
90
+ * stripped by the route handler.
91
+ *
92
+ * The service-layer `CreateTaskSchema` still accepts them because
93
+ * internal callers (routes, MCP handlers) populate them from
94
+ * request.user / boot-time context. This separation makes the public
95
+ * API surface honest about what fields clients control.
96
+ */
97
+ export const CreateTaskClientSchema = CreateTaskSchema.omit({
98
+ created_by_user_id: true,
99
+ assignee_user_id: true,
100
+ }).strict();
101
+ /**
102
+ * UpdateTaskSchema - validation for updating tasks
103
+ * All fields are optional (partial updates)
104
+ */
105
+ export const UpdateTaskSchema = z.object({
106
+ title: z.string().min(1).max(255),
107
+ description: z.string().max(5000).nullable(),
108
+ status: z.enum(TASK_STATUSES),
109
+ priority: z.enum(TASK_PRIORITIES),
110
+ parent_task_id: z.number().int().positive().nullable(),
111
+ estimated_minutes: z.number().int().min(0).max(10080).nullable(),
112
+ assignee: z.string().max(100).nullable(),
113
+ due_date: z.string().datetime().nullable(),
114
+ tags: z.array(z.string().min(1).max(50)).max(20),
115
+ // Phase 31 (Plan 31-01): optional FK field. Server-derived at the route
116
+ // boundary (T-31-02) — downstream plans STRIP body-supplied values.
117
+ assignee_user_id: z.number().int().positive().nullable(),
118
+ // Wave 1.3 (task #311): patch acceptance_criteria on existing tasks.
119
+ // Pass null to clear, a string to set. Same 5000-char cap as create.
120
+ acceptance_criteria: z.string().max(5000).nullable(),
121
+ // Wave 1.4 (task #312): structured verification evidence. The Zod enum on
122
+ // `verdict` rejects unknown values at the boundary (the "unknown verdict =
123
+ // 400" contract). Pass null to clear, an object to set. Stored as a JSON
124
+ // string by the repository.
125
+ verification_evidence: VerificationEvidenceSchema.nullable(),
126
+ }).partial();
127
+ /**
128
+ * Client-facing variant of UpdateTaskSchema for MCP tool registration
129
+ * (Phase 31 review WR-04). Omits the server-derived `assignee_user_id`
130
+ * FK; clients update the FK indirectly by supplying `assignee` (an email
131
+ * or display name), which the MCP handler resolves server-side via
132
+ * `resolveAssigneeUserId`.
133
+ */
134
+ export const UpdateTaskClientSchema = z.object({
135
+ title: z.string().min(1).max(255),
136
+ description: z.string().max(5000).nullable(),
137
+ status: z.enum(TASK_STATUSES),
138
+ priority: z.enum(TASK_PRIORITIES),
139
+ parent_task_id: z.number().int().positive().nullable(),
140
+ estimated_minutes: z.number().int().min(0).max(10080).nullable(),
141
+ assignee: z.string().max(100).nullable(),
142
+ due_date: z.string().datetime().nullable(),
143
+ tags: z.array(z.string().min(1).max(50)).max(20),
144
+ // Wave 1.3 (task #311): clients can patch acceptance_criteria — it is
145
+ // NOT server-derived, so it stays on the client-facing schema.
146
+ acceptance_criteria: z.string().max(5000).nullable(),
147
+ // Wave 1.4 (task #312): verifier subagents call update_task with this
148
+ // envelope. It is NOT server-derived, so it stays on the client-facing
149
+ // schema. Unknown verdicts get rejected at the Zod boundary.
150
+ verification_evidence: VerificationEvidenceSchema.nullable(),
151
+ }).partial().strict();
152
+ /**
153
+ * CreateProjectSchema - validation for creating new projects
154
+ */
155
+ export const CreateProjectSchema = z.object({
156
+ name: z.string().min(1, 'Name is required').max(100, 'Name must be 100 characters or less'),
157
+ description: z.string().max(1000).optional().nullable(),
158
+ });
159
+ /**
160
+ * Pagination bounds applied to all list endpoints.
161
+ *
162
+ * `limit` — page size; capped at 500 to bound query cost (GROUP_CONCAT
163
+ * over task_tags scales with row count).
164
+ * `offset` — starting row, zero-based.
165
+ *
166
+ * Both fields default to safe values so existing callers that omit them
167
+ * receive the first page (50 rows) rather than the full table.
168
+ */
169
+ export const PaginationSchema = z.object({
170
+ limit: z.coerce.number().int().positive().max(500).default(50),
171
+ offset: z.coerce.number().int().nonnegative().default(0),
172
+ });
173
+ /**
174
+ * Optional pagination — same bounds, but each field can be omitted entirely.
175
+ * Used inside service-level filter parsing where defaults are applied later.
176
+ */
177
+ export const PaginationOptionalSchema = z.object({
178
+ limit: z.coerce.number().int().positive().max(500).optional(),
179
+ offset: z.coerce.number().int().nonnegative().optional(),
180
+ });
181
+ /**
182
+ * Wrap a row schema in the standard paginated envelope:
183
+ * { data: [...], total, limit, offset }
184
+ *
185
+ * `total` is the unbounded count for the same filter set, so clients can
186
+ * implement page navigation without re-issuing without filters.
187
+ */
188
+ export function paginatedSchema(itemSchema) {
189
+ return z.object({
190
+ data: z.array(itemSchema),
191
+ total: z.number().int().nonnegative(),
192
+ limit: z.number().int().positive(),
193
+ offset: z.number().int().nonnegative(),
194
+ });
195
+ }
196
+ /**
197
+ * TaskFiltersSchema - validation for task filtering
198
+ * All fields are optional. Includes pagination knobs (limit/offset).
199
+ */
200
+ export const TaskFiltersSchema = z.object({
201
+ project_id: z.number().int().positive(),
202
+ status: z.enum(TASK_STATUSES),
203
+ assignee: z.string(),
204
+ tags: z.array(z.string()),
205
+ due_before: z.string().datetime(),
206
+ due_after: z.string().datetime(),
207
+ updated_before: z.string().datetime(),
208
+ updated_after: z.string().datetime(),
209
+ search: z
210
+ .string()
211
+ .min(1)
212
+ .max(200)
213
+ .refine((s) => s.trim().split(/\s+/).filter(Boolean).length <= 32, { message: 'Search query must contain at most 32 terms.' }),
214
+ // Wave 1.4 (#312): verified-state filter. See TaskFilters.verified in
215
+ // src/types/task.ts for semantics. The repository builds the
216
+ // json_extract(verification_evidence, '$.verdict') predicate.
217
+ verified: z.boolean(),
218
+ limit: z.coerce.number().int().positive().max(500),
219
+ offset: z.coerce.number().int().nonnegative(),
220
+ }).partial();
221
+ /**
222
+ * ListTasksMcpSchema - filters plus MCP-only knobs.
223
+ *
224
+ * `verbose` opts back into full task bodies (description + audit fields).
225
+ * Default response is a compact projection to keep MCP tool result payloads
226
+ * within reasonable token budgets — full data is still available via get_task.
227
+ */
228
+ export const ListTasksMcpSchema = TaskFiltersSchema.extend({
229
+ verbose: z.boolean().optional(),
230
+ });
231
+ /**
232
+ * Strip heavy/audit fields from a task for use in list responses. Keeps the
233
+ * fields a caller needs to decide whether to drill into a task with get_task.
234
+ *
235
+ * `parent_task_id` is optional because the remote REST TaskResponse does not
236
+ * surface it; in-process Task does. The compact projection includes it when
237
+ * present so callers can still see hierarchy.
238
+ */
239
+ export function toCompactTask(task) {
240
+ return {
241
+ id: task.id,
242
+ title: task.title,
243
+ status: task.status,
244
+ priority: task.priority,
245
+ project_id: task.project_id,
246
+ parent_task_id: task.parent_task_id ?? null,
247
+ assignee: task.assignee,
248
+ due_date: task.due_date,
249
+ tags: task.tags,
250
+ };
251
+ }
252
+ /**
253
+ * ClaimTaskSchema - validation for claiming a task
254
+ */
255
+ export const ClaimTaskSchema = z.object({
256
+ assignee: z.string().min(1, 'Assignee is required').max(100),
257
+ });
258
+ /**
259
+ * CompletionReportSchema - validation for `getCompletionReport`.
260
+ *
261
+ * Caller supplies EITHER `days` (trailing N days from now, max 365) OR an
262
+ * explicit `start`/`end` pair (both ISO8601, end >= start). Optional
263
+ * `project_id` and `assignee` filters narrow the result set.
264
+ */
265
+ export const CompletionReportSchema = z
266
+ .object({
267
+ days: z.number().int().min(1).max(365).optional(),
268
+ start: z.string().datetime().optional(),
269
+ end: z.string().datetime().optional(),
270
+ project_id: z.number().int().positive().optional(),
271
+ assignee: z.string().min(1).max(100).optional(),
272
+ })
273
+ .refine((v) => v.days !== undefined || (v.start !== undefined && v.end !== undefined), { message: 'Provide either `days` or both `start` and `end`' })
274
+ .refine((v) => v.days !== undefined ||
275
+ (v.start !== undefined && v.end !== undefined && v.end >= v.start), { message: '`end` must be greater than or equal to `start`' });
276
+ //# sourceMappingURL=task.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"task.schema.js","sourceRoot":"","sources":["../../src/schemas/task.schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Wave 4.1 (task #318) — Task-topology classifier output contract.
4
+ *
5
+ * `TopologyReportSchema` is the wire-shape returned by:
6
+ * - `TopologyService.classify(projectId)`
7
+ * - the `tasks topology --project <id>` CLI command (stdout JSON)
8
+ * - the `topology_check` MCP tool (structuredContent)
9
+ *
10
+ * The classifier decides whether a project is `/tasks:loop`-safe (parallelizable
11
+ * leaves) or requires `/tasks:loop-dag` (wave-by-wave parallel dispatch
12
+ * respecting dependency edges; Wave 4.3 / task #341) based on whether the
13
+ * project's `task_dependencies` rows form a flat set, an acyclic DAG, or a
14
+ * cycle-bearing graph.
15
+ *
16
+ * Field semantics:
17
+ * - `topology`:
18
+ * FLAT — zero `task_dependencies` edges in the project.
19
+ * DAG — ≥1 edge, no cycles (a total order exists).
20
+ * DAG_CYCLIC — ≥1 edge, contains a cycle (`/tasks:loop` is unsafe).
21
+ * - `edges`: `{from, to}` rows where `from` blocks `to` (i.e. `from` must
22
+ * complete before `to` can start). Derived from `task_dependencies`
23
+ * (`task_id → blocks_task_id`). Sorted by (from asc, to asc) for
24
+ * deterministic comparison across runs.
25
+ * - `roots`: task IDs with zero in-degree (no task blocks them). Sorted asc.
26
+ * - `leaves`: task IDs with zero out-degree (they block nothing). Sorted asc.
27
+ * - `advisory`:
28
+ * `/tasks:loop` — recommended for FLAT projects.
29
+ * `/tasks:loop-dag` — recommended for DAG projects (Wave 4.3 / #341).
30
+ * `BLOCKED` — refuse to loop; manual intervention needed for
31
+ * DAG_CYCLIC projects.
32
+ *
33
+ * NOTE: `parent_task_id` (the taxonomy column) is INCLUDED in node enumeration
34
+ * (we know about parent/child rows) but NOT counted as graph edges — per AC
35
+ * "excluding parent/child taxonomy edges". The only edge source is the
36
+ * `task_dependencies` table.
37
+ */
38
+ export declare const TopologyReportSchema: z.ZodObject<{
39
+ topology: z.ZodEnum<{
40
+ FLAT: "FLAT";
41
+ DAG: "DAG";
42
+ DAG_CYCLIC: "DAG_CYCLIC";
43
+ }>;
44
+ edges: z.ZodArray<z.ZodObject<{
45
+ from: z.ZodNumber;
46
+ to: z.ZodNumber;
47
+ }, z.core.$strip>>;
48
+ roots: z.ZodArray<z.ZodNumber>;
49
+ leaves: z.ZodArray<z.ZodNumber>;
50
+ advisory: z.ZodEnum<{
51
+ "/tasks:loop": "/tasks:loop";
52
+ "/tasks:loop-dag": "/tasks:loop-dag";
53
+ BLOCKED: "BLOCKED";
54
+ }>;
55
+ }, z.core.$strip>;
56
+ export type TopologyReport = z.infer<typeof TopologyReportSchema>;
@@ -0,0 +1,48 @@
1
+ import { z } from 'zod';
2
+ /**
3
+ * Wave 4.1 (task #318) — Task-topology classifier output contract.
4
+ *
5
+ * `TopologyReportSchema` is the wire-shape returned by:
6
+ * - `TopologyService.classify(projectId)`
7
+ * - the `tasks topology --project <id>` CLI command (stdout JSON)
8
+ * - the `topology_check` MCP tool (structuredContent)
9
+ *
10
+ * The classifier decides whether a project is `/tasks:loop`-safe (parallelizable
11
+ * leaves) or requires `/tasks:loop-dag` (wave-by-wave parallel dispatch
12
+ * respecting dependency edges; Wave 4.3 / task #341) based on whether the
13
+ * project's `task_dependencies` rows form a flat set, an acyclic DAG, or a
14
+ * cycle-bearing graph.
15
+ *
16
+ * Field semantics:
17
+ * - `topology`:
18
+ * FLAT — zero `task_dependencies` edges in the project.
19
+ * DAG — ≥1 edge, no cycles (a total order exists).
20
+ * DAG_CYCLIC — ≥1 edge, contains a cycle (`/tasks:loop` is unsafe).
21
+ * - `edges`: `{from, to}` rows where `from` blocks `to` (i.e. `from` must
22
+ * complete before `to` can start). Derived from `task_dependencies`
23
+ * (`task_id → blocks_task_id`). Sorted by (from asc, to asc) for
24
+ * deterministic comparison across runs.
25
+ * - `roots`: task IDs with zero in-degree (no task blocks them). Sorted asc.
26
+ * - `leaves`: task IDs with zero out-degree (they block nothing). Sorted asc.
27
+ * - `advisory`:
28
+ * `/tasks:loop` — recommended for FLAT projects.
29
+ * `/tasks:loop-dag` — recommended for DAG projects (Wave 4.3 / #341).
30
+ * `BLOCKED` — refuse to loop; manual intervention needed for
31
+ * DAG_CYCLIC projects.
32
+ *
33
+ * NOTE: `parent_task_id` (the taxonomy column) is INCLUDED in node enumeration
34
+ * (we know about parent/child rows) but NOT counted as graph edges — per AC
35
+ * "excluding parent/child taxonomy edges". The only edge source is the
36
+ * `task_dependencies` table.
37
+ */
38
+ export const TopologyReportSchema = z.object({
39
+ topology: z.enum(['FLAT', 'DAG', 'DAG_CYCLIC']),
40
+ edges: z.array(z.object({
41
+ from: z.number().int().positive(),
42
+ to: z.number().int().positive(),
43
+ })),
44
+ roots: z.array(z.number().int().positive()),
45
+ leaves: z.array(z.number().int().positive()),
46
+ advisory: z.enum(['/tasks:loop', '/tasks:loop-dag', 'BLOCKED']),
47
+ });
48
+ //# sourceMappingURL=topology.schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"topology.schema.js","sourceRoot":"","sources":["../../src/schemas/topology.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,YAAY,CAAC,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAC,KAAK,CACZ,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;QACjC,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;KAChC,CAAC,CACH;IACD,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC3C,MAAM,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC;IAC5C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,iBAAiB,EAAE,SAAS,CAAC,CAAC;CAChE,CAAC,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Failed-auth audit-log helper.
3
+ *
4
+ * Locks the AUDIT-03 contract: the helper signature physically cannot accept
5
+ * a raw credential. Callers MUST reduce the failure to a categorical
6
+ * `reasonCode` before invoking, which makes credential-leakage a compile-time
7
+ * error rather than a runtime convention.
8
+ *
9
+ * Used by Phase 28's auth chain (PAT / session / legacy strategies). Defined
10
+ * here in Phase 27 so the contract is fixed before any caller exists.
11
+ */
12
+ /** Authentication strategy that produced the failure. */
13
+ export type AuthStrategy = 'pat' | 'session' | 'legacy';
14
+ /**
15
+ * Categorical reason a credential-bearing request was rejected. The set is
16
+ * intentionally narrow — anything that does not fit one of these buckets
17
+ * should be widened here (and in the test fixture) rather than smuggled in
18
+ * via a free-form string.
19
+ */
20
+ export type AuthFailureReason = 'missing_credential' | 'malformed' | 'unknown_token' | 'revoked' | 'expired' | 'user_disabled' | 'wrong_prefix';
21
+ /**
22
+ * Required context for every auth-failure log line. There is NO field for
23
+ * the supplied credential — this is the discipline the helper enforces.
24
+ */
25
+ export interface AuthFailureContext {
26
+ readonly strategy: AuthStrategy;
27
+ readonly reasonCode: AuthFailureReason;
28
+ readonly requestId: string;
29
+ readonly peerIp: string;
30
+ }
31
+ /**
32
+ * Structural logger contract — compatible with both Fastify's
33
+ * `FastifyBaseLogger` and a vitest mock. Kept minimal to avoid pulling
34
+ * Fastify types into the helper's surface.
35
+ */
36
+ export interface MinimalWarnLogger {
37
+ warn(obj: object, msg?: string): void;
38
+ }
39
+ /**
40
+ * Emit exactly one `warn`-level structured log line tagged `auth.failure`.
41
+ *
42
+ * The payload is deliberately minimal: `tag`, `strategy`, `reasonCode`,
43
+ * `requestId`, `peerIp` — nothing else. Aggregators filter on `tag` and
44
+ * group by `strategy` + `reasonCode`.
45
+ */
46
+ export declare function logAuthFailure(logger: MinimalWarnLogger, ctx: AuthFailureContext): void;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Failed-auth audit-log helper.
3
+ *
4
+ * Locks the AUDIT-03 contract: the helper signature physically cannot accept
5
+ * a raw credential. Callers MUST reduce the failure to a categorical
6
+ * `reasonCode` before invoking, which makes credential-leakage a compile-time
7
+ * error rather than a runtime convention.
8
+ *
9
+ * Used by Phase 28's auth chain (PAT / session / legacy strategies). Defined
10
+ * here in Phase 27 so the contract is fixed before any caller exists.
11
+ */
12
+ /**
13
+ * Emit exactly one `warn`-level structured log line tagged `auth.failure`.
14
+ *
15
+ * The payload is deliberately minimal: `tag`, `strategy`, `reasonCode`,
16
+ * `requestId`, `peerIp` — nothing else. Aggregators filter on `tag` and
17
+ * group by `strategy` + `reasonCode`.
18
+ */
19
+ export function logAuthFailure(logger, ctx) {
20
+ logger.warn({
21
+ tag: 'auth.failure',
22
+ strategy: ctx.strategy,
23
+ reasonCode: ctx.reasonCode,
24
+ requestId: ctx.requestId,
25
+ peerIp: ctx.peerIp,
26
+ }, 'Authentication failed');
27
+ }
28
+ //# sourceMappingURL=auth-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-audit.js","sourceRoot":"","sources":["../../src/services/auth-audit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAwCH;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAyB,EACzB,GAAuB;IAEvB,MAAM,CAAC,IAAI,CACT;QACE,GAAG,EAAE,cAAc;QACnB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,MAAM,EAAE,GAAG,CAAC,MAAM;KACnB,EACD,uBAAuB,CACxB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,42 @@
1
+ import type Database from 'better-sqlite3';
2
+ /**
3
+ * ClaimReleaseService - auto-releases stale task claims after a configurable timeout.
4
+ *
5
+ * Tasks that have been claimed but show no activity (no updated_at changes)
6
+ * for longer than the timeout are considered stale and are automatically
7
+ * released back to 'open' status with no assignee.
8
+ */
9
+ export declare class ClaimReleaseService {
10
+ private db;
11
+ private timeoutMinutes;
12
+ private intervalHandle;
13
+ constructor(db: Database.Database, timeoutMinutes?: number);
14
+ /**
15
+ * Find all claimed tasks with no activity past the timeout.
16
+ * "No activity" = claimed_at is older than timeoutMinutes AND updated_at is also older.
17
+ * This way, any update/comment activity resets the clock via updated_at.
18
+ */
19
+ findStaleClaims(): Array<{
20
+ id: number;
21
+ assignee: string;
22
+ claimed_at: string;
23
+ }>;
24
+ /**
25
+ * Release a stale claim: set assignee to NULL, status to 'open',
26
+ * clear claimed_at, increment version.
27
+ */
28
+ releaseClaim(taskId: number): boolean;
29
+ /**
30
+ * Sweep: find and release all stale claims.
31
+ * Returns count of released claims.
32
+ */
33
+ sweep(): number;
34
+ /**
35
+ * Start periodic sweep (default: every 5 minutes).
36
+ */
37
+ start(intervalMs?: number): void;
38
+ /**
39
+ * Stop periodic sweep.
40
+ */
41
+ stop(): void;
42
+ }
@@ -0,0 +1,90 @@
1
+ import { eventBus } from '../events/event-bus.js';
2
+ /**
3
+ * ClaimReleaseService - auto-releases stale task claims after a configurable timeout.
4
+ *
5
+ * Tasks that have been claimed but show no activity (no updated_at changes)
6
+ * for longer than the timeout are considered stale and are automatically
7
+ * released back to 'open' status with no assignee.
8
+ */
9
+ export class ClaimReleaseService {
10
+ db;
11
+ timeoutMinutes;
12
+ intervalHandle = null;
13
+ constructor(db, timeoutMinutes = 30) {
14
+ this.db = db;
15
+ this.timeoutMinutes = timeoutMinutes;
16
+ }
17
+ /**
18
+ * Find all claimed tasks with no activity past the timeout.
19
+ * "No activity" = claimed_at is older than timeoutMinutes AND updated_at is also older.
20
+ * This way, any update/comment activity resets the clock via updated_at.
21
+ */
22
+ findStaleClaims() {
23
+ const cutoff = `-${this.timeoutMinutes} minutes`;
24
+ return this.db.prepare(`SELECT id, assignee, claimed_at FROM tasks
25
+ WHERE assignee IS NOT NULL
26
+ AND claimed_at IS NOT NULL
27
+ AND status = 'in_progress'
28
+ AND claimed_at <= datetime('now', ?)
29
+ AND updated_at <= datetime('now', ?)`).all(cutoff, cutoff);
30
+ }
31
+ /**
32
+ * Release a stale claim: set assignee to NULL, status to 'open',
33
+ * clear claimed_at, increment version.
34
+ */
35
+ releaseClaim(taskId) {
36
+ const info = this.db.prepare(`UPDATE tasks
37
+ SET assignee = NULL, status = 'open', claimed_at = NULL,
38
+ version = version + 1, updated_at = datetime('now')
39
+ WHERE id = ? AND assignee IS NOT NULL AND status = 'in_progress'`).run(taskId);
40
+ return info.changes > 0;
41
+ }
42
+ /**
43
+ * Sweep: find and release all stale claims.
44
+ * Returns count of released claims.
45
+ */
46
+ sweep() {
47
+ const stale = this.findStaleClaims();
48
+ let released = 0;
49
+ for (const claim of stale) {
50
+ if (this.releaseClaim(claim.id)) {
51
+ // Reload task for event payload
52
+ const task = this.db.prepare(`SELECT t.*, GROUP_CONCAT(tt.tag, ',') as tags_csv
53
+ FROM tasks t
54
+ LEFT JOIN task_tags tt ON tt.task_id = t.id
55
+ WHERE t.id = ?
56
+ GROUP BY t.id`).get(claim.id);
57
+ if (task) {
58
+ const { tags_csv, ...taskData } = task;
59
+ const tags = tags_csv ? tags_csv.split(',').sort() : [];
60
+ eventBus.emit('task.updated', {
61
+ eventType: 'task.updated',
62
+ timestamp: new Date().toISOString(),
63
+ data: { ...taskData, tags },
64
+ metadata: { source: 'workflow' }
65
+ });
66
+ }
67
+ released++;
68
+ }
69
+ }
70
+ return released;
71
+ }
72
+ /**
73
+ * Start periodic sweep (default: every 5 minutes).
74
+ */
75
+ start(intervalMs = 5 * 60 * 1000) {
76
+ if (this.intervalHandle)
77
+ return;
78
+ this.intervalHandle = setInterval(() => this.sweep(), intervalMs);
79
+ }
80
+ /**
81
+ * Stop periodic sweep.
82
+ */
83
+ stop() {
84
+ if (this.intervalHandle) {
85
+ clearInterval(this.intervalHandle);
86
+ this.intervalHandle = null;
87
+ }
88
+ }
89
+ }
90
+ //# sourceMappingURL=claim-release.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claim-release.service.js","sourceRoot":"","sources":["../../src/services/claim-release.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGlD;;;;;;GAMG;AACH,MAAM,OAAO,mBAAmB;IAIpB;IACA;IAJF,cAAc,GAA0C,IAAI,CAAC;IAErE,YACU,EAAqB,EACrB,iBAAyB,EAAE;QAD3B,OAAE,GAAF,EAAE,CAAmB;QACrB,mBAAc,GAAd,cAAc,CAAa;IAClC,CAAC;IAEJ;;;;OAIG;IACH,eAAe;QACb,MAAM,MAAM,GAAG,IAAI,IAAI,CAAC,cAAc,UAAU,CAAC;QACjD,OAAO,IAAI,CAAC,EAAE,CAAC,OAAO,CACpB;;;;;8CAKwC,CACzC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAgE,CAAC;IACvF,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,MAAc;QACzB,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;;wEAGkE,CACnE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACd,OAAO,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,KAAK;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;QACrC,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,KAAK,MAAM,KAAK,IAAI,KAAK,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC;gBAChC,gCAAgC;gBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;;;yBAIe,CAChB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAqD,CAAC;gBACpE,IAAI,IAAI,EAAE,CAAC;oBACT,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,EAAE,GAAG,IAAI,CAAC;oBACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxD,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE;wBAC5B,SAAS,EAAE,cAAc;wBACzB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;wBACnC,IAAI,EAAE,EAAE,GAAG,QAAQ,EAAE,IAAI,EAAE;wBAC3B,QAAQ,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;qBACjC,CAAC,CAAC;gBACL,CAAC;gBACD,QAAQ,EAAE,CAAC;YACb,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAqB,CAAC,GAAG,EAAE,GAAG,IAAI;QACtC,IAAI,IAAI,CAAC,cAAc;YAAE,OAAO;QAChC,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACH,IAAI;QACF,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,44 @@
1
+ import type { ICommentRepository } from '../repositories/interfaces.js';
2
+ import type { ITaskRepository } from '../repositories/interfaces.js';
3
+ import type { Comment, PaginatedResponse } from '../types/task.js';
4
+ export declare class CommentService {
5
+ private commentRepo;
6
+ private taskRepo;
7
+ constructor(commentRepo: ICommentRepository, taskRepo: ITaskRepository);
8
+ /**
9
+ * Add a comment to a task
10
+ * @throws ValidationError if input is invalid
11
+ * @throws NotFoundError if task does not exist
12
+ */
13
+ addComment(input: unknown): Comment;
14
+ /**
15
+ * Get comments for a task in chronological order — current page only.
16
+ * Internal callers use this; REST/MCP use {@link getCommentsPaginated}.
17
+ * @throws NotFoundError if task does not exist
18
+ */
19
+ getComments(taskId: number, pagination?: {
20
+ limit?: number;
21
+ offset?: number;
22
+ }): Comment[];
23
+ /**
24
+ * Paginated get-comments: `{ data, total, limit, offset }`.
25
+ */
26
+ getCommentsPaginated(taskId: number, pagination?: {
27
+ limit?: number;
28
+ offset?: number;
29
+ }): PaginatedResponse<Comment>;
30
+ /**
31
+ * Delete a comment
32
+ *
33
+ * @param id - Comment id to delete.
34
+ * @param task_id - Optional parent task id. When provided, the comment is
35
+ * only deleted if it belongs to this task. This protects the
36
+ * `DELETE /tasks/:id/comments/:commentId` route from IDOR — a caller cannot
37
+ * delete a comment by guessing its id under an unrelated task. Mismatches
38
+ * are reported as NotFoundError to avoid leaking comment existence across
39
+ * tasks.
40
+ * @throws NotFoundError if the comment does not exist, or if `task_id` is
41
+ * provided and the comment does not belong to that task.
42
+ */
43
+ deleteComment(id: number, task_id?: number): void;
44
+ }