One random threshold per DIRECTED edge, drawn once per world: scenarios
sharing thresholds differ only in who is educated, the prototype's
'same world, different lever' trick. The cascade is plain BFS in rounds;
an educated student receives the fake but never forwards it, which is
the entire effect of the lever. The result stores the first-reached
round per node (exactly what a frontend animation needs).
Tests hand-craft a 4-node line graph with exact thresholds, so every
expectation is exact: spread, directional blocking, educated cutoff.
Preferential attachment via an attachment pool that holds one entry per
edge endpoint, so uniform draws are degree-proportional: that is the
whole hub-forming mechanism. A triangle step closes friend-of-a-friend
links with probability triangleProb, giving friend-group clustering.
Semantics ported from networkx, NOT its RNG stream (per the handoff,
no cross-language number matching).
Tests are property-based: size, edge bounds, connectivity, hub
formation across seeds, plus exact determinism for a fixed seed.
'go test ./...', gofmt and golangci-lint all clean.
Adjacency lives in slices, not maps, on purpose: Go randomises map
iteration order between runs, and the engine's determinism guarantee
needs every graph walk to visit neighbours in the same order. AddEdge
mirrors networkx semantics (duplicates and self loops are no-ops) so
the Holme-Kim port can lean on the same behaviour.
Receiver names stay short per Go convention (g *Graph); everything
else uses descriptive names.
math/rand/v2 (Go 1.22+) replaces the old math/rand: PCG generator,
no global Seed(), and rand.New(rand.NewPCG(seed, 0)) gives an isolated
deterministic stream. Each randomness consumer (graph, thresholds,
education sampling) will get its own stream so levers vary independently.
Tests live next to the code as *_test.go; 'go test ./...' runs them all.
'for i := range 100' is Go 1.22 range-over-int.
go.mod declares the module path (github.com/JustinZeus/spreadlab); every
import inside the repo is spelled relative to it. Layout follows the
standard Go shape: cmd/<binary>/main.go per executable, internal/ for
packages other modules may not import (the compiler enforces this).
No engine code yet, just a placeholder main that proves 'go build' works.