# Primitives catalog + replication checklist

Audience: AI coding agents first. Files in `../templates/` are VENDORED from the platform repo at merged main 2026-07-06 (PR#67→#81, all gate-proven). Templates here = canonical generic copies; any project's copy is an instance and may diverge freely. When you materially improve an instance, back-port the generic part here.

## File catalog (templates/)

| File | Role | Adaptation points |
|---|---|---|
| `cpu-limit.sh` | THE wrapper — cross-user FIFO admission, systemd scope/slice, nice, ionice, SCHED_IDLE, GOMAXPROCS, VITEST_MAX_FORKS/THREADS, node heap | cache dir; slice; package manager |
| `safe-merge.mjs` | fail-closed merge wrapper — refuses unless named gate check SUCCESS; authoritative on PR STATE not gh exit code; deletes leftover remote branch | workflow name "PR Gate" / job name "Full gate" |
| `ci-artifact-gate.test.mjs` | executable workflow contract — asserts gate topology + safe-merge behavior so drift fails the gate | rewrite asserts to your workflows; keep the PATTERN (topology as test) |
| `lefthook.yml` | pre-push guard — blocks main pushes, skips branch-deletes, FAST smoke only (typecheck + script tests, no e2e) | hook manager (lefthook/husky); smoke command |
| `workflows/pr-gate.yml` | pre-merge full gate on `pull_request`; env: `BUILD_CPU_RESERVE`, `TURBO_CACHE_DIR`, **`BUILD_SCHED_IDLE: "0"`** (MUST keep — CI under SCHED_IDLE starves) | runner labels; gate command; drop `TURBO_CACHE_DIR` if runner ≠ dev box |
| `workflows/main-gate.yml` | post-merge run — delivery trigger ONLY, no auto-revert | same |
| `workflows/delivery.yml` | publish+deploy gated on Main Gate success, pinned to `workflow_run.head_sha` | registry, deploy target, secrets |
| `vitest-config/` | shared factory — `realPg` preset: singleFork + hookTimeout 300s / testTimeout 180s (contention budget, factory-OWNED). Per-package overrides silently CAP factory via mergeConfig — DO NOT add them | preset names; drop realPg if no DB suites |
| `pg-template/` | `initdbCached()` — initdb template cache, ~3x faster DB boot. Key = version + binary size/mtime + user + args + LC_*/LANG/TZ; atomic-rename race; refuses non-empty dataDir; fail-open to real initdb. Tests prove each invariant RED | none (host-agnostic Node) |
| `hooks/deny-raw-pr-merge.sh` | PreToolUse hook blocking raw `gh pr merge` → forces safe-merge | project settings.json registration |

## One-time per MACHINE (not per project)

```bash
# one cross-user queue; every heavy caller fails closed when unavailable
sudo groupadd --force dev-build
sudo install -d -o <dev> -g dev-build -m 2770 /run/dev-build-slot /var/cache/<project>-turbo
sudo setfacl -m g:dev-build:rwx,d:g:dev-build:rwx,d:m:rwx /run/dev-build-slot /var/cache/<project>-turbo
# initial policy: BUILD_SLOTS=1; CPUQuota=200%; MemoryHigh=12G; MemoryMax=16G
systemctl --user daemon-reload
```

Seed cache from an existing checkout: `cp -an <repo>/.turbo/cache/. /var/cache/<project>-turbo/` (NOT `cp -n` with glob — copies nothing silently).

## New-project checklist (order matters)

1. Machine setup above (skip cache-sharing + SCHED_IDLE entirely if runner is a dedicated box).
2. Install `/usr/local/lib/local-ci/buildslot.sh`; copy `cpu-limit.sh`; wire every heavy script through it. Prove cross-user exclusion, crash release, permission fail-closed, `BUILD_SCHED_IDLE=0`, and `BUILD_NO_CAP`.
3. Copy workflows; set runner labels + gate command; `BUILD_SCHED_IDLE: "0"` stays.
4. Copy `safe-merge.mjs` + deny hook + lefthook guard; rename check/job strings consistently in all three + workflow.
5. Write the workflow-contract test (adapt `ci-artifact-gate.test.mjs`); wire into the smoke.
6. DB suites: vitest factory (singleFork + factory timeouts), socket-only harness, then `pg-template` for initdb.
7. Prove: cold gate run, warm replay run (expect ~10x), post-merge main-gate replay. Record numbers.
