-
Notifications
You must be signed in to change notification settings - Fork 0
build/qa: kit-scene contamination gate — auto-strip KitRoom_* roots at build + sandbox level-file scan #1690
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
0dedfa2
3e0104f
ecfa2e1
607a165
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| { | ||
| "version": 1, | ||
| "ortho": 11.7851, | ||
| "cols": 16, "rows": 12, | ||
| "provenance": "kit-derived (build_room_kit ExportBoxes): per-mass renderer bounds of KitRoom_crypt", | ||
| "boxes": [ | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-15, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-13, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-11, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-9, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-7, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-5, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-3, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [1, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [3, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [5, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [7, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [9, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [11, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [13, 0, 11]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [15, 0, 11]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-13, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-11, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-9, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-7, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-5, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-3, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-1, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [1, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [3, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [5, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [7, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [9, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [11, 0, -11]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [13, 0, -11]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, -11]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, 9]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, 7]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, 5]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, 3]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, 1]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, -1]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, -3]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, -5]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, -7]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-15, 0, -9]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, 9]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, 7]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, 5]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, 3]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, -1]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, -3]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, -5]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, -7]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [15, 0, -9]}, | ||
| {"kind": "tomb", "size": [6, 1.563, 2.609], "center": [1, 0, 0]}, | ||
| {"kind": "tomb", "size": [6, 0.75, 2.576], "center": [1, 0.761, 0]}, | ||
| {"kind": "tomb", "size": [1.739, 1.042, 4], "center": [1, 0, 0]}, | ||
| {"kind": "pillar", "size": [1.7, 4, 3.4], "center": [-7, 2, 4]}, | ||
| {"kind": "pillar", "size": [1.7, 4, 3.4], "center": [9, 2, 4]}, | ||
| {"kind": "pillar", "size": [1.7, 4, 3.4], "center": [-7, 2, -6]}, | ||
| {"kind": "pillar", "size": [1.7, 4, 3.4], "center": [9, 2, -6]}, | ||
| {"kind": "gate", "size": [0.95, 1.95, 0.95], "center": [-5, 0.975, 9]}, | ||
| {"kind": "gate", "size": [1.3, 0.45, 1.3], "center": [-5, 0.225, 9]}, | ||
| {"kind": "tavern", "size": [0.95, 1.95, 0.95], "center": [13, 0.975, 3]}, | ||
| {"kind": "tavern", "size": [1.3, 0.45, 1.3], "center": [13, 0.225, 3]}, | ||
| {"kind": "urn", "size": [1.8, 1.5, 1.8], "center": [5, 0.75, -3]}, | ||
| {"kind": "bone", "size": [1.8, 0.85, 3.6], "center": [-11, 0.425, -8]}, | ||
| {"kind": "cracked", "size": [1.8, 0.85, 1.8], "center": [-9, 0.425, -9]}, | ||
| {"kind": "tomb", "size": [0.95, 1.95, 0.95], "center": [-3, 0.975, 1]}, | ||
| {"kind": "tomb", "size": [1.3, 0.45, 1.3], "center": [-3, 0.225, 1]}, | ||
| {"kind": "tomb", "size": [0.95, 1.95, 0.95], "center": [5, 0.975, 1]}, | ||
| {"kind": "tomb", "size": [1.3, 0.45, 1.3], "center": [5, 0.225, 1]}, | ||
| {"kind": "buttress", "size": [1.7, 2.2, 1.7], "center": [-11, 1.1, 9]}, | ||
| {"kind": "buttress", "size": [1.7, 2.2, 1.7], "center": [-9, 1.1, 9]}, | ||
| {"kind": "buttress", "size": [1.7, 2.2, 1.7], "center": [3, 1.1, 9]}, | ||
| {"kind": "buttress", "size": [1.7, 2.2, 1.7], "center": [7, 1.1, 9]}, | ||
| {"kind": "buttress", "size": [1.7, 2.2, 1.7], "center": [9, 1.1, 9]} | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| { | ||
| "version": 1, | ||
| "ortho": 10.5224, | ||
| "cols": 14, "rows": 11, | ||
| "provenance": "kit-derived (build_room_kit ExportBoxes): per-mass renderer bounds of KitRoom_tavern", | ||
| "boxes": [ | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-13, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-11, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-9, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-7, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-5, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-3, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [-1, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [3, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [5, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [7, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [9, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [11, 0, 10]}, | ||
| {"kind": "wallback", "size": [2, 5.4, 1.4], "center": [13, 0, 10]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-11, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-9, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-7, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-5, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-3, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [-1, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [1, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [3, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [5, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [7, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [9, 0, -10]}, | ||
| {"kind": "parapet", "size": [2, 0.55, 1.4], "center": [11, 0, -10]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, -10]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, 8]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, 6]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, 4]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, 2]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, 0]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, -2]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, -4]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, -6]}, | ||
| {"kind": "parapet", "size": [1.4, 0.55, 2], "center": [-13, 0, -8]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, 8]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, 6]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, 4]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, 2]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, -2]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, -4]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, -6]}, | ||
| {"kind": "wallright", "size": [1.4, 5.4, 2], "center": [13, 0, -8]}, | ||
| {"kind": "bar", "size": [7.2, 1.4, 1.8], "center": [-6, 0.7, 6]}, | ||
| {"kind": "barrel", "size": [1.8, 1.5, 1.8], "center": [-9, 0.75, 8]}, | ||
| {"kind": "barrel", "size": [1.8, 1.5, 1.8], "center": [-7, 0.75, 8]}, | ||
| {"kind": "hearth", "size": [3.6, 1.4, 1.8], "center": [8, 0.7, 8]}, | ||
| {"kind": "table", "size": [1.8, 1.4, 3.6], "center": [-5, 0.7, -1]}, | ||
| {"kind": "table", "size": [1.8, 1.4, 3.6], "center": [5, 0.7, 1]}, | ||
| {"kind": "table", "size": [3.6, 1.4, 1.8], "center": [2, 0.7, -4]}, | ||
| {"kind": "table", "size": [3.6, 1.4, 1.8], "center": [10, 0.7, -4]}, | ||
| {"kind": "candle", "size": [0.95, 1.95, 0.95], "center": [3, 0.975, 8]}, | ||
| {"kind": "candle", "size": [1.3, 0.45, 1.3], "center": [3, 0.225, 8]}, | ||
| {"kind": "candle", "size": [0.95, 1.95, 0.95], "center": [11, 0.975, 4]}, | ||
| {"kind": "candle", "size": [1.3, 0.45, 1.3], "center": [11, 0.225, 4]} | ||
| ] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -188,6 +188,10 @@ public static void Build() | |
| // player can runtime-spawn actors for any campaign (not just the baked scene's cast). | ||
| EnsurePackaged(); | ||
|
|
||
| // Kit rooms (build_room_kit.cs) are QA constructions; a capture flow that saves the scene while | ||
| // one exists would otherwise ship it inside the player, drawing grey kit masses over every plate. | ||
| string[] strippedQARoots = StripQAConstructions(); | ||
|
|
||
| // --- Player identity (was DefaultCompany/WorldOS-Unity-spike) --- | ||
| PlayerSettings.companyName = "worldos"; | ||
| PlayerSettings.productName = "WorldOSPlayer"; | ||
|
|
@@ -259,13 +263,44 @@ public static void Build() | |
| "platform=" + s.platform + "\n" + | ||
| "architecture=" + archResult + "\n" + | ||
| "alwaysIncludedShaders=" + string.Join(",", includedShaders) + "\n" + | ||
| "strippedQARoots=" + (strippedQARoots.Length == 0 ? "(none)" : string.Join(",", strippedQARoots)) + "\n" + | ||
| "scenesBuilt=" + string.Join(",", options.scenes) + "\n"); | ||
|
|
||
| Debug.Log("[BuildMacOSPlayer] DONE result=" + s.result + " errors=" + s.totalErrors | ||
| + " warnings=" + s.totalWarnings + " size=" + s.totalSize + " time=" + s.totalTime | ||
| + " report=" + reportPath); | ||
| } | ||
|
|
||
| // QA-construction roots that must NEVER ship inside a player build. build_room_kit.cs assembles | ||
| // kit rooms as "KitRoom_<roomId>" roots in whatever scene is open; a capture/lighting flow that | ||
| // saves the scene mid-session bakes them in, and the built player then renders grey kit masses | ||
| // (fallback boxes, brazier plinths, parapets) in front of every plate. Measured three times | ||
| // (kit-crypt cleankit trap ×2, kit-tavern 2026-07-23 — the withheld tavern install). The build | ||
| // opens the canonical scene EXPLICITLY (also killing the wrong-open-scene trap), strips matching | ||
| // roots, saves, and reports them in build-report.txt (strippedQARoots=...). | ||
| const string QARootPrefix = "KitRoom_"; | ||
|
|
||
| static string[] StripQAConstructions() | ||
| { | ||
| var scene = UnityEditor.SceneManagement.EditorSceneManager.OpenScene(SceneToBuild); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: OpenScene(path) defaults to OpenSceneMode.Single and discards an unsaved current editor scene without a guard EditorSceneManager.OpenScene(SceneToBuild) with no mode uses OpenSceneMode.Single. This Build() MenuItem runs in the headed editor (the box forbids -batchmode, per the class doc), so if the operator has an unsaved scene open when they invoke Tools/WorldOS/Build/macOS Player, Unity raises the 'Unsaved changes in scene' dialog and the build blocks until dismissed — or, depending on editor settings, silently discards the operator's unsaved work in the open scene. OccluderVerify.cs:41 and W5bWireScene.cs:35 both call OpenScene(path, OpenSceneMode.Single) explicitly; at minimum make the mode explicit here for parity. More importantly, there is no Force/Save check, so this Build entry point can clobber operator work in a different open scene. Consider OpenSceneMode.Single plus a documented precondition or a SaveCurrentModifiedScenesIfUserWantsTo prompt before opening. Category: Data loss Why this matters: Build is an operator-facing MenuItem invoked from the headed editor. An unexpected scene swap mid-build is a data-loss surface for whatever the operator was editing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: StripQAConstructions opens the canonical scene in Single mode, dropping the editor's active scene StripQAConstructions calls EditorSceneManager.OpenScene(SceneToBuild) with no mode argument, which defaults to OpenSceneMode.Single — it replaces the editor's currently active scene. If a developer invokes Tools/WorldOS/Build/macOS Player (Universal) while editing a different scene with unsaved work, the build silently closes that scene. Use OpenSceneMode.Additive for the strip pass (and remove the stripped roots + the added scene afterward), or document that the build must be run from a clean state. The comment claims this 'opens the canonical scene EXPLICITLY (also killing the wrong-open-scene trap)' but the cost is destroying unsaved editor state on every invocation that hits the build path. Category: Runtime correctness Why this matters: A build menu item that silently discards the developer's active scene and unsaved changes is a real workflow hazard on a headed-editor build flow (the BOX.md-forbidden -batchmode path means this runs interactively). |
||
| var stripped = new List<string>(); | ||
| foreach (var go in scene.GetRootGameObjects()) | ||
| { | ||
| if (go != null && go.name.StartsWith(QARootPrefix, StringComparison.Ordinal)) | ||
| { | ||
| stripped.Add(go.name); | ||
| UnityEngine.Object.DestroyImmediate(go); | ||
| } | ||
| } | ||
| if (stripped.Count > 0) | ||
| { | ||
| UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: StripQAConstructions ignores SaveScene return value; a silent save failure ships contaminated art with strippedQARoots=(none) EditorSceneManager.SaveScene returns bool and fails non-throwing on read-only files, VCS/OneDrive locks, disk pressure, or a scene path that resolves but is not writable. Here the bool is discarded, so after DestroyImmediate has already mutated the in-memory scene, a failed save (a) leaves the canonical M1CombatV1_canonical.unity dirty on disk as built and (b) still returns the stripped list, so build-report.txt records strippedQARoots= while the on-disk/built scene still contains the roots. The build then proceeds at line 250 against the un-stripped source. Wrap the save: Category: Release regression Why this matters: The entire value of this gate is that no KitRoom_* ships. A silent save failure produces a build-report that claims success while the player renders the grey kit masses the PR exists to prevent — the exact kit-tavern contamination, just with a misleading evidence trail. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: Strip persists into the tracked source asset as a build side-effect; no smoke/rollback note SaveScene writes the strip back into Assets/Scenes/M1CombatV1_canonical.unity — a tracked source asset — as an irreversible side effect of Build(). After Build, the canonical scene on disk is permanently altered (the KitRoom_* roots are gone), and a subsequent git status will show the scene changed by a build run. The repo profile asks that scene changes carry explicit rollback and smoke notes; this PR's body should state the strip is destructive to the source scene and that BuildMacOSPlayer is the only recovery path (re-run build_room_kit to re-add, which is the opposite of the gate's intent). Consider writing a timestamped .unity.bak before SaveScene so an operator who ran Build against a scene they did not want stripped can recover without git surgery. Category: Unity scene/prefab Why this matters: A build mutating a tracked scene asset without a backup couples release packaging to source-tree mutation; an operator who triggers Build expecting packaging-only behavior silently commits a scene diff. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: StripQAConstructions persists a source-controlled scene file as a build side effect When stripped.Count > 0 the method calls EditorSceneManager.SaveScene(scene), writing Assets/Scenes/M1CombatV1_canonical.unity — a source-controlled canonical asset — during a build. This can produce an unexpected diff in the scene file (Unity may rewrite metadata/object ordering) that gets committed by accident, and there is no rollback note in the PR despite the repo's high-risk-paths policy requiring explicit rollback notes for Assets/** changes. Prefer destroying the roots in-memory only (the BuildPlayer call at line 250 opens its own copy of the scene from disk for the actual build) and NOT saving the source scene — the build does not require the source .unity to be re-saved, since BuildPlayer serializes from the loaded scene state. Category: Release regression Why this matters: Silent mutation of a canonical scene asset during a build is exactly the class of release-regression risk the repo profile flags as high-risk; an unintended scene diff could ship gameplay-changing object state. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P3: StripQAConstructions persists a destructive SaveScene on the canonical scene asset at build time StripQAConstructions() opens Assets/Scenes/M1CombatV1_canonical.unity, DestroyImmediate's every root whose name starts with "KitRoom_", then unconditionally calls EditorSceneManager.SaveScene(scene). This mutates the tracked canonical .unity source asset as a side effect of running the build menu item, and the strip predicate is a bare prefix match (QARootPrefix = "KitRoom_") with no allowlist. Today the kit lighting helpers (KitRoom_Fire/KitRoom_TombGlow/KitRoom_CoolKey in build_room_kit.cs:554/561/567) are nested children of the room root, so they are not root objects and survive — but if any future legitimate GameObject is ever placed at the scene ROOT with a KitRoom_ name, this build step will silently destroy it AND commit that deletion to source. The qa_sandbox.py detector (line 99) already maintains a whitelist for those helper prefixes; the stripper does not, so the gate and the stripper are asymmetric. Consider (a) narrowing the strip to the exact contaminant pattern (e.g. KitRoom_) or mirroring the qa_sandbox whitelist, and (b) only saving when a strip actually occurred is already done — but add a one-line guard/comment that this intentionally rewrites the source scene, so the destructive write is not mistaken for a build-output artifact. Category: Data loss Why this matters: A build step that silently rewrites the canonical gameplay scene asset is a release-regression/data-loss surface: a contaminant-removal intended for build output instead commits a structural edit to the source-of-truth scene, and the broad prefix makes future false-positive destruction likely. |
||
| Debug.LogWarning("[BuildMacOSPlayer] stripped QA construction roots from " + SceneToBuild | ||
| + ": " + string.Join(",", stripped)); | ||
| } | ||
| return stripped.ToArray(); | ||
| } | ||
|
|
||
| // #1674: shaders CombatSurfaceClient resolves at runtime via Shader.Find and that NO asset references, so | ||
| // the player build strips them unless they are listed in Graphics -> Always-Included Shaders. The player | ||
| // build MUST carry both or the runtime feature (occluder proxies / walk-behind silhouette) silently no-ops | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win
Correct the stale “boxes unchanged” provenance. Both entries replace the occluder sidecar, so claiming the prior boxes are unchanged makes the release evidence self-contradictory. Preserve that engine geometry/walkmask collision is unchanged, but explicitly state that the visual occluder sidecar changed. Confidence: 100%.
extensions/renderers/unity/plates_manifest.json#L52-L52: replacesame geometry/walkmask/boxes as crypt_v36with wording that distinguishes unchanged geometry/walkmask from the new kit-derived boxes.extensions/renderers/unity/plates_manifest.json#L82-L82: replacetavern_v2 geometry/walkmask/boxeswith the same distinction.📍 Affects 1 file
extensions/renderers/unity/plates_manifest.json#L52-L52(this comment)extensions/renderers/unity/plates_manifest.json#L82-L82🤖 Prompt for AI Agents