Day 2 D2-Lab5 Lab 75 minutes

The translation layer between the spec you wrote and the code you'll generate

Lab 5 — Story Decomposition & Task Generation

The translation layer

A story without acceptance criteria is a wish. A task without a spec reference is a guess. Both produce wrong code in Lab 6.

Surface: Antigravity (Developer agent · Amelia) + editor Artifacts: docs/stories.md + docs/tasks.md The rule: Lab 6 quality is entirely determined by Lab 5 quality.


⚠️ How this maps to BMAD V6

The guide says "switch to the Developer persona and decompose the spec." In BMAD V6 that's the Developer agent (Amelia) running bmad-create-epics-and-stories (trigger CE), with the readiness gate (IR) before code.

What you produce V6 workflow Agent Output
Epics + stories + AC bmad-create-epics-and-stories (CE) Developer (Amelia) epic/story files
Readiness gate bmad-check-implementation-readiness (IR) PM/Dev PASS/CONCERNS/FAIL

We assemble the output into docs/stories.md and docs/tasks.md — the files Lab 6 works through. The content below (4 epics, the 12 tasks) is what you produce; V6 is how.


Phase 1 · Setup + INVEST recap (8 min)

Step 1 — Create the files

🪟  cd $env:USERPROFILE\stacklog-workshop ; New-Item docs\stories.md, docs\tasks.md
🍎🐧 cd ~/stacklog-workshop && touch docs/stories.md docs/tasks.md

Step 2 — Load the Developer agent

Open Antigravity's agent menu → Developer (Amelia). Run CE (bmad-create-epics-and-stories). It decomposes the signed-off spec into epics and stories with acceptance criteria.

The agent's job: every story passes INVEST, has 3–5 testable AC, and every task names a target file, signature, I/O, and spec §ref — ordered so backend comes before the frontend that calls it.


Step 3 — INVEST recap

Validate every generated story against these six:

Means StackLog test
I Independent builds/ships without another story first can we demo it in isolation?
N Negotiable details can still change is this the simplest version?
V Valuable value to a named persona which persona benefits, and how?
E Estimable roughly sizable can we estimate it in hours?
S Small one sprint — ideally one Lab-6 task can one dev do it in ≤60 min?
T Testable verifiable AC can we write a failing test from each AC now?

The most important letter for Lab 6 is S — Small. Test: "Can one agent prompt generate this story's code?" If it'd need multiple prompts, split it.


Phase 2 · Generate epics & stories (37 min)

Step 4 — The four target epics

# Epic Stories Lab 6 task sets Spec §
1 Entry feed display all entries newest-first; pagination A: GET /entries · B: EntryFeed + EntryCard §2, §1
2 Search & filter full-text search; tag filter A: GET /entries/search · B: SearchBar §2, §1
3 Weekly summary group by day for the week; one-click A: GET /entries/week · B: WeeklySummary §2, §1
4 App shell & data Express bootstrap; SQLite + migration; React scaffold A: server.ts + db.ts · B: App.tsx + main.tsx §4, §3

Step 5 — Generate, then review against INVEST

Feed the agent the signed-off spec and generate stories in this structure (per story): a persona-framed statement, the 6-point INVEST check, 3–5 acceptance criteria, and a test stub (what to assert — not full test code).

Weak vs. strong story — the difference is everything:


Step 5 — example story shape (cont.)

Example story to match (paste this shape into docs/stories.md):

## Epic 2 — Search & Filter
### Story 2.1 — Full-text search
As Alex (solo developer) I can type a query into the search bar so that
matching entries appear in the feed within 200ms.

INVEST check:
- I: Yes — SearchBar and GET /entries/search are self-contained
- N: Yes — debounce timing and result count are negotiable
- V: Alex — finds any past insight without scrolling the full feed
- E: ~60 min (30 backend, 30 frontend)
- S: Yes — fits one Lab 6 session
- T: Yes — response time and match accuracy are measurable

Acceptance criteria:
1. GET /entries/search?q={query} returns Entry[] where title, content, OR tags
   contain the query (case-insensitive)
2. Response time < 200ms for up to 1,000 entries
3. SearchBar input debounced 300ms before the API call
4. Empty query returns all entries (identical to GET /entries)
5. Matching is case-insensitive: "React" matches "react" and "REACT"

Test stub:
- Assert: GET /entries/search?q=typescript returns only entries where title,
  content, or tags contain "typescript" (case-insensitive)
- Assert: response time < 200ms for a 1,000-entry store

Story checkpoint: all 4 epics present · ≥10 stories total · every story has a named persona (Alex/Jordan) · 3–5 single-testable-statement AC each · a test stub · none would take >60 min (the S check).


Phase 3 · Generate BMAD dev tasks (23 min)

A task is the unit of code generation — one task ≈ one Lab-6 agent prompt. Vague task → vague prompt → wrong code. Precise task → right code first time.

Step 6 — The BMAD task format (every field required)

## TASK-001
Story:        2.1 (Full-text search)
Target file:  backend/src/routes/entries.ts
Action:       Create and export GET /entries/search route handler
Signature:    searchEntries(req: Request, res: Response): void
Inputs:       req.query.q — string, required. The search query.
Output:       200 + Entry[] (matching, sorted timestamp DESC)
              400 + { error: "q parameter is required" } if q missing
              500 + { error: "Internal server error" } on DB failure
Notes:        SELECT * FROM entries WHERE LOWER(title) LIKE ?
              OR LOWER(content) LIKE ? OR LOWER(tags) LIKE ?
              bind: %${q.toLowerCase()}%
Spec ref:     Tech Spec §2 — GET /entries/search
AC ref:       Story 2.1 AC #1, #2

Step 7 — The 12 mandatory tasks

Every student must have at least these. Check generated tasks cover all 12; add any missing by hand:

ID Target file What to build Set §ref
TASK-001 backend/src/db.ts SQLite connection + entries table auto-migration A §3
TASK-002 backend/src/server.ts Express bootstrap, CORS, JSON middleware, port 3001 A §4
TASK-003 backend/src/routes/entries.ts GET /entries — all entries, timestamp DESC A §2
TASK-004 backend/src/routes/entries.ts GET /entries/search — full-text across title/content/tags A §2
TASK-005 backend/src/routes/entries.ts GET /entries/week — 7-day date-range filter A §2
TASK-006 frontend/src/App.tsx Root — fetch entries, pass to EntryFeed + SearchBar B §1
TASK-007 frontend/src/components/EntryFeed.tsx List of EntryCards; props entries[], isLoading B §1
TASK-008 frontend/src/components/EntryCard.tsx One entry — title, timestamp, preview, TagBadge list B §1
TASK-009 frontend/src/components/TagBadge.tsx Clickable tag chip; props tag, onClick B §1
TASK-010 frontend/src/components/SearchBar.tsx Controlled input, 300ms debounce, calls onSearch B §1
TASK-011 frontend/src/components/WeeklySummary.tsx Group entries by day for the week B §1
TASK-012 frontend/ (Vite config) Vite + React scaffold; proxy /api → :3001; Tailwind B §4

Step 7 — task notes (cont.)

Each task should be completable in 10–15 min with the codegen agent in Lab 6. If one describes more than a single function/component, split it (EntryFeed and EntryCard are separate tasks).

🔗 Reconcile with the data bridge: TASK-001 (db.ts) should also handle the one-time seed from the Day-1 stacklog-entries.json into SQLite, so yesterday's entries display. Add it as an explicit step in that task (or a TASK-001b).


Phase 4 · Backlog hygiene (5 min)

Step 5 — Order by dependency, flag questions

Dependency order for Lab 6:

  1. TASK-001 (db.ts) — first; all routes depend on it (and seeds Day-1 data).
  2. TASK-002 (server.ts) — second; mounts routes.
  3. TASK-003/004/005 (routes) — any order, all before frontend.
  4. TASK-012 (Vite scaffold) — before any frontend component.
  5. TASK-006 (App.tsx) — before child components.
  6. TASK-007–011 (components) — any order once App exists.

Flag unclear decisions inline (they'd be GitHub Issues in a real project):

<!-- OPEN QUESTION: WeeklySummary — client-side date grouping, or rely on
     GET /entries/week? Decide before TASK-011. -->

Phase 5 · Commit (2 min)

Step 6 — Commit stories + tasks

🪟  cd $env:USERPROFILE\stacklog-workshop
🍎🐧 cd ~/stacklog-workshop
git add docs/stories.md docs/tasks.md
git commit -m "lab5: stories and tasks for all 4 epics"
git push origin main

Lab 5 complete when both files are on GitHub.


Troubleshooting (top 6)

  1. Stories have no AC → re-load the Developer agent; instruct: "You MUST include 3–5 acceptance criteria per story, each a single testable statement. Don't proceed without them."
  2. Tasks too large (most common, breaks Lab 6) → if a task names more than one function/component, split it. EntryFeed ≠ EntryCard.
  3. <10 stories → spec too thin; prompt for edge cases: empty feed, no-results search, loading states.
  4. INVEST E fails (can't estimate) → ask "what would you need to know to estimate this?" — the answer is what's missing from the task.
  5. Path style → V6/most agents emit forward slashes (backend/src/...); that's what Lab 6 uses cross-platform. (Original Windows guide used backslashes.)
  6. Git auth fails → use the editor's Source Control panel → Sync; it handles browser auth.

Bridge to Lab 6

In Lab 6 you open each task, hand it to the codegen agent with the relevant spec section, and generate the code — backend before frontend. docs/tasks.md is your agenda. docs/spec.md is the agent's context.

Before Lab 6: keep docs/tasks.md and docs/spec.md open; confirm your codegen agent (Antigravity / Copilot) is ready.