@noclaf/cli 0.7.0 → 0.9.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 (294) hide show
  1. package/README.md +26 -84
  2. package/dist/app.js +13 -0
  3. package/dist/app.js.map +1 -0
  4. package/dist/brand.js +9 -49
  5. package/dist/brand.js.map +1 -1
  6. package/dist/cli.js +3 -37
  7. package/dist/cli.js.map +1 -1
  8. package/dist/mcp-server.js +3 -187
  9. package/dist/mcp-server.js.map +1 -1
  10. package/package.json +8 -17
  11. package/dist/adapters/supabase/allocation-gateway.js +0 -291
  12. package/dist/adapters/supabase/allocation-gateway.js.map +0 -1
  13. package/dist/adapters/supabase/analytics-gateway.js +0 -18
  14. package/dist/adapters/supabase/analytics-gateway.js.map +0 -1
  15. package/dist/adapters/supabase/calendar-gateway.js +0 -48
  16. package/dist/adapters/supabase/calendar-gateway.js.map +0 -1
  17. package/dist/adapters/supabase/calendar-write-gateway.js +0 -35
  18. package/dist/adapters/supabase/calendar-write-gateway.js.map +0 -1
  19. package/dist/adapters/supabase/client.js +0 -136
  20. package/dist/adapters/supabase/client.js.map +0 -1
  21. package/dist/adapters/supabase/context-gateway.js +0 -23
  22. package/dist/adapters/supabase/context-gateway.js.map +0 -1
  23. package/dist/adapters/supabase/gateway.js +0 -26
  24. package/dist/adapters/supabase/gateway.js.map +0 -1
  25. package/dist/adapters/supabase/release-gateway.js +0 -61
  26. package/dist/adapters/supabase/release-gateway.js.map +0 -1
  27. package/dist/adapters/supabase/sprint-gateway.js +0 -59
  28. package/dist/adapters/supabase/sprint-gateway.js.map +0 -1
  29. package/dist/adapters/supabase/task-gateway.js +0 -533
  30. package/dist/adapters/supabase/task-gateway.js.map +0 -1
  31. package/dist/auth.js +0 -141
  32. package/dist/auth.js.map +0 -1
  33. package/dist/cli/commands/auth.js +0 -127
  34. package/dist/cli/commands/auth.js.map +0 -1
  35. package/dist/cli/commands/clean.js +0 -120
  36. package/dist/cli/commands/clean.js.map +0 -1
  37. package/dist/cli/commands/completion.js +0 -114
  38. package/dist/cli/commands/completion.js.map +0 -1
  39. package/dist/cli/commands/exec.js +0 -69
  40. package/dist/cli/commands/exec.js.map +0 -1
  41. package/dist/cli/commands/init/analyze-step.js +0 -21
  42. package/dist/cli/commands/init/analyze-step.js.map +0 -1
  43. package/dist/cli/commands/init/apply-answers.js +0 -122
  44. package/dist/cli/commands/init/apply-answers.js.map +0 -1
  45. package/dist/cli/commands/init/apply-step.js +0 -165
  46. package/dist/cli/commands/init/apply-step.js.map +0 -1
  47. package/dist/cli/commands/init/auth-step.js +0 -48
  48. package/dist/cli/commands/init/auth-step.js.map +0 -1
  49. package/dist/cli/commands/init/boilerplate-step.js +0 -20
  50. package/dist/cli/commands/init/boilerplate-step.js.map +0 -1
  51. package/dist/cli/commands/init/clients-step.js +0 -78
  52. package/dist/cli/commands/init/clients-step.js.map +0 -1
  53. package/dist/cli/commands/init/context-step.js +0 -81
  54. package/dist/cli/commands/init/context-step.js.map +0 -1
  55. package/dist/cli/commands/init/describe-step.js +0 -68
  56. package/dist/cli/commands/init/describe-step.js.map +0 -1
  57. package/dist/cli/commands/init/index.js +0 -98
  58. package/dist/cli/commands/init/index.js.map +0 -1
  59. package/dist/cli/commands/init/mode.js +0 -18
  60. package/dist/cli/commands/init/mode.js.map +0 -1
  61. package/dist/cli/commands/init/progress.js +0 -60
  62. package/dist/cli/commands/init/progress.js.map +0 -1
  63. package/dist/cli/commands/init/project-step.js +0 -133
  64. package/dist/cli/commands/init/project-step.js.map +0 -1
  65. package/dist/cli/commands/init/provision-step.js +0 -103
  66. package/dist/cli/commands/init/provision-step.js.map +0 -1
  67. package/dist/cli/commands/map.js +0 -18
  68. package/dist/cli/commands/map.js.map +0 -1
  69. package/dist/cli/commands/plan.js +0 -45
  70. package/dist/cli/commands/plan.js.map +0 -1
  71. package/dist/cli/commands/skills.js +0 -23
  72. package/dist/cli/commands/skills.js.map +0 -1
  73. package/dist/cli/commands/sync.js +0 -319
  74. package/dist/cli/commands/sync.js.map +0 -1
  75. package/dist/cli/commands/validate-plan.js +0 -42
  76. package/dist/cli/commands/validate-plan.js.map +0 -1
  77. package/dist/cli/commands/wave.js +0 -57
  78. package/dist/cli/commands/wave.js.map +0 -1
  79. package/dist/cli/copy/auth.json +0 -6
  80. package/dist/cli/copy/flows.json +0 -6
  81. package/dist/cli/copy/init.json +0 -20
  82. package/dist/cli/copy/sync.json +0 -3
  83. package/dist/cli/copy.js +0 -23
  84. package/dist/cli/copy.js.map +0 -1
  85. package/dist/cli/flows/clients.js +0 -130
  86. package/dist/cli/flows/clients.js.map +0 -1
  87. package/dist/cli/flows/completion.js +0 -63
  88. package/dist/cli/flows/completion.js.map +0 -1
  89. package/dist/cli/flows/dependencies.js +0 -114
  90. package/dist/cli/flows/dependencies.js.map +0 -1
  91. package/dist/cli/flows/sections.js +0 -85
  92. package/dist/cli/flows/sections.js.map +0 -1
  93. package/dist/cli/flows/user-config.js +0 -37
  94. package/dist/cli/flows/user-config.js.map +0 -1
  95. package/dist/cli/ui/render.js +0 -239
  96. package/dist/cli/ui/render.js.map +0 -1
  97. package/dist/cli/ui/report.js +0 -130
  98. package/dist/cli/ui/report.js.map +0 -1
  99. package/dist/config.js +0 -289
  100. package/dist/config.js.map +0 -1
  101. package/dist/constants.js +0 -9
  102. package/dist/constants.js.map +0 -1
  103. package/dist/core/ports.js +0 -2
  104. package/dist/core/ports.js.map +0 -1
  105. package/dist/core/types.js +0 -5
  106. package/dist/core/types.js.map +0 -1
  107. package/dist/database.types.js +0 -11
  108. package/dist/database.types.js.map +0 -1
  109. package/dist/lib/active-project.js +0 -28
  110. package/dist/lib/active-project.js.map +0 -1
  111. package/dist/lib/autopull.js +0 -13
  112. package/dist/lib/autopull.js.map +0 -1
  113. package/dist/lib/boilerplate-scaffold.js +0 -65
  114. package/dist/lib/boilerplate-scaffold.js.map +0 -1
  115. package/dist/lib/boilerplates.js +0 -61
  116. package/dist/lib/boilerplates.js.map +0 -1
  117. package/dist/lib/calendar-logic.js +0 -59
  118. package/dist/lib/calendar-logic.js.map +0 -1
  119. package/dist/lib/calendar-write-logic.js +0 -6
  120. package/dist/lib/calendar-write-logic.js.map +0 -1
  121. package/dist/lib/client-configs.js +0 -191
  122. package/dist/lib/client-configs.js.map +0 -1
  123. package/dist/lib/client-install.js +0 -40
  124. package/dist/lib/client-install.js.map +0 -1
  125. package/dist/lib/colors.js +0 -92
  126. package/dist/lib/colors.js.map +0 -1
  127. package/dist/lib/cowork-extension.js +0 -143
  128. package/dist/lib/cowork-extension.js.map +0 -1
  129. package/dist/lib/dates.js +0 -21
  130. package/dist/lib/dates.js.map +0 -1
  131. package/dist/lib/dependencies.js +0 -145
  132. package/dist/lib/dependencies.js.map +0 -1
  133. package/dist/lib/dependency-install.js +0 -163
  134. package/dist/lib/dependency-install.js.map +0 -1
  135. package/dist/lib/duration.js +0 -5
  136. package/dist/lib/duration.js.map +0 -1
  137. package/dist/lib/exec-delegate.js +0 -218
  138. package/dist/lib/exec-delegate.js.map +0 -1
  139. package/dist/lib/exec-engines.js +0 -90
  140. package/dist/lib/exec-engines.js.map +0 -1
  141. package/dist/lib/exec-events.js +0 -87
  142. package/dist/lib/exec-events.js.map +0 -1
  143. package/dist/lib/exec-translators.js +0 -198
  144. package/dist/lib/exec-translators.js.map +0 -1
  145. package/dist/lib/file-merge.js +0 -33
  146. package/dist/lib/file-merge.js.map +0 -1
  147. package/dist/lib/git-exposure.js +0 -35
  148. package/dist/lib/git-exposure.js.map +0 -1
  149. package/dist/lib/harness.js +0 -127
  150. package/dist/lib/harness.js.map +0 -1
  151. package/dist/lib/hooks.js +0 -216
  152. package/dist/lib/hooks.js.map +0 -1
  153. package/dist/lib/patterns.js +0 -25
  154. package/dist/lib/patterns.js.map +0 -1
  155. package/dist/lib/pg-error.js +0 -53
  156. package/dist/lib/pg-error.js.map +0 -1
  157. package/dist/lib/plan-delegate.js +0 -117
  158. package/dist/lib/plan-delegate.js.map +0 -1
  159. package/dist/lib/project-context.js +0 -151
  160. package/dist/lib/project-context.js.map +0 -1
  161. package/dist/lib/prompts.js +0 -69
  162. package/dist/lib/prompts.js.map +0 -1
  163. package/dist/lib/provision-apply.js +0 -220
  164. package/dist/lib/provision-apply.js.map +0 -1
  165. package/dist/lib/provision-collect.js +0 -47
  166. package/dist/lib/provision-collect.js.map +0 -1
  167. package/dist/lib/provision.js +0 -45
  168. package/dist/lib/provision.js.map +0 -1
  169. package/dist/lib/release-logic.js +0 -10
  170. package/dist/lib/release-logic.js.map +0 -1
  171. package/dist/lib/repo-map.js +0 -176
  172. package/dist/lib/repo-map.js.map +0 -1
  173. package/dist/lib/require-config.js +0 -32
  174. package/dist/lib/require-config.js.map +0 -1
  175. package/dist/lib/rules.js +0 -146
  176. package/dist/lib/rules.js.map +0 -1
  177. package/dist/lib/sections.js +0 -89
  178. package/dist/lib/sections.js.map +0 -1
  179. package/dist/lib/skill-agent.js +0 -44
  180. package/dist/lib/skill-agent.js.map +0 -1
  181. package/dist/lib/skill-serve.js +0 -128
  182. package/dist/lib/skill-serve.js.map +0 -1
  183. package/dist/lib/skills-cache.js +0 -99
  184. package/dist/lib/skills-cache.js.map +0 -1
  185. package/dist/lib/skills.js +0 -237
  186. package/dist/lib/skills.js.map +0 -1
  187. package/dist/lib/sprint-deadline.js +0 -28
  188. package/dist/lib/sprint-deadline.js.map +0 -1
  189. package/dist/lib/sprint-logic.js +0 -31
  190. package/dist/lib/sprint-logic.js.map +0 -1
  191. package/dist/lib/targets.js +0 -150
  192. package/dist/lib/targets.js.map +0 -1
  193. package/dist/lib/task-history.js +0 -15
  194. package/dist/lib/task-history.js.map +0 -1
  195. package/dist/lib/telemetry.js +0 -51
  196. package/dist/lib/telemetry.js.map +0 -1
  197. package/dist/lib/tool-result.js +0 -15
  198. package/dist/lib/tool-result.js.map +0 -1
  199. package/dist/lib/validate-plan-delegate.js +0 -106
  200. package/dist/lib/validate-plan-delegate.js.map +0 -1
  201. package/dist/lib/version-check.js +0 -89
  202. package/dist/lib/version-check.js.map +0 -1
  203. package/dist/lib/wave-scheduler.js +0 -95
  204. package/dist/lib/wave-scheduler.js.map +0 -1
  205. package/dist/session-factory.js +0 -19
  206. package/dist/session-factory.js.map +0 -1
  207. package/dist/spinner.js +0 -12
  208. package/dist/spinner.js.map +0 -1
  209. package/dist/tools/activate-sprint.js +0 -44
  210. package/dist/tools/activate-sprint.js.map +0 -1
  211. package/dist/tools/add-checklist.js +0 -63
  212. package/dist/tools/add-checklist.js.map +0 -1
  213. package/dist/tools/add-holiday.js +0 -41
  214. package/dist/tools/add-holiday.js.map +0 -1
  215. package/dist/tools/add-home-office.js +0 -31
  216. package/dist/tools/add-home-office.js.map +0 -1
  217. package/dist/tools/add-vacation.js +0 -39
  218. package/dist/tools/add-vacation.js.map +0 -1
  219. package/dist/tools/attach-pr.js +0 -97
  220. package/dist/tools/attach-pr.js.map +0 -1
  221. package/dist/tools/comment-task.js +0 -72
  222. package/dist/tools/comment-task.js.map +0 -1
  223. package/dist/tools/create-release.js +0 -46
  224. package/dist/tools/create-release.js.map +0 -1
  225. package/dist/tools/create-sprint.js +0 -66
  226. package/dist/tools/create-sprint.js.map +0 -1
  227. package/dist/tools/create-task.js +0 -174
  228. package/dist/tools/create-task.js.map +0 -1
  229. package/dist/tools/delegate-exec.js +0 -63
  230. package/dist/tools/delegate-exec.js.map +0 -1
  231. package/dist/tools/end-allocation.js +0 -38
  232. package/dist/tools/end-allocation.js.map +0 -1
  233. package/dist/tools/end-sprint.js +0 -37
  234. package/dist/tools/end-sprint.js.map +0 -1
  235. package/dist/tools/end-task-allocation.js +0 -60
  236. package/dist/tools/end-task-allocation.js.map +0 -1
  237. package/dist/tools/exec-status.js +0 -45
  238. package/dist/tools/exec-status.js.map +0 -1
  239. package/dist/tools/finalize-release.js +0 -45
  240. package/dist/tools/finalize-release.js.map +0 -1
  241. package/dist/tools/get-active-allocation.js +0 -69
  242. package/dist/tools/get-active-allocation.js.map +0 -1
  243. package/dist/tools/get-calendar.js +0 -40
  244. package/dist/tools/get-calendar.js.map +0 -1
  245. package/dist/tools/get-context.js +0 -48
  246. package/dist/tools/get-context.js.map +0 -1
  247. package/dist/tools/get-sprint.js +0 -38
  248. package/dist/tools/get-sprint.js.map +0 -1
  249. package/dist/tools/get-task.js +0 -146
  250. package/dist/tools/get-task.js.map +0 -1
  251. package/dist/tools/index.js +0 -84
  252. package/dist/tools/index.js.map +0 -1
  253. package/dist/tools/list-my-allocations.js +0 -71
  254. package/dist/tools/list-my-allocations.js.map +0 -1
  255. package/dist/tools/list-projects.js +0 -38
  256. package/dist/tools/list-projects.js.map +0 -1
  257. package/dist/tools/list-releases.js +0 -32
  258. package/dist/tools/list-releases.js.map +0 -1
  259. package/dist/tools/list-sprints.js +0 -30
  260. package/dist/tools/list-sprints.js.map +0 -1
  261. package/dist/tools/list-tasks.js +0 -95
  262. package/dist/tools/list-tasks.js.map +0 -1
  263. package/dist/tools/move-task.js +0 -82
  264. package/dist/tools/move-task.js.map +0 -1
  265. package/dist/tools/plan.js +0 -56
  266. package/dist/tools/plan.js.map +0 -1
  267. package/dist/tools/record-delivery.js +0 -100
  268. package/dist/tools/record-delivery.js.map +0 -1
  269. package/dist/tools/remove-holiday.js +0 -31
  270. package/dist/tools/remove-holiday.js.map +0 -1
  271. package/dist/tools/remove-home-office.js +0 -32
  272. package/dist/tools/remove-home-office.js.map +0 -1
  273. package/dist/tools/remove-vacation.js +0 -31
  274. package/dist/tools/remove-vacation.js.map +0 -1
  275. package/dist/tools/set-project.js +0 -52
  276. package/dist/tools/set-project.js.map +0 -1
  277. package/dist/tools/set-review.js +0 -132
  278. package/dist/tools/set-review.js.map +0 -1
  279. package/dist/tools/sprint-common.js +0 -13
  280. package/dist/tools/sprint-common.js.map +0 -1
  281. package/dist/tools/start-allocation.js +0 -32
  282. package/dist/tools/start-allocation.js.map +0 -1
  283. package/dist/tools/start-task-allocation.js +0 -83
  284. package/dist/tools/start-task-allocation.js.map +0 -1
  285. package/dist/tools/update-release.js +0 -58
  286. package/dist/tools/update-release.js.map +0 -1
  287. package/dist/tools/update-sprint.js +0 -56
  288. package/dist/tools/update-sprint.js.map +0 -1
  289. package/dist/tools/update-task.js +0 -183
  290. package/dist/tools/update-task.js.map +0 -1
  291. package/dist/tools/validate-plan.js +0 -58
  292. package/dist/tools/validate-plan.js.map +0 -1
  293. package/dist/version.js +0 -16
  294. package/dist/version.js.map +0 -1
@@ -1,61 +0,0 @@
1
- import { FINISHED_FILTER } from '../../core/types.js';
2
- const COLS = 'id, project_id, name, status, target_date, delivered_at';
3
- /** Adaptador Supabase do `ReleaseGateway`. */
4
- export function releaseGateway(db) {
5
- return {
6
- async listReleases(projectId, status) {
7
- let q = db.from('releases').select(COLS).eq('project_id', projectId);
8
- if (status)
9
- q = q.eq('status', status);
10
- const { data, error } = await q.order('target_date', { ascending: true });
11
- if (error)
12
- throw new Error(`Erro ao listar releases: ${error.message}`);
13
- return data ?? [];
14
- },
15
- async findRelease(projectId, releaseId) {
16
- const { data, error } = await db
17
- .from('releases')
18
- .select(COLS)
19
- .eq('project_id', projectId)
20
- .eq('id', releaseId)
21
- .maybeSingle();
22
- if (error)
23
- throw new Error(`Erro ao buscar release: ${error.message}`);
24
- return data ?? null;
25
- },
26
- async createRelease(r) {
27
- const { data, error } = await db.from('releases').insert(r).select(COLS).single();
28
- if (error)
29
- throw new Error(`Erro ao criar release: ${error.message}`);
30
- return data;
31
- },
32
- async updateRelease(releaseId, patch) {
33
- const { data, error } = await db.from('releases').update(patch).eq('id', releaseId).select(COLS).single();
34
- if (error)
35
- throw new Error(`Erro ao atualizar release: ${error.message}`);
36
- return data;
37
- },
38
- async finalizeRelease(releaseId, unlinkPending) {
39
- // Desvincular é idempotente: roda antes, então retry após falha não deixa release delivered com pendentes.
40
- if (unlinkPending) {
41
- const { error } = await db
42
- .from('tasks')
43
- .update({ release_id: null, updated_at: new Date().toISOString() })
44
- .eq('release_id', releaseId)
45
- .not('status', 'in', FINISHED_FILTER);
46
- if (error)
47
- throw new Error(`Erro ao desvincular tasks pendentes: ${error.message}`);
48
- }
49
- const { data, error } = await db
50
- .from('releases')
51
- .update({ status: 'delivered', delivered_at: new Date().toISOString() })
52
- .eq('id', releaseId)
53
- .select(COLS)
54
- .single();
55
- if (error)
56
- throw new Error(`Erro ao finalizar release: ${error.message}`);
57
- return data;
58
- },
59
- };
60
- }
61
- //# sourceMappingURL=release-gateway.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"release-gateway.js","sourceRoot":"","sources":["../../../src/adapters/supabase/release-gateway.ts"],"names":[],"mappings":"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"}
@@ -1,59 +0,0 @@
1
- const COLS = 'id, project_id, name, status, start_date, end_date';
2
- /** Adaptador Supabase do `SprintGateway` (ciclo de vida de sprints). */
3
- export function sprintGateway(db) {
4
- return {
5
- async listSprints(projectId) {
6
- const { data, error } = await db
7
- .from('sprints')
8
- .select(COLS)
9
- .eq('project_id', projectId)
10
- .order('created_at', { ascending: false });
11
- if (error)
12
- throw new Error(`Erro ao listar sprints: ${error.message}`);
13
- return data ?? [];
14
- },
15
- async findSprint(projectId, idOrActive) {
16
- let q = db.from('sprints').select(COLS).eq('project_id', projectId);
17
- q = idOrActive === 'active'
18
- ? q.eq('status', 'ativa').order('created_at', { ascending: false }).limit(1)
19
- : q.eq('id', idOrActive);
20
- const { data, error } = await q.maybeSingle();
21
- if (error)
22
- throw new Error(`Erro ao buscar sprint: ${error.message}`);
23
- return data ?? null;
24
- },
25
- async listSprintTasks(sprintId) {
26
- const { data, error } = await db
27
- .from('tasks')
28
- .select('id, key, title, status, end_date')
29
- .eq('sprint_id', sprintId);
30
- if (error)
31
- throw new Error(`Erro ao listar tasks da sprint: ${error.message}`);
32
- return data ?? [];
33
- },
34
- async createSprint(projectId, name, startDate, endDate) {
35
- const { data, error } = await db
36
- .from('sprints')
37
- .insert({ project_id: projectId, name, status: 'ativa', start_date: startDate, end_date: endDate })
38
- .select(COLS)
39
- .single();
40
- if (error)
41
- throw new Error(`Erro ao criar sprint: ${error.message}`);
42
- return data;
43
- },
44
- async updateSprint(sprintId, patch) {
45
- const { data, error } = await db.from('sprints').update(patch).eq('id', sprintId).select(COLS).single();
46
- if (error)
47
- throw new Error(`Erro ao atualizar sprint: ${error.message}`);
48
- return data;
49
- },
50
- async returnTasksToBacklog(taskIds) {
51
- if (taskIds.length === 0)
52
- return;
53
- const { error } = await db.from('tasks').update({ sprint_id: null, status: 'backlog' }).in('id', taskIds);
54
- if (error)
55
- throw new Error(`Erro ao devolver tasks ao backlog: ${error.message}`);
56
- },
57
- };
58
- }
59
- //# sourceMappingURL=sprint-gateway.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"sprint-gateway.js","sourceRoot":"","sources":["../../../src/adapters/supabase/sprint-gateway.ts"],"names":[],"mappings":"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"}
@@ -1,533 +0,0 @@
1
- import { insertTaskHistory } from '../../lib/task-history.js';
2
- const SPRINT_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3
- /** Mapeia o conjunto de vínculos → tabela/coluna/campo de histórico + mensagens de erro. */
4
- const ID_SET_SPEC = {
5
- assignees: {
6
- table: 'task_assignees', idColumn: 'user_id', historyField: 'assignees',
7
- fetchErr: 'Erro ao buscar assignees atuais', clearErr: 'Erro ao limpar assignees', insertErr: 'Erro ao gravar novos assignees',
8
- },
9
- labels: {
10
- table: 'task_label_assignments', idColumn: 'label_id', historyField: 'labels',
11
- fetchErr: 'Erro ao buscar labels atuais', clearErr: 'Erro ao limpar labels', insertErr: 'Erro ao gravar novas labels',
12
- },
13
- };
14
- /** Agrupa assignees (já resolvidos p/ perfil) por task_id. Pura. */
15
- export function groupAssigneesByTask(assigneeRows, profilesById) {
16
- const assigneesByTask = new Map();
17
- for (const row of assigneeRows) {
18
- const profile = profilesById.get(row.user_id);
19
- const list = assigneesByTask.get(row.task_id) ?? [];
20
- list.push({
21
- user_id: row.user_id,
22
- full_name: profile?.full_name ?? null,
23
- username: profile?.username ?? null,
24
- });
25
- assigneesByTask.set(row.task_id, list);
26
- }
27
- return assigneesByTask;
28
- }
29
- /** Monta a lista de tasks com assignees embutidos, a partir das linhas + assignees agrupados. Pura. */
30
- export function formatTaskList(tasks, assigneesByTask) {
31
- return tasks.map((t) => ({
32
- id: t.id,
33
- key: t.key,
34
- title: t.title,
35
- status: t.status,
36
- priority: t.priority,
37
- type: t.type,
38
- sprint_id: t.sprint_id,
39
- start_date: t.start_date,
40
- end_date: t.end_date,
41
- release_id: t.release_id,
42
- created_at: t.created_at,
43
- assignees: assigneesByTask.get(t.id) ?? [],
44
- }));
45
- }
46
- /** Adaptador Supabase do `TaskGateway` (listagem, detalhe, CRUD, comentário). */
47
- /** Achata o embed do PostgREST em checklists com itens ordenados. Pura. */
48
- export function normalizeChecklists(rows) {
49
- return (rows ?? []).map((c) => ({
50
- id: c.id,
51
- title: c.title,
52
- icon: c.icon ?? null,
53
- order: c.order ?? 0,
54
- items: (c.task_checklist_items ?? [])
55
- .map((i) => ({ id: i.id, text: i.text, checked: i.checked, order: i.order ?? 0 }))
56
- .sort((a, b) => a.order - b.order),
57
- }));
58
- }
59
- /**
60
- * Payload de insert de uma checklist. `icon` é NOT NULL DEFAULT 'ListChecks' no banco —
61
- * mandar `null` explícito estoura 23502, então sem ícone a chave é omitida. Pura.
62
- */
63
- export function buildChecklistInsert(taskId, title, icon, order) {
64
- return { task_id: taskId, title, order, ...(icon ? { icon } : {}) };
65
- }
66
- export function taskGateway(db) {
67
- return {
68
- async listTasks(filter) {
69
- const sprint = await resolveSprintFilter(db, filter.projectId, filter.sprint);
70
- if (sprint.noActive)
71
- return { tasks: [], note: 'Não há sprint ativa neste projeto.' };
72
- const rows = await queryFilteredTasks(db, filter, sprint.filter);
73
- if (rows.length === 0)
74
- return { tasks: [] };
75
- const { assigneeRows, profilesById } = await loadAssigneeProfiles(db, rows.map((t) => t.id));
76
- return { tasks: formatTaskList(rows, groupAssigneesByTask(assigneeRows, profilesById)) };
77
- },
78
- async getTaskWithRelations(taskId, projectId) {
79
- const taskRes = await db
80
- .from('tasks')
81
- .select('*')
82
- .eq('id', taskId)
83
- .eq('project_id', projectId)
84
- .maybeSingle();
85
- if (taskRes.error)
86
- throw new Error(`Erro ao buscar tarefa: ${taskRes.error.message}`);
87
- if (!taskRes.data)
88
- return null;
89
- const [assigneesRes, checklistRes, commentsRes, historyRes, reposRes, labelsRes] = await Promise.all([
90
- db.from('task_assignees').select('user_id').eq('task_id', taskId),
91
- // Destipado: `task_checklists` não está nos types gerados.
92
- db
93
- .from('task_checklists')
94
- .select('id, title, icon, order, task_checklist_items(id, text, checked, order)')
95
- .eq('task_id', taskId)
96
- .order('order', { ascending: true }),
97
- db
98
- .from('task_comments')
99
- .select('id, content, created_at, updated_at, author_id')
100
- .eq('task_id', taskId)
101
- .order('created_at', { ascending: true })
102
- .limit(50),
103
- db
104
- .from('task_history')
105
- .select('id, action, field, old_value, new_value, created_at, user_id')
106
- .eq('task_id', taskId)
107
- .order('created_at', { ascending: false })
108
- .limit(50),
109
- db.from('task_repositories').select('repository_id').eq('task_id', taskId),
110
- db.from('task_label_assignments').select('label_id').eq('task_id', taskId),
111
- ]);
112
- if (assigneesRes.error)
113
- throw new Error(`Erro ao buscar assignees: ${assigneesRes.error.message}`);
114
- if (checklistRes.error)
115
- throw new Error(`Erro ao buscar checklist: ${checklistRes.error.message}`);
116
- if (commentsRes.error)
117
- throw new Error(`Erro ao buscar comentários: ${commentsRes.error.message}`);
118
- if (historyRes.error)
119
- throw new Error(`Erro ao buscar histórico: ${historyRes.error.message}`);
120
- if (reposRes.error)
121
- throw new Error(`Erro ao buscar repositórios: ${reposRes.error.message}`);
122
- if (labelsRes.error)
123
- throw new Error(`Erro ao buscar labels: ${labelsRes.error.message}`);
124
- return {
125
- task: taskRes.data,
126
- rows: {
127
- assigneeRows: assigneesRes.data ?? [],
128
- checklistRows: normalizeChecklists(checklistRes.data),
129
- commentRows: commentsRes.data ?? [],
130
- historyRows: historyRes.data ?? [],
131
- repoRows: reposRes.data ?? [],
132
- labelRows: labelsRes.data ?? [],
133
- },
134
- };
135
- },
136
- async loadTaskRefs(userIds, repoIds, labelIds) {
137
- const profiles = await fetchProfiles(db, userIds);
138
- const reposById = new Map();
139
- if (repoIds.length > 0) {
140
- const repoFetch = await db
141
- .from('repositories')
142
- .select('id, name, url, default_branch')
143
- .in('id', repoIds);
144
- if (repoFetch.error)
145
- throw new Error(`Erro ao buscar repositórios: ${repoFetch.error.message}`);
146
- for (const r of repoFetch.data ?? []) {
147
- reposById.set(r.id, { name: r.name, url: r.url, default_branch: r.default_branch });
148
- }
149
- }
150
- const labelsById = new Map();
151
- if (labelIds.length > 0) {
152
- const labelFetch = await db.from('task_labels').select('id, name, color').in('id', labelIds);
153
- if (labelFetch.error)
154
- throw new Error(`Erro ao buscar labels: ${labelFetch.error.message}`);
155
- for (const l of labelFetch.data ?? [])
156
- labelsById.set(l.id, { name: l.name, color: l.color });
157
- }
158
- return { profiles, reposById, labelsById };
159
- },
160
- async resolveSprintId(projectId, sprintInput) {
161
- if (sprintInput === 'active') {
162
- const sprintRes = await db
163
- .from('sprints')
164
- .select('id')
165
- .eq('project_id', projectId)
166
- .eq('status', 'ativa')
167
- .maybeSingle();
168
- if (sprintRes.error)
169
- throw new Error(`Erro ao buscar sprint ativa: ${sprintRes.error.message}`);
170
- // Criação prefere a sprint ativa (quem pede tarefa costuma ir fazer em
171
- // seguida), mas projeto sem sprint ativa não é motivo pra tarefa não
172
- // nascer: cai no backlog e a tool avisa. Diferente do update, onde
173
- // pedir "active" sem sprint ativa é erro de verdade.
174
- return sprintRes.data?.id ?? null;
175
- }
176
- if (sprintInput === 'none')
177
- return null;
178
- if (!SPRINT_UUID_RE.test(sprintInput)) {
179
- throw new Error('Argumento "sprint" deve ser "active", "none" ou um UUID válido.');
180
- }
181
- const sprintRes = await db.from('sprints').select('id, project_id').eq('id', sprintInput).maybeSingle();
182
- if (sprintRes.error)
183
- throw new Error(`Erro ao validar sprint: ${sprintRes.error.message}`);
184
- if (!sprintRes.data || sprintRes.data.project_id !== projectId) {
185
- throw new Error('Sprint informada não pertence ao projeto atual.');
186
- }
187
- return sprintRes.data.id;
188
- },
189
- async createTask(payload, links, userId) {
190
- const insertRes = await db
191
- .from('tasks')
192
- .insert(payload)
193
- .select('id, key, title, status, priority, type, sprint_id, start_date, end_date, created_at')
194
- .single();
195
- if (insertRes.error)
196
- throw new Error(`Erro ao criar tarefa: ${insertRes.error.message}`);
197
- const task = insertRes.data;
198
- const warnings = await linkSecondaryRecords(db, task.id, links.assigneeIds, links.labelIds, links.repoIds);
199
- await insertTaskHistory(db, {
200
- task_id: task.id,
201
- user_id: userId,
202
- action: 'created',
203
- field: 'mcp',
204
- new_value: task.title,
205
- });
206
- return { task, warnings };
207
- },
208
- async getCurrentTask(taskId, projectId) {
209
- const res = await db
210
- .from('tasks')
211
- .select('id, title, description, status, priority, type, sprint_id, release_id, start_date, end_date, project_id')
212
- .eq('id', taskId)
213
- .eq('project_id', projectId)
214
- .maybeSingle();
215
- if (res.error)
216
- throw new Error(`Erro ao buscar tarefa: ${res.error.message}`);
217
- return res.data ?? null;
218
- },
219
- async resolveNextSprintId(projectId, sprintInput) {
220
- if (sprintInput === undefined)
221
- return undefined;
222
- if (sprintInput === 'none')
223
- return null;
224
- if (sprintInput === 'active') {
225
- const sprintRes = await db
226
- .from('sprints')
227
- .select('id')
228
- .eq('project_id', projectId)
229
- .eq('status', 'ativa')
230
- .maybeSingle();
231
- if (sprintRes.error)
232
- throw new Error(`Erro ao buscar sprint ativa: ${sprintRes.error.message}`);
233
- if (!sprintRes.data)
234
- throw new Error('Não há sprint ativa no projeto.');
235
- return sprintRes.data.id;
236
- }
237
- if (!SPRINT_UUID_RE.test(sprintInput)) {
238
- throw new Error('Argumento "sprint" deve ser "active", "none" ou um UUID válido.');
239
- }
240
- const sprintRes = await db.from('sprints').select('id, project_id').eq('id', sprintInput).maybeSingle();
241
- if (sprintRes.error)
242
- throw new Error(`Erro ao validar sprint: ${sprintRes.error.message}`);
243
- if (!sprintRes.data || sprintRes.data.project_id !== projectId) {
244
- throw new Error('Sprint informada não pertence ao projeto atual.');
245
- }
246
- return sprintRes.data.id;
247
- },
248
- async applyTaskPatch(taskId, projectId, userId, patch, changes) {
249
- if (Object.keys(patch).length > 0) {
250
- const updateRes = await db.from('tasks').update(patch).eq('id', taskId).eq('project_id', projectId);
251
- if (updateRes.error)
252
- throw new Error(`Erro ao atualizar tarefa: ${updateRes.error.message}`);
253
- }
254
- for (const ch of changes) {
255
- await insertTaskHistory(db, {
256
- task_id: taskId,
257
- user_id: userId,
258
- action: 'updated',
259
- field: ch.field,
260
- old_value: ch.old_value,
261
- new_value: ch.new_value,
262
- });
263
- }
264
- },
265
- async getTaskIdSet(kind, taskId) {
266
- const spec = ID_SET_SPEC[kind];
267
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- tabela dinâmica
268
- const res = await db.from(spec.table).select(spec.idColumn).eq('task_id', taskId);
269
- if (res.error)
270
- throw new Error(`${spec.fetchErr}: ${res.error.message}`);
271
- return (res.data ?? []).map((r) => r[spec.idColumn]);
272
- },
273
- async replaceTaskIdSet(kind, taskId, userId, nextIds, before, after) {
274
- const spec = ID_SET_SPEC[kind];
275
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- tabela dinâmica
276
- const del = await db.from(spec.table).delete().eq('task_id', taskId);
277
- if (del.error)
278
- throw new Error(`${spec.clearErr}: ${del.error.message}`);
279
- if (nextIds.length > 0) {
280
- const rows = nextIds.map((id) => ({ task_id: taskId, [spec.idColumn]: id }));
281
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- tabela dinâmica
282
- const ins = await db.from(spec.table).insert(rows);
283
- if (ins.error)
284
- throw new Error(`${spec.insertErr}: ${ins.error.message}`);
285
- }
286
- await insertTaskHistory(db, {
287
- task_id: taskId,
288
- user_id: userId,
289
- action: 'updated',
290
- field: spec.historyField,
291
- old_value: JSON.stringify(before),
292
- new_value: JSON.stringify(after),
293
- });
294
- },
295
- async reloadTask(taskId) {
296
- const finalRes = await db
297
- .from('tasks')
298
- .select('id, key, title, status, priority, type, sprint_id, start_date, end_date, updated_at')
299
- .eq('id', taskId)
300
- .single();
301
- if (finalRes.error)
302
- throw new Error(`Tarefa atualizada, mas falhou ao recarregar: ${finalRes.error.message}`);
303
- return finalRes.data;
304
- },
305
- async getTaskForMove(taskId, projectId) {
306
- const res = await db
307
- .from('tasks')
308
- .select('id, key, title, status')
309
- .eq('id', taskId)
310
- .eq('project_id', projectId)
311
- .maybeSingle();
312
- if (res.error)
313
- throw new Error(`Erro ao buscar tarefa: ${res.error.message}`);
314
- return res.data ?? null;
315
- },
316
- async getTaskForAttachPr(taskId, projectId) {
317
- const res = await db
318
- .from('tasks')
319
- .select('key, title, status, pr_url, review_state')
320
- .eq('id', taskId)
321
- .eq('project_id', projectId)
322
- .maybeSingle();
323
- if (res.error)
324
- throw new Error(`Erro ao buscar tarefa: ${res.error.message}`);
325
- return res.data ?? null;
326
- },
327
- async getTaskForSetReview(taskId, projectId) {
328
- const res = await db
329
- .from('tasks')
330
- .select('key, title, status, review_state, pr_url')
331
- .eq('id', taskId)
332
- .eq('project_id', projectId)
333
- .maybeSingle();
334
- if (res.error)
335
- throw new Error(`Erro ao buscar tarefa: ${res.error.message}`);
336
- return res.data ?? null;
337
- },
338
- async moveTaskStatus(taskId, projectId, status, userId, oldStatus) {
339
- // Cast: status já validado pela tool (zod) contra o enum gerado.
340
- const updateRes = await db
341
- .from('tasks')
342
- .update({ status: status })
343
- .eq('id', taskId)
344
- .eq('project_id', projectId);
345
- if (updateRes.error)
346
- throw new Error(`Erro ao mover tarefa: ${updateRes.error.message}`);
347
- await insertTaskHistory(db, {
348
- task_id: taskId,
349
- user_id: userId,
350
- action: 'moved',
351
- field: 'status',
352
- old_value: oldStatus,
353
- new_value: status,
354
- });
355
- },
356
- async commentTask(taskId, projectId, userId, content, historyEntry) {
357
- const taskRes = await db
358
- .from('tasks')
359
- .select('id')
360
- .eq('id', taskId)
361
- .eq('project_id', projectId)
362
- .maybeSingle();
363
- if (taskRes.error)
364
- throw new Error(`Erro ao validar tarefa: ${taskRes.error.message}`);
365
- if (!taskRes.data)
366
- return null;
367
- const insertRes = await db
368
- .from('task_comments')
369
- .insert({ task_id: taskId, author_id: userId, content })
370
- .select('id, task_id, created_at')
371
- .single();
372
- if (insertRes.error)
373
- throw new Error(`Erro ao gravar comentário: ${insertRes.error.message}`);
374
- await insertTaskHistory(db, historyEntry);
375
- return insertRes.data;
376
- },
377
- async addChecklist(taskId, projectId, title, icon, items) {
378
- const taskRes = await db
379
- .from('tasks')
380
- .select('id')
381
- .eq('id', taskId)
382
- .eq('project_id', projectId)
383
- .maybeSingle();
384
- if (taskRes.error)
385
- throw new Error(`Erro ao validar tarefa: ${taskRes.error.message}`);
386
- if (!taskRes.data)
387
- return null;
388
- // `task_checklists`/`task_checklist_items` não estão nos types gerados — client destipado.
389
- const raw = db;
390
- const existing = await raw.from('task_checklists').select('id').eq('task_id', taskId);
391
- if (existing.error)
392
- throw new Error(`Erro ao ler checklists: ${existing.error.message}`);
393
- const clRes = await raw
394
- .from('task_checklists')
395
- .insert(buildChecklistInsert(taskId, title, icon, existing.data?.length ?? 0))
396
- .select('id')
397
- .single();
398
- if (clRes.error)
399
- throw new Error(`Erro ao criar checklist: ${clRes.error.message}`);
400
- const checklistId = clRes.data.id;
401
- const rows = items.map((text, i) => ({
402
- task_id: taskId,
403
- checklist_id: checklistId,
404
- text,
405
- checked: false,
406
- order: i,
407
- }));
408
- const itRes = await raw.from('task_checklist_items').insert(rows);
409
- if (itRes.error)
410
- throw new Error(`Erro ao gravar itens da checklist: ${itRes.error.message}`);
411
- return { checklist_id: checklistId, item_count: rows.length };
412
- },
413
- };
414
- }
415
- async function resolveSprintFilter(db, projectId, sprint) {
416
- if (!sprint)
417
- return { noActive: false, filter: null };
418
- if (sprint === 'active') {
419
- const res = await db
420
- .from('sprints')
421
- .select('id')
422
- .eq('project_id', projectId)
423
- .eq('status', 'ativa')
424
- .maybeSingle();
425
- if (res.error)
426
- throw new Error(`Erro ao buscar sprint ativa: ${res.error.message}`);
427
- if (!res.data)
428
- return { noActive: true };
429
- return { noActive: false, filter: { mode: 'eq', value: res.data.id } };
430
- }
431
- if (sprint === 'none')
432
- return { noActive: false, filter: { mode: 'is_null' } };
433
- return { noActive: false, filter: { mode: 'eq', value: sprint } };
434
- }
435
- function applyAssigneeFilter(query, filter) {
436
- const { assignee } = filter;
437
- if (assignee === 'unassigned')
438
- return query.is('task_assignees', null);
439
- if (assignee)
440
- return query.eq('task_assignees.user_id', assignee === 'me' ? filter.userId : assignee);
441
- return query;
442
- }
443
- /** Sobreposição: end_date >= from E coalesce(start_date, end_date) <= to (sem end_date não entra). */
444
- function applyOverlapFilter(query, filter) {
445
- let q = query;
446
- if (filter.from)
447
- q = q.gte('end_date', filter.from);
448
- if (filter.to) {
449
- q = q.not('end_date', 'is', null);
450
- q = q.or(`start_date.lte.${filter.to},and(start_date.is.null,end_date.lte.${filter.to})`);
451
- }
452
- return q;
453
- }
454
- async function queryFilteredTasks(db, filter, sprintFilter) {
455
- const cols = 'id, key, title, status, priority, type, sprint_id, start_date, end_date, release_id, created_at';
456
- const { assignee } = filter;
457
- // Join filtrado no PostgREST: evita mandar centenas de ids na URL (.in/.not.in).
458
- const embed = !assignee ? '' : assignee === 'unassigned' ? ', task_assignees!left(user_id)' : ', task_assignees!inner(user_id)';
459
- let query = db.from('tasks').select(`${cols}${embed}`).eq('project_id', filter.projectId);
460
- query = applyAssigneeFilter(query, filter);
461
- query = applyOverlapFilter(query, filter);
462
- if (sprintFilter?.mode === 'eq')
463
- query = query.eq('sprint_id', sprintFilter.value);
464
- else if (sprintFilter?.mode === 'is_null')
465
- query = query.is('sprint_id', null);
466
- // Cast: a porta é neutra (`string[]`), mas estes valores já vêm validados
467
- // pela tool (zod) contra os mesmos enums — o cast só reconcilia os tipos gerados.
468
- if (filter.status?.length)
469
- query = query.in('status', filter.status);
470
- if (filter.priority?.length)
471
- query = query.in('priority', filter.priority);
472
- if (filter.type?.length)
473
- query = query.in('type', filter.type);
474
- if (filter.search) {
475
- const pattern = `%${filter.search.replace(/[%_]/g, (m) => `\\${m}`)}%`;
476
- query = query.or(`title.ilike.${pattern},description.ilike.${pattern},key.ilike.${pattern}`);
477
- }
478
- query = query
479
- .order('created_at', { ascending: false })
480
- .range(filter.offset, filter.offset + filter.limit - 1);
481
- const { data, error } = await query;
482
- if (error)
483
- throw new Error(`Erro ao listar tarefas: ${error.message}`);
484
- // O embed serve só de filtro: não vaza pro resultado.
485
- const rows = (data ?? []);
486
- return rows.map(({ task_assignees: _ta, ...row }) => row);
487
- }
488
- async function loadAssigneeProfiles(db, taskIds) {
489
- const assigneesRes = await db.from('task_assignees').select('task_id, user_id').in('task_id', taskIds);
490
- if (assigneesRes.error)
491
- throw new Error(`Erro ao buscar assignees: ${assigneesRes.error.message}`);
492
- const assigneeRows = assigneesRes.data ?? [];
493
- const userIds = Array.from(new Set(assigneeRows.map((a) => a.user_id)));
494
- let profilesById = new Map();
495
- if (userIds.length > 0) {
496
- const profilesRes = await db.from('profiles').select('id, full_name, username').in('id', userIds);
497
- if (profilesRes.error)
498
- throw new Error(`Erro ao buscar perfis: ${profilesRes.error.message}`);
499
- profilesById = new Map((profilesRes.data ?? []).map((p) => [p.id, { full_name: p.full_name, username: p.username }]));
500
- }
501
- return { assigneeRows, profilesById };
502
- }
503
- async function linkSecondaryRecords(db, taskId, assigneeIds, labelIds, repoIds) {
504
- const results = await Promise.all([
505
- insertTaskLinks(db, 'task_assignees', 'user_id', 'assignees', taskId, assigneeIds),
506
- insertTaskLinks(db, 'task_label_assignments', 'label_id', 'labels', taskId, labelIds),
507
- insertTaskLinks(db, 'task_repositories', 'repository_id', 'repositories', taskId, repoIds),
508
- ]);
509
- return results.filter((w) => w !== null);
510
- }
511
- async function insertTaskLinks(db, table, idField, label, taskId, ids) {
512
- if (ids.length === 0)
513
- return null;
514
- const rows = ids.map((id) => ({ task_id: taskId, [idField]: id }));
515
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- tabela dinâmica
516
- const res = await db.from(table).insert(rows);
517
- return res.error ? `Falha ao vincular ${label}: ${res.error.message}` : null;
518
- }
519
- async function fetchProfiles(db, userIds) {
520
- if (userIds.length === 0)
521
- return new Map();
522
- const res = await db
523
- .from('profiles')
524
- .select('id, full_name, username, avatar_url')
525
- .in('id', userIds);
526
- if (res.error)
527
- throw new Error(`Erro ao buscar perfis: ${res.error.message}`);
528
- return new Map((res.data ?? []).map((p) => [
529
- p.id,
530
- { full_name: p.full_name, username: p.username, avatar_url: p.avatar_url },
531
- ]));
532
- }
533
- //# sourceMappingURL=task-gateway.js.map