HBEngineering handbook

How we build it.

Seven practices a small team uses to ship serious AI-operations software. Not theory — what's in source control, what we'll defend in a PR review, what we've learned to do (sometimes the hard way).

01Type safety

Closed unions over runtime checks.

Every state machine, every event payload, every outcome lives in a closed-union TypeScript type. The compiler is the first reviewer — if a switch statement doesn't cover every case, the build fails. This is the cheapest insurance against the most common production bug: an unexpected category we forgot to handle.

  • ·type DraftStatus = "drafted" | "in_review" | "approved" | ...
  • ·Exhaustive switch + assertNever() helper at every endpoint
  • ·No any in production code. unknown at boundaries, then narrowed

02Architecture

Pure kernels + thin IO boundary.

Decision logic lives in pure functions with no side effects — easy to test, easy to reason about, no need to mock anything. Database calls, network requests, file I/O all live in a single thin file per feature that composes the pure kernel with the outside world. When something breaks, it's almost always in the IO file.

  • ·lib/growth/autopilot.ts — pure decision kernel (40 lines of logic)
  • ·app/api/cron/linkedin-daily-drafts/route.ts — IO orchestrator (200 lines)
  • ·Unit tests cover the kernel. Integration tests cover the IO boundary

03Observability

Best-effort audit. Never blocking.

Every business event writes an audit row. But audit writes never block the business event itself — they're wrapped in try/catch that silently absorbs DB outages. If the audit store is down, we don't refuse to approve a draft. Audit is a side-effect; the business event is the goal.

  • ·writeGrowthAudit() is always async + always best-effort
  • ·Closed-union GrowthAuditAction so audit typos are compile errors
  • ·Retention ≥ 365 days. Sha-256 signed. Never edited, only appended

04Deployment

Two switches between staging and production.

Posting to LinkedIn requires LINKEDIN_POSTING_ENABLED=true AND a live LinkedInAccountConnection AND a draft in status=approved|scheduled. Three independent gates. If any one is missing, the operation returns a typed `skipped_*` outcome and writes a run record. Defense in depth — flipping any one switch is reversible in a single env-var edit.

05Defaults

Safe defaults. Loud opt-outs.

Autopilot defaults to off. Posting defaults to off. Cron jobs refuse to run without CRON_SECRET set. The system ships in the most conservative state and gets more aggressive only via explicit env-var flips. Production safety is a property of the default, not the carefulness of the operator.

06Schema

Migrations as the source of truth.

The Prisma schema file is the design surface; the migrations directory is the contract with the production database. We never edit production tables manually. If a schema change isn't in a migration file checked into source control, it didn't happen. (We learned this the hard way — see Phase 470.)

07Hallmarks

Hallmarks of code we'd merge.

Tight scope. Comments explain WHY, not WHAT. No dead code. No commented-out blocks. No `// TODO` markers older than the sprint. Names that disambiguate from neighbors, not just describe their referent. Functions short enough that the entire signature fits on one line.