@noclaf/cli 0.6.0 → 0.7.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 (74) hide show
  1. package/README.md +18 -1
  2. package/dist/adapters/supabase/calendar-gateway.js +48 -0
  3. package/dist/adapters/supabase/calendar-gateway.js.map +1 -0
  4. package/dist/adapters/supabase/calendar-write-gateway.js +35 -0
  5. package/dist/adapters/supabase/calendar-write-gateway.js.map +1 -0
  6. package/dist/adapters/supabase/gateway.js +8 -0
  7. package/dist/adapters/supabase/gateway.js.map +1 -1
  8. package/dist/adapters/supabase/release-gateway.js +61 -0
  9. package/dist/adapters/supabase/release-gateway.js.map +1 -0
  10. package/dist/adapters/supabase/sprint-gateway.js +59 -0
  11. package/dist/adapters/supabase/sprint-gateway.js.map +1 -0
  12. package/dist/adapters/supabase/task-gateway.js +36 -33
  13. package/dist/adapters/supabase/task-gateway.js.map +1 -1
  14. package/dist/core/types.js +4 -6
  15. package/dist/core/types.js.map +1 -1
  16. package/dist/lib/calendar-logic.js +59 -0
  17. package/dist/lib/calendar-logic.js.map +1 -0
  18. package/dist/lib/calendar-write-logic.js +6 -0
  19. package/dist/lib/calendar-write-logic.js.map +1 -0
  20. package/dist/lib/dates.js +21 -0
  21. package/dist/lib/dates.js.map +1 -0
  22. package/dist/lib/pg-error.js +4 -0
  23. package/dist/lib/pg-error.js.map +1 -1
  24. package/dist/lib/release-logic.js +10 -0
  25. package/dist/lib/release-logic.js.map +1 -0
  26. package/dist/lib/sprint-logic.js +31 -0
  27. package/dist/lib/sprint-logic.js.map +1 -0
  28. package/dist/tools/activate-sprint.js +44 -0
  29. package/dist/tools/activate-sprint.js.map +1 -0
  30. package/dist/tools/add-holiday.js +41 -0
  31. package/dist/tools/add-holiday.js.map +1 -0
  32. package/dist/tools/add-home-office.js +31 -0
  33. package/dist/tools/add-home-office.js.map +1 -0
  34. package/dist/tools/add-vacation.js +39 -0
  35. package/dist/tools/add-vacation.js.map +1 -0
  36. package/dist/tools/create-release.js +46 -0
  37. package/dist/tools/create-release.js.map +1 -0
  38. package/dist/tools/create-sprint.js +66 -0
  39. package/dist/tools/create-sprint.js.map +1 -0
  40. package/dist/tools/create-task.js +26 -8
  41. package/dist/tools/create-task.js.map +1 -1
  42. package/dist/tools/end-sprint.js +37 -0
  43. package/dist/tools/end-sprint.js.map +1 -0
  44. package/dist/tools/finalize-release.js +45 -0
  45. package/dist/tools/finalize-release.js.map +1 -0
  46. package/dist/tools/get-calendar.js +40 -0
  47. package/dist/tools/get-calendar.js.map +1 -0
  48. package/dist/tools/get-sprint.js +38 -0
  49. package/dist/tools/get-sprint.js.map +1 -0
  50. package/dist/tools/get-task.js +1 -0
  51. package/dist/tools/get-task.js.map +1 -1
  52. package/dist/tools/index.js +34 -0
  53. package/dist/tools/index.js.map +1 -1
  54. package/dist/tools/list-releases.js +32 -0
  55. package/dist/tools/list-releases.js.map +1 -0
  56. package/dist/tools/list-sprints.js +30 -0
  57. package/dist/tools/list-sprints.js.map +1 -0
  58. package/dist/tools/list-tasks.js +18 -16
  59. package/dist/tools/list-tasks.js.map +1 -1
  60. package/dist/tools/remove-holiday.js +31 -0
  61. package/dist/tools/remove-holiday.js.map +1 -0
  62. package/dist/tools/remove-home-office.js +32 -0
  63. package/dist/tools/remove-home-office.js.map +1 -0
  64. package/dist/tools/remove-vacation.js +31 -0
  65. package/dist/tools/remove-vacation.js.map +1 -0
  66. package/dist/tools/sprint-common.js +13 -0
  67. package/dist/tools/sprint-common.js.map +1 -0
  68. package/dist/tools/update-release.js +58 -0
  69. package/dist/tools/update-release.js.map +1 -0
  70. package/dist/tools/update-sprint.js +56 -0
  71. package/dist/tools/update-sprint.js.map +1 -0
  72. package/dist/tools/update-task.js +46 -31
  73. package/dist/tools/update-task.js.map +1 -1
  74. package/package.json +1 -1
@@ -0,0 +1,59 @@
1
+ import { FINISHED_STATUSES } from '../core/types.js';
2
+ const pad = (n) => String(n).padStart(2, '0');
3
+ const iso = (d) => `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`;
4
+ /** Datas YYYY-MM-DD de `from` a `to`, inclusive. */
5
+ export function eachDay(from, to) {
6
+ const out = [];
7
+ for (let d = new Date(`${from}T00:00:00Z`); iso(d) <= to; d.setUTCDate(d.getUTCDate() + 1))
8
+ out.push(iso(d));
9
+ return out;
10
+ }
11
+ const isLeap = (y) => (y % 4 === 0 && y % 100 !== 0) || y % 400 === 0;
12
+ /** Ocorrência anual (mês/dia de `origin`) em `date`; 29/02 cai em 28/02 em ano não bissexto. Devolve anos desde a origem. */
13
+ export function yearsOn(origin, date) {
14
+ if (!origin)
15
+ return null;
16
+ const [oy, om, od] = origin.split('-').map(Number);
17
+ const [y, m, d] = date.split('-').map(Number);
18
+ const day = om === 2 && od === 29 && !isLeap(y) ? 28 : od;
19
+ return om === m && day === d ? y - oy : null;
20
+ }
21
+ /** Monta os dias com eventos (só dias não vazios), agrupados por data. */
22
+ export function buildCalendar(from, to, s) {
23
+ const byDay = new Map();
24
+ const add = (date, ev) => {
25
+ if (date < from || date > to)
26
+ return;
27
+ const list = byDay.get(date);
28
+ if (list)
29
+ list.push(ev);
30
+ else
31
+ byDay.set(date, [ev]);
32
+ };
33
+ for (const h of s.holidays)
34
+ add(h.date, { kind: 'holiday', id: h.id, name: h.name, type: h.type, scope: h.scope });
35
+ for (const t of s.deadlines) {
36
+ if (FINISHED_STATUSES.includes(t.status))
37
+ continue;
38
+ add(t.end_date, { kind: 'deadline', key: t.key, title: t.title, status: t.status, project: t.project });
39
+ }
40
+ for (const v of s.vacations) {
41
+ for (const d of eachDay(v.start_date, v.end_date))
42
+ add(d, { kind: 'vacation', id: v.id, person: v.person, notes: v.notes });
43
+ }
44
+ for (const h of s.homeOffice)
45
+ add(h.date, { kind: 'home_office', person: h.person });
46
+ for (const r of s.releases)
47
+ add(r.target_date, { kind: 'release', name: r.name, status: r.status });
48
+ for (const d of eachDay(from, to)) {
49
+ for (const p of s.people) {
50
+ if (yearsOn(p.birth_date, d) !== null)
51
+ add(d, { kind: 'birthday', person: p.name });
52
+ const y = yearsOn(p.company_anniversary_date, d);
53
+ if (y !== null && y > 0)
54
+ add(d, { kind: 'work_anniversary', person: p.name, years: y });
55
+ }
56
+ }
57
+ return [...byDay.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([date, events]) => ({ date, events }));
58
+ }
59
+ //# sourceMappingURL=calendar-logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-logic.js","sourceRoot":"","sources":["../../src/lib/calendar-logic.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /** Regras puras da escrita no calendário. */
2
+ /** DELETE negado por RLS afeta 0 linhas sem erro: 0 vira mensagem amigável; null se ok. */
3
+ export function deleteFailure(rows, what) {
4
+ return rows && rows.length > 0 ? null : `${what} não encontrado ou sem permissão.`;
5
+ }
6
+ //# sourceMappingURL=calendar-write-logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"calendar-write-logic.js","sourceRoot":"","sources":["../../src/lib/calendar-write-logic.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAE7C,2FAA2F;AAC3F,MAAM,UAAU,aAAa,CAAC,IAAsB,EAAE,IAAY;IAChE,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,mCAAmC,CAAC;AACrF,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { z } from 'zod';
2
+ /** Hoje em YYYY-MM-DD, fuso local. */
3
+ export function todayStr(now = new Date()) {
4
+ const p = (n) => String(n).padStart(2, '0');
5
+ return `${now.getFullYear()}-${p(now.getMonth() + 1)}-${p(now.getDate())}`;
6
+ }
7
+ const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
8
+ /** YYYY-MM-DD real (rejeita 2026-02-31 por round-trip). */
9
+ export function isIsoDate(s) {
10
+ if (!DATE_RE.test(s))
11
+ return false;
12
+ const d = new Date(`${s}T00:00:00Z`);
13
+ return !Number.isNaN(d.getTime()) && d.toISOString().slice(0, 10) === s;
14
+ }
15
+ /** Schema zod de data ISO válida, compartilhado pelas tools. */
16
+ export const isoDate = z.string().refine(isIsoDate, 'use uma data real no formato YYYY-MM-DD');
17
+ /** Erro se início > fim (ISO, comparação lexicográfica); null se ok ou se faltar um lado. */
18
+ export function dateRangeError(start, end) {
19
+ return start && end && start > end ? `Intervalo inválido: início (${start}) deve ser <= fim (${end}).` : null;
20
+ }
21
+ //# sourceMappingURL=dates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dates.js","sourceRoot":"","sources":["../../src/lib/dates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,sCAAsC;AACtC,MAAM,UAAU,QAAQ,CAAC,MAAY,IAAI,IAAI,EAAE;IAC7C,MAAM,CAAC,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACpD,OAAO,GAAG,GAAG,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,OAAO,GAAG,qBAAqB,CAAC;AAEtC,2DAA2D;AAC3D,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACrC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;AAC1E,CAAC;AAED,gEAAgE;AAChE,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,SAAS,EAAE,yCAAyC,CAAC,CAAC;AAE/F,6FAA6F;AAC7F,MAAM,UAAU,cAAc,CAAC,KAAqB,EAAE,GAAmB;IACvE,OAAO,KAAK,IAAI,GAAG,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,+BAA+B,KAAK,sBAAsB,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAChH,CAAC"}
@@ -32,6 +32,10 @@ const RULES = [
32
32
  re: /null value in column "([^"]+)" of relation "([^"]+)" violates not-null constraint/i,
33
33
  text: (m) => `o campo obrigatório "${m[1]}" de ${m[2]} veio vazio — preencha antes de repetir`,
34
34
  },
35
+ {
36
+ re: /new row violates row-level security policy(?: for table "[^"]+")?/i,
37
+ text: () => 'sem permissão pra essa ação (seu papel não permite escrever aqui)',
38
+ },
35
39
  ];
36
40
  /**
37
41
  * Reescreve o trecho cru do Postgres dentro da mensagem, preservando o resto
@@ -1 +1 @@
1
- {"version":3,"file":"pg-error.js","sourceRoot":"","sources":["../../src/lib/pg-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,4FAA4F;AAC5F,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAc;IACtD,MAAM,YAAY,GAAG,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjG,OAAO,YAAY,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACvF,CAAC;AAED,MAAM,KAAK,GAA4D;IACrE;QACE,EAAE,EAAE,mGAAmG;QACvG,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACV,sCAAsC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK;YAC5F,qDAAqD;KACxD;IACD;QACE,EAAE,EAAE,2DAA2D;QAC/D,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACV,mDAAmD,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;YAClF,oDAAoD;KACvD;IACD;QACE,EAAE,EAAE,8GAA8G;QAClH,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACV,0BAA0B,CAAC,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;YAC/E,yDAAyD;KAC5D;IACD;QACE,EAAE,EAAE,oFAAoF;QACxF,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,yCAAyC;KAC/F;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
1
+ {"version":3,"file":"pg-error.js","sourceRoot":"","sources":["../../src/lib/pg-error.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,4FAA4F;AAC5F,SAAS,kBAAkB,CAAC,IAAY,EAAE,KAAc;IACtD,MAAM,YAAY,GAAG,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACjG,OAAO,YAAY,CAAC,OAAO,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AACvF,CAAC;AAED,MAAM,KAAK,GAA4D;IACrE;QACE,EAAE,EAAE,mGAAmG;QACvG,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACV,sCAAsC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,KAAK;YAC5F,qDAAqD;KACxD;IACD;QACE,EAAE,EAAE,2DAA2D;QAC/D,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACV,mDAAmD,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;YAClF,oDAAoD;KACvD;IACD;QACE,EAAE,EAAE,8GAA8G;QAClH,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CACV,0BAA0B,CAAC,CAAC,CAAC,CAAC,YAAY,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO;YAC/E,yDAAyD;KAC5D;IACD;QACE,EAAE,EAAE,oFAAoF;QACxF,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,yCAAyC;KAC/F;IACD;QACE,EAAE,EAAE,oEAAoE;QACxE,IAAI,EAAE,GAAG,EAAE,CAAC,mEAAmE;KAChF;CACF,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC;YAAE,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { z } from 'zod';
2
+ /** Status aceitos no update; `delivered` só via finalize. */
3
+ export const UPDATABLE_RELEASE_STATUS = z.enum(['planning', 'in_progress', 'cancelled']);
4
+ /** Garante que a release é do projeto; erro acionável senão. */
5
+ export async function assertReleaseInProject(gw, projectId, releaseId) {
6
+ if (!(await gw.findRelease(projectId, releaseId))) {
7
+ throw new Error('Release não encontrada neste projeto. Use list_releases pra ver os ids válidos.');
8
+ }
9
+ }
10
+ //# sourceMappingURL=release-logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"release-logic.js","sourceRoot":"","sources":["../../src/lib/release-logic.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,6DAA6D;AAC7D,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC,CAAC;AAEzF,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAAC,EAAuC,EAAE,SAAiB,EAAE,SAAiB;IACxH,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;IACrG,CAAC;AACH,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { FINISHED_STATUSES } from '../core/types.js';
2
+ /** Plano de encerramento: quem volta pro backlog e quem fica. Pura. */
3
+ export function planSprintEnd(tasks) {
4
+ const toBacklog = [];
5
+ const kept = [];
6
+ for (const t of tasks)
7
+ (FINISHED_STATUSES.includes(t.status) ? kept : toBacklog).push(t.id);
8
+ return { toBacklog, kept };
9
+ }
10
+ /** Contagem por status + vencidas (end_date < hoje, fora de done/production). Pura. */
11
+ export function summarizeSprintTasks(tasks, today) {
12
+ const by_status = {};
13
+ for (const t of tasks)
14
+ by_status[t.status] = (by_status[t.status] ?? 0) + 1;
15
+ const overdue = tasks
16
+ .filter((t) => t.end_date && t.end_date < today && !FINISHED_STATUSES.includes(t.status))
17
+ .map(({ key, title, end_date }) => ({ key, title, end_date }));
18
+ return { total: tasks.length, by_status, overdue };
19
+ }
20
+ /** Encerra a sprint: tasks primeiro, sprint depois. Já encerrada = no-op (preserva end_date). */
21
+ export async function closeSprint(gw, sprint, today) {
22
+ if (sprint.status === 'encerrada') {
23
+ return { sprint, already_closed: true, returned_to_backlog: 0, kept_done: 0 };
24
+ }
25
+ const tasks = await gw.listSprintTasks(sprint.id);
26
+ const { toBacklog, kept } = planSprintEnd(tasks);
27
+ await gw.returnTasksToBacklog(toBacklog);
28
+ const updated = await gw.updateSprint(sprint.id, { status: 'encerrada', end_date: today });
29
+ return { sprint: updated, already_closed: false, returned_to_backlog: toBacklog.length, kept_done: kept.length };
30
+ }
31
+ //# sourceMappingURL=sprint-logic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sprint-logic.js","sourceRoot":"","sources":["../../src/lib/sprint-logic.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAsC,MAAM,kBAAkB,CAAC;AAEzF,uEAAuE;AACvE,MAAM,UAAU,aAAa,CAAC,KAAsB;IAClD,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAC5F,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,oBAAoB,CAAC,KAAsB,EAAE,KAAa;IACxE,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,KAAK,MAAM,CAAC,IAAI,KAAK;QAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;IAC5E,MAAM,OAAO,GAAG,KAAK;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,GAAG,KAAK,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;SACxF,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACjE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC;AACrD,CAAC;AAED,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,EAAiB,EAAE,MAAiB,EAAE,KAAa;IACnF,IAAI,MAAM,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;QAClC,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;IACjD,MAAM,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3F,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,mBAAmB,EAAE,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;AACnH,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { z } from 'zod';
2
+ import { jsonResult, errorResult } from '../lib/tool-result.js';
3
+ import { resolveProjectConfig, isErrorResult } from '../lib/require-config.js';
4
+ import { closeSprint } from '../lib/sprint-logic.js';
5
+ import { todayStr } from '../lib/dates.js';
6
+ import { brand } from '../brand.js';
7
+ import { projectIdProp } from './sprint-common.js';
8
+ const ArgsSchema = z.object({ sprint_id: z.uuid(), project_id: z.uuid().optional() }).strict();
9
+ export const definition = {
10
+ name: `${brand.toolPrefix}activate_sprint`,
11
+ description: 'Reativa uma sprint: encerra qualquer outra ativa do projeto (tasks não concluídas voltam pro backlog) ' +
12
+ 'e reabre a escolhida com status "ativa", start_date = hoje e end_date = null (como a UI).',
13
+ inputSchema: {
14
+ type: 'object',
15
+ properties: { sprint_id: { type: 'string', format: 'uuid' }, project_id: projectIdProp },
16
+ required: ['sprint_id'],
17
+ additionalProperties: false,
18
+ },
19
+ };
20
+ export async function handler(args, ctx) {
21
+ const parsed = ArgsSchema.safeParse(args);
22
+ if (!parsed.success)
23
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
24
+ const cfg = resolveProjectConfig(ctx, parsed.data.project_id);
25
+ if (isErrorResult(cfg))
26
+ return cfg;
27
+ try {
28
+ const gw = ctx.gateway;
29
+ const target = await gw.findSprint(cfg.project_id, parsed.data.sprint_id);
30
+ if (!target)
31
+ return errorResult('Sprint não encontrada neste projeto.');
32
+ if (target.status === 'ativa')
33
+ return jsonResult({ ok: true, sprint: target, already_active: true });
34
+ const today = todayStr();
35
+ const active = await gw.findSprint(cfg.project_id, 'active');
36
+ const closed = active && active.id !== target.id ? await closeSprint(gw, active, today) : undefined;
37
+ const sprint = await gw.updateSprint(target.id, { status: 'ativa', start_date: today, end_date: null });
38
+ return jsonResult({ ok: true, sprint, ...(closed && { closed_previous: closed }) });
39
+ }
40
+ catch (err) {
41
+ return errorResult(err.message);
42
+ }
43
+ }
44
+ //# sourceMappingURL=activate-sprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"activate-sprint.js","sourceRoot":"","sources":["../../src/tools/activate-sprint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAE/F,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,iBAAiB;IAC1C,WAAW,EACT,wGAAwG;QACxG,2FAA2F;IAC7F,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE,EAAE,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE;QACxF,QAAQ,EAAE,CAAC,WAAW,CAAC;QACvB,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,MAAM,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,aAAa,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACnC,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;QACvB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1E,IAAI,CAAC,MAAM;YAAE,OAAO,WAAW,CAAC,sCAAsC,CAAC,CAAC;QACxE,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO;YAAE,OAAO,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;QACrG,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,MAAM,IAAI,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpG,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACxG,OAAO,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC;IACtF,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import { jsonResult, errorResult } from '../lib/tool-result.js';
3
+ import { brand } from '../brand.js';
4
+ import { isoDate } from '../lib/dates.js';
5
+ const ArgsSchema = z
6
+ .object({
7
+ date: isoDate,
8
+ name: z.string().trim().min(1),
9
+ type: z.enum(['full', 'half']).default('full'),
10
+ scope: z.enum(['national', 'state', 'municipal']).default('national'),
11
+ })
12
+ .strict();
13
+ export const definition = {
14
+ name: `${brand.toolPrefix}add_holiday`,
15
+ description: 'Cria feriado no calendário do time (só admin/gerente).',
16
+ inputSchema: {
17
+ type: 'object',
18
+ properties: {
19
+ date: { type: 'string', description: 'Data (YYYY-MM-DD).' },
20
+ name: { type: 'string', description: 'Nome do feriado.' },
21
+ type: { type: 'string', enum: ['full', 'half'], description: 'Padrão full.' },
22
+ scope: { type: 'string', enum: ['national', 'state', 'municipal'], description: 'Padrão national.' },
23
+ },
24
+ required: ['date', 'name'],
25
+ additionalProperties: false,
26
+ },
27
+ };
28
+ export async function handler(args, ctx) {
29
+ const parsed = ArgsSchema.safeParse(args ?? {});
30
+ if (!parsed.success)
31
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
32
+ const a = parsed.data;
33
+ try {
34
+ const h = await ctx.gateway.addHoliday(a);
35
+ return jsonResult({ holiday_id: h.id, ...a });
36
+ }
37
+ catch (err) {
38
+ return errorResult(err.message);
39
+ }
40
+ }
41
+ //# sourceMappingURL=add-holiday.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-holiday.js","sourceRoot":"","sources":["../../src/tools/add-holiday.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,IAAI,EAAE,OAAO;IACb,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9B,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IAC9C,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;CACtE,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,aAAa;IACtC,WAAW,EAAE,wDAAwD;IACrE,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;YAC3D,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kBAAkB,EAAE;YACzD,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE;YAC7E,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,WAAW,EAAE,kBAAkB,EAAE;SACrG;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC;QAC1B,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1C,OAAO,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { z } from 'zod';
2
+ import { jsonResult, errorResult } from '../lib/tool-result.js';
3
+ import { brand } from '../brand.js';
4
+ import { isoDate } from '../lib/dates.js';
5
+ const ArgsSchema = z.object({ date: isoDate }).strict();
6
+ export const definition = {
7
+ name: `${brand.toolPrefix}add_home_office`,
8
+ description: 'Marca home office do PRÓPRIO usuário num dia (o banco pode recusar por limite mensal).',
9
+ inputSchema: {
10
+ type: 'object',
11
+ properties: {
12
+ date: { type: 'string', description: 'Data (YYYY-MM-DD).' },
13
+ },
14
+ required: ['date'],
15
+ additionalProperties: false,
16
+ },
17
+ };
18
+ export async function handler(args, ctx) {
19
+ const parsed = ArgsSchema.safeParse(args ?? {});
20
+ if (!parsed.success)
21
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
22
+ const a = parsed.data;
23
+ try {
24
+ const h = await ctx.gateway.addHomeOffice(ctx.user.id, a.date);
25
+ return jsonResult({ home_office_id: h.id, date: a.date });
26
+ }
27
+ catch (err) {
28
+ return errorResult(err.message);
29
+ }
30
+ }
31
+ //# sourceMappingURL=add-home-office.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-home-office.js","sourceRoot":"","sources":["../../src/tools/add-home-office.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AAExD,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,iBAAiB;IAC1C,WAAW,EAAE,wFAAwF;IACrG,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE;SAC5D;QACD,QAAQ,EAAE,CAAC,MAAM,CAAC;QAClB,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;IACtB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QAC/D,OAAO,UAAU,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAC5D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+ import { jsonResult, errorResult } from '../lib/tool-result.js';
3
+ import { brand } from '../brand.js';
4
+ import { isoDate, dateRangeError } from '../lib/dates.js';
5
+ const ArgsSchema = z
6
+ .object({ user_id: z.uuid(), start_date: isoDate, end_date: isoDate, notes: z.string().optional() })
7
+ .strict();
8
+ export const definition = {
9
+ name: `${brand.toolPrefix}add_vacation`,
10
+ description: 'Registra férias de um usuário no calendário do time (só admin/gerente).',
11
+ inputSchema: {
12
+ type: 'object',
13
+ properties: {
14
+ user_id: { type: 'string', format: 'uuid', description: 'ID do usuário.' },
15
+ start_date: { type: 'string', description: 'Início (YYYY-MM-DD).' },
16
+ end_date: { type: 'string', description: 'Fim (YYYY-MM-DD), >= start_date.' },
17
+ notes: { type: 'string', description: 'Observações.' },
18
+ },
19
+ required: ['user_id', 'start_date', 'end_date'],
20
+ additionalProperties: false,
21
+ },
22
+ };
23
+ export async function handler(args, ctx) {
24
+ const parsed = ArgsSchema.safeParse(args ?? {});
25
+ if (!parsed.success)
26
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
27
+ const a = parsed.data;
28
+ const bad = dateRangeError(a.start_date, a.end_date);
29
+ if (bad)
30
+ return errorResult(bad);
31
+ try {
32
+ const v = await ctx.gateway.addVacation({ ...a, notes: a.notes ?? null, created_by: ctx.user.id });
33
+ return jsonResult({ vacation_id: v.id, ...a });
34
+ }
35
+ catch (err) {
36
+ return errorResult(err.message);
37
+ }
38
+ }
39
+ //# sourceMappingURL=add-vacation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"add-vacation.js","sourceRoot":"","sources":["../../src/tools/add-vacation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAE1D,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC;KACnG,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,cAAc;IACvC,WAAW,EAAE,yEAAyE;IACtF,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE;YAC1E,UAAU,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAE;YACnE,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kCAAkC,EAAE;YAC7E,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE;SACvD;QACD,QAAQ,EAAE,CAAC,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC;QAC/C,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAChD,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;IACtB,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,GAAG;QAAE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACnG,OAAO,UAAU,CAAC,EAAE,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { z } from 'zod';
2
+ import { jsonResult, errorResult } from '../lib/tool-result.js';
3
+ import { resolveProjectConfig, isErrorResult } from '../lib/require-config.js';
4
+ import { isoDate } from '../lib/dates.js';
5
+ import { brand } from '../brand.js';
6
+ import { projectIdProp } from './sprint-common.js';
7
+ const ArgsSchema = z
8
+ .object({
9
+ name: z.string().trim().min(1).max(100),
10
+ target_date: isoDate,
11
+ description: z.string().optional(),
12
+ project_id: z.uuid().optional(),
13
+ })
14
+ .strict();
15
+ export const definition = {
16
+ name: `${brand.toolPrefix}create_release`,
17
+ description: 'Cria uma release (status planning) no projeto. target_date é obrigatória (YYYY-MM-DD).',
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ name: { type: 'string' },
22
+ target_date: { type: 'string', description: 'YYYY-MM-DD.' },
23
+ description: { type: 'string' },
24
+ project_id: projectIdProp,
25
+ },
26
+ required: ['name', 'target_date'],
27
+ additionalProperties: false,
28
+ },
29
+ };
30
+ export async function handler(args, ctx) {
31
+ const parsed = ArgsSchema.safeParse(args);
32
+ if (!parsed.success)
33
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
34
+ const cfg = resolveProjectConfig(ctx, parsed.data.project_id);
35
+ if (isErrorResult(cfg))
36
+ return cfg;
37
+ const { project_id: _p, ...rest } = parsed.data;
38
+ try {
39
+ const release = await ctx.gateway.createRelease({ ...rest, project_id: cfg.project_id, created_by: ctx.user.id });
40
+ return jsonResult({ ok: true, release });
41
+ }
42
+ catch (err) {
43
+ return errorResult(err.message);
44
+ }
45
+ }
46
+ //# sourceMappingURL=create-release.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-release.js","sourceRoot":"","sources":["../../src/tools/create-release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,UAAU,GAAG,CAAC;KACjB,MAAM,CAAC;IACN,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC;IACvC,WAAW,EAAE,OAAO;IACpB,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,EAAE;CAChC,CAAC;KACD,MAAM,EAAE,CAAC;AAEZ,MAAM,CAAC,MAAM,UAAU,GAAS;IAC9B,IAAI,EAAE,GAAG,KAAK,CAAC,UAAU,gBAAgB;IACzC,WAAW,EAAE,wFAAwF;IACrG,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACxB,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE;YAC3D,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC/B,UAAU,EAAE,aAAa;SAC1B;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC;QACjC,oBAAoB,EAAE,KAAK;KAC5B;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAa,EAAE,GAAgB;IAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,WAAW,CAAC,uBAAuB,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACvF,MAAM,GAAG,GAAG,oBAAoB,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,aAAa,CAAC,GAAG,CAAC;QAAE,OAAO,GAAG,CAAC;IACnC,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,GAAG,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QAClH,OAAO,UAAU,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,WAAW,CAAE,GAAa,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC"}
@@ -0,0 +1,66 @@
1
+ import { z } from 'zod';
2
+ import { jsonResult, errorResult } from '../lib/tool-result.js';
3
+ import { resolveProjectConfig, isErrorResult } from '../lib/require-config.js';
4
+ import { closeSprint } from '../lib/sprint-logic.js';
5
+ import { todayStr, isoDate, dateRangeError } from '../lib/dates.js';
6
+ import { brand } from '../brand.js';
7
+ import { projectIdProp } from './sprint-common.js';
8
+ const ArgsSchema = z
9
+ .object({
10
+ name: z.string().trim().min(1).max(100),
11
+ start_date: isoDate.optional(),
12
+ end_date: isoDate.optional(),
13
+ replace_active: z.boolean().optional(),
14
+ project_id: z.uuid().optional(),
15
+ })
16
+ .strict();
17
+ export const definition = {
18
+ name: `${brand.toolPrefix}create_sprint`,
19
+ description: 'Cria uma sprint já ATIVA. Se o projeto já tem sprint ativa, falha dizendo qual — ' +
20
+ 'passe replace_active=true pra encerrá-la (tasks não concluídas voltam pro backlog) e criar a nova.',
21
+ inputSchema: {
22
+ type: 'object',
23
+ properties: {
24
+ name: { type: 'string' },
25
+ start_date: { type: 'string', description: 'YYYY-MM-DD. Default: hoje.' },
26
+ end_date: { type: 'string', description: 'YYYY-MM-DD.' },
27
+ replace_active: { type: 'boolean', description: 'Encerra a sprint ativa atual antes de criar. Default false.' },
28
+ project_id: projectIdProp,
29
+ },
30
+ required: ['name'],
31
+ additionalProperties: false,
32
+ },
33
+ };
34
+ export async function handler(args, ctx) {
35
+ const parsed = ArgsSchema.safeParse(args);
36
+ if (!parsed.success)
37
+ return errorResult(`Argumento inválido: ${parsed.error.message}`);
38
+ const { name, replace_active } = parsed.data;
39
+ const today = todayStr();
40
+ const start = parsed.data.start_date ?? today;
41
+ const end = parsed.data.end_date ?? null;
42
+ const bad = dateRangeError(start, end);
43
+ if (bad)
44
+ return errorResult(bad);
45
+ const cfg = resolveProjectConfig(ctx, parsed.data.project_id);
46
+ if (isErrorResult(cfg))
47
+ return cfg;
48
+ try {
49
+ const gw = ctx.gateway;
50
+ const active = await gw.findSprint(cfg.project_id, 'active');
51
+ let closed;
52
+ if (active) {
53
+ if (!replace_active) {
54
+ return errorResult(`Já existe sprint ativa: "${active.name}" (${active.id}). Use replace_active=true pra encerrá-la ` +
55
+ `e criar a nova, ou ${brand.toolPrefix}end_sprint antes.`);
56
+ }
57
+ closed = await closeSprint(gw, active, today);
58
+ }
59
+ const sprint = await gw.createSprint(cfg.project_id, name, start, end);
60
+ return jsonResult({ ok: true, sprint, ...(closed && { closed_previous: closed }) });
61
+ }
62
+ catch (err) {
63
+ return errorResult(err.message);
64
+ }
65
+ }
66
+ //# sourceMappingURL=create-sprint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-sprint.js","sourceRoot":"","sources":["../../src/tools/create-sprint.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import { z } from 'zod';
2
+ import { isoDate, dateRangeError } from '../lib/dates.js';
2
3
  import { jsonResult, errorResult } from '../lib/tool-result.js';
3
4
  import { resolveProjectConfig, isErrorResult } from '../lib/require-config.js';
4
5
  import { resolveTaskDeadline, SPRINT_DEADLINE_FALLBACK_DAYS } from '../lib/sprint-deadline.js';
6
+ import { assertReleaseInProject } from '../lib/release-logic.js';
5
7
  import { brand } from '../brand.js';
6
8
  const TASK_STATUS = [
7
9
  'backlog',
@@ -22,8 +24,10 @@ const ArgsSchema = z
22
24
  priority: z.enum(TASK_PRIORITY).default('none'),
23
25
  type: z.enum(TASK_TYPE).default('task'),
24
26
  status: z.enum(TASK_STATUS).default('todo'),
25
- end_date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional(),
27
+ start_date: isoDate.optional(),
28
+ end_date: isoDate.optional(),
26
29
  sprint: z.string().default('active'),
30
+ release: z.uuid().optional(),
27
31
  assignee_user_ids: z.array(z.uuid()).optional(),
28
32
  label_ids: z.array(z.uuid()).optional(),
29
33
  link_to_current_repository: z.boolean().default(true),
@@ -36,8 +40,11 @@ export const definition = {
36
40
  description: 'Cria uma nova tarefa no projeto atual. Por padrão: status=todo, sprint=active, ' +
37
41
  'type=task, assignee=você. Pra colocar no backlog fora de sprint, passe ' +
38
42
  'status="backlog" e sprint="none". O reporter é sempre o usuário autenticado. ' +
39
- 'Tarefa em sprint SEMPRE tem prazo: se a sprint resolver pra alguma sprint e ' +
40
- `"end_date" não vier, é aplicado hoje + ${SPRINT_DEADLINE_FALLBACK_DAYS} dias (vem em "warnings"). ` +
43
+ 'Tarefa em sprint SEMPRE tem prazo: ESTIME o "end_date" pelo tamanho do trabalho ' +
44
+ `(hoje + ${SPRINT_DEADLINE_FALLBACK_DAYS} dias só é aplicado como fallback se você não informar, e vem em "warnings"). ` +
45
+ '"start_date" (opcional) marca o início no cronograma e deve ser <= end_date. ' +
46
+ 'Deixe FORA da sprint (sprint="none" + status="backlog") só quando for ideia, "um dia"/algum dia, ' +
47
+ 'algo sem dono, ou o usuário pedir explicitamente; fora isso, fica na sprint ativa. ' +
41
48
  'Backlog (sprint="none") segue livre de prazo. Se o projeto não tiver sprint ativa, ' +
42
49
  'a tarefa nasce no backlog e avisa em "warnings" — criar nunca falha por falta de sprint.',
43
50
  inputSchema: {
@@ -48,17 +55,19 @@ export const definition = {
48
55
  priority: { type: 'string', enum: [...TASK_PRIORITY] },
49
56
  type: { type: 'string', enum: [...TASK_TYPE] },
50
57
  status: { type: 'string', enum: [...TASK_STATUS] },
58
+ start_date: { type: 'string', description: 'Data ISO (YYYY-MM-DD), opcional. Deve ser <= end_date.' },
51
59
  end_date: {
52
60
  type: 'string',
53
- description: `Data ISO (YYYY-MM-DD). Obrigatório de fato quando a tarefa entra em sprint — omitido, ` +
54
- `vira hoje + ${SPRINT_DEADLINE_FALLBACK_DAYS} dias.`,
61
+ description: 'Data ISO (YYYY-MM-DD). ESTIME pelo tamanho do trabalho quando a tarefa entra em sprint; ' +
62
+ `só se omitido vira o fallback hoje + ${SPRINT_DEADLINE_FALLBACK_DAYS} dias.`,
55
63
  },
56
64
  sprint: {
57
65
  type: 'string',
58
- description: '"active", "none" ou UUID. Default "active" — a tarefa entra na sprint corrente, ' +
59
- 'que é onde quem pede costuma trabalhar em seguida; sem sprint ativa, cai no backlog. ' +
66
+ description: '"active", "none" ou UUID. Default "active" — a tarefa entra na sprint corrente; sem sprint ativa, cai no backlog. ' +
67
+ 'Use "none" (com status="backlog") só pra ideia, "um dia"/algum dia, algo sem dono ou pedido explícito. ' +
60
68
  'Qualquer valor != "none" puxa "end_date" junto (default de prazo se você não informar).',
61
69
  },
70
+ release: { type: 'string', format: 'uuid', description: 'UUID de uma release do mesmo projeto (list_releases).' },
62
71
  assignee_user_ids: { type: 'array', items: { type: 'string', format: 'uuid' } },
63
72
  label_ids: { type: 'array', items: { type: 'string', format: 'uuid' } },
64
73
  link_to_current_repository: {
@@ -90,6 +99,10 @@ export function resolveTaskLinks(input, repositoryId, userId) {
90
99
  }
91
100
  /** Monta o payload de insert da task a partir do input + sprint já resolvida. Pura. */
92
101
  export function buildTaskInsertPayload(input, projectId, reporterId, sprintId, today) {
102
+ const endDate = resolveTaskDeadline(sprintId, input.end_date, today);
103
+ const rangeErr = dateRangeError(input.start_date, endDate);
104
+ if (rangeErr)
105
+ throw new Error(rangeErr);
93
106
  return {
94
107
  title: input.title,
95
108
  description: input.description,
@@ -99,7 +112,9 @@ export function buildTaskInsertPayload(input, projectId, reporterId, sprintId, t
99
112
  project_id: projectId,
100
113
  reporter_id: reporterId,
101
114
  sprint_id: sprintId,
102
- end_date: resolveTaskDeadline(sprintId, input.end_date, today),
115
+ ...(input.release && { release_id: input.release }),
116
+ start_date: input.start_date,
117
+ end_date: endDate,
103
118
  };
104
119
  }
105
120
  /**
@@ -127,6 +142,7 @@ export function buildCreateTaskResult(task, assigneeIds, labelIds, repoIds, warn
127
142
  priority: task.priority,
128
143
  type: task.type,
129
144
  sprint_id: task.sprint_id,
145
+ start_date: task.start_date,
130
146
  end_date: task.end_date,
131
147
  created_at: task.created_at,
132
148
  linked: { assignee_user_ids: assigneeIds, label_ids: labelIds, repository_ids: repoIds },
@@ -142,6 +158,8 @@ export async function handler(args, ctx) {
142
158
  if (isErrorResult(cfg))
143
159
  return cfg;
144
160
  try {
161
+ if (input.release)
162
+ await assertReleaseInProject(ctx.gateway, cfg.project_id, input.release);
145
163
  const sprintId = await ctx.gateway.resolveSprintId(cfg.project_id, input.sprint);
146
164
  const payload = buildTaskInsertPayload(input, cfg.project_id, ctx.user.id, sprintId);
147
165
  const { assigneeIds, repoIds } = resolveTaskLinks(input, cfg.repository_id, ctx.user.id);