Ten changes, with and without a codex

after an original for the codex lesson

Ten changes without a codex, and ten with one one repo, one week

one repoten small changesfour separate sessions

they part company here — whether three rules were written down

No codex

every change decides for itself

· —
  • #1user detailgetXthrow

    const u = await getUserById(id)

  • #2order listgetXthrow

    const list = await getOrders()

  • #3profile cardfetch_xthrow

    const p = await fetch_profile(id)

  • #4empty statefetch_xnull

    if (!p) return null

  • #5invoice rowfetch_xnull

    function fmtDate(d) { … }

  • #6audit logfetch_xconsole

    console.error('bad date')

  • #7team pageloadXnull

    const t = await loadTeam()

  • #8date columnloadXnull

    function formatDate2(d) { … }

  • #9billingloadXswallow

    try { … } catch {}

  • #10settingsfetchXswallow

    const s = await fetchSettings()

“We don't write it that way here” — said four times, in one week.

naming conventions in play4
error conventions in play4
helpers written twice2
diverged

Three rules

decided once, applied every time

  • · reads are named getX
  • · failures throw AppError, never return null
  • · dates go through @/lib/format
  • #1user detailgetXthrow

    const u = await getUser(id)

  • #2order listgetXthrow

    const list = await getOrders()

  • #3profile cardgetXthrow

    const p = await getProfile(id)

  • #4empty stategetXthrow

    if (!p) throw new AppError('no profile')

  • #5invoice rowgetXthrow

    import { formatDate } from '@/lib/format'

  • #6audit loggetXthrow

    throw new AppError('unparseable date')

  • #7team pagegetXthrow

    const t = await getTeam()

  • #8date columngetXthrow

    import { formatDate } from '@/lib/format'

  • #9billinggetXthrow

    throw new AppError('charge failed', { cause })

  • #10settingsgetXthrow

    const s = await getSettings()

Review spent its whole budget on whether the logic is right.

naming conventions in play1
error conventions in play1
helpers written twice0
consistent

changes 9–10 · reviewReview time. On the left, every comment is a matter of taste, so each one is negotiable and half of them lose. On the right there is nothing to negotiate, which is what frees a reviewer to look at whether the code is CORRECT.

Not one of the left column's choices is wrong on its own. That is the point: divergence is what ten reasonable decisions taken independently look like, so “please be consistent” cannot produce consistency and three written lines can. Consistency is a codex problem, not a talent problem — and not a model problem either.

step 5 / 5