Skip to main content
Paul Welty, PhD AI, WORK, AND STAYING HUMAN

Work log: March 12, 2026

What shipped today

Today was a high-throughput pipeline day — 25 commits landed on main across three major themes: engine test infrastructure, production reliability, and UI improvements.

Engine test coverage went from 35 to 115 tests. The parent issue #1051 (“engine has 1 test file across 42 handlers”) is now fully closed. We built shared pytest fixtures (conftest with mock_db, mock_pool, make_command_row), then wrote comprehensive unit tests for the four most critical engine modules: the poller (payload decode, stuck command recovery, fail/retry, handler dispatch), the scheduler (idempotency keys, briefing hour matching, 5-minute window rounding, timezone-aware nudges), social_publish (credential validation across all 5 platforms, publish dispatch for both legacy and social queue paths), and briefing_generate (lifecycle classification with boundary tests and edge cases). All tests use consistent patterns — parametrized inputs, datetime mocking, and SQL assertion via call_args inspection.

Production bug fix: KeyError in content.stage_start handler. A user’s content creation via the AI assistant tool was failing because assistant_tools.py sent "stage" instead of "stage_name" in the command payload. Every other caller in the codebase (15+ places) used the correct key — this was a simple typo that only triggered through the Maya chat path. Fixed the caller and hardened the handler to accept both keys for in-flight commands.

Infrastructure hardening. The asyncpg connection pool was running with minimal config — no connection acquisition timeout, no TCP keepalive. After a cluster of Sentry TimeoutErrors and a transient Railway deploy failure, we added timeout=30 and keepalive settings to detect stale connections through pgbouncer. Also triaged and closed 7 duplicate Sentry/deploy issues that all stemmed from the same transient database hiccup.

Ideas page sort toggle. Added strength/newest/oldest sort buttons to the ideas list page, persisted via URL params across tab switches and search queries.

Completed

  • #1080 — Add pytest conftest with db mocking fixtures for engine tests
  • #1081 — Add poller unit tests for payload decode, stuck commands, and dispatch
  • #1082 — Add scheduler unit tests for idempotency keys and briefing hour matching
  • #1083 — Add social_publish unit tests for credential validation and publish dispatch
  • #1084 — Add briefing_generate unit tests for lifecycle classification
  • #1051 — Engine test coverage parent (all 5 children complete)
  • #1089 — [Sentry] TimeoutError (pool hardening)
  • #1091 — Deploy failure (transient, resolved)
  • #1094 — Deploy failure (duplicate of #1091)
  • #1096 — [Sentry] KeyError: ‘stage_name’ (bug fix)
  • #1095 — Sort ideas by date
  • #1087, #1088, #1097, #1098, #1099 — Duplicate Sentry TimeoutError issues (closed)

Release progress

  • v1.5: 1 open / 4 closed
  • v2: 0 open / 20 closed (complete)
  • v1-outbound: 0 open / 19 closed (complete)

Carry-over

  • #1100 — Add words target on content initiation (ready-for-prep, not yet started)
  • #1036 — In-memory rate limiter (blocked on Upstash setup)

Risks

  • The content that failed due to the stage_name bug should auto-retry now that the fix is deployed. If it doesn’t, the command may need manual reset in the commands table.

Flags and watch-outs

  • Engine tests run from within engine/ directory — import paths are engine.poller not engine.engine.poller
  • SQL parameter assertions: idempotency key is at call_args.args[5] (args[0] is SQL, args[1-5] are $1-$5)
  • The deploy alert workflow labels issues as “Failed Vercel deploy” even for Railway failures — minor but confusing

Next session

  • Prep and exec #1100 (words target on content initiation)
  • Check that the stage_name fix actually unblocked the user’s content (verify in commands table)
  • Consider prepping #1036 if Paul has set up Upstash
  • Run /scout to find more improvement opportunities now that engine test infra is solid

Why customer tools are organized wrong

This article reveals a fundamental flaw in how customer support tools are designed—organizing by interaction type instead of by customer—and explains why this fragmentation wastes time and obscures the full picture you need to help users effectively.

Infrastructure shapes thought

The tools you build determine what kinds of thinking become possible. On infrastructure, friction, and building deliberately for thought rather than just throughput.

Server-side dashboard architecture: Why moving data fetching off the browser changes everything

How choosing server-side rendering solved security, CORS, and credential management problems I didn't know I had.

The work of being available now

A book on AI, judgment, and staying human at work.

The practice of work in progress

Practical essays on how work actually gets done.

The machine is eating faster than you can feed it

Sixty-three issues closed across thirteen projects in one day. Four milestones completed. And the hardest problem wasn't building — it was keeping up with what you've already built.

The proxy problem

Every organization has this problem: knowledge locked inside one person's head. Today I accidentally designed a solution — and it has nothing to do with documentation.

True 1-to-1 outreach is finally possible with AI

The 1-to-1 personalization promise is thirty years old. It never worked because understanding each person was too expensive. AI changed the economics.