@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
@@ -1,4 +1,5 @@
1
1
  import type { Task, TaskId, TaskType } from '@opentask/taskin-types';
2
+ import type { IGroupRegistry } from './group-registry.types.js';
2
3
 
3
4
  /**
4
5
  * Options for creating a new task
@@ -40,6 +41,14 @@ export type ValidationSeverity = 'error' | 'warning' | 'info';
40
41
  * A validation error or warning found during linting
41
42
  * @public
42
43
  */
44
+ /** Um criterio que ainda impede a conclusao. */
45
+ export interface CriterioEmAberto {
46
+ /** O texto do item, como escrito. */
47
+ readonly texto: string;
48
+ /** Onde ele esta, quando a fonte sabe dizer. */
49
+ readonly linha?: number;
50
+ }
51
+
43
52
  export interface ValidationIssue {
44
53
  /** The file or task that has the issue */
45
54
  file: string;
@@ -130,6 +139,20 @@ export interface ITaskProvider<TTask extends Task = Task> {
130
139
  * @returns The lint result with any validation issues found
131
140
  */
132
141
  lint: (fix?: boolean) => Promise<LintResult>;
142
+
143
+ /**
144
+ * Os criterios de conclusao que ainda bloqueiam esta tarefa, se a fonte tiver
145
+ * o conceito.
146
+ *
147
+ * **Opcional de proposito.** Checklist e uma forma do provider de arquivos: o
148
+ * Jira tem subtarefas, o GitHub tem itens de lista na descricao. Um provider
149
+ * sem nada equivalente simplesmente nao implementa, e o `finishTask` conclui
150
+ * sem portao — em vez de chamar algo que falha.
151
+ *
152
+ * O conceito e de dominio ("o que falta para isto estar pronto?"); a
153
+ * representacao e de provider.
154
+ */
155
+ getCompletionBlockers?: (task: TTask) => Promise<CriterioEmAberto[]>;
133
156
  }
134
157
 
135
158
  /**
@@ -154,6 +177,64 @@ export interface ITaskManager<TTask extends Task = Task> {
154
177
  */
155
178
  finishTask: (taskId: TaskId) => Promise<TTask>;
156
179
 
180
+ /**
181
+ * Every task the configured provider knows about.
182
+ *
183
+ * Delegates to the provider, like {@link ITaskManager.lint} does. Listing is
184
+ * a domain question — "what work exists?" — and a consumer that only holds a
185
+ * manager should not need the provider to answer it. The MCP server did, and
186
+ * shipped a `taskin://tasks` resource that answered with a placeholder.
187
+ *
188
+ * @returns The tasks, in whatever order the provider returns them
189
+ */
190
+ getAllTasks: () => Promise<TTask[]>;
191
+
192
+ /**
193
+ * Da a cada tarefa um numero de prioridade, de uma vez.
194
+ *
195
+ * E operacao de dominio, e nao um `updateTask` generico, por dois motivos.
196
+ *
197
+ * O primeiro e de desenho: a regra da numeracao — preservar a ordem, manter o
198
+ * numero de quem ja tem, abrir espaco quando faltar — passa a viver num lugar
199
+ * so, em vez de ser reescrita pela CLI e pelo servidor MCP.
200
+ *
201
+ * O segundo e de tipo: um metodo que **consome** `TTask` torna a interface
202
+ * contravariante nele, e um `ITaskManager<TarefaEspecifica>` deixa de poder
203
+ * ser usado onde se espera `ITaskManager<Task>`. Uma operacao que so devolve
204
+ * numeros nao tem esse problema.
205
+ *
206
+ * Existe porque um projeto **meio numerado** cobra caro: mover uma tarefa do
207
+ * meio da regiao sem numero reescreve todos os antecessores — 124 arquivos num
208
+ * projeto de 500, medido. Depois desta operacao, todo movimento custa um.
209
+ *
210
+ * @param options - `dryRun` apenas conta, sem gravar
211
+ * @returns Quantas existem, quantas estavam sem numero, e quantas mudaram
212
+ */
213
+ /**
214
+ * Os grupos, quando a fonte tem o conceito — `undefined` quando nao tem.
215
+ *
216
+ * Opcional de proposito: o GitHub mapeia para milestone, o Redmine para
217
+ * categoria, e uma fonte sem nada equivalente simplesmente nao oferece. Quem
218
+ * consome descobre pela ausencia, em vez de chamar algo que falha.
219
+ */
220
+ readonly groupRegistry?: IGroupRegistry;
221
+
222
+ /**
223
+ * Conclui a tarefa e relata os criterios que ficaram em aberto.
224
+ *
225
+ * Avisa, e nao recusa: fechar e um gesto unico, muitas vezes com pressa, e
226
+ * recusar ali torna o comando fragil. O portao duro vive no `lint`.
227
+ *
228
+ * O relato vem vazio quando o provider nao tem o conceito de checklist.
229
+ */
230
+ finishTaskComRelato: (taskId: TaskId) => Promise<{ task: TTask; blockers: CriterioEmAberto[] }>;
231
+
232
+ prioritizeAll: (options?: { dryRun?: boolean }) => Promise<{
233
+ total: number;
234
+ withoutPriority: number;
235
+ changed: number;
236
+ }>;
237
+
157
238
  /**
158
239
  * Mark a task as ready for review.
159
240
  * Transitions the task from 'in-progress' to 'in-review' status.
@@ -197,4 +278,18 @@ export interface ITaskManager<TTask extends Task = Task> {
197
278
  * @returns The lint result with any validation issues found
198
279
  */
199
280
  lint: (fix?: boolean) => Promise<LintResult>;
281
+
282
+ /**
283
+ * Os criterios de conclusao que ainda bloqueiam esta tarefa, se a fonte tiver
284
+ * o conceito.
285
+ *
286
+ * **Opcional de proposito.** Checklist e uma forma do provider de arquivos: o
287
+ * Jira tem subtarefas, o GitHub tem itens de lista na descricao. Um provider
288
+ * sem nada equivalente simplesmente nao implementa, e o `finishTask` conclui
289
+ * sem portao — em vez de chamar algo que falha.
290
+ *
291
+ * O conceito e de dominio ("o que falta para isto estar pronto?"); a
292
+ * representacao e de provider.
293
+ */
294
+ getCompletionBlockers?: (task: TTask) => Promise<CriterioEmAberto[]>;
200
295
  }
package/src/testing.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Contratos que as implementacoes provam contra si mesmas.
3
+ *
4
+ * Exportado por `@opentask/taskin-task-manager/testing` para o `vitest` nunca
5
+ * entrar no grafo de execucao do pacote.
6
+ */
7
+ export * from './group-registry.contract.js';
8
+ export * from './user-registry.contract.js';
@@ -40,7 +40,7 @@ export function runUserRegistryContractTests(createSubject: () => Promise<IUserR
40
40
  const user = registry.resolveUser('joao.silva');
41
41
  expect(user).toBeDefined();
42
42
  expect(user!.id).toBe('joao.silva');
43
- expect(user!.avatar).toMatch(/^https:\/\/www\.gravatar\.com\/avatar\/[a-f0-9]{32}\?d=mp$/);
43
+ expect(user!.avatarHash).toMatch(/^[a-f0-9]{32}$/);
44
44
  });
45
45
 
46
46
  it('should return user by name (case-insensitive)', async () => {
@@ -54,7 +54,7 @@ export function runUserRegistryContractTests(createSubject: () => Promise<IUserR
54
54
  const user = registry.resolveUser('Maria Souza');
55
55
  expect(user).toBeDefined();
56
56
  expect(user!.id).toBe('maria');
57
- expect(user!.avatar).toMatch(/^https:\/\/www\.gravatar\.com\/avatar\/[a-f0-9]{32}\?d=mp$/);
57
+ expect(user!.avatarHash).toMatch(/^[a-f0-9]{32}$/);
58
58
  });
59
59
 
60
60
  it('should return undefined for unknown user', async () => {
@@ -65,21 +65,21 @@ export function runUserRegistryContractTests(createSubject: () => Promise<IUserR
65
65
  });
66
66
 
67
67
  describe('createTemporaryUser', () => {
68
- it('should create user with Gravatar URL', async () => {
68
+ it('should create user with an avatar identity hash', async () => {
69
69
  const registry = await createSubject();
70
70
  const user = registry.createTemporaryUser('Carlos');
71
71
 
72
72
  expect(user.id).toBe('carlos');
73
73
  expect(user.name).toBe('Carlos');
74
74
  expect(user.email).toBe('carlos@example.com');
75
- expect(user.avatar).toMatch(/^https:\/\/www\.gravatar\.com\/avatar\/[a-f0-9]{32}\?d=mp$/);
75
+ expect(user.avatarHash).toMatch(/^[a-f0-9]{32}$/);
76
76
  });
77
77
 
78
- it('should create different Gravatar URLs for different inputs', async () => {
78
+ it('should create different avatar hashes for different inputs', async () => {
79
79
  const registry = await createSubject();
80
80
  const user1 = registry.createTemporaryUser('Alice');
81
81
  const user2 = registry.createTemporaryUser('Bob');
82
- expect(user1.avatar).not.toBe(user2.avatar);
82
+ expect(user1.avatarHash).not.toBe(user2.avatarHash);
83
83
  });
84
84
  });
85
85