Steps 7–24: Persistent WebXR Disability World + Wolfram-grounded algorithms - #2
Steps 7–24: Persistent WebXR Disability World + Wolfram-grounded algorithms#2ausdisau wants to merge 46 commits into
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
| constructor(seed: PersistentWorldState = initialOpenWorldState) { | ||
| this.state = JSON.parse(JSON.stringify(seed)) as PersistentWorldState; | ||
| this.restore(); | ||
| } |
There was a problem hiding this comment.
Seed ignored on restore
Medium Severity
PersistentWorldStore copies the provided seed, then restore() unconditionally replaces it with localStorage when any saved blob exists. Callers that pass initialOpenWorldState for a deterministic world still receive prior session state, with no version check or merge of new default entities.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 9cd6c22. Configure here.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9cd6c22763
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if(p.mobility.mode.includes('wheelchair')) { const chair=B.MeshBuilder.CreateBox(entity.id+'-mobility',{width:.85,height:.55,depth:1.05},scene); chair.position.set(p.position[0],.38,p.position[2]); chair.material=personMat; } | ||
| } | ||
| if(entity.kind==='infrastructure') { | ||
| const i=entity as InfrastructureEntity; const marker=B.MeshBuilder.CreateCylinder(entity.id,{height:1.5,diameter:.65},scene); marker.position.set(i.position[0],.75,i.position[2]); marker.material=i.operational?accessMat:unavailableMat; meshes.set(i.id,marker); |
There was a problem hiding this comment.
Keep infrastructure markers synchronized with state changes
When the lift is toggled after the scene has loaded, this material assignment is never revisited: toggleLift changes only the store, and the meshes map is otherwise unused. Consequently, an unavailable lift remains teal (or a restored unavailable lift remains red after being re-enabled) even while the status text reports the opposite state; update the marker whenever the infrastructure state changes.
Useful? React with 👍 / 👎.
| const saved = window.localStorage?.getItem('mert-open-world-v1'); | ||
| if (!saved) return; | ||
| try { this.state = JSON.parse(saved) as PersistentWorldState; } catch { /* retain safe seed */ } |
There was a problem hiding this comment.
Fall back when browser storage is unavailable
In browsers or embedded contexts where storage is blocked, accessing localStorage or calling getItem can throw a SecurityError, and this happens during PersistentWorldStore construction before the web world can render. The same issue affects the unguarded setItem in persist for denied or full storage, so storage access should be caught and treated as an in-memory fallback rather than crashing the application.
Useful? React with 👍 / 👎.
| this.state.events.push({ id: `${this.state.simulationSeconds}-${this.state.events.length}`, at: this.state.simulationSeconds, type, entityId, detail }); | ||
| this.state.events = this.state.events.slice(-100); |
There was a problem hiding this comment.
Generate unique IDs after the event buffer fills
Once the event list reaches 100 entries, slicing keeps events.length fixed at 100, so two mutations occurring before simulationSeconds advances both receive the same ${simulationSeconds}-100 ID. This corrupts identifier uniqueness in longer-running worlds and can make future event reconciliation or keyed rendering ambiguous; use a monotonic counter or another value that does not depend on the bounded array length.
Useful? React with 👍 / 👎.
| if (activity.kind === 'seek-alternative') { | ||
| signals.push({ node: 'environment', personId: person.id, metric: 'access-barrier', delta: 1, confidence: 0.95, cause: 'preferred route unavailable', provenance: 'deterministic-vnn' }); | ||
| signals.push({ node: 'fatigue', personId: person.id, metric: 'energy-demand', delta: 0.2, confidence: 0.7, cause: 'rerouting burden', provenance: 'deterministic-vnn' }); | ||
| } |
There was a problem hiding this comment.
False barrier on unmapped goals
Medium Severity
planNextActivity labels any accessible pick as seek-alternative when goalTarget returns no preferred id, and proposeDynamics always treats that kind as a blocked preferred route. That emits an environment / access-barrier signal and rerouting fatigue even when no preferred route existed or failed, inventing environmental causality.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit b74e6c1. Configure here.
| reasons: ['high-confidence health-state change proposed by bounded dynamics; requires scenario evidence gate'], | ||
| scenarioId: 'not-my-baseline', | ||
| preserve: { authority: true, baseline: true, communicationState: true, worldHistory: true }, | ||
| }; |
There was a problem hiding this comment.
Wrong clinical scenario identifier
High Severity
assessClinicalTrigger hardcodes scenarioId as not-my-baseline, but the registered scenario id is adl-ed-cp-aac-respiratory-001. When the bridge becomes eligible, bridgeToClinicalRuntime emits a scenario reference that no runtime scenario matches, so the clinical handoff cannot load the intended scenario.
Reviewed by Cursor Bugbot for commit 96626b5. Configure here.
| const fields = new Set([...Object.keys(leftEntity), ...Object.keys(rightEntity)]); | ||
| const changedFields = [...fields].filter((field) => JSON.stringify((leftEntity as any)[field]) !== JSON.stringify((rightEntity as any)[field])); | ||
| return changedFields.length ? [{ entityId: leftEntity.id, changedFields }] : []; | ||
| }); |
There was a problem hiding this comment.
Compare misses added entities
Medium Severity
compare only walks entities from the left snapshot. Entities present on the right but absent on the left are never reported, so counterfactual branches that add people, places, or infrastructure appear unchanged aside from shared ids.
Reviewed by Cursor Bugbot for commit 96626b5. Configure here.
| const active = currentSchedule(state, personId, entries); | ||
| if (!active) return 'No fixed activity: personal goals and accessible opportunities remain available.'; | ||
| return `${active.activity.toUpperCase()} · ${active.targetId ?? 'self-directed'} · ${active.flexible ? 'flexible timing' : 'time-specific'}`; | ||
| } |
There was a problem hiding this comment.
Orphaned schedule module
Medium Severity
schedules.ts defines a second daily-schedule model (defaultDailySchedules, currentSchedule, scheduleSummary) that is never imported. The live loop uses dailyLife.ts instead, so this module is dead code with overlapping concepts.
Reviewed by Cursor Bugbot for commit c7729d9. Configure here.
| at: state.simulationSeconds, | ||
| type: 'daily-life.activity.planned', | ||
| entityId: person.id, | ||
| detail: `hour=${simulatedHour(state)}; goal=${scheduled.goal}; activity=${activity.kind}; target=${activity.targetId ?? scheduled.destinationId ?? 'none'}`, |
There was a problem hiding this comment.
Schedule destinations ignored
Low Severity
Schedule entries carry destinationId, but runDailyLifeTick only promotes the goal string into planning and never applies destinationId. The 08:00 entry targets transit while goal-based planning resolves move through the community to community-hub.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c7729d9. Configure here.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
There are 7 total unresolved issues (including 6 from previous reviews).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 9affbc3. Configure here.
| const requestSupport=()=>{runtime().requestSupport('maya','liam');setStatus('SUPPORT · Maya explicitly requested support from Liam');}; | ||
| const beginContinuity=()=>{runtime().beginContinuity('maya');setStatus('CONTINUITY · educational community deterioration episode started');}; | ||
| const advanceContinuity=()=>{runtime().advanceContinuity('maya');setStatus(`CONTINUITY · ${runtime().continuity().summary('maya')}`);}; | ||
| const resetWorld=()=>{storeRef.current!.reset();setStatus('WORLD RESET · reload to reseed population');}; |
There was a problem hiding this comment.
Reset leaves engines stale
Medium Severity
resetWorld only resets the PersistentWorldStore. The live WorldRuntime keeps door, lift, charger, transport, encounter, and continuity state, so after reset the UI can show mid-move lifts, boarded passengers, open doors, and active clinical episodes against a freshly seeded world.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit 9affbc3. Configure here.


Extends MERT into a persistent multi-person disability world model and WebXR open world. Steps 7–20 provide persistent people/places/infrastructure, bounded autonomy, affordances, VNN proposals, social agents, counterfactual timelines, semantic VR interaction and one WorldRuntime. Steps 21–24 add Wolfram-grounded accessible route planning, stateful doors/lifts/AAC charging/transport boarding, proximity + relationship social encounters with explicit support requests, and world→clinical→world continuity that preserves authority, communication state, baseline and history. Simulation tuning values are educational parameters, not accessibility-code thresholds or clinical-treatment guidance. Tests cover route barriers, Wolfram-derived motion/charging equations, social support non-assumption, continuity adjacency and authority preservation.
Note
Medium Risk
Large new simulation and clinical-continuity surface area; behavior is heavily test-guarded but WebXR + localStorage persistence add integration and state-restoration risk.
Overview
Introduces a persistent open-world simulation (
PersistentWorldStore, people/places/infrastructure) with invariants that keep decision authority on the person, attribute barriers to the environment, and treat unavailable AAC as unknown rather than incapacity.A single
WorldRuntimetick loop ties together daily-life scheduling, affordance-based autonomy, VNN dynamics proposals, social agents/encounters, accessible route planning, object interactions (doors, lift, AAC charging, shuttle), evidence-gated clinical bridge, and continuity episodes back to community—with Scenario Studio validation blocking silent authority changes.OpenWorldWebis rewired from static Babylon scenery to drive meshes and HUD from the store/runtime (routes, access, encounters, facilitator controls). The mobile companion shows AAC reliability and decision authority and adds the diagnostic-overshadowing scenario choice with accessibility labels.Broad test coverage encodes these disability-world invariants across integration, navigation, objects, and continuity.
Reviewed by Cursor Bugbot for commit 9affbc3. Bugbot is set up for automated code reviews on this repo. Configure here.