Spaces:
Sleeping
Sleeping
Commit History
-
Trial-mode UX: live progress visibility + cosmetic fixes + tighter caps
Three classes of issue surfaced during the trial playthrough: (1) The 3-minute /advance felt completely silent in the UI even though the LiveProgress component was mounted. Root cause: EventSource has no way to attach an X-Trial-Password header, so the password gate rejected every SSE connection silently. Backend now also accepts the password as a ?token= query param on the /games/{id}/stream endpoint, and the frontend streamUrl appends it from localStorage. Live deliberation cards, the phase rail, and the cost meter now render during advance. (2) Cosmetic SPA bugs that shipped wrong turn counts: - GameView.tsx:96 had `(turns?.length && 5) || 5` which always returned 5 regardless of the game's actual world.max_turns. Read straight from state.world.max_turns now. - Debrief.tsx:31 hardcoded `turn:5, max:5` for the shell header. Now pulls from /games/{id}/state. - i18n strings in en.ts / de.ts hardcoded "Five turns" and "Turn 1 of 5" in newGame.scenario.footnote, newGame.ready.e…b9537b4 -
Trial-mode: cap games to 1 turn + 5 agents
In trial mode (WARGAME_TRIAL_MODE=1), shrink the surface of every new game so a single click can't cascade into a full 5-turn / 13-agent run: - WARGAME_TRIAL_MAX_TURNS (default 1): override the world's max_turns at game creation. A 1-turn game = briefing -> action -> single advance -> debrief, ~12 LLM calls instead of ~80. - WARGAME_TRIAL_MAX_AGENTS (default 5): truncate the YAML roster every load_scenario sees. The rival CEO is always preserved (engine relies on its multi-turn plan continuity); the rest is first-N from YAML order. Trimming at the registry layer means snapshot save/load stays consistent — game.private state, deliberation, adjudication, debrief reveal all see the same 5-agent set. Combined with the per-day budget cap, a leaked password's worst case is now bounded to ~1-2 trial games' worth of tokens per day rather than unbounded /advance loops. Both env vars default to "off" via WARGAME_TRIAL_MODE, so local DX is unchanged. 5 new tests (345 passing tota…b587cd8 -
Allow setup wizard in trial mode
Per user request: keep the interactive scenario wizard (POST /scenarios/setup*) reachable when WARGAME_TRIAL_MODE=1. Cost is bounded — 1 LLM call per Q&A round, 3-5 calls on commit — and the daily LLM-call cap is the backstop. Still blocked: orchestrator (the real spike, 50-150 calls/click), one-shot scaffold, fork, challenge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>38a8b21 -
Add trial-mode endpoint gate + daily LLM-call budget
Two safety nets to bound Azure spend on the public trial deployment: WARGAME_TRIAL_MODE=1 disables the high-token-cost endpoints — orchestrator (50–150 calls/click), setup wizard (free-text chatbot), scenario scaffold, fork, and challenge — by returning 503 from the existing middleware. The minimal gameplay loop (list/create game, recon, act, advance, debrief) stays open. Password gate runs first so 503 doesn't leak route existence to unauthenticated callers. WARGAME_DAILY_LLM_CALLS sets a hard daily cap that's checked at the top of every call_structured. Counter persists to /data/.wargame_budget.json so it survives container restarts and resets at UTC midnight. Hitting the cap raises BudgetExceeded, which a global exception handler turns into a 503 carrying the cap status. New /admin/budget endpoint exposes today's counter for operator visibility. Both default to off — local DX unchanged. 16 new tests (340 passing total) cover: trial mode off-by-default, every gated endpoint retur…158f655
-
Merge remote-tracking branch 'space/main' into claude/busy-mendel-1be5e0
989f66b -
Add HF Spaces deployment scaffold + trial password gate
Dockerfile (Python 3.12 + uv, listens on 7860, persists to /data) and .dockerignore let us push the FastAPI engine to a Hugging Face Docker Space. README.md gets the YAML frontmatter HF needs to detect the Space type. Two env-driven gates so a public Space stays trial-only: - WARGAME_ALLOWED_ORIGINS CORS allow-list (defaults to *) - WARGAME_TRIAL_PASSWORD shared password; clients send X-Trial-Password. /healthz and CORS preflights are exempt so HF healthchecks and browser preflights still work. Frontend caches the password in localStorage and re-prompts on a 401. Both gates default to permissive so local dev DX is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>17a40e4 -
Merge pull request #7 from schipsy/claude/admiring-haibt-2f07fd
schipsyUnverified signatureRounds 1-7: KB-grounded feature plan + browser-validated fixes6e7c2c9 -
fix(GameView): "Use this opener" must switch composer to manual mode
adoptOpener was setting intent/justification/anchors state, but the composer defaults to the 'coach' tab (chat thread) which doesn't render those fields. Clicking the button silently mutated invisible state — from the user's perspective, nothing happened. Flip composerMode to 'manual' inside the handler so the populated form is what scrolls into view. Mirrors the same setComposerMode('manual') that the action-coach commit-review path already uses. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>d71e491 -
api: GET /admin/cache_stats + 409 guard on duplicate orchestrate POSTs
Two ops items surfaced live-testing the orchestrator on case_mok5mpdk. 1. GET /admin/cache_stats — exposes the in-process LLM accounting (calls, cache_read_tokens, cache_write_tokens, uncached_input_tokens, output_tokens, validation_retries) so live ops can confirm whether work is flowing during long operations. The wargame.* loggers default to WARNING, so the per-call INFO line from record_usage was normally invisible — this surfaces the same numbers without log-level fiddling. No auth (localhost-only MVP). 2. POST /games/{id}/orchestrate now 409s if the game already has a pending or running ScenarioMap. A page reload during the first run was firing a second daemon thread that competed for tokens and wrote parallel branches against the same source game. The startup sweep (d327256) handles orphans across process restarts; this catches the double-fire case while the same process is still alive. 324 tests pass (322 baseline + 2 new — TestAdminCacheStat…495b592 -
fix(orchestrator): widen 12-actor cap; sweep orphan maps on startup
Two bugs surfaced live-testing case_mok5mpdk (12-agent ORF Causa Weißmann scaffold). 1. CriticAssessmentList / PreMortemList / EvaluatorScoreList capped at max_length=12, but a 12-agent scenario produces 13 actors (12 agents + 1 player). The LLM correctly produced 13 entries; Pydantic rejected the response on every closing flow, retries cascaded, branches stuck. Bumped to max_length=20 so up-to-19-agent scenarios fit. 2. Orchestrator workers run as daemon=True threads inside uvicorn. When the parent dies (deploy / OOM / restart), every in-flight thread dies with it, but the on-disk ScenarioMap stays in its last running/pending state forever. Status polls block on dead work. Adds wargame.orchestrator.sweep_orphan_maps() and runs it from a FastAPI lifespan context so any pending/running map at boot is rewritten as failed with error="orphaned by process restart". Migrated FastAPI startup hook to lifespan (the on_event API was deprecated). 322 tests pass (+…d327256 -
fix: include scenario_id in StateResponse so the recon agent dropdown loads the real roster
GameView's loadGame guards api.listAgents on st?.scenario_id, then falls back to a hardcoded DEFAULT_AGENTS placeholder list (CFO/CRO/CTO/...) if agents stay empty. The /games/{id}/state endpoint never returned scenario_id, so the guard always failed and every game showed the generic 10-agent placeholder roster instead of the scenario's actual agents — most visible on freshly scaffolded scenarios like the Causa Weißmann case where the user expects Schrom/Huber/Nadler/ Steinacher/Steger/Hafenecker/Klenk in the dropdown. Adds scenario_id to StateResponse and threads it through the two call sites (/state and /pause). Frontend type was already correct. 321 tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>de51526 -
Round 7: episodic memory experiment (per-scenario atoms)
Minimum-viable episodic memory layer per the user's "memory could be tested" guidance — KB calls out a full hierarchical memory architecture (working / episodic / semantic / graph / archival); this round ships Episodic with strict gating, defers the rest. Concept: at game completion, an LLM call extracts a few short verified-against-verdicts insights ("memory atoms") from the debrief. The selector keeps CONFIRMED + PLAUSIBLE atoms, drops SPECULATIVE, dedupes >70% substring matches against existing atoms, and caps each scenario at 50 atoms (oldest evicted). On the next game with the same scenario, the top 3-5 most-recent atoms are prepended to write_briefing's USER message under "## Memory of past games (treat as priors, not proof)" — system prompt untouched so the prompt cache stays warm. - wargame/memory/store.py — JSON per scenario at games_dir/memory/{id}.json - wargame/memory/extractor.py — extract_atoms + selector + persistence - wargame/engine/state.py — MemoryAtom, MemoryAtomL…b6f158e -
Round 6: German localization (en + de)
Backend (backend-i18n teammate): - Game.language: Literal["en","de"] = "en"; default keeps old snapshots loadable. - language_directive(lang) appended to every call_structured user message; system prefix stays byte-identical so the prompt cache stays warm. - use_game_language() context manager + ContextVar; loop.py + orchestrator pin language across all entry points; ThreadPoolExecutor in run_deliberations now propagates context (fixes a latent issue for per-game model selection too). - CLI: wargame new --language en|de; wargame state shows the language. - API: NewGameRequest.language + StateResponse.language. - _delta_summary, _metrics_table, _recent_events placeholders localized via _t(en, de) helper. - 13 new tests including a system-prompt-byte-identical-across-languages invariant that protects the cache. Frontend (frontend-i18n teammate): - New frontend/src/i18n/ module — ~95-line shim with useI18n() hook, setLanguage, getLanguage, {name} interpolation, English fall…bd956f0 -
Round 5b: frontend wiring — live progress, pause/resume, role overrides, doc upload, constraint manager
Two parallel streams merged cleanly via separate banners in api.ts: LIVE UX (live-ux teammate): - LiveProgress.tsx — SSE-driven step rail (Deliberation → Critic → Pre-mortem → Adjudication → Evaluator → World update → Next briefing), live deliberation feed, verdict cards coloured by outcome, rAF-debounced cost meter, paused banner, error toast, 2s reconnect-after-double-fail. - GameView replaces the fake-ticker terminal with <LiveProgress> while advance is in flight or status==paused. Pause button mid-advance, Resume button when paused. Handles /advance status="paused" the same as the SSE paused event. - api.ts: pauseGame, resumeGame, streamUrl, PhaseEvent union. - frontend/scripts/sse-smoke.mjs + README — stdlib-fetch SSE smoke client. FORMS (forms teammate): - NewGame.tsx — collapsible "Per-role model routing" panel iterating models.roles with fallback list. Role overrides flow through createGame. - SetupCase.tsx — drag-and-drop "Grounding documents" zone (10 docs cap…ecf16e0 -
Round 5a: backend SSE event streaming + HITL pause primitive
Lays the live-UX backend the frontend (Round 5b) will consume. Event bus (wargame/engine/events.py) — per-game subscriber registry, context-bound publisher, queue.put_nowait fan-out with drop-oldest backpressure. Pure stdlib; no async/await contagion in phase code. PhaseEvent kinds emitted at every step boundary: - phase_started / phase_completed (one per high-level step) - deliberation_complete (one per agent) - critic_complete, premortem_complete - verdict_complete (one per actor) - evaluator_complete, world_updated, briefing_ready - usage_tick (cumulative cost), paused, resumed, error HITL pause primitive — Game.pause_requested + status="paused"; loop.advance is now idempotent over partial TurnRecord state and checks pause between each step. GamePaused exception is a domain exception; the API catches it and returns 200 with the paused game. loop.resume clears the flag and re-enters advance, which picks up where it left off without re-mutating world state. API: GET /games/{id}/st…aff2409 -
Round 4: document upload + hard-constraint blocking
Adds backend for: uploading grounding docs into a setup session, extracting explicit hard constraints (covenants, deadlines, no-fly clauses) from those docs, and blocking action submissions that breach any hard constraint. Schemas: - HardConstraint (description, rationale, test_question, severity, source) - ConstraintCheckResult (passes, violations[]) - HardConstraintList (extraction wrapper) - Game.hard_constraints; ScenarioConfig.hard_constraints Constraint checker (wargame/agents/constraint_checker.py) — single LLM call from a stable system prompt; short-circuits when the game has no HARD constraints so the action path stays fast. Extraction (wargame/scaffold/extract_constraints.py) — runs at setup commit time over the uploaded docs and persists the result as scenarios/{id}/hard_constraints.yaml so it survives any later replay. Document store (wargame/scaffold/document_store.py) — sanitised filenames, 25MB cap, per-session dir under games_dir/setup_documents/. Loop: - act() run…143020d -
Round 3: per-role model routing
Lets each game route different roles to different models, e.g. control to Opus while Critic/Evaluator run on a cheaper model: wargame new --model-for control=claude-opus-4-7 --model-for evaluator=gpt-5.4 - Game.role_model_overrides (dict[str, str]) — empty default; old snapshots load unchanged. - model_for(role) precedence: override > scoped game model > env > default. - use_game_model() now accepts role_overrides; validates every model id against the registry before mutating any ContextVar. - Canonical role tags exposed via wargame/agents/roles.py: control, agent, rival, critic, premortem, evaluator. - Rival CEO now uses role="rival" instead of spec.model_role so it can be routed independently from the generic role agents. - CLI: --model-for ROLE=MODEL_ID repeatable; `wargame models` lists canonical role tags alongside registered models. - API: POST /games accepts role_model_overrides and 422s on bad ids; GET /models returns roles[] for the (later) frontend editor. - C…63544d5 -
Round 2: Critic, Pre-mortem, Evaluator agents + Red Team debrief section
Three new procedural agents (tools, not characters — no hidden agenda, no agents.yaml entry): - Critic: consistency + realism check on every adjudicated action. Runs after deliberation, before adjudication. - Pre-mortem: 1-5 plausible failure modes per action with most-likely highlighted and 0-3 safeguards. Runs after Critic, before adjudication. - Evaluator: independent 9-criterion rubric scoring after adjudication. Computes mean-abs-delta against Control's rubric (deviation_from_control) in Python. Outputs land on TurnRecord (critic_assessments, pre_mortems, evaluator_scores) but are NEVER injected into Control's adjudicate prompt — keeps Control independent so the matrix-game reveal in the debrief still works. The debrief gets a new per-turn section "Adversarial Red Team — Was spricht dagegen?" between the deliberation reveal and the verdict scorecard. Skips gracefully on snapshots without the new fields. 20 new tests; 212 total pass. Co-Authored-By: Claude Opus 4.7 (1M…497f031 -
Round 1: forecast cards, decision-quality rubric, confidence tags, cost tracking
Adds the measurement schema foundation downstream rounds depend on: - ConfidenceLevel (gesichert/plausibel/spekulativ) on every Anchor - DecisionQualityRubric (9 criteria x 1-7) on every Verdict - ForecastCard (probability, horizon, resolution_rule) emitted by Control - AdjudicationOutput composes verdicts + forecasts; VerdictList kept for re-adjudication - TurnUsage tracks per-turn token + USD cost; Game.total_usage aggregates - Game.seed for deterministic replays (recorded; provider plumbing later) - wargame.eval.scoring: brier_score + expected_calibration_error - wargame.agents.pricing: per-model USD-per-mtok table + cost_for() The control adjudicate prompt now requests rubric scores and 0-3 forecast cards alongside verdicts; system prefix stays stable for prompt caching. record_usage attributes USD cost into a context-bound TurnUsage so the loop can capture per-turn spend without threading state through callers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.c…76b1603 -
Action Coach (conversational action input) + orchestrator post-action guard (#6)
schipsy +1: Claude Opus 4.7 (1M context)Unverified signature* Add post-action guard to orchestrator route + UI gate The orchestrator clones a pristine Turn 1 to fork branches; clone_pristine raises ValueError if the source has already played. The route silently passed the request through, the worker swallowed the exception, and the UI showed three failed branches with no usable signal. Now the route rejects with 409 when game.world.turn > 1, the first turn has a player_action, or phase != BRIEFING. The frontend hides the launch button under the same conditions and shows a one-line helper pointing the user at fork. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Add Action Coach: conversational action input that drafts 3-anchor ActionSubmissions Adds a small LLM-driven coach that turns CEO prose into the engine's exact action contract (intent + justification + 3 anchors of valid kind). Mirrors the setup_agent shape: one structured-output call per turn, JSON session storage under games_dir/action_coach_sessions/, capped…2ead142 -
initial commit
Verified signaturee403f9a
-
Merge Board Console UI + setup agent + orchestrator into main (#5)
schipsy +1: Claude Opus 4.7Unverified signature* Wire real agent picker into recon (was hardcoded to missing 'analyst') Before: GameView called api.recon(id, 'analyst', …), which 409ed on every shipped scenario because none of them defines an agent with that id. Now: GameView chains GET /scenarios/{id}/agents off the existing listGames call, renders a dropdown of real agent labels (e.g. "Bettina Lange, CFO"), and passes the selected id to recon. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * Drop Claude Design handoff artifacts now that the UI is built Removes design-notes/, examples/, flows/, openapi.json, endpoints.md, and state-machine.md from frontend/. These were the spec handed to Claude Design to build the UI. Now that frontend/src exists and works against the API, the handoff docs are vestigial — the API is the contract and pyproject/FastAPI generate a live spec at /docs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * Replace frontend with Claude Design Board Console handoff Port t…fa0970b
-
Merge pull request #4 from schipsy/claude/silly-montalcini-731a2e
schipsyUnverified signatureSync README and CLAUDE.md with current codebase6eb11f1 -
Add missing orchestrator_synthesis prompt and unshadow it in .gitignore
wargame/orchestrator/synthesis.py calls render("orchestrator_synthesis", ...) but the template was never committed: .gitignore line 38 had a bare `orchestrator_synthesis.md` that matched paths globally (not just the intended root-level smoke-test file), so the file in wargame/prompts/ was silently ignored and never staged. CI exposed the missing template via 6 failing orchestrator/setup tests with FileNotFoundError. Fix: drop the ignore line and add the prompt template with the four-section synthesis contract (cross-branch patterns / vector wins-and-breaks / unasked question / recommended posture) that the debrief exporter expects.2b67ebf -
Add CI workflow running pytest on push + PR
Runs the existing offline pytest suite (156 tests, ~60s) on ubuntu-latest with Python 3.12 via uv. conftest.py already sets dummy env vars, so no secrets are needed. Gated on PRs so branch protection on main can require it before merge. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>641d0db -
Sync README and CLAUDE.md with current state of the codebase
The docs had drifted through three recent shipments (frontend drop, 8 DACH/EU scenarios, multi-model support + benchmark) and also undersold the debrief reveal by using "the CFO" as the hook example when the hit actually lands on named characters (Sir Rupert, Aergis, Andrew Greenwood, …) across 12 scenarios with 11-13 agents each. README: - Reveal hook: named-character examples instead of generic "CFO" - Scenarios: 4 -> 12, with a second table for the DACH/EU set - Tests: 120 -> 156, ~40s -> ~60s - LLM backend: rewritten for 3 providers (Anthropic via Foundry, Azure OpenAI Responses, Azure AI Inference); gpt-5.4 as default - Frontend: documents the shipped Vite + React + TS app alongside the API contract (no longer "deliberately not in this repo") - Architecture block: adds agents/providers/, scripts/, benchmarks/ - Deferred-to-v1: removes the stale "everything is claude-opus-4-6" line; per-game routing works, per-agent routing is what's left CLAUDE.md: - Frontend block: remove…9eaa92f -
Merge pull request #2 from schipsy/claude/objective-ramanujan-1f670b
schipsyUnverified signatureAdd 8 DACH/EU scenarios grounded in recent European events02cca71 -
Multi-model support: per-game model picker + live benchmark (#3)
schipsyUnverified signatureProvider abstraction behind call_structured so each game runs on any of five registered LLMs (Claude Opus 4.6/4.7, Claude Sonnet 4.6, GPT-5.4 via Azure OpenAI Responses, Kimi-K2.5 via Azure AI Inference). Chosen model is pinned on the Game and echoed in CLI, API, UI, and debrief header. Live-benchmarked every model against a fixed one-turn competitor_disruption run; two reports in benchmarks/. Default switched to gpt-5.4 — 45% faster than Opus 4.6 at par quality, the only model that meaningfully exercises server-side prompt caching (~63K re-used tokens per run). Added 429 exponential backoff (10s/30s/60s/120s) to the AI Inference provider after Kimi repeatedly hit its 8-concurrent capacity cap. Two rounds of review feedback addressed in-place. Key fixes: Anthropic cache_control moved from top-level kwarg (silently ignored) to the system content block — the benchmark's cache_read=0 across every Claude model was the smoking gun. Orchestrator now wraps run_orchestration in use_game_mode…b76b644
-
Add 8 DACH/EU scenarios grounded in recent European events
Ships 8 new playable war-gaming archetypes alongside the original 4, all fictionalized but inspired by real 2022-2026 European corporate and political pressure cycles: - energy_supply_shock — Austrian gas utility (Uniper-style derivative blowout) - signa_contagion — DACH department-store holding (Signa landlord insolvency fallout) - ev_transition — Swabian Tier-1 auto supplier (ICE→EV pivot, VW/MB/BMW concentration) - russia_exit — Vienna-HQ bank with CEE/Russia footprint (OFAC + ECB pincer) - swiss_bank_contagion — Swiss private bank (post-CS RM poaching + FINMA Pillar-2) - defense_ramp_up — German MDAX defense prime (Zeitenwende 3x ramp + ESG coalition) - orf_reform — Austrian public broadcaster (Stiftungsrat reshuffle + Generaldirektor contract) - hormuz_energy_shock — Austrian integrated oil & gas (Iran war + Strait of Hormuz) Each scenario ships the full three-file contract (world_bible.md, agents.yaml, initial_state.json) with 10-12 agents carrying distinct hidden_agenda + hidd…f4c25ce -
Merge pull request #1 from schipsy/frontend/initial-drop
schipsyUnverified signatureAdd Vite + React + TS frontend built by Claude Designe17fcfc -
Add Vite + React + TS frontend built by Claude Design
Drops a working UI scaffold into frontend/ wired against the FastAPI backend. Four screens (GamesList, NewGame, GameView, Debrief) hit the contract documented in frontend/openapi.json and frontend/endpoints.md. Vite proxies /api/* to VITE_API_BASE (default http://localhost:8080). Note: CLAUDE.md sec. 1 previously stated no frontend code lives in this repo. That rule needs a follow-up decision — keep the frontend here (update CLAUDE.md) or split into a sibling repo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>cf8cdd9 -
Wire --orchestrate flag on wargame new and wargame setup
Adds the one-command "CEO walk-up" experience: wargame new --scenario X --orchestrate # creates a game AND runs the 3-branch/1-turn Scenario Orchestrator, # printing the strategic-landscape synthesis inline. wargame setup my_topic --brief "..." --orchestrate # implies --auto-commit; runs the full chain: # setup conversation -> commit scenario -> new game -> orchestrate. # 12-16 minutes end-to-end, single command. Optional flags --orchestrate-branches and --orchestrate-turns override the defaults (3 branches, 1 turn) on both entry points. Shared _run_orchestrate_and_print() helper keeps behavior consistent across both commands. Prints progress, map id, vectors explored, and the full synthesis markdown. The default (no-flag) `wargame new` output now hints at `--orchestrate` as the one-command variant alongside the existing `wargame orchestrate` standalone command. Tests (CliRunner via Typer): - test_cli_new_with_orchestrate_flag - test_cli_new_without_orchestrate_hint…81ef5f6 -
Scrub Azure Foundry account identifier from .env.example
Replace the real subdomain in the endpoint placeholder with generic `your-foundry-account` / `your-project-id` tokens. Expand the comment to explain both accepted endpoint shapes (service base URL vs full project URL) since the config normaliser accepts either. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>c307437 -
Merge GitHub's auto-generated README into initial import
674f3d8 -
Initial commit: AI War Gaming prototype
A headless Python engine for strategic war-gaming: a single human CEO plays against 11-13 AI agents (CFO, CMO, rival CEO, regulator, media, board, unions) simulating the rest of the world. Matrix-game methodology — actions carry three anchors (prior_analogue, stated_capability, resource_committed); Control adjudicates plausibility 1-5 and emits effect_major / effect_minor / no_effect / backfires. Surfaces: Typer CLI (primary), FastAPI web wrapper, markdown debrief exporter. Azure AI Foundry via Anthropic's native Messages API at /anthropic/v1/messages. claude-opus-4-6 for every role in MVP. Features shipped: - 4 scenario archetypes (competitor_disruption, crisis_response, ma_integration, activist_investor), each with world bible + 8-13 agents with distinct hidden agendas + initial state. - Setup wizard: LLM-driven interactive scenario composer. - Document grounding: PDF/DOCX/MD/TXT attached to scaffolding. - Scenario Orchestrator: agentic-age Monte Carlo — K forked branches aut…0bf1063
-
Initial commit
schipsy4a330d0