-
Notifications
You must be signed in to change notification settings - Fork 0
Steps 7–24: Persistent WebXR Disability World + Wolfram-grounded algorithms #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ausdisau
wants to merge
46
commits into
feat/steps-1-6-world-state-vnn
Choose a base branch
from
feat/step-7-persistent-open-world
base: feat/steps-1-6-world-state-vnn
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
a166108
Add persistent open-world entity and accessibility model
ausdisau f5440b2
Connect WebXR world to persistent entities and accessibility state
ausdisau 9cd6c22
Test persistent world accessibility causality
ausdisau 63e47ad
Add environment affordance graph
ausdisau 6106173
Add bounded autonomous daily-life planner
ausdisau d30f4cc
Add bounded VNN world dynamics modules
ausdisau b74e6c1
Test autonomous planning and disability world invariants
ausdisau 4e96ea5
Add bounded social multi-agent layer
ausdisau aedc85b
Bridge open-world events into MERT clinical runtime
ausdisau 33de785
Add counterfactual timeline and replay engine
ausdisau 998a258
Add modality-neutral VR interaction contract
ausdisau 96626b5
Test social agents clinical bridge timeline and VR parity
ausdisau c9e333f
Extend world store for live simulation integration
ausdisau abd7b59
Add persistent daily life schedules
ausdisau 055c5ae
Wire planners dynamics social and clinical bridge into live loop
ausdisau 0781c26
Add open world scenario studio model
ausdisau 94ba8ef
Wire autonomous world systems into live runtime
ausdisau 04de7b2
Wire live world dynamics into Babylon WebXR scene
ausdisau 7fdd228
Add persistent daily schedule system
ausdisau ccd9a2a
Test live world integration and studio safeguards
ausdisau 3b79344
Fix live runtime timeline integration
ausdisau a49683a
Advance autonomous people through live world
ausdisau c7729d9
Test live open-world integration
ausdisau 8c56096
Add entity upsert for multi-person world runtime
ausdisau 339a6d2
Add multi-person population and relationships
ausdisau a5a2d43
Add semantic spatial interaction and wayfinding
ausdisau 7718b2e
Consolidate authoritative world runtime with population schedules
ausdisau dcc1880
Wire consolidated runtime and semantic nearby interactions into WebXR…
ausdisau 0a1497e
Test consolidated runtime population and spatial interaction
ausdisau 7fb02f8
Add Wolfram-grounded accessible navigation
ausdisau 66a5cf7
Add Wolfram-grounded object interaction dynamics
ausdisau ba1363e
Add Wolfram-grounded social encounter model
ausdisau 28d0c3c
Add persistent world clinical continuity engine
ausdisau 775bec2
Integrate navigation objects encounters and continuity into WorldRuntime
ausdisau f0e7e2a
Display Wolfram-grounded Steps 21-24 in WebXR world
ausdisau 02870d2
Test Wolfram-grounded Steps 21-24 algorithms
ausdisau 0321609
Fix strict ref typing in WebXR world
ausdisau 90d7f95
Fix strict navigation typing
ausdisau 2c4dc7f
Fix strict autonomy typing
ausdisau b4e227a
Fix strict daily schedule typing
ausdisau 2068d32
Collapse deprecated runtime onto WorldRuntime
ausdisau a4d4cfe
Fix Scenario Studio strict entity typing
ausdisau b23d106
Fix timeline exact optional typing
ausdisau 2e23314
Fix strict live world tests
ausdisau 23b22a2
Fix strict advanced world tests
ausdisau 9affbc3
Restore accessible companion controls and state labels
ausdisau File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { LiveWorldLoop } from '../src/world/liveWorldLoop'; | ||
| import { PersistentWorldStore, initialOpenWorldState, type PersonEntity } from '../src/world/worldModel'; | ||
| import { addInfrastructure, validateWorldDraft, type WorldStudioDraft } from '../src/world/scenarioStudio'; | ||
|
|
||
| function memoryStore() { | ||
| return new PersistentWorldStore(initialOpenWorldState); | ||
| } | ||
|
|
||
| describe('live disability world integration', () => { | ||
| test('autonomous travel changes position without changing person authority', () => { | ||
| const store = memoryStore(); | ||
| const before = store.entity('maya') as PersonEntity; | ||
| const start = [...before.position]; | ||
| const loop = new LiveWorldLoop(store); | ||
| loop.step(3); | ||
| const after = store.entity('maya') as PersonEntity; | ||
| expect(after.position).not.toEqual(start); | ||
| expect(after.authority).toBe('self'); | ||
| }); | ||
|
|
||
| test('infrastructure failure remains an environmental event', () => { | ||
| const store = memoryStore(); | ||
| store.setInfrastructure('station-lift', false); | ||
| const event = store.snapshot().events.at(-1); | ||
| expect(event?.type).toBe('infrastructure.changed'); | ||
| expect(event?.detail).toContain('unavailable'); | ||
| expect((store.entity('maya') as PersonEntity).authority).toBe('self'); | ||
| }); | ||
|
|
||
| test('Scenario Studio rejects silent authority reassignment', () => { | ||
| const draft: WorldStudioDraft = { title: 'Test', description: 'Test world', seed: initialOpenWorldState }; | ||
| const extended = addInfrastructure(draft, { id: 'test-ramp', label: 'Test ramp', position: [0,0,0], feature: 'ramp', accessibility: ['powered-wheelchair'] }); | ||
| expect(validateWorldDraft(extended).filter(issue => issue.severity === 'error')).toHaveLength(0); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| import { defaultSchedules, runDailyLifeTick } from '../src/world/dailyLife'; | ||
| import { LiveWorldLoop } from '../src/world/liveWorldLoop'; | ||
| import { addInfrastructure, exportWorldDraft, validateWorldDraft } from '../src/world/scenarioStudio'; | ||
| import { initialOpenWorldState, PersistentWorldStore, type PersonEntity } from '../src/world/worldModel'; | ||
|
|
||
| describe('live disability world integration', () => { | ||
| it('plans daily life without replacing person authority', () => { | ||
| const schedule = defaultSchedules[0]; | ||
| expect(schedule).toBeDefined(); | ||
| if (!schedule) return; | ||
| const tick = runDailyLifeTick(initialOpenWorldState, schedule); | ||
| expect(tick.activity?.personId).toBe('maya'); | ||
| const maya = initialOpenWorldState.entities.find((entity): entity is PersonEntity => entity.id === 'maya' && entity.kind === 'person'); | ||
| expect(maya?.authority).toBe('self'); | ||
| }); | ||
|
|
||
| it('runs the bounded world loop and records dynamics events', () => { | ||
| const store = new PersistentWorldStore(initialOpenWorldState); | ||
| const loop = new LiveWorldLoop(store); | ||
| loop.step(6); | ||
| expect(store.snapshot().events.some((event) => event.type.startsWith('vnn.'))).toBe(true); | ||
| }); | ||
|
|
||
| it('scenario studio validates duplicate IDs and authority invariants', () => { | ||
| const draft = { title: 'Test', description: '', seed: initialOpenWorldState }; | ||
| const withDuplicate = addInfrastructure(draft, { id: 'station-lift', label: 'Duplicate lift', position: [0,0,0], feature: 'lift', accessibility: ['powered-wheelchair'] }); | ||
| expect(validateWorldDraft(withDuplicate).some((issue) => issue.severity === 'error')).toBe(true); | ||
| expect(() => exportWorldDraft(withDuplicate)).toThrow(); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| import { initialOpenWorldState } from '../src/world/worldModel'; | ||
| import { defaultSocialAgents, interact } from '../src/world/socialAgents'; | ||
| import { assessClinicalTrigger } from '../src/world/clinicalBridge'; | ||
| import { WorldTimeline } from '../src/world/timeline'; | ||
| import { equivalentAction, validateInteractionProfile } from '../src/world/vrInteraction'; | ||
|
|
||
| describe('advanced disability world invariants', () => { | ||
| it('keeps an unavailable AAC answer unknown rather than transferring authority', () => { | ||
| const state = JSON.parse(JSON.stringify(initialOpenWorldState)); | ||
| const maya = state.entities.find((entity: any) => entity.id === 'maya'); | ||
| maya.communication.access = 'unavailable'; | ||
| const agent = defaultSocialAgents[0]; | ||
| expect(agent).toBeDefined(); | ||
| if (!agent) return; | ||
| const interaction = interact(state, agent, 'maya', 'ask'); | ||
| expect(interaction?.outcome).toBe('unknown'); | ||
| expect(maya.authority).toBe('self'); | ||
| }); | ||
|
|
||
| it('does not launch a clinical scenario without an evidence-gated health transition', () => { | ||
| const assessment = assessClinicalTrigger(initialOpenWorldState, 'maya', []); | ||
| expect(assessment.status).toBe('continue-world'); | ||
| expect(assessment.preserve.authority).toBe(true); | ||
| }); | ||
|
|
||
| it('creates counterfactual branches without mutating the captured original', () => { | ||
| const timeline = new WorldTimeline(); | ||
| const original = timeline.capture(initialOpenWorldState, 'original'); | ||
| const branch = timeline.branch(original.id, 'lift failure', (state) => { | ||
| const lift = state.entities.find((entity) => entity.id === 'station-lift') as any; | ||
| lift.operational = false; | ||
| }, 'station lift unavailable'); | ||
| expect((timeline.get(original.id)?.state.entities.find((entity) => entity.id === 'station-lift') as any).operational).toBe(true); | ||
| expect((branch?.state.entities.find((entity) => entity.id === 'station-lift') as any).operational).toBe(false); | ||
| }); | ||
|
|
||
| it('treats VR and switch selection as equivalent semantic actions', () => { | ||
| expect(equivalentAction( | ||
| { actorId: 'maya', action: 'select', targetId: 'community-hub', modality: 'xr-controller' }, | ||
| { actorId: 'maya', action: 'select', targetId: 'community-hub', modality: 'switch' }, | ||
| )).toBe(true); | ||
| }); | ||
|
|
||
| it('rejects reduced-motion smooth locomotion configuration', () => { | ||
| expect(validateInteractionProfile({ modalities: ['gaze'], locomotion: 'smooth', reducedMotion: true, dwellMilliseconds: 1200, responseTimeMultiplier: 2 })).toContain('reduced-motion profile should use teleport, seated snap turn, or non-spatial locomotion'); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import { initialOpenWorldState } from '../src/world/worldModel'; | ||
| import { evaluateAffordance } from '../src/world/affordanceGraph'; | ||
| import { planNextActivity } from '../src/world/autonomy'; | ||
| import { proposeDynamics } from '../src/world/vnnDynamics'; | ||
|
|
||
| describe('open world autonomy', () => { | ||
| test('AAC loss changes observability without changing authority', () => { | ||
| const state = structuredClone(initialOpenWorldState); | ||
| const maya = state.entities.find((entity) => entity.id === 'maya') as any; | ||
| maya.communication.access = 'unavailable'; | ||
| const activity = planNextActivity(state, 'maya')!; | ||
| const proposal = proposeDynamics(state, activity); | ||
|
|
||
| expect(maya.authority).toBe('self'); | ||
| expect(proposal.signals.some((signal) => signal.node === 'communication' && signal.metric === 'observability')).toBe(true); | ||
| expect(proposal.invariantChecks).toContain('communication access does not infer incapacity'); | ||
| }); | ||
|
|
||
| test('failed lift is represented as an environmental barrier', () => { | ||
| const state = structuredClone(initialOpenWorldState); | ||
| const maya = state.entities.find((entity) => entity.id === 'maya') as any; | ||
| const lift = state.entities.find((entity) => entity.id === 'station-lift') as any; | ||
| lift.operational = false; | ||
|
|
||
| const result = evaluateAffordance(maya, lift, 'use'); | ||
| expect(result.available).toBe(false); | ||
| expect(result.reason).toBe('environmental infrastructure unavailable'); | ||
| expect(maya.mobility.independent).toBe(true); | ||
| }); | ||
|
|
||
| test('planner preserves the goal by searching for alternatives', () => { | ||
| const state = structuredClone(initialOpenWorldState); | ||
| const activity = planNextActivity(state, 'maya'); | ||
| expect(activity).toBeDefined(); | ||
| expect(['travel', 'seek-alternative', 'rest']).toContain(activity!.kind); | ||
| expect(activity!.goal).toBe('move through the community'); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| import { InfrastructureEntity, PersonEntity, PersistentWorldStore, accessAssessment, initialOpenWorldState } from '../src/world/worldModel'; | ||
|
|
||
| describe('persistent disability world', () => { | ||
| it('attributes a failed lift to the environment rather than person incapacity', () => { | ||
| const store = new PersistentWorldStore(initialOpenWorldState); | ||
| const person = store.entity('maya') as PersonEntity; | ||
| const lift = store.entity('station-lift') as InfrastructureEntity; | ||
| expect(accessAssessment(person, lift)).toEqual({ pass: true, cause: 'accessible' }); | ||
| store.setInfrastructure('station-lift', false); | ||
| expect(accessAssessment(person, store.entity('station-lift') as InfrastructureEntity)).toEqual({ pass: false, cause: 'environmental infrastructure unavailable' }); | ||
| expect(person.authority).toBe('self'); | ||
| }); | ||
|
|
||
| it('does not change decision authority when AAC access degrades', () => { | ||
| const store = new PersistentWorldStore(initialOpenWorldState); | ||
| store.setCommunicationAccess('maya', 'degraded'); | ||
| const person = store.entity('maya') as PersonEntity; | ||
| expect(person.communication.access).toBe('degraded'); | ||
| expect(person.authority).toBe('self'); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import { PersistentWorldStore, initialOpenWorldState, type PersonEntity } from '../src/world/worldModel'; | ||
| import { WorldRuntime } from '../src/world/liveWorldLoop'; | ||
| import { ensurePopulation, relationships } from '../src/world/population'; | ||
| import { createSpatialIntent, evaluateSpatialIntent, nearbyEntities, wayfind } from '../src/world/spatialInteraction'; | ||
|
|
||
| describe('Steps 18-20 world integration',()=>{ | ||
| test('population seeds multiple self-authoritative people and relationships',()=>{const store=new PersistentWorldStore(initialOpenWorldState);ensurePopulation(store);const people=store.snapshot().entities.filter(e=>e.kind==='person') as PersonEntity[];expect(people.length).toBeGreaterThanOrEqual(4);expect(people.every(p=>p.authority==='self')).toBe(true);expect(relationships.length).toBeGreaterThan(0);}); | ||
| test('WorldRuntime is authoritative and advances population without changing authority',()=>{const store=new PersistentWorldStore(initialOpenWorldState);const runtime=new WorldRuntime(store);runtime.step(3);runtime.step(3);const maya=store.entity('maya') as PersonEntity;expect(maya.authority).toBe('self');expect(runtime.snapshot().activities.length).toBeGreaterThan(0);}); | ||
| test('semantic interaction is modality-independent',()=>{const store=new PersistentWorldStore(initialOpenWorldState);ensurePopulation(store);const state=store.snapshot();const touch=createSpatialIntent('maya','liam','communicate','touch');const xr=createSpatialIntent('maya','liam','communicate','xr-controller');expect(evaluateSpatialIntent(state,touch).allowed).toBe(evaluateSpatialIntent(state,xr).allowed);}); | ||
| test('AAC loss blocks immediate communication action but preserves intent and authority',()=>{const store=new PersistentWorldStore(initialOpenWorldState);ensurePopulation(store);store.setCommunicationAccess('maya','unavailable');const result=evaluateSpatialIntent(store.snapshot(),createSpatialIntent('maya','liam','communicate','switch'));expect(result.allowed).toBe(false);expect(result.reason).toContain('intent is preserved');expect((store.entity('maya') as PersonEntity).authority).toBe('self');}); | ||
| test('wayfinding attributes failed infrastructure to environment',()=>{const store=new PersistentWorldStore(initialOpenWorldState);store.setInfrastructure('station-lift',false);const route=wayfind(store.snapshot(),'maya','station-lift');expect(route?.accessible).toBe(false);expect(route?.reason).toContain('environmental infrastructure unavailable');}); | ||
| test('nearby discovery supports non-spatial equivalent of proximity interaction',()=>{const store=new PersistentWorldStore(initialOpenWorldState);ensurePopulation(store);const near=nearbyEntities(store.snapshot(),'maya',30);expect(near.length).toBeGreaterThan(0);}); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| import { defaultNavigationNetwork, findAccessibleRoutes, navigationProfile } from '../src/world/accessibleNavigation'; | ||
| import { chargerPercent, ObjectInteractionEngine, smoothstep } from '../src/world/objectInteractions'; | ||
| import { encounterScore, SocialEncounterEngine } from '../src/world/socialEncounters'; | ||
| import { ContinuityEngine } from '../src/world/continuity'; | ||
| import { initialOpenWorldState, PersistentWorldStore, type InfrastructureEntity, type PersonEntity } from '../src/world/worldModel'; | ||
|
|
||
| describe('Steps 21-24 Wolfram-grounded world algorithms', () => { | ||
| test('accessible routes are ordered by cost and failed infrastructure is environmental', () => { | ||
| const store = new PersistentWorldStore(initialOpenWorldState); | ||
| const maya = store.entity('maya') as PersonEntity; | ||
| expect(navigationProfile(maya).mobility).toBe('powered-wheelchair'); | ||
| const routes = findAccessibleRoutes(defaultNavigationNetwork, store.snapshot(), maya, 'plaza', 'transit', 3); | ||
| expect(routes.length).toBeGreaterThan(0); | ||
| for (let i = 1; i < routes.length; i++) expect(routes[i]!.cost).toBeGreaterThanOrEqual(routes[i-1]!.cost); | ||
| const lift = store.entity('station-lift') as InfrastructureEntity; | ||
| store.setInfrastructure(lift.id, false); | ||
| const blocked = findAccessibleRoutes(defaultNavigationNetwork, store.snapshot(), maya, 'plaza', 'transit', 3); | ||
| expect(blocked.every(route => !route.nodeIds.includes('station-lift'))).toBe(true); | ||
| expect((store.entity('maya') as PersonEntity).authority).toBe('self'); | ||
| }); | ||
|
|
||
| test('smoothstep lift model has stationary endpoints', () => { | ||
| expect(smoothstep(0)).toBe(0); | ||
| expect(smoothstep(1)).toBe(1); | ||
| const engine = new ObjectInteractionEngine(); | ||
| expect(engine.requestLift(1, 'maya')).toBe(true); | ||
| engine.step(4); | ||
| expect(engine.snapshot().lift.positionMetres).toBeCloseTo(2.1, 5); | ||
| engine.step(4); | ||
| expect(engine.snapshot().lift.positionMetres).toBeCloseTo(4.2, 5); | ||
| }); | ||
|
|
||
| test('Wolfram-derived charger curve reaches approximately 80 percent at computed time', () => { | ||
| expect(chargerPercent(30, 100, .0015, 835.1753123302453)).toBeCloseTo(80, 5); | ||
| }); | ||
|
|
||
| test('relationship and proximity affect encounters while support remains explicit', () => { | ||
| expect(encounterScore(1.5, 1, 1, .2)).toBeGreaterThan(encounterScore(1.5, 0, 0, .2)); | ||
| const store = new PersistentWorldStore(initialOpenWorldState); | ||
| const engine = new SocialEncounterEngine(); | ||
| const before = engine.detect(store.snapshot()).encounters; | ||
| expect(before.every(encounter => encounter.supportRequested === false)).toBe(true); | ||
| engine.requestSupport('maya', 'liam'); | ||
| }); | ||
|
|
||
| test('continuity preserves authority and rejects non-adjacent jumps', () => { | ||
| const store = new PersistentWorldStore(initialOpenWorldState); | ||
| const maya = store.entity('maya') as PersonEntity; | ||
| const engine = new ContinuityEngine(store); | ||
| engine.start(maya, 'educational test'); | ||
| expect(engine.episode('maya')?.preserved.authority).toBe('self'); | ||
| expect(engine.advance('maya', 'icu')).toBe(false); | ||
| expect(engine.advance('maya', 'ed')).toBe(true); | ||
| expect(engine.advance('maya', 'icu')).toBe(true); | ||
| expect(engine.advance('maya', 'mert-scenario')).toBe(true); | ||
| expect(engine.advance('maya', 'discharge')).toBe(true); | ||
| expect(engine.advance('maya', 'community-return')).toBe(true); | ||
| expect(engine.advance('maya', 'community-with-consequences')).toBe(true); | ||
| expect((store.entity('maya') as PersonEntity).authority).toBe('self'); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.