Village Economy Simulation: Implementation Spec

Document iteration: 2 (a living document). Date: 2026-10-12. Merges the iteration 2 addendum (owner review of the flow budget + decisions). See the changelog at the end. Later iterations revise decisions, so always read the latest iteration and its changelog before starting.

This is the single repository file holding natural-language specification, architecture, decisions and progress (governance rule, section 0 item 5). Machine-readable artifacts (the flow-budget CSV/XLSX, Go source, metrics) live beside it. There must not be separate PROGRESS.md, DECISIONS.md or report markdown files.

Status tags used throughout - [DECIDED]: stated or accepted by the project owner. - [PROPOSED]: suggested during design discussion, plausible default, not yet confirmed. Implement unless told otherwise, but keep it easy to change. - [OPEN]: explicitly undecided. Do not hard-code; keep the code flexible.


0. Working instructions for the coding agent

Executing agent: DeepSeek Flash 4.1 [DECIDED]. It should spin up subagents for context management [DECIDED]. The suggested working method below is [PROPOSED] and can be adjusted.

  1. Keep the main agent's context small. The main agent holds this spec's summary, the milestone plan (section 12), and the current progress log. It delegates implementation work instead of doing everything itself.
  2. Delegate by focused task. Spawn a subagent per component or milestone step, for example: graph + grid generator + pathfinding; economy entities and world timers; scripted/random policies and executors; metrics, determinism and conservation tests; sweep tooling. Give each subagent only the spec sections and interfaces it needs, not the whole conversation.
  3. Subagents return short reports: files changed, tests run and their results, open issues or deviations from the spec. The main agent integrates these and does not re-read all code.
  4. Shared interfaces are stable contracts. The Policy interface, graph structure, config struct, and snapshot format must not be changed by a subagent without reporting it to the main agent, which records the change in the decision log.
  5. One governance file [DECIDED: owner]. This spec is the single repository file for natural-language specification, architecture, decisions and progress. Update it (progress log appendix, decisions log appendix, changelog) after each step instead of writing separate PROGRESS.md / DECISIONS.md / report files. Keep it a living document: revise decisions in place, bump the iteration, and add a changelog line.
  6. After each milestone, run the determinism test (same config and seed gives identical output) and the item-conservation test before moving on.
  7. Close every work session properly [DECIDED: owner]. A session is not finished until (a) the progress log and fresh-session handover (Appendix D) are updated in this file, and (b) the current results are published to the public URL (section 0.9). This applies to every session, always, whether or not the owner asked.
  8. Proceed-and-log. When the spec is silent on a detail needed to keep moving, adopt a [PROPOSED] default, keep it easy to change, and record it in the decisions log appendix. Never decide [OPEN] items; batch those for the owner in the handover.
  9. Stay within scope. Do not add goods, tasks, or mechanics beyond this spec (section 2, principle 1). Out-of-scope items are listed in section 1 and section 13.
  10. Subagents are required [DECIDED]. The executing agent should spin up subagents for context management and delegate implementation by focused task; the main agent holds this spec's summary, the milestone plan, and the progress log.

0.9 Public URL and handover rule [DECIDED: owner]

The report is served over HTTPS by the shared Caddy instance at https://nn-village-sim.bernie-dev.de/ (see section 0.10). Every work session must close by regenerating that site from this spec and publishing the latest results there, and by updating the fresh-session handover (Appendix D). The public page is the owner's cockpit: current milestone status, flow-budget results, test evidence, and the open questions.

0.10 Hosting mechanics (do not re-derive)


1. Goal and scope

A 2D village simulation in which a small population of agents, each controlled by a small neural network (NN), lives in a resource economy that grows in complexity stage by stage. Agents have diverse skills, work on production chains, and are exposed to rare disasters.

The long-term vision is a townscape-style visual UI filled with life by the simulation, rendered later in the Godot engine. The UI is out of scope for now [DECIDED]. The immediate work is the simulation backend, the economy, and a deterministic scripted decision engine that stabilizes it.

Out of scope for now: UI/rendering, procedural town maps, trade/money, a townhall voting system, free-form agent communication, reinforcement learning. See section 13.

2. Guiding principles

  1. Keep the economy simple but interesting [DECIDED]. Two production chains, six task types, few goods. Do not add content before the existing chains are validated.
  2. Build the world and a scripted baseline first [DECIDED]. The scripted engine is the baseline, the teacher for NNs, and the fallback. NNs come later.
  3. Separate world tuning from agent learning. Tune world parameters with scripted agents only. Freeze them before any learning experiments.
  4. Everything is deterministic and reproducible from a config plus a seed.
  5. Headless first. The simulation core knows nothing about rendering.

3. Architecture

3.1 Language and runtime [DECIDED]

3.2 Separation from the future UI [DECIDED: Godot later]

3.3 Outputs for sweeps [PROPOSED]

4. World model

4.1 Map as a general graph [DECIDED]

Decision: do not settle on procedural town maps yet. Build the simulation on a graph abstraction and use a square 2D grid generator as the first (and for now only) map source.

Graph:
  nodes:  [{id, x, y}]
  edges:  [{id, from, to, travel_time}]      # time-based cost, not cell counts
  sites:  [{id, type, node}]                 # trees, field tiles, well, building lots...
  lots:   [{id, node, neighbors: [lot_id]}]  # explicit adjacency for fire spread

Rules: - Agent logic must not assume four neighbors, uniform edge cost, or integer coordinates. - Agent position is a node or an (edge, progress) pair, also on the grid, so the snapshot format stays stable when the map type changes. - Pathfinding: A using node coordinates for the heuristic. Cache distance fields (flow fields) per target type (nearest tree, well, brewery, ...) and invalidate on map change. - Use a spatial index or incremental counters for "nearest X" queries. Avoid scanning all objects. - A coarse graph is acceptable [PROPOSED]: one node per place (forest patch, field, house lot, junction), edges as roads with travel times. Economic behavior depends on distances, capacities and timing, not fine geometry. - Adjacency between lots is stored explicitly* (needed for fire spread) and is independent of walking edges.

4.2 Future procedural maps (reference only, not now)

For a later organic townscape look, known open-source references (read for algorithms and reimplement in Go; check licenses): - Watabou's Medieval Fantasy City Generator, source repo TownGeneratorOS (Haxe; license unclear, check). - ProbableTrain MapGenerator (TypeScript, tensor-field street networks, GPL-3.0; copying code into a distributed project can impose GPL). - Literature: Parish and Muller, "Procedural Modeling of Cities"; Chen et al., "Interactive Procedural Street Modeling". Both reference projects use fine grids for hundreds to thousands of buildings; the simulation graph can be much coarser.

4.3 Time

5. Economy

5.1 Chains [DECIDED]

Chain 1: Food and drink 1. A field tile is tilled, sown, grows (world timer), is harvested. 2. Wheat is carried to a silo. 3. Wheat is carried from the silo to the brewery; water is carried from the well to the brewery. 4. Beer is brewed (world timer). 5. Beer is carried to the inn, where it is drunk.

Beer counts as food [DECIDED]. Wheat is not eaten directly. Beer is the village's only food, so this chain is survival-critical.

Chain 2: Housing 1. Wood is chopped (trees regrow, world timer). 2. Logs are carried to a building site. 3. A house is built; agents can sleep in it. 4. Buildings decay over time and need repair (consumes logs).

5.2 World timers [DECIDED]

Crop growth, tree regrowth, beer brewing, building decay. All seeded and deterministic.

5.3 Capacities [DECIDED]

Buildings have finite capacity for people and for items: - House: N beds. - Inn: limited seats and service rate; drinking only works while a server is present (see 5.4). - Brewery: one batch at a time (batch size and brew time as parameters) [PROPOSED]. - Silo: finite wheat capacity. - Shelter during storms uses free capacity in any building (see section 11).

5.4 Tasks (what the agents choose between)

The six professions the owner named (farmer, carrier, innkeeper, brewer, wood chopper, builder) map to six task families. Professions are emergent labels, not hard slots [PROPOSED]: every agent can perform every task with a skill coefficient; "brewer" is a label derived from what an agent mostly does. Reason: a hard role system in a small village stalls whenever one role is unfilled.

Task Needs Produces Skill coefficient
farm a field tile stage advance (till, sow, harvest), wheat farming
chop a tree logs strength/axe
haul goods at A goods at B carrying (speed, capacity)
brew wheat + water at brewery beer after timer brewing
build (incl. repair) logs at site/building house progress / repair building
serve inn with beer makes drinking possible, its output is the service [DECIDED] serving

Need actions (not jobs): sleep (house with free bed), eat/drink (inn with beer and an attendant).

Simplifications to keep the network's output count small (about 8) [PROPOSED]: - farm is one task; the executor performs whichever stage the tile needs. - haul is one task; the executor picks the most urgent flow (destination demand, source surplus, distance). - Growth/brewing timers are world processes, not tasks. Agents never idle through them; they pick another task.

5.5 Initial conditions [DECIDED: owner decisions in iteration 2]

6. Agents

6.1 State

6.2 Decision cycle [PROPOSED]

6.3 Policy interface [PROPOSED]

type Policy interface {
    Decide(obs []float32, mask []bool) (scores []float32)  // masked argmax or softmax picks the task
}

Implementations: scripted, random, NN, NN-residual-on-scripted. Anything implementing it can also be a teacher for imitation. Keeping this interface small is how evolution-vs-RL stays undecided.

6.4 Observation vector [PROPOSED]

6.5 Per-task demand signals [PROPOSED]

Each workplace exposes a visible demand/urgency value (brewery lacks water, house needs logs). These are what let agents coordinate and prevent deadlocks. They are also the natural seed for prices if trade is ever added.

7. Decision engines

7.1 Scripted baseline (build first) [DECIDED]

Deterministic. Sketch [PROPOSED]: - Need overrides first: if a need is below a threshold, eat/sleep. - Otherwise score each task as urgency x skill coefficient / distance; pick the max; break ties by agent id. - No randomness except via the seeded RNG. Purpose: (a) make the world tunable, (b) baseline, (c) teacher for NNs, (d) fallback. Also build a random-task baseline as a lower bound. A well-tuned world shows a clear gap between random and scripted.

7.2 Neural networks (later)

7.3 Making NNs productive while learning [PROPOSED, owner likes the direction]

8. Fitness, pride, and decision incentives

9. Population dynamics

9.1 Immigration and emigration [DECIDED: possible]; rules [DECIDED: owner, iteration 2]

9.2 Lifespans [DECIDED]

Agents have a lifespan so scripted agents die out naturally. - Stagger founders' initial ages across the lifespan to avoid a synchronized die-off [PROPOSED]. - Vary lifespans per agent (mean +/- ~20%) [PROPOSED]. - Lifespan must be much longer than apprenticeship (at least 10 to 20x) [PROPOSED]. - On death, carried goods are dropped at the location (conservation). Log the cause: age, disaster, starvation.

9.3 Handover from scripted to NN agents [DECIDED direction; details PROPOSED]

9.4 Social imitation [DECIDED direction; details PROPOSED]

Selection pressure comes from who is chosen as teacher: random teachers give drift, successful teachers give evolution. 1. Newcomer spawns at the map edge with random skills and walks to the village. 2. It samples K nearby villagers (K about 3 to 5) and picks the one with the best smoothed recent welfare (adjusted for skill); softmax for diversity. 3. Weight copy + Gaussian mutation (simplest; requires identical architectures). The newcomer keeps its own skills. 4. About 10% "innovators" with large mutation or random start. 5. Apprenticeship phase for random-start newcomers: for the first T decisions the agent acts on the teacher's decision (teacher policy evaluated on the newcomer's own observation) or the scripted decision, while its own network trains in the background by behavior cloning. Hand over control once agreement with the teacher exceeds about 90%. 6. Use behavior cloning instead of weight copy when architectures differ (needed as networks grow between stages). 7. A teacher is anything implementing Policy, so scripted agents can be the first generation of teachers. - Optional visual flavor for the future UI: the newcomer follows its teacher; teaching requires proximity. - Which immigrant network source is best (random, mutated pretrained, sampled from an evolved pool) is [OPEN]: to be tested as an experiment after everything else is stable. Owner leans toward random newcomers with apprenticeship, accepting slower learning.

Pitfalls to guard against: - Monoculture (single lineage; missing skills like storm response vanish): mutation, innovators, mixing several teachers, a small fresh-lineage immigrant share. - Telephone-game degradation over generations: track agreement with the scripted policy across generations. - Noisy success signal: measure over a window; if best-of-K teachers do not beat random teachers, the signal is uninformative.

10. Population balance, the overshoot problem, and the flow budget

In earlier simulations the owner observed populations grow until all resources were depleted instead of reaching an equilibrium. Brakes built into this design: - Building upkeep (houses consume wood; wood regrowth is finite) [DECIDED observation, mechanism PROPOSED]. - Conditional immigration and automatic emigration (9.1). - Density-dependent fire spread (section 11). - Capacity limits (beds, seats, silo, brewery).

The flow budget was done before coding parameters (iteration 1, revised in iteration 2; see Appendix A and budget/flow_budget.py). The owner's iteration-2 review added requirements the budget must model [DECIDED: owner]:

The inn is the master population dial for the early stages [DECIDED]. One inn sets the population. A second inn as a later expansion is possible but must not be implemented now.

The flow budget's acceptance criteria (iteration 2) and its results live in Appendix A.

11. Disasters [DECIDED mechanics; details PROPOSED]

12. Implementation roadmap

Implement chain by chain. Design the inputs/outputs for all six tasks up front, but validate each chain with the scripted baseline before adding the next.

13. Deferred / optional ideas

14. Metrics to record from the start

15. Background references (for orientation)

16. Open questions summary

  1. Training method: evolution vs RL (postponed).
  2. Immigrant network source: random vs mutated pretrained vs sampled from evolved pool (test later; owner leans random with apprenticeship).
  3. Foraging fallback for food: adopt or not.
  4. Concrete definition and weights for pride/village welfare.
  5. Whether and when a townhall vote is added.
  6. Exact numeric parameters: to be derived from the flow budget (section 10) and sweeps.

17. Changelog


Appendix A — Flow budget (iteration 2)

The pre-code steady-state accounting required by section 10. Source of truth is budget/flow_budget.py; outputs are budget/flow_budget.csv, budget/flow_budget.xlsx. Reproduce with python3 budget/flow_budget.py.

Method. Flows in units per in-game day. Labor = work lines + travel lines. Haul capacity is derived from travel (carry_cap / weighted-average round-trip), so distances consume labor. A population is feasible when utilization ≤ 1, feed margin ≥ 0, and beds ≥ P. The paper model ignores latency and queuing, so it is an upper bound on feasibility and a lower bound on labor (owner's review, section 10); it is validated against measured M3 runs.

Starting parameters (all [PROPOSED] until measured runs confirm them).

Parameter Value Parameter Value
ticks_per_day 600 inn_service_slots × serve_rate_per_server 2 × 10 = 20 beer/day
work_fraction 0.5 target population (gate) 12–14 (ref 13)
beer_per_agent_day 1.0 immigration beer gate > 3 days supply + free beds
carry_cap 10 (≈ 50 items/day at these distances) tree_count_map 8 (≈ 2× the sustainable need)
ticks_per_edge / distances 15 ticks; field 5, tree 7, build 6, well/brewery/silo 4, inn 3 house_wood_cost, building_decay_days 20 logs, 20 days
founders / buffers 10–12; ~5 days beer + wheat buffer foraging yield 0 (switch off)

Results at the target population (P = 13, foraging off).

Quantity Value Acceptance target Met
Labor utilization (demand / supply) 0.843 (5.48 / 6.50 agent-days) 75–90% yes
Feed margin (inn cap − demand) / cap 35% ≥ 15% yes
Wood demand / regrowth supply 0.42 (4.0 / 9.6 logs/day) ≈ half yes
Bed margin 3 beds ≥ 0 yes
Inn staffing line 1.45 agent-days (26% of labor) explicit yes
Haul labor (travel-derived) 0.82 agent-days — —
Foraging on/off comparison shown (below) required yes

Feasibility by population (foraging off).

P utilization feed margin bed margin wood frac feasible
10 0.97 50% 2 0.31 yes
11 0.91 45% 1 0.31 yes
12 0.85 40% 0 0.31 yes
13 0.84 35% 3 0.42 yes
14 0.80 30% 2 0.42 yes
15 0.76 25% 1 0.42 yes
16 0.73 20% 0 0.42 yes
18 0.85 10% 2 0.52 yes
20 0.79 0% 0 0.52 yes

Foraging switch. Turning foraging on (assumed yield 0.3 beer/agent/day) lowers beer demand, so at P = 13 utilization drops to 0.77 and the feed margin rises to 55%. Default remains off to keep the budget honest (section 5.5).

Findings. - The inn remains the master dial (cap 20 beer/day); the immigration gate at 12–14 keeps the village ~30–35% below the feeding cap, so it never rides the hard limit. - Travel time is what makes labor tight: without it the same parameters leave a large surplus (iteration 1, ~64% idle). With time-based edges the target sits at ~84% utilization, inside the owner's 75–90% band. - Serving is the single largest labor line (~26%), so inn staffing is budgeted explicitly. - Wood is now a visible brake: demand is ~42% of regrowth for a map with 8 trees; the initial four houses also cost a one-off 80 logs. Tree count is an explicit config parameter.

Open questions carried to the owner (do not decide): confirm the exact inn cap (18 vs 20) and whether work_fraction 0.5 or 0.55 feels right; the paper model must be reconciled with measured M3 runs before any parameter is frozen.


Appendix B — Decisions log

Decisions made during implementation, beyond the spec body. Newest first.

2026-10-12 — Sweep metric visualization

2026-10-12 — M6 sweep tooling

2026-10-12 — M5 disasters

2026-10-12 — M4 population dynamics

2026-10-12 — M3 beer chain

2026-10-12 — M2 wheat chain

2026-10-12 — M1 housing chain

2026-10-12 — M0 skeleton

2026-10-12 — Spec iteration 2 merge

2026-10-12 — Flow budget (iteration 2)

2026-10-12 — Flow budget (iteration 1) and hosting

2026-10-12 — Repository bootstrap


Appendix C — Progress log

Milestone status (roadmap section 12). Update after every step.

Milestone Description Status
— Spec iteration 2 + flow-budget re-run (Appendix A) done
M0 Skeleton: tick loop, per-run RNG, graph + grid generator, config struct, metrics, determinism + conservation tests, Policy interface, scripted + random policies done
M1 Housing chain: chop, haul, build, sleep; regrowth, decay, repair; foraging switch done
M2 Wheat chain: farm stages, growth timer, silo, haul done
M3 Beer chain: well, water haul, brewery, inn, serve; beer as food; flow budget checked vs measured done
M4 Population dynamics: staggered lifespans, immigration/emigration, death causes done
M5 Disasters: fire (adjacency spread), storm (warning + shelter), scenario harness done
M6 Sweep tooling: sampling, seeds, early kill, regression suite done
M7 NN agents (out of scope for this run) not started
M8 Handover experiments (out of scope for this run) not started
M9 Snapshot/replay + Godot client (out of scope for this run) not started

Current run scope: M0–M6, autonomous, Go stdlib-first. Run complete.

M0 evidence (2026-10-12). Go module nnvillage, Go 1.22, standard library only. Packages: internal/config (all Appendix A parameters + ForagingYield switch), internal/world (graph, grid generator, Dijkstra distance fields, A*, sites + explicit lot adjacency), internal/sim (tick loop, seeded RNG, founders with staggered ages, ledger, metrics + state hash), internal/policy (Policy interface, scripted + random), cmd/village (CLI). go build ./..., go vet ./... and go test ./... pass. Two runs at -seed 12345 -ticks 3000 produce byte-identical JSON metrics and identical state hash (determinism test), and the ledger conserves items (conservation test). At M0 agents are idle by design (executors arrive in M1), so reported labor utilization is 0.

M1 evidence (2026-10-12). Mutable world state (internal/sim/state.go): trees with regrowth timers, fields with growth stages, buildings with condition + occupants + repair logs, build sites, named stores (yard/silo/brewery/inn) and ground piles. Executors (tasks.go) implement chop, haul, build/repair, sleep and eat with pathfinding and time-based walking; the scripted decision scores urgency × skill / distance with need overrides. Tree regrowth and building decay are world timers. The foraging switch is wired end-to-end (default off; forage at the nearest field/forest when hungry and no beer). Verified: at seed 12345 over 45 days the village holds 5 houses at mean condition ~0.97 with trees cycling (no wood deadlock), logs are conserved, and two identical runs produce byte-identical metrics. go test ./... green, including conservation over 6000 ticks and a foraging on/off test.

M2 evidence (2026-10-12). The farm task advances a field through till → sow → (world-timer growth) → harvest, then carries the wheat to the silo. A growing (sown) field is not offered as work, so agents do not idle through growth timers. Verified: at seed 7 the silo wheat rises 20 → 56 → 122 over 12 days while labor utilization stays in the 0.74–0.93 band. Conservation and determinism tests stay green.

M3 evidence (2026-10-12, + flow-budget check). The beer chain is complete: the well is infinite (water is created through the ledger on pickup), a general haul task moves wheat silo→brewery, water well→brewery and beer brewery→inn, the brewer loads a batch (inputs consumed, timer set) and the timer produces beer, and the innkeeper's serve shift makes drinking possible (SPEC 5.3: no server, no drinking). Beer is the only food. Measured vs paper budget (30 days, seeds 1/2/3/42/99): labor utilization 0.86–0.87 against the paper budget's 0.84 at P=13; serving is the largest labor line, as predicted; population holds at 11–12 with 5 houses at condition 0.90–0.98; beer/wheat/water cycle without unbounded growth (demand caps on brewing and farming). go test ./... green, including the beer-chain end-to-end test and conservation.

M4 evidence (2026-10-12). Population dynamics (population.go): a daily-day boundary update computes a smoothed days-of-beer-supply EMA; immigration requires free beds and > 3 days of smoothed supply, with a 3-day bootstrap warm-up so the initial buffer does not pull in newcomers early. Emigration is automatic after EmigrateUnmetDays of unmet needs; starvation death is a later fallback; age death at lifespan. Carried goods drop on the ground and beds are freed, so conservation holds across births/deaths (no births). Verified: seeds 42/7/1/99 all settle at population 14 (founders 12 + 2 immigrants) with no deaths or emigrations over 60 days, houses at ~0.97 condition and utilization 0.82–0.90; dedicated tests cover immigration, emigration and age death.

M5 evidence (2026-10-12). disasters.go implements fire and storm, both off by default (probability 0) so ordinary runs and their determinism baselines are unaffected; the scenario harness forces them via IgniteRandomHouse/IgniteBuilding/StartStorm (also CLI -fire and -storm). Fire spreads over the explicit lot adjacency with density-scaled probability, kills occupants, and is extinguished when agents haul FireWaterToExtinguish water from the well (an emergency task that preempts normal decisions). Storms emit a warning longer than a typical trip to shelter; agents take the internal shelter task (not a policy output) into any building with free capacity, and unsheltered agents/trees die with the configured probability. Tests cover spread, occupant death, shelter success under a long warning, boosted-frequency rolls, and conservation. M5 decisions: disasters are opt-in (so they never perturb the tuned equilibrium), and the storm/fire responses are emergency overrides rather than policy outputs, keeping the Policy vector at 8.

M6 evidence (2026-10-12). internal/sweep samples bounded parameter sets with a low-discrepancy Kronecker sequence over six world knobs (work fraction, serve rate, beer buffer, tree count, carry cap, house wood cost), runs each set over multiple seeds one-sim-per-goroutine, early-kills dead villages, and writes CSV keyed by config hash, seed and state hash. cmd/sweep exposes it: -runs, -seeds, -days, -jobs, -out. Verified worker determinism: 10 sets × 5 seeds × 5 days produces byte-identical CSV at -jobs 1 and -jobs 4 (50 rows). A regression suite (internal/sim/regression_test.go) runs per-stage benchmarks (housing sustains, full economy survives, halved-yield survives) with survival/utilization/conservation checks. The suite caught a real conservation leak — abandoning a task while carrying goods destroyed them — which is now fixed by dropping carried items on clearTask. M6 decisions: sweeps are deterministic by construction (independent runs, output sorted by run/seed); the regression suite is the guard against behaviour regressions per stage.


Appendix D — Fresh-session handover

Operational facts a fresh session needs. Updated at the close of every work session (section 0.7).

What this project is. A headless, deterministic 2D village economy simulation in Go, where a small population of agents works a two-chain economy (beer/food and housing), eventually driven by small neural networks. The long-term UI is a Godot townscape, out of scope. The binding process rules are in section 0; the design is the body of this file; the current numbers are in Appendix A.

Repository layout.

nn-village-sim/
├── SPEC.md                 # this file: spec + architecture + decisions + progress + handover
├── go.mod                  # module nnvillage, Go 1.22, standard library only
├── cmd/
│   ├── village/main.go     # run one sim; -seed -ticks -json -fire -storm
│   ├── sweep/main.go       # parameter sweeps; -runs -seeds -days -jobs -out
│   └── sweepviz/main.go    # scored runs + daily series -> budget/sweep_series.json
├── internal/
│   ├── config/config.go    # all world parameters + Hash()
│   ├── world/              # graph, grid generator, Dijkstra/A*, sites, lots
│   ├── policy/policy.go    # Policy interface; scripted + random
│   ├── sim/                # sim loop, state, tasks, needs, population, disasters, metrics, tests
│   └── sweep/sweep.go      # sampling, parallel execution, early kill, CSV
└── budget/
    ├── flow_budget.py      # iteration-2 budget generator (writes CSV/XLSX)
    ├── flow_budget.csv     # canonical computed output
    ├── flow_budget.xlsx    # spreadsheet (parameters + derived)
    ├── sweep_series.json   # daily metric series for best/average/worst sweep runs
    ├── sweep_charts.py     # renders sweep_series.json to inline SVG
    └── build_site.py       # renders SPEC appendices + sweeps to the public site

Reproduce the budget. python3 budget/flow_budget.py. Build-time Python deps: openpyxl, markdown (installed via pip install --user --break-system-packages). The CSV is canonical.

Public URL. https://nn-village-sim.bernie-dev.de/ (Caddy file_server on the /var/www mount; config /root/caddy/sites/nn-village-sim.caddy). Regenerate with python3 budget/build_site.py; reload Caddy only when the site config changes. Every session must republish here before finishing.

Verify. go test ./... (determinism, item conservation over 6000 ticks, beer-chain end-to-end, foraging switch, immigration/emigration/age-death, fire/storm scenarios, sweep worker determinism, and the per-stage regression suite). Also: go vet ./..., gofmt -l . (empty), go run ./cmd/village -seed 12345 -ticks 3000 -json twice → identical output; go run ./cmd/sweep -runs 10 -seeds 1,2,3,4,5 -days 5 -jobs 1 vs -jobs 4 → identical CSV. Regenerate the charted runs with go run ./cmd/sweepviz -runs 6 -seeds 1,2,3 -days 30 -jobs 4 (writes budget/sweep_series.json), then python3 budget/build_site.py.

Do not decide [OPEN] items (section 16); collect them for the owner in this handover. Prefer Go standard library; log any added dependency. Use subagents for focused implementation tasks.

Where the last session left off (run complete). Spec is at iteration 2 and its flow budget passes all acceptance targets (utilization 84% at P=13). M0–M6 are all complete and tested, Go standard library only: - M0 skeleton, M1 housing chain, M2 wheat chain, M3 beer chain (scripted two-chain economy at a stable equilibrium; measured utilization 0.86 matches the 0.84 budget), M4 population dynamics (village settles at population 14), M5 disasters (fire + storm, opt-in, scenario harness), M6 sweep tooling + regression suite (deterministic across workers; the suite caught and fixed a conservation leak). - Next actions (NOT started, for the owner to prioritise): M7 (NN agents: MLP policy, decision logging, imitation pretraining, residual policy) and M8 (handover experiments); M9 (snapshot/replay + Godot) is a separate project. Nothing beyond M6 was built. - Open questions for the owner are in section 16 and are unchanged: training method (evolution vs RL), immigrant network source, pride/village-welfare weights, townhall vote, and final numeric parameters. Also worth a decision: whether the immigration gate should target 12–14 explicitly or stay purely margin-based, and calibration of the disaster probabilities. - Regenerate the public site with python3 budget/build_site.py; run go test ./... before any change.