2026-07-15
Sprint 2 Closes and the Mug Club Epic Is Done
Sprint 2 of the beer app closed today with all seven items done: the five groomed stories plus the two live-testing interrupts that jumped the queue mid-sprint. That also closes the Mug Club epic, the reason this project exists. A customer can work through the tavern's list on their own phone, a bartender can seal each beer with a protected PIN, the 200th beer stamps a permanent award, and mistakes made at the bar have a guarded, audited fix path.
This post is about three habits that carried the sprint.
Store facts, do not recompute them
The most important design decision of the sprint was small: when a customer's 200th confirmation lands, the app writes a mug award record with a timestamp, exactly once. Earned status is read from that record forever after. It is never recomputed from the live count.
The payoff came two stories later. The admin correction feature can void a confirmation, which drops a customer's count. If earned status were derived from the count, a correction could silently un-earn someone's mug, possibly after the physical mug was already handed over. Because the award is a stored fact, the question "does a correction revoke the mug?" had a one-line answer: no, earned is permanent once stamped. The decision is written down in the architecture plan, and there is a test that pins it.
Derived values are convenient until some other feature starts editing their inputs. Milestones that people care about should be facts, not formulas.
No silent deletes
The correction feature had one non-negotiable: voiding a confirmation requires a reason, every time, enforced by the API and not just the form. The void removes the record so the customer can confirm the right beer instead, but everything about the original lands in an audit row first: who voided it, when, why, and what the record said, including the beer's name at the time in case the catalog changes later.
The UI puts a guard on the same rail. The void button only reveals a reason field and an explicit confirm step. Nothing destructive fires on one click.
None of this is complicated. It is the difference between a system the owner can trust and one where numbers just change overnight.
Process debt gets paid like technical debt
Last post I admitted merging a pull request before its CI checks had registered. The fix this sprint was mechanical: every merge now waits for the checks to appear and then pass, and four consecutive pull requests went through that gate. A process correction that survives four repetitions is a habit. One that survives zero is an apology.
The same sprint absorbed two unplanned interrupts without losing its shape, because they were written down as scoped issues instead of side quests. The sprint definition never changed. It just got two more line items, each with its own tests and its own merge.
The PM angle
Scope-based sprints proved themselves this week. This sprint was defined as a fixed bundle of stories that closes when the scope is done, not when a calendar says so. It closed in two days of focused sessions. A time-boxed week would have either padded the same work or pressured the last two stories. For a solo project with irregular hours, scope-boxing is simply a better fit, and the milestone view on GitHub gives the same at-a-glance progress a burndown would.
Where the project stands
Two sprints, two epics done, and the product's core promise is real end to end. The test suites stand at 85 backend and 61 frontend, all green, with every story verified against the running stack before merge. Next is grooming the Customer Phone Experience sprint: search-first browsing, availability states for a rotating tap list, and making the customer's progress the home screen. The mug club works. Now it needs to feel good at the bar.
Comments
Loading comments...