@opentask/taskin-task-manager 3.0.2 → 3.2.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 (79) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/dist/completion-blockers.test.d.ts +1 -0
  3. package/dist/completion-blockers.test.js +57 -0
  4. package/dist/completion-blockers.test.js.map +1 -0
  5. package/dist/filter-tasks/filter-criteria.d.ts +181 -0
  6. package/dist/filter-tasks/filter-criteria.js +115 -0
  7. package/dist/filter-tasks/filter-criteria.js.map +1 -0
  8. package/dist/filter-tasks/filter-criteria.test.d.ts +1 -0
  9. package/dist/filter-tasks/filter-criteria.test.js +86 -0
  10. package/dist/filter-tasks/filter-criteria.test.js.map +1 -0
  11. package/dist/filter-tasks/filter-tasks.d.ts +26 -0
  12. package/dist/filter-tasks/filter-tasks.js +99 -0
  13. package/dist/filter-tasks/filter-tasks.js.map +1 -0
  14. package/dist/filter-tasks/filter-tasks.test.d.ts +1 -0
  15. package/dist/filter-tasks/filter-tasks.test.js +110 -0
  16. package/dist/filter-tasks/filter-tasks.test.js.map +1 -0
  17. package/dist/filter-tasks/filter-tasks.types.d.ts +27 -0
  18. package/dist/filter-tasks/filter-tasks.types.js +2 -0
  19. package/dist/filter-tasks/filter-tasks.types.js.map +1 -0
  20. package/dist/filter-tasks/index.d.ts +4 -0
  21. package/dist/filter-tasks/index.js +3 -0
  22. package/dist/filter-tasks/index.js.map +1 -0
  23. package/dist/group-registry.contract.d.ts +18 -0
  24. package/dist/group-registry.contract.js +73 -0
  25. package/dist/group-registry.contract.js.map +1 -0
  26. package/dist/group-registry.types.d.ts +44 -0
  27. package/dist/group-registry.types.js +2 -0
  28. package/dist/group-registry.types.js.map +1 -0
  29. package/dist/index.d.ts +4 -0
  30. package/dist/index.js +4 -0
  31. package/dist/index.js.map +1 -1
  32. package/dist/numerar-prioridade/index.d.ts +1 -0
  33. package/dist/numerar-prioridade/index.js +2 -0
  34. package/dist/numerar-prioridade/index.js.map +1 -0
  35. package/dist/numerar-prioridade/numerar-prioridade.d.ts +36 -0
  36. package/dist/numerar-prioridade/numerar-prioridade.js +75 -0
  37. package/dist/numerar-prioridade/numerar-prioridade.js.map +1 -0
  38. package/dist/numerar-prioridade/numerar-prioridade.test.d.ts +1 -0
  39. package/dist/numerar-prioridade/numerar-prioridade.test.js +55 -0
  40. package/dist/numerar-prioridade/numerar-prioridade.test.js.map +1 -0
  41. package/dist/ordenar-tarefas/index.d.ts +1 -0
  42. package/dist/ordenar-tarefas/index.js +2 -0
  43. package/dist/ordenar-tarefas/index.js.map +1 -0
  44. package/dist/ordenar-tarefas/ordenar-tarefas.d.ts +70 -0
  45. package/dist/ordenar-tarefas/ordenar-tarefas.js +79 -0
  46. package/dist/ordenar-tarefas/ordenar-tarefas.js.map +1 -0
  47. package/dist/ordenar-tarefas/ordenar-tarefas.test.d.ts +1 -0
  48. package/dist/ordenar-tarefas/ordenar-tarefas.test.js +70 -0
  49. package/dist/ordenar-tarefas/ordenar-tarefas.test.js.map +1 -0
  50. package/dist/task-manager.d.ts +34 -1
  51. package/dist/task-manager.js +58 -0
  52. package/dist/task-manager.js.map +1 -1
  53. package/dist/task-manager.types.d.ts +93 -0
  54. package/dist/testing.d.ts +8 -0
  55. package/dist/testing.js +9 -0
  56. package/dist/testing.js.map +1 -0
  57. package/dist/user-registry.contract.js +6 -6
  58. package/dist/user-registry.contract.js.map +1 -1
  59. package/package.json +7 -6
  60. package/src/completion-blockers.test.ts +77 -0
  61. package/src/filter-tasks/filter-criteria.test.ts +113 -0
  62. package/src/filter-tasks/filter-criteria.ts +175 -0
  63. package/src/filter-tasks/filter-tasks.test.ts +129 -0
  64. package/src/filter-tasks/filter-tasks.ts +106 -0
  65. package/src/filter-tasks/filter-tasks.types.ts +26 -0
  66. package/src/filter-tasks/index.ts +16 -0
  67. package/src/group-registry.contract.ts +99 -0
  68. package/src/group-registry.types.ts +47 -0
  69. package/src/index.ts +4 -0
  70. package/src/numerar-prioridade/index.ts +1 -0
  71. package/src/numerar-prioridade/numerar-prioridade.test.ts +69 -0
  72. package/src/numerar-prioridade/numerar-prioridade.ts +80 -0
  73. package/src/ordenar-tarefas/index.ts +1 -0
  74. package/src/ordenar-tarefas/ordenar-tarefas.test.ts +92 -0
  75. package/src/ordenar-tarefas/ordenar-tarefas.ts +135 -0
  76. package/src/task-manager.ts +70 -0
  77. package/src/task-manager.types.ts +95 -0
  78. package/src/testing.ts +8 -0
  79. package/src/user-registry.contract.ts +6 -6
@@ -0,0 +1,99 @@
1
+ /**
2
+ * O que conta como "ainda em aberto".
3
+ *
4
+ * `paused` e `in-review` entram: a tarefa nao foi entregue nem descartada, so
5
+ * nao esta sendo tocada agora. Deixa-las de fora escondia trabalho em curso de
6
+ * quem filtrava por `--open`.
7
+ */
8
+ const EM_ABERTO = ['pending', 'in-progress', 'paused', 'in-review', 'blocked'];
9
+ const ENCERRADOS = ['done', 'canceled'];
10
+ /**
11
+ * Comecou e nao terminou.
12
+ *
13
+ * O meio que faltava entre `open` e `status: 'in-progress'`. `open` inclui
14
+ * `pending` — o que ainda nao comecou, e que num painel de acompanhamento e
15
+ * ruido. `in-progress` sozinho e estreito demais: a tarefa some da tela no
16
+ * instante em que alguem a pausa ou a manda para revisao.
17
+ *
18
+ * `blocked` fica de fora por decisao declarada: bloqueada e trabalho comecado,
19
+ * mas ninguem esta mexendo nela agora, e quem olha "o que esta andando" nao
20
+ * quer ve-la ali.
21
+ */
22
+ const ATIVAS = ['in-progress', 'paused', 'in-review'];
23
+ const contem = (valor, procurado) => valor?.toLowerCase().includes(procurado) ?? false;
24
+ /**
25
+ * Casa o responsavel por id ou nome, inteiro ou em parte.
26
+ *
27
+ * Tarefa sem responsavel nunca casa: filtrar por uma pessoa e perguntar "o que
28
+ * e dela", e "de ninguem" nao e resposta.
29
+ */
30
+ function casaResponsavel(task, procurado) {
31
+ const alvo = procurado.toLowerCase();
32
+ return contem(task.assignee?.id, alvo) || contem(task.assignee?.name, alvo);
33
+ }
34
+ /**
35
+ * Seleciona tarefas por criterio, sem saber como elas serao exibidas.
36
+ *
37
+ * Vive aqui, no pacote agnostico, porque a mesma pergunta e feita de tres
38
+ * lugares: o comando `list`, a saida em JSON e o servidor MCP. Antes eram duas
39
+ * implementacoes que ja discordavam — o comando casava o responsavel por
40
+ * substring em nome ou id, e a classe `Taskin` casava `userId` exato.
41
+ *
42
+ * Nao ordena e nao muda o arranjo recebido: a ordem que entra e a que sai.
43
+ *
44
+ * @public
45
+ */
46
+ export function filterTasks(tasks, criteria) {
47
+ return tasks.filter((task) => {
48
+ if (criteria.status !== undefined) {
49
+ if (task.status !== criteria.status)
50
+ return false;
51
+ }
52
+ else if (criteria.open && !EM_ABERTO.includes(task.status)) {
53
+ return false;
54
+ }
55
+ else if (criteria.closed && !ENCERRADOS.includes(task.status)) {
56
+ return false;
57
+ }
58
+ else if (criteria.active && !ATIVAS.includes(task.status)) {
59
+ return false;
60
+ }
61
+ if (criteria.type !== undefined && task.type !== criteria.type)
62
+ return false;
63
+ if (criteria.assignee !== undefined && !casaResponsavel(task, criteria.assignee))
64
+ return false;
65
+ if (criteria.text !== undefined) {
66
+ const procurado = criteria.text.toLowerCase();
67
+ const casa = task.id.toLowerCase().includes(procurado) ||
68
+ contem(task.title, procurado) ||
69
+ contem(task.status, procurado) ||
70
+ casaResponsavel(task, procurado);
71
+ if (!casa)
72
+ return false;
73
+ }
74
+ return true;
75
+ });
76
+ }
77
+ /**
78
+ * O que identifica uma tarefa numa listagem, sem o que ela diz.
79
+ *
80
+ * O provider de arquivos carrega o markdown inteiro em `content` e
81
+ * `description`. Incluir isso faria a listagem deste repositorio passar de
82
+ * vinte mil linhas — e quem lista quer **escolher** uma tarefa, nao le-las
83
+ * todas. O corpo se busca depois, pelo id.
84
+ *
85
+ * @public
86
+ */
87
+ export function summarizeTask(task) {
88
+ return {
89
+ id: task.id,
90
+ title: task.title,
91
+ status: task.status,
92
+ type: task.type,
93
+ ...(task.assignee && { assignee: { id: task.assignee.id, name: task.assignee.name } }),
94
+ ...(task.order !== undefined && { priority: task.order }),
95
+ ...(task.groupId && { groupId: task.groupId }),
96
+ ...(task.difficulty !== undefined && { difficulty: task.difficulty }),
97
+ };
98
+ }
99
+ //# sourceMappingURL=filter-tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-tasks.js","sourceRoot":"","sources":["../../src/filter-tasks/filter-tasks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,110 @@
1
+ import { parseTaskId } from '@opentask/taskin-types';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { filterTasks } from './filter-tasks.js';
4
+ function tarefa({ id, ...resto }) {
5
+ return {
6
+ createdAt: '2026-09-12T00:00:00.000Z',
7
+ status: 'pending',
8
+ title: `Tarefa ${id}`,
9
+ type: 'feat',
10
+ ...resto,
11
+ id: parseTaskId(id),
12
+ };
13
+ }
14
+ const ANA = { id: 'ana-souza', name: 'Ana Souza', email: 'ana@example.com' };
15
+ const JOAO = { id: 'joao', name: 'João Silva', email: 'joao@example.com' };
16
+ /**
17
+ * A selecao de tarefas, isolada de como ela e exibida.
18
+ *
19
+ * Existiam duas implementacoes divergentes: o comando `list` casava assignee
20
+ * por substring em nome **ou** id, e o `Taskin.list` casava `userId` exato — e
21
+ * ainda projetava a task derrubando o proprio `assignee`. Duas respostas
22
+ * diferentes para a mesma pergunta, e o servidor MCP sem nenhuma.
23
+ */
24
+ describe('filterTasks', () => {
25
+ const TAREFAS = [
26
+ tarefa({ id: '001', status: 'pending', type: 'feat', assignee: ANA, title: 'Criar login' }),
27
+ tarefa({ id: '002', status: 'done', type: 'fix', assignee: JOAO, title: 'Corrigir crash' }),
28
+ tarefa({ id: '003', status: 'in-progress', type: 'feat', assignee: ANA, title: 'Painel de metricas' }),
29
+ tarefa({ id: '004', status: 'blocked', type: 'chore', title: 'Sem responsavel' }),
30
+ tarefa({ id: '005', status: 'canceled', type: 'docs', assignee: JOAO, title: 'Guia antigo' }),
31
+ ];
32
+ it('sem criterio, devolve tudo na ordem recebida', () => {
33
+ expect(filterTasks(TAREFAS, {}).map((t) => t.id)).toEqual(['001', '002', '003', '004', '005']);
34
+ });
35
+ it('filtra por status', () => {
36
+ expect(filterTasks(TAREFAS, { status: 'done' }).map((t) => t.id)).toEqual(['002']);
37
+ });
38
+ it('filtra por tipo', () => {
39
+ expect(filterTasks(TAREFAS, { type: 'feat' }).map((t) => t.id)).toEqual(['001', '003']);
40
+ });
41
+ it('`open` traz o que ainda esta em aberto, e nao o que foi encerrado', () => {
42
+ expect(filterTasks(TAREFAS, { open: true }).map((t) => t.id)).toEqual(['001', '003', '004']);
43
+ });
44
+ it('`closed` traz done e canceled', () => {
45
+ expect(filterTasks(TAREFAS, { closed: true }).map((t) => t.id)).toEqual(['002', '005']);
46
+ });
47
+ it('casa o assignee pelo id, pelo nome e por parte dele', () => {
48
+ expect(filterTasks(TAREFAS, { assignee: 'ana-souza' }).map((t) => t.id)).toEqual(['001', '003']);
49
+ expect(filterTasks(TAREFAS, { assignee: 'Ana Souza' }).map((t) => t.id)).toEqual(['001', '003']);
50
+ expect(filterTasks(TAREFAS, { assignee: 'ana' }).map((t) => t.id)).toEqual(['001', '003']);
51
+ });
52
+ it('nao devolve tarefa sem responsavel quando se filtra por um', () => {
53
+ expect(filterTasks(TAREFAS, { assignee: 'ana' }).map((t) => t.id)).not.toContain('004');
54
+ });
55
+ it('o texto livre procura em id, titulo, status e responsavel', () => {
56
+ expect(filterTasks(TAREFAS, { text: 'crash' }).map((t) => t.id)).toEqual(['002']);
57
+ expect(filterTasks(TAREFAS, { text: '003' }).map((t) => t.id)).toEqual(['003']);
58
+ expect(filterTasks(TAREFAS, { text: 'blocked' }).map((t) => t.id)).toEqual(['004']);
59
+ expect(filterTasks(TAREFAS, { text: 'joão' }).map((t) => t.id)).toEqual(['002', '005']);
60
+ });
61
+ it('combina criterios, exigindo todos', () => {
62
+ expect(filterTasks(TAREFAS, { type: 'feat', assignee: 'ana', status: 'pending' }).map((t) => t.id)).toEqual([
63
+ '001',
64
+ ]);
65
+ });
66
+ it('nao altera o arranjo recebido', () => {
67
+ const original = [...TAREFAS];
68
+ filterTasks(TAREFAS, { status: 'done' });
69
+ expect(TAREFAS).toEqual(original);
70
+ });
71
+ });
72
+ /**
73
+ * "Em andamento" nao e `in-progress`, e nao e `open`.
74
+ *
75
+ * `open` inclui `pending` — o que ainda nao comecou, e que no painel e ruido.
76
+ * `in-progress` sozinho e estreito demais: uma tarefa some da tela no instante
77
+ * em que alguem a pausa ou a manda para revisao, o que e enganoso.
78
+ *
79
+ * `active` e o meio que faltava: **comecou e nao terminou**. `blocked` fica de
80
+ * fora por decisao declarada — ninguem esta trabalhando numa bloqueada agora.
81
+ */
82
+ describe('filtro active', () => {
83
+ const tarefas = [
84
+ tarefa({ id: '001', status: 'pending' }),
85
+ tarefa({ id: '002', status: 'in-progress' }),
86
+ tarefa({ id: '003', status: 'paused' }),
87
+ tarefa({ id: '004', status: 'in-review' }),
88
+ tarefa({ id: '005', status: 'blocked' }),
89
+ tarefa({ id: '006', status: 'done' }),
90
+ tarefa({ id: '007', status: 'canceled' }),
91
+ ];
92
+ it('traz o que comecou e nao terminou', () => {
93
+ const ids = filterTasks(tarefas, { active: true }).map((t) => String(t.id));
94
+ expect(ids).toEqual(['002', '003', '004']);
95
+ });
96
+ it('deixa pending de fora — nao comecou', () => {
97
+ expect(filterTasks(tarefas, { active: true }).map((t) => String(t.id))).not.toContain('001');
98
+ });
99
+ it('deixa blocked de fora, por decisao declarada', () => {
100
+ expect(filterTasks(tarefas, { active: true }).map((t) => String(t.id))).not.toContain('005');
101
+ });
102
+ it('e mais estreito que open e mais largo que in-progress', () => {
103
+ const abertas = filterTasks(tarefas, { open: true }).length;
104
+ const ativas = filterTasks(tarefas, { active: true }).length;
105
+ const emProgresso = filterTasks(tarefas, { status: 'in-progress' }).length;
106
+ expect(ativas).toBeLessThan(abertas);
107
+ expect(ativas).toBeGreaterThan(emProgresso);
108
+ });
109
+ });
110
+ //# sourceMappingURL=filter-tasks.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-tasks.test.js","sourceRoot":"","sources":["../../src/filter-tasks/filter-tasks.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { GroupId, TaskId, TaskStatus, TaskType } from '@opentask/taskin-types';
2
+ /**
3
+ * O que restringe uma listagem de tarefas — derivado do schema unico.
4
+ *
5
+ * Vive em `filter-criteria.ts`, onde os criterios sao definidos uma vez so e as
6
+ * superficies (CLI e MCP) derivam. Reexportado aqui para nao mudar os imports
7
+ * existentes.
8
+ */
9
+ export type { TaskFilterCriteria } from './filter-criteria.js';
10
+ /**
11
+ * A forma de uma tarefa numa listagem — o que identifica, nao o que ela diz.
12
+ *
13
+ * @public
14
+ */
15
+ export interface TaskSummary {
16
+ readonly id: TaskId;
17
+ readonly title: string;
18
+ readonly status: TaskStatus;
19
+ readonly type: TaskType;
20
+ readonly assignee?: {
21
+ readonly id: string;
22
+ readonly name: string;
23
+ };
24
+ readonly priority?: number;
25
+ readonly groupId?: GroupId;
26
+ readonly difficulty?: number;
27
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=filter-tasks.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-tasks.types.js","sourceRoot":"","sources":["../../src/filter-tasks/filter-tasks.types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ export type { CriterionCli, CriterionSurface, FilterCliOption, FilterJsonSchema, TaskFilterCriteria, } from './filter-criteria.js';
2
+ export { FILTER_CRITERIA_SURFACES, FilterCriteriaSchema, filterCriteriaCliOptions, filterCriteriaJsonSchema, parseFilterCriteria, } from './filter-criteria.js';
3
+ export { filterTasks, summarizeTask } from './filter-tasks.js';
4
+ export type { TaskSummary } from './filter-tasks.types.js';
@@ -0,0 +1,3 @@
1
+ export { FILTER_CRITERIA_SURFACES, FilterCriteriaSchema, filterCriteriaCliOptions, filterCriteriaJsonSchema, parseFilterCriteria, } from './filter-criteria.js';
2
+ export { filterTasks, summarizeTask } from './filter-tasks.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/filter-tasks/index.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { IGroupRegistry } from './group-registry.types.js';
2
+ /**
3
+ * Contrato que toda implementacao de {@link IGroupRegistry} precisa cumprir.
4
+ *
5
+ * Vive no pacote agnostico pelo mesmo motivo do contrato de usuarios: um
6
+ * provider de arquivos, um do Redmine e um do GitHub provam o mesmo
7
+ * comportamento sem depender do pacote um do outro. Exportado pelo subcaminho
8
+ * `./testing`, para o `vitest` nunca entrar no grafo de execucao.
9
+ *
10
+ * @param createSubject - Devolve um registro vazio, e uma forma de saber quantas
11
+ * tarefas pertencem a um grupo — porque apagar precisa dizer quantas foram
12
+ * afetadas, e isso e o unico ponto onde o contrato toca em tarefas.
13
+ * @public
14
+ */
15
+ export declare function runGroupRegistryContractTests(createSubject: () => Promise<{
16
+ registry: IGroupRegistry;
17
+ atribuir: (groupId: string, quantas: number) => Promise<void>;
18
+ }>): void;
@@ -0,0 +1,73 @@
1
+ import { parseGroupId } from '@opentask/taskin-types';
2
+ import { describe, expect, it } from 'vitest';
3
+ /**
4
+ * Contrato que toda implementacao de {@link IGroupRegistry} precisa cumprir.
5
+ *
6
+ * Vive no pacote agnostico pelo mesmo motivo do contrato de usuarios: um
7
+ * provider de arquivos, um do Redmine e um do GitHub provam o mesmo
8
+ * comportamento sem depender do pacote um do outro. Exportado pelo subcaminho
9
+ * `./testing`, para o `vitest` nunca entrar no grafo de execucao.
10
+ *
11
+ * @param createSubject - Devolve um registro vazio, e uma forma de saber quantas
12
+ * tarefas pertencem a um grupo — porque apagar precisa dizer quantas foram
13
+ * afetadas, e isso e o unico ponto onde o contrato toca em tarefas.
14
+ * @public
15
+ */
16
+ export function runGroupRegistryContractTests(createSubject) {
17
+ const g = (id) => parseGroupId(id);
18
+ describe('IGroupRegistry contract', () => {
19
+ it('cria e lista', async () => {
20
+ const { registry } = await createSubject();
21
+ await registry.createGroup({ id: g('g-1'), name: 'Sprint' });
22
+ expect(await registry.listGroups()).toEqual([{ id: 'g-1', name: 'Sprint' }]);
23
+ });
24
+ it('acha pelo id, e devolve indefinido para o que nao existe', async () => {
25
+ const { registry } = await createSubject();
26
+ await registry.createGroup({ id: g('g-1'), name: 'Sprint' });
27
+ expect(await registry.findGroup(g('g-1'))).toEqual({ id: 'g-1', name: 'Sprint' });
28
+ expect(await registry.findGroup(g('g-2'))).toBeUndefined();
29
+ });
30
+ it('recusa id repetido', async () => {
31
+ const { registry } = await createSubject();
32
+ await registry.createGroup({ id: g('g-1'), name: 'Sprint' });
33
+ await expect(registry.createGroup({ id: g('g-1'), name: 'Outro' })).rejects.toThrow();
34
+ });
35
+ /*
36
+ * O ponto da entidade: o nome vive num lugar so, entao renomear e uma
37
+ * escrita — e nenhuma tarefa e tocada.
38
+ */
39
+ it('renomeia sem tocar em tarefa nenhuma', async () => {
40
+ const { registry, atribuir } = await createSubject();
41
+ await registry.createGroup({ id: g('g-1'), name: 'Sprint' });
42
+ await atribuir('g-1', 3);
43
+ await registry.renameGroup(g('g-1'), 'Sprint de outubro');
44
+ expect(await registry.findGroup(g('g-1'))).toEqual({ id: 'g-1', name: 'Sprint de outubro' });
45
+ });
46
+ it('recusa renomear o que nao existe', async () => {
47
+ const { registry } = await createSubject();
48
+ await expect(registry.renameGroup(g('g-404'), 'Qualquer')).rejects.toThrow();
49
+ });
50
+ it('apagar sem destino solta os membros, e diz quantos eram', async () => {
51
+ const { registry, atribuir } = await createSubject();
52
+ await registry.createGroup({ id: g('g-1'), name: 'Sprint' });
53
+ await atribuir('g-1', 3);
54
+ const resultado = await registry.deleteGroup(g('g-1'));
55
+ expect(resultado.reassigned).toBe(3);
56
+ expect(await registry.findGroup(g('g-1'))).toBeUndefined();
57
+ });
58
+ it('apagar com destino move os membros para la', async () => {
59
+ const { registry, atribuir } = await createSubject();
60
+ await registry.createGroup({ id: g('g-1'), name: 'Sprint' });
61
+ await registry.createGroup({ id: g('g-2'), name: 'Backlog' });
62
+ await atribuir('g-1', 2);
63
+ const resultado = await registry.deleteGroup(g('g-1'), { reassignTo: g('g-2') });
64
+ expect(resultado.reassigned).toBe(2);
65
+ expect(await registry.findGroup(g('g-2'))).toBeDefined();
66
+ });
67
+ it('recusa apagar o que nao existe', async () => {
68
+ const { registry } = await createSubject();
69
+ await expect(registry.deleteGroup(g('g-404'))).rejects.toThrow();
70
+ });
71
+ });
72
+ }
73
+ //# sourceMappingURL=group-registry.contract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-registry.contract.js","sourceRoot":"","sources":["../src/group-registry.contract.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { Group, GroupId } from '@opentask/taskin-types';
2
+ /**
3
+ * O que acontece com os membros quando o grupo e apagado.
4
+ *
5
+ * Nao ha opcao de "nao dizer": tarefa apontando para grupo inexistente em
6
+ * silencio foi o unico resultado considerado inaceitavel ao decidir isto. As
7
+ * duas escolhas cobrem o que Redmine (`reassign_to_id`) e Jira (`moveIssuesTo`)
8
+ * ja oferecem na propria chamada de exclusao.
9
+ *
10
+ * @public
11
+ */
12
+ export interface DeleteGroupOptions {
13
+ /**
14
+ * Para onde os membros vao. Ausente, eles ficam **sem grupo** — e a operacao
15
+ * informa quantos foram afetados, para o efeito nunca ser invisivel.
16
+ */
17
+ reassignTo?: GroupId;
18
+ }
19
+ /** @public */
20
+ export interface DeleteGroupResult {
21
+ /** Quantas tarefas pertenciam ao grupo apagado. */
22
+ reassigned: number;
23
+ }
24
+ /**
25
+ * Operacoes de grupo que um provider oferece.
26
+ *
27
+ * Separado de `ITaskProvider` de proposito: nem toda fonte tem o conceito. Um
28
+ * provider que tenha implementa isto; um que nao tenha simplesmente nao o
29
+ * expoe, e quem consome descobre pela ausencia em vez de receber uma operacao
30
+ * que falha — o mesmo erro do `-t sse` do `mcp-server`, que existia na flag e
31
+ * nao na implementacao.
32
+ *
33
+ * @public
34
+ */
35
+ export interface IGroupRegistry {
36
+ listGroups: () => Promise<Group[]>;
37
+ findGroup: (id: GroupId) => Promise<Group | undefined>;
38
+ /** Falha quando o id ja existe. */
39
+ createGroup: (group: Group) => Promise<void>;
40
+ /** Falha quando o grupo nao existe. */
41
+ renameGroup: (id: GroupId, name: string) => Promise<void>;
42
+ /** Falha quando o grupo nao existe. */
43
+ deleteGroup: (id: GroupId, options?: DeleteGroupOptions) => Promise<DeleteGroupResult>;
44
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=group-registry.types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"group-registry.types.js","sourceRoot":"","sources":["../src/group-registry.types.ts"],"names":[],"mappings":""}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,9 @@
1
1
  export type { Task, TaskStatus, TaskType, User } from '@opentask/taskin-types';
2
+ export * from './filter-tasks/index.js';
3
+ export * from './group-registry.types.js';
2
4
  export * from './metrics.types.js';
5
+ export * from './numerar-prioridade/index.js';
6
+ export * from './ordenar-tarefas/index.js';
3
7
  export * from './task-manager.js';
4
8
  export * from './task-manager.types.js';
5
9
  export * from './user-registry.types.js';
package/dist/index.js CHANGED
@@ -1,4 +1,8 @@
1
+ export * from './filter-tasks/index.js';
2
+ export * from './group-registry.types.js';
1
3
  export * from './metrics.types.js';
4
+ export * from './numerar-prioridade/index.js';
5
+ export * from './ordenar-tarefas/index.js';
2
6
  export * from './task-manager.js';
3
7
  export * from './task-manager.types.js';
4
8
  export * from './user-registry.types.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,sBAAsB,CAAC;AACrC,cAAc,wBAAwB,CAAC;AACvC,cAAc,iBAAiB,CAAC;AAChC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from './numerar-prioridade.js';
@@ -0,0 +1,2 @@
1
+ export * from './numerar-prioridade.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/numerar-prioridade/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,36 @@
1
+ import type { Task } from '@opentask/taskin-types';
2
+ /**
3
+ * Passo largo de proposito.
4
+ *
5
+ * Com 100 cabem muitos movimentos entre dois vizinhos antes de a renumeracao
6
+ * local precisar acontecer. Com 10 — o passo que o quadro de priorizacao usava —
7
+ * o espaco acaba depressa, e cada esgotamento custa escrita em arquivo.
8
+ */
9
+ export declare const PASSO_DE_PRIORIDADE = 100;
10
+ /**
11
+ * Devolve as tarefas que precisam de um `order` novo, e so elas.
12
+ *
13
+ * ## Por que isto existe
14
+ *
15
+ * O custo de reordenar no quadro de priorizacao ja e de um arquivo por
16
+ * movimento — **exceto** num projeto meio numerado. Ali, dar numero a uma tarefa
17
+ * do meio obriga a numerar todos os antecessores, porque uma tarefa sem `order`
18
+ * ordena por ultimo e nao tem posicao propria entre as numeradas. Num projeto de
19
+ * 500 tarefas com metade sem numero, isso chegou a 124 arquivos.
20
+ *
21
+ * A saida nao e um algoritmo mais esperto: e acabar com o estado meio numerado.
22
+ * Depois desta passada, ou o projeto inteiro tem numero, ou nunca foi priorizado
23
+ * — e todo movimento seguinte custa um arquivo.
24
+ *
25
+ * ## O que ela preserva
26
+ *
27
+ * A ordem relativa em que as tarefas chegaram, e o numero de quem ja tem um.
28
+ * Quem priorizou tomou uma decisao; o comando preenche as lacunas em volta dela
29
+ * em vez de reescreve-la.
30
+ *
31
+ * @param tarefas - Na ordem em que devem ficar
32
+ * @returns Copias apenas das tarefas que mudaram, prontas para gravar. Vazio
33
+ * quando nao ha nada a fazer — o que torna uma segunda passada inofensiva.
34
+ * @public
35
+ */
36
+ export declare function numerarPrioridade(tarefas: readonly Task[], passo?: number): Task[];
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Passo largo de proposito.
3
+ *
4
+ * Com 100 cabem muitos movimentos entre dois vizinhos antes de a renumeracao
5
+ * local precisar acontecer. Com 10 — o passo que o quadro de priorizacao usava —
6
+ * o espaco acaba depressa, e cada esgotamento custa escrita em arquivo.
7
+ */
8
+ export const PASSO_DE_PRIORIDADE = 100;
9
+ /**
10
+ * Devolve as tarefas que precisam de um `order` novo, e so elas.
11
+ *
12
+ * ## Por que isto existe
13
+ *
14
+ * O custo de reordenar no quadro de priorizacao ja e de um arquivo por
15
+ * movimento — **exceto** num projeto meio numerado. Ali, dar numero a uma tarefa
16
+ * do meio obriga a numerar todos os antecessores, porque uma tarefa sem `order`
17
+ * ordena por ultimo e nao tem posicao propria entre as numeradas. Num projeto de
18
+ * 500 tarefas com metade sem numero, isso chegou a 124 arquivos.
19
+ *
20
+ * A saida nao e um algoritmo mais esperto: e acabar com o estado meio numerado.
21
+ * Depois desta passada, ou o projeto inteiro tem numero, ou nunca foi priorizado
22
+ * — e todo movimento seguinte custa um arquivo.
23
+ *
24
+ * ## O que ela preserva
25
+ *
26
+ * A ordem relativa em que as tarefas chegaram, e o numero de quem ja tem um.
27
+ * Quem priorizou tomou uma decisao; o comando preenche as lacunas em volta dela
28
+ * em vez de reescreve-la.
29
+ *
30
+ * @param tarefas - Na ordem em que devem ficar
31
+ * @returns Copias apenas das tarefas que mudaram, prontas para gravar. Vazio
32
+ * quando nao ha nada a fazer — o que torna uma segunda passada inofensiva.
33
+ * @public
34
+ */
35
+ export function numerarPrioridade(tarefas, passo = PASSO_DE_PRIORIDADE) {
36
+ const mudancas = [];
37
+ let anterior = 0;
38
+ for (let i = 0; i < tarefas.length; i++) {
39
+ const atual = tarefas[i];
40
+ if (!atual)
41
+ continue;
42
+ if (atual.order !== undefined && atual.order > anterior) {
43
+ anterior = atual.order;
44
+ continue;
45
+ }
46
+ /*
47
+ * Precisa de numero. O teto e o proximo valor ja existente que ainda esta a
48
+ * frente — respeita-lo e o que preserva a decisao de quem priorizou.
49
+ */
50
+ const teto = tarefas.slice(i + 1).find((t) => t?.order !== undefined && t.order > anterior)?.order;
51
+ const valor = teto === undefined ? anterior + passo : Math.floor((anterior + teto) / 2);
52
+ if (!(valor > anterior) || (teto !== undefined && valor >= teto)) {
53
+ /*
54
+ * Sem espaco entre os vizinhos: abre espaco andando para a frente e para
55
+ * no primeiro que ja estiver alem. A renumeracao fica na vizinhanca.
56
+ */
57
+ let corrido = anterior;
58
+ for (let j = i; j < tarefas.length; j++) {
59
+ const item = tarefas[j];
60
+ if (!item)
61
+ continue;
62
+ if (j > i && item.order !== undefined && item.order > corrido)
63
+ break;
64
+ corrido += passo;
65
+ mudancas.push({ ...item, order: corrido });
66
+ }
67
+ anterior = corrido;
68
+ continue;
69
+ }
70
+ mudancas.push({ ...atual, order: valor });
71
+ anterior = valor;
72
+ }
73
+ return mudancas;
74
+ }
75
+ //# sourceMappingURL=numerar-prioridade.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"numerar-prioridade.js","sourceRoot":"","sources":["../../src/numerar-prioridade/numerar-prioridade.ts"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAwB,EAAE,KAAK,GAAG,mBAAmB;IACrF,MAAM,QAAQ,GAAW,EAAE,CAAC;IAC5B,IAAI,QAAQ,GAAG,CAAC,CAAC;IAEjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACxC,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,KAAK;YAAE,SAAS;QAErB,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,GAAG,QAAQ,EAAE,CAAC;YACxD,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC;YACvB,SAAS;QACX,CAAC;QAED;;;WAGG;QACH,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,EAAE,KAAK,CAAC;QACnG,MAAM,KAAK,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAExF,IAAI,CAAC,CAAC,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,IAAI,IAAI,CAAC,EAAE,CAAC;YACjE;;;eAGG;YACH,IAAI,OAAO,GAAG,QAAQ,CAAC;YACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;gBACxB,IAAI,CAAC,IAAI;oBAAE,SAAS;gBACpB,IAAI,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,GAAG,OAAO;oBAAE,MAAM;gBACrE,OAAO,IAAI,KAAK,CAAC;gBACjB,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YAC7C,CAAC;YACD,QAAQ,GAAG,OAAO,CAAC;YACnB,SAAS;QACX,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1C,QAAQ,GAAG,KAAK,CAAC;IACnB,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}