speckit.tasks: Cara AI Breakdown Task Golang yang Actionable dan Estimasi Akurat
Panduan lengkap speckit.tasks untuk membuat task breakdown yang actionable di project Golang. Cara membaca tasks.md, assign tasks ke developer, dan tracking progress implementasi.
speckit.tasks: Breakdown Tasks yang Actionable dan Paralel
Perintah specify tasks (atau speckit.tasks) mengambil plan.md yang sudah kita validasi dan memecahnya menjadi task breakdown Golang yang bisa dikerjakan oleh satu developer dalam 15-90 menit per task. Setiap task punya definition of done yang concrete, file yang harus dibuat atau dimodifikasi, dan dependency yang jelas.
Ini adalah “sprint planning yang sudah di-prepare oleh AI” — dan di artikel ini kita bedah cara membacanya, meng-assign task, hingga tracking progress implementasi.
09.1 Menjalankan specify tasks
Untuk menghasilkan breakdown, jalankan perintah dengan nama fitur seperti berikut.
1specify tasks product-searchSetelah dijalankan, Spec Kit membaca plan.md lalu melaporkan ringkasan jumlah fase, file, dan estimasi waktu seperti output berikut.
1📋 Generating Task Breakdown: product-search
2
3Reading plan.md...
4 Phase count: 4
5 Files to create: 8
6 Files to modify: 3
7 Test cases: 12
8
9Generating tasks...
10
11✅ Tasks created: .specify/features/product-search/tasks.md
12 Total tasks: 16
13 Estimated total time: 11.5 hours
14 Phases: 4
15 Can be parallelized: Phase 3 and 4 can run in parallel after Phase 2Output di atas langsung memberi gambaran besar: berapa banyak task yang dihasilkan, total estimasi waktu, dan bagian mana yang bisa dikerjakan paralel — sebelum kamu membuka isi tasks.md.
09.2 Anatomy tasks.md yang Lengkap
Berikut adalah isi lengkap tasks.md yang dihasilkan. Perhatikan bagaimana setiap fase punya tabel ringkasan, task dengan file target, snippet kode, langkah, dan definition of done.
1# Tasks: Product Search
2# Based on: plan.md v1.0, spec.md v1.3
3# Generated: 2025-07-02
4# Total estimated: 11.5 hours across 4 phases
5
6---
7
8## Summary
9
10| Phase | Name | Tasks | Est. Time | Dependencies |
11|-------|------|-------|-----------|--------------|
12| 1 | Infrastructure | 2 | 1.5h | None |
13| 2 | Data Layer | 4 | 4h | Phase 1 |
14| 3 | Business Logic | 4 | 3h | Phase 2 |
15| 4 | HTTP Layer | 4 | 2.5h | Phase 2 (can run parallel with Phase 3) |
16| 5 | Integration | 2 | 0.5h | Phase 3 + 4 |
17
18---
19
20## Phase 1: Infrastructure [1.5 hours] 🏗️
21
22### Task 1.1: Create Database Migration [30 min]
23
24**File:** `migrations/20250702001_add_search_index.sql`
25
26**Content:**
27```sql
28CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_products_fts
29ON products
30USING gin(
31 to_tsvector('indonesian', name || ' ' || COALESCE(description, ''))
32);
33```
34
35**Steps:**
361. Create migration file with the SQL above
372. Run against local PostgreSQL: `psql $DATABASE_URL -f migrations/20250702001_add_search_index.sql`
383. Verify with: `SELECT indexname FROM pg_indexes WHERE tablename = 'products' AND indexname = 'idx_products_fts'`
39
40**Definition of Done:**
41- [ ] Migration file created at correct path
42- [ ] Index exists in local database
43- [ ] `go build ./...` still passes (migration only, no Go changes)
44
45---
46
47### Task 1.2: Add Search DTOs [30 min]
48
49**File:** `internal/product/usecase/dto.go` (MODIFY — add to existing file)
50
51**Content to add:**
52```go
53// SearchQuery represents a validated search request.
54type SearchQuery struct {
55 Keyword string
56 CategoryID *uuid.UUID
57 SortBy SortOption
58 Page int
59 PerPage int
60}
61
62// SortOption defines valid sort orders.
63type SortOption string
64
65const (
66 SortByRelevance SortOption = "relevance"
67 SortByNewest SortOption = "newest"
68 SortByPriceAsc SortOption = "price_asc"
69 SortByPriceDesc SortOption = "price_desc"
70)
71
72// SearchResult is the paginated product search response.
73type SearchResult struct {
74 Products []ProductSearchItem
75 TotalItems int
76 Page, PerPage, TotalPages int
77}
78
79// ProductSearchItem is one product in search results.
80type ProductSearchItem struct {
81 ID uuid.UUID
82 Name string
83 PriceCents int64
84 Stock int
85 IsAvailable bool // false when stock=0 (shows "Out of Stock" badge)
86 CategoryID *uuid.UUID
87 ThumbnailURL string
88}
89```
90
91**Definition of Done:**
92- [ ] Structs added to dto.go without breaking existing types
93- [ ] `go build ./internal/product/usecase/...` passes
94
95---
96
97## Phase 2: Data Layer [4 hours] 🗄️
98
99### Task 2.1: Add SearchUseCase Interface [20 min]
100
101**File:** `internal/product/usecase/interface.go` (MODIFY)
102
103**Add to SearchUseCase interface:**
104```go
105type SearchUseCase interface {
106 SearchProducts(ctx context.Context, query SearchQuery) (*SearchResult, error)
107}
108```
109
110**Add SearchProducts to ProductRepository interface:**
111```go
112type ProductRepository interface {
113 // ... existing methods ...
114 SearchProducts(ctx context.Context, filter SearchQuery) ([]ProductSearchItem, int, error)
115}
116```
117
118**After adding interface, regenerate mock:**
119```bash
120go generate ./internal/product/usecase/...
121```
122
123**Definition of Done:**
124- [ ] Interfaces updated
125- [ ] Mock regenerated: `internal/product/usecase/mocks/mock_product_repository.go`
126- [ ] `go build ./internal/product/...` passes
127
128---
129
130### Task 2.2: Implement SearchProducts Repository [90 min]
131
132**File:** `internal/product/repository/postgres_repository.go` (MODIFY)
133
134**Method signature:**
135```go
136func (r *postgresProductRepository) SearchProducts(
137 ctx context.Context,
138 filter usecase.SearchQuery,
139) ([]usecase.ProductSearchItem, int, error)
140```
141
142**Implementation approach:**
1431. Build SQL with dynamic ORDER BY based on SortBy
1442. Use `plainto_tsquery` for keyword (handles multi-word naturally)
1453. Count query (same WHERE but without LIMIT/OFFSET)
1464. Scan results into `[]ProductSearchItem`
147
148**SQL to implement:**
149```sql
150-- Count query
151SELECT COUNT(*) FROM products p
152WHERE p.status = 'ACTIVE' AND p.deleted_at IS NULL
153AND to_tsvector('indonesian', p.name || ' ' || COALESCE(p.description, ''))
154 @@ plainto_tsquery('indonesian', $1)
155AND ($2::uuid IS NULL OR p.category_id = $2)
156
157-- Results query
158SELECT p.id, p.name, p.price_cents, p.stock, p.stock > 0 AS is_available,
159 p.category_id, p.thumbnail_url
160FROM products p
161WHERE [same conditions]
162ORDER BY [dynamic based on SortBy]
163LIMIT $4 OFFSET $5
164```
165
166**Definition of Done:**
167- [ ] Method compiles without error
168- [ ] Manual test with psql or integration test passes
169- [ ] `go vet ./internal/product/repository/...` passes
170
171---
172
173### Task 2.3: Write Repository Integration Test [40 min]
174
175**File:** `internal/product/repository/postgres_repository_test.go` (MODIFY)
176
177**Tests to add:**
178```go
179func (s *ProductRepositorySuite) TestSearchProducts_ValidKeyword_ReturnsMatching()
180func (s *ProductRepositorySuite) TestSearchProducts_DeactivatedProduct_NotInResults()
181func (s *ProductRepositorySuite) TestSearchProducts_OutOfStock_ShowsIsAvailableFalse()
182func (s *ProductRepositorySuite) TestSearchProducts_CategoryFilter_FiltersCorrectly()
183func (s *ProductRepositorySuite) TestSearchProducts_EmptyResults_ReturnsZeroCount()
184```
185
186**Setup:** Use test database (testcontainers or local test DB) with seed data:
187- 3 active products matching "laptop"
188- 1 inactive product matching "laptop" (should not appear)
189- 1 active product with stock=0 (should appear with is_available=false)
190- 2 products in different category (should not appear with category filter)
191
192**Definition of Done:**
193- [ ] All 5 test functions pass with `go test -tags=integration`
194- [ ] Test correctly verifies is_available for stock=0 case
195
196---
197
198### Task 2.4: Implement SearchUseCase [40 min]
199
200**File:** `internal/product/usecase/search_usecase.go` (CREATE)
201
202**Implementation:**
203```go
204package usecase
205
206type searchUseCase struct {
207 repo ProductRepository
208}
209
210func NewSearchUseCase(repo ProductRepository) SearchUseCase {
211 return &searchUseCase{repo: repo}
212}
213
214func (uc *searchUseCase) SearchProducts(
215 ctx context.Context,
216 query SearchQuery,
217) (*SearchResult, error) {
218 // 1. Validate (keyword length, sort option)
219 // 2. Set defaults (page=1, per_page=20 if not set)
220 // 3. Call repository
221 // 4. Calculate total pages
222 // 5. Return SearchResult
223}
224```
225
226**Definition of Done:**
227- [ ] File compiles
228- [ ] Validation: keyword < 2 chars returns error with code
229- [ ] Defaults applied correctly
230
231---
232
233## Phase 3: Business Logic Tests [3 hours] 🧪
234
235(Can run in PARALLEL with Phase 4 after Phase 2 complete)
236
237### Task 3.1: Write SearchUseCase Unit Tests [90 min]
238
239**File:** `internal/product/usecase/search_usecase_test.go` (CREATE)
240
241**Tests (mapped to spec ACs):**
242```go
243// AC1, AC3
244func (s *SearchUseCaseSuite) TestSearchProducts_ValidKeyword_ReturnsMatchingProducts()
245// AC2
246func (s *SearchUseCaseSuite) TestSearchProducts_DeactivatedProduct_NotInResults()
247// AC2a (from clarification Q1)
248func (s *SearchUseCaseSuite) TestSearchProducts_OutOfStockProduct_IsAvailableFalse()
249// AC4
250func (s *SearchUseCaseSuite) TestSearchProducts_WithCategoryFilter_Filters()
251// AC5
252func (s *SearchUseCaseSuite) TestSearchProducts_SortOptions_AllValid()
253// AC6
254func (s *SearchUseCaseSuite) TestSearchProducts_NoResults_ReturnsEmptySlice()
255// AC7
256func (s *SearchUseCaseSuite) TestSearchProducts_KeywordTooShort_ValidationError()
257// AC8
258func (s *SearchUseCaseSuite) TestSearchProducts_Pagination_CorrectCalculation()
259```
260
261**Definition of Done:**
262- [ ] All 8 tests pass
263- [ ] Coverage >= 85% for search_usecase.go
264- [ ] `go test -race ./internal/product/usecase/...` passes
265
266---
267
268### Tasks 3.2-3.4: [Additional usecase tests and refinements]
269
270...
271
272---
273
274## Phase 4: HTTP Layer [2.5 hours] 🌐
275
276(Can run in PARALLEL with Phase 3)
277
278### Task 4.1: Create Search Handler [60 min]
279
280**File:** `internal/product/handler/search_handler.go` (CREATE)
281
282**Method signature:**
283```go
284func (h *ProductHandler) SearchProducts(c echo.Context) error
285```
286
287**Logic:**
2881. Parse query params (q, category_id, sort, page, per_page)
2892. Validate (required: q; constraints: per_page max 50)
2903. Convert to usecase.SearchQuery
2914. Call searchUseCase.SearchProducts
2925. Return paginated response or error
293
294**Error mapping (spec AC7):**
295```go
296case *usecase.KeywordTooShortError:
297 return c.JSON(422, ErrorResponse{ErrorCode: "SEARCH_KEYWORD_TOO_SHORT", ...})
298```
299
300**Definition of Done:**
301- [ ] Handler compiles
302- [ ] Manual curl test returns 200 with products
303- [ ] Missing q param returns 422
304
305---
306
307### Task 4.2: Write Handler Tests [60 min]
308
309**File:** `internal/product/handler/search_handler_test.go` (CREATE)
310
311**5 test cases matching plan.md test plan**
312
313**Definition of Done:**
314- [ ] All 5 tests pass
315- [ ] Error codes match spec exactly (SEARCH_KEYWORD_TOO_SHORT, etc.)
316
317---
318
319### Task 4.3: Register Route [15 min]
320
321**File:** `internal/product/handler/router.go` (MODIFY)
322
323```go
324productGroup.GET("/search", handler.SearchProducts,
325 middleware.Auth(),
326 middleware.RateLimitPerUser(60, time.Minute),
327)
328```
329
330**Definition of Done:**
331- [ ] `go build ./...` passes
332- [ ] Route visible in startup log: "GET /api/v1/products/search"
333
334---
335
336## Phase 5: Integration [30 min] 🔌
337
338### Task 5.1: Wire Dependencies [20 min]
339
340**File:** `cmd/server/main.go` (MODIFY)
341
342```go
343searchRepo := product_repo.NewPostgresProductRepository(db) // reuse existing
344searchUC := product_uc.NewSearchUseCase(searchRepo)
345productHandler := product_handler.NewProductHandler(productUC, searchUC)
346```
347
348Dengan dependency ter-wiring, endpoint pencarian siap dipanggil. Langkah berikut menjalankan smoke test cepat untuk memastikan happy path dan error path berperilaku sesuai spesifikasi.
349
350### Task 5.2: Smoke Test [10 min]
351
352Jalankan dua permintaan berikut untuk memverifikasi endpoint secara manual sebelum menandai Definition of Done.
353
354```bash
355# Happy path
356curl "http://localhost:8080/api/v1/products/search?q=laptop&sort=relevance&page=1&per_page=10" \
357 -H "Authorization: Bearer $JWT"
358# Expected: 200 with products
359
360# Validation error
361curl "http://localhost:8080/api/v1/products/search?q=a" \
362 -H "Authorization: Bearer $JWT"
363# Expected: {"error_code":"SEARCH_KEYWORD_TOO_SHORT","message":"..."}
364```
365
366Kedua permintaan di atas mengonfirmasi happy path dan error path berperilaku benar. Checklist berikut merangkum kriteria selesai untuk task ini.
367
368**Definition of Done:**
369- [ ] Happy path returns 200 with paginated products
370- [ ] Validation error returns 422 with correct error_code
371- [ ] Deactivated product not in results (manual verify)
372
373---
374
375## Progress Tracking
376
377| Task | Assignee | Status | Started | Completed |
378|------|----------|--------|---------|-----------|
379| 1.1 Migration | @andi | ⬜ Not Started | | |
380| 1.2 DTOs | @andi | ⬜ Not Started | | |
381| 2.1 Interfaces | @andi | ⬜ Not Started | | |
382| 2.2 Repository | @andi | ⬜ Not Started | | |
383| 2.3 Repo Tests | @andi | ⬜ Not Started | | |
384| 2.4 UseCase | @andi | ⬜ Not Started | | |
385| 3.1 UC Tests | @citra | ⬜ Not Started | | |
386| 4.1 Handler | @citra | ⬜ Not Started | | |
387| 4.2 Handler Tests | @citra | ⬜ Not Started | | |
388| 4.3 Route | @citra | ⬜ Not Started | | |
389| 5.1 Wire | Both | ⬜ Not Started | | |
390| 5.2 Smoke | Both | ⬜ Not Started | | |Dari struktur tasks.md di atas terlihat empat elemen kunci: tabel summary (fase, jumlah task, estimasi, dependency), detail per-task lengkap dengan file dan DoD, tabel progress tracking, serta catatan paralelisasi — semuanya siap dipakai untuk sprint tanpa perencanaan tambahan.
09.3 Fitur Parallelization dalam tasks.md
Spec Kit secara eksplisit menandai task mana yang bisa dikerjakan secara paralel. Blok berikut adalah catatan paralelisasi yang dihasilkan otomatis.
1## Parallelization Notes
2
3After Phase 2 completes (both Task 2.2 and 2.3 done):
4- Developer A can start Phase 3 (UseCase tests)
5- Developer B can start Phase 4 (Handler implementation)
6- Both can work simultaneously without conflict
7
8Merge point: Phase 5 (Integration) requires both Phase 3 and 4 to be complete.Catatan ini bukan tebakan — Spec Kit menghitungnya dari analisis dependency di plan.md, sehingga kamu bisa langsung tahu berapa banyak developer yang bisa bekerja bersamaan tanpa saling menabrak.
09.4 specify tasks Flags
specify tasks menyediakan flag untuk mengatur granularity dan format export. Kumpulan perintah berikut merangkum opsi yang tersedia.
1# Generate tasks dengan granularity lebih kasar (30-120 menit per task)
2specify tasks product-search --granularity=coarse
3
4# Task yang lebih granular (15-45 menit per task)
5specify tasks product-search --granularity=fine
6
7# Regenerate jika plan berubah
8specify tasks product-search --regenerate
9
10# Export ke format Jira-compatible
11specify tasks product-search --export=jira
12
13# Export ke CSV untuk spreadsheet tracking
14specify tasks product-search --export=csvDengan --granularity kamu bisa menyesuaikan ukuran task dengan gaya kerja tim, sementara flag --export memungkinkan integrasi mulus ke Jira atau spreadsheet tanpa entri manual.
09.5 Mengupdate Progress di tasks.md
Progress task perlu di-update saat status berubah. Perintah berikut menandai task sebagai in-progress atau done, atau kamu bisa mengeditnya langsung.
1# Mark task sebagai in progress
2specify tasks product-search --task=2.2 --status=in-progress --assignee=andi
3
4# Mark task sebagai done
5specify tasks product-search --task=2.2 --status=done
6
7# Atau edit langsung
8vim .specify/features/product-search/tasks.md
9# Update [ ] ke [x] di checklist setiap taskSetiap perubahan progress sebaiknya di-commit agar git log menjadi timeline development. Perintah berikut menunjukkan pola commit-nya.
1git add .specify/features/product-search/tasks.md
2git commit -m "chore(product-search): update task progress [tasks 1.1, 1.2, 2.1 done]"Dengan meng-commit setiap update progress, tasks.md berubah menjadi catatan historis yang bisa dipakai saat retrospective untuk melihat kapan tiap task benar-benar selesai.
09.6 Task Duration Distribution
Spec Kit mengikuti target durasi tertentu per task agar breakdown tetap seimbang. Panduan durasi berikut menjadi acuannya.
1Ideal task duration: 30-90 minutes
2Minimum: 15 minutes (too small = too many context switches)
3Maximum: 120 minutes (too large = hard to review)
4
5If a task exceeds 90 minutes, Spec Kit automatically splits it:
6"Implement SearchProducts Repository" (originally 120 min)
7→ Task 2.2a: Implement SearchProducts repository method (60 min)
8→ Task 2.2b: Write repository integration tests (50 min)Aturan durasi ini menjaga setiap task cukup kecil untuk di-review tapi tidak terlalu kecil sampai menimbulkan overhead — dan Spec Kit otomatis memecah task yang melampaui batas 90 menit.
09.7 Definition of Done yang Efektif
Kualitas sebuah task sangat ditentukan oleh DoD-nya. Contoh berikut menunjukkan DoD yang efektif karena setiap item bisa diverifikasi.
1Definition of Done:
2- [ ] File compiles (go build ./...)
3- [ ] Existing tests masih pass (go test ./...)
4- [ ] Specific test passes: TestSearchProducts_ValidKeyword
5- [ ] Manual curl test returns expected response
6- [ ] go vet passes (no warnings)Sebagai perbandingan, DoD berikut kurang efektif karena itemnya terlalu kabur atau bukan tanggung jawab task tersebut.
1Definition of Done:
2- [ ] Implementation complete (terlalu vague)
3- [ ] Code reviewed (bukan DoD task, tapi PR requirement)Perbedaannya jelas: DoD yang baik bisa dicek secara objektif (“test X pass”), sedangkan DoD yang buruk mengundang perdebatan tentang apakah sesuatu sudah “selesai”.
09.8 Task yang Mengcover Multiple AC
Beberapa task sengaja dirancang untuk meng-cover lebih dari satu acceptance criteria. Contoh berikut menunjukkan satu task yang memetakan delapan AC sekaligus ke test.
1### Task 3.1: Write UseCase Tests
2
3Covers:
4- AC1: Customer searches by keyword → TestSearchProducts_ValidKeyword
5- AC2: Deactivated products not shown → TestSearchProducts_DeactivatedProduct
6- AC2a: stock=0 shows badge → TestSearchProducts_OutOfStockProduct
7- AC4: Category filter → TestSearchProducts_WithCategoryFilter
8- AC5: Sort options → TestSearchProducts_SortOptions
9- AC6: No results → TestSearchProducts_NoResults
10- AC7: Keyword validation → TestSearchProducts_KeywordTooShort
11- AC8: Pagination → TestSearchProducts_Pagination
12
13All 8 ACs covered in one 90-minute task.Menggabungkan AC yang berkaitan ke dalam satu task testing seperti ini efisien, asalkan seluruh AC tetap terpetakan eksplisit ke test function-nya masing-masing agar tak ada yang terlewat.
09.9 Menggunakan Tasks untuk Daily Standup
tasks.md sangat cocok dijadikan referensi daily standup. Contoh berikut menunjukkan bagaimana laporan standup mengacu langsung ke nomor task.
1Monday standup:
2"Kemarin: Selesaikan task 1.1 (migration) dan 1.2 (DTOs).
3Hari ini: Task 2.1 (interfaces) dan mulai 2.2 (repository impl).
4Blocker: Belum ada akses ke staging DB untuk verify migration."
5
6→ Progress yang clear, blocker yang specific, tidak perlu elaborasi panjangDengan mengacu ke nomor task, laporan standup menjadi ringkas dan tidak ambigu — semua orang tahu persis pekerjaan mana yang dimaksud tanpa penjelasan panjang.
09.10 Tasks sebagai PR Checklist
Setiap PR bisa mereferensikan task yang sudah di-complete sebagai checklist. Contoh deskripsi PR berikut memisahkan task yang selesai dari yang masih berjalan.
1# PR Description
2
3## Tasks Completed
4- [x] Task 1.1: Database migration
5- [x] Task 1.2: Search DTOs
6- [x] Task 2.1: Interface updates + mock regeneration
7- [x] Task 2.2: Repository implementation
8- [x] Task 2.3: Repository integration tests
9
10## Tasks Remaining (separate PR)
11- [ ] Task 3.x: UseCase tests (in progress by @citra)
12- [ ] Task 4.x: Handler (in progress by @citra)PR checklist berbasis task seperti ini memudahkan reviewer memahami cakupan perubahan dan memastikan tidak ada task yang diklaim selesai padahal belum di-cover kode.
09.11 Task Tracking di Jira
Task di tasks.md bisa di-export menjadi sub-task Jira agar tracking terpusat. Perintah berikut menunjukkan cara export dengan parent ticket.
1# Export tasks ke Jira sebagai sub-tasks
2specify tasks product-search --export=jira --parent=SHOP-123
3
4# Creates Jira sub-tasks:
5# SHOP-123.1: [product-search] Task 1.1: Create Database Migration
6# SHOP-123.2: [product-search] Task 1.2: Add Search DTOs
7# ...Export otomatis ini menyelaraskan breakdown teknis di tasks.md dengan board manajemen proyek, sehingga PM dan engineer melihat sumber kebenaran yang sama.
09.12 Ketika Task Lebih Besar dari Estimasi
Estimasi AI tidak selalu tepat. Contoh berikut menunjukkan bagaimana mencatat selisih antara estimasi dan waktu aktual beserta penyebabnya.
1Task 2.2: Implement SearchProducts Repository
2Estimate: 90 minutes
3Actual: 3 hours
4
5What happened:
61. PostgreSQL 'indonesian' dictionary not installed (30 min to fix)
72. Dynamic ORDER BY with ts_rank needed custom approach (60 min)
83. COUNT query optimization (30 min)
9
10Action:
111. Update tasks.md actual time: "90 min estimated, 180 min actual"
122. Note the reason: "Indonesian dictionary setup + ts_rank integration"
133. This data helps improve future estimatesMencatat selisih estimasi seperti ini mengubah “meleset dari target” menjadi data berharga: alasan yang terdokumentasi akan mempertajam akurasi estimasi di fitur-fitur berikutnya.
09.13 Tasks untuk Rollback Planning
Task tidak hanya soal membangun fitur, tapi juga menyiapkan rollback. Contoh fase opsional berikut menyiapkan SQL rollback dan feature flag.
1## Phase 0 (Optional): Rollback Preparation
2
3### Task 0.1: Verify Rollback SQL [10 min]
4Test that rollback migration works:
5```sql
6DROP INDEX CONCURRENTLY IF EXISTS idx_products_fts;
7-- Verify: no queries should fail after index removal
8```
9
10### Task 0.2: Feature Flag Setup [15 min]
11Add feature flag for search endpoint:
12```go
13if !featureFlag.IsEnabled("product-search") {
14 return c.JSON(404, ErrorResponse{ErrorCode: "FEATURE_NOT_AVAILABLE"})
15}
16```
17Allows instant disable without deployment if issues in production.Menyiapkan rollback sebagai task tersendiri sejak awal memastikan kamu punya jalur keluar yang teruji — SQL rollback maupun feature flag — jika fitur bermasalah di production.
09.14 Paralel Development dengan Tasks
Ketika dua developer bekerja paralel, pembagian task perlu jelas agar tidak konflik. Contoh berikut memetakan task, fokus, dan branch untuk masing-masing developer.
1Dev A (Andi) — Backend Focus:
2Tasks: 1.1, 1.2, 2.1, 2.2, 2.3, 2.4
3Branch: feat/SHOP-123-search-backend
4
5Dev B (Citra) — Testing Focus:
6Tasks: 3.1, 3.2, 4.1, 4.2, 4.3
7Branch: feat/SHOP-123-search-handler
8(starts after Dev A completes Phase 2)
9
10Integration:
11Task 5.1, 5.2 — Pair programming
12Branch: feat/SHOP-123-search-integration
13(merge of A and B)Pembagian berbasis fase dan branch terpisah ini memungkinkan dua developer bekerja bersamaan dengan aman, lalu bertemu di titik integrasi yang sudah ditentukan sejak awal.
09.15 Task Health Check
Spec Kit bisa melaporkan kesehatan progress task secara ringkas. Perintah berikut menampilkan berapa persen task selesai, yang ter-blocked, dan proyeksi penyelesaian.
1# Cek berapa persen tasks sudah done
2specify tasks product-search --health
3
4# Output:
5# Task Health: product-search
6# Done: 4/12 (33%)
7# In Progress: 2/12 (17%)
8# Not Started: 6/12 (50%)
9#
10# Blocked tasks: None
11# Overdue tasks (> 2x estimate): Task 2.2 (180 min actual vs 90 min est.)
12#
13# Projected completion: 2025-07-06 (2 days from now)Laporan health check ini memberi sinyal dini: task yang overdue (seperti 2.2) dan proyeksi tanggal selesai membantu tim menyesuaikan ekspektasi sebelum deadline benar-benar terlewat.
09.16 Ketika Menemukan Task yang Tidak Ada di Plan
Saat implementasi, sering muncul pekerjaan yang tidak terprediksi di plan. Contoh berikut menunjukkan langkah menambahkan task baru dan memperbarui dependency-nya.
1Saat implementasi, @andi menemukan bahwa perlu custom pg_catalog configuration
2untuk Indonesian full-text search yang tidak ada di plan.
3
4Action:
51. Add task to tasks.md:
6 "Task 1.3: Configure Indonesian FTS dictionary [45 min]
7 Install: unaccent + indonesian dictionary in PostgreSQL
8 Required before Task 2.2 can be completed"
9
102. Update phase dependency:
11 Task 2.2 now depends on Task 1.3
12
133. Note in plan.md: "Indonesian FTS configuration needed (discovered during implementation)"
14
154. Update estimate in JiraMenangani pekerjaan tak terduga dengan menambahkannya secara eksplisit ke tasks.md — bukan mengerjakannya diam-diam — menjaga breakdown tetap mencerminkan realitas dan dependency tetap akurat.
09.17 Tasks untuk Monitoring Setup
Fitur yang baik juga butuh observability. Contoh task berikut menambahkan metrics Prometheus ke handler search.
1### Task 4.4: Add Search Metrics [30 min]
2
3**File:** `internal/product/handler/search_handler.go` (MODIFY)
4
5Add Prometheus metrics:
6```go
7var (
8 searchDuration = prometheus.NewHistogramVec(...)
9 searchResults = prometheus.NewCounterVec(...)
10)
11
12func (h *ProductHandler) SearchProducts(c echo.Context) error {
13 start := time.Now()
14 defer func() {
15 searchDuration.WithLabelValues(/* sort, has_category */).
16 Observe(time.Since(start).Seconds())
17 }()
18 // ... existing implementation
19}
20```
21
22**Definition of Done:**
23- [ ] Metrics registered in Prometheus
24- [ ] Grafana dashboard updated (if available locally)
25- [ ] `/metrics` endpoint shows search_duration_seconds histogramMemasukkan setup monitoring sebagai task eksplisit memastikan observability tidak terlupakan — metrics dan dashboard siap sejak fitur dirilis, bukan ditambal setelah insiden terjadi.
09.18 Tips & Gotchas
💡 Tip 1: Update tasks.md secara real-time
Task yang sudah done tapi tidak diupdate di tasks.md membuat progress tracking tidak akurat. Update segera setelah selesai.
💡 Tip 2: Gunakan tasks.md sebagai daily standup reference
Sebelum standup, lihat tasks.md untuk tahu progress kemarin dan rencana hari ini.
💡 Tip 3: Task yang terlalu kecil = overhead tinggi
Task kurang dari 15 menit biasanya better dikombinasikan dengan task berikutnya.
💡 Tip 4: Commit tasks.md setiap perubahan progress
Git log dari tasks.md memberikan timeline yang bagus untuk retrospective.
⚠️ Gotcha 1: Estimate AI tidak memperhitungkan “unknown unknowns”
Selalu tambahkan buffer 20-30% ke total estimate Spec Kit.
⚠️ Gotcha 2: Jangan skip task karena “obvious”
Setiap task punya DoD yang perlu di-check. Bahkan task yang “obvious” bisa punya edge case.
⚠️ Gotcha 3: Regenerate tasks jika plan berubah signifikan
Tasks yang tidak mencerminkan plan terbaru akan menyebabkan implementasi yang salah.
⚠️ Gotcha 4: Paralel tasks butuh coordination yang baik
Developer A dan B yang bekerja paralel harus sync sebelum mulai untuk menghindari conflict.
09.19 Dari Tasks ke Implementasi
Setelah tasks.md di-validate dan progress tracking sudah setup, kamu siap masuk ke tahap eksekusi. Perintah berikut memulai implementasi per fase atau per task.
1# Mulai implementasi task pertama
2specify implement product-search --phase=1
3# atau
4specify implement product-search --task=1.1
5
6# Spec Kit akan:
7# 1. Load context (constitution + spec + plan + tasks)
8# 2. Focus pada task yang diminta
9# 3. Generate kode yang sesuai
10# 4. Mark task sebagai "in progress" di tasks.md
11# 5. Run post_implement hook setelah selesaiPerintah specify implement menutup rantai SDD: ia memuat seluruh context yang sudah dibangun bertahap, lalu fokus mengeksekusi satu task pada satu waktu sambil otomatis memperbarui progress.
09.20 Ringkasan
specify tasks mengubah plan.md menjadi unit kerja yang konkret — setiap task punya durasi 15-90 menit, definition of done yang measurable, dan dependency yang jelas.
Paralelisasi adalah key benefit: Tasks dibuat dengan memperhatikan mana yang bisa dikerjakan secara bersamaan, mengoptimalkan penggunaan sumber daya tim.
Progress tracking built-in: tasks.md adalah living document yang di-update saat development berlangsung, memberikan visibility yang jelas tentang status feature.
Buffer estimate: Selalu tambahkan 20-30% dari total estimate AI untuk “unknown unknowns” yang akan muncul saat implementasi.
Di artikel berikutnya, specify implement — tahap eksekusi terakhir yang menghasilkan kode Go dari setiap task.