Lab 4 — StackLog Spec Writing Sprint

75 minutes to a signed-off spec

Everything the AI generates in Labs 5 and 6 flows from what you write here.
A weak spec produces weak code. A precise spec produces precise code.

Surface: Antigravity (PM + Architect agents) + your editor
Artifacts: BMAD V6 outputs (prd.md, architecture.md) + an assembled docs/spec.md
The sign-off bar: "Could a stranger build this from the spec alone — without asking any questions?"

⚠️ How this maps to BMAD V6

The facilitator guide describes "write a PRD, then a Tech Spec" with an Architect persona. In BMAD V6 that's two workflows run by two agents:

What you're writing V6 workflow Agent Output
Project rules (constitution) project-context.md project-context.md
PRD (the what & why) bmad-prd (trigger PRD) PM (John) prd.md
Technical Spec (the how) bmad-create-architecture (trigger CA) Architect (Winston) architecture.md

The content below (StackLog's goals, features, schema, endpoints) is what you produce.
The method is V6 workflows. We'll also assemble everything into one docs/spec.md as the committed source of truth the later labs reference.

Phase 1 · Setup (7 min)

Step 1 — Confirm BMAD is installed

From your workshop folder (you cloned BMAD last night):

🪟  cd $env:USERPROFILE\stacklog-workshop
🍎🐧 cd ~/stacklog-workshop

Verify the BMAD agents are available in Antigravity (the bmad-help skill, or the agent menu). If not installed, run the BMAD installer now — or use the fallback templates in docs/bmad/.

⚠️ Check current UI: how skills/agents surface varies by Antigravity build. bmad-help is the interactive guide if you're unsure of the next step.

Step 2 — Set the constitution (project-context.md)

Before any feature, capture StackLog's non-negotiable rules. Create project-context.md (or run bmad-generate-project-context):

# StackLog — Project Context (Constitution)

## Stack
- Frontend: React + Vite (TypeScript)
- Backend: Express (TypeScript)
- DB: SQLite via better-sqlite3
- Day-1 data source: stacklog-entries.json (MCP store)

## Principles
- Local-first: no external services, no auth, single user.
- Read-only web app in v1 — entries are created by the MCP server, not the UI.
- Every feature must have a measurable success criterion.
- Markdown input only — no rich-text editor.
- Nothing may exceed PRD scope; out-of-scope list is binding.

This is the constitution from Session 10 — it outranks everything and guides every later workflow.

Step 3 — Open the PM agent

Open Antigravity's agent menu, select the Product Manager (John) agent, and run the PRD trigger (the bmad-prd workflow). It will guide you through PRD discovery interactively.

💡 If you prefer manual control, you can still write docs/spec.md by hand using the section guides below — the V6 workflow just facilitates it.

Phase 2 · Write the PRD (33 min)

The PRD answers: what does StackLog do, for whom, and how do we know it's done?
(The Tech Spec answers how it works — don't mix them.)

Run bmad-prd and work through these five sections. The PM agent challenges assumptions and demands a measurable success criterion for everything.

🎯 Goals

A 3–5 sentence statement: problem, solution, success.

  • Problem: "Developers lose insights created during coding sessions — there's no frictionless way to capture them."
  • Solution: "StackLog provides an AI-powered capture layer (the MCP server) and a browsable web interface."
  • Success: "A developer can retrieve any past insight in under 10 seconds via search or tags."

⚠️ Watch for goals written as feature lists. "Has search, tags, a feed" is not a goal — push back: why does a developer need these?

👤 User Personas

2–3 personas, each with a name, role, frustration, and measurable success state.

  • Alex — solo dev, uses StackLog daily to log research/debugging insights; frustrated by losing context between sessions. Success: finds any past insight in under 10s.
  • Jordan — team lead, uses it weekly to review team activity; frustrated by lack of visibility. Success: weekly summary surfaces patterns without manual review.

⚡ Key Features

4–6 MVP features, each with a name, one-line description, and a success metric:

  • Entry creation via MCP — agent creates entries via create_entry (Day 1). Success: entries appear in the feed within 1s.
  • Entry feed — paginated, newest first. Success: loads < 500ms for up to 1,000 entries.
  • Tag filtering — click a tag to filter. Success: applies instantly (client-side).
  • Full-text search — queries title, content, tags. Success: results < 200ms.
  • Weekly summary — entries grouped by day for the week. Success: one click from the feed.

⚠️ "Full-text search" isn't a feature. "Full-text search returns results in under 200ms" is.

🚫 Out-of-Scope (as important as the feature list)

  • Multi-user accounts · Authentication/login · Cloud sync/remote storage
  • Mobile app · Real-time collaboration · Rich-text/WYSIWYG editor
  • Entry editing or deletion (read + create only in v1)

Every item here is a decision that prevents scope creep in Labs 5–6. The codegen agent will try to add auth. This list is your defence.

📏 Success Metrics (project-level, testable in <5 min at the showcase)

  • All Day-1 entries in stacklog-entries.json display correctly in the web app.
  • create_entry from the agent → entry visible in the browser in under 2s.
  • Search returns correct results across title, content, and tags.
  • The app runs with a single start command.
  • Generated code passes the Reviewer check — no spec section violated.

PRD sign-off: Goals have problem+solution+success? Both personas have a measurable success? Every feature has a metric? "multi-user" and "auth" on the out-of-scope list? Every metric testable in <5 min?
The question: Could a stranger build the right product from this PRD — no questions asked?

Phase 3 · Write the Technical Spec (20 min)

The bridge between what (PRD) and how the agent should build it. Every section is a constraint on code generation. Vague → inconsistent code. Precise → predictable code.

Switch to the Architect (Winston) agent, run CA (bmad-create-architecture). Tell it: "Refer to the PRD — nothing may exceed its scope. Ask clarifying questions on any ambiguous technical decision." Produce these five sections.

1 · React component tree

App
├── Layout (Header: title+nav · Footer)
├── EntryFeed (props: entries[], isLoading)
│   └── EntryCard[] (props: entry)
│       └── TagBadge[] (props: tag string)
├── SearchBar (props: onSearch callback)
└── WeeklySummary (props: entries[], weekStart date)

Tells the agent what to build and each component's props. Without it, the agent invents a structure.

2 · Express REST endpoints

Base: http://localhost:3001/api

GET /entries            ?tag=string (optional)
                        → Entry[] sorted by timestamp DESC   · 200 | 500
GET /entries/search     ?q=string (required)
                        → Entry[] matching title/content/tags (case-insensitive)
                        · 200 | 400 (missing q) | 500
GET /entries/week       ?start=YYYY-MM-DD (default: Monday this week)
                        → Entry[] for the 7-day period        · 200 | 500

⚠️ No POST in v1 — entries are created by the MCP server, not the web app. The app is read-only. If someone adds POST /entries "just in case," point at the out-of-scope list.

3 · SQLite schema

Database: stacklog.db (project root) — migrate on startup if absent

Table: entries
  id        TEXT  PRIMARY KEY    -- UUID from randomUUID()
  title     TEXT  NOT NULL       -- max 80 chars
  content   TEXT  NOT NULL       -- markdown
  tags      TEXT  DEFAULT ''     -- comma-separated lowercase
  timestamp TEXT  NOT NULL       -- ISO 8601

Index: entries_timestamp_idx ON entries(timestamp DESC)
Index: entries_tags_idx       ON entries(tags)

🔗 The bridge: Day-1 writes JSON (stacklog-entries.json); Day-2 reads SQLite (stacklog.db). Note a one-time seed/migration: on first run, import the Day-1 JSON entries into SQLite so yesterday's entries display today. (This is the deliberate JSON→SQLite bridge from the StackLog definition.)

4 · File structure

stacklog-workshop/
├── stacklog-mcp/        (Day 1 — MCP server)
│   └── src/index.ts
├── frontend/            (Lab 6 — React)
│   └── src/components/{EntryFeed,EntryCard,SearchBar,TagBadge,WeeklySummary}.tsx
├── backend/             (Lab 6 — Express)
│   └── src/{routes/entries.ts, db.ts, server.ts}
├── docs/
│   ├── spec.md          (this file — source of truth)
│   ├── stories.md       (Lab 5)
│   └── tasks.md         (Lab 5)
└── README.md

5 · Non-functional requirements

Performance:  GET /entries < 500ms (≤1,000 entries) · /search < 200ms · initial load < 2s
Data:         local only · SQLite via better-sqlite3 · DB auto-migrated on startup
              MCP JSON store: ~/stacklog-entries.json (Win: %USERPROFILE%\stacklog-entries.json)
Compat:       Node 18+ · Chrome/Edge latest
Ports:        frontend (Vite) :3000 · backend API :3001

Tech Spec sign-off: every feature has a supporting endpoint? Every schema field has type+constraint+comment? Frontend/backend separate? Response targets testable? Ports specified?
The question: Could a developer implement this without asking a single question?

Phase 4 · Peer review (12 min)

Not about being nice — about finding gaps that cost you time in Lab 6. Every ambiguity surfaced now saves ~10 min of confused code generation later.

Step 4 — Swap specs, run an Architect review

Swap docs/spec.md with a neighbour (push to GitHub and share the link, or paste into a shared doc). Load the Architect agent and review the other team's spec:

Review this StackLog spec as a critical senior engineer. For each section
(Goals, Personas, Features, Out-of-scope, Success Metrics, Component Tree,
Endpoints, Schema, File Structure, NFRs), identify:
1. Any requirement that is ambiguous or unmeasurable
2. Any missing constraint that would force a developer to guess
3. Any inconsistency between the PRD and Technical Spec
4. Any out-of-scope feature that snuck into the spec
Format as a numbered list. For each: quote the line, name the problem, suggest a fix.

Common findings: features without metrics; components without prop types; endpoints without status codes; schema fields without constraints.

Step 5 — Incorporate feedback (5 min)

Update your own spec from the review. Share: "What was the most valuable finding?"

Phase 5 · Commit (3 min)

Step 6 — Assemble and commit docs/spec.md

Consolidate the V6 outputs (prd.md + architecture.md) into a single docs/spec.md (PRD on top, Tech Spec below, ## headings separating them), then:

🪟  cd $env:USERPROFILE\stacklog-workshop
🍎🐧 cd ~/stacklog-workshop
git add docs/spec.md project-context.md
git commit -m "lab4: StackLog PRD and Technical Spec signed off"
git push origin main

Lab 4 complete when docs/spec.md is on GitHub.
This file is now the single source of truth. Every story, task, and line of code in Labs 5–6 must reference a section of it. Don't change the spec without updating the section.

Troubleshooting (top 5)

  1. The agent just agrees with everything → the PM/Architect agent isn't really loaded, or your constitution is too soft. Re-invoke the agent; test with "I want to add real-time collaboration" — it should push back via the out-of-scope rule.
  2. Writing code in the spec → the most common error. Ask: requirement or implementation? "Use useState for search" is implementation; "search updates as the user types, 300ms debounce" is a requirement. Spec holds only requirements.
  3. Spec too short (bullets, no constraints) → ask: can the agent generate the correct endpoint response format from this? If no, add detail. For each section: "what's missing that would force a developer to guess?"
  4. Git push auth fails → use Antigravity/your editor's built-in Git auth (Source Control panel → Publish/Sync) to handle the browser auth flow.
  5. JSON vs SQLite confusion → Day-1 store is JSON, Day-2 app is SQLite by design. The spec's schema is SQLite; note the one-time seed from the Day-1 JSON so existing entries appear.

Bridge to Lab 5

The spec is signed off. Next you feed it to the Developer (Amelia) agent and generate user stories with acceptance criteria — the stories that drive every line of code in Lab 6. The spec is the input. Keep it open.

Before Lab 5: keep docs/spec.md open; Lab 5 starts the Developer agent (bmad-create-epics-and-stories); confirm GitHub is up to date.