---
title: "Louie — Thinking Cap's central job dispatcher"
description: "Team briefing · 2026-10-03 · status: dev-proven, rolling out"
created: 2026-10-03
updated: 2026-10-03
authors: ThinkingCap
topics: [Research Development]
status: published
canonical: https://console.thinkingcap.com/guest/Research-Development/System-Architecture/louie-team-briefing
---

# Louie — Thinking Cap's central job dispatcher

**Team briefing · 2026-10-03 · status: dev-proven, rolling out**

> *"Give it to Louie. He'll get it where it needs to go."*
> Named for Louie De Palma, the dispatcher in *Taxi*.

---

## 1. Why Louie exists

**The law: nothing touches the queues directly again** — not a web app, not a
worker, not a cron. Even a worker that needs to put a job on *another* queue
goes through Louie. Callers get **receipts**, never queue handles. Workers are
invisible implementation details. The stable contract is the **job type**.

What that buys us:

- **Receipts for everything.** Every job has an id, a status URL, and a full
  event ledger (submitted → claimed → renewed → completed/failed). No more
  "did it run?" archaeology across five tables.
- **One place to see it all.** The **Dispatch Desk** in capcom (Monitoring
  group, taxi icon): every lane's depth, oldest wait, failures, latencies,
  sparklines; a job inspector with the whole ledger; dead-letter triage with
  an audited Requeue button.
- **One security boundary.** Principals + per-type grants (bearer keys),
  instead of handing out queue DSNs. Authorization is against *capabilities*,
  never tables.
- **One discipline.** Claim fencing, retries, leases, dead-letter — defined
  once, in the Louie contract, instead of re-implemented (and re-broken) per
  queue. This kills the entire class of cross-engine double-processing bugs
  (the 2026 SCORM deadlock incident is the reference case: two engines
  committing the same rows).

---

## 2. How it works

Louie is a **stateless Node/TS service ×2** (HA pair, capcom + capcomaux).
**Postgres is authoritative for all state** — schema `louie` in the queues
database (`maestroqueues` prod / `maestroqueuesstable` dev). There is no
broker to lose.

**Submit** — `POST /jobs` with a bearer key. Body:
`{type, payload, dedupeKey?, priority?, jobId?, wait?}`. Returns a receipt:
`{jobId, statusUrl, resultUrl}` (`202`), or the result inline on the fast
route. `dedupeKey` re-submissions **re-attach** to the in-flight job instead
of duplicating.

**Job types** are the contract: `family.capability`, versioned JSON Schemas
(`type.kind.vN`) for request and result, per-type options (priority lanes:
sync 10 / async 100; `sync_allowed` + `sync_timeout_ms` for the fast route;
`enabled` — types are born dormant).

**Fast route** (data workers): `POST /jobs?wait=10` blocks server-side up to
the type's sync timeout and returns `200` + the result inline, or `202` with
a receipt on timeout.

**Workers** come in two binding modes:

- **Native** (all *new* capabilities): the SQL contract —
  `louie.claim / renew / complete / fail`, EXECUTE-only, zero table grants.
  Claiming is fenced (claim_token), leased, and long jobs must `renew` at
  half-lease intervals (mandatory — a job that outlives its lease is
  reclaimed, but only up to max attempts).
- **Adapted** (existing PG queues, *no worker change*): Louie **dual-writes**
  `louie.jobs` + the legacy queue row in **one transaction**, with the job id
  AS the legacy row id. The legacy worker drains the same table it always
  did and never knows Louie exists. Louie projects status/results back from
  the legacy tables, so receipts and the Dispatch Desk stay truthful.

**Never-go-dark properties** (by design): the dual-write is atomic (a job
can't exist in Louie without its legacy row); the drain path never moves;
every producer rewire ships behind an env var, dark by default; rollback =
unset the env, seconds, no deploy.

---

## 3. What's going through Louie now

**Live on the dev pair** (maestroqueuesstable): live gate **22/22** (2,000
async zero-doubles, fast route p95 ~1.2s, kill-9 lease reclaim, dedupe
re-attach, worker chaining). Dispatch Desk live in capcom.

**Registered adapted types (dev):** `scorm.commit`, `scorm.terminate`,
`enrollment.api`, and 12 surface lanes (`surface.bi/activity/analytics/
badges/users/accounting/calendar/logs/ltisetup/media/packagemanager/skills`).

**Producer rewires merged (all env-gated, dark until flipped):**
- **21 surface repos** (tc-surface ×13, lv-surface ×7) — the data-plane
  enqueue goes through Louie when `LOUIE_SUBMIT_URL`/`KEY` are set.
- **SCORM enqueue API** — on branch `scorm-pg-queue`, one human push from
  landing (Campbell; handoff doc in Douglas's share).

**Native citizens:** `test.echo` (the slice proof). `transcript.pdf / .clr /
credential.pdf / .email / .batch` are registered dormant — the transcript
worker becomes the first native production citizen when its binding lands
(D7, in flight with Douglas).

**Pending operator moves (tracked):** framework image deploy to the pair,
Campbell's branch push, production arming (DB + principals), per-capability
env flips, NSG rule for the pair's 4100, `managed=true`.

---

## 4. How to onboard

### A. New capability → native (the default)

1. **Register the type** — `POST /admin/job-types` (operator key):
   `{name: "family.capability", description, enabled: false, schemas:
   [{kind: "request", version: 1, schema: {...}}, {kind: "result", ...}]}`.
   Names match `^[a-z0-9]+(\.[a-z0-9-]+)+$`. Schema versions are **immutable**
   — to change one, register `v2`.
2. **Mint principals** — `POST /admin/principals` with
   `{name, kind: "caller"|"worker"|"operator", grants: [{typePattern:
   "family.*"}]}`. The bearer is shown **once**. One principal per producer
   family (dedupe namespaces are per-principal).
3. **Producer** — `POST /jobs {type, payload, dedupeKey}`. Always send a
   dedupeKey when retries are possible.
4. **Worker** — `LISTEN louie_q_<queue>` + poll fallback; `louie.claim` →
   work → `louie.complete(jobId, claimToken, result)` (or `louie.fail`);
   `louie.renew` at half-lease for anything long. The result must validate
   against the type's result schema or the sweeper fails the job (loudly —
   that's the point).
5. Reference implementation: `worker-test/echo-worker.ts` in the repo;
   `docs/WORKER-CONTRACT.md` is the contract.

### B. Existing PG queue → adapted (repoint, no worker change)

1. **Check the adapter kind** — `enrollment`/`settings` (triplet with
   details/failed companions), `scorm` (single table, ack-DELETE), `maestro`
   (inline status/result/error). Different shape? Talk to Douglas/Claude —
   a new kind is a small, deliberate code add, not a hack.
2. **Register the adapted type** with its adapter config (the column map from
   the Louie payload to legacy columns). Working examples in the registry:
   `scorm.commit`, `surface.bi`, `enrollment.api`.
3. **Rewire the producer behind env** — swap the direct INSERT for
   `POST /jobs` when `LOUIE_SUBMIT_URL`/`LOUIE_SUBMIT_KEY` are set, keep the
   legacy path when unset. Copy the pattern from any merged surface repo
   (`worker/src/lib/dataPlane/queue.ts`) or the SCORM API (`src/api/server.ts`
   on branch `scorm-pg-queue`). If your client mints its own job ids, pass
   `jobId` — the same id lands in `louie.jobs` and the legacy row.
4. **Worker: nothing.** It drains the same table at the same cadence.
5. **Roll when ready** — set the env; unset to roll back. The queue of
   record never changed hands, so there is no cutover risk.

### Rules of the road

- One Louie principal per producer family; never share keys across teams.
- Types are born `enabled:false` — enabling is a deliberate act.
- `attempts ≥ max_attempts` is terminal on every automated path; the only
  override is the operator Requeue on the Dispatch Desk (audited in the
  job's ledger).
- Louie never leaks the legacy shape: receipts speak
  `queued / running / completed / failed` only.
- Large results ride the `result_ref` blob channel (tcqueueca
  `louie-results`) — landing with the transcript worker.

---

## 5. Where to look

- **Dispatch Desk:** capcom → Monitoring → **Louie** (taxi icon) — the live
  board, job inspector, dead-letter triage.
- **Repo:** `thinking-cap/tc-svc-louie` — `docs/API.md`,
  `docs/WORKER-CONTRACT.md`, `docs/ARCHITECTURE.md`,
  `docs/TRANSCRIPT-BINDING.md`; the standing release gate is
  `scripts/gate-slice.mjs` (rerun-safe — run it before any Louie release).
- **Questions:** Douglas, or the Louie build session's transcripts on the
  ClaudeCode VM (`~/.claude/sessions/2026-10-01-louie-dispatcher.txt`).
