pipelines/PIPE_CONTROL_PLANE_2026-07-29.md
Lane: how the director runs ALL generation lanes autonomously. Status: PROPOSAL-TIER (lane-canon).
This doc invents no world canon. It is ENGINE per the reuse directive — game #2 inherits the whole
control plane and supplies its own registries. Every model/tool claim below is either WEB-VERIFIED
(source URL given) or REPO-CITED (file:line given) — nothing is asserted from memory.
**MY BUDGET AND SCHEDULING CLASS (the concurrency law, answered first): the orchestrator is
CPU-ONLY. 0 GB VRAM, ~2 GB RAM, ~1% of one core at steady state. Scheduling class: ALWAYS-ON.**
It never holds the GPU lease; it *issues* leases. This is deliberate — a control plane that competes
with UE for VRAM cannot arbitrate between UE and the asset lanes. Matches Stage W's ruled shape
("Watchers are CPU-only … zero GPU cycles", docs/5090_SETUP_RUNBOOK.md:~536).
---
| Job | Primary | Fallback | Licence | Source |
|---|---|---|---|---|
| Agent dispatch (author/critic/fix waves) | Claude Code headless claude -p --output-format stream-json --allowedTools --permission-mode | Claude Agent SDK (claude-agent-sdk, Python) — same loop, in-process | Anthropic commercial terms; tool, not an output-taint | https://code.claude.com/docs/en/headless · https://platform.claude.com/docs/en/agent-sdk/overview |
| GPU job server (image/audio/3D) | ComfyUI HTTP+WS: POST /prompt {prompt, client_id, prompt_id} · GET /history/{prompt_id} · GET /view?filename&subfolder&type · ws://host:port/ws?clientId= | direct per-model CLI in its own venv | GPL-3.0 — see the taint note below | verified in ComfyUI's own script_examples/websockets_api_example.py (raw.githubusercontent.com/comfyanonymous/ComfyUI/master/…) · https://github.com/comfyanonymous/ComfyUI |
| Trigger / restart / boot chain | Windows Task Scheduler (boot trigger, highest privileges, battery flags per D-11c) | manual python run_window.py | OS | docs/5090_SETUP_RUNBOOK.md Stage W, Stage 7.2 |
| GPU lease arbitration | nvidia-smi --query-gpu=memory.used,memory.total poll + one lease file | UE-side refusal (job declines when free VRAM < request) | — | Stage 5 VRAM table, docs/5090_SETUP_RUNBOOK.md:834-860 |
| Ledger / state transport | git (explicit paths only — never git add -A) | — | — | CLAUDE.md; MEMORY.md shared-tree-never-git-add-dash-A |
| Heartbeat shape | RUN_STATUS.json, modelled on Continuo's shipped window_runner (one-command, heartbeat, self-stopping, survives-Josh-unreachable) | — | — | docs/5090_SETUP_RUNBOOK.md:535 |
GPL-3.0 taint note (licence-law): GPL-3.0 binds ComfyUI's *code*. The orchestrator therefore calls
ComfyUI over HTTP only — never imports it, never vendors nodes into Source/Humanity, never ships
it. Generated PNG/WAV/GLB outputs are not derivative works of the generator; the taint that matters is
the weights licence of the model that produced them, which is why §3 makes generating_model +
model_licence mandatory columns on every artifact record.
Explicitly REJECTED: Prefect / Dagster / Airflow / Celery. A scheduler daemon is a second
always-on failure mode with its own DB, and the ruled shape is already proven (Task Scheduler + one
Python runner + a JSON heartbeat). Rejection recorded so a later wave does not re-litigate it.
The routing table is the committed docs/routing_table.json. It is benchmark-day-emitted: rows
below are the pre-flight state, and every switch after that is a ledger commit.
| Job class | Pin | Licence (verified) | Verdict |
|---|---|---|---|
| music / theme stems | ACE-Step 1.5 XL — three variants xl-base / xl-sft / xl-turbo (~4B, turbo ≈6× faster), native ComfyUI nodes | MIT, "legally compliant training data" | CONFIRMED — https://blog.comfy.org/p/ace-step-15-xl-commercial-grade-music (2026-04-17) · https://github.com/ace-step/ACE-Step-1.5 |
| bulk NPC TTS | Kokoro-82M | Apache-2.0 weights | CONFIRMED — https://huggingface.co/hexgrad/Kokoro-82M (repo-ruled pin, AUDIO_STACK/runbook 6c) |
| character motion / anim | ARDY (NVIDIA, real-time text-to-motion, SIGGRAPH 2026) | code Apache-2.0; weights NVIDIA Open Model License — commercial use permitted, NVIDIA claims no ownership of outputs | CONFIRMED — https://github.com/nv-tlabs/ardy · https://www.nvidia.com/en-us/agreements/enterprise-software/nvidia-open-model-agreement/ |
| motion (constrained/keyframed) | Kimodo (NVIDIA, kinematic motion diffusion, 2026-03-16, v1.1 2026-04-10) | code Apache-2.0; **weights split — NVIDIA Open Model License OR NVIDIA *R&D* Model License depending on the training source of the variant** | CONFIRMED-WITH-FLAG — https://github.com/nv-tlabs/kimodo. PER-VARIANT licence read is mandatory before first GPU hour; any R&D-licensed variant is previz-only |
| world / video generation | NVIDIA Cosmos 3 (2026-06-01, super/nano now, edge "coming soon") | not read | REAL, NOT ROUTED — https://nvidianews.nvidia.com/news/nvidia-launches-cosmos-3-the-open-frontier-foundation-model-for-physical-ai. No job class in the slice consumes it; the world-model lane owns the licence read |
| mesh (geometry) | TRELLIS.2 | repo-cited MIT-class code; textured path via nvdiffrast is NON-COMMERCIAL | REPO-VERIFIED (LOCAL_3D_ASSET_GEN.md §1.1 [VERIFIED]) — textured output is previz-only, never a ship path |
| mesh (alt) | Hunyuan3D-2.1 | Tencent Hunyuan Community License — Territory EXCLUDES the EU, UK and South Korea; MAU cap | CONFIRMED-TAINTED — https://github.com/Tencent-Hunyuan/Hunyuan3D-2.1/blob/main/LICENSE. Blocks a worldwide Steam ship. Routing row = previz-only until Josh rules on ship territory (§5) |
| concept image (Lanes P/G) | null — deliberately unpinned | — | RULED: the pick + licence read fold into benchmark-day pre-flight (D-3; REALM_ANALYSIS_ART_PIPELINE §8.5). The row ships with a null pin, never a guess |
| local triage / ranking | 7-8B now, 14B on measured noise (D-5); 14B pick open (D-4) | Apache-2.0/MIT tiers only (runbook 5.3) | REPO-RULED, tier fixed, model open by design |
Leads adjudicated (confirm-or-kill, per the standing rule that no unverifiable name is adopted):
Cosmos 3 ✅ real · ARDY ✅ real · Kimodo ✅ real · ACE-Step 1.5 + its ComfyUI UI ✅ real · "XL SFT" ✅
real (xl-sft) · "XL Turbo" ✅ real (xl-turbo) · **"Excel Bass" ❌ KILLED as a name — it is a
transcription artifact of xl-base, the third real variant.** The corrected token is xl-base; the
mis-heard string never enters a config, a prompt, or a registry cell.
---
Environment lane (per D-1 containment). The orchestrator is **Windows-native, outside every
containment boundary** — not in WSL2, not in the Puget comfy_ui container, not in a per-model venv.
Reason: it must survive any lane's environment churn and must be able to restart the lanes it
supervises. It speaks to WSL2/container lanes over localhost HTTP only. This is the one lane where
D-1's fork does not apply, and saying so removes it from the D-1 time estimate.
Disk placement (per the RULED layout).
D:\pipe\ — venv, run_window.py, RUN_STATUS.json,the lease file, the live queue, the last 30 days of run artifacts.
E:\pipe_archive\ — rolled run logs, superseded captures, rejected outputs(kept, never deleted — a rejected asset is the QA gate's evidence).
Install order (all after Stage 4 "Claude Code signed in", before Stage 7's first soak):
1. python -m venv D:\pipe\.venv (Python 3.12 from Stage 3).
2. pip install requests websocket-client psutil — the entire third-party surface. (psutil is
already a runbook 7.1 item; it is listed here so the soak's memory signal is not silently absent.)
3. Optional: pip install claude-agent-sdk — only if the in-process loop beats subprocess claude -p
on the benchmark-day question in §6. Default is subprocess: fewer moving parts, and a crashed
agent cannot take the runner down with it.
4. Write D:\pipe\lanes.json (lane → endpoint, VRAM request, scheduling class) and the empty
routing_table.json. Both git-tracked in the canon repo, symlink-free copies on D:.
5. Register the two scheduled tasks: pipe_boot (boot trigger → Stage W chain → arm the runner) and
pipe_window (the dispatch loop). Battery flags per D-11c: measure first, then clear both.
6. **Firewall pre-authorization for the ComfyUI listener and the runner happens at Stage 6F, before
anything unattended runs.** An unacknowledged Defender dialog at 04:00 presents as a hung editor,
not an error — the single worst overnight signature, and it is the orchestrator's problem because
the orchestrator is what appears to have stalled.
Thursday-night download list — this lane: 0 GB. The control plane has no weights. Its Thursday
deliverable is instead the download manifest itself: one JSON row per artifact the other lanes
pull, carrying url, bytes, sha256, dest, licence, so an interrupted overnight pull is
*verifiable* rather than re-downloaded. Seed rows already pinned in the repo and inherited unchanged:
Qwen2.5-14B-Instruct-Q4_K_M.gguf ~9 GB (LAN-copy from the Ally, never re-download — sha256
pinned e47ad95d…c008, VERIFY after copy) and its Q5_K_M sibling ~10.3 GB (one HF pull), both
repo-cited at docs/5090_SETUP_RUNBOOK.md:~527. Every other lane's sizes are that lane's dossier to
supply; the manifest schema is mine, and a row with no bytes/sha256 is rejected at write time.
---
The dispatcher owns no schema of its own. It reads and writes the already-ratified assetgen block,
verified live in docs/registry_extensions.json on 7 registries:
`mesh_id_ref · mesh_pipeline_type · substrate_material_ref_path · mesh_tags · generation_status ·
generation_prompt_hash · last_generated_timestamp · regeneration_trigger · generation_tier ·
decay_bearing · decay_stage. The item-6/6-D columns (generation_tier, decay_bearing`,
decay_stage) have LANDED — the reservation is real, not pending.
A work order is a registry row, not a ticket. `(registry, RowName, canon_id, generation_tier,
decay_stage, presentation_tier_ref)` is the whole key. The dispatcher never invents an id, never
writes canon prose, and never writes a /Game/ path — it writes only the four state columns, through
the sanctioned writer, with docs/fidelity_baseline.json refreshed in the same commit (the
standing rule; a registry edit without --emit-baseline reds the gates).
Lifecycle, exactly as ratified (DR-2 §3): pending → in_progress (+ generation_prompt_hash set)
→ complete (+ ue_asset_path + last_generated_timestamp) → *reviewed* is a process gate, not a
state → *live* is the resolver returning non-placeholder. Rejection writes rejected and the id
stays on its placeholder. regeneration_required is set by a regeneration_trigger: a prompt-hash
change, a canon edit, a tier change (§6.3), or a decay_stage prompt change (§6-D D2).
Reproducibility. generation_prompt_hash = sha256(canonical_json(prompt_payload)) where the
payload includes the composed prompt, the model id + revision, the seed, the sampler/step config,
generation_tier, decay_stage, and presentation_tier_ref. Same hash ⇒ same asset, or the pipeline
is lying. The hash is what makes §6.3 self-enforcing: a realm surface accidentally generated at region
tier is caught by the state machine, not by a human noticing.
Counted across registries/**/*.csv: **831 rows carry generation_status, and 796 of them are the
EMPTY STRING** — Antagonist 64, Boss 281, Character 164, Creature 150, Equipment 1, Familiar 22,
Vril_Site 42, Weapon 72. Only T0_Theme_Registry (12) and T0_Voice_Registry (9) actually read
pending. Empty string is outside the ratified five-value enum. A dispatcher whose scan is
WHERE generation_status == 'pending' therefore returns **21 work orders across the entire mesh
surface and reports the queue clean** — the exact "a search that CANNOT match reports zero" class in
MEMORY.md, reproduced inside the control plane.
Two more, same family: **T0_SFX_Registry (30 rows) has ue_sound_asset_path but NO
generation_status column at all** — and SFX is DR-2 §6 Batch 2, the *handshake exit*. And
T0_Scene_Spec_Registry (16 rows) carries generation_prompt_hash with no status column.
Ruling applied (creative-within-vision; the path is shown, not asked):
never treated as complete, never as pending, never skipped silently.
pending on all 796 rows through the sanctioned writer, baselinerefreshed in the same commit. Zero GPU hours, zero canon content, fully reversible.
generation_status + regeneration_trigger + last_generated_timestamp are added to T0_SFX_Registry and T0_Scene_Spec_Registry in the same Batch-0 landing.
rows in a registry that has assetgen columns, the run exits non-zero. A queue that cannot
match reports zero and looks exactly like a finished night.
`{canon_id, registry, lane, generating_model, model_revision, model_licence, prompt_hash, seed,
generation_tier, decay_stage, presentation_tier_ref, out_path, sha256, bytes, qa_verdict,
qa_evidence[], previz_only:bool}. model_licence and previz_only` are mandatory, non-null —
this is the licence law made mechanical. A previz_only:true artifact is refused by the importer,
so a textured TRELLIS output or an R&D-licensed Kimodo clip cannot reach a ship path by accident.
Formats: image PNG (16-bit where the lane supports it) + the ComfyUI workflow JSON beside it ·
audio WAV 48k/24-bit (stems separate) · mesh GLB + the source .blend/.ply · motion FBX or the
model's native rig format · everything else as the lane's native + a sidecar record. UE ingest is
the existing idempotent importer (Tools/import_audio_assets.py, replace_existing=True) extended
per class — path takeover is the ratified default (DR-2 §7 item 3), manifest re-point reserved
for licensed/MetaHuman off-convention assets.
---
scan → batch → schedule → run → QA → flip or fall back — one pass per cycle, resumable, idempotent.
1. SCAN. Read the live CSVs (never the frozen xlsx). Emit work orders for pending and
regeneration_required. Fail loud on UNENROLLED. Care gate first: a row whose care tier makes
it §17.1 reference-built is *never* emitted as a raw-generation order (DR-2 §7 item 4) — real
living-heritage forms and living-tradition realm iconography go to Lane R/P, never Lane G.
2. BATCH. Group by lane and by model, so one model load serves many rows. Cap batch wall-clock so
a batch always fits inside its window.
3. SCHEDULE by concurrency class, arbitrated by ONE lease file plus an nvidia-smi free-VRAM
precondition:
Runs when a human or a director session is live.
never co-resident**: a resident 14B (9 GB) plus a Hunyuan combined run (29 GB) does not fit on 32 GB,
and an OOM from our own sloppiness would falsely fire HARDWARE_DECISION's upgrade trigger #1.
4. RUN. Model lanes → ComfyUI /prompt + /ws. Agent lanes → claude -p with --allowedTools
pre-approved and --permission-mode set, so an unattended run never blocks on a prompt.
Model tier is set EXPLICITLY on every dispatch — nothing inherits the director's session model
(the standing rule; a Fable fan-out once cost ~20% of a weekly limit).
5. QA GATE (§4.2). 6. FLIP complete, or rejected + fallback + flag.
| Lane | Gate | Verdict source |
|---|---|---|
| image / concept | rubric board bands (band_source, tier_applicability), image critics read the PNGs; the realm band grades the ten generation_tier='realm' surfaces, never the region floor | QA_WATCHING_PROGRAM §4.4 |
| mesh | resolver returns non-placeholder · mesh_id_ref resolves (QT-8) · material-identity + capture diff | DR-2 §2 |
| audio (SFX/VO/music) | cue-fired telemetry non-zero (QT-10) · muted/wired fixture (QT-AU) · §17.12 gender-lock (QT-9) · no sampling of consecrated performance; reference-composition permitted | DR-2 §2, §7 item 6 sourcing rule |
| cinematic | framed scene plays for FORK_CH02_A; critics read the shots | DR-2 §2 |
| all canon-touching text | reveal-discipline gate · care/§17.1 collective-care validator · entailment-verify · the full run_gates.py suite unpiped | CLAUDE.md, gates roster |
| every gate | must-fire + must-not-fire fixtures, --self-test on every real invocation, exit 2 if a ruler rotted; critics read-only on the shared tree | AI_QA_LOOP §4.2 |
The director re-read gate binds the whole plane: before any play-quality claim enters a commit
message, STATUS.md, a ledger note, or a report to Josh, the DIRECTOR opens the deciding frames from
the newest session dir via last_run.json — never a path an agent typed. On mismatch the claim is
discarded, not negotiated (QA_WATCHING §2.4).
Promote / demote — measured survival, never vibes. Each routing row carries
{pin, fallback, pinned_on, benchmark_id, rolling_reject_rate, n}.
and a QA-survival delta outside noise. Quality is protected by the BAR, not the author tier.
the row swaps to fallback, the run continues, and a ledger entry + a flag are written. Autonomy
means the night does not stop; honesty means the swap is never silent.
with no record.
RUN_STATUS.json is written every 30 s: `{state, lane, batch_id, orders_done/total, lease_holder,
vram_used, started_at, last_beat, last_error, next_action}`. A beat older than 10 minutes with a live
process = a stall record, not a crash — the loudest class, because Stage 6F's firewall dialog and
a hung editor look identical from outside. Stage W's boot chain (repo state → task arming → service
→ post-outage path) re-arms the runner on every boot with zero human touches; the pull-the-plug
rehearsal is the acceptance test. Runs are self-stopping: a hard wall-clock ceiling per window, so
a runaway lane cannot eat the next day's window.
is a deterministic gate or a rubric band — asset batches, triage, gates, regression, index rebuilds,
soak. Remote reach is Tailscale (D-19, RULED, a pre-departure gate) + RustDesk.
contested-finding adjudication, any care-tier or hard-line ruling, the final integration pass.
Josh-authorized sensitive edits apply at DIRECTOR level — a subagent writing a real user ruling
into canon flags as fabricated authority every time (MEMORY.md).
Surfaces: the ledger entry per landing · choice boards (realm art, the director-led
accurate/enriched/surrounding options) · threshold-crossing flags only — a licence taint that would
bind a ship path, a care/hard-line judgement above the delegated band, a build-space meta-collapse
signal, a hardware-suspect stop, a budget/window overrun, a Josh-minimum item from §5.
Never surfaces: routine pass/fail, retries, per-order status flips, model swaps *inside* the
pinned roster, batch scheduling, anything a gate already decided. The care doctrine is delegated:
the loop RULES above the §17 floor after a devil's-advocate pass calibrated against over-conservatism.
Care-tier inflation is a defect. Josh is the BACKSTOP, from a real playthrough — not a queue.
---
1. Ship-territory ruling on Hunyuan3D-2.1. Its licence excludes the EU, UK and South Korea. That
is a business decision about where Humanity Forgotten ships, not a technical pick. Until ruled, the
routing row stays previz-only. (A brief, not a bare question — the alternatives are: drop it and
stand on TRELLIS geometry; accept previz-only; or accept a territory-limited ship. Recommendation:
drop it from the ship path — the geometry leg is already covered and a worldwide Steam release
is worth more than one alternate mesh backend.)
2. Credentialed downloads — any HF-gated weights needing an account token. Never pasted into a
session; Josh pulls, or supplies the token through his own environment.
3. Claude Code sign-in on the new box (already a walkthrough step; the on-box session owns
everything after it).
4. The Puget burn-in / benchmark sheet ask to the rep — the only pre-arrival thermal/power
baseline for this exact machine, and the orchestrator's window-sizing math wants it.
5. Choice-board rulings when the realm art program surfaces boards. Everything else in this lane
is delegated by standing protocol.
Not Josh's: D-3/D-4/D-5/D-6 picks (director-ruled on benchmark-day evidence), lane scheduling, model
promote/demote inside the roster, retries, the Batch-0 backfill.
---
1. Real free VRAM under a live UE editor — the 32 GB budget assumes the iGPU rule held (monitors
on the motherboard, 5090 headless). Measure before any lane's ceiling is trusted; the 29 GB fit is
what the whole hardware decision turns on.
2. Wall-clock per order per lane at the pinned settings → the batch cap and the window arithmetic.
Without this, "overnight" is a hope.
3. Cold-start cost of a model load — decides whether batching by model actually pays, and how big
a batch has to be before it does.
4. claude -p subprocess vs in-process Agent SDK: startup overhead, crash isolation, and whether
a dead agent can take the runner with it. Default stays subprocess unless the SDK wins clearly.
5. The three unsourced VRAM estimates (7-8B ≈5 GB, 3-4B ≈2.5 GB, 0.6-1.7B ≈1 GB) — relabelled as
operator estimates in the runbook. Replace with observations.
6. QA reject rate per lane at the pinned model — this is the *baseline* the demote rule measures
against. Without a measured baseline the demote threshold is arbitrary.
7. Does the empty-string backfill hold? Re-scan after Batch 0: 831 enrolled, 0 UNENROLLED, and the
vacuity guard fires correctly on a deliberately-emptied fixture.
8. Licence re-check, GPU-free, first — the ruled pre-flight. Re-read every pinned model's licence
on benchmark day before a single GPU hour, and record the read date in the routing row.
9. Heartbeat stall detection — kill the runner mid-batch and confirm the stall record opens and
the boot chain re-arms it. A watcher that has never been proven to fire is not armed.
---
Josh, 2026-08-05, verbatim: "What about their pipelines?" The comparator program had studied the
teachers' outcomes only. This addendum studies their production methods for the domain this
dossier owns — how content spaces are DERIVED, scheduled, validated and shipped at scale — and rules
each technique ADOPT (with the route) or NO-ADOPT (with the reason). Scope: WoW itemization
and faction data models, Diablo IV itemization, Fortnite/Epic live tooling, Pokemon creature content
at franchise scale. Zone/region production lands on PIPE_ART (same addendum, other domain);
rig-archetype reuse is ROUTED to PIPE_ANIMATION and deliberately NOT written there by this pass.
Source tiers used below, declared: PRIMARY = vendor/official documentation or an official dev
blog · COMMUNITY-DOC = open-source schema definitions or emulator documentation of shipped data
(reverse-engineered, verifiable by reading the files) · SECONDARY = press/conference write-up of a
talk whose slides I could not read verbatim. Nothing below is asserted from memory.
| Fact | Evidence | Tier |
|---|---|---|
RandPropPoints carries Epic[5], Superior[5], Good[5] (plus float twins EpicF/SuperiorF/GoodF) — a quality x slot-budget-bucket matrix, one row per level band. VERIFIED BY DIRECT FETCH 2026-08-05: the three 5-wide arrays and their float twins are confirmed verbatim in the definition. Precision note: a .dbd defines COLUMNS, not row semantics — "one row per item level" is the well-known runtime meaning of the ID, not something the definition file itself states. The adoption (allocation/magnitude split) does not depend on it | wowdev/WoWDBDefs -> definitions/RandPropPoints.dbd (raw.githubusercontent.com/wowdev/WoWDBDefs/master/definitions/RandPropPoints.dbd) | COMMUNITY-DOC |
ItemDamageOneHand is one row per ItemLevel with Quality[7] — weapon damage is a curve read, not a per-weapon number | definitions/ItemDamageOneHand.dbd, same repo | COMMUNITY-DOC |
The per-item record (Item-sparse) carries ItemStatType[10], ItemStatValue[10], ItemScalingValue[10], ScalingStatDistributionID, InventoryType, Delay — the item row names which axes it spends on and in what proportion; magnitude comes from the shared tables above | definitions/Item-sparse.dbd, same repo | COMMUNITY-DOC |
What it teaches ours. This is the same claim our itemization matrix makes (items DERIVE, never
hand-listed) but with the split drawn one notch sharper than we drew it: they separate allocation
(authored, per item, a vector of stat types plus proportions) from magnitude (shared, per level x
quality x slot class, one table for the whole game). Our T0_Item_Derivation_Rule.derived_property_map
currently has to carry both. ADOPT — routed: mint a budget-curve table keyed
(mastery_tier 1-12 x rarity_grade x slot_class) and have derived_property_map reference it, so a
balance change is one curve edit rather than N rule edits. Our existing correspondences make the
mapping cheap: rarity grades map to quality, the twelve mastery levels map to the item-level band, and
T0_Equip_Slot_Registry's 32 rows over four declared axes map to InventoryType. NO-ADOPT: shipping
the tables as client-side binary DB2 — our cook path is CSV to registry to cook, and the format is not
the lesson; the split is.
loot_template columns, verbatim: Entry, Item, Reference, Chance, QuestRequired,
LootMode, GroupId, MinCount, MaxCount, Comment. Reference points at
reference_loot_template.entry and splices that template's entries into the current one (self-
reference is documented as a crash). GroupId makes a set mutually exclusive — only one item from a
group drops; if the group's chances sum to 100 a drop is guaranteed, below 100 an empty result is
possible; a referenced template can itself compete inside a group.
Source: https://www.azerothcore.org/wiki/loot_template — tier COMMUNITY-DOC.
What it teaches ours. Our T0_RNG_Drop_Table header is
`drop_id, drop_name, drop_class, linked_entity_id, linked_entity_type, base_rate_mean,
sigma_floor_rolls, sigma_ceiling_rolls, reset_condition, integrity_band_modifier, chapter_gate_min,
chapter_gate_max, mastery_tier_gate, tier_classification, pipeline_consumer, populated_from, notes,
extensions, rarity_class, derivation_rule_ref` — there is no reference column and no group column,
so every creature's table must be enumerated in full and a region's shared common pool cannot be
authored once. ADOPT — routed: add reference_drop_id (with a self-reference guard in
harness/check_drop_seed_join.py) and group_id plus a group-sum check (sum at or above 100 means
guaranteed; below 100 means an empty result is a DECLARED outcome, never an accident). This is the
single highest-leverage schema add found in this pass: it converts drop authoring from
O(creatures x items) to O(pools) + O(creatures).
| Fact | Evidence | Tier |
|---|---|---|
| Greater Affixes are "1.5x more powerful versions of normal affixes", appear only on Ancestral Legendary and Unique items, and cannot be enchanted in — they are only discovered | Blizzard, *Galvanize your Legend in Season 4: Loot Reborn* (news.blizzard.com/en-us/article/24077223) | PRIMARY |
| Affix counts were reduced (3 on Legendary, 2 on Rare) while individual affixes were made more effective and the pool was condensed; conditional affixes were replaced with flat ones | same | PRIMARY |
| Tempering Manuals each hold a small number of affixes across six categories — Weapons, Offensive, Defensive, Mobility, Utility, Resource; Ancestral items could take two tempered affixes from different categories | same | PRIMARY |
| Masterworking upgrades one equipped affix massively every 4th tier | same | PRIMARY |
| Legendary drops from enemies over level 95 are always 925 Item Power — the magnitude axis is deliberately flattened at the top of the curve | same | PRIMARY |
| The system was later corrected in data, not rebuilt: tempering became player-selected rather than random, items were capped at one tempered affix, and temper charges became restorable indefinitely | Blizzard, *Sanctuary Ignites with Itemization & Systems Changes* (news.blizzard.com/en-us/article/24243142) | PRIMARY |
What it teaches ours. Four transfers, each already load-bearing somewhere in our stack:
1. A rarity grade can be a derived multiplier over an existing affix row, not a new row. Greater
Affixes cost one column and one rule, and they doubled the perceived item space. **ADOPT —
routed** to T0_Item_Derivation_Rule as a materialization policy (DERIVED_MULTIPLIER) so our
ratified rarity ramp gains grade depth without minting rows. This composes with the standing law
that LEGENDARY and MYTHIC are RARITY GRADES and never tier names.
2. Affix pools are category-keyed closed vocabularies — exactly the shape of
T0_Item_Axis_Registry (vocabulary_registry / vocabulary_column / closed_vocabulary). Their
six categories are evidence that a small number of orthogonal categories, each with a shallow
pool, out-reads one long flat pool. ADOPT as a design constraint on the axis registry: prefer
more axes with short vocabularies over one long vocabulary; the three NONE_YET axes should be
filled as categories, not as lists.
3. Flatten the magnitude axis at the top so variety carries the interest (the fixed 925). This is
the mechanism our own AAAAA balance rule (OP allowed, meta-collapse banned) has been asserting
without a mechanism. ADOPT — routed to the build-space sweep as an explicit end-of-curve rule.
4. Their correction arc is the argument for keeping derivation editable in data. Random to chosen
tempering, and two to one tempered affix, shipped as data and rule changes. Our derivation rules
living in a registry rather than in code is the same bet, now with a comparator's receipt.
NO-ADOPT: the seasonal wipe and ladder cadence that frames all of the above. We are a single-player
narrative RPG with no seasons; the item-space lessons transfer, the cadence that motivated them does not.
Faction.db2 columns, verbatim from the definition: ID, ReputationIndex, ReputationRaceMask[4]
(64-bit), ReputationClassMask[4], ReputationBase[4], ReputationMax[4], ReputationFlags[4],
ParentFactionID, ParentFactionMod[2], ParentFactionCap[2], Expansion, FriendshipRepID,
Flags, ParagonFactionID, RenownFactionID, RenownCurrencyID, Name_lang, Description_lang.
Source: wowdev/WoWDBDefs -> definitions/Faction.dbd — tier COMMUNITY-DOC.
Our T0_Faction_Registry header is `faction_id, faction_name, kind, region_ref, chapter_ref,
relationship_type, standing_on_arrival, arrival_note, web_ally_refs, web_rival_refs, web_trade_refs,
improve_event_classes, degrade_event_classes, never_target, joinable, questline_ref, cast_token_count,
ladder_ref, reveal_gated, reveal_gate_anchor, source_ref, notes`. Three structural absences, and the
nine ruled bands are untouched by all three — the bands are canon, this is plumbing under them:
own race/class mask, its own base and its own cap. Our analog is not race and class — it is
integrity band, prior-chapter choices, and companion roster. standing_on_arrival plus
arrival_note can express one arrival; they cannot express "this faction starts you at Cooled if
you took the broker's contract in Ch 9." ADOPT — routed: a small faction_arrival_condition
table (faction x predicate to band) reusing docs/CONDITION_EXPRESSION_GRAMMAR.md, rather than
widening the registry.
ParentFactionID plus ParentFactionMod[2] plus ParentFactionCap[2] is the tooling answer to "help the village, the region notices — but only so
far." Our region pages are explicitly relational webs and web_ally_refs/web_rival_refs name the
edges, but no column carries a propagation coefficient or a propagation cap. ADOPT — routed:
add parent_faction_ref, parent_standing_mod, parent_standing_cap. This is the mechanism the
regions-are-relational-webs ruling has been describing in prose.
FriendshipRepID, ParagonFactionID, RenownFactionID are three alternate ladder systems keyed on the same table).
Our ladder_ref column exists and reads GLOBAL_DEFAULT_9BAND on every row — the column is right,
the roster is one. NO-ADOPT NOW, RECORDED: the nine bands are ruled canon and stay the default;
the finding is only that the column is already shaped for a second ladder if a faction ever earns
one (a joinable order with a rank track is the likely first case). Do not mint one speculatively.
| Fact | Evidence | Tier |
|---|---|---|
| Epic's UEFN content-cook fleet runs on HashiCorp Nomad at 20,000 concurrent cooks across 2,000+ hosts, having processed 14 million cooks in six months | HashiCorp, *Cooking with Nomad: Powering the Fortnite creator ecosystem* (hashicorp.com/en/resources/cooking-with-nomad-powering-the-fortnite-creator-ecosystem) | PRIMARY (vendor case study, Epic engineer quoted) |
| They use spread scheduling, not bin-packing, for resource-heavy cooks, plus node-class routing to send workload classes to matched instance types | same | PRIMARY |
| The job is a four-phase task lifecycle: pre-start downloads and validates input assets, main runs the containerized UE5 cook, post-start runs a monitor enforcing an SLA timeout, post-stop does crash analysis and cache sync | same | PRIMARY |
| Cooked output is rendered live back into the running UEFN editor session as the user works | same | PRIMARY |
| At scale they split into multiple ~500-node clusters on a consistent hash ring rather than federating one giant cluster | same | PRIMARY |
| Horde is "a set of services supporting workflows Epic Games uses to develop Fortnite, Unreal Engine, and other projects": Remote Execution (including Unreal Build Accelerator for C++), Build Automation/CI-CD for large Perforce repos, Test Automation (AutomationTool plus Gauntlet), Studio Analytics, an UnrealGameSync metadata server, and a mobile/console device manager | Epic, *Horde in Unreal Engine* (dev.epicgames.com/documentation/en-us/unreal-engine/horde-in-unreal-engine) | PRIMARY |
| A hotfix is a small piece of code replaced directly in a live game — usually CVars — with no download and no downtime, carrying things like item stat adjustments and boss/NPC health values | Epic, Fortnite documentation glossary (dev.epicgames.com/documentation/fortnite/hotfix) | PRIMARY |
What it teaches ours.
1. The four-phase job contract beats our order/lease shape and should extend it. We have a lease
and an order; they have validate-inputs-before-you-burn-the-GPU, a **separate watchdog task
holding the SLA, and a post-stop crash-analysis plus cache-sync hook**. Our §3 DR-2 rows and §4
autonomy contract already own retries and the heartbeat, but pre-start input validation and the
post-stop crash harvest are genuinely absent. ADOPT — routed into the DR-2 job contract as two
new mandatory phases; §6 benchmark question 9 (heartbeat stall detection) becomes the post-start
monitor's own must-fire test rather than a separate concern.
2. Spread-not-bin-pack has a single-GPU translation, and it is temporal. With one 5090 the
equivalent of "never co-locate two heavy cooks" is "never co-schedule two VRAM-heavy orders" —
which is exactly the C-14 exclusive-class ruling for UE cooks in
STACK_CONFLICT_ADJUDICATIONS_2026-07-29.md. ADOPT as corroboration: the ruling now has an
external source and a name, and node-class routing maps onto our routing table's job classes (the
concept we already built; the missing half is a per-class SCHEDULING hint, not just a model pin).
3. The cluster-split finding is NO-ADOPT (one box), but its reason is adoptable: the scheduler's
own coordination cost became the bottleneck before the workers did. Our analog is the
orchestrator's per-order bookkeeping as a batch grows. ADOPT — routed to §6 as a new
benchmark-day question: measure orchestrator overhead per order at batch sizes 1 / 20 / 200 and
confirm it stays flat, because "the control plane is CPU-only and about 1% of a core" is a
steady-state claim measured at small N.
4. The hotfix/CVar layer is the one live-ops capability we have no analog for. Balance numbers a
designer changes often — drop rates (base_rate_mean, the sigma floor and ceiling), standing band
thresholds, damage coefficients — should be readable from a data layer replaceable without a cook.
ADOPT — routed as a scoped question to the engine lane (not built here): which of our
registry-derived values are cooked constants today, and which could be runtime-read? The honest
note is that we ship single-player and do not NEED zero-downtime; the win is **iteration speed for
the AI QA loop**, which currently pays a cook for a number change.
5. "Rendered live back into the running editor session" is the return path our generation lanes
lack: plates, meshes and audio land in folders and wait for an import step. **ADOPT — stretch,
routed** to docs/ASSET_DROPIN_CONTRACT.md, flagged honestly as convenience, not correctness.
*The Data Building Pipeline of 'Overwatch'*, David Clyde (Senior Software Engineer, Blizzard),
GDC 2017 — a proprietary source-content revision system plus a matching data conversion pipeline,
built to sustain monthly content updates (new maps, heroes, modes) on a proprietary engine shipping
simultaneously on three platforms. The stated pipeline goals: pull the latest build and content in
under five minutes; changes seen instantly in engine; local changes fully affecting the game
immediately; share changes with others before committing them; and **never commit content with a
known issue**.
Sources: session listing gdcvault.com/play/1024444/The-Data-Building-Pipeline-of and the deck at
media.gdcvault.com/gdc2017/Presentations/Clyde_David_TheDataBuilding.pdf.
CAVEAT, declared: that deck is an image-only PDF and could not be read verbatim in this pass; the
goal bullets above are reported from the session and deck write-up, tier SECONDARY. Anyone who
upgrades this to PRIMARY should read the slides and correct this paragraph in place.
What it teaches ours. "Never commit content with a known issue" is our gate suite's whole thesis
and we already run it pre-commit, so that goal is CORROBORATION, not a gap. The goal we do not
have is "share changes with others before committing them" — a preview channel for un-landed
content. Our review boards publish from landed state. ADOPT — routed to the boards/publish lane as
a staging surface, which is also the honest answer to the phone-first board law when a wave wants
Josh's eye on something before it lands.
| Fact | Evidence | Tier |
|---|---|---|
| CEDEC 2022, GAME FREAK (Keiichi Maezawa): the Pokemon MODEL PRODUCTION ENVIRONMENT for making two titles at once — covering how assets were developed across the series, how models are stored and tweaked from game to game, and the shader and effect usage the updated pipeline supports | GoNintendo talk write-up (gonintendo.com/contents/8412) and the archived presentation (archive.org/details/cedec-2022-game-freak-presentation-2) | SECONDARY |
| Animation is reused across body-type "moulds" — snake-like, dragon-like, dog or cat-like — copying motion between structurally similar creatures | same | SECONDARY |
| The two titles ran concurrently off that one environment: Legends Arceus began development in fall 2018 (about three years), Scarlet/Violet began as Gen 8 finished (about three years) | Nintendo Wire (nintendowire.com/news/2022/08/26/) and GoNintendo, same talk | SECONDARY |
| Per-species data is a fixed-schema record per species AND per form — base stats, types, abilities, species permissions — loaded from a resource table, not authored per creature in code | kwsch/PKHeX open source: PKHeX.Core/PersonalInfo/ (PersonalInfo.cs, PersonalTable.cs, Info/, Table/) | COMMUNITY-DOC |
What it teaches ours.
1. One table, N rows, forms as rows — never bespoke per-creature data. This validates our
per-entity registries directly, and it argues that our tier and variant bands should be **form
rows against one species row, not new entity rows. ADOPT as a constraint** on the creature and
ability variant work: GAP-185's per-tier variant sets are exactly this shape — variants are forms.
2. Rig archetypes are the unit of animation reuse. Their moulds are the reason a thousand-creature
roster is animatable at all. ROUTED, NOT WRITTEN HERE: our creature roster should carry a
body_mould_ref so animation sets are authored per mould and inherited per creature. That belongs
to PIPE_ANIMATION and is left for that dossier's owner rather than edited across lanes by this pass.
3. One shared asset environment is why two titles ship in parallel. External evidence for the
engine-agnostic reuse-machine directive: the ENVIRONMENT, not the title, is the durable artifact.
Our ENGINE-vs-CANON declaration on every gate and tool is the same bet.
CONTESTED — adopt nothing from it, recorded so a later pass does not re-litigate: whether Sword
and Shield's models were rebuilt or reused is a DISPUTED public record (Game Freak stated in 2019 that
models were being remade for Switch and that content was cut to protect quality; datamining claims
asserted reuse). Both readings appear only in press coverage of interviews and in community analysis —
tier SECONDARY at best, and mutually contradictory. The pipeline lesson we take (one shared model
environment; archetype-based animation reuse) comes from the CEDEC talk and does not depend on
resolving that dispute.
| # | Technique | Teacher | Verdict | Route |
|---|---|---|---|---|
| C-1 | Budget-curve table keyed (tier x grade x slot); the item row holds allocation only | WoW | ADOPT | mint the curve table; T0_Item_Derivation_Rule.derived_property_map references it |
| C-2 | reference_drop_id + group_id on drop tables (compose pools; one-of-group rolls) | WoW-derived servers | ADOPT — highest leverage | T0_RNG_Drop_Table schema add; self-reference guard and group-sum check in harness/check_drop_seed_join.py |
| C-3 | Rarity grade as a derived multiplier over an existing affix row | D4 (Greater Affixes, 1.5x) | ADOPT | materialization_policy = DERIVED_MULTIPLIER |
| C-4 | Many short category-keyed vocabularies over one long flat pool | D4 (six temper categories) | ADOPT as constraint | T0_Item_Axis_Registry, including the three NONE_YET axes |
| C-5 | Flatten the magnitude axis at the top of the curve | D4 (fixed 925 Item Power) | ADOPT | build-space sweep end-of-curve rule |
| C-6 | Per-faction arrival conditions (their per-group base and cap vector) | WoW Faction.db2 | ADOPT | faction_arrival_condition table on the existing condition grammar |
| C-7 | Standing propagation up a faction tree with a modifier and a cap | WoW ParentFactionID/Mod/Cap | ADOPT | T0_Faction_Registry + docs/FACTION_STANDING_WIRING_SPEC.md |
| C-8 | Alternate ladder curves per faction | WoW Friendship/Paragon/Renown | NO-ADOPT NOW | column already shaped; nine bands stay canon; revisit only for a ranked joinable order |
| C-9 | Four-phase job contract (validate-in, main, SLA watchdog, crash + cache) | Epic / Nomad | ADOPT | DR-2 job contract, §3 |
| C-10 | Per-class scheduling hints; exclusive class for heavy orders | Epic (spread, node-class) | CORROBORATES C-14 | routing table gains a scheduling-class column |
| C-11 | Measure control-plane overhead as batch N grows | Epic (cluster split) | ADOPT | new §6 benchmark-day question |
| C-12 | Hotfix/CVar layer for balance numbers | Fortnite | ADOPT — scoped question | engine lane: which registry-derived values are cooked constants |
| C-13 | Generated output returned into the running editor session | UEFN | ADOPT — stretch | docs/ASSET_DROPIN_CONTRACT.md |
| C-14 | Preview and share content BEFORE committing | Overwatch | ADOPT | boards/publish lane staging surface |
| C-15 | Species and form as rows on one fixed schema | Pokemon (PersonalInfo) | ADOPT as constraint | variants are FORMS, not new entities (GAP-185) |
| C-16 | Rig-archetype (mould) animation inheritance | Pokemon (CEDEC 2022) | ADOPT — routed elsewhere | PIPE_ANIMATION; body_mould_ref on the creature roster |
| C-17 | Client-side binary table format | WoW DB2 | NO-ADOPT | the format is not the lesson; the allocation/magnitude split is |
| C-18 | Seasonal wipe and ladder cadence | D4 | NO-ADOPT | single-player narrative RPG; no seasons |
| C-19 | Multi-cluster federation at 500 nodes | Epic | NO-ADOPT | one box; only the coordination-cost reason transfers (C-11) |
---
Provenance. Josh, 2026-08-05, verbatim: *"What about their pipelines?"* — the comparator program
(docs/proposals/COMPARATOR_LENS_PROGRAM.md) had only ever studied the teachers' OUTCOMES. This addendum
studies how they BUILD. Lands here per the pipe-dossiers-bind law (commit 732f9bff). Domain: open world ·
quests · world building. The world-BUILDING half (terrain, density, procedural placement) lands on
GEODATA_TERRAIN_CHAIN.md §8; this section owns **authoring tooling, quest data model, world population,
and production cadence**.
Standing gap named (gap-hunter step): no PIPE_* dossier owns quests / open-world production / world
population. The eight dossiers are art · 3D · animation · video · audio-music · voice · website ·
control-plane — all *asset* lanes. The largest content surface in the game (79 nodes of quest and world
content) has no pipeline dossier of its own. This addendum is placed in the two closest owners rather than
minting a ninth dossier mid-wave; minting PIPE_WORLD_QUEST is boarded, not done.
Source tiers used below. FIRST-PARTY = the developer's own published tooling documentation or their
own talk page. TALK-RECAP = a named journalist/practitioner recap of a named GDC/CEDEC session (speaker
and session named). REVERSE-ENGINEERED = community documentation of shipped data files, with no
developer statement behind it. Nothing below is asserted from memory; every row carries its URL.
| # | Fact (paraphrased) | Tier · source |
|---|---|---|
| C1 | A quest is a directed graph carrying a signal, not a linear script. The signal starts at a Start block, travels the connections, and fires blocks as it passes. It can be diverted down multiple connections and be in two or more places at once | FIRST-PARTY — REDkit Quest Editor |
| C2 | The composition unit is a phase — a subgraph with unlimited named In/Out sockets (socketID), nestable without limit. When the signal passes an Out, every node still alive inside that phase dies. That single rule is what makes a 100-hour quest graph tractable: scope-exit is structural, not bookkeeping. VERIFIED BY DIRECT FETCH 2026-08-05, and the citation is tightened: the scope-exit sentence lives ONLY on the HOW-TO page — verbatim, *"Once the signal passes this all other nodes inside the phase will die."* The Quest Editor page carries the signal model (Start block, signal "can be in two or more places simultaneously", End block "kills any other signal that may still be going inside") but NOT the phase-level rule. Cite the HOW-TO page for scope-exit; cite the Quest Editor page for the signal model | FIRST-PARTY — HOW-TO: Use quest nodes (scope-exit) · Quest Editor (signal model) |
| C3 | World state is a Facts DataBase — named runtime variables, filterable, some with expiry timeframes. Quest conditions read it; quest blocks write it. One surface, not per-quest bespoke state | FIRST-PARTY — TOOL: Quests Debugger |
| C4 | The debugger is the throughput tool. It loads the questline tree from the last save, highlights the live signal on the graph, and lets a designer right-click any node's pin and continue execution from there — arbitrary phase-jump testing without replaying to that point. The Facts DB is a live tab beside it | FIRST-PARTY — same as C3 |
| C5 | NPC population is authored by two deliberately different systems. Encounters are area-bound to one world and carry the large stuff — city crowds, village communities, herds, monster nests, patrols, quest group fights. Communities are NOT bound to a world and carry quest-important NPCs with many phases and small enemy groups | FIRST-PARTY — HOW-TO: Create a monster encounter |
| C6 | Encounter content is a spawn tree: TopInitializerList nodes apply properties to a whole branch; green SpawnEntries nodes spawn the actual NPCs. Density and composition are branch properties, not per-instance placement | FIRST-PARTY (REDkit encounter docs) — HOW-TO: Find and debug encounters |
| C7 | The Community editor is literally two spreadsheets. *Spawnset* columns: Entry ID · Entity Template · Appearances · Story Phase Name · Timetable Name · Entity Spawn Tags · Spawn Point Tags · Spawn Delay · Start In AP · Spawn Strategy (the player-radius that triggers spawn/despawn) · Quantity · Respawn Delay · Don't Respawn · Despawn Point Tags · Always Spawned · Is Background · Mappin Tag · Mappin Type · Initializers (script actions fired on spawn, with no quest scripting) · Is Hidden Spawn. *Timetables* columns: Name · Time (intervals down to the minute) · Layer Name · Category · Weight · AP Tags | FIRST-PARTY — Community editor |
| C8 | The join is a naming convention. The Quest Editor enters a Story Phase (q109_sneaking_garden — quest number, underscore, description); every Spawnset row whose Story Phase Name matches activates; its Timetable Name selects a timetable; the timetable's Layer Name plus Category are matched against Action Points in the world; AP Tags narrow the match, Weight randomizes among candidates | FIRST-PARTY — same as C7 |
| C9 | An Action Point is an entity of class CActionPoint with a CActionPointComponent whose jobTreeRes points at a JobTree resource. The JobTree holds: Valid Categories (the array the community timetables match on), Selection Mode SM_SEQUENCE or SM_RANDOM, iteration count, which item goes in which hand, and enter/child/leave animation nodes whose category names index globals/animations.csv | FIRST-PARTY — Actionpoints |
| C10 | The cinematic-dialogue generator — the single most transferable fact in this research. The Witcher 3 shipped over 35 hours of dialogue content against only 2.5 hours of hand-made cutscenes, across 1,463 systemic dialogues, with a deliberately small animation team. A generator takes three inputs — actor data, cinematic instructions, and analysis of the VO audio files — and emits camera placement and cuts (obeying the 180-degree rule), body and idle animation (selected from ~35 idle variations per character type), gesture markers, facial animation, look-ats, and establishing shots. Designers re-roll it until they like the result, then hand-tweak. ~2,400 dialogue animations were re-used across body types via additive conversion, bone masking and blend-weight adjustment — human animations were shared across characters "as varied as werewolves". SYNTHESIZER CORRECTION 2026-08-05: the researcher return stated "all 1,463 were touched by hand". The source does not support that and partly contradicts it — it says the generator left *"some less-important dialogues hardly touched"*. The verified shape is generator output as the baseline for 100% of dialogues, with hand-polish TIERED by narrative importance, not universal hand-polish. Re-verified by direct fetch this pass | TALK-RECAP of GDC 2016 *"Behind the Scenes of Cinematic Dialogues in 'The Witcher 3: Wild Hunt'"* — gameanim.com breakdown · PC Gamer · GDC Vault session |
| C11 | Production rules the quest team actually ran: a writing cap of ~15 lines of dialogue per quest, broken deliberately three times (senior writer Kuba Szamalek); and content-first world sizing — *"the quest content dictated the size of the world, not the other way around"* (level designer Miles Tost), with the quest team deciding how many quests a region could carry and the world resized to match. Placement was entirely hand-crafted; procedural generation was rejected | TALK-RECAP / interview — Kotaku |
| C12 | Sasko's GDC 2023 production discipline, the parts that are pipeline and not taste: cut repeated exposition (multiple characters re-summarizing the same events); isolate signal from noise (critical information gets a distraction-free moment, filler gets the walk-and-talk); delayed consequences must be visible — subtle ones go unnoticed and the authoring spend is wasted; and do not overdesign — *"a game is not a life simulation, it is entertainment"* | TALK-RECAP — Game Developer, 10 key takeaways · GDC Vault session |
WHAT IT TEACHES OURS.
1. Our quest data model is already the right shape; the missing half is the RUNTIME and the DEBUGGER.
registries/T0_Quest_Definition_Registry [ACTIVE v1.0] (16 rows) already carries quest_beat_structure,
branching_logic, objectives_array, completion_condition, fail_state, progression_guarantee,
state_writes, fork_option_refs. That is CDPR's graph expressed as rows. What we do not have is
(a) a signal executor with phase scope-exit (C2 — the rule that kills every live node when a phase
exits; without it, branch cleanup becomes per-quest bookkeeping and 79 nodes of content will rot), and
(b) phase-jump testing (C4). Every hour the AI QA loop spends replaying to reach a quest state is an
hour CDPR's designers did not spend. **A --start-at-phase entry point in the quest runtime is a
QA-throughput multiplier, not a nicety.**
2. state_writes should resolve to ONE facts surface, with expiry. C3 is the shape: named facts,
filterable, some time-boxed. We have harness/condition_expr.py plus docs/CONDITION_EXPRESSION_GRAMMAR.md
for the read side; the write side is currently a column of prose per quest row. One surface, or the
world_memory_write and irreversible_choice columns drift apart from it.
3. The Community spreadsheet VALIDATES the registry-as-authoring-surface bet at AAA scale. The living
world of The Witcher 3 — the thing every review named its best feature — was authored in **two
spreadsheets joined by a naming convention** (C7, C8). Our whole architecture is registries joined by id
conventions. This is the strongest external evidence the project has that the approach ships.
4. ambient_population_band_default should become a TIMETABLE, not a scalar.
registries/T0_Region_Index [ACTIVE v1.2] (76 rows) carries one band per region. C7's Timetable sheet is
Time × Category × Weight × AP Tags — near-identical authoring cost, but it buys day/night life.
env_density_band_default has the same shape problem.
5. Personas should be CATEGORY TAGS, not schedules. C9 is the cheapest ambient-life system that has ever
shipped at this scale: the NPC carries category tags, the *world* carries tagged points with animation
trees, and the engine joins them. Our persona system (memory:
every-entity-detailed-persona-nonblocking-paths) currently reads as per-entity authored life. Re-express
it as valid_categories on the persona and category + weight on world points, and the same content
becomes combinatorial instead of enumerated.
6. C10 is our factory, shipped in 2015 without ML. Generate a rough pass from structured inputs, let the
author re-roll, hand-polish everything, re-use a small animation pool across many bodies. That is exactly
the generate → critic → fix belt this control plane already dispatches (§4.1). The adoptable specifics:
the generator's inputs were actor data + cinematic instructions + VO-audio analysis (not a text
prompt); the re-roll was cheap and expected; and the generator's output was the baseline for
100% of dialogues, with hand-polish tiered by narrative importance (SYNTHESIZER CORRECTION — see
C10; the researcher return's "universal hand-polish" reading is contradicted by the source, which
records less-important dialogues as *hardly touched*). Our T0_Dialogue_Line plus
docs/dialogue_divergence_baseline.json lane should be restructured around a generator whose input is
the beat/VO data we already hold, with 100% generator coverage as the plan and a **declared polish
tier per line** — which is the same honest-tier-register discipline this repo already runs, one level
down. The corrected reading is the CHEAPER one, and it is the one with evidence behind it.
7. C11 is a direct instruction to our region-page sizing. We size regions from real-world geography
(GEODATA_TERRAIN_CHAIN §7). CDPR sized from quest count. We hold T0_Quest_Seed_Registry (74 rows) and
T0_Questline_Index (101 rows) — those numbers should drive playable-area targets, not the reverse.
8. C12's "delayed consequences must be visible" is a gate, not advice: any irreversible_choice or
world_memory_write that never produces a player-legible callback is authoring spend with no return.
The teeth are cheap — every write must have at least one downstream read that surfaces to the player.
| # | Fact (paraphrased) | Tier · source |
|---|---|---|
| N1 | Task management lived inside the game world. A task was created by placing a sign in the field; clicking the sign opened its specs and related meeting information. A "field task view" showed higher-level items. Stated purpose: stop two people doing the same work. A separate dashboard existed for when you did not want to run around the world hunting for a task pinned in a cave | TALK-RECAP of CEDEC 2017 (Fujibayashi / Yonezu), Matt Walker translation — translation gist · Nintendo Everything |
| N2 | Bug reporting was built into the game and carried world state. A flag raised in-game automatically logged coordinates, scene data and event information, and routed the report to the responsible developer. A ZELDA_ERROR call was placed at 6,000 sites to catch freezes proactively. Early testing found 617 freezes in two days, which is why debugging was prioritized from the prototype phase instead of deferred | TALK-RECAP — same as N1 |
| N3 | Three production "laps": prototype (build the framework, prove the fun) → production (all assets, no polish) → polish | TALK-RECAP — same as N1 |
| N4 | Cadence and automation: ROM builds every 5 minutes; Jenkins handled 48% of submissions (52% manual); 2,344 unique map screens generated procedurally every night; the map was 120 sections × 4 zoom levels; main ROMs loaded resources locally and copied only executables to keep build times down; multiple ROM versions kept for recovery | TALK-RECAP — same as N1 |
| N5 | Non-programmers authored systems directly. LayoutEditor was extended so designers could place and animate UI data-driven, without programmers; SLink let designers assign sounds by clicking an actor in-game; AssetBinder unified asset search, filtering and batch adjustment. The UI team was two designers — the gap was closed by tooling and programmer collaboration, not headcount | TALK-RECAP — same as N1 |
| N6 | The design philosophy stated as a production rule by technical director Takuhiro Dohta: "Rather than create something fun, create a system that makes fun things happen." The chemistry engine was conceived as the pair to the physics engine — a rule set over elements (fire, ice, wind) — and the goal was multiplicative rather than additive gameplay | TALK-RECAP of GDC 2017 *"Change and Constant — Breaking Conventions with Breath of the Wild"* (Fujibayashi / Takizawa / Dohta) — Game Developer · Nintendo Life |
| N7 | TotK: mixing hand-authored motion with simulation FAILED, and they deleted the hand-authored half. Lead physics programmer Takahiro Takayama: kinematic rigid bodies had infinite mass, so *"objects like giant interlocking gears and gates would break on a regular basis."* The fix was to make every moving object physics-driven. Object mass and volume are auto-derived from shape plus an assigned material (wood/metal/stone), then deliberately de-tuned for feel — boards made thicker than reality because the computed weights were "too heavy" | TALK-RECAP of GDC 2024 *"Tunes of the Kingdom: Evolving Physics and Sounds for TotK"* (Dohta / Takayama / Osada) — Game Developer · GDC Vault session |
| N8 | One generalized primitive out-earned every special case. The ball-and-socket joint built so a portable cooking pot would sit level on slopes was re-used by players for wheel suspension, robotic arms and laser targeting. Takayama: *"We were so happy to see that the joint on the portable pot has seen a whole range of use."* | TALK-RECAP — same as N7 |
WHAT IT TEACHES OURS.
1. N2 is a direct upgrade to our bug ledger. Our BUG-00NN entries are prose typed by an agent.
Nintendo's carried coordinates plus scene plus event state, emitted by the game. The AI QA loop is our
only player until the Josh Gate (memory: josh-playtest-target-ch2-slice), so a finding it cannot
reproduce is a dead finding. **The QA loop's bug emitter should serialize world position, active quest
phase and a facts snapshot into every report** — the same payload CDPR's Facts DB tab shows (C3).
2. N1's in-world task pins map onto our region pages. We already treat the region page as the unit of
world authoring. A finding pinned to a *world coordinate inside a region* rather than to a document line
is the difference between a board Josh can walk and a board he has to read.
3. N4 is the honest benchmark for our nightly window. Nightly regeneration of 2,344 derived artifacts on
a 5-minute build cadence is what "the factory runs overnight" means at AAA. §6 Q2 (wall-clock per order
per lane) is the measurement that tells us how far off we are. **48% automated submission is a number to
beat, not to admire** — our submission path is already scripted.
4. N5 is our whole premise, externally validated: two UI designers shipped BotW's UI because the tool let
them author data instead of filing a request with a programmer. Every harness/apply_*.py in this repo is
that same move.
5. N6/N7/N8 are a warning aimed at our combat and interaction lanes. The mixed kinematic/physics failure
(N7) is exactly the class our GAS/ability work can fall into — hand-authored motion adjacent to simulated
motion, breaking at the seam. And N8 says the payoff comes from one primitive generalized, not many
authored. Our element matrix (memory: elemental-matrix-recovery-from-gdd; 125-row grid, 21 hybrid
combos) is a chemistry engine by another name; the teaching is that it must be a **rule set the world
obeys everywhere**, not a table consulted at scripted moments. harness/check_counter_class_coverage.py
and the D1-27 element visual law are the right instinct; the bar is *ubiquity*, and it has to be measured.
| # | Fact (paraphrased) | Tier · source |
|---|---|---|
| R1 | Rockstar's quest/mission authoring pipeline is not publicly documented. Missions across the series are compiled bytecode scripts, not data graphs — main.scm in the 3D era, SCO in GTA IV, YSC in GTA V (header, code section, and a native function table whose hashes Rockstar has rotated every game update since build b350). All of this is community reverse engineering; Rockstar's internal tools and proprietary language remain undocumented | REVERSE-ENGINEERED — GTAMods: Mission Scripting (Overview)) · GTAMods: Script Container |
| R2 | World population IS data. popcycle.dat holds the population makeup per map region/zone type (business, entertainment, shopping and so on), as percentages; the community-documented invariant is that the values must total 100%, and a region whose values fall below that crashes the game there. popgroups.meta enumerates the peds available per zone, ambientpedmodelsets.meta widens the model pool, scenarios.meta raises the probability of scenario peds. Population varies by time of day — fewer peds and cars at night | REVERSE-ENGINEERED — GTAMods: Popcycle.dat |
| R3 | The ambient scenario taxonomy is small and combinatorial: Stationary (stands and plays anims) · MoveBetween (moves between nearby points playing anims) · Group (spawns the ped plus companions in conversation) · Seated · Wandering | REVERSE-ENGINEERED — GTA Wiki: scenarios · GTAForums scenario list |
| R4 | Rockstar considered a procedural world for RDR2 and rejected it — the design had to be scripted *"so that it all feels right"*, on the belief procedural tools would not feel real | TALK-RECAP / press — GamesBeat |
| R5 | The one substantial public Rockstar production talk in this domain is GDC 2020 *"Breathing Life into the Wild West: Animating the Animals of Red Dead Redemption 2"* (Alex O'Dwyer, Animation Director), covering how the ecosystem was planned, conceived and delivered and how the systems evolved from GTA V's. The announcement page carries no technical detail; the content is in the session itself | FIRST-PARTY announcement — GDC |
WHAT IT TEACHES OURS.
1. Say it plainly: Rockstar is not a pipeline teacher. Their outcomes are the industry's ceiling and their
process is closed. Any lane claiming to "follow Rockstar's approach" to quest authoring is claiming
something unverifiable. That is a finding, not a gap to fill — do not spend more research budget here.
Their comparator value stays on the outcome lenses where the program already placed it.
2. R2 is nonetheless the sharpest population data shape in this research, and it is better than ours.
Population as a table keyed by zone type × time of day, with **percentages that must sum to 100 and a
loud failure when they do not**, is exactly the registry-plus-gate idiom this repo runs. Our
T0_Region_Index.ambient_population_band_default is a single scalar per region across 76 rows. The
adoptable move: a population-composition table per region node × time band, with a run_gates.py check
that each composition sums correctly and no band is empty. **A missing zone in GTA crashes; a missing band
in ours should fail a gate** — the same instinct we already apply to FK coverage.
3. R3 says the ambient vocabulary should be TINY. Five scenario kinds cover a city. Our persona and
dwelling registries should resolve ambient behaviour into a similarly small closed set of kinds, with the
variety coming from the join (who × where × when) rather than from enumerating behaviours.
4. R1 versus C1: the fork is already decided for us, and CDPR is right for our constraints. Missions as
compiled script (Rockstar) needs a studio's worth of engineers; quests as graph data (CDPR) is
authorable, diffable, gate-checkable and machine-generatable. Our registry-first quest model sits on the
CDPR side of that line. Recorded so a later wave does not re-litigate it.
| # | Fact (paraphrased) | Tier · source |
|---|---|---|
| B1 | A Radiant quest is a template whose participants are ALIASES filled at quest start. Alias fill types include Find Matching Reference (search a location for a reference matching the alias's conditions) and Location Alias Reference / find-matching-location. Aliases fill in order, and later aliases may depend on earlier ones | FIRST-PARTY tool docs (Bethesda's Creation Kit wiki) — Quest Alias Tab · Bethesda Tutorial: Radiant Quests. FLAG: ck.uesp.net returned HTTP 403 to direct fetch this pass; B1-B3 come from the search index's extracts of those pages. Re-verify against the pages themselves before building on the exact fill-type list. SYNTHESIZER RE-CHECK 2026-08-05: the FLAG STANDS and widens — a second direct fetch of ck.uesp.net returned 403 again, and en.uesp.net returned 403 as well, so the whole UESP domain is unreachable from this environment, not one page. What a second independent search-index pass DID corroborate is the ordered-fill semantics: aliases are filled in order at quest start, and the order matters where aliases depend on each other directly or through conditions. What remains UNCONFIRMED by any direct read is the exact fill-type NAME list and B3's alias-versus-base-actor design rule |
| B2 | The matching runs on keywords, in two layers: locations carry Loc Ref Types (dungeon, bandits, crypt…) and markers/clutter inside a location carry their own keywords (boss, boss chest, captive position…). A quest therefore targets *a kind of place and a kind of spot inside it*, never a specific place | FIRST-PARTY, same FLAG as B1 |
| B3 | The design rule stated by the tool docs: the more functionality you put on the alias instead of on the base actor, the more you can overlay that functionality onto any actor | FIRST-PARTY, same FLAG as B1 |
| B4 | Radiant generates quests from components — location, enemy type, reward — some randomized, not all | SECONDARY — UESP: Skyrim Radiant (403 to direct fetch; via search index) |
WHAT IT TEACHES OURS.
1. B1-B3 are the mechanism that lets a small team fill a huge world, and we already hold the substrate.
T0_Quest_Definition_Registry.participant_entity_refs and spatial_requirements_array are alias slots by
another name; T0_Region_Index (76 rows) plus the dwelling / interior-space / gather-node registries are
the keyword-taggable target pool. What is missing is the fill contract: a declared rule saying *this
slot is filled by any entity satisfying these conditions in any location of this class*, plus the tags on
the world side to satisfy it.
2. This is the honest, non-slop version of "generative content" for us. Memory
(generative-entity-system-vision) already rules deterministic-first. B2 is deterministic: the pool is
authored, the conditions are authored, only the *pairing* is late-bound. It multiplies authored content
without inventing canon — precisely the line the cardinal rule draws.
3. B3 generalizes past quests. "Put the behaviour on the slot, not on the actor" is the same instruction
as C9's category-tagged action points and R3's five scenario kinds. Three independent AAA pipelines
converged on it. **Our persona, faction-standing and companion systems should each be re-read against one
question: is this authored onto the entity, or onto a slot the entity can fill?**
**SYNTHESIZER VERDICT 2026-08-05 — this block is the ONE under-verified adoption in the whole pass, and it
is split rather than swallowed.** Every other load-bearing claim in §§7-8 and in the sibling dossiers was
confirmed by direct fetch this pass; B1-B4 alone could not be, because UESP 403s the whole domain from here.
So the adoption splits in two:
the entity" does not depend on Bethesda at all — it is independently carried by C9 (CActionPoint +
JobTree Valid Categories, FIRST-PARTY, verified) and R3 (the five-verb scenario vocabulary,
REVERSE-ENGINEERED, verified). Two verified legs are enough to route the persona / faction-standing /
companion re-read, and that re-read is therefore ADOPTED.
participant_entity_refs — the exactfill-type list, the two-layer keyword matching, the ordered dependent fill — must not be built against
search-index extracts. **Routed as: re-verify first (from an environment that can read UESP, or against
the Creation Kit's own shipped documentation), then build.** An adoption whose mechanism was never read
directly is a hallucination risk wearing a citation, and this repo's standing law is cited-or-cut.
1. Phase-scoped quest graph + a facts DB + phase-jump debugging (C2, C3, C4). Highest leverage on QA
throughput, and QA is our only player until the Josh Gate. Nothing else here is worth as much per hour.
2. Generator-first-pass with universal hand-polish, for dialogue scenes (C10). The proof that our belt
shape ships AAA — with the specific lesson that the generator's inputs are *structured production data*,
the re-roll is expected and cheap, and the polish pass is planned for 100% of rows.
3. Population and ambient life as joined tables — Spawnset × Timetable × category-tagged action points
(C7, C8, C9), with Rockstar's zone × time-of-day composition table and its sum-to-100 invariant as the
gate shape (R2), and a five-verb ambient vocabulary (R3).
4. Alias/slot-filled quest templates over keyword-tagged locations (B1-B3): the multiplier that gets us
from 74 quest seeds to a populated world without inventing canon.
5. In-world, state-carrying task and bug capture on a nightly deterministic cadence (N1, N2, N4):
findings that carry coordinates plus phase plus facts, and a world that rebuilds itself every night.
Boarded, not done (gap-hunter output): mint PIPE_WORLD_QUEST as the ninth dossier · the
--start-at-phase quest-runtime entry point · the facts-DB write surface behind state_writes · the region
population timetable replacing ambient_population_band_default · the alias fill contract on
participant_entity_refs · the QA bug emitter's world-state payload · re-verify B1-B4 against the Creation
Kit wiki pages directly (403 this pass).