web: regenerate types and sync for the new forwarding levers

go generate brings novelty, harmAwareness, programEffect into the
generated Config and Bounds; preset base, field labels, the clamp switch,
and the test fixtures pick them up. No UI for them yet (that is the next
slice); behaviour and the demo are unchanged. type-check, unit tests and
lint all green, so CI's type-drift guard is satisfied.
This commit is contained in:
Justin Visser 2026-06-18 20:10:27 +02:00
parent f21994cc96
commit 430d59a2e8
8 changed files with 39 additions and 1 deletions

View file

@ -12,6 +12,9 @@ const base: Config = {
edgesPerNode: 2, edgesPerNode: 2,
triangleProb: 0.4, triangleProb: 0.4,
forwardProb: 0.5, forwardProb: 0.5,
novelty: 0,
harmAwareness: 0,
programEffect: 1,
numEducated: 3, numEducated: 3,
origin: 0, origin: 0,
graphSeed: 1, graphSeed: 1,

View file

@ -23,6 +23,9 @@ const TEST_BOUNDS: Bounds = {
edgesPerNode: { min: 1, max: 8 }, edgesPerNode: { min: 1, max: 8 },
triangleProb: { min: 0, max: 1 }, triangleProb: { min: 0, max: 1 },
forwardProb: { min: 0, max: 0.9 }, forwardProb: { min: 0, max: 0.9 },
novelty: { min: 0, max: 1 },
harmAwareness: { min: 0, max: 1 },
programEffect: { min: 0, max: 1 },
} }
// The fake engine: numReached mirrors numEducated so tests can tell which // The fake engine: numReached mirrors numEducated so tests can tell which

View file

@ -8,6 +8,9 @@ const bounds: Bounds = {
edgesPerNode: { min: 1, max: 8 }, edgesPerNode: { min: 1, max: 8 },
triangleProb: { min: 0, max: 1 }, triangleProb: { min: 0, max: 1 },
forwardProb: { min: 0, max: 0.9 }, forwardProb: { min: 0, max: 0.9 },
novelty: { min: 0, max: 1 },
harmAwareness: { min: 0, max: 1 },
programEffect: { min: 0, max: 1 },
} }
const config: Config = { const config: Config = {
@ -15,6 +18,9 @@ const config: Config = {
edgesPerNode: 3, edgesPerNode: 3,
triangleProb: 0.45, triangleProb: 0.45,
forwardProb: 0.38, forwardProb: 0.38,
novelty: 0,
harmAwareness: 0,
programEffect: 1,
numEducated: 36, numEducated: 36,
origin: 0, origin: 0,
graphSeed: 17, graphSeed: 17,

View file

@ -16,6 +16,9 @@ const preset: StudyPreset = {
edgesPerNode: 3, edgesPerNode: 3,
triangleProb: 0.45, triangleProb: 0.45,
forwardProb: 0.38, forwardProb: 0.38,
novelty: 0,
harmAwareness: 0,
programEffect: 1,
numEducated: 36, numEducated: 36,
origin: 0, origin: 0,
graphSeed: 17, graphSeed: 17,

View file

@ -39,6 +39,12 @@ export function clampConfigField(
return clampNumber(rounded, bounds.triangleProb.min, bounds.triangleProb.max) return clampNumber(rounded, bounds.triangleProb.min, bounds.triangleProb.max)
case 'forwardProb': case 'forwardProb':
return clampNumber(rounded, bounds.forwardProb.min, bounds.forwardProb.max) return clampNumber(rounded, bounds.forwardProb.min, bounds.forwardProb.max)
case 'novelty':
return clampNumber(rounded, bounds.novelty.min, bounds.novelty.max)
case 'harmAwareness':
return clampNumber(rounded, bounds.harmAwareness.min, bounds.harmAwareness.max)
case 'programEffect':
return clampNumber(rounded, bounds.programEffect.min, bounds.programEffect.max)
case 'numEducated': case 'numEducated':
return clampNumber(rounded, 0, numStudents) return clampNumber(rounded, 0, numStudents)
case 'origin': case 'origin':

View file

@ -7,7 +7,10 @@ export const CONFIG_FIELD_LABELS: Record<keyof Config, string> = {
edgesPerNode: 'Friends per student', edgesPerNode: 'Friends per student',
triangleProb: 'Clique tendency', triangleProb: 'Clique tendency',
forwardProb: 'Chance to forward', forwardProb: 'Chance to forward',
novelty: 'Novelty / shock',
harmAwareness: 'Harm awareness',
numEducated: 'Education budget', numEducated: 'Education budget',
programEffect: 'Program strength',
origin: 'First poster', origin: 'First poster',
graphSeed: 'Friendship network', graphSeed: 'Friendship network',
thresholdSeed: 'Who resists', thresholdSeed: 'Who resists',

View file

@ -28,6 +28,9 @@ export const deepfakeSchoolPreset: StudyPreset = {
edgesPerNode: 3, edgesPerNode: 3,
triangleProb: 0.45, triangleProb: 0.45,
forwardProb: 0.38, forwardProb: 0.38,
novelty: 0,
harmAwareness: 0,
programEffect: 1,
numEducated: 36, numEducated: 36,
origin: 0, origin: 0,
graphSeed: 17, graphSeed: 17,

View file

@ -20,8 +20,16 @@ export interface Config {
numStudents: number /* int */; numStudents: number /* int */;
edgesPerNode: number /* int */; // attachment edges per new student (network density) edgesPerNode: number /* int */; // attachment edges per new student (network density)
triangleProb: number /* float64 */; // chance to close a friend-of-a-friend triangle triangleProb: number /* float64 */; // chance to close a friend-of-a-friend triangle
forwardProb: number /* float64 */; // chance a student forwards the fake along an edge /**
* Forwarding is an additive composite (see ForwardChance): a baseline
* propensity, raised by how novel/shocking the fake is, lowered by the
* year group's ambient harm awareness.
*/
forwardProb: number /* float64 */; // baseline chance a student forwards the fake along an edge
novelty: number /* float64 */; // how novel/shocking the fake is (0..1); raises forwarding
harmAwareness: number /* float64 */; // ambient AI-literacy / harm awareness in the year group (0..1); lowers forwarding
numEducated: number /* int */; // students the education program reaches numEducated: number /* int */; // students the education program reaches
programEffect: number /* float64 */; // how strongly the program suppresses an educated student's forwarding (0..1; 1 = never forwards)
origin: number /* int */; // student who first posts the fake origin: number /* int */; // student who first posts the fake
graphSeed: number /* uint64 */; graphSeed: number /* uint64 */;
thresholdSeed: number /* uint64 */; thresholdSeed: number /* uint64 */;
@ -53,6 +61,9 @@ export interface Bounds {
edgesPerNode: IntBounds; edgesPerNode: IntBounds;
triangleProb: FloatBounds; triangleProb: FloatBounds;
forwardProb: FloatBounds; forwardProb: FloatBounds;
novelty: FloatBounds;
harmAwareness: FloatBounds;
programEffect: FloatBounds;
} }
/** /**
* Result is the outcome of one scenario run. * Result is the outcome of one scenario run.