Skip to content

Latest commit

 

History

History
2335 lines (1791 loc) · 65.3 KB

File metadata and controls

2335 lines (1791 loc) · 65.3 KB

Developer README

This document is the technical, developer-facing companion to the public/project README.

It is intentionally more detailed than the root README.md, and it is written for engineers who need to:

  • understand what this repository actually is today;
  • run it locally in its different modes;
  • debug or extend the simulation runtime;
  • work on the Electron shell, AI provider integrations, or experiment pipeline;
  • inherit the codebase without relying on outdated assumptions.

This file is based on the repository state inspected on 2026-03-28.

1. What This Project Actually Is

At a high level, this repository is a hybrid codebase that combines:

  • a React application for interactive AI-driven social simulation;
  • an Electron shell for desktop delivery;
  • local AI integration through Ollama;
  • cloud AI integration through Gemini;
  • browser-side AI and translation support through WebGPU/WebLLM and @huggingface/transformers;
  • a multi-agent simulation runtime with world state, memory, social state, and experiment orchestration;
  • a local HTTP API and batch runner for protocol, benchmark, replay, and ablation workflows.

This is not just a chat UI.

It is closer to a combined product made of:

  • an interactive simulation frontend;
  • a local-first AI client;
  • a desktop app wrapper;
  • a social/agent runtime;
  • an experiment harness for reproducible runs and metrics.

The codebase reflects that history. Some parts are cohesive and actively used. Some parts are legacy carryovers from earlier iterations. Some configuration and documentation still reference older tooling or older naming.

This README tries to describe the project as it really exists, not as a cleaned-up idealized architecture.

2. Naming and Product Identity

The repository uses multiple names for overlapping concepts. This is important because it can confuse both onboarding and release discussions.

Name Where it appears What it means in practice
aiagent-app repo folder, package.json name repository/package identity
AI Social Lab UI, package.json product name, index.html, Electron window title, docs current product name
AI Agent Ultra cleanup fallback in packaging script, historical references in old artifacts/history previous desktop/product label
AI Family Simulation main component/file naming and some older concepts older or narrower framing of the simulation use case

Recommended internal language:

  • use aiagent-app for repository discussions;
  • use AI Social Lab for the current application and packaging discussions;
  • treat AI Agent Ultra and AI Family Simulation as legacy names that may still appear in older code paths.

If this project continues to evolve, naming should be normalized. Right now it is functional but inconsistent.

3. Reality Check: Verified Current State

The following checks were run directly against the repository on 2026-03-28:

  • node scripts/world-validate.cjs: passed
  • npm test: passed (33 files, 115 tests)
  • npm run build: passed
  • npm run electron:build: passed

Also observed during inspection:

  • src/ contains about 156 files
  • there are at least 33 test files in src/ (32 .test.js files and 1 .test.jsx file)

What was not fully verified in the same pass:

  • the Git object store still needs deeper cleanup even though normal git status access was restored by repairing HEAD
  • cross-platform packaging outside the current Windows environment was not verified

Git state after the cleanup pass:

  • HEAD now points back to refs/heads/main
  • git status works again
  • git fsck --full still reports missing historical objects plus an index cache-tree warning, so the repository is operational again but not fully pristine

Build-time observations from the verified Vite build:

  • the client build is successful but heavy
  • a large WASM asset is emitted from the browser AI stack
  • Vite reports several modules that are both dynamically and statically imported, so some intended chunk-splitting does not fully materialize

Modules flagged by Vite in the inspected build:

  • src/services/AIAdapter.js
  • src/services/DirectorService.js
  • src/services/BioEngine.js
  • src/utils/vectorEngine.js
  • src/services/webLlmService.js

4. Technical Stack

4.1 Application and UI

  • React 19.x
  • React DOM 19.x
  • React Router DOM 6.x
  • Vite 7.x
  • Tailwind CSS 3.x
  • Lucide React icons

4.2 Desktop shell

  • Electron 39.x
  • Electron Packager 16.0.0

4.3 AI and language tooling

  • Ollama HTTP API for local models
  • Google Gemini via @google/generative-ai
  • @huggingface/transformers for browser translation/model features
  • browser-side vector-memory ranking worker

4.4 Testing

  • Vitest
  • Testing Library
  • JSDOM

4.5 Build and tooling notes

  • no engines field is enforced in package.json
  • existing docs assume Node.js 18+ and npm 9+
  • Vite is the active frontend dev/build toolchain
  • some repository files still reflect prior Create React App assumptions

5. Repository Layout

This section focuses on the directories that matter to developers.

Path Role Notes
src/ primary source code most of the active logic lives here
public/ public assets and synced worker output public/vector.worker.js is generated from source
scripts/ validation, batch, API, sync, and repair scripts includes both active and legacy-support scripts
build/ Vite production build output generated artifact
dist/ packaged or distributable output generated artifact
build_check_orchestrator/ example run outputs for orchestrator/pipeline checks generated data
build_check_worker/ distributed/worker smoke output generated data
_recovery_snapshots/ recovery or replay-related output generated data
AgentSociety/ currently empty in the inspected state no active role was identified
electron.cjs Electron main process window creation, Ollama IPC bridge, devtools shortcuts
preload.cjs Electron preload bridge exposes restricted Ollama stream APIs
AIagent.jsx standalone mount/API bridge module not the main app entrypoint

6. Main Entry Points

6.1 Browser renderer entry

Primary flow:

  • src/index.jsx
  • src/App.jsx
  • src/AIFamilySimulation.jsx

What each file does:

  • src/index.jsx

    • creates the React root
    • wraps the app in ErrorBoundary
    • disables most console output in production
    • removes the splash screen after load
  • src/App.jsx

    • uses HashRouter
    • renders the simulation container
    • this is appropriate for file-based/Electron routing
  • src/AIFamilySimulation.jsx

    • the top-level application container
    • orchestrates most UI state, persistence, modals, onboarding, import/export, simulation controls, and settings

Important architectural fact:

  • src/AIFamilySimulation.jsx is approximately 1898 lines long
  • it functions as a large "god component"
  • many cross-cutting concerns still converge there

6.2 Electron desktop entry

Desktop flow:

  • electron.cjs
  • preload.cjs
  • renderer loaded from http://127.0.0.1:3000 in dev
  • renderer loaded from build/index.html in production

Important Electron behavior:

  • the BrowserWindow uses contextIsolation: true, sandbox: true, and nodeIntegration: false
  • external links are opened in the system browser
  • trusted renderer origin is restricted:
    • dev: http://localhost:3000 and http://127.0.0.1:3000
    • prod: file://
  • the app auto-checks whether Ollama is running and attempts to start it locally
  • global shortcuts are registered for DevTools:
    • Ctrl/Cmd + Shift + I
    • F12

6.3 Batch and local API entrypoints

These are the non-UI execution surfaces:

  • scripts/society-api-server.cjs
  • scripts/society-batch-runner.cjs
  • scripts/world-validate.cjs

These scripts instantiate the runtime and experiment pipeline directly from source modules in src/agent/ and src/experiments/.

Important note:

  • these scripts use require('sucrase/register')
  • sucrase is now declared directly in package.json
  • that removes the old hidden-dependency problem from clean installs

7. High-Level Architecture

The codebase is easiest to understand as a set of layers rather than a strict clean architecture.

7.1 UI layer

The UI lives mostly in src/components/ and src/AIFamilySimulation.jsx.

Main responsibilities:

  • timeline display
  • agent panels and detail modals
  • settings, onboarding, and help flows
  • overlays for Ollama connection and generation state
  • world generation and feedback panels
  • God Mode, debugging, and operational controls

Notable components:

  • SettingsModal.jsx
  • Timeline.jsx
  • AgentPanel.jsx
  • AgentDetailModal.jsx
  • OllamaConnectOverlay.jsx
  • HelpGuide.jsx
  • WorldGenesisModal.jsx
  • AgentDebugPanel.jsx
  • GodModePanel.jsx

SettingsModal.jsx matters more than a normal settings screen because it controls real runtime behavior:

  • provider mode
  • model selection
  • map pack
  • orchestration history limit
  • translation-related features
  • data reset
  • connection testing

7.2 State and UI runtime hooks

Primary hooks:

  • src/hooks/useAIGeneration.js
  • src/hooks/useOllamaConnection.js
  • src/hooks/useSimulationEngineRuntime.js
  • src/hooks/useSimulationEngineStore.js
  • src/hooks/useAutoConnect.js

Roles:

  • useAIGeneration.js

    • main generation runtime
    • executes the simulation turn pipeline
    • integrates AI provider calls, retries, quality gates, memory diffusion, consolidation, and orchestration logging
  • useOllamaConnection.js

    • tests provider availability
    • handles WebGPU/Gemini/Ollama mode checks
    • surfaces latency, connection errors, and model availability
  • useSimulationEngineRuntime.js

    • wraps the simulation task queue
    • manages immediate reaction and forced turn requests
  • useSimulationEngineStore.js

    • holds app-visible simulation state such as timeline, agents, world state, social state, bio state, and UI state
  • useAutoConnect.js

    • scans for likely local AI endpoints
    • mainly used to discover Ollama-like services

Important architectural fact:

  • src/hooks/useAIGeneration.js is approximately 1796 lines long
  • it is another "god module" in the current codebase
  • large changes in simulation behavior usually involve this file

7.3 Simulation engine layer

The simulation engine is spread across:

  • src/engine/
  • src/engine/phases/

Main concerns:

  • simulation task queue
  • world schema validation
  • map and world rules
  • response parsing
  • scheduling
  • planning
  • evaluation
  • governance/institution phases
  • error and retry policy

Representative files:

  • src/engine/SimulationRuntime.js
  • src/engine/WorldSchemaValidator.js
  • src/engine/WorldRules.js
  • src/engine/UrbanMapEngine.js
  • src/engine/phases/perceivePhase.js
  • src/engine/phases/schedulePhase.js
  • src/engine/phases/planPhase.js
  • src/engine/phases/actPhase.js
  • src/engine/phases/evaluationPhase.js
  • src/engine/phases/qualityGatePhase.js

This layer is where "simulation turn" logic lives, distinct from raw UI control.

7.4 Agent runtime and experiment layer

Primary directories:

  • src/agent/
  • src/experiments/

Main agent/runtime responsibilities:

  • message bus
  • agent memory
  • agent policy and context dispatch
  • intervention handling
  • runtime metrics
  • agent selection by role or cohort

Representative files:

  • src/agent/SocietyRuntime.js
  • src/agent/message/MessageBus.js
  • src/agent/core/FamilyAgentKernel.js
  • src/agent/core/AgentPolicyEngine.js
  • src/agent/core/AgentContextDispatcher.js

Experiment/orchestration responsibilities:

  • seed scenarios
  • run pipeline batches
  • deterministic replay
  • protocol runs
  • ablation suites
  • benchmarks and Monte Carlo variants
  • job management for async local API execution

Representative files:

  • src/experiments/SocietyExperimentPipeline.js
  • src/experiments/ExperimentOrchestrator.js
  • src/experiments/ExperimentJobManager.js
  • src/experiments/ExperimentKpiService.js
  • src/experiments/ProtocolRegistry.js

This is one of the most important distinctions in the repository:

  • the UI is only one surface
  • the social runtime and experiment pipeline are real reusable subsystems

7.5 AI provider and transport layer

Key files:

  • src/services/AIAdapter.js
  • src/services/RequestQueue.js
  • src/services/aiConnection.js
  • src/services/webLlmService.js

Provider model:

  • Local Ollama

    • default local-first path
    • accessed via HTTP in browser mode
    • accessed via Electron IPC bridge in desktop mode when URL is local
  • Gemini

    • cloud provider path via SDK
    • also used as fallback in some failure scenarios if a key exists
  • WebGPU/WebLLM

    • supported as a browser-side path
    • contributes significantly to bundle size and build output

RequestQueue.js is important because it serializes asynchronous provider calls. This matters for Ollama and similar local runtimes that can degrade under concurrent requests.

7.6 Language, translation, and output enforcement layer

Key files:

  • src/translations.js
  • src/services/LanguageGuardService.js
  • src/services/TranslationGlossary.js

What this layer does in practice:

  • stores UI text bundles
  • attempts to keep model output in the selected target language
  • supports browser translation via HuggingFace runtime when available
  • falls back to LLM-driven translation when necessary
  • persists translation cache locally
  • applies glossary consistency and override rules

Important reality:

  • the repository also contains src/locales/*.json
  • however, the primary app flow imports src/translations.js
  • src/locales/*.json are now synced/generated mirrors via scripts/sync-locales.cjs
  • so src/translations.js is the practical source of truth for UI strings

7.7 World, map, and environment layer

Key files:

  • src/services/WorldSystemService.js
  • src/services/MapPackService.js
  • src/engine/WorldSchemaValidator.js
  • src/data/urbanMap.default.json
  • src/data/urbanMap.megacity.json
  • src/data/worldRules.default.json
  • src/data/experimentProtocols.default.json
  • src/data/benchmarkProfiles.default.json

Responsibilities:

  • validate map and world rules
  • initialize or repair world state
  • apply map packs
  • relocate agents/objects when a pack changes and current locations are invalid
  • expose diagnostics and descriptions for runtime use

Current built-in map packs:

  • default -> MetroLite
  • megacity -> MetroMega100

7.8 Persistence layer

Primary persistence utilities:

  • src/utils.js
  • src/services/OrchestrationStorageService.js

The application is local-first. There is no backend database for normal app state.

Most persistent state is stored through an IndexedDB wrapper in src/utils.js.

Important note:

  • src/idb-local.js contains the low-level key/value IndexedDB helpers
  • src/utils.js now delegates the base get/set operations to src/idb-local.js
  • the main application flow still consumes the higher-level utilities exported from src/utils.js

7.9 Vector memory ranking worker

Source flow:

  • source of truth: src/services/vector.worker.js
  • synced output: public/vector.worker.js
  • sync script: scripts/sync-vector-worker.cjs

Rule:

  • edit src/services/vector.worker.js
  • do not manually edit public/vector.worker.js

The following scripts already sync it for you:

  • npm run sync:generated
  • npm start
  • npm run build

8. Core Runtime Data Model

The app does not only track text messages. It maintains several related state domains.

Main state slices visible in the UI/runtime:

  • timeline
  • agents
  • family knowledge
  • world state
  • social state
  • bio state
  • UI state

Key defaults live in src/constants.js:

  • world presets
  • initial agents
  • initial world state
  • initial relationships
  • initial bio state
  • recommended models
  • default settings

Default setting highlights:

  • ollamaUrl: http://localhost:11434
  • model: hermes3:latest
  • theme: dark
  • language: vi
  • modelLanguage: en
  • generationInterval: 10000
  • mapPackId: default
  • orchestrationHistoryLimit: 120

Interpretation:

  • the product is still local-first by default
  • Vietnamese is the default UI language
  • model-facing language is still biased toward English
  • Ollama on localhost is the baseline assumption

9. Detailed Development Workflows

9.1 Install dependencies

npm install

9.2 Run the web app in development mode

npm start

What it does:

  • syncs generated locale mirrors from src/translations.js
  • syncs vector.worker.js
  • runs Vite on 127.0.0.1:3000
  • enforces strictPort

Expected URL:

  • http://127.0.0.1:3000

Important note:

  • the active dev server binds to 127.0.0.1, not 0.0.0.0

9.3 Run the Electron app in development mode

npm run electron:dev

What it does:

  • starts the Vite dev server
  • waits for TCP port 3000
  • launches Electron

This is the primary way to test the desktop shell during development.

9.4 Build the web app

npm run build

Output:

  • build/

Vite build settings in vite.config.js:

  • base: './'
  • outDir: 'build'
  • emptyOutDir: true

9.5 Build/package the Electron app

npm run electron:build

What it currently does:

  • runs clean
  • syncs generated locale/worker assets
  • runs the web build
  • packages the app with electron-packager

Important note:

  • packaging is now described directly by the electron:build script plus top-level package metadata
  • the old unused desktop-builder-style "build" block was removed during cleanup

9.6 Run the local experiment/orchestration API

npm run society:api

Default server:

  • http://localhost:4488

Quick health check:

curl http://localhost:4488/health

9.7 Run the batch experiment pipeline

Generic command:

npm run society:batch -- --ticks 200 --agents 100 --output build_check_orchestrator/result.json

Useful examples:

Basic batch run:

npm run society:batch -- --ticks 200 --agents 100 --output build_check_orchestrator/result.json

Deterministic replay check:

npm run society:batch -- --ticks 120 --agents 80 --replay-runs 3 --output build_check_orchestrator/replay_result.json

Protocol suite:

npm run society:batch -- --mode protocol --agents 80 --baseline-ticks 60 --followup-ticks 60 --seed 2026 --replay-runs 3 --output build_check_orchestrator/protocol_result.json

Protocol by registry ID:

npm run society:batch -- --mode protocol --protocol-id stability_recovery --agents 80 --replay-runs 3 --output build_check_orchestrator/protocol_registry_result.json

Ablation suite:

npm run society:batch -- --mode ablation --agents 80 --ticks 60 --include-roles government,bank --treatment-ratio 0.5 --replay-runs 2 --output build_check_orchestrator/ablation_result.json

Benchmark suite:

npm run society:batch -- --mode benchmark --agents 80 --protocol-ids stability_recovery,employment_shock,inflation_guardrail --output build_check_orchestrator/benchmark_result.json

Benchmark profile:

npm run society:batch -- --mode benchmark --profile-id core_city --agents 80 --output build_check_orchestrator/benchmark_profile_result.json

Monte Carlo benchmark:

npm run society:batch -- --mode benchmark-mc --agents 80 --protocol-ids stability_recovery,employment_shock --runs-per-protocol 4 --base-seed 2026 --output build_check_orchestrator/benchmark_mc_result.json

Distributed benchmark:

npm run society:batch -- --mode benchmark-distributed --profile-id core_city --workers 3 --agents 100 --output build_check_orchestrator/benchmark_distributed_result.json

10. Command Reference

Command What it really does Notes
npm start starts Vite dev server after syncing generated locale/worker assets active frontend dev entry
npm run dev alias of npm start same behavior
npm run electron:dev runs Vite and Electron together main desktop dev flow
npm run build syncs generated locale/worker assets, then runs the production web build writes to build/
npm run electron:build web build plus desktop packaging uses electron-packager
npm run electron:pack alias of electron:build same behavior
npm run clean kills running packaged app process and removes dist/ Windows-oriented script
npm run world:validate validates map/rule JSON useful quick safety check
npm run society:batch runs the experiment pipeline from CLI supports multiple modes
npm run society:distributed distributed benchmark preset uses profile core_city
npm run society:api local HTTP API for experiments and jobs default port 4488
npm run lang:scan scans for mojibake/corrupted text maintenance utility
npm run lang:repair repairs known mojibake patterns maintenance utility
npm test runs the Vitest suite full suite not revalidated in one pass
npm run test:watch runs Vitest in watch mode normal dev test mode

11. Environment, Ports, and Network Assumptions

11.1 Ports

Port Purpose
3000 Vite dev server
11434 Ollama default local server
4488 local society API server

11.2 Relevant environment/config inputs

Variable Used by Purpose
REACT_APP_OLLAMA_URL vite.config.js, src/constants.js default Ollama base URL
PUBLIC_URL vite.config.js, src/utils.js affects public asset paths, including worker path
PORT scripts/society-api-server.cjs local API server port
OLLAMA_ORIGINS external environment / helper scripts CORS allowlist for browser-to-Ollama access
OLLAMA_HOST external Ollama config bind host for Ollama

11.3 CORS and safety notes

The repository now uses one main default pattern:

Default local-development allowlist:

  • fix_cors_windows.ps1 sets:
    • OLLAMA_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
  • dev.bat and launcher.bat now use the same localhost-only allowlist for their session environment

That means:

  • the repo no longer defaults to OLLAMA_ORIGINS=*
  • local development still works without widening browser access more than necessary
  • LAN/mobile access now requires an intentional Ollama configuration change instead of being opened implicitly

12. Local Helper Scripts

12.1 fix_cors_windows.ps1

Purpose:

  • configure Ollama for localhost browser access with a safer allowlist
  • restart Ollama

Behavior:

  • sets OLLAMA_ORIGINS at user level
  • stops existing Ollama processes
  • attempts to restart ollama serve

12.2 dev.bat

Purpose:

  • convenience launcher for Windows development

Behavior:

  • installs dependencies if node_modules is missing
  • sets the localhost-only OLLAMA_ORIGINS allowlist for the session
  • starts the dev server

12.3 launcher.bat

Purpose:

  • older Windows launcher for dev/prod/build/check workflows

Behavior:

  • offers a simple menu
  • can run dev mode
  • can serve the build/ folder
  • can build
  • can run a basic Ollama connectivity check

Important note:

  • this script has been brought closer to the current repository identity
  • it still remains a thin Windows helper, not the canonical source of operational behavior

13. Storage and Persistence

The app persists a meaningful amount of local state.

Main storage wrapper:

  • src/utils.js

Storage backend:

  • IndexedDB for most structured app state
  • localStorage for some flags, caches, and glossary-related entries

13.1 Important IndexedDB keys

Key Purpose
ai_family_settings_v2 app settings
ai_family_agents_v2 persisted agents state
ai_family_timeline_v2 persisted timeline
ai_family_knowledge family knowledge store
ai_orchestration_runs_v1 orchestration history
ai_family_save_{slot} slot-based saves used directly by the main app
ai_family_saves_v2 older/parallel save-manager style aggregate storage

13.2 Important localStorage keys

Key Purpose
language_auto_set tracks whether initial language auto-detection already ran
ai_onboarding_completed onboarding completion flag
training_dataset training/debug dataset collection used by the app
ai_translation_cache_v1 persisted translation cache
ai_translation_glossary_overrides_v1 persisted glossary override data

13.3 Persistence caveats

The repository currently has some overlap in persistence patterns:

  • slot saves are stored individually as ai_family_save_{slot}
  • SaveManager also uses ai_family_saves_v2
  • src/utils.js and src/idb-local.js still split high-level vs low-level persistence responsibilities

This is workable, but it is still not a single clean persistence abstraction.

14. Simulation Turn: What Happens During Generation

The simulation runtime is not a single provider call.

At a high level, a typical generation cycle goes through something like this:

  1. Read current settings and simulation state.
  2. Sync the active agent/runtime view.
  3. Resolve language handling between UI language and model language.
  4. Determine whether there is a pending reaction event or forced turn.
  5. Run perception/context assembly.
  6. Run scheduling to choose the next speaker.
  7. Build prompt context from timeline, agents, world state, and memory.
  8. Call the AI provider.
  9. Parse the response into structured output.
  10. Apply timeline, memory, bio, social, and world updates.
  11. Run diffusion and consolidation phases.
  12. Run evaluation and possible interventions.
  13. Persist or append orchestration metadata where appropriate.

Key files involved:

  • src/hooks/useAIGeneration.js
  • src/engine/phases/*
  • src/services/AIAdapter.js
  • src/services/LanguageGuardService.js
  • src/services/RequestQueue.js

15. AI Provider Modes

The app supports several runtime modes, but they are not all equal in maturity or complexity.

15.1 Ollama

This is the default local-first path.

Behavior:

  • default URL is http://localhost:11434
  • in browser mode, it uses direct HTTP requests
  • in Electron with a local URL, it can route stream requests through the preload/main-process IPC bridge

Why the IPC bridge exists:

  • it avoids some browser/CORS friction for localhost access
  • it restricts the exposed surface to approved endpoints

15.2 Gemini

Gemini is supported as a cloud mode.

Behavior:

  • configured through geminiKey
  • used explicitly when provider/mode indicates Gemini
  • may also become a fallback through queue/circuit-breaker logic if a local path fails and a key is present

15.3 WebGPU/WebLLM / browser-side AI

This mode is supported in the app and contributes to:

  • large build output
  • large WASM payloads
  • more demanding browser runtime requirements

It is useful, but it also raises bundle and runtime complexity compared with the pure local-Ollama path.

16. Translation and Language Enforcement

This app does more than simply switch UI labels.

It attempts to:

  • keep generated output in the selected user language
  • translate between UI-facing and model-facing language contexts
  • cache translations locally
  • apply glossary consistency to reduce terminology drift
  • repair mojibake or corrupted text where possible

Main implementation files:

  • src/services/LanguageGuardService.js
  • src/services/TranslationGlossary.js
  • src/utils/mojibakeFix.js
  • src/translations.js

Operational takeaway:

  • translation is part of the runtime behavior, not just a presentation layer concern
  • bugs in language enforcement can affect agent behavior, memory contents, and UI text

17. World, Map Packs, and Rule Validation

The simulation includes a structured world model.

That world includes:

  • objects and object states
  • maps and places
  • roads and reachability
  • institutional/economic state
  • world rules and action categories

Validation:

  • scripts/world-validate.cjs validates:
    • default map
    • megacity map
    • world rules
    • institution rule structure

If you change any of the following, run validation:

  • src/data/urbanMap.default.json
  • src/data/urbanMap.megacity.json
  • src/data/worldRules.default.json

Map-pack behavior:

  • changing the map pack in settings can relocate agents and objects to valid fallback places
  • this relocation is explicit behavior, not an accidental side effect

18. Orchestration, Protocols, Benchmarks, and Replay

One of the most important parts of the repository is that it supports reproducible experiment-style execution, not just interactive UI simulation.

Core concepts:

  • protocol run
  • benchmark run
  • ablation run
  • deterministic replay
  • Monte Carlo benchmark
  • distributed benchmark
  • async local job execution through the API server

Key files:

  • src/experiments/SocietyExperimentPipeline.js
  • src/experiments/ProtocolRegistry.js
  • src/experiments/ExperimentOrchestrator.js
  • src/experiments/ExperimentJobManager.js
  • src/services/SocietyApiClient.js

The experiment pipeline is capable of:

  • seeding agent populations
  • running ticks in batch
  • comparing before/after intervention behavior
  • computing protocol KPIs
  • aggregating benchmark statistics across runs

This is one of the strongest parts of the repository from an engineering/product perspective.

19. Local API Server

The local HTTP API in scripts/society-api-server.cjs exposes runtime and experiment capabilities without requiring the browser UI.

Default base URL:

  • http://localhost:4488

19.1 GET routes

Route Purpose
/health server health and agent count
/metrics runtime metrics snapshot
/protocols list available protocols
/benchmark-profiles list available benchmark profiles
/jobs list recent jobs
/jobs/:id inspect one job

19.2 POST routes

Route Purpose
/syncAgents seed/sync runtime agents and social/institution state
/tick run tick batch
/experiment/survey run survey experiment
/experiment/interview run interview experiment
/experiment/intervention run intervention experiment
/pipeline/run run full pipeline
/pipeline/protocol run protocol suite or protocol by ID
/pipeline/replay run deterministic replay
/pipeline/ablation run ablation suite
/pipeline/benchmark run benchmark suite
/pipeline/benchmark-mc run Monte Carlo benchmark
/pipeline/benchmark-distributed run distributed benchmark
/jobs/run queue an async job

19.3 Example requests

Health:

curl http://localhost:4488/health

List protocols:

curl http://localhost:4488/protocols

Replay:

curl -X POST http://localhost:4488/pipeline/replay -H "Content-Type: application/json" -d "{\"tickCount\":40,\"seed\":2026,\"runs\":3}"

Protocol:

curl -X POST http://localhost:4488/pipeline/protocol -H "Content-Type: application/json" -d "{\"protocolId\":\"stability_recovery\",\"replayRuns\":3}"

Ablation:

curl -X POST http://localhost:4488/pipeline/ablation -H "Content-Type: application/json" -d "{\"ticks\":50,\"includeRoles\":[\"government\",\"bank\"],\"treatmentRatio\":0.5,\"replayRuns\":2}"

Benchmark:

curl -X POST http://localhost:4488/pipeline/benchmark -H "Content-Type: application/json" -d "{\"protocolIds\":[\"stability_recovery\",\"employment_shock\",\"inflation_guardrail\"]}"

Async job:

curl -X POST http://localhost:4488/jobs/run -H "Content-Type: application/json" -d "{\"taskType\":\"benchmark-mc\",\"payload\":{\"protocolIds\":[\"stability_recovery\"],\"runsPerProtocol\":2,\"baseSeed\":2026}}"

20. Important Files by Task Area

Use this section as a fast navigation map.

If you are changing the main UI or interaction flow

Read first:

  • src/AIFamilySimulation.jsx
  • src/App.jsx
  • src/components/*

If you are changing provider behavior or connection handling

Read first:

  • src/services/AIAdapter.js
  • src/hooks/useOllamaConnection.js
  • src/services/RequestQueue.js
  • electron.cjs
  • preload.cjs

If you are changing generation/simulation turn behavior

Read first:

  • src/hooks/useAIGeneration.js
  • src/engine/phases/*
  • src/engine/SimulationRuntime.js

If you are changing agent runtime behavior

Read first:

  • src/agent/SocietyRuntime.js
  • src/agent/core/*
  • src/agent/message/MessageBus.js

If you are changing experiments or benchmarks

Read first:

  • src/experiments/SocietyExperimentPipeline.js
  • src/experiments/ProtocolRegistry.js
  • src/experiments/ExperimentOrchestrator.js
  • scripts/society-batch-runner.cjs
  • scripts/society-api-server.cjs

If you are changing world/map/rules data

Read first:

  • src/data/*
  • src/services/WorldSystemService.js
  • src/services/MapPackService.js
  • src/engine/WorldSchemaValidator.js
  • scripts/world-validate.cjs

If you are changing translation or text quality behavior

Read first:

  • src/services/LanguageGuardService.js
  • src/services/TranslationGlossary.js
  • src/translations.js
  • src/utils/mojibakeFix.js

If you are changing persistence

Read first:

  • src/utils.js
  • src/services/OrchestrationStorageService.js
  • src/idb-local.js

21. Legacy, Drift, and Technical Debt You Should Know Up Front

This is the section that matters most for honest onboarding.

21.1 The public docs were realigned with the active repo

The root README.md and TROUBLESHOOTING.md were cleaned up to match the current Vite/Electron flow and to remove the previous encoding drift in troubleshooting content.

They are now substantially closer to the truth of the current repo.

21.2 CRA-era residue was removed from the active tree

The old compatibility files:

  • scripts/start.js
  • src/setupProxy.js

were removed because they no longer matched the live Vite workflow.

If you are debugging startup or proxy behavior, treat:

  • package.json scripts
  • vite.config.js

as the actual source of truth.

21.3 Translation sources are now intentionally one-way

The repository still contains:

  • src/translations.js
  • src/locales/*.json

But the relationship is clearer now:

  • src/translations.js remains the editable source of truth
  • src/locales/*.json are synced/generated mirrors via scripts/sync-locales.cjs
  • dev/build flows call npm run sync:generated before running Vite

21.4 The main runtime files are still very large

Two central files are especially large:

  • src/AIFamilySimulation.jsx (~1.9k lines)
  • src/hooks/useAIGeneration.js (~1.8k lines)

Practical impact:

  • changes often have broad side effects
  • regressions can be easy to introduce
  • large refactors should be done in narrow, testable slices

21.5 Packaging config is simpler, but the workflow is still local-script driven

The old unused desktop-builder-style package.json "build" metadata was removed.

Current packaging truth:

  • npm run electron:build
  • electron-packager

This is clearer than before, but still intentionally lightweight rather than a formal release pipeline.

21.6 Some generated artifacts live directly in the repo root

Generated or output-heavy directories include:

  • build/
  • dist/
  • build_check_orchestrator/
  • build_check_worker/
  • _recovery_snapshots/

This is convenient for quick local use, but it also increases noise and makes source/output boundaries less clear.

21.7 Git repository access is usable again, but deeper cleanup is still pending

The direct HEAD breakage was repaired, so normal git status access works again.

However:

  • git fsck --full still reports missing historical objects
  • the index cache-tree still shows a warning

So the repo is operational again for normal day-to-day inspection, but not fully pristine at the object-store level.

21.8 AgentSociety/ currently has no identified active role

The directory exists but was effectively empty in the inspected state.

If it is intended as a future module boundary, it should be documented. If not, it should be cleaned up.

21.9 Dependency declaration is now more explicit

The batch/API scripts still use sucrase/register, but sucrase is now declared directly in package.json.

That particular install-time ambiguity has been removed.

22. Build Output and Performance Observations

The app is not lightweight.

From the inspected build:

  • a browser AI WASM artifact above 21 MB was emitted
  • the main JS bundle is large
  • the transformers bundle is also large

Practical consequences:

  • slower cold starts
  • slower builds
  • larger desktop/web footprint
  • more memory pressure in the browser

If performance work becomes a priority, these are likely first areas to investigate:

  • WebGPU/WebLLM dependencies
  • translation/runtime chunking
  • static-plus-dynamic import overlap
  • the size and breadth of useAIGeneration.js

23. Tests and Validation

The repository has a meaningful amount of test coverage, especially around:

  • world schema validation
  • simulation engine pieces
  • experiments
  • runtime services
  • reducers
  • translation/mojibake utilities

Useful targeted checks:

node scripts/world-validate.cjs
npx vitest run src/services/SocietyApiClient.test.js
npx vitest run src/engine/WorldSchemaValidator.test.js

Full suite:

npm test

Watch mode:

npm run test:watch

Recommendation:

  • run the targeted tests closest to the subsystem you changed
  • run world:validate when touching map/rules data
  • run a build when touching provider or bundling behavior

24. How to Approach This Codebase as a New Developer

Recommended onboarding sequence:

  1. Read this file.
  2. Read package.json to understand scripts and runtime surfaces.
  3. Read src/constants.js to understand defaults and baseline data assumptions.
  4. Read src/App.jsx and src/AIFamilySimulation.jsx to understand the main app shell.
  5. Read src/hooks/useAIGeneration.js to understand the simulation runtime.
  6. Read src/agent/SocietyRuntime.js and src/experiments/SocietyExperimentPipeline.js to understand the non-UI core.
  7. Run node scripts/world-validate.cjs.
  8. Run npm start or npm run electron:dev.
  9. If working on providers, read src/services/AIAdapter.js, src/hooks/useOllamaConnection.js, and src/services/RequestQueue.js.
  10. If working on world or protocol data, read src/data/*, src/services/WorldSystemService.js, and src/engine/WorldSchemaValidator.js.

25. What to Change First for Common Tasks

Add or modify a simulation phase

Look at:

  • src/engine/phases/*
  • src/hooks/useAIGeneration.js

Add a new experiment mode or benchmark behavior

Look at:

  • src/experiments/SocietyExperimentPipeline.js
  • src/experiments/ProtocolRegistry.js
  • scripts/society-batch-runner.cjs
  • scripts/society-api-server.cjs

Add a new user-facing setting

Look at:

  • src/components/SettingsModal.jsx
  • src/constants.js
  • src/AIFamilySimulation.jsx

Add or change a map pack

Look at:

  • src/services/MapPackService.js
  • src/services/WorldSystemService.js
  • src/data/urbanMap*.json
  • scripts/world-validate.cjs

Change how local model requests are handled

Look at:

  • src/services/AIAdapter.js
  • src/services/RequestQueue.js
  • electron.cjs
  • preload.cjs

Change translation consistency or language enforcement

Look at:

  • src/services/LanguageGuardService.js
  • src/services/TranslationGlossary.js
  • src/translations.js

26. Recommended Maintenance Priorities

If the project is going to be actively developed further, the highest-value maintenance tasks are probably:

  1. Finish the deeper Git object-store cleanup so git fsck --full is clean, not just git status.
  2. Continue normalizing legacy internal naming (AIFamilySimulation, older labels, historical artifacts).
  3. Break down AIFamilySimulation.jsx and useAIGeneration.js into smaller units.
  4. Reduce bundle weight and investigate the dynamic/static import overlap warnings from the browser AI stack.
  5. Clarify source vs generated artifacts in the repository layout.
  6. Keep translation edits centered in src/translations.js and treat src/locales/*.json as generated output.

27. Bottom Line

This repository is strong in a few important ways:

  • it already contains a real multi-agent simulation runtime
  • it has more than one execution surface: web, Electron, batch, and local API
  • it includes world validation and experiment orchestration, not just UI
  • it has non-trivial tests across several subsystems
  • it still builds successfully in its current inspected state

It is also uneven in predictable ways:

  • naming is inconsistent
  • documentation drift exists
  • a few central modules are too large
  • some legacy tooling/configuration remains
  • some dependencies and generated artifacts are not managed as cleanly as they could be

The right way to work in this codebase is not to assume it is already tidy. The right way is:

  • use this file as the engineering map
  • verify behavior against the live code
  • make changes in narrow slices
  • prefer local truth over inherited assumptions

That approach fits the actual state of the project much better than treating it like a clean-slate application.

Appendix A. Codebase Map by Directory

This appendix is meant to reduce first-contact friction when someone opens the repository for the first time.

A.1 src/

Top-level subdirectories:

  • src/agent/
  • src/components/
  • src/data/
  • src/engine/
  • src/experiments/
  • src/hooks/
  • src/locales/
  • src/services/
  • src/utils/

Top-level source files worth knowing:

  • src/index.jsx
  • src/App.jsx
  • src/AIFamilySimulation.jsx
  • src/constants.js
  • src/reducers.js
  • src/translations.js
  • src/utils.js
  • src/idb-local.js
  • src/index.css

A.2 src/agent/

Role:

  • agent runtime, memory kernel, message bus, and policy dispatching

Important files:

  • src/agent/SocietyRuntime.js
  • src/agent/message/MessageBus.js
  • src/agent/core/FamilyAgentKernel.js
  • src/agent/core/AgentKernel.js
  • src/agent/core/AgentMemory.js
  • src/agent/core/AgentPolicyEngine.js
  • src/agent/core/AgentContextDispatcher.js
  • src/agent/core/defaultBlocks.js

What to expect here:

  • the agent layer is not just a display model
  • it contains runnable behavior and diagnostics
  • interventions and dialogue distribution eventually pass through this layer

A.3 src/components/

Role:

  • user-facing UI components and control surfaces

Current component list observed in the repo:

  • AgentDebugPanel.jsx
  • AgentDetailModal.jsx
  • AgentPanel.jsx
  • Avatar.jsx
  • ChaosDiceButton.jsx
  • ConnectionStatusBadge.jsx
  • ErrorBoundary.jsx
  • FeedbackModal.jsx
  • GenerativeOverlay.jsx
  • GodModePanel.jsx
  • HelpGuide.jsx
  • ModelLibraryModal.jsx
  • OllamaConnectOverlay.jsx
  • SettingsModal.jsx
  • SignalStatus.jsx
  • SmartDoctorModal.jsx
  • SoulManagerModal.jsx
  • Timeline.jsx
  • Toast.jsx
  • WorldGenesisModal.jsx

Operationally important UI components:

  • SettingsModal.jsx: behavior and runtime configuration
  • Timeline.jsx: event rendering
  • AgentPanel.jsx and AgentDetailModal.jsx: character management
  • OllamaConnectOverlay.jsx: connection bootstrap and guidance
  • SmartDoctorModal.jsx: onboarding and environment diagnosis
  • AgentDebugPanel.jsx: debug surface

A.4 src/data/

Role:

  • built-in simulation data and benchmark defaults

Current built-in data files:

  • worldRules.default.json
  • urbanMap.default.json
  • urbanMap.megacity.json
  • experimentProtocols.default.json
  • benchmarkProfiles.default.json

This directory is effectively the baseline content/config package for the simulation runtime.

A.5 src/engine/

Role:

  • simulation engine primitives, world validation/rules, and turn runtime support

Important files:

  • SimulationEngine.js
  • SimulationRuntime.js
  • SimulationInputTypes.js
  • WorldSchemaValidator.js
  • WorldRules.js
  • WorldRulePack.js
  • UrbanMapEngine.js
  • SocietyRoleService.js

The internal store engine:

  • SimulationEngine.js is a small custom state container
  • it supports slice reducers and batch dispatching
  • React hooks consume it through useSyncExternalStore

Simulation input types currently defined:

  • immediate_reaction
  • force_speaker_turn
  • generate_tick

A.6 src/engine/phases/

Role:

  • the staged generation/simulation pipeline

Current phase and support files observed:

  • actPhase.js
  • consolidationPhase.js
  • diffusionPhase.js
  • errorPolicy.js
  • evaluationPhase.js
  • governPhase.js
  • institutionPhase.js
  • perceivePhase.js
  • planPhase.js
  • promptBuilderPhase.js
  • qualityGatePhase.js
  • recallPhase.js
  • responseParser.js
  • retryPolicy.js
  • schedulePhase.js

When the app "takes a turn", this directory is where most of the staged runtime behavior is defined.

A.7 src/experiments/

Role:

  • orchestration, benchmarks, protocols, KPIs, and experiment job management

Important files:

  • SocietyExperimentPipeline.js
  • ProtocolRegistry.js
  • ExperimentOrchestrator.js
  • ExperimentJobManager.js
  • ExperimentKpiService.js
  • ExperimentStatsService.js

If you are trying to understand how benchmark or replay modes work, this is the first directory to study.

A.8 src/hooks/

Role:

  • connects React to the simulation runtime and provider state

Important files:

  • useAIGeneration.js
  • useOllamaConnection.js
  • useSimulationEngineState.js
  • useSimulationEngineStore.js
  • useSimulationEngineRuntime.js
  • useAutoConnect.js

The most important relationships are:

  • useSimulationEngineState.js creates the internal slice-based simulation store
  • useSimulationEngineStore.js exposes state plus refs to the latest values
  • useSimulationEngineRuntime.js adds queue-based input execution
  • useAIGeneration.js uses all of the above to run the actual simulation loop

A.9 src/services/

Role:

  • runtime services, provider adapters, diagnostics, persistence helpers, and sidecar systems

Current service files observed:

  • AgentPlanner.js
  • AIAdapter.js
  • aiConnection.js
  • BioEngine.js
  • CharacterFactory.js
  • ConsolidationService.js
  • CriticAgent.js
  • DirectorService.js
  • GpuCapabilityService.js
  • LanguageGuardService.js
  • MapPackService.js
  • NetworkGuardService.js
  • NewsService.js
  • OrchestrationStorageService.js
  • RequestQueue.js
  • SocietyApiClient.js
  • TimeService.js
  • TranslationGlossary.js
  • vector.worker.js
  • WeatherService.js
  • webLlmService.js
  • WorldSystemService.js

This is the most mixed directory in the repository. It contains:

  • AI adapter logic
  • language tooling
  • hardware diagnostics
  • orchestration persistence
  • world/map services
  • external-data-like services

A.10 src/utils/

Role:

  • lower-level helpers and specialized utilities

Examples:

  • vectorEngine.js
  • hardwareBenchmarker.js
  • timeEngine.js
  • mojibakeFix.js
  • geoLocator.js
  • dreamEngine.js
  • configGenerator.js

This folder overlaps conceptually with src/services/ in places. The separation is not always strict.

Appendix B. State Model, Store, and Reducer Contracts

The runtime store is not Redux, Zustand, or MobX. It is a custom slice-based store implemented with:

  • src/engine/SimulationEngine.js
  • src/hooks/useSimulationEngineState.js
  • src/hooks/useSimulationEngineStore.js

B.1 State slices

The internal simulation state is initialized with:

  • timeline
  • agents
  • familyKnowledge
  • worldState
  • socialState
  • bioState
  • uiState

Initial values come from:

  • INITIAL_AGENTS
  • INITIAL_WORLD_STATE
  • INITIAL_RELATIONSHIPS
  • INITIAL_BIO_STATE
  • empty defaults for timeline, family knowledge, and UI widgets

B.2 How the store works

SimulationEngine.js:

  • stores a plain JS object of slices
  • maps each slice to a reducer
  • supports dispatchTo(sliceKey, action)
  • supports dispatchBatch(batch)
  • notifies subscribers via a simple listener set

useSimulationEngineState.js:

  • creates one SimulationEngine instance
  • exposes each slice through useSyncExternalStore
  • provides dispatch helpers for each slice

useSimulationEngineStore.js:

  • wraps useSimulationEngineState.js
  • mirrors current slice values into refs
  • gives runtime code access to the latest state without stale closure issues

B.3 Timeline reducer actions

Important timeline actions observed:

  • ADD_EVENT
  • REMOVE_LAST_EVENT
  • UPDATE_EVENT
  • RESET_TO_INDEX
  • CLEAR
  • INIT
  • TOGGLE_LIKE
  • TRUNCATE_TIMELINE
  • UPDATE_EVENT_TEXT
  • UPDATE_EVENT_BY_ID
  • REMOVE_EVENT_BY_ID

Non-obvious behavior:

  • updating system events tends to re-arm reaction flags such as requiresReaction and reactionHandled
  • timeline truncation is used by rewind/butterfly-effect behavior

B.4 Agent reducer actions

Important agent actions observed:

  • ADD_AGENT
  • DELETE_AGENT
  • UPDATE_MEMORIES
  • UPDATE_MEMORY_INDEX
  • UPDATE_MEMORY_TYPE
  • DELETE_MEMORY_INDEX
  • ADD_SINGLE_MEMORY
  • UPDATE_AGENT_DETAILS
  • UPDATE_PERSONALITY
  • UPDATE_AGENT
  • ADD_MEMORY
  • ADD_REFLECTION
  • ADD_MEMORIES_ALL
  • SUMMARIZE_MEMORIES
  • ROLLBACK_MEMORIES
  • CLEAR_MEMORIES
  • REBUILD_MEMORIES
  • INIT
  • RESTORE_SNAPSHOT

Important constraints:

  • agent count is capped by MAX_AGENT_COUNT
  • memory trimming happens through trimMemories(...)
  • system agent handling is special-cased in several places

B.5 Family knowledge reducer

Important actions:

  • ADD_KNOWLEDGE
  • INIT

Important behavior:

  • deduplicates entries
  • normalizes capitalization
  • keeps only the latest KNOWLEDGE_WINDOW entries

B.6 World reducer

Important actions:

  • INIT
  • ADD_GHOST
  • DELETE_GHOST
  • UPDATE_OBJECT
  • UPDATE_INSTITUTIONS
  • RESTORE_SNAPSHOT

Important behavior:

  • delegates to WorldSystemService
  • world init merges and sanitizes map/rule payloads

B.7 Social reducer

Important actions:

  • INIT
  • UPDATE_RELATIONSHIP
  • RESTORE_SNAPSHOT

Important behavior:

  • scores are clamped
  • relationship labels are derived from score bands
  • relation change reasons can be stored

B.8 Bio reducer

Important actions:

  • INIT
  • UPDATE_ALL_BIO
  • UPDATE_BIO
  • RESTORE_SNAPSHOT
  • TRUNCATE_TIMELINE
  • TICK_METABOLISM

Important behavior:

  • energy, dopamine, and cortisol are bounded values
  • there is both direct update behavior and periodic metabolism-like decay behavior

B.9 UI reducer

Important actions:

  • INIT
  • ADD_WIDGET
  • REMOVE_WIDGET
  • UPDATE_WIDGET
  • CLEAR_ALL

This slice represents transient UI widgets, not the whole visual app state.

Appendix C. Provider Selection, Connection Logic, and Failure Semantics

The repository contains multiple layers of provider and network logic:

  • selection of provider mode
  • connectivity checks
  • request serialization
  • transport-specific behavior
  • fallback or degraded-mode handling

C.1 Effective provider selection rules

In practice, provider routing is determined by the current settings and some convenience heuristics.

High-level paths:

  • WebGPU path
    • active when apiProvider === 'webgpu' or mode === 'webgpu'
  • Gemini path
    • active when apiProvider === 'gemini'
    • also inferred in some cases when a Gemini-like key is present
  • Ollama path
    • used as the default local path when not in a cloud/WebGPU path

From useOllamaConnection.js, the check order is effectively:

  1. WebGPU shortcut
  2. Gemini check
  3. Ollama/local endpoint check

C.2 What useOllamaConnection actually does

useOllamaConnection manages:

  • connectionStatus
  • errorCount
  • lastError
  • latency
  • availableModels

It also exposes checkConnection(...).

Special behaviors:

  • WebGPU mode is treated as ready without a network roundtrip
  • Gemini mode tests several model candidates until one succeeds
  • Ollama mode:
    • checks /api/tags
    • checks whether the endpoint is actually Ollama
    • then performs a lightweight generation call to verify the selected model path

C.3 Failure classes handled in connection logic

Observed categories include:

  • CHECK_IN_PROGRESS
  • AUTH_MISSING
  • QUOTA_EXCEEDED
  • PERMISSION_DENIED
  • MODEL_NOT_FOUND
  • MIXED_CONTENT
  • TIMEOUT
  • REMOTE_ACCESS_DENIED
  • OLLAMA_NOT_RUNNING
  • MODEL_ERROR
  • UNKNOWN

These categories matter because:

  • they affect toast text
  • they affect whether the app pauses or retries
  • they affect how much guidance the UI can provide

C.4 Mixed content and remote endpoint behavior

The app explicitly checks for this scenario:

  • browser page is served over https:
  • Ollama endpoint is http:

If that is true, the browser path is considered blocked by mixed-content policy.

This is surfaced as:

  • code: MIXED_CONTENT
  • message: HTTPS app cannot call HTTP endpoint

Remote endpoint handling is also treated differently from localhost:

  • remote failure gets more explicit "remote access" guidance
  • localhost failure gets more "is Ollama running?" guidance

C.5 Request serialization and fallback

src/services/RequestQueue.js is the queue that prevents runaway concurrent provider calls.

Important behavior:

  • serial execution
  • retry with backoff
  • cancellation/debounce by task ID
  • queue clearing
  • a "circuit breaker" that can switch persisted provider settings to Gemini if Ollama is failing and a Gemini key already exists

This is one of the most operationally important services in the repository.

C.6 Electron IPC transport path

When AIAdapter uses the Ollama path:

  • if window.electronAPI exists
  • and the base URL looks local (localhost or 127.0.0.1)
  • then the adapter can use the Electron IPC bridge for streaming

Why that matters:

  • it reduces some browser CORS friction
  • it keeps the renderer-side API narrow
  • it only applies to local URLs, not arbitrary remote endpoints

Appendix D. Batch Runner CLI Flag Reference

The CLI batch runner is scripts/society-batch-runner.cjs.

It supports:

  • inline flags
  • optional config file input
  • output file writing

D.1 Supported CLI flags

Observed flags:

  • --config
  • --output
  • --mode
  • --protocol-id
  • --protocol-ids
  • --profile-id
  • --include-roles
  • --exclude-roles
  • --treatment-ratio
  • --runs-per-protocol
  • --base-seed
  • --workers
  • --ticks
  • --baseline-ticks
  • --followup-ticks
  • --seed
  • --agents
  • --replay-runs

D.2 What the flags mean

Flag Meaning
--config path to JSON config file
--output output JSON path
--mode pipeline mode such as pipeline, protocol, ablation, benchmark, benchmark-mc, benchmark-distributed
--protocol-id single protocol registry ID
--protocol-ids comma-separated list of protocol IDs
--profile-id benchmark profile ID
--include-roles comma-separated role filter
--exclude-roles comma-separated exclusion filter
--treatment-ratio ablation treatment ratio
--runs-per-protocol Monte Carlo/distributed runs per protocol
--base-seed base seed for repeated benchmark runs
--workers worker count for distributed or Monte Carlo flows
--ticks generic tick count
--baseline-ticks protocol baseline window
--followup-ticks protocol follow-up window
--seed deterministic seed
--agents seeded agent count
--replay-runs deterministic replay repetition count

D.3 Config file structure

The runner can also read a JSON config file containing fields such as:

  • agents
  • socialState
  • institutionState
  • agentCount
  • baseName
  • mode
  • protocolId
  • profileId
  • ticks
  • baselineTicks
  • followupTicks
  • seed
  • replayRuns
  • includeRoles
  • excludeRoles
  • treatmentRatio
  • runsPerProtocol
  • baseSeed
  • workers
  • overrides

D.4 Batch runner outputs

The runner writes a JSON file containing:

  • normalized run config
  • result payload
  • optional deterministic replay summary

The CLI also logs:

  • mode
  • protocol/profile info where relevant
  • agent count
  • tick counts
  • replay status where relevant
  • output path

Appendix E. Society API Client and Payload Reference

The client wrapper for the local API is src/services/SocietyApiClient.js.

E.1 Client defaults

Defaults observed:

  • base URL: http://localhost:4488
  • timeout: 15000ms
  • retry count: 2
  • retry delay: 350ms
  • retry backoff: 1.8

Retryable HTTP statuses:

  • 408
  • 425
  • 429
  • 500
  • 502
  • 503
  • 504

E.2 Client methods

Observed client methods:

  • health()
  • metrics()
  • listProtocols()
  • listBenchmarkProfiles()
  • syncAgents(payload)
  • tick(payload)
  • runSurvey(payload)
  • runInterview(payload)
  • runIntervention(payload)
  • runPipeline(payload)
  • runProtocol(payload)
  • runReplay(payload)
  • runAblation(payload)
  • runBenchmark(payload)
  • runBenchmarkMonteCarlo(payload)
  • runBenchmarkDistributed(payload)
  • runJob(taskType, payload)
  • listJobs()
  • getJob(jobId)
  • waitForJob(jobId, options)

E.3 Common payload shapes by route

These are the practical payload fields accepted by the local server, based on server-side parsing logic.

POST /syncAgents

  • agents
  • socialState
  • institutionState
  • agentCount
  • baseName

POST /tick

  • tickCount
  • seed

POST /experiment/survey

  • survey
  • sampleSize
  • tag

POST /experiment/interview

  • question
  • sampleSize
  • tag

POST /experiment/intervention

  • intervention
  • followupSurvey
  • tag

POST /pipeline/run

  • ticks
  • surveyEvery
  • interviewSampleSize
  • intervention

POST /pipeline/protocol

  • protocolId
  • baselineTicks
  • followupTicks
  • seed
  • replayRuns
  • survey
  • intervention
  • interviewQuestion
  • interviewSampleSize
  • sampleSize
  • resetToSeed

POST /pipeline/replay

  • tickCount
  • seed
  • runs

POST /pipeline/ablation

  • ticks
  • seed
  • includeRoles
  • excludeRoles
  • treatmentRatio
  • intervention
  • followupSurvey
  • replayRuns
  • resetToSeed

POST /pipeline/benchmark

  • protocolIds
  • profileId
  • overrides
  • resetToSeed

POST /pipeline/benchmark-mc

  • protocolIds
  • profileId
  • overrides
  • runsPerProtocol
  • baseSeed
  • workers
  • resetToSeed

POST /pipeline/benchmark-distributed

  • protocolIds
  • profileId
  • overrides
  • runsPerProtocol
  • baseSeed
  • workers
  • resetToSeed

POST /jobs/run

  • taskType
  • payload

E.4 Job polling behavior

waitForJob(jobId, options):

  • polls every 1200ms by default
  • defaults to a 300000ms timeout
  • can stop on failed status
  • supports onUpdate
  • throws on timeout or failed final state

Appendix F. Built-In Protocol and Benchmark Catalog

The current protocol registry comes from:

  • src/data/experimentProtocols.default.json
  • src/data/benchmarkProfiles.default.json

F.1 Built-in protocols currently present

stability_recovery

  • title: Stability Recovery
  • purpose: baseline run, policy intervention, follow-up for social risk stabilization
  • defaults:
    • baselineTicks: 40
    • followupTicks: 40
    • seed: 2026
    • replayRuns: 3

employment_shock

  • title: Employment Shock
  • purpose: stress labor response under low employment pressure
  • defaults:
    • baselineTicks: 50
    • followupTicks: 50
    • seed: 2027
    • replayRuns: 2

inflation_guardrail

  • title: Inflation Guardrail
  • purpose: track citizen pressure and policy compliance under inflation
  • defaults:
    • baselineTicks: 45
    • followupTicks: 45
    • seed: 2028
    • replayRuns: 2

F.2 Built-in benchmark profiles currently present

core_city

  • title: Core City Baseline
  • protocol IDs:
    • stability_recovery
    • employment_shock
    • inflation_guardrail
  • defaults:
    • runsPerProtocol: 3
    • baseSeed: 2026
    • workers: 2

macro_policy_stress

  • title: Macro Policy Stress
  • protocol IDs:
    • employment_shock
    • inflation_guardrail
    • stability_recovery
  • defaults:
    • runsPerProtocol: 4
    • baseSeed: 3040
    • workers: 3

rapid_regression

  • title: Rapid Regression
  • purpose: fast smoke-style benchmark profile
  • protocol IDs:
    • stability_recovery
  • defaults:
    • runsPerProtocol: 2
    • baseSeed: 1500
    • workers: 2

F.3 Registry resolution behavior

ProtocolRegistry.js provides:

  • listing
  • lookup by ID
  • normalization of IDs
  • fallback behavior

Observed defaults:

  • protocol fallback resolves toward stability_recovery
  • benchmark profile fallback resolves toward core_city

Appendix G. Electron IPC Contract and Security Model

The Electron preload exposes a deliberately narrow API under window.electronAPI.

G.1 Exposed preload methods

Observed methods:

  • ollamaStreamRequest(payload)
  • ollamaStreamCancel(requestId)
  • onOllamaReply(handler)
  • onOllamaReplyEnd(handler)
  • onOllamaError(handler)

G.2 Allowed IPC flow

electron.cjs enforces:

  • trusted sender URL only
  • payload shape checks
  • request ID validation
  • endpoint allowlist

Allowed endpoints:

  • /api/generate
  • /api/chat

Request constraints:

  • requestId must be a non-empty string
  • max requestId length is constrained
  • duplicate in-flight IDs are aborted before replacement

G.3 Network destination for IPC bridge

The main-process bridge always sends to:

  • protocol: http:
  • host: localhost
  • port: 11434

That means:

  • the IPC bridge is a localhost-only Ollama bridge
  • it is not a generic remote proxy

G.4 Why this matters

This design narrows the attack surface compared with exposing broad file or network access to the renderer.

At the same time, it means:

  • remote Ollama endpoints will still go through browser fetch logic, not the Electron local bridge
  • debugging local vs remote provider behavior requires understanding both code paths

Appendix H. Provider and Runtime Scenario Matrix

This section gives practical "what happens if..." summaries.

H.1 Pure local web development

Scenario:

  • run npm start
  • app served on http://127.0.0.1:3000
  • Ollama on http://localhost:11434

Behavior:

  • Vite serves the app
  • browser uses direct fetch to Ollama
  • CORS matters
  • no Electron IPC bridge is involved

H.2 Electron local development

Scenario:

  • run npm run electron:dev
  • renderer from localhost dev server
  • Ollama local

Behavior:

  • browser UI still runs via Vite
  • Electron preload exists
  • local Ollama streaming can use IPC instead of raw fetch in some flows

H.3 Production web build served over HTTPS

Scenario:

  • static build hosted over HTTPS
  • Ollama endpoint remains HTTP

Behavior:

  • browser mixed-content rules block the connection
  • app surfaces MIXED_CONTENT

H.4 Remote Ollama endpoint

Scenario:

  • custom remote host entered in settings

Behavior:

  • browser fetch is used
  • remote access/CORS/firewall concerns apply
  • Electron localhost bridge does not act as a remote tunnel

H.5 Gemini-only path

Scenario:

  • Gemini key configured
  • provider/mode points to Gemini

Behavior:

  • connection check tests Gemini models
  • generation bypasses Ollama
  • some local-first assumptions still exist elsewhere in the app, so test carefully after switching modes

H.6 WebGPU/WebLLM path

Scenario:

  • WebGPU mode selected

Behavior:

  • connection is treated as available without network probing
  • browser runtime complexity increases
  • bundle and hardware capability concerns become more relevant

Appendix I. Non-Obvious Behaviors and Gotchas

These are behaviors that are easy to miss if you only skim the code.

I.1 System event edits can re-arm reactions

Updating a system event may reset:

  • requiresReaction
  • reactionHandled
  • reactionHandledAt

This is deliberate and affects replay/reactivity behavior.

I.2 Agent count is capped

The app enforces MAX_AGENT_COUNT. If new agent payloads exceed that cap, extra agents can be dropped silently at reducer/runtime boundaries.

I.3 Memory trimming is built into reducer paths

When adding memories:

  • reducers may trim and archive memory data
  • not every append results in an unbounded growth of the memory list

I.4 Map pack changes can relocate data

Changing the map pack is not a cosmetic change. It can actively relocate:

  • agents
  • world objects

This is good for consistency, but it means map changes can have meaningful simulation consequences.

I.5 Request queue can mutate persisted provider settings

RequestQueue.js contains circuit-breaker behavior that may:

  • switch apiProvider to Gemini
  • save that updated setting to storage

This is operationally useful, but it also means provider choice is not always purely manual.

I.6 Some runtime paths are duplicated conceptually

Examples:

  • src/translations.js is the editable translation source while src/locales/*.json are generated mirrors
  • src/utils.js still holds higher-level helpers, but low-level key/value access now delegates to src/idb-local.js
  • generated assets still live alongside source in the repo tree, which can blur the source/output boundary

That means code search can still reveal more than one path for a concern, but the dominant path is clearer than it was before the cleanup pass.

Appendix J. Suggested Reading Order by Goal

If you are debugging a specific class of issue, this reading order can save time.

J.1 "Why is generation failing?"

Read in this order:

  1. src/hooks/useAIGeneration.js
  2. src/services/AIAdapter.js
  3. src/services/RequestQueue.js
  4. src/hooks/useOllamaConnection.js
  5. src/engine/phases/errorPolicy.js
  6. src/engine/phases/retryPolicy.js

J.2 "Why is the desktop app behaving differently from the browser?"

Read in this order:

  1. electron.cjs
  2. preload.cjs
  3. src/services/AIAdapter.js
  4. src/App.jsx
  5. src/index.jsx

J.3 "Why are benchmarks or protocol runs not matching expectations?"

Read in this order:

  1. src/experiments/SocietyExperimentPipeline.js
  2. src/experiments/ProtocolRegistry.js
  3. src/data/experimentProtocols.default.json
  4. src/data/benchmarkProfiles.default.json
  5. scripts/society-batch-runner.cjs
  6. scripts/society-api-server.cjs

J.4 "Why is world state or validation failing?"

Read in this order:

  1. src/engine/WorldSchemaValidator.js
  2. src/services/WorldSystemService.js
  3. src/services/MapPackService.js
  4. src/data/urbanMap.default.json
  5. src/data/worldRules.default.json
  6. scripts/world-validate.cjs