Skip to content

Steps 7–24: Persistent WebXR Disability World + Wolfram-grounded algorithms - #2

Open
ausdisau wants to merge 46 commits into
feat/steps-1-6-world-state-vnnfrom
feat/step-7-persistent-open-world
Open

Steps 7–24: Persistent WebXR Disability World + Wolfram-grounded algorithms#2
ausdisau wants to merge 46 commits into
feat/steps-1-6-world-state-vnnfrom
feat/step-7-persistent-open-world

Conversation

@ausdisau

@ausdisau ausdisau commented Aug 16, 2026

Copy link
Copy Markdown
Owner

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 WorldRuntime tick 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.

OpenWorldWeb is 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.

@coderabbitai

coderabbitai Bot commented Aug 16, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 108cbc55-2b5c-4947-9841-b95e88c39354

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread src/world/OpenWorldWeb.tsx Outdated
Comment thread src/world/worldModel.ts
constructor(seed: PersistentWorldState = initialOpenWorldState) {
this.state = JSON.parse(JSON.stringify(seed)) as PersistentWorldState;
this.restore();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9cd6c22. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/world/OpenWorldWeb.tsx Outdated
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/world/worldModel.ts
Comment on lines +117 to +119
const saved = window.localStorage?.getItem('mert-open-world-v1');
if (!saved) return;
try { this.state = JSON.parse(saved) as PersistentWorldState; } catch { /* retain safe seed */ }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Comment thread src/world/worldModel.ts Outdated
Comment on lines +106 to +107
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);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

@ausdisau ausdisau changed the title Step 7: Persistent open-world entity system Steps 7–10: Persistent open world, autonomy, affordances and VNN dynamics Aug 16, 2026
Comment thread src/world/vnnDynamics.ts
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' });
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b74e6c1. Configure here.

Comment thread src/world/vnnDynamics.ts
Comment thread src/world/affordanceGraph.ts
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 },
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 96626b5. Configure here.

Comment thread src/world/timeline.ts Outdated
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 }] : [];
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 96626b5. Configure here.

Comment thread src/world/liveWorldLoop.ts Outdated
Comment thread src/world/OpenWorldWeb.tsx Outdated
Comment thread src/world/liveWorldRuntime.ts Outdated
Comment thread src/world/schedules.ts
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'}`;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c7729d9. Configure here.

Comment thread __tests__/liveWorldIntegration.test.ts
Comment thread src/world/dailyLife.ts Outdated
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'}`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit c7729d9. Configure here.

Comment thread src/world/OpenWorldWeb.tsx Outdated
Comment thread src/world/population.ts
@ausdisau ausdisau changed the title Steps 7–10: Persistent open world, autonomy, affordances and VNN dynamics Steps 7–24: Persistent WebXR Disability World + Wolfram-grounded algorithms Aug 16, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Fix All in Cursor

❌ 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');};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 9affbc3. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant