From 8012b5d25cfe38a19e56c2d8863fbf32e13bf557 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Tue, 7 Jul 2026 00:32:04 -0400 Subject: [PATCH] =?UTF-8?q?feat(phase-b):=20sweep=20seeds=20=E2=80=94=20st?= =?UTF-8?q?ory-state=20explorer=20(which=20scenes=20a=20flag=20affects)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sweep [--boot] [0xADDR=VAL...] runs each scene with and without the seeds from the same baseline and reports which scenes' dialogue changes. Maps a story flag's reach across the corpus. Finding: the Lily form-A flag 0xa57=1 changes dialogue in 34/297 scenes (SC0000 186->229, SC0040 111->156, ...) — a pervasive ADV lever, validating the state-divergence finding at scale. Engine 18/18. Co-Authored-By: Claude Opus 4.8 (1M context) --- engine/Age.Cli/Program.cs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/engine/Age.Cli/Program.cs b/engine/Age.Cli/Program.cs index 3bbfbae..6ee938d 100644 --- a/engine/Age.Cli/Program.cs +++ b/engine/Age.Cli/Program.cs @@ -122,11 +122,43 @@ if (args[0] == "sweep") baseline = bootSession.ToJson(); Console.WriteLine($"[boot] baseline = {bootSession.Globals.Count} globals; running {names.Count} scenes from it."); } + // Optional seeds turn sweep into a story-state explorer: run each scene with AND without the seeds + // (from the same baseline) and report which scenes' dialogue changes — i.e. what a story flag affects. + var seeds = new List<(int, long)>(); + foreach (var s in args.Skip(1).Where(a => a.Contains('='))) + { + var kv = s.Split('='); + int k = kv[0].StartsWith("0x") ? Convert.ToInt32(kv[0], 16) : int.Parse(kv[0]); + long v = kv[1].StartsWith("0x") ? Convert.ToInt64(kv[1], 16) : long.Parse(kv[1]); + seeds.Add((k, v)); + } + GameSession Fresh() => baseline != null ? GameSession.FromJson(baseline) : new GameSession(); + int RunLines(string name, bool seeded) + { + var session = Fresh(); + if (seeded) foreach (var (k, v) in seeds) session.Seed(k, v); + return session.RunScene(Sys4Loader.Load(scripts[name], table), table, new CaptureHost()).Emitted.Count; + } + + if (seeds.Count > 0) + { + var changed = new List(); + foreach (var name in names) + { + int baseLines = RunLines(name, false), seededLines = RunLines(name, true); + if (baseLines != seededLines) changed.Add($"{name}: {baseLines} -> {seededLines} lines ({seededLines - baseLines:+#;-#;0})"); + } + var seedStr = string.Join(" ", seeds.Select(s => $"0x{s.Item1:x}={s.Item2}")); + Console.WriteLine($"seed [{seedStr}]{(boot ? " (booted)" : "")}: {changed.Count}/{names.Count} scenes change dialogue"); + foreach (var c in changed) Console.WriteLine(" " + c); + return 0; + } + var haltDist = new SortedDictionary(StringComparer.Ordinal); long totalLines = 0; var anomalies = new List(); foreach (var name in names) { - var session = baseline != null ? GameSession.FromJson(baseline) : new GameSession(); + var session = Fresh(); var r = session.RunScene(Sys4Loader.Load(scripts[name], table), table, new CaptureHost()); var halt = r.Halt ?? "null"; haltDist[halt] = haltDist.GetValueOrDefault(halt) + 1;