Problem explored: Human developers don't write useful commit messages — and that won't change. But AI agents can write rich, structured commit messages as a native part of their workflow. This demo shows what PR review looks like when the commit history is the documentation: a narrative arc with decisions, alternatives, and risk notes at each step. The opening comparison between a human PR and an agent PR with identical code makes the case for a new norm.

Same code. Same files. Different story.
Open Human-written
Migrate auth to shared middleware layer
+291 / −56 lines 8 files changed 5 commits
a3f9c1
fix auth
2 hours ago · Kevin Q
+89 −14 · 3 files
b2d8e0
more work
2 hours ago · Kevin Q
+52 −38 · 2 files
c9a1f2
wip
1 hour ago · Kevin Q
+14 −3 · 4 files
d7b3e1
tests
45 min ago · Kevin Q
+178 −0 · 1 file
e2c0a8
cleanup
30 min ago · Kevin Q
+2 −1 · 2 files
🤷
Where do you start?
Five commits: "fix auth", "more work", "wip", "tests", "cleanup".
The diff has 347 lines across 8 files. There's no story here — just a pile of changes.

What did each commit capture? What alternatives were considered? Why is lib/session.ts in this PR at all?

Compare with the Agent PR to see the same code with a complete story.
Open AI-generated
Migrate auth to shared middleware layer
+291 / −56 lines 8 files changed 5 commits
📖 Commits shown in narrative order, not chronological. The agent reordered them to present the data model first, core logic second, and cleanup last — the order that makes the PR easiest to evaluate.
Foundation
Core Change
Routing
Tests
Cleanup
Steps reviewed: 0 / 5
Step 1 · Foundation
Establish PUBLIC_ROUTES contract
Start here — everything else is built on this config
Decision
Auth defaults to required. Routes that should be public are listed explicitly in config/routes.ts. The allowlist, not the code, is the authoritative record of what's public.
Alternative I explored
A @public decorator per-route. Rejected — it requires touching each route file and fails open when forgotten. A single config file fails closed.
Risk
● Low  The list is small and obvious. Any reviewer can sanity-check it in 10 seconds. Current public routes: /health, /status, /docs, /auth/login, /auth/register.
+12config/routes.ts (new)
Step 2 · Core Change
Implement auth middleware
The central architectural decision — read after the config
Decision
Auth runs as Express middleware before any route handler. Routes bypass via the PUBLIC_ROUTES allowlist from Step 1. This makes the secure path the default path — any new route is protected unless explicitly excluded.
Why middleware over decorators
23 routes had @requireAuth. Every new route added without it was silently unauthenticated. The decorator approach requires discipline on every PR. Middleware requires discipline once, in this PR.
Risk
● Medium  Any route that should be public but is NOT in the allowlist will start returning 401 after this deploy. I cross-checked against the existing @requireAuth usage but a reviewer should verify the allowlist is complete.
+47middleware/auth.ts (new)   +8 −4server.ts
Step 3 · Infrastructure
Migrate session storage to Redis
⚠️ Flagged — requires your judgment on deployment
⚠️
Decision
Replaced in-memory Map<string, Session> with Redis. In-memory sessions don't survive restarts and break across multiple server instances.
What I don't know — please verify
Is Redis deployed in this environment? If REDIS_URL is unset, the server will fail to start. If Redis goes down, all active sessions are lost and users are logged out. I cannot determine from the codebase whether either scenario is acceptable. This needs a human judgment call.
Risk
● High  If Redis is not deployed or the URL is wrong, this is a deploy-blocking defect. Recommend verifying REDIS_URL is set in all environments before merging.
+38 −14lib/session.ts
Step 4 · Cleanup
Remove 23 redundant @requireAuth decorators
Mechanical — safe to approve quickly
What happened
With middleware in place, the per-route requireAuth calls are redundant — auth runs twice if both exist. I removed all 23. Each was verified against PUBLIC_ROUTES before removal.
What I did NOT remove
@adminOnly and @roleRequired decorators are untouched. Those handle authorization (who can access), not authentication (are you logged in). They layer on top of auth and are out of scope for this PR.
Risk
● Low  This is a mechanical deletion with no logic change. If middleware is working, removing the redundant decorators has no behavioral effect. Low risk to review quickly.
+2 −12routes/admin.ts   +3 −10routes/api.ts   +3 −12routes/users.ts
Step 5 · Tests
Add middleware and integration tests
Review last — tests reflect decisions made in steps 1–4
What's tested
Unit tests for the middleware itself (token validation, public route bypass, 401 on missing token). Integration tests verifying that each entry in PUBLIC_ROUTES returns 200 without a token. Integration tests verifying that non-public routes return 401 without a token.
What's not tested
Redis failure scenarios — I don't have a Redis instance available in the test environment. Recommend adding a test for when Redis is unavailable before this ships, but that's a follow-up task, not a blocker.
Risk
● Medium  The missing Redis failure test is a gap. The happy path is well covered. The Redis degradation path is not.
+178tests/auth.test.ts
Story complete
You reviewed 5 narrative steps — each with a decision, an alternative, and a risk rating. No guesswork about what each commit was doing or why.
The New Norm This Requires
This experience only works because the agent treated review-readiness as a first-class output — not just code that passes CI, but a story a human can follow. Every commit message recorded a decision, an alternative considered, and a risk level. The narrative reordering was deliberate: data model first, core logic second, cleanup last.

This isn't a new tool — it's a new expectation for how AI agents should commit. An agent that ships unreadable history is shipping an incomplete product.