Systems Thinking

10 min read

The 12-Slot Rule: Constraint-Driven Prioritization for Distributed Teams

From cardiac refractory periods to diesel governors to analog watch faces, constraint is how reliable systems stay alive. Here is a low-resolution but concrete git-based pacemaker protocol that brings the same instinct to distributed teams.

2026-03-16

Aerial view of a sailboat navigating between rocky islands with digital signal arcs, overlaid with the text Constraint-Driven Prioritization

Most systems fail not because they lacked capacity, but because they had too much of it. Unlimited slots mean unlimited deferral. Unlimited deferral means nothing actually moves. The instinct to maximize throughput by removing constraints is wrong in a way that takes years to feel.

Constraint-driven prioritization is the principle that capacity limits aren't bugs to be engineered around — they're the architecture. The constraint is what makes the system legible, predictable, and alive.

The heart never asks permission to beat

The sinoatrial node fires at 60–100 beats per minute. It doesn't poll for capacity. It doesn't wait for downstream organs to signal readiness. It ticks, and the rest of the system responds or doesn't.

What makes this reliable isn't the rate, it's the refractory period. For roughly 200–400 milliseconds after each contraction, cardiac muscle cells physically cannot fire again. The absolute refractory period is not a soft limit enforced by policy. It's a hard mechanical constraint baked into ion channel biology. The heart cannot overcommit. It cannot queue more work than it can process in the current cycle.

Heart rate variability (HRV) research reveals the inverse: a low-variability signal, one that looks rigid and metronomic, is associated with reduced autonomic flexibility and stress. High-performing athletes and well-rested systems show more variation, not less. The constraint creates the floor; variability within it is the signal of health. When HRV collapses, it often precedes burnout or illness by days. The pacemaker is both the clock and the diagnostic.

The architecture here is worth naming: there is a primary oscillator (SA node), a fallback oscillator (AV node at 40–60 BPM), and a tertiary fallback (Purkinje fibers at 20–40 BPM). Each fires slower than the one above it. If the primary fails, the system doesn't stop, it degrades gracefully at a lower cadence. The fallback doesn't try to match the primary rate. It just keeps the system alive at the rate it can sustain.

The governor knows best

A diesel engine governor is not a safety feature. It's a design principle.

Most commercial trucks running a Paccar MX-13 or Detroit Diesel DD15 are governed to roughly 1800–2100 RPM and 65 mph road speed. The engines are physically capable of more. The 15L Detroit DD15 produces 505 HP and 1750 lb-ft of torque; it doesn't redline until 2100 RPM, but peak torque arrives at 1000 RPM. The governor is set not at the ceiling but near the efficiency band.

Fleet operators who run governed trucks see 12–15% better fuel economy compared to ungoverned equivalents on the same routes, and significantly lower injector and turbo replacement rates. The constraint doesn't just preserve the engine, it shifts operator behavior. When a driver can't push past 65 mph, they stop trying. Decision fatigue about speed drops to zero. The system is self-regulating.

The same pattern appears in engine timing. An internal combustion engine fires pistons in a fixed sequence with precisely constrained ignition advance. Too much advance causes knock and head damage. Too little wastes energy. The optimal advance curve is narrow. Modern ECUs spend enormous compute pulling ignition timing back toward a known-safe constraint when knock sensors fire. They don't optimize for maximum power, they optimize for maximum sustained power within a thermal and mechanical envelope.

In both cases, the constraint produces the outcome. Remove the governor and you don't get more throughput, you get shorter engine life and higher variance failure modes. The constraint is what makes the system trustworthy enough to run for a million miles.

The watch face as a capacity model

A 12-hour analog watch face is a constraint model. It has 12 positions. Each position is visibly finite. When the face is full, you see the face is full.

A 24-hour digital display gives you 24 slots and no friction. You'd never trim. The display becomes a dashboard, informational, passive, infinitely extensible. You add entries without feeling the cost of each addition. The constraint disappears into abstraction, and with it, the forcing function to prioritize.

The analog metaphor maps cleanly to a work system:

  • Hour markers: each one is a routine slot. 12 max. You feel the face getting crowded. Every routine you add costs a position.
  • Hands: the sweep is the cadence engine. The watch is always moving. It doesn't stop when the inbox is full.
  • Crown: the poke. You wind it to energize, to acknowledge, to inject intent. Without the wind, the mainspring runs down.
  • Complications: subdials for different categories of work: research, operations, hygiene. A complication is valuable precisely because it costs face real estate. You don't add a complication casually.
  • Mainspring: the energy store. Bounded capacity that depletes as routines fire and replenishes when you engage with the system.

The key insight is that the constraint is what you carry. A pocket watch, a wristwatch — you bring it with you. The face is your capacity. It doesn't grow just because you have more things to do. You choose what's worth a position on the dial.

If you want to add routine #13, you have to park or remove one first. The watch face is full. That's not a limitation — that's the feature.

Git as a pacemaker

Distributed teams need a shared clock. Not a meeting, a clock. Something that ticks independently of attendance, fires on cadence, and leaves a legible history. Git is already close to this. The commit log is a heartbeat record. The branch topology is a capacity surface. PR lanes are work-in-progress slots.

The problem is that git doesn't enforce capacity. You can open 40 PRs simultaneously. You can queue work indefinitely. There's no refractory period, no governor, no analog face telling you it's full. So the system accretes until review latency spikes, merge conflicts multiply, and the critical path becomes invisible.

A git-based pacemaker protocol imposes that constraint from within the repository itself. The clock is the repo. The routines are config files. The cadence engine is a CI job or a scheduled action. The capacity limit is enforced by checking open issue count before materializing new work.

Here's what the mechanism looks like at low resolution.

A concrete sketch

Each routine lives as a YAML file in .keel/routines/. It declares a cadence, a label, a WIP limit, and a template for the issue it creates.

yaml
# .keel/routines/dependency-audit.yaml
name: dependency-audit
cadence: weekly
label: ops:deps
wip_limit: 1
title: "Weekly dependency audit"
body: |
  Review for CVEs, major version bumps, and deprecated APIs.
  Check: npm outdated, cargo audit, nix flake update --dry-run.
  Resolution: patch, defer, or file a follow-up epic.

A scheduler reads every file in .keel/routines/ on the declared cadence. Before materializing an issue, it queries the open issue count for that routine's label.

bash
#!/usr/bin/env bash
# .keel/scripts/tick.sh
# Runs on cron or a scheduled CI job

ROUTINE=$1
LABEL=$(yq '.label' ".keel/routines/$ROUTINE.yaml")
WIP_LIMIT=$(yq '.wip_limit' ".keel/routines/$ROUTINE.yaml")

OPEN_COUNT=$(gh issue list --label "$LABEL" --state open --json id | jq 'length')

if [ "$OPEN_COUNT" -ge "$WIP_LIMIT" ]; then
  echo "[$ROUTINE] WIP limit reached ($OPEN_COUNT/$WIP_LIMIT). Skipping tick."
  exit 0
fi

TITLE=$(yq '.title' ".keel/routines/$ROUTINE.yaml")
BODY=$(yq '.body' ".keel/routines/$ROUTINE.yaml")

gh issue create --title "$TITLE" --body "$BODY" --label "$LABEL"
echo "[$ROUTINE] Materialized: $TITLE"

That's the refractory period. If the previous cycle's output hasn't been resolved, the system doesn't queue another. It skips and logs. The log is the diagnostic, if a routine keeps skipping, that's your HRV signal. Something upstream is blocked.

The watch face constraint maps to a branch topology rule: no more than 12 active routine labels on the board at once. You can enforce this as a repository policy — a pre-receive hook or a CI check that counts distinct routine labels in open issues and fails if the count exceeds the limit. Adding routine #13 requires archiving one first.

bash
#!/usr/bin/env bash
# .keel/scripts/watch-capacity-check.sh
# CI gate: fail if active routine labels exceed watch face limit

WATCH_FACE_LIMIT=12
ROUTINE_DIR=".keel/routines"

ACTIVE_COUNT=0
for f in "$ROUTINE_DIR"/*.yaml; do
  LABEL=$(yq '.label' "$f")
  COUNT=$(gh issue list --label "$LABEL" --state open --json id | jq 'length')
  if [ "$COUNT" -gt 0 ]; then
    ACTIVE_COUNT=$((ACTIVE_COUNT + 1))
  fi
done

if [ "$ACTIVE_COUNT" -gt "$WATCH_FACE_LIMIT" ]; then
  echo "Watch face full: $ACTIVE_COUNT/$WATCH_FACE_LIMIT active routines."
  echo "Park or resolve one before adding another."
  exit 1
fi

echo "Watch capacity: $ACTIVE_COUNT/$WATCH_FACE_LIMIT slots used."

The git log now serves as the pacemaker record. Each materialized issue is traceable back to a tick. The cadence is visible in the issue creation timestamps. You can plot issue creation rate over time and see whether the system is maintaining rhythm, accelerating into overload, or going quiet in ways that signal drift.

The fallback hierarchy

Recall the cardiac architecture: SA node, AV node, Purkinje fibers. Each fallback fires slower. The system degrades gracefully.

A git pacemaker can express the same thing. Define three cadence tiers: primary routines (daily or weekly), secondary routines (biweekly, fires if primary lane is clear), and tertiary housekeeping (monthly, fires only when secondary is also clear). If the team is under load, primary routines saturate and the secondaries stop materializing automatically. The system slows itself down rather than flooding the board.

This is the governor. You don't need a manager to call a moratorium on new tickets during crunch. The protocol does it. The WIP limits and cadence tiers enforce the constraint structurally. The decision doesn't require attention — it's already been made in the config.

What the clock tells you

The most useful property of a pacemaker protocol isn't that it schedules work. It's that deviation from the expected rhythm is itself a signal.

If a weekly routine skips three consecutive ticks because the WIP limit is always full, that's not a scheduling problem — that's a capacity problem. The resolution rate for that category of work is lower than the materialization rate you intended. That mismatch is visible in the log before it becomes visible in the retro.

If a daily routine materializes but issues sit open for 8 days on average before closing, your effective cycle time has drifted from 1 day to 8 days. You can see this without a project management tool. The git log and the issue API are sufficient.

The clock doesn't just run the system. It tells you how the system is doing. That's the watch: a mechanism you carry with you, that does work in the background, and that you glance at to know the time.

Conclusion

The heart can't overcommit. The diesel engine can't over-rev. The watch face can't show 13 hours. These aren't failures of design, they're the design. Constraints are how systems stay alive long enough to be useful.

A git-based pacemaker protocol is a low-overhead way to bring that same instinct to distributed work. YAML files that declare cadence and WIP limits. A scheduler that checks capacity before firing. A branch topology that reflects a bounded watch face. The git log as a heartbeat history you can query.

It doesn't require a new tool. It requires a new instinct: that the right response to "we have too much to do" isn't to build a bigger board. It's to accept the 12 slots, choose what belongs on the face, and let the clock run.