adi_dev_workflow 1.1.1 → 1.3.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 (98) hide show
  1. package/bin/index.js +8 -8
  2. package/frameworks/agents/qa-staff-engineer.md +311 -311
  3. package/frameworks/agents/qa-validation-expert.md +458 -458
  4. package/frameworks/agents/tech-review-conformance.md +200 -200
  5. package/frameworks/commands/ministack/README.md +2 -0
  6. package/frameworks/commands/ministack/code-review.md +2 -0
  7. package/frameworks/commands/ministack/generate-intent.md +2 -0
  8. package/frameworks/commands/ministack/generate-scope.md +2 -0
  9. package/frameworks/commands/ministack/generate-tasks.md +2 -0
  10. package/frameworks/commands/ministack/generate-tech-direction.md +2 -0
  11. package/frameworks/commands/ministack/run-ministack-tasks.md +3 -0
  12. package/frameworks/commands/ministack/run-ministack-withlinear.md +2 -0
  13. package/frameworks/commands/ministack/status.md +2 -0
  14. package/frameworks/commands/sdd/code-review.md +2 -0
  15. package/frameworks/commands/sdd/generate-prd.md +2 -0
  16. package/frameworks/commands/sdd/generate-task-plan.md +2 -0
  17. package/frameworks/commands/sdd/generate-tech-direction.md +2 -0
  18. package/frameworks/commands/sdd/generate-tech-spec.md +2 -0
  19. package/frameworks/commands/sdd/generate-tests.md +2 -0
  20. package/frameworks/commands/sdd/run_tasks.md +3 -0
  21. package/frameworks/commands/sdd/run_tasks_withlinear.md +2 -0
  22. package/frameworks/commands/sdd/status.md +2 -0
  23. package/frameworks/commands/sdd/validate-sdd.md +2 -0
  24. package/frameworks/commands/sync-tasks-to-linear.md +2 -0
  25. package/frameworks/commands/taskcard/generate-taskcard.md +2 -0
  26. package/frameworks/commands/taskcard/run-taskcard.md +2 -0
  27. package/frameworks/config/ai-framework-config.yaml +112 -0
  28. package/frameworks/skills/ministack-tasks-expert/SKILL.md +204 -204
  29. package/frameworks/skills/ministack-tasks-expert/templates/task_plan_template.md +78 -78
  30. package/frameworks/skills/ministack-tasks-expert/templates/task_template.md +103 -103
  31. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/benchmark.json +99 -99
  32. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/benchmark.md +64 -64
  33. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/eval_metadata.json +12 -12
  34. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/grading.json +32 -32
  35. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/outputs/response.md +134 -134
  36. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/outputs/transcript.md +68 -68
  37. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/with_skill/timing.json +5 -5
  38. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/grading.json +32 -32
  39. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/outputs/response.md +525 -525
  40. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/outputs/transcript.md +30 -30
  41. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-1-happy-path/without_skill/timing.json +5 -5
  42. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/eval_metadata.json +12 -12
  43. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/grading.json +32 -32
  44. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/outputs/response.md +1126 -1126
  45. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/outputs/transcript.md +131 -131
  46. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/with_skill/timing.json +5 -5
  47. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/grading.json +32 -32
  48. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/outputs/response.md +452 -452
  49. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/outputs/transcript.md +78 -78
  50. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-2-spec-simples/without_skill/timing.json +5 -5
  51. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/eval_metadata.json +12 -12
  52. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/grading.json +32 -32
  53. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/outputs/response.md +101 -101
  54. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/outputs/transcript.md +133 -133
  55. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/with_skill/timing.json +5 -5
  56. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/grading.json +32 -32
  57. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/outputs/response.md +248 -248
  58. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/outputs/transcript.md +49 -49
  59. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/eval-3-sem-user-stories/without_skill/timing.json +5 -5
  60. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-1/review.html +1325 -1325
  61. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/benchmark.json +94 -94
  62. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/benchmark.md +67 -67
  63. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/eval_metadata.json +12 -12
  64. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/grading.json +32 -32
  65. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/outputs/response.md +117 -117
  66. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/outputs/transcript.md +91 -91
  67. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/with_skill/timing.json +1 -1
  68. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/grading.json +32 -32
  69. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/outputs/response.md +694 -694
  70. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/outputs/transcript.md +45 -45
  71. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-1-happy-path/without_skill/timing.json +1 -1
  72. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/eval_metadata.json +12 -12
  73. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/grading.json +32 -32
  74. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/outputs/response.md +1087 -1087
  75. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/outputs/transcript.md +124 -124
  76. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/with_skill/timing.json +1 -1
  77. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/grading.json +32 -32
  78. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/outputs/response.md +458 -458
  79. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/outputs/transcript.md +84 -84
  80. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-2-spec-simples/without_skill/timing.json +1 -1
  81. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/eval_metadata.json +12 -12
  82. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/grading.json +32 -32
  83. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/outputs/response.md +70 -70
  84. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/outputs/transcript.md +148 -148
  85. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/with_skill/timing.json +1 -1
  86. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/grading.json +32 -32
  87. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/outputs/response.md +249 -249
  88. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/outputs/transcript.md +80 -80
  89. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/eval-3-sem-user-stories/without_skill/timing.json +1 -1
  90. package/frameworks/skills/sdd-task-plan-expert-workspace/iteration-2/review.html +1325 -1325
  91. package/frameworks/skills/sdd-tech-spec-expert/SKILL.md +317 -317
  92. package/frameworks/skills/sdd-tech-spec-expert/evals/evals.json +199 -199
  93. package/frameworks/skills/sdd-tech-spec-expert/templates/spec_tech_template.md +290 -290
  94. package/frameworks/skills/sdd-tech-spec-expert/templates/tech_direction-template.md +23 -23
  95. package/package.json +28 -28
  96. package/src/cli.js +121 -121
  97. package/src/installer.js +155 -136
  98. package/src/transformer.js +86 -86
@@ -1,249 +1,249 @@
1
- # TASK PLAN -- Cache de Cardapio v1
2
-
3
- ## 1. Identificacao
4
-
5
- | Campo | Valor |
6
- |-------|-------|
7
- | **Feature/Projeto** | Cache de Cardapio em Memoria |
8
- | **Versao** | v1 |
9
- | **Data** | 2026-03-08 |
10
- | **SPEC_TECH** | Cache de Cardapio v1 |
11
- | **Branch base** | user-feature |
12
-
13
- ---
14
-
15
- ## 2. Observacoes Preliminares
16
-
17
- O SPEC_TECH fornecido nao referencia User Stories nem PRD. Consequencias praticas:
18
-
19
- - Os criterios de aceite de cada task serao derivados exclusivamente das definicoes tecnicas do SPEC_TECH.
20
- - Nao ha requisitos funcionais de negocio formalizados (ex: "como garcom, quero ver o cardapio rapidamente"). A motivacao implicita e performance: evitar queries repetidas ao SQLite para leitura do cardapio.
21
- - **O codebase atual nao possui modulo de Product/Produto.** Apenas o modulo User esta implementado. O SPEC_TECH menciona "ProductService" como ponto de integracao do cache, portanto o modulo Product deve existir antes das tasks de integracao. Este task plan trata isso como pre-requisito explicito.
22
-
23
- ---
24
-
25
- ## 3. Pre-requisitos
26
-
27
- | # | Pre-requisito | Justificativa | Status |
28
- |---|---------------|---------------|--------|
29
- | P1 | Modulo Product completo (proto, migration, queries SQLC, repository, service, handler gRPC) | O cache sera integrado ao ProductService que ainda nao existe | Pendente |
30
- | P2 | Codigo SQLC gerado para produtos (`make sqlc`) | Repository de produtos depende do codigo gerado | Pendente |
31
- | P3 | Codigo Proto gerado para produtos (`make proto`) | Handler gRPC de produtos depende do codigo gerado | Pendente |
32
-
33
- > Tasks 1 e 2 (infraestrutura de cache e config) sao independentes dos pre-requisitos e podem ser iniciadas imediatamente. Tasks 3 a 5 dependem de P1.
34
-
35
- ---
36
-
37
- ## 4. Tasks
38
-
39
- ### Task 1 -- Configuracao de cache (config.yaml + struct Config)
40
-
41
- **Objetivo:** Tornar o TTL do cache configuravel via `config.yaml` e variaveis de ambiente.
42
-
43
- **Arquivos afetados:**
44
- - `configs/config.yaml` (modificar)
45
- - `internal/infra/config/config.go` (modificar)
46
-
47
- **Subtasks:**
48
-
49
- | # | Descricao | Detalhe |
50
- |---|-----------|---------|
51
- | 1.1 | Adicionar secao `cache` ao config.yaml | `cache:` com `ttl_seconds: 300` |
52
- | 1.2 | Adicionar campo `CacheTTLSeconds int` na struct `Config` | Em `internal/infra/config/config.go` |
53
- | 1.3 | Popular o campo no construtor `NewConfig` | `CacheTTLSeconds: v.GetInt("cache.ttl_seconds")`. Se valor for 0 (nao configurado), aplicar fallback para 300 |
54
- | 1.4 | Teste unitario | Verificar valor padrao 300, override via YAML e override via env var `APP_CACHE_TTL_SECONDS` |
55
-
56
- **Criterios de aceite:**
57
- - `Config.CacheTTLSeconds` retorna 300 quando a secao `cache` nao esta presente no YAML.
58
- - Override via YAML e via variavel de ambiente funciona corretamente.
59
- - Testes passam com `CGO_ENABLED=1 go test ./internal/infra/config/...`.
60
-
61
- **Estimativa:** P (pequena)
62
-
63
- ---
64
-
65
- ### Task 2 -- Pacote de cache generico com sync.Map
66
-
67
- **Objetivo:** Criar `internal/infra/cache/` com interface generica e implementacao in-memory com TTL.
68
-
69
- **Arquivos a criar:**
70
- - `internal/infra/cache/cache.go` -- interface e implementacao
71
- - `internal/infra/cache/cache_test.go` -- testes unitarios
72
- - `internal/infra/cache/fx.go` -- modulo FX (placeholder)
73
-
74
- **Subtasks:**
75
-
76
- | # | Descricao | Detalhe |
77
- |---|-----------|---------|
78
- | 2.1 | Definir interface `Cache[K comparable, V any]` | Metodos: `Get(key K) (V, bool)`, `Set(key K, value V)`, `Invalidate(key K)`, `InvalidateAll()` |
79
- | 2.2 | Definir struct interna `cacheEntry[V any]` | Campos: `value V`, `createdAt time.Time` |
80
- | 2.3 | Implementar `InMemoryCache[K, V]` | Usar `sync.Map` como storage. No `Get`, verificar `time.Since(entry.createdAt) > ttl`; se expirado, deletar e retornar zero value + false |
81
- | 2.4 | Construtor `NewInMemoryCache[K, V](ttl time.Duration) Cache[K, V]` | Retornar ponteiro para InMemoryCache |
82
- | 2.5 | Testes unitarios | Cenarios: Get/Set basico, expiracao por TTL (usar TTL de 50ms + time.Sleep), Invalidate chave unica, InvalidateAll, Get de chave inexistente |
83
- | 2.6 | Modulo FX | Criar `fx.go` com modulo vazio por enquanto; a factory concreta sera adicionada na Task 3 |
84
-
85
- **Decisoes tecnicas:**
86
- - `sync.Map` e thread-safe e otimizado para leitura frequente, adequado para cache de cardapio.
87
- - Verificacao de TTL e lazy (no `Get`), sem goroutine de limpeza. Aceitavel em v1 para cardapio com poucos itens.
88
- - Generics do Go 1.24 permitem type safety sem type assertions manuais.
89
-
90
- **Criterios de aceite:**
91
- - Interface `Cache[K, V]` exportada e documentada.
92
- - `InMemoryCache` implementa todos os metodos da interface.
93
- - Itens expirados nao sao retornados por `Get`.
94
- - `Invalidate` remove entrada especifica; `InvalidateAll` limpa tudo.
95
- - Testes passam, incluindo cenario de expiracao.
96
-
97
- **Estimativa:** M (media)
98
-
99
- ---
100
-
101
- ### Task 3 -- Registro do cache no sistema de DI (Uber FX)
102
-
103
- **Objetivo:** Criar factory function para cache de produtos e registrar no grafo de dependencias.
104
-
105
- **Arquivos afetados:**
106
- - `internal/infra/cache/fx.go` (modificar -- criado na Task 2)
107
- - `internal/infra/di/fx.go` (modificar)
108
-
109
- **Subtasks:**
110
-
111
- | # | Descricao | Detalhe |
112
- |---|-----------|---------|
113
- | 3.1 | Criar factory `NewProductCache` | `func NewProductCache(cfg *config.Config) Cache[string, *repository.Product]` -- converte `cfg.CacheTTLSeconds` para `time.Duration` e chama `NewInMemoryCache` |
114
- | 3.2 | Registrar provider no modulo FX | `fx.Provide(NewProductCache)` dentro de `cache.Module` |
115
- | 3.3 | Importar `cache.Module` em `internal/infra/di/fx.go` | Posicionar apos `config.Module` e antes de `repository.Module` |
116
- | 3.4 | Verificar inicializacao | Rodar `fx.ValidateApp` ou iniciar a aplicacao para confirmar que o grafo resolve sem erros |
117
-
118
- **Dependencias:** Task 1, Task 2, Pre-requisito P1 (tipo `repository.Product` deve existir)
119
-
120
- **Criterios de aceite:**
121
- - `cache.Module` registrado em `AppModule()`.
122
- - Aplicacao inicializa sem erros de resolucao de dependencias.
123
- - Factory usa o TTL do config (nao hardcoded).
124
-
125
- **Estimativa:** P (pequena)
126
-
127
- ---
128
-
129
- ### Task 4 -- Integracao do cache no ProductService
130
-
131
- **Objetivo:** Implementar padrao cache-aside no ProductService: consultar cache antes do repository nas leituras, e invalidar cache nas escritas.
132
-
133
- **Arquivos afetados:**
134
- - `internal/service/product_service.go` (modificar)
135
- - `internal/service/product_service_test.go` (modificar)
136
-
137
- **Subtasks:**
138
-
139
- | # | Descricao | Detalhe |
140
- |---|-----------|---------|
141
- | 4.1 | Adicionar campo `cache` na struct do service | `cache cache.Cache[string, *repository.Product]` |
142
- | 4.2 | Atualizar construtor `NewProductService` | Adicionar parametro `cache cache.Cache[string, *repository.Product]` |
143
- | 4.3 | Implementar cache-aside no `GetProduct` (ou `GetProductByID`) | 1) `cache.Get(id)` -- se hit, logar e retornar. 2) Se miss, `repo.GetByID(id)`, `cache.Set(id, product)`, retornar. |
144
- | 4.4 | Invalidar cache no `CreateProduct` | Apos criacao no repository com sucesso, **nao popular o cache** (evita inconsistencia com listagens). |
145
- | 4.5 | Invalidar cache no `UpdateProduct` | `cache.Invalidate(id)` apos update no repository |
146
- | 4.6 | Invalidar cache no `DeleteProduct` | `cache.Invalidate(id)` apos delete no repository |
147
- | 4.7 | Adicionar logs de cache | `s.logger.Debug("cache hit para produto", zap.String("id", id))` e `s.logger.Debug("cache miss para produto", zap.String("id", id))` |
148
- | 4.8 | Testes unitarios com mock de cache | Cenarios: (a) cache hit -- repo nao e chamado, (b) cache miss -- repo e chamado e cache e populado, (c) create/update/delete invalidam cache |
149
-
150
- **Dependencias:** Task 3, Pre-requisito P1
151
-
152
- **Criterios de aceite:**
153
- - `GetProduct` retorna do cache em cache hit sem chamar o repository.
154
- - `GetProduct` busca do repository em cache miss, popula o cache, e retorna.
155
- - Operacoes de escrita (`Create`, `Update`, `Delete`) invalidam a entrada correspondente.
156
- - Logs de debug indicam hit/miss.
157
- - Testes unitarios passam com mocks para cache e repository.
158
- - Nenhuma regressao nos testes existentes do modulo.
159
-
160
- **Estimativa:** M (media)
161
-
162
- ---
163
-
164
- ### Task 5 -- Testes de integracao e validacao final
165
-
166
- **Objetivo:** Validar o comportamento end-to-end do cache, incluindo TTL, concorrencia e ausencia de regressoes.
167
-
168
- **Arquivos afetados:**
169
- - `internal/service/product_service_test.go` (adicionar testes)
170
-
171
- **Subtasks:**
172
-
173
- | # | Descricao | Detalhe |
174
- |---|-----------|---------|
175
- | 5.1 | Teste de fluxo completo | Create -> Get (miss, popula) -> Get (hit) -> Update (invalida) -> Get (miss novamente) |
176
- | 5.2 | Teste de expiracao por TTL | Set com TTL curto (100ms) -> Get (hit) -> Sleep(150ms) -> Get (miss) |
177
- | 5.3 | Teste de concorrencia (race detection) | Multiplas goroutines fazendo Get/Set simultaneo; rodar com `-race` |
178
- | 5.4 | Rodar suite completa | `make test` -- todos os testes do projeto devem passar |
179
- | 5.5 | Validar build | `make build` deve compilar sem erros |
180
-
181
- **Dependencias:** Tasks 1 a 4 completas
182
-
183
- **Criterios de aceite:**
184
- - Todos os cenarios de teste passam.
185
- - `CGO_ENABLED=1 go test -race ./internal/...` nao detecta race conditions.
186
- - `make build` e `make test` passam sem erros.
187
-
188
- **Estimativa:** M (media)
189
-
190
- ---
191
-
192
- ## 5. Grafo de Dependencias
193
-
194
- ```
195
- Task 1 (Config) ─────┐
196
- ├──> Task 3 (DI) ──> Task 4 (Service) ──> Task 5 (Validacao)
197
- Task 2 (Cache pkg) ──┘
198
- ```
199
-
200
- - **Paralelizaveis:** Tasks 1 e 2 (sem dependencia entre si).
201
- - **Sequenciais:** Task 3 depende de 1 + 2. Task 4 depende de 3. Task 5 depende de 4.
202
- - **Bloqueio externo:** Tasks 3, 4 e 5 dependem do pre-requisito P1 (modulo Product).
203
-
204
- ---
205
-
206
- ## 6. Resumo de Estimativas
207
-
208
- | Task | Descricao | Estimativa | Dependencias |
209
- |------|-----------|------------|--------------|
210
- | 1 | Config de cache | P (pequena) | Nenhuma |
211
- | 2 | Pacote cache generico | M (media) | Nenhuma |
212
- | 3 | Registro no FX (DI) | P (pequena) | Tasks 1, 2 + P1 |
213
- | 4 | Integracao no ProductService | M (media) | Task 3 + P1 |
214
- | 5 | Testes e validacao | M (media) | Task 4 |
215
-
216
- **Esforco total estimado:** 1.5 a 2 dias de desenvolvimento (assumindo P1 ja resolvido).
217
-
218
- ---
219
-
220
- ## 7. Riscos e Mitigacoes
221
-
222
- | # | Risco | Impacto | Mitigacao |
223
- |---|-------|---------|-----------|
224
- | R1 | Modulo Product nao existe -- bloqueia Tasks 3-5 | Alto | Tasks 1 e 2 sao independentes e podem avancar. Priorizar implementacao do modulo Product. |
225
- | R2 | `sync.Map` usa `any` internamente, exigindo type assertions | Baixo | Wrapper generico (`InMemoryCache[K, V]`) encapsula as assertions. Testes garantem type safety. |
226
- | R3 | Lazy expiration pode acumular entradas expiradas em memoria | Baixo | Cardapio tem poucos itens (dezenas). Aceitavel em v1. Considerar cleanup periodico em v2. |
227
- | R4 | Dados stale em escrita concorrente (ex: dois updates simultaneos) | Baixo | Invalidacao sincrona no fluxo de escrita. TTL de 300s garante convergencia eventual. |
228
- | R5 | Ausencia de metricas (hit rate, tamanho do cache) | Baixo | Fora de escopo em v1. Logs de debug permitem analise manual. Considerar metricas em v2. |
229
- | R6 | Sem PRD/User Stories -- criterios de aceite podem nao cobrir expectativas do negocio | Medio | Criterios derivados do SPEC_TECH. Validar com stakeholders se ha requisitos funcionais adicionais. |
230
-
231
- ---
232
-
233
- ## 8. Arquivos Criados e Modificados
234
-
235
- ### Novos arquivos:
236
- | Arquivo | Task |
237
- |---------|------|
238
- | `internal/infra/cache/cache.go` | Task 2 |
239
- | `internal/infra/cache/cache_test.go` | Task 2 |
240
- | `internal/infra/cache/fx.go` | Tasks 2, 3 |
241
-
242
- ### Arquivos modificados:
243
- | Arquivo | Task | Alteracao |
244
- |---------|------|-----------|
245
- | `configs/config.yaml` | Task 1 | Adicionar secao `cache` |
246
- | `internal/infra/config/config.go` | Task 1 | Adicionar campo `CacheTTLSeconds` |
247
- | `internal/infra/di/fx.go` | Task 3 | Importar e registrar `cache.Module` |
248
- | `internal/service/product_service.go` | Task 4 | Adicionar dependencia de cache e logica cache-aside |
249
- | `internal/service/product_service_test.go` | Tasks 4, 5 | Testes de cache hit/miss, TTL, concorrencia |
1
+ # TASK PLAN -- Cache de Cardapio v1
2
+
3
+ ## 1. Identificacao
4
+
5
+ | Campo | Valor |
6
+ |-------|-------|
7
+ | **Feature/Projeto** | Cache de Cardapio em Memoria |
8
+ | **Versao** | v1 |
9
+ | **Data** | 2026-03-08 |
10
+ | **SPEC_TECH** | Cache de Cardapio v1 |
11
+ | **Branch base** | user-feature |
12
+
13
+ ---
14
+
15
+ ## 2. Observacoes Preliminares
16
+
17
+ O SPEC_TECH fornecido nao referencia User Stories nem PRD. Consequencias praticas:
18
+
19
+ - Os criterios de aceite de cada task serao derivados exclusivamente das definicoes tecnicas do SPEC_TECH.
20
+ - Nao ha requisitos funcionais de negocio formalizados (ex: "como garcom, quero ver o cardapio rapidamente"). A motivacao implicita e performance: evitar queries repetidas ao SQLite para leitura do cardapio.
21
+ - **O codebase atual nao possui modulo de Product/Produto.** Apenas o modulo User esta implementado. O SPEC_TECH menciona "ProductService" como ponto de integracao do cache, portanto o modulo Product deve existir antes das tasks de integracao. Este task plan trata isso como pre-requisito explicito.
22
+
23
+ ---
24
+
25
+ ## 3. Pre-requisitos
26
+
27
+ | # | Pre-requisito | Justificativa | Status |
28
+ |---|---------------|---------------|--------|
29
+ | P1 | Modulo Product completo (proto, migration, queries SQLC, repository, service, handler gRPC) | O cache sera integrado ao ProductService que ainda nao existe | Pendente |
30
+ | P2 | Codigo SQLC gerado para produtos (`make sqlc`) | Repository de produtos depende do codigo gerado | Pendente |
31
+ | P3 | Codigo Proto gerado para produtos (`make proto`) | Handler gRPC de produtos depende do codigo gerado | Pendente |
32
+
33
+ > Tasks 1 e 2 (infraestrutura de cache e config) sao independentes dos pre-requisitos e podem ser iniciadas imediatamente. Tasks 3 a 5 dependem de P1.
34
+
35
+ ---
36
+
37
+ ## 4. Tasks
38
+
39
+ ### Task 1 -- Configuracao de cache (config.yaml + struct Config)
40
+
41
+ **Objetivo:** Tornar o TTL do cache configuravel via `config.yaml` e variaveis de ambiente.
42
+
43
+ **Arquivos afetados:**
44
+ - `configs/config.yaml` (modificar)
45
+ - `internal/infra/config/config.go` (modificar)
46
+
47
+ **Subtasks:**
48
+
49
+ | # | Descricao | Detalhe |
50
+ |---|-----------|---------|
51
+ | 1.1 | Adicionar secao `cache` ao config.yaml | `cache:` com `ttl_seconds: 300` |
52
+ | 1.2 | Adicionar campo `CacheTTLSeconds int` na struct `Config` | Em `internal/infra/config/config.go` |
53
+ | 1.3 | Popular o campo no construtor `NewConfig` | `CacheTTLSeconds: v.GetInt("cache.ttl_seconds")`. Se valor for 0 (nao configurado), aplicar fallback para 300 |
54
+ | 1.4 | Teste unitario | Verificar valor padrao 300, override via YAML e override via env var `APP_CACHE_TTL_SECONDS` |
55
+
56
+ **Criterios de aceite:**
57
+ - `Config.CacheTTLSeconds` retorna 300 quando a secao `cache` nao esta presente no YAML.
58
+ - Override via YAML e via variavel de ambiente funciona corretamente.
59
+ - Testes passam com `CGO_ENABLED=1 go test ./internal/infra/config/...`.
60
+
61
+ **Estimativa:** P (pequena)
62
+
63
+ ---
64
+
65
+ ### Task 2 -- Pacote de cache generico com sync.Map
66
+
67
+ **Objetivo:** Criar `internal/infra/cache/` com interface generica e implementacao in-memory com TTL.
68
+
69
+ **Arquivos a criar:**
70
+ - `internal/infra/cache/cache.go` -- interface e implementacao
71
+ - `internal/infra/cache/cache_test.go` -- testes unitarios
72
+ - `internal/infra/cache/fx.go` -- modulo FX (placeholder)
73
+
74
+ **Subtasks:**
75
+
76
+ | # | Descricao | Detalhe |
77
+ |---|-----------|---------|
78
+ | 2.1 | Definir interface `Cache[K comparable, V any]` | Metodos: `Get(key K) (V, bool)`, `Set(key K, value V)`, `Invalidate(key K)`, `InvalidateAll()` |
79
+ | 2.2 | Definir struct interna `cacheEntry[V any]` | Campos: `value V`, `createdAt time.Time` |
80
+ | 2.3 | Implementar `InMemoryCache[K, V]` | Usar `sync.Map` como storage. No `Get`, verificar `time.Since(entry.createdAt) > ttl`; se expirado, deletar e retornar zero value + false |
81
+ | 2.4 | Construtor `NewInMemoryCache[K, V](ttl time.Duration) Cache[K, V]` | Retornar ponteiro para InMemoryCache |
82
+ | 2.5 | Testes unitarios | Cenarios: Get/Set basico, expiracao por TTL (usar TTL de 50ms + time.Sleep), Invalidate chave unica, InvalidateAll, Get de chave inexistente |
83
+ | 2.6 | Modulo FX | Criar `fx.go` com modulo vazio por enquanto; a factory concreta sera adicionada na Task 3 |
84
+
85
+ **Decisoes tecnicas:**
86
+ - `sync.Map` e thread-safe e otimizado para leitura frequente, adequado para cache de cardapio.
87
+ - Verificacao de TTL e lazy (no `Get`), sem goroutine de limpeza. Aceitavel em v1 para cardapio com poucos itens.
88
+ - Generics do Go 1.24 permitem type safety sem type assertions manuais.
89
+
90
+ **Criterios de aceite:**
91
+ - Interface `Cache[K, V]` exportada e documentada.
92
+ - `InMemoryCache` implementa todos os metodos da interface.
93
+ - Itens expirados nao sao retornados por `Get`.
94
+ - `Invalidate` remove entrada especifica; `InvalidateAll` limpa tudo.
95
+ - Testes passam, incluindo cenario de expiracao.
96
+
97
+ **Estimativa:** M (media)
98
+
99
+ ---
100
+
101
+ ### Task 3 -- Registro do cache no sistema de DI (Uber FX)
102
+
103
+ **Objetivo:** Criar factory function para cache de produtos e registrar no grafo de dependencias.
104
+
105
+ **Arquivos afetados:**
106
+ - `internal/infra/cache/fx.go` (modificar -- criado na Task 2)
107
+ - `internal/infra/di/fx.go` (modificar)
108
+
109
+ **Subtasks:**
110
+
111
+ | # | Descricao | Detalhe |
112
+ |---|-----------|---------|
113
+ | 3.1 | Criar factory `NewProductCache` | `func NewProductCache(cfg *config.Config) Cache[string, *repository.Product]` -- converte `cfg.CacheTTLSeconds` para `time.Duration` e chama `NewInMemoryCache` |
114
+ | 3.2 | Registrar provider no modulo FX | `fx.Provide(NewProductCache)` dentro de `cache.Module` |
115
+ | 3.3 | Importar `cache.Module` em `internal/infra/di/fx.go` | Posicionar apos `config.Module` e antes de `repository.Module` |
116
+ | 3.4 | Verificar inicializacao | Rodar `fx.ValidateApp` ou iniciar a aplicacao para confirmar que o grafo resolve sem erros |
117
+
118
+ **Dependencias:** Task 1, Task 2, Pre-requisito P1 (tipo `repository.Product` deve existir)
119
+
120
+ **Criterios de aceite:**
121
+ - `cache.Module` registrado em `AppModule()`.
122
+ - Aplicacao inicializa sem erros de resolucao de dependencias.
123
+ - Factory usa o TTL do config (nao hardcoded).
124
+
125
+ **Estimativa:** P (pequena)
126
+
127
+ ---
128
+
129
+ ### Task 4 -- Integracao do cache no ProductService
130
+
131
+ **Objetivo:** Implementar padrao cache-aside no ProductService: consultar cache antes do repository nas leituras, e invalidar cache nas escritas.
132
+
133
+ **Arquivos afetados:**
134
+ - `internal/service/product_service.go` (modificar)
135
+ - `internal/service/product_service_test.go` (modificar)
136
+
137
+ **Subtasks:**
138
+
139
+ | # | Descricao | Detalhe |
140
+ |---|-----------|---------|
141
+ | 4.1 | Adicionar campo `cache` na struct do service | `cache cache.Cache[string, *repository.Product]` |
142
+ | 4.2 | Atualizar construtor `NewProductService` | Adicionar parametro `cache cache.Cache[string, *repository.Product]` |
143
+ | 4.3 | Implementar cache-aside no `GetProduct` (ou `GetProductByID`) | 1) `cache.Get(id)` -- se hit, logar e retornar. 2) Se miss, `repo.GetByID(id)`, `cache.Set(id, product)`, retornar. |
144
+ | 4.4 | Invalidar cache no `CreateProduct` | Apos criacao no repository com sucesso, **nao popular o cache** (evita inconsistencia com listagens). |
145
+ | 4.5 | Invalidar cache no `UpdateProduct` | `cache.Invalidate(id)` apos update no repository |
146
+ | 4.6 | Invalidar cache no `DeleteProduct` | `cache.Invalidate(id)` apos delete no repository |
147
+ | 4.7 | Adicionar logs de cache | `s.logger.Debug("cache hit para produto", zap.String("id", id))` e `s.logger.Debug("cache miss para produto", zap.String("id", id))` |
148
+ | 4.8 | Testes unitarios com mock de cache | Cenarios: (a) cache hit -- repo nao e chamado, (b) cache miss -- repo e chamado e cache e populado, (c) create/update/delete invalidam cache |
149
+
150
+ **Dependencias:** Task 3, Pre-requisito P1
151
+
152
+ **Criterios de aceite:**
153
+ - `GetProduct` retorna do cache em cache hit sem chamar o repository.
154
+ - `GetProduct` busca do repository em cache miss, popula o cache, e retorna.
155
+ - Operacoes de escrita (`Create`, `Update`, `Delete`) invalidam a entrada correspondente.
156
+ - Logs de debug indicam hit/miss.
157
+ - Testes unitarios passam com mocks para cache e repository.
158
+ - Nenhuma regressao nos testes existentes do modulo.
159
+
160
+ **Estimativa:** M (media)
161
+
162
+ ---
163
+
164
+ ### Task 5 -- Testes de integracao e validacao final
165
+
166
+ **Objetivo:** Validar o comportamento end-to-end do cache, incluindo TTL, concorrencia e ausencia de regressoes.
167
+
168
+ **Arquivos afetados:**
169
+ - `internal/service/product_service_test.go` (adicionar testes)
170
+
171
+ **Subtasks:**
172
+
173
+ | # | Descricao | Detalhe |
174
+ |---|-----------|---------|
175
+ | 5.1 | Teste de fluxo completo | Create -> Get (miss, popula) -> Get (hit) -> Update (invalida) -> Get (miss novamente) |
176
+ | 5.2 | Teste de expiracao por TTL | Set com TTL curto (100ms) -> Get (hit) -> Sleep(150ms) -> Get (miss) |
177
+ | 5.3 | Teste de concorrencia (race detection) | Multiplas goroutines fazendo Get/Set simultaneo; rodar com `-race` |
178
+ | 5.4 | Rodar suite completa | `make test` -- todos os testes do projeto devem passar |
179
+ | 5.5 | Validar build | `make build` deve compilar sem erros |
180
+
181
+ **Dependencias:** Tasks 1 a 4 completas
182
+
183
+ **Criterios de aceite:**
184
+ - Todos os cenarios de teste passam.
185
+ - `CGO_ENABLED=1 go test -race ./internal/...` nao detecta race conditions.
186
+ - `make build` e `make test` passam sem erros.
187
+
188
+ **Estimativa:** M (media)
189
+
190
+ ---
191
+
192
+ ## 5. Grafo de Dependencias
193
+
194
+ ```
195
+ Task 1 (Config) ─────┐
196
+ ├──> Task 3 (DI) ──> Task 4 (Service) ──> Task 5 (Validacao)
197
+ Task 2 (Cache pkg) ──┘
198
+ ```
199
+
200
+ - **Paralelizaveis:** Tasks 1 e 2 (sem dependencia entre si).
201
+ - **Sequenciais:** Task 3 depende de 1 + 2. Task 4 depende de 3. Task 5 depende de 4.
202
+ - **Bloqueio externo:** Tasks 3, 4 e 5 dependem do pre-requisito P1 (modulo Product).
203
+
204
+ ---
205
+
206
+ ## 6. Resumo de Estimativas
207
+
208
+ | Task | Descricao | Estimativa | Dependencias |
209
+ |------|-----------|------------|--------------|
210
+ | 1 | Config de cache | P (pequena) | Nenhuma |
211
+ | 2 | Pacote cache generico | M (media) | Nenhuma |
212
+ | 3 | Registro no FX (DI) | P (pequena) | Tasks 1, 2 + P1 |
213
+ | 4 | Integracao no ProductService | M (media) | Task 3 + P1 |
214
+ | 5 | Testes e validacao | M (media) | Task 4 |
215
+
216
+ **Esforco total estimado:** 1.5 a 2 dias de desenvolvimento (assumindo P1 ja resolvido).
217
+
218
+ ---
219
+
220
+ ## 7. Riscos e Mitigacoes
221
+
222
+ | # | Risco | Impacto | Mitigacao |
223
+ |---|-------|---------|-----------|
224
+ | R1 | Modulo Product nao existe -- bloqueia Tasks 3-5 | Alto | Tasks 1 e 2 sao independentes e podem avancar. Priorizar implementacao do modulo Product. |
225
+ | R2 | `sync.Map` usa `any` internamente, exigindo type assertions | Baixo | Wrapper generico (`InMemoryCache[K, V]`) encapsula as assertions. Testes garantem type safety. |
226
+ | R3 | Lazy expiration pode acumular entradas expiradas em memoria | Baixo | Cardapio tem poucos itens (dezenas). Aceitavel em v1. Considerar cleanup periodico em v2. |
227
+ | R4 | Dados stale em escrita concorrente (ex: dois updates simultaneos) | Baixo | Invalidacao sincrona no fluxo de escrita. TTL de 300s garante convergencia eventual. |
228
+ | R5 | Ausencia de metricas (hit rate, tamanho do cache) | Baixo | Fora de escopo em v1. Logs de debug permitem analise manual. Considerar metricas em v2. |
229
+ | R6 | Sem PRD/User Stories -- criterios de aceite podem nao cobrir expectativas do negocio | Medio | Criterios derivados do SPEC_TECH. Validar com stakeholders se ha requisitos funcionais adicionais. |
230
+
231
+ ---
232
+
233
+ ## 8. Arquivos Criados e Modificados
234
+
235
+ ### Novos arquivos:
236
+ | Arquivo | Task |
237
+ |---------|------|
238
+ | `internal/infra/cache/cache.go` | Task 2 |
239
+ | `internal/infra/cache/cache_test.go` | Task 2 |
240
+ | `internal/infra/cache/fx.go` | Tasks 2, 3 |
241
+
242
+ ### Arquivos modificados:
243
+ | Arquivo | Task | Alteracao |
244
+ |---------|------|-----------|
245
+ | `configs/config.yaml` | Task 1 | Adicionar secao `cache` |
246
+ | `internal/infra/config/config.go` | Task 1 | Adicionar campo `CacheTTLSeconds` |
247
+ | `internal/infra/di/fx.go` | Task 3 | Importar e registrar `cache.Module` |
248
+ | `internal/service/product_service.go` | Task 4 | Adicionar dependencia de cache e logica cache-aside |
249
+ | `internal/service/product_service_test.go` | Tasks 4, 5 | Testes de cache hit/miss, TTL, concorrencia |