Bluesquare Dev Week 2026 · 3 hours

Spec-driven development and TDD with coding agents

Hands-on, with Claude Code and Superpowers.

Today

Goals

Goals

  • Try spec-driven development and TDD with an agent
  • See what ADRs bring
  • Take an issue through the whole workflow, then another if time allows
  • Form your own opinion

Not goals

  • Learning the stack
  • A coherent product
  • Coordinating the pairs: this is not a Scrum session

Today

Plan for the three hours

0:00Why and how
0:30Wee-App
0:55Build, round 1
2:05Build, round 2
I talkyou buildwe talk

Part 1 · Why

TDD before agents

Benefits

  • Tests describe behaviour
  • Pressure towards testable design
  • A safety net for later changes

Costs

  • More to write up front
  • Tests rewritten when the design moves
  • Often dropped near a deadline

Part 1 · Why

What changes with coding agents

Writing tests costs less

The agent writes and rewrites them.

Reviewing costs more

Hundreds of lines arrive in minutes.

Tests give a feedback loop

The agent can check its own work.

Part 1 · Why

Red, green, refactor

RedOne failing test
GreenJust enough code to pass
RefactorClean up, tests stay green

Part 1 · Why

Spec-driven development

  • Agree on what and why before the code
  • A short spec is quicker to review than a diff
  • The spec stays in the repo after the chat session ends

Today: one page

  • Purpose
  • Approaches considered, and why this one
  • Shape of the query or component
  • Acceptance criteria
  • Out of scope

Part 1 · Why

The workflow

BrainstormQuestions, then approachesyou pick
SpecWritten and committedyou review
PlanSmall steps, each with a testyou read it
ImplementRed, green, refactor, commit
VerifyTests, type-check, try the feature
Pull requestPreview with its own databaseanother pair reviews
ADRThe agent proposesyou decide

Part 1 · Why

Three tools for spec-driven development

GitHub Spec KitGSDSuperpowers
Stepsconstitution → specify → plan → tasks → implement → convergediscuss → plan → execute → verify → shipbrainstorm → spec → plan → implement → review
Who drivesYou, command by commandYou, phase by phaseSkills load on their own
Main concernWhat and why before howA fresh context for each taskKeeping the agent on the method
TestsLeft to the constitutionA verify phase after the buildTest first, required

Same family: Kiro, OpenSpec, BMAD. Today: Superpowers, for the discipline (next slide).

Part 1 · Why

Superpowers: a method and some discipline

  • Agents know TDD
  • They skip steps when a task looks simple, or when stuck
  • Skills add gates, "iron laws" and lists of excuses
test-driven-developmentNo production code without a failing test first
systematic-debuggingNo fixes without root cause investigation first
verification-before-completionNo completion claims without fresh verification evidence

Part 1 · Why

When is it worth it?

Throwaway prototype

Usually not

The process slows exploration.

A day or two

Debatable

A direct prompt often does it.

Days to weeks

Often yes

The spec and the plan help you keep track.

A long-lived product

Yes

Specs and ADRs record why things were done.

Today's issues are too small to show a gain. The aim is to try the workflow.

Part 1 · Why

Architecture Decision Records (ADRs)

An ADR is a short file in the repo that records one technical decision.

  • Context: the situation
  • Decision: what was chosen, what was rejected
  • Consequences: what gets easier or harder
0007. GeoJSON in jsonb instead of PostGIS Status: Accepted Context The dashboard draws districts on a map. IASO stores geometry with PostGIS. Decision Simplified GeoJSON in a jsonb column. No PostGIS. Consequences No extension needed. No spatial queries in SQL. Revisit if a ticket needs one.

Part 1 · Why

Why ADRs work well with agents

  • An agent starts each session without history
  • It reads docs/adr/ before brainstorming
  • After a plan, it proposes ADRs; you decide

From this repo

0006 Synthetic seed derived from anonymised IASO data

0008 No authentication yet

0012 Migrate during the deploy build

Part 2 · Wee-App

The use case: IASO device syncs

  • Mobile devices sync their data to IASO
  • A silent device means missing data
  • Who has not synced recently, and where?
  • For now the app has a single page, showing a table of syncs
In the database
Org units1,332
country / districts / chiefdoms / facilities1 / 13 / 152 / 1,166
Devices (12 never synced)200
Syncs over 90 days6,066
Users, anonymised41

Real org units from an IASO dump, synthetic syncs, no personal data.

Part 2 · Wee-App

The database

org_unit1,332 rows idinteger nametext parent_id→ org_unit level1 to 4 pathtext latitude, longitude geometryjsonb device200 rows idinteger serialtext, unique org_unit_id→ org_unit device_sync6,066 rows ididentity device_id→ device user_id→ app_user synced_attimestamptz submission_countinteger org_unit_countinteger entity_countinteger app_user41 rows idinteger usernametext, unique n1 n1 n1 n1

Part 2 · Wee-App

The stack, coming from Python and Django

You knowHere
Django ORMKyselyTyped SQL builder, not an ORM
DRF viewstRPCTyped functions called from the frontend
Django migrationsKysely migrationsNumbered files
pytestVitestQueries on an in-process Postgres (PGlite); each test inserts its rows
Testing LibraryComponents in jsdom: render with props, find by role and text
React + MUIReact + MantineComponents and charts; MapLibre for maps
A serverVercel + NeonOne URL and one database per pull request

For today, not knowing the stack is fine. The agent handles the syntax.

Part 2 · Wee-App

Frontend and backend

Browser
Pageui/SyncsPage.tsxAsks for the data, passes it to components
↓ rows, as props
Componentui/SyncTable.tsxShows the rows it receives; like a template
tRPCA typed call over HTTP. No URL or serializer to write
Server · Node.js
Procedureapi/router.tsChecks the input, calls the query; like a DRF view
Queryapi/queries.tsSQL written with Kysely; like a queryset
SQL
Database
PostgresDocker locally, Neon when deployed

Part 2 · Wee-App

What gets a test

HowPattern to copy
QueryReal SQL on a Postgres that runs inside the test (PGlite); each test inserts its rowsqueries.test.ts
ComponentRendered with props in a simulated browser (jsdom); find by role and text, clickSyncTable.test.tsx
Page, procedureNo test: the type-check, then try the feature
Whole appThe preview of the pull request

No test replaces the database or a component with a fake (a mock): a test that passes means the real code ran. pnpm test runs everything in a few seconds, with nothing to start first.

Part 2 · Wee-App

Environments

Code
App
Database
Your laptop
One git worktree per issue
pnpm dev on :3000
Postgres in Docker, seeded
Pull request
Your branch
Vercel preview URL
Neon branch, forked from production
main
Merged pull requests
Vercel production
Neon production

Part 2 · Wee-App

Repository structure

wee-app/ ├─ CLAUDE.md agent instructions ├─ .claude/skills/ Superpowers skills ├─ docs/ │ ├─ adr/ decisions │ └─ superpowers/ specs and plans ├─ data/ org units, users: seed input ├─ compose.yaml local Postgres └─ src/ ├─ routes/ one file per page URL ├─ features/ your work goes here ├─ server/db/ migrations, seed, types └─ ui/ app shell, theme
src/features/ ├─ router.ts list of feature APIs ├─ nav.ts menu entries └─ device-syncs/ the existing feature ├─ api/ │ ├─ queries.ts SQL, with Kysely │ ├─ queries.test.ts its tests │ └─ router.ts tRPC procedures └─ ui/ ├─ SyncsPage.tsx the page ├─ SyncTable.tsx the table └─ SyncTable.test.tsx its tests

Part 2 · Wee-App

Agent instructions: CLAUDE.md

Rules

  • Everything in English
  • Skills are mandatory
  • Read the ADRs first; propose ADRs after
  • Worktree, then pull request; never main
  • Test the queries and the components
  • Write for Python developers: explain the jargon
  • No linter, e2e, auth or CI: they are issues

Pace, for today

  • Questions in batches of three, two batches at most
  • Then two or three approaches
  • One-page spec, one-page plan
  • No sub-agents, one round of review

Part 3 · How we work

Pairs, issues, Kanban

Backlog

  • GitHub issues
  • Each describes a need and leaves the solution open

Kanban

  • Backlog → Ready → In progress → In review → Done
  • One card per pair at a time

Pair

  • Driver talks to the agent
  • Navigator reads and reviews
  • Swap at the round table

Part 3 · How we work

Roadmap: the open issues

Features
#2List devices that have stopped syncingS
#5Chart syncs per day over the last 30 daysS
#6Device detail page with its sync historyS
#3Sync health per district on a mapM
#7Sync activity per userM
#17Filter devices by user, on list and mapM
#19Improve the table of synced devicesM
#20Basic dashboard pageM
#21Dark modeS
Cross-cutting
#12Pin the Node and pnpm versionsS
#10Type-check and tests on every pull requestS
#9End-to-end smoke testM
#11Linting, dead code, module boundariesM
#13Decide what documentation we need, write itM
#8Sign-in with a Bluesquare accountL

Missing something? Open an issue and take it.

Part 3 · How we work

Getting started on an issue

$ claude > /brainstorming https://github.com/BLSQ/wee-app/issues/<n>

The agent will

  • create a worktree
  • read the issue and the ADRs
  • ask one or two rounds of questions
  • propose two or three approaches
  • offer mockups in a browser

You will

  • answer as the user would
  • read the spec before approving
  • disagree when needed

Part 3 · How we work

The visual companion

  • Mockups in a browser tab, for visual questions
  • Offered once: say yes
  • Text questions stay in the terminal
localhost · Which layout for "stopped syncing"?
A · table only
B · map and list

Part 3 · How we work

Review by another pair

  • Spec committed? Ask the agent for a draft pull request
  • The next pair reviews the spec while you implement
  • Then the code and the preview
  • Ring: pair 1 → pair 2 → … → pair 1

What to look at

  • Does the spec answer the issue?
  • Is "out of scope" clear?
  • Do the tests describe behaviour?
  • Worth an ADR?

Part 3 · How we work

Merging, and merge conflicts

> Merge origin/main into this branch and resolve the conflicts, keeping the features from both sides.
  • Approved? You merge your own pull request
  • Conflicts are likely
  • Ask your agent to resolve them

Then check

  • Both features still registered
  • Lockfile regenerated by pnpm install
  • Two migration files with the same number? Renumber yours
  • Tests and type-check pass

Part 3 · How we work

While the agent works

  • Read the plan before it runs
  • Review the other pair's spec
  • Read the ADRs, a spec, a plan
  • Check claims like "this should work now"
  • Note one surprise for the round table

Brainstorming needs you

The agent waits for your answers.

Part 3 · How we work

Setup check

$ gh auth status $ git clone git@github.com:BLSQ/wee-app.git && cd wee-app $ pnpm install && docker compose up -d && pnpm db:reset $ pnpm test # green; needs no database $ pnpm dev # http://localhost:3000

Needs Claude Code, Docker, Node 22.12 or newer, pnpm, and write access to BLSQ/wee-app.

Part 3 · How we work

Read what is already written

ADRs

docs/adr/

  • One decision each, with its reasons
  • Fourteen so far; the agent reads them before brainstorming

Specs

docs/superpowers/specs/

  • What a piece of work must do, on one page
  • Written after brainstorming, before any code

Plans

docs/superpowers/plans/

  • The steps to build it, each with a test
  • Written once you approve the spec

Your work today adds to all three. Read a few while pnpm install runs, or while the agent implements.

Round table · 1:45

Round table: two minutes per pair

Leave the agent running. Then swap driver and navigator.

Round table · Inside Superpowers

What a skill is, and how it loads

Session startsOnly names and descriptions are in context
Something happensA test fails
A description matches"Use when encountering any bug, test failure…"
The skill loads"Using systematic-debugging"
.claude/skills/systematic-debugging/SKILL.md
Plain Markdown, one folder per skill
description: Use when…
The trigger
## The Iron Law
A rule with no exceptions
## The Four Phases
The procedure
## Red Flags · ## Common Rationalizations
Likely shortcuts, each with an answer

Round table · Inside Superpowers

Which skill, and when

Brainstorm, specwriting-adrsusing-git-worktreesbrainstorming
Planwriting-plans
Implementexecuting-planstest-driven-developmentsystematic-debuggingsubagent-driven-development
Verifyverification-before-completion
Pull requestrequesting-code-reviewreceiving-code-reviewfinishing-a-development-branch
ADRwriting-adrs
written for this repoonly when something breaksstruck: switched off today

Round table · Inside Superpowers

Skills list the usual excuses, with an answer

What the agent is tempted to think
What the skill replies
"This is too simple to need a design"
Simple means a short design, not no design. Two sentences in chat, then approval.
"Too simple to test"
Simple code breaks. Test takes 30 seconds.
"Emergency, no time for process"
Systematic debugging is faster than guess-and-check thrashing.
"One more fix attempt"
3+ failures = architectural problem. Question pattern, don't fix again.

Round table · Inside Superpowers

Systematic debugging

1 · Root causeRead, reproduce. No fix yet
2 · PatternCompare with what works
3 · HypothesisOne at a time
4 · FixFailing test, one fix, verify
Fix failed?Under 3: back to 1
3 or more: discuss the architecture

In this repo: the deployed app fails with relation "device_sync" does not exist

1 · Root cause
The deployment is fine. The migration command had run against a developer's local database
2 · Pattern
Locally the tables exist; in production they do not
3 · Hypothesis
Production was never migrated
4 · Fix
Migrate during the deploy build; a failing migration now fails the build
redeployrun db:migrate againneither touches the production database

Round table · Inside Superpowers

Verification before completion

Before any "done", the skill asks for the output of a check run just now. The check has to match the claim.

# the claim: "the syncs page works". The check: the tests$ pnpm test ✓ all tests pass
# what a user saw on /syncsa spinner that never ends ReferenceError: Can't find variable: Buffer

The tests run in Node and never load the page. For "the page works", the matching check is to open the page.

Close · 2:40

Demos: two minutes per pair

Close · 2:52

Retro

Close

To try it on your own projects

> /plugin install superpowers@claude-plugins-official
· ←/→ ·