⌂ Home Gemini CLI Mastery — AI SDLC Track
Track 3 — AI SDLC
📚 Module 6 of 18 ⏰ 45 min
M05 — Requirements & Planning

Build the Right Thing First

Most bugs start in the requirements phase, not the code. Use Gemini CLI to analyze TaskFlow, write a Product Requirements Document for a new Recurring Tasks feature, and produce a machine-readable spec before a single line of code is written.

  • Generate a complete PRD by feeding TaskFlow's GEMINI.md to Gemini CLI
  • Decompose the PRD into INVEST-scored user stories
  • Run a gap analysis against TaskFlow's existing models.py and routers/tasks.py
  • Critique an existing requirements document for edge cases and ambiguities
  • Output a JSON spec that M06 (design) and M07 (implementation) will consume

The Requirements Problem

Before we write our first Gemini CLI command, let's be honest about why requirements go wrong — because that's exactly what Gemini CLI is about to fix.

Analogy — The Blueprint Problem

BEFORE: Imagine hiring a contractor to build you a kitchen. You say "I want more storage." They start work immediately — tearing out cabinets and framing new ones.
PAIN: Two weeks in, you realize you meant a pantry in the corner, not floor-to-ceiling cabinets on every wall. The work is half done. Tearing it out costs more than doing it right the first time.
MAPPING: Software requirements are the blueprint. Without one, every developer builds their mental model of "what was meant." Gemini CLI lets you cross-examine that blueprint before concrete gets poured.

TaskFlow right now has basic task CRUD: create a task, read it, update it, delete it. The product manager says "we need Recurring Tasks — tasks that auto-recreate on a schedule." Sounds simple. But consider what's actually unspecified:

  • Does the schedule run server-side or does the client call an endpoint?
  • What schedule format — cron expressions, human-readable intervals, or fixed days?
  • Does a completed recurring task auto-reset, or spawn a new task?
  • What happens if the server is down during a scheduled spawn?
  • Does the recurrence belong to the task, or is it a separate entity?

A developer who jumps straight to models.py will answer every one of these questions silently — with assumptions. Gemini CLI makes those assumptions visible and questionable before they become database schemas.

Why It Matters

IBM's Systems Sciences Institute found defects cost 100x more to fix in production than in requirements. A 30-minute Gemini CLI requirements session can prevent a 3-day implementation reversal. On a 4-person team shipping weekly, that's 12% of a sprint saved per feature.

Requirements Generation Flow — TaskFlow Recurring Tasks
01
Feed Context
Load GEMINI.md so Gemini understands the existing system
gemini "@GEMINI.md ..."
02
Generate PRD
Full Product Requirements Document with acceptance criteria
→ spec/recurring-tasks-prd.md
03
Decompose to Stories
INVEST-scored user stories from the PRD
→ 6 actionable stories with acceptance criteria
04
Gap Analysis
Compare feature needs to models.py + routers/tasks.py
gemini "@models.py @routers/tasks.py ..."
05
Output JSON Spec
Machine-readable spec consumed by design and implementation
→ spec/recurring-tasks.json

PRD Generation

A PRDProduct Requirements Document — the canonical written description of a feature: what it does, who it serves, what success looks like, and what is explicitly out of scope. answers the question "what are we building and why?" before the team debates "how." Let's generate one for Recurring Tasks by feeding Gemini CLI TaskFlow's existing context document.

The Prompt

TaskFlow ships with GEMINI.md — a project context file that tells Gemini what every file does. Use @GEMINI.md to load it automatically:

PowerShell / Terminal — run from sample-project/taskflow/
gemini "@GEMINI.md Write a Product Requirements Document for a Recurring Tasks feature.

The feature: tasks that auto-recreate on a schedule after they are completed.

Include:
1. Problem Statement
2. Goals and Non-Goals
3. User Personas (who needs this?)
4. Functional Requirements (numbered, testable)
5. Acceptance Criteria for each requirement
6. Out of Scope items
7. Open Questions

Be specific to TaskFlow's existing data model. Reference actual fields
from models.py where relevant."
WHAT: The @GEMINI.md prefix tells Gemini CLI to read the file and inject its contents into the prompt. Gemini sees the entire project context before generating anything.
WHY: Without context, Gemini would generate a generic PRD. With GEMINI.md it knows Task has owner_id, priority, and due_date — and can write requirements that reference real fields.
GOTCHA: Run this command from the sample-project/taskflow/ directory so relative file paths resolve correctly.

Realistic Output

Gemini will produce a structured markdown document. Here's what a representative output looks like — annotated section by section:

Gemini CLI Output — PRD (abbreviated)
# Product Requirements Document: Recurring Tasks

## Problem Statement
TaskFlow users currently manage repetitive obligations (weekly team reports,
monthly expense submissions, daily standup notes) by manually recreating
identical tasks after completion. This creates cognitive overhead and risks
tasks being forgotten.

## Goals
- Users can mark any Task as recurring with a defined schedule
- When a recurring task is completed, a new instance auto-spawns
- Users can pause, modify, or delete a recurrence without losing task history

## Non-Goals (Out of Scope v1)
- Email/push notifications when a recurrence triggers
- Sharing recurrences across users
- Calendar integration

## Functional Requirements
FR-1: A user SHALL be able to set a recurrence on any existing task via
      POST /tasks/{id}/recurrence
FR-2: The recurrence SHALL support three schedule types:
      daily, weekly (specific days), monthly (specific date)
FR-3: When a task with active recurrence is marked completed, the system
      SHALL automatically create a new task with identical fields within
      60 seconds
FR-4: A user SHALL be able to retrieve the recurrence settings for a task
      via GET /tasks/{id}/recurrence
FR-5: A user SHALL be able to delete a recurrence, which stops future
      auto-spawn but does not affect existing tasks

## Acceptance Criteria
FR-1 AC: POST /tasks/42/recurrence with {"schedule_type": "daily"} returns
         201 with the recurrence object; GET /tasks/42 shows has_recurrence: true
FR-3 AC: Mark task 42 completed at T=0; by T=60s a new task exists with
         the same title, description, priority, and owner_id

## Open Questions
- OQ-1: Who triggers the spawn — a background scheduler or an endpoint call?
- OQ-2: What timezone does "daily" mean? User's timezone or UTC?
- OQ-3: Should the spawned task inherit the original task's tags?
WHAT: Gemini produced numbered, testable requirements (FR-1 through FR-5) — not vague statements like "users should be able to recur tasks."
WHY THIS MATTERS: FR-3 is specific: "within 60 seconds." That SLA becomes a test assertion. Without it, "auto-spawn" means different things to every developer.
NOTICE: The Open Questions section surfaces the three decisions that would have been made silently in code. Answer OQ-1 before design begins — it determines whether you need a background scheduler or a webhook.
Anatomy of a Good PRD — Each Section's Purpose
Problem Statement
Why this feature, not just what. Prevents building a solution to the wrong problem.
Non-Goals
What is explicitly excluded. Prevents scope creep during implementation.
Functional Requirements
Numbered, testable "SHALL" statements. Each one maps to a test case.
Acceptance Criteria
Exact pass/fail conditions. If you can't write this, the requirement is ambiguous.
Open Questions
Decisions not yet made. Force these to be answered before code starts.
Out of Scope
v1 boundaries. Prevents "while we're in there" feature expansion.
Tip — Save the PRD

Pipe Gemini's output directly to a file: gemini "@GEMINI.md Write a PRD..." > spec/recurring-tasks-prd.md. Commit it to git. When a developer asks "why did we build it this way?" the answer is in version control.

User Story Decomposition

A PRD describes the feature. User storiesSmall, user-centered requirements written as: "As a [persona], I want [goal] so that [benefit]." They are the unit of work in agile development — each story should be shippable independently. break it into shippable units of work. The INVEST criteriaA quality checklist for user stories: Independent (can be built without other stories), Negotiable (scope can be discussed), Valuable (delivers user benefit), Estimable (team can size it), Small (fits in one sprint), Testable (can be verified). ensure each story is actually ready to develop — not a vague paragraph that balloons in scope.

Decompose the PRD

PowerShell / Terminal
gemini "@GEMINI.md @spec/recurring-tasks-prd.md
Convert the Recurring Tasks PRD into 5-8 user stories.
For each story:
- Write it in 'As a [user] I want [goal] so that [benefit]' format
- Score it on the INVEST criteria (I/N/V/E/S/T — each: Pass/Partial/Fail)
- List 3 acceptance criteria
- Estimate story points (1/2/3/5/8)
- Flag any dependencies on other stories"
WHAT: We feed both GEMINI.md and the PRD we just generated. Gemini reads the existing codebase context AND the new requirements simultaneously.
WHY: Without GEMINI.md, Gemini wouldn't know that "create a recurrence" requires auth (all /tasks/ routes use get_current_user) — and might omit the auth story entirely.

Sample Output

Gemini Output — User Stories
## Story 1 — Set a Recurrence
As a TaskFlow user, I want to attach a recurring schedule to any of my tasks
so that I don't have to manually recreate repetitive tasks.

INVEST: I=Pass, N=Pass, V=Pass, E=Pass, S=Pass, T=Pass

Acceptance Criteria:
  AC1: POST /tasks/{id}/recurrence with valid schedule returns 201
  AC2: GET /tasks/{id} returns has_recurrence: true
  AC3: POST to a non-existent task_id returns 404

Story Points: 3
Dependencies: None (builds on existing Task CRUD)

---
## Story 2 — View Recurrence Settings
As a user, I want to retrieve the recurrence settings for a task
so that I can verify what schedule is active.

INVEST: I=Pass, N=Pass, V=Pass, E=Pass, S=Pass, T=Pass

Acceptance Criteria:
  AC1: GET /tasks/{id}/recurrence returns recurrence object for recurring task
  AC2: GET /tasks/{id}/recurrence returns 404 for non-recurring task
  AC3: Only the task owner can view recurrence settings (401 otherwise)

Story Points: 1
Dependencies: Story 1

---
## Story 3 — Auto-Spawn on Completion
As a user, I want a new task to be automatically created when I complete
a recurring task so that the next instance appears without manual work.

INVEST: I=Partial (depends on scheduler), N=Pass, V=Pass, E=Partial, S=Fail, T=Pass

Story Points: 8
Dependencies: Stories 1, 2, and background scheduler (OQ-1 must be resolved)
NOTE: S=Fail — this story is too large. Split into 3a (spawn logic) and
      3b (background scheduler integration)
WHAT JUST HAPPENED: Gemini flagged Story 3 as S=Fail (too large) and told you to split it. This is the value: Gemini caught a scoping problem before planning poker.
NOTICE: Story 3 depends on resolving Open Question OQ-1 (who triggers the spawn). The PRD open question became a story dependency. Fix the dependency before sprint planning, not during implementation.
INVEST Criteria — What Each Letter Catches
I
Independent
Can be shipped without blocking other stories
N
Negotiable
Scope can flex — not a rigid contract
V
Valuable
Delivers benefit to a real user
E
Estimable
Team can size it confidently
S
Small
Fits in one sprint (≤ 5 points)
T
Testable
Has verifiable acceptance criteria

Gap Analysis

The PRD says what we need. The gap analysis compares that to what we have. Load TaskFlow's actual source files to get a specific, actionable list of what needs to change.

PowerShell / Terminal — from sample-project/taskflow/
gemini "@models.py @schemas.py @routers/tasks.py
Identify gaps between the current TaskFlow implementation and the
Recurring Tasks feature described here:

Feature: Tasks that auto-recreate on a schedule when completed.
- New endpoint: POST /tasks/{id}/recurrence
- New endpoint: GET /tasks/{id}/recurrence
- New endpoint: DELETE /tasks/{id}/recurrence
- Background spawn: when Task.completed = True, create new Task

For each gap:
1. Which file needs to change
2. What specifically needs to be added or modified
3. Risk level (Low/Medium/High) and reason"
WHAT: We load three files simultaneously: @models.py, @schemas.py, and @routers/tasks.py. Gemini reads all three before answering.
WHY: A gap analysis without the actual code produces generic advice. With the actual code, Gemini spots that Task.completed is a plain Boolean field — there's no hook or event system to detect completion changes, so a background scheduler is mandatory.

Gap Analysis Output

Gemini Output — Gap Analysis
## Gap Analysis: TaskFlow → Recurring Tasks Feature

### models.py
GAP-1: No RecurringTask model exists
  - Add: class RecurringTask(Base) with fields:
    task_id (FK → tasks.id), schedule_type (str), interval_value (int),
    next_run_at (DateTime), is_active (bool), created_at (DateTime)
  - Also add: Task.recurrence = relationship("RecurringTask", ..., uselist=False)
  Risk: Medium — requires Alembic migration; existing rows unaffected

GAP-2: Task model has no completion event/hook
  - Task.completed is a plain Boolean; there is no SQLAlchemy event listener
  - A scheduler polling Task.completed changes is required
  Risk: High — architectural decision (polling vs. event sourcing)

### schemas.py
GAP-3: No RecurringTaskCreate, RecurringTask response schemas
  - Add: RecurringTaskCreate(schedule_type, interval_value)
  - Add: RecurringTask(id, task_id, schedule_type, next_run_at, is_active)
  - Pattern to follow: existing Tag / TagCreate pair (lines 7-16)
  Risk: Low

### routers/tasks.py
GAP-4: No recurrence endpoints in tasks router
  - Add: POST /tasks/{id}/recurrence
  - Add: GET /tasks/{id}/recurrence
  - Add: DELETE /tasks/{id}/recurrence
  - Pattern: follow existing get_task() / update_task() auth pattern
  Risk: Low

### NEW FILE REQUIRED
GAP-5: No background scheduler exists
  - Need: APScheduler or similar; polls for tasks where
    completed=True AND recurrence.is_active=True AND next_run_at <= now()
  - Or: use FastAPI startup event to launch scheduler thread
  Risk: High — requires new dependency; impacts app startup
WHAT JUST HAPPENED: Gemini read the actual models.py and noticed that Task.completed is just a Boolean column — there's no trigger or event. This is a real architectural decision you need to make before writing a single line of implementation code.
GAP-2 is the big one: it tells you that auto-spawn requires either a poller or an event hook. That decision belongs in the design phase (M06), not discovered mid-implementation.
What Just Happened?

You ran three Gemini CLI commands and produced: a complete PRD, 6 user stories with INVEST scores, and 5 specific gaps with risk ratings. A junior developer starting fresh would spend 2-3 hours researching the codebase to produce equivalent output. This took under 5 minutes — and the output is grounded in the actual source files, not assumptions.

Feeding Existing Docs

Not every project starts from scratch. More often, you inherit an existing requirements doc that was written without AI assistance — and it has gaps. Here's how to use Gemini CLI to critique documents you already have.

Critique an Existing Spec

PowerShell / Terminal
# Assume you have a spec file at docs/recurring-tasks-spec.md
gemini "@GEMINI.md @docs/recurring-tasks-spec.md
Review this requirements document as a senior engineer.
Identify:
1. Ambiguous requirements (could be interpreted multiple ways)
2. Missing edge cases (what happens when X fails?)
3. Untestable requirements (no pass/fail criteria)
4. Contradictions with the existing codebase
5. Security concerns (auth, data isolation, rate limits)

For each issue, quote the relevant line and suggest a fix."
WHY THIS WORKS: The @GEMINI.md context gives Gemini knowledge of TaskFlow's auth model. It can then flag "the spec doesn't mention auth on the recurrence endpoint" because it knows all /tasks/ routes require get_current_user.
GOTCHA: Gemini will sometimes flag things that are intentionally simple for v1. Read each issue and decide — don't treat every flag as a required change.

Find Edge Cases

PowerShell / Terminal — Targeted Edge Case Hunt
gemini "@GEMINI.md @spec/recurring-tasks-prd.md
List every edge case that is NOT addressed in this PRD.
Focus on:
- What happens when the task is deleted while a recurrence is active?
- What happens when next_run_at is in the past (server was down)?
- What if a user sets daily recurrence on a task with a past due_date?
- What if the spawned task should inherit tags — but a tag was deleted?

For each edge case: state the scenario, the expected behavior, and
whether it needs a new requirement or just a code comment."
WHY: These edge cases involve TaskFlow's many-to-many tag relationship (the task_tags join table in models.py). Gemini knows about it from GEMINI.md. A generic AI without context would never surface "what if the inherited tag was deleted?"
Warning — Garbage In, Garbage Out

The quality of Gemini's analysis depends entirely on the quality of context you provide. If your GEMINI.md is out of date or missing key files, Gemini will make assumptions. Keep GEMINI.md current — it's the single source of truth for AI-assisted development on this project.

Machine-Readable Specs

Markdown PRDs are readable by humans. But the real power of Gemini CLI comes when you output a structured JSON specA machine-readable version of your requirements. JSON can be parsed by scripts, fed back into future Gemini prompts, or used as input to code generation commands in M07. that downstream modules (design in M06, implementation in M07) can consume directly.

Generate the JSON Spec

PowerShell / Terminal
gemini "@GEMINI.md @spec/recurring-tasks-prd.md
Output the Recurring Tasks feature spec as valid JSON only.
No markdown, no explanation — just the JSON object.

Use this structure:
{
  'feature': string,
  'version': '1.0',
  'user_stories': [{ 'id': string, 'story': string, 'points': number, 'acceptance_criteria': string[] }],
  'new_models': [{ 'name': string, 'fields': object, 'relationships': string[] }],
  'new_endpoints': [{ 'method': string, 'path': string, 'auth': boolean, 'request_body': object, 'response': object }],
  'acceptance_criteria': string[],
  'out_of_scope': string[],
  'open_questions': string[]
}" > spec/recurring-tasks.json
WHAT: The > spec/recurring-tasks.json redirect saves Gemini's JSON output directly to a file. This file is your contract between requirements, design, and implementation.
WHY JSON: In M07, you'll run gemini "@spec/recurring-tasks.json @models.py Implement the RecurringTask model..." — Gemini reads the spec you generated here and produces code that matches it exactly.
GOTCHA: Gemini sometimes adds markdown code fences around JSON output. Add "No markdown, no explanation — just the JSON object" to suppress them.

Sample JSON Output

spec/recurring-tasks.json
{
  "feature": "Recurring Tasks",
  "version": "1.0",
  "user_stories": [
    {
      "id": "US-1",
      "story": "As a user I want to set a recurring schedule on a task so that it auto-recreates on completion",
      "points": 3,
      "acceptance_criteria": [
        "POST /tasks/{id}/recurrence returns 201 with recurrence object",
        "GET /tasks/{id} shows has_recurrence: true",
        "POST to non-existent task returns 404"
      ]
    }
  ],
  "new_models": [
    {
      "name": "RecurringTask",
      "fields": {
        "id": "Integer PK",
        "task_id": "Integer FK tasks.id UNIQUE",
        "schedule_type": "String (daily|weekly|monthly)",
        "interval_value": "Integer nullable",
        "next_run_at": "DateTime timezone=True",
        "is_active": "Boolean default=True",
        "created_at": "DateTime server_default=func.now()"
      },
      "relationships": ["Task.recurrence backref via task_id"]
    }
  ],
  "new_endpoints": [
    {
      "method": "POST",
      "path": "/tasks/{task_id}/recurrence",
      "auth": true,
      "request_body": { "schedule_type": "string", "interval_value": "int?" },
      "response": { "status": 201, "body": "RecurringTask schema" }
    },
    {
      "method": "GET",
      "path": "/tasks/{task_id}/recurrence",
      "auth": true,
      "request_body": null,
      "response": { "status": 200, "body": "RecurringTask schema" }
    },
    {
      "method": "DELETE",
      "path": "/tasks/{task_id}/recurrence",
      "auth": true,
      "request_body": null,
      "response": { "status": 204, "body": null }
    }
  ],
  "out_of_scope": ["Notifications", "Cross-user sharing", "Calendar integration"],
  "open_questions": [
    "OQ-1: Background scheduler vs endpoint-triggered spawn?",
    "OQ-2: User timezone vs UTC for schedule evaluation?",
    "OQ-3: Should spawned task inherit parent's tags?"
  ]
}
THIS IS YOUR CONTRACT: This JSON file will be fed into every subsequent Gemini CLI command in M06 and M07. The new_models array becomes the SQLAlchemy model. The new_endpoints array becomes the OpenAPI spec. Everything flows from this one file.

Lab: Plan the Recurring Tasks Feature

LAB From Zero to Spec in 5 Steps

By the end of this lab, you will have a complete feature spec in spec/recurring-tasks.json ready for the design phase in M06.

1
Navigate to TaskFlow
PowerShell
cd sample-project\taskflow
# Verify GEMINI.md exists
Get-Item GEMINI.md
# Create the spec directory
New-Item -ItemType Directory -Force -Path spec
2
Generate the PRD
PowerShell / Terminal
gemini "@GEMINI.md Write a full PRD for a Recurring Tasks feature.
Tasks should auto-recreate when completed based on a schedule.
Include: Problem Statement, Goals, Non-Goals, 5+ Functional Requirements
with Acceptance Criteria, and Open Questions.
Reference actual field names from models.py." > spec/recurring-tasks-prd.md

# Verify it was created
Get-Content spec\recurring-tasks-prd.md | Select-Object -First 20
3
Decompose to User Stories
PowerShell / Terminal
gemini "@GEMINI.md @spec/recurring-tasks-prd.md
Convert this PRD into 5-8 user stories in 'As a user I want...' format.
Score each on INVEST. Flag any stories with S=Fail and suggest splits.
Include story points (1/2/3/5/8) and dependency chains." \
  >> spec/recurring-tasks-prd.md
4
Run the Gap Analysis
PowerShell / Terminal
gemini "@models.py @schemas.py @routers/tasks.py @spec/recurring-tasks-prd.md
Identify all gaps between the current TaskFlow implementation
and the Recurring Tasks feature. For each gap: file name, what
to add/change, and risk level (Low/Medium/High)." \
  >> spec/recurring-tasks-prd.md
5
Output the JSON Spec
PowerShell / Terminal
gemini "@GEMINI.md @spec/recurring-tasks-prd.md
Output the Recurring Tasks spec as valid JSON only. No markdown.
Include: feature, user_stories, new_models, new_endpoints,
out_of_scope, open_questions." > spec/recurring-tasks.json

# Validate it's valid JSON
python -c "import json; json.load(open('spec/recurring-tasks.json')); print('Valid JSON!')"

Expected output: Valid JSON! — your spec is ready for M06.

Quiz

Check Your Understanding 0 / 5
1. You run gemini "@models.py Write a PRD..." from a different directory. What is the most likely problem?
A. Gemini ignores the @ prefix outside the project root
B. The relative path @models.py won't resolve — Gemini looks in the current directory
C. Gemini CLI requires absolute paths for all @ references
D. PRDs can only be generated with GEMINI.md loaded
2. A user story is scored INVEST: I=Pass, N=Pass, V=Pass, E=Partial, S=Fail, T=Pass. What is the most important action?
A. Reject the story and remove it from the backlog
B. Accept it — Partial and one Fail is within acceptable range
C. Split the story into smaller stories until S=Pass, then re-score
D. Move the story to a later sprint and reassess
3. In the gap analysis, Gemini flagged GAP-2: "No completion event/hook in Task model." This is Risk: High. What does this mean for planning?
A. The feature cannot be built — the codebase is incompatible
B. This is an architectural decision (scheduler vs. hook) that must be resolved in design before implementation begins
C. The developer should pick the simplest option and document it later
D. This gap only matters if a background scheduler is required
4. Why is the JSON spec output more valuable than the markdown PRD for downstream modules?
A. JSON is shorter and easier for Gemini to read
B. JSON can be fed back to Gemini CLI in M06/M07 as structured input, enabling precise code generation aligned to the spec
C. Markdown files cannot be read by Gemini CLI with @ prefixes
D. JSON forces Gemini to generate more accurate output
5. You inherit a requirements doc with the requirement: "The system should handle recurring tasks efficiently." What is the primary problem with this statement?
A. It uses "should" instead of "shall"
B. It is untestable — "efficiently" has no measurable definition or pass/fail criteria
C. It doesn't specify a user persona
D. The requirement is too simple — it needs more detail about the feature