← Back to Lab

Porting a simulation to PHP changed the test plan

We moved an existing server simulation to PHP, then followed one real resident design through engine acceptance, construction and first use without turning that single chain into a general autonomy claim.

What we tried→What happened→What we learned→Decision

The problem

Antropo already had a browser world and server-side simulation behaviour, but the available hosting contract was PHP rather than the existing server runtime. The Owner chose a native PHP route instead of continuing with Sites. That was a product and hosting decision, not evidence that Sites had failed. The question was whether we could port the current behaviour without silently changing the game, losing the previous version or turning a large test count into a general correctness claim.

01

What we tried

  • We first measured the runtime that the existing hosting actually provided. We then translated the current server simulation and persistence boundary to native PHP while retaining the existing browser interface. The earlier Sites version stayed intact as a separate fallback and reference.
  • We split the port into small testable steps: state and time arithmetic, transactional storage, navigation, movement and then complete simulation scenarios. Each step compared selected PHP results with the existing JavaScript reference before the next layer was added.
  • We packaged public and server files separately, preserved the previous web version, rehearsed recovery and repeated a bounded runtime probe on the host. Publication was followed by exact public-file checks, access-boundary checks and a browser journey on desktop and mobile.
  • After release, we added a navigation route cache. Before timing it, we tested repeated lookups, copied return values, changed worlds, removed obstacles, different search radii, cached failures, opened gates, narrow exits and reload invalidation. The performance question came after the stale-route question.
  • A later evidence pass followed the one already authorised shelter rebuild through four separate states: accepted design, planned replacement, work in progress, and completed structure with first use. We matched the rebuild identifier, design request, design fingerprint, resident designer, components, contributors and event times across the preserved records. The pre-build and completed records also share the world start identifier; the intermediate progress record does not contain that field and is linked through the same rebuild and design identity.

02

What happened

  • The completed comparison suite reported 326,966 matching results across the selected deterministic scenarios, including a 1,200-world-second run and reload points. This is strong regression evidence for those cases, not proof that every simulation state is correct.
  • On the host, one synthetic starting family with four residents advanced 3,600 world seconds in 18.49 seconds of wall time. The run used about 18.31 CPU seconds and peaked at 10 MiB. It did not test a large old world, concurrent demand or sustained production load.
  • A later synthetic host comparison used 32 residents over 300 simulation seconds, with a complete snapshot round trip and an empty static cache every 120 simulation seconds. The old navigation code took 26.558687 seconds and the cached code took 4.956557 seconds, about 5.36 times as fast in this one comparison. Both ended with 32 residents and the same functional world hash after excluding the routeMisses diagnostic counter. This simulated reload boundaries rather than 300 separate HTTP requests.
  • The cached code also took 7.818347 seconds when the snapshot round trip happened every three simulation seconds. We did not run the old code under that cadence, so this result has no old-versus-new speed comparison.
  • The release package contained 61 manifest-bound files. An independent final check matched all 27 public static files and repeated the public session, world-access and configuration-boundary responses. The executor's browser receipt covered registration, a four-resident world, an advancing server clock, mobile viewing, logout and return to the same world; the General Manager did not repeat that account journey.
  • The previous webroot and the earlier Sites version were retained. No existing PHP world data required migration. Recovery material was prepared before the switch, and the live version was kept after public verification.
  • In the preserved world at revision 1,565, Mira’s accepted design contained 12 parts and the replacement site still had progress zero. At revision 1,625, the same rebuild was in progress at about 0.359, with separate wood, dismantling and building contributions for Mira and Bo. At revision 1,658, the status was built, progress was one and their recorded building contributions summed to the design requirement of 188 work units. Events then recorded Bo and Mira using the new shelter at world times 20,301.8 and 20,309.4.
  • The operator handoff states that this was the same one-off trial, without synthetic acceleration, direct world-state editing or a second trigger. The pre-build and completed snapshots support one world start identifier, while all three records retain the same rebuild and design identity and advance in revision order. We did not observe every intervening update and therefore keep the no-intervention statement attributed to the handoff.

03

What we learned

Parity is a coverage map, not a correctness certificate. A large number is useful only when the scenarios, reference implementation and excluded states remain visible.
Changing server runtimes changes the proof required around the simulation. Integer time anchors, transactions, ownership, retries, sessions and catch-up limits needed separate checks even when the browser looked the same.
A route cache is an invalidation contract before it is a speed optimisation. Equal end-state hashes and faster timing would not expose every stale intermediate route, so changes to obstacles, gates, radii, failed searches and reloads needed their own regression cases.
Preserving the old version made the port reversible and kept the comparison honest. Choosing PHP did not require rewriting the history as a platform failure.
A fast synthetic run is a bounded feasibility result. It cannot support claims about production scale, concurrent users, long-running worlds or cost savings without separate measurements.
Engine acceptance is an intermediate contract, not the outcome. For a design-to-world feature, the evidence chain needs one stable request identity through accepted geometry, build state, separately attributed work, completion and actual use. Later completed designs exist in the source history, but they are outside this bounded shelter lesson and do not broaden its conclusion.

The decision

ADOPT. Keep the native PHP port and tested route cache, and require the same design-to-engine-to-build-to-use chain for future AI-directed world changes. Retain the previous version and recovery evidence. Treat this one completed shelter rebuild, the parity suite and the cache tests as bounded evidence for their recorded cases only; require separate old-world, concurrent-request, sustained-load, backup and physical-device evidence before making autonomy, scale, reliability or cost claims.

What this means next

Observe the live port within its current limits. Preserve the completed shelter as the canonical rebuild trial and do not retrigger it. Evaluate later structures under their own evidence boundaries rather than using them to inflate this result. Test actual concurrent HTTP requests and compare both navigation implementations under the same frequent-reload cadence before extending performance claims.

Open Antropo →