ACTIVE SPRINT: charter #1702 (DEMO COMPLETION, then the town). Refresh this pointer at every charter transition.
The master navigation doc (v2 — the three Acts). VISION.md says what the product IS and the bar it must clear; this doc says the ORDER we build it in — every sprint from here to the Walkable World and beyond, with a binding gate, an ordered issue list, and a version pin, so that ANY agent (Claude, Codex, GLM, human) can open this file, find the active sprint, and execute a lane without needing this repo's history in its head. (New here? Start at
docs/OPERATIONS.md— the one-page bootstrap.) v1 authored + red-teamed 2026-07-03; v2 same day after the owner expanded the North Star (full walkable rendered games, the template library, the harvest loop — see VISION "The destination"). Owner reviews via PR.
- ACT I — The Demo (now → GA = v1.1.0): sprints S1–S10 (§4), unchanged from v1 except that
the render-delivery decision is now RESOLVED (
RENDER-DELIVERY-DECISION.md: Unity standalone = the demo's delivery; the S2 entry gate is satisfied) and S8's delivery is the Unity standalone + app handoff. - ACT II — The Walkable World + The Harvest Loop: the W-series (§4b: scene-at-rest → walk → talk → living stage → the Unity player tier) and the HV-series (§4c: artifact evals → extract → promote → reuse → flywheel ops). Interleaves with Act I where parallel-safe — W1, HV1, HV2 start immediately. Act II's exit = T3 is real: a blind AI playtester completes a quest loop IN the rendered surface, on a library-assembled game.
- ACT III — The Universe Platform (§6): packs, remaining agent lanes, hosted runtime, creator, KOTOR-class universes, the 2D tier, engine-as-platform.
WorldOS is "Baldur's Gate that writes itself, played through your own AI." Three concentric products, built in this order:
- The Game — the BG-universe flagship: the deterministic SRD 5.2 engine + the OpenWorlds viewer + the native app + the PoE2 painterly combat demo. The 1.0 ladder ships this.
- The Platform — the same game played through any agent (Claude Code today; Codex / OpenClaw / Hermes lanes in epic #911) and eventually hosted (milestone 25). The moat: the player brings their own agent + credentials, so there is no central LLM cost — the distribution economics are the platform bet.
- The Universe System — universe creator + template packs (#644) + licensed universes (KOTOR #330, VtM #331, Shadowrun #332) + fan showcase (milestone 26). Post-GA revenue shape: original-world paid alpha (#712) with BG as the free flagship.
The meta-product (name it, because it is working): the measurement culture itself — control-anchored art panels, story lenses, the behavioral gate, the FELT track. These instruments are what let autonomous agents build a game to a bar. WorldOS is the game AND the proof that the method ships games.
Engine releases stay semver v1.0.x; product rungs are named releases pinned to an engine version. The old "v1.1 — The Table" milestone label was misleading (its content ships inside v1.0.7–v1.0.8) and is retitled "The Table (story/world systems)".
| Engine version | Sprint(s) | Product rung cut at this version |
|---|---|---|
| v1.0.5 | S1 | SHIPPED 2026-07-08 — S1 evidence gate3d: story 4.2 / mech 4.1 / behavioral GREEN |
| v1.0.6 | S2 + S3 | — (felt demo loop + combat readability) |
| v1.0.7 | S4 | — (The Table I) |
| v1.0.8 | S5 + S6 | — (The Table II + alive/latency) |
| v1.0.9 | S7 | Player-Ready Beta (2D-viewer scope — see §4/S7) |
| v1.0.10 | S8 (+S9 parallel) | 1.0 Playable Combat Demo |
| v1.1.0 | S10 | 1.0 GA |
| v2.x | post-GA phases | platform / universes / rendered-game (§6) |
- A sprint = a charter epic issue (label
sprint-charter) + its milestone. The charter carries: GOAL · BINDING GATE (as runnable commands + evidence paths, never vibes) · ORDERED issues with lane labels · INVARIANT checklist · RISKS/owner-gates. - Lanes (issue labels):
lane:engine·lane:story·lane:renderer·lane:app·lane:qa·lane:art·lane:platform. - An issue enters a charter only when dispatch-ready: spec, acceptance criteria, evidence requirements, invariant notes. The charter author upgrades stale issues or they wait.
- The loop (unchanged, from VISION "How we build"): worktree off main → additive change →
single-process pytest +
qa/fast_gate.sh→ PR → review-gated merge → prune. QA tiers perdocs/qa/FAST_GATE.md; never report Tier-0/1 as a release verdict. - Anti-variance rule for release gates (red-team amendment): a story gate is never a single duo — the deep 24-beat read must be corroborated by the sweep duo; if they straddle the bar, a third duo decides by median. Mech is always a combat-sprint median (n≥3). FELT gates are control-anchored same-panel deltas (beat the embedded disguised real-art control), never raw votes or absolute numbers.
- Ledger discipline: every scored run →
qa/scores_db.py; every panel embeds a disguised real-art control; identity mappings live outside panel dirs.
- Goal: the engine's relationship/quest/camp machinery is driven, not narrated — the measured rri-a1-duo2 defect class (behavioral RED: 0 quest/relationship tool calls in 22 beats) is closed by every-beat obligation cues.
- Issues: #1286 (✅ PR #1299) · #1288 (✅) · #1287 + #1285 (PR #1300) · #1160 WS3a rebase · merge-queue closeout (#1282 #1283 #1293 #1294 #1295 #1297 #1298).
- Gate (runnable): re-freeze SHA → fresh 24-beat Opus duo: story ≥4.3 and behavioral
GREEN (structural_completeness passes), corroborated per §3 anti-variance rule → 3× combat
sprint median → VM 5-persona sweep → Mac native part-A →
qa/release_readiness.pyrollup → cut v1.0.5 (CHANGELOG batch + tag + pre-release + evidence bundle). - Lane:
lane:story+lane:qa.
- ENTRY GATE (red-team amendment — do this FIRST): the render-delivery decision doc (issue filed as the S2-entry blocker): how does the Unity render reach the player's screen — embedded Unity build in the app / render-service streaming frames into OpenWorlds / native Unity player? First-principles decision doc (options, data, diagram, debate, decision), NOT code. Today's path is one-way box→QA-frames; S2's packaging depends on the answer even though the Animator/VFX logic itself is delivery-agnostic.
- Goal: the demo's moment-to-moment feel — animation, VFX, death, motion — driven by real engine events.
- Issues:
/eventsAction-Replay → Animator/VFX wiring (verb→clip map,anim_hint, DOTweenlastPathglide, damage/VFX at engine cells) · death/defeat visual resolution (topple/fade) · #1296 edge-blending (Beautify composite grade / silhouette feather) · #1284 prop-cell grounding · #1281 re-validation on a REAL church-located combat · L7 motion-reel lens first run · ghoul combat-clip completion. - Gate: combat-FUN checklist 6/6 with evidence frames (VISION §Graphics) + FELT re-panel where the hero frame meets/beats the embedded real-art control same-panel (votes are a secondary signal only).
- Lane:
lane:renderer+lane:art.
- Goal: the combat UI communicates state like a real CRPG on the 2D OpenWorlds surface — independent of the render-delivery answer.
- Issues: #595 condition badges + initiative row · #596 reaction pip / OA banner / concentration warning · #597 target-bind indicator · #599 dodge/dash/disengage/hide/shove verbs · #219 crit attribution + point-blank nits · #827 character-sheet button.
- Gate (runnable, taxonomy fixed up front): a blind AI playtester (
qa/ui_playtest.sh, combat-seeking persona) completes a GUI combat with zero bugs in the defined confusion-taxonomy: dead-control · state-mismatch (UI disagrees with engine values) · unexplained-wait >10s · mislabeled-affordance. Taxonomy classes tagged inbugs.ndjson. - Lane:
lane:app+lane:engine.
- Goal: camp/rest is a real subsystem and the world visibly remembers choices — the two cheapest-highest-leverage Table pillars, aimed at the engagement WARNs S1's measurement surfaced (camp never fired, world under-peopled).
- Issues: #611 camp_supplies + make_camp/forage · #609 honest camp clock · #612 + #613 + #614 relationship/reputation change-logs + panel · #616 ArcGate ladder · #775 retrieval surface revival (+#803 prerequisites) · #753 latency BUDGET definition (pulled forward — red-team amendment: it is the documented #1 give-up driver; defining + instrumenting is cheap and it must be measurable before Beta gates on it).
- Gate: a scored 24-beat duo where camp fires ≥1×, the change-logs populate, a companion arc-gate progresses, and the S1-era engagement WARNs (camp/world_peopled/faction) are clear — story ≥4.3 held per §3 rule.
- Lane:
lane:story+lane:engine.
- Goal: companions push back; sessions have rhythm; failure becomes story.
- Issues: #837 companion agendas (includes the engine-side
proactive_beatflag, write+read in the same change — red-team amendment: "companion-initiated" must be an engine-mutated value, never fiction-read) · #838 session rhythm (recap/cliffhanger/epilogue) · #839 fail-forward complications · #836 consequence surface · #141 parley relay · #608 parley echo. - Gate: a scored duo with ≥1 engine-flagged proactive companion beat + recap/cliffhanger
present + tolkien
dramatic_momentumdim ≥4.3 (an existing rubric dimension — red-team's "invented metric" objection was wrong on this one point; it printed 4.2 in tonight's scorecard). - Lane:
lane:story.
- Goal: the screen always shows motion — #835 keystone (stream the DM's scene as written), wired against the #753 budget defined in S4; #561 effort tiers.
- Gate: measured perceived-latency inside the budget on the GUI loop (from
duration_api_ms+ streaming-visible evidence); no dead wait beyond budget anywhere in a full playtest. - Lane:
lane:engine+lane:app.
- SCOPE (red-team amendment, explicit): Beta's "no broken moment" bar applies to the shipped 2D OpenWorlds surface in the built .app. The Unity render is NOT in scope for Beta — render-in-app is a Demo-1.0 (S8) gate. This resolves the ladder contradiction; VISION is patched to say so.
- Issues: #640 multi-campaign freeze (P0) · #307/#308/#310 playtest fixes · #288/#284 responsive · #279/#174 icon registry · #503/#502 chronicle/narration polish · onboarding self-teach pass · "how a player plays" run-flow doc (per surface: app / CLI / bring-your-own- agent) · latency budget met (from S4/S6).
- Gate: VISION's Beta rung verbatim on the scoped surface: built .app, a no-prior-knowledge dogfood arc with no broken moment, honest felt session; 5-persona sweep green at the beta bar.
- Lane:
lane:app.
- Goal: assemble the demo per the render-delivery decision (made at S2 entry): a modular multi-room dungeon, playable in-app, on placeholders, backdrop scorecard passing per room.
- Issues: render-in-app integration (per the decision) · demo dungeon authoring (4–6 linked room-units with door-cell graph: crypt/church/tavern/bosshall + 2 new) · monster wave 2 (cast to ~10, registry-complete) · day/night in-app · #441 blind traversal + combat build gate · backdrop scorecard run per demo room.
- Gate: VISION's 1.0 rung verbatim: playable modular combat scene in-app on the PoE2 stack, placeholders OK, backdrop scorecard PASS per room, combat-FUN 6/6 in-app, FELT control-anchored parity on the hero frame.
- Lane:
lane:renderer+lane:app+lane:art.
- Issues: #1241 Atelier kit (3D modular base + albedo LoRA paint-over) · #1243 tile-ControlNet finisher · #1217 multi-room composition craft · #1218 stray-item control.
- Gate: adopted plates beat their real-art controls by ≥+1 median on ≥2 consecutive panels; FELT control-parity on hero frames.
- Provider-fallback note (red-team amendment): Scenario + Gemini are single-vendor dependencies for the plate pipeline; the registry-by-slot invariant makes output swaps cheap, but the generation lane needs a named fallback (ComfyUI/SDXL on the local Mac when configured) documented in the graphics roadmap.
- Lane:
lane:art.
- Issues: placeholder→real art registry swap (through the S2/S9-proven pipelines) · #151 notarized distribution · #134 Sparkle updates · #591 parity meta-check · #643 Scoring v2 as the GA-grade instrument (RRI saturation + satisfaction provenance fixed BEFORE the GA verdict is measured on it) · #1137 save-compat CI guard · #1122 security triage (also gates the hosted-runtime track) · multi-agent GA slice (see platform track).
- Gate: VISION's GA rung: Demo workflow on real art + Beta story/world bar + notarized + parity + the bring-your-own-agent surface documented and the Claude Code lane verified end-to-end (red-team amendment: GA-block ONE proven provider lane, not the 5-lane epic).
- Lane: all.
Every W sprint ships its EVAL FIRST (decision-by-eval) + a text-tier byte-identity test (VISION invariant: the text tier always plays). Exploration ground truth: scene_grid already carries walkable cells AND populated
spawns(per-kind generators, scene_grid.py:254–660) — spawns is read today by the layout-validator (scene_grid.py:974, spawn cells vs blocked cells) and by the Unity closed-loop renderer (ClosedLoopBuilder.cs:126-129, party/foe cell placement); no CONSUMER reads it for rendering/projection in the live viewer/product surface yet; move_to_coords exists combat-gated; the viewer already paints walkability. The gaps are ungatings + one new render mode.
Act II execution state (living; last trued 2026-07-08): Sprint 1 (charter #1328, CLOSED) — W1 #1330 ✅ · HV1 #1331 ✅ · HV2 #1329 ✅ · Tier-1.5 probe harness #1336 ✅. QA-economics v2 doctrine merged (#1340, docs/OPERATIONS.md). Sprint 2 (charter #1337, CLOSED) — W1–W4 (#1330/#1341/#1344/…) and HV1–HV5 (#1331/#1329/#1338/ #1342/…) are MERGED; W5 (#1322, the Unity player tier) remains open, not yet started. Historical charter = #1386 ("Act II close-out — Rendered Felt"): ordered lane was #1284 actor grounding v2 → the rendered rest-scene demo (canon fixture, grounded actors, W1 stage block, FELT panel vs the PoE2 anchor) → W5a Unity player build (#1322) → HV follow-ups (#1378 cross_door re-stage, HV extractor quality pass 2). Entry gate was satisfied: v1.0.5 released, local Unity lane reachable, render-delivery decision #1302 CLOSED. #1386 is now history; the current queue is #1702. The superseded follow-on was S2 (#1309, entry gate satisfied); it is not the current queue. v1.0.5 RELEASED 2026-07-08 — S1 evidence gate: gate3d story 4.2 / mech 4.1 / behavioral GREEN. Trued 2026-09-02: the ACTIVE charter is #1702 (#1386 is history); the renderer runs LOCALLY on the Paris Mac (the GEX44 box is retired); the 3D-first kit chain is the shipping room surface.
- W1 — "Scene at Rest" (✅ SHIPPED — PR #1330, incl. the felt_rest_panel instrument). Additive
stageblock (mode: rest|combat+ rest tokens) inbuild_combat_surface(viewer/server.py:3376; optionally aliased as /scene-surface) — party + present NPCs (Character.location_id == current) PROJECTED ontoscene_grid.spawns(addnpc:<id>spawn keys in the generators). Projection only — zero new persisted state. Renderer scene-at-rest mode (idle clips; assets exist). EVAL (build first): FELT-style rest-scene panel — "does the tavern-with-innkeeper read as a game?" (disguised real-game controls, same calibration law). Known risk:spawnssits inside_layout_hash(scene_grid.py:158) → one-time Tier-2 art-cache invalidation, accepted. - W2 — "Walk" (engine half ✅ SHIPPED — PR #1341; UI half split → #1350, unblocked by #1303's
glide PR #1345). New additive
walk_toverb BESIDE move_to_coords (servers/engine/server.py:4583 — the combat gate stays untouched), reusingcombat_grid.shortest_path:221via ONE shared blocked-set function (never fork pathing). Writes additiveCharacter.stage_cell. Emits Action-Replay walk beats via /events (viewer/server.py:9181) so the Animator glides them. Walkmask click-to-move in rest mode (screen-combat.jsx pattern exists); door-cell click →cross_doorwalk-through. Rule: the renderer glides only engine-confirmed paths — no client prediction. EVAL: scripted click-walk replay (path legality, glide renders, text-tier identity). - W3 — "Talk" (engine+surface half ✅ SHIPPED — PR #1344; real seams: viewer read-model
build_parley_surface~viewer/server.py:6472 + enginegenerate_parley_options(approach=); UI/staging half remains). Parley surface gains additive stage metadata (NPC stage cell, attitude); click-NPC → approach-to-talk (walk_to adjacent, then parley); dialogue rendered at the actor (2D reuses screen-dialogue.jsx). EVAL: blind panel + a behavioral check that the DM receives IDENTICAL parley moves as the text tier. - W4 — "The Living Stage" (coordinate with S8).
servers/engine/server.py:4039(start_combat) additive param seeds combatant cells fromstage_cell(default = today);servers/engine/server.py:6976(end_combat) writes survivors back; day/night from the campaign clock (surfaced per #1307). EVAL gate = NO TELEPORT: combat entry cells == last rest cells; exit cells == combat end cells. Full explore→talk→fight→loot→ move-on loop playable. - W5 — "The Unity Player tier" (depends W1–W4; formalizes the render-delivery ruling). macOS player build of extensions/renderers/unity, launched beside the app (mirror native-bridge.js handoff); input = existing POST /move kinds ONLY. EVAL = the T3 gate: a blind AI playtester completes a quest loop IN the rendered surface (extend the GUI harness).
The question this series answers: the subsystems all exist and gate individually — rooms walk, the DM plays, panels score, the harvest promotes. The A-series composes them into ONE evaluated PLAYABLE LOOP (a Diablo-1-grade quest) and turns its eval into the routing instrument for everything else: each cycle, the weakest dimension gets the next sprint. S8 (Demo Assembly) is absorbed by this series — its gate becomes A-G's gate.
- A0 — Compose (two units, parallel):
get_questsfull-read RPC (engine additive; get_state lists active only) +qa/seed_adventure_demo.py— the one-call fixture: camp ↔ tavern_snug (Keeper/giver) ↔ shop (merchant), camp ↔ crypt (goblins) ↔ throne_hall (Goblin Boss); add_quest 4-objective arc; reward staged; full static stack at seed. Every room class is already walk-green certified — composition, zero new geometry. - A-T — The text-arc eval (parallel with A-G):
qa/run_adventure.sh(duo-derivative, arc-directed persona, 20-beat budget (raised from 15 on 2026-09-02 — a control run with the July DM model completed at beat 19 while 15 was knife-edge; the bar is unchanged: N≥3, completion ≥ 0.67, behavioral GREEN; DM and player model ids are pinned and recorded per row), completion short-circuit) +qa/quest_progress.py(per-beat get_quests polling → quest_trace.json: reached_giver / quest_accepted / entered_dungeon / boss_dead / reward_received / quest_completed) +qa/adventure_eval.py(N runs via the run_parallel pattern → completion_rate · beats/wall-time · stuck (dead beats + stage-gap outliers) · engagement · 3 lenses · behavioral gate → scores_db surface="adventure"- a WEAKEST-LINK verdict line). Ruler: new ac_-family config list per HV1's
scoring_config_version rule. ARC MODE + addendum v2 (2026-09-02, the G2 completion lever):
the runner sets
WORLDOS_ARC_MODE=1, which rewrites the three shared duo directives that pull against a PRE-SEEDED world — the SCENE-INTRO "named face who SPEAKS" mandate, the duo brief's "new named faces enter and speak" obligation, and the midpoint reversal (in arc mode the reversal is a PRICE, never a new fight, and waits for objective 2) — and the ARC ADDENDUM adds five seeded-arc rules (seeded hostiles only · reversal-is-a-price · never drop the PC / never reroll · Maera by beat 3, throne hall by beat 6, no add_location · end_combat only at zero live hostiles · the quest giver and every objective-named NPC are ESSENTIAL and cannot die before the quest resolves). All six have TEETH: underWORLDOS_GATE_ARCthe behavioral gate turnsreroll_character,add_location, aspawn_monsteroff the seed's species (read from the run's own seed manifest, never hard-coded), anend_combatreturningwarning_live_hostiles, a call that kills an essential NPC (giver_id + objective text, read from the snapshot), and an end-of-run ACTIVE quest with a dead essential NPC (the softlock) into hard FAIL rows naming the beat. run_duo is untouched (it never sets the flag) and the adventure ruler is UNCHANGED atav_a9536e9af875— the addendum text is not hashed into it; only adventure_eval_config.json + adventure_eval.py are.
- a WEAKEST-LINK verdict line). Ruler: new ac_-family config list per HV1's
scoring_config_version rule. ARC MODE + addendum v2 (2026-09-02, the G2 completion lever):
the runner sets
- A-G — The walked eval (parallel with A-T; absorbs S8's gate):
qa/adventure_walk.pydrives the SANDBOX player through the arc route on the :8972 channel (walk_test door-graph machinery + journey_eval VQA per stage + ui_playtest-style stuck/dead-click accounting), feeding the same aggregator (modality column). Prereq: ONE box build batching the #1616 T-pose registry-sync + any #76-adopted plates. Gate (from S8, upgraded): the full quest loop completes walked, in-app semantics, tri-state gates green, per-room backdrop scorecard PASS. - A2 — The flywheel protocol: each autonomous run = 1 full adventure eval (N≥3 arc + ≥1
walked) + 1 improvement cycle on the weakest dimension, then re-eval. The two-anchor panel
ruler RATCHETS: when a flagship room is hand-elevated past the calibration reference, the
reference upgrades and pulls the bulk tier on the next cycle. Variation breadth (bar variants,
dungeon variants) = re-running Loop 0 (the room pipeline) per seed — the
library/is the accumulation of gate-passed artifacts (HV3 promote is its sole writer). - A3 — Proceduralization gate: only when the A-eval holds green across N seeds do we parameterize — adventure templates × universe skins (the DM pulls a world), background generation on library cache-miss via the StreamingAssets HOT-LOAD mechanism (camOrtho-proven; box builds are ship-time only) with the never-T-pose floor as the immediate stand-in. Proceduralizing an ungated loop generates infinite mediocrity; gating first generates infinite shippable.
The mechanism: every scored QA run is ALSO a harvest candidate — no new run types. Content flows snapshot → extract → eval-gated promote →
library/→ reused by world-gen/questgen → measured as a trend ("less AI dependence" becomes a number). All promotion is eval-gated; the content analogue of the real-art-control law is disguised hand-authored canon as panel controls.
- HV1 — "Artifact Evals FIRST" (✅ SHIPPED — PR #1331; instrument DISCRIMINATES: canon controls
2.9–4.2 vs thin extract 2.05).
qa/artifact_score.py+ per-class rubrics (quest / npc-or-villain / location / encounter; plates already have visual-critic). Controls = hand-authored canon (world.json quest_variants / npc_roster dossiers / wiki-canon areas) pushed through the SAME artifact schema. Storage: additiveartifactsTABLE in qa/scores.db — new ruler familyac_…via a NEW file-list in scoring_config_version.py (NEVER append to SCORING_CONFIG_FILES — that silently re-versionssc_). Ships a thin snapshot reader so it runs on EXISTING finished campaigns immediately. - HV2 — "Extract" (✅ SHIPPED — PR #1329; 165 artifacts extracted from 4 campaigns; its merged
schema is canonical). (original spec: first commit = the schema handshake
data/library/artifact_schema.json).qa/export_campaign_artifacts.py(sibling of export_scene_grid.py; reuses distill.py's transcript reader for dialogue snippets + attitude arcs) →qa/artifacts_out/<campaign>/{quests,npcs,locations,encounters}/*.jsonwith provenance {campaign_id, run_id, world, sha, scores}. Strictly read-only on play-state. - HV3 — "Promote" (✅ SHIPPED — PR #1338; first live promotion batch in flight).
tools/library/promote.py: nominations (qa/nominations.jsonl) → artifact panels → threshold gate (overall ≥4.0, no dim <3.0, control-valid →stable;canonical= human curation only) →library/(pack-shaped, #644-forward-compatible: pack.json {name, version, license, provenance} + quests/npcs/locations/encounters/rooms). Rooms UNIFY the proto-library: entries REFERENCE room_recipes keys + registry asset_ids — promote.py NEVER edits either. promote.py = sole writer of library/; a library-lint (no unscored stable entries; provenance+license required). Bootstrap ruling (nomination-queue circular dep): nothing upstream of HV3 producesqa/nominations.jsonl— HV5 (#1327,qa/closeout.pyauto-nominator) does, and it depends ON HV3. For the FIRST batch the queue is hand-authored (one JSON line perartifact_id, sourced from HV2'sqa/artifacts_out/<campaign>/**/*.json); promote.py invents NO nomination heuristic — that logic lives solely in HV5's closeout auto-nominator. See docs/OPERATIONS.md "HV3 promotion". - HV4 — "Reuse" (needs HV3). questgen._derive_hooks gains a library candidate source
(tier-weighted, DEFAULT-OFF — default seed path stays byte-identical, guarded by the existing
test_seed_world_default_is_unchanged test); world.json additive
library_packs:[...]; new engine toollookup_library(mirrors the wiki-first canon pattern); library rooms ship as registry aliases (zero renderer edits by contract). EVAL: A/B duo library-first vs pure-gen — lens parity-or-better + latency/token reduction + feature_engagement confirms library content is ENGAGED, not decorative. - HV5 — "Flywheel ops" (slice 1 ✅ SHIPPED — PR #1342: closeout auto-nomination via
qa/nominate.py; nightly batch scoring, weekly curation, library_metrics + backdrop cadence
remain). qa/closeout.py auto-NOMINATES artifacts from every
scored run (story threshold = STORY_BAR, qa/closeout.py, currently 4.3; quest completed; NPC
turn floor N=3) — artifact scoring runs in a
nightly batch, never inline (duo latency untouched). Weekly curation batch. Backdrop cadence:
2 environments a night, panel-gated, weekly curation → ~100 environments in ~10 weeks on the
proven local Unity pipeline.
library_metricstable (size by class/tier, Σreuse_count, promotion pass-rate, %library-sourced beats) — the flywheel's own eval: the "less AI dependence" trend.
Act II additive-invariant register (what a skeptic refutes per stage): HV1 sc_/lc_ hashes
unchanged · HV2 zero writes under play-state · HV3 room_recipes/registry byte-identical ·
HV4 default seed path identical with library_packs absent · HV5 closeout append-only + duo
wall-clock unchanged · every W sprint: text-tier byte-identity + no new writers.
Act II sequencing: NOW: W1 ∥ W2-engine ∥ HV1 ∥ HV2 (schema handshake first) → HV3 → HV5-hooks + backdrop cadence → W3 → HV4 (+A/B) → W4 (with S8) → W5 → T3 gate.
Decision record:
docs/decisions/DESIGN-MEMO-2026-09-02.md§3. Today's top rung is completion + behavioral GREEN + panel parity. Nothing measures "want to play".
- DESIRE — three instruments, cheapest first.
(a) Voluntary continuation — blind personas are told the objective is OPTIONAL; measure beats
played PAST it and whether they explore. Desire runs must DISABLE the completion short-circuit:
qa/run_adventure.shends the beat loop as soon as the quest leavesactive, so a--no-short-circuitcontinuation flag on the runner is part of thedesire_evalwork item — without it there are no post-objective beats to measure. (b) Would-play-again / would-share — two fixed questions, N ≥ 5 personas, two-anchored against a scripted CONTROL session. (c) The owner's felt score — the rare calibration anchor, never the routine gate. Ships asqa/desire_eval.pyon the scores_db discipline: predeclared bars, recorded N, control. Machine-checkable metrics and judge-scored subjective metrics stay separate columns, never averaged. - MODEL SWAPS ARE RULER CHANGES. The
opusalias moving from opus-4-8 to Opus 5 turned a 3/3 into a 0/4 with a byte-identical harness.- Every measured row pins the DM and player model ids (landed, #1727) and records N.
- A version change counts as an improvement only when its delta exceeds the standard error of the same metric over N ≥ 3 repeated runs per model — in score units, not variance (squared units rescale with the ruler). A delta inside that band is noise, not progress.
- A model change gets a CONTROL run before it counts.
- The engine IS the fact ledger; the arc-mode FAIL rows are its auditor. reroll / add_location /
non-seeded spawn / false
end_combat(§4d,WORLDOS_GATE_ARC) are the drift detector — keep the referee in code, never in prose.
- #911 multi-agent plugin — GA slice = docs + Claude lane verified (S10); Codex CLI lane next (the cheapest second runtime), then OpenClaw/Hermes post-GA.
- Milestone 25 hosted runtime — strictly behind #1122 security triage; the runtime-host decision (#706) is a first-principles doc. Economics note: hosted sessions pay the DM cost-per-beat centrally — the bring-your-own-agent default (#911) is the hedge; a hosted tier prices against measured $/beat from the ledger.
- Milestone 26 creator + showcase — post-GA; #711 licensing policy is an owner/legal gate.
- #32 Discord / #31 multiplayer — vNext after hosted runtime proves session economics.
- "Any Agent, Anywhere": all #911 lanes + hosted runtime + Discord distribution.
- "The Universe System": creator (#713), template packs (#644 — the HV library IS the pack content: pack.json is the HV3 schema shipped externally), licensed universes v2.1–v2.4 (#330–#332: KOTOR-class recreations run on the same engine + a themed library), fan showcase policy (#711), paid-alpha original world (#712).
- "Engine as Platform": release the engine so others plug in their own renderers (the pure-consumer surface contract makes Unity/RPG-Maker/2D plugs identical in shape); the 2D pixel-art tier (#1145) graduates from filed option to the reference third-party-style renderer.
- The old "Phase C — Rendered Game" (#645) is DELIVERED BY the W-series — #645 closes as superseded when W5's T3 gate passes. #1045 Unreal fidelity tier stays deferred until the Unity path caps.
| Item | Needed by | What the owner must do |
|---|---|---|
| Apple Developer cert + notarization creds | S10 start | provision cert into Keychain (#151) |
| Sparkle signing key | S10 start | generate/store key (#134) |
| Licensing: Owlcat/OpenWorlds reference assets | before S8 art ships | #122 audit sign-off |
| Fan-showcase / user-content policy | milestone 26 | #711 policy call |
| Asset-Store purchases (if S2/S9 need packs) | as flagged | purchase + import to local Unity project |
| Unity host capacity/renewal | continuous | local Mac Unity seat |
| Paid-alpha pricing | Phase B | business call (#712) |
#1302 render-delivery DECISION (S2-entry blocker) · #1303 Action-Replay→Animator/VFX
wiring (incl. death topple/fade) · #1304 L7 motion-reel first run · #1305 monster wave 2 +
ghoul clips · #1306 demo dungeon authoring (room-unit graph) · #1307 time_of_day on
/combat-surface · #1308 run-level duo resume (constructive half of #1285).
Charters live: #1309 (S2 — The Felt Demo Loop, incl. the FELT control-anchored gate) ·
#1310 (S3 — Combat Readability, incl. the confusion-bug taxonomy). Later charters (S4+) are
authored from §4 when their predecessor's gate passes — same template.
The milestone: an AGENT plays "The Crypt Below" (adventure_demo_v1) end-to-end in the WorldOS player, unassisted (owner ruling 2026-09-02 — the agent plays first; the owner tests only at the 80/20 wall): camp hub → Keeper Maera (visible, quest accepted) → crypt (visible goblins, combat runs AND CLOSES with XP) → throne (visible boss, fight completes) → return → reward → quest_completed — with ZERO user-truth defects. Demo completion proves the system can build the rest.
Proven by four gates (checkable, never narrative):
- G1 — the certification gates that EXIST run green against the INSTALLED build, verified by
build identity: the app self-reports its build stamp via the /app-status contract (WorldOS-GUI-RUNBOOK §app-status; viewer/server.py), and the gate evidence records the
SAME stamp — a mismatch is a G1 FAIL (the certified-build ≠ installed-build class, #1651).
Today that means walk_static (CI) + the paint-coherence gate + the A-T/A-G evals run against the
installed pair; G1 UPGRADES to the full
player_certsuite when §9.2 lands (a proof clause may only reference gates that exist). - G2 — arc-duo eval: completion at bar with behavioral GREEN (surface=adventure, av_ ruler).
- G3 — walked-arc eval GREEN over the FULL arc route INCLUDING the return-for-reward leg back to the giver (navigation + cast presence + VQA stages at every leg).
- G4 — AGENT playthrough (owner ruling 2026-09-02): an agent playthrough observes ZERO P1 user-truth defects of ANY class (walk-through, invisible actor, dead door, spawn-in-furniture, stuck UI panel) across TWO CONSECUTIVE builds, and then a BLIND agent persona completes the arc. The owner tests only at the 80/20 wall (the residual unknown-unknowns absorber).
Decision record:
docs/decisions/DESIGN-MEMO-2026-09-02.md§1.
Two passes per build. Pass 1 = a walkaround with NO DM (navigation/doors · collision-vs-paint ·
actors/occlusion · legibility · viewer). Pass 2 = the story against the live DM through the DM-only
loop (qa/agent_play.sh) — the same code path the installed instance's DM agent runs, so a human at
the viewer and an agent play ONE game.
Multi-lens, multi-pass, reproduce-before-file. One pass finds about half the bugs and lenses are blind to each other, so every build gets multiple lenses across both passes. Every candidate finding is REPRODUCED by a DIFFERENT agent on a FRESH sandbox before it is filed — VLM lenses throw false positives on near-contact geometry and partial occlusion, exactly the silhouette/proxy class this demo hits. An unreproduced observation is not a defect.
Defect contract — every filed defect carries: room · cells · what a player would say · the frame
the reporter looked at · the /debug line · repro · layer (engine grid / seed / sidecar / client
render / plate / viewer) · severity P1–P3.
Score row (qa/SCORECARD.md, surface agent_g4): P1 / P2 / P3 counts, route completion,
legibility median per room, actor-luminance floor, frames per room. A build advances only at
P1 = 0; two consecutive P1 = 0 builds, then a blind persona completing the arc, close G4.
The 80/20 wall, defined. A defect whose fix needs a NEW SUBSYSTEM (> 1 day) or a TASTE FORK with two good answers. Only these escalate to the owner, and the escalation carries the frames, what was tried, and the options — never raw lens output (testers anchored by AI errors decide worse).
- ⊘ #1645 combat lifecycle (M) — DM closes fights (action economy, end_combat, XP, time-advance).
- ⊘ #1639 cast presence (M) — rest surface emits NPC + live-monster tokens; client renders them.
- ⊘ #1522 parley-panel lifecycle (S) — CloseParley() from the location-change path (sits on the demo's FIRST beat: Maera parley → door-cross). UI/panel lifecycle is a NAMED demo property.
- ⊘ #1647 wave 1 (S-M) — coherence-aware spawns/arrivals (instrument merged; relocation in flight); silhouette fix + door hotspots (#1649); #1584 spawn test wired into CI.
- ⊘ ONE local build carrying the client fixes → sandbox gates → owner install (install gate = §9.2).
- Camp HUB (fork-dependent): regen geometry is GREEN; ships as greybox-composite / #1642-lit / 3D-first per the spike outcome.
- ⊘ #1642 alive plates (M) — normal pass + light composite (batch with build 5 when ready).
- #83 THE 3D SPIKE — decides room construction FORWARD; not demo-blocking. SPIKE EXIT CRITERIA (red-team): per-actor silhouette-per-submesh + spawn-centroid assertions over the NEW crypt roster — the 3D re-author must not reintroduce either decayed class.
qa/player_cert— CHARTERED WORK (L), not an aspiration: fold walk_test + adventure_walk + journey_eval + the user-truth stages + a combat-lifecycle probe into ONE tri-state command. SPLIT (red-team F1): a CI-RUNNABLE static/headless half (every PR) and a LOCALLY-HOSTED live half with a NAMED trigger — a local Editor session + owning runbook step + a version-stamp the owner app self-reports on launch, diffed against the latest cert run (drift is loud, not silent). ROSTER-COMPLETE (F2): live properties iterate the FULL actor roster; any roster addition is a trigger event re-running the applicable property set against the new member. BUILD ORDER (red-team sequencing): the two shared assertion PRIMITIVES first — silhouette-per- submesh and spawn-centroid — consumed by the #83 spike immediately, aggregated by player_cert.qa/features.json+ lint — the EXECUTABLE feature registry: every shipped capability row binds to a gate assertion id; CI fails on unbound rows or orphan gates. Docs inform; only red CI enforces (archaeology case 6: a written runbook rule recurred anyway).- Known-hole SLA — player-feelable holes cannot defer past the next box build; every deferral names the gate that guards it meanwhile.
- Rebuild-not-patch — rooms failing registration/coherence are REGENERATED through the current chain, never hand-patched; the cert-required lint (#1644) keeps retired plates unshippable.
Decision record:
docs/decisions/DESIGN-MEMO-2026-09-02.md§2. §9's four gates define DONE for a BUILD. This defines DONE for a WORLD — the finish linedocs/ACTIVE-GOAL.mdpoints at.
A world is DONE when, on ONE installed build with recorded identity:
- Rooms — every room in the world graph is walk-certified EXHAUSTIVE and per-object-aligned at the calibrated registration floor.
- Doors — every door crosses BOTH ways with that room's camera pin.
- Actors — actors read as lit figures at the luminance floor, with NO silhouette in the open.
- Text arc — completes ≥ 0.67 VERIFIED at the recorded ruler, with pinned model ids per row.
- Walked arc — GREEN over the FULL route INCLUDING the return-for-reward leg.
- Agent G4 — zero P1 user-truth defects in TWO CONSECUTIVE builds (protocol above).
- Blind persona — a persona that never authored the world completes the arc.
- The wall — the owner's 80/20 wall, if hit, was RESOLVED: an option chosen and its fix landed.
First world = "The Crypt Below" (5 rooms: camp_clearing, tavern_snug, shop, crypt, throne_hall). Second = the town (6–10 rooms, Track C / C1). A world failing any clause is not "mostly done" — it is a world with an open clause and a named owner for it.
Two-anchor calibrated panels; av_ ruler for adventure aggregates; blind adjudication wherever an author would judge their own work; honest negatives are progress and get scorecard rows.