Avalonia MobilityLab (tax–mobility session)
Policies that keep the org coherent
name: Avalonia MobilityLab session overview: Add an Avalonia dogfood app MobilityLab that runs a controlled tax–mobility experiment on the Civics/Economy/Geopolitics kernels, with a readable scientific session (hypothesis, parameters, series, map, PASS/FAIL scorecard)—not a Spectre console clone. todos:
- id: scaffold
content: Scaffold MobilityLab Avalonia app (csproj, Program/App/MainWindow, CPM pins, slnx + READMEs) status: completed
- id: experiment-core
content: Implement TaxMobilityWorld/Month/ExperimentResult with PASS/FAIL coupling checks status: completed
- id: session-ui
content: "Build scientific session UI: hypothesis, params, series canvas, map, Briefing scorecard" status: completed
- id: headless-docs
content: Add --headless evidence output + README abstract/identification; verify build/run status: completed isProject: false
Academic framing (locked)
Research question: Holding geography and initial stocks fixed, does raising polity Alpha’s household tax above the Economy tax-push / Civics emigration thresholds cause (1) net population outflow, (2) higher emigration pressure, and (3) weaker legitimacy vs a low-tax twin Beta, with Gamma as a low-tax destination?
Design: twin / treatment–control month loop (not free-play theatre). One optional “war shock” toggle exists as a confounder switch, off by default so the primary claim stays identifiable.
Placement and stack
New app: `d:\novolis\novolis-dogfooding\apps\avalonia\MobilityLab\`
- Template: MovieMakerLab-style
Program/App/MainWindow(Fluent, noAvalonia.Fonts.Inter). - Visual language: navy/teal + copper amber (scientific session, not purple SaaS / cream terracotta). Brand hero: MobilityLab as first-viewport title.
- Packages: Avalonia 12 + Desktop + Fluent + DataGrid;
Novolis.Avalonia.Briefing(scorecard / metric table / feed); triad kernels matching PolityTriad (Civics.*,Economy.Core,Geopolitics.Core|Diplomacy|Trade|Conflict,Civics.EconomyBridge,Civics.Agents). - Add missing CPM pins in `Directory.Packages.props`:
Novolis.Avalonia.Briefing2026.1.*(and Agents/Conflict if not already present from PolityTriad).
Register in `Novolis.Dogfooding.slnx` under /avalonia/, plus root README row and app README with absolute dotnet run + ProjectRef flag.
Simulation core (app-local, rigorous)
Do not drag Spectre PolityTriad into the Avalonia project. Implement a focused experiment host:
| Type | Role |
|---|---|
| `TaxMobilityWorld` | Seed 3 polities / 6 provinces (α treatment, β control, γ haven); dual Economy ledgers; sync demography from owned pop |
| `TaxMobilityMonth` | Month order: agents → trade → Economy periods → Civics delivery → Gamma geo civic → `PopulationMigration` → optional conflict → sample |
| `MonthSample` / `ExperimentHistory` | Series: pop, net migration, emigration pressure, legitimacy, tax, prodVal, control |
| `ExperimentSpec` | Parameters: α tax, β tax, months, seed, warShockOn |
| `ExperimentResult` | End stocks + `CouplingCheck[]` with PASS/FAIL and human-readable claims |
Reuse kernel APIs already proven in PolityTriad / Wave 1 (CivicEconomyBridge, PopulationMigration, pop-weighted control, tax-push migrate). Formulas stay in kernels; the app only configures treatments and reports.
Default treatment: α tax 0.38, β tax 0.14, γ tax 0.12, 36 months, seed 42.
UI composition (understandable first viewport)
One composition, one job:
flowchart TB
header [MobilityLab title plus hypothesis]
params [Tax knobs Run Reset]
body [Series plus province map]
evidence [Briefing Scorecard and Feed]
header --> params --> body --> evidence- Hypothesis strip — one sentence RQ + expected signs (α pop net < 0, α pressure > β, α L < β L at horizon).
- Controls — α/β tax sliders or numeric boxes, Months, Run / Step / Reset; war shock checkbox (off by default).
- Series panel — lightweight Avalonia
Canvaspolylines for α/β population and emigration pressure (no new chart package); legend in mono only for Raw values if needed. - Map strip — province ownership + population labels (text/grid, readable).
- Evidence —
ScorecardView/MetricTableView/FeedPanelfrom Briefing for coupling checks and month log (escape any markup).
HardPause while editing params; Run advances on UI timer or blocking Run(N) then refresh.
Docs / rigor
App README sections: Abstract, Identification strategy, Month loop, How to reproduce, Interpretation of PASS/FAIL. Link `demography-coupling.md`.
Verification
dotnet build d:\novolis\novolis-dogfooding\apps\avalonia\MobilityLab\MobilityLab.csproj -p:NovolisUseProjectReferences=true
dotnet run --project d:\novolis\novolis-dogfooding\apps\avalonia\MobilityLab\MobilityLab.csproj -p:NovolisUseProjectReferences=trueHeadless smoke path: --headless 36 writes the same scorecard text to stdout (for CI/agents without a display).