Skip to content
Courtyard

Under the hood

Builds & validation

Build instructions, verification results and platform limitations.

On this page

Living worlds — October 5, 2026

The default entry point now generates a community and three matched futures: Guide, Collaborate and Let it grow. The original annual model remains accessible with --lab; existing saves and replay formats remain separate. See living worlds for the new model boundary and portable contract.

Verified locally: 887 simulation checks + 14 evening scene checks + 56 annual scene checks + 50 living-world scene checks = 1,007 checks, all passing.

  • Simulation checks cover repeated seeds, 40 buildable starting worlds, independent locked layers, exact starting conditions, collision rejection, pure previews, paid work queues, live-state preservation, construction energy accounting, autonomous growth, protection, modded priorities, full-year monetary and utility balances, bounded histories, and recorded-decision replay.
  • The living-world scene suite exercises preview/cancel/confirm, pause, matched progression, render rebinding, staged import success and failure, and all panels at 390×844, 844×390 and 1440×900. Earlier lab and evening scene suites still pass.
  • Native desktop and portrait renders were inspected. Browser WebGL loaded the new default, ran one week, switched futures, rendered resident additions, and exercised the 390×844 Scene toggle. No browser warnings or errors were observed in that session.
  • Browser ZIP export was downloaded, replayed through the native headless runner, repackaged and reimported through the browser file chooser. At hour 168, Guide / Collaborate / Let it grow showed 0 / 1 / 3 completed projects, 720 / 720 / 870 cold person-hours and €800.60 / €808.61 / €815.61 operating costs. The browser restored the same displayed outcomes and its pending project.

Three six-home futures over 30 days took approximately 0.80 seconds in one headless run on this Apple M1 Max, excluding startup. This is a local observation, not a low-end-device benchmark. Simulation work is bounded between rendered frames; world generation and individual daily planning steps are atomic.

The website uses actual in-engine screenshots of the three futures after 30 days. Run scripts/capture_living.gd with --living-test to regenerate them. The new guide is included in the Astro site, search index and local-link validation.

Physical phones, sustained thermal/power measurements, novice usability testing and empirical calibration remain unverified. The release provides a bounded recipe planner, ground-level room geometry and a one-year fixed cohort. It does not implement unbounded worlds, general autonomous invention, a local material supply chain, natural-disaster mechanics or generational simulation.

python3 scripts/check.py
godot --path . --script tests/living_playable.gd -- --living-test
godot --headless --path . --script scripts/run_living.gd -- --seed=2406 --hours=720 --output=/tmp/futures.json
# Browser QA without autosaving: http://localhost:8060/?living-test

Annual community lab — October 4, 2026

At this milestone the default entry point was Warm homes, shared systems; it is now available with --lab. The earlier evening game is available with --evening, and the foundation with --foundation; their save files and model paths are preserved. See the lab guide for the data contract and numerical boundaries.

CheckObserved result
Simulation and mod API765 checks passed, including annual stock/energy/cash reconciliation, analytical thermal fixtures, capacity failures, supported loads, schema/dependency rejection, full weather CSVs, archive bounds and exact replay
Evening scene regression14 checks passed
Annual scene/controller56 checks passed: form-created mod, layout/undo, pause/continue, matched year, import/replay, rejected import preservation, rendered temperature binding, and all five panels at 390×844, 844×390 and 1440×900
Native rendered labDesktop and portrait annual smoke runs completed and inspected; rendering uses the active run rather than the original draft
BrowserWebGL 2 load, wall selection, complete annual comparison, ZIP download and file-chooser reimport completed; no console errors or warnings observed; portrait comparison inspected
Portable file exchangeThe browser download was found in Downloads and replayed by the native headless runner. Its two reports matched the native reference run. The browser then imported that ZIP and returned to the same displayed annual results
CLI and packagingFull-year JSON output and experiment ZIP round trip reproduced both reports; v1 and v2 packaging passed; v2 archive validated with the host compiler
ExportsUpdated Web, macOS and Android development builds completed without script/export errors

Local simulation timing on this Apple M1 Max: one 24-person year took 900 ms in the headless test; two matched years through the CLI took 1,755 ms, excluding startup/compilation and output serialization. These are individual local observations, not low-end hardware or sustained-phone benchmarks. The UI uses a bounded work budget between frames.

The default continental example produced 42,783 occupied cold person-hours for light timber and 4,551 for insulated timber. Insulation increased construction from €471,141 to €499,639. These values demonstrate the declared synthetic model and are regression evidence, not predictions about real buildings. Utility funding shortages contribute to year-end failures; the household inspector exposes the shared reserve, maintenance state and storage levels.

The browser’s automated download event observer timed out, but the actual archive was saved and successfully replayed. Native and browser float bit identity is not generally guaranteed; this one exported case and its displayed outcomes matched. Physical Android/iOS devices, Safari, accessibility/screen-reader coverage, native mobile file pickers, long thermal-soak tests and empirical calibration remain unverified. Prior iOS runtime limitations below still apply. No marketplace, arbitrary asset/code loading, general model modules or century simulation is implied by this slice.

python3 scripts/check.py
godot --headless --path . --script scripts/run_lab.gd -- --assembly=core:warm_wall --hours=8760
godot --path . -- --lab-smoke --screenshot=artifacts/lab-desktop.png
godot --path . --resolution 390x844 -- --lab-smoke --screenshot=artifacts/lab-phone.png
# Browser QA without modifying saves: http://localhost:8060/?lab-test

Evening playable validation — October 2, 2026

At that milestone the default entry point ran An evening back; it is now selected with --evening. The original sandbox and its measured rendering baseline remain available with --foundation (the existing --smoke / --benchmark flags still select that model).

CheckResult
Simulation/extension suite608 checks passed, including service alternatives, stock and money reconciliation, utility failures, worker tradeoffs, invalid definitions/reports and deterministic mid-service save continuation
Actual scene/controller suite14 checks passed: scenario startup, service placement, incremental reference comparison, reset/notebook, custom recipe, portrait inspector/rotation and landscape control separation
Native rendered scenario1440×900 desktop and 390×844 portrait smoke runs completed; final result and responsive layout inspected
In-app browserInitial load, route preview, six-hour trial, matched comparison, save reload, workshop JSON validation/placement and fresh-start backup flow exercised; no reported browser warnings/errors
Web, macOS and AndroidUpdated debug exports completed without export/script errors

The browser mod-export action reported a ready download, but the automation download observer did not capture the archive. Archive delivery and mobile file pickers still need ordinary-browser/device testing. The new scene smoke runs are short functional checks, not a new performance benchmark or physical-phone measurement. Physical phones and the prior iOS runtime blocker remain outstanding.

python3 scripts/check.py
godot --headless --path . --script tests/playable.gd -- --evening-smoke
godot --path . -- --evening-smoke --screenshot=artifacts/evening-desktop.png
godot --path . --resolution 390x844 -- --evening-smoke --screenshot=artifacts/evening-phone.png

See the playable guide for implemented mechanics, synthetic balancing assumptions, data-mod boundaries and remaining work. AI creation currently uses exported prompts and validated pasted definitions; no model provider is integrated.

Godot 4.7.2 standard (GDScript), using Compatibility/OpenGL/WebGL 2. Run from the repository root. Export templates must match the installed editor; the official 4.7.2 archive was checked against its published SHA-512 checksum.

Build

mkdir -p exports/web exports/macos exports/android exports/ios exports/windows exports/linux
python3 scripts/check.py
godot --headless --path . --export-debug Web exports/web/index.html
python3 scripts/serve.py
# Open http://localhost:8060 in a WebGL 2 browser.

godot --headless --path . --export-debug macOS exports/macos/CourtyardBlock.zip
godot --headless --path . --export-debug Android exports/android/courtyard-block.apk
godot --headless --path . --export-debug Windows exports/windows/CourtyardBlock.exe
godot --headless --path . --export-debug Linux exports/linux/courtyard-block.x86_64

Android requires a JDK, current Android SDK platform/build tools, Godot’s Android SDK editor setting, and a debug keystore. This machine’s old build-tools 27 signing utility failed on modern Java; installing build-tools 36.0.0 resolved signing. The APK is a development build. Use current platform-tools/ADB to install it; old ADB versions caused emulator connection failures.

adb install -r exports/android/courtyard-block.apk
adb shell monkey -p org.courtyardblock.game -c android.intent.category.LAUNCHER 1

Web exports are single-threaded with no GDExtension dependency and do not require cross-origin isolation headers. Serve HTTP locally or HTTPS remotely; do not open index.html as a file: URL. Source GDScript export is intentional: the loader reads entry scripts for pack fingerprints, and runtime trusted source mods must remain supported. Do not switch to bytecode export without updating that contract.

iOS

The checked-in iOS preset exports an Xcode project. Real device development needs your Apple team ID and provisioning; the preset intentionally leaves that identity empty.

For an unsigned simulator project:

python3 scripts/export_ios_simulator.py
xcodebuild -project exports/ios/CourtyardBlock.xcodeproj \
  -scheme CourtyardBlock -configuration Debug -sdk iphonesimulator \
  -derivedDataPath exports/ios/build CODE_SIGNING_ALLOWED=NO \
  ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO

The script uses a temporary project with a SIMULATOR placeholder solely to pass Godot’s project-export validation. It does not sign or invent a development identity. The installed official template has an x86_64 simulator library; an arm64 simulator link failed with architecture errors. The x86_64 build succeeds and installs on an iOS 17.2 iPhone 15 Pro simulator, but execution stalled at OpenGL ES context initialization. A launch with the Mobile renderer also failed to produce a playable scene. iOS runtime support is not yet validated. Resolve the simulator/template graphics path and test a provisioned physical device before declaring iOS ready.

Original foundation verification record

Tested on an Apple M1 Max Mac running macOS 26.7, October 2, 2026. Browser: headed Chromium 154, device pixel ratio 1, 1440×900 canvas.

CheckResult
Headless simulation/extension suite550 checks passed
Seven-day seeded replay with 150 residentsIdentical outcomes across two runs
JSON round trip and continuationPreserved outcomes at full precision
Malformed data, missing/cyclic dependencies and duplicate IDsRejected; live state and successful registrations preserved
External zipped GDScript packInstalled and loaded at runtime
Native rendered gameRendering, furnishing, floor cutaway and simulation smoke passed
Chromium WebGL 2 gameLoaded with no console errors; resident inspection, furnishing, fork/switch/week comparison and JSON export exercised
Landscape mobile layout844×390 browser/native layout inspected; Android menu and touch exercised
Android development APKExported, signed, verified, installed and rendered on an ARM64 API 35 emulator
Windows/Linux x86_64Exported successfully; execution not tested on this Mac
iOS project/simulator buildExport and x86_64 build passed; runtime graphics blocked
Physical phones, thermal soak, Safari and low-end PCsNot tested

The API 35 emulator uses SwiftShader/ANGLE; its rendering performance is not a phone GPU measurement. iOS simulator success would likewise not establish physical-device performance.

Performance protocol

godot --path . -- --smoke --benchmark
# Browser: http://localhost:8060/?benchmark

Reference load: 150 residents, seven storeys, 5,000 extra primitive objects and 10,000 extra catalogue definitions (10,007 total). All floors are visible; simulation runs at 20×. Static geometry is instanced; these objects are not 5,000 independent physics bodies. The stress objects are synthetic geometry, not 5,000 persisted furnishing slots. This measures steady-state overview rendering and active simulation, not construction spikes, arbitrary custom meshes or catalogue-search latency. The benchmark records monotonic wall-clock intervals between frames after 120 warm-up frames, then samples 3,600 frames. It reports p95, p99, maximum and simulation-step p95. Browser results appear in window.courtyardBenchmark and the console; native results are written to artifacts/native-benchmark.json when running from the project, or user://benchmarks/native-benchmark.json from an exported app.

Target: p95 ≤16.7 ms. Final exported macOS debug build (1440×900, M1 Max): 13.409 ms p95, 14.364 ms p99, 15.718 ms maximum over 3,600 measured frames. Simulation p95 was 2.291 ms across 625 ticks. This meets the local 60 fps frame-time target. Browser debug build at the same load: 9.2 ms p95, 9.3 ms p99, 9.7 ms maximum; simulation p95 3.6 ms across 625 ticks. Both local targets passed. These are wall-clock measurements; earlier _process(delta) measurements were superseded because engine smoothing concealed some frame variation. A 30–60 second desktop run is not a sustained mobile thermal test. Mod behavior, mesh/material diversity, layout complexity, drivers and browser scheduling can change performance substantially.

Remaining gates

  • Provision and exercise an iOS device build; resolve simulator graphics startup.
  • Run at least 15 minutes on physical iPhone 13/Pixel 7-class hardware, including low-power/thermal conditions.
  • Check Safari, mobile file pickers, pinch gestures and safe-area behavior on real devices.
  • Measure a low-end integrated-GPU desktop; add quality settings based on observed limits.
  • Extend save migrations and pack fingerprints to arbitrary helper scripts/assets.
  • Add physical utility capacities, stock inventories and richer employment/activity systems.

The current utility model tracks demand, expense and financial reliability. It does not yet simulate pipe networks or resource storage. See model assumptions for the implemented economic boundary.