Skip to content

HDR alpha remap — implementation plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Stop the HDR canvas’s linear-light alpha blending from lifting faint translucent layers ~10-20x (the “washed out” HDR look) by remapping alpha a -> a^γ on the HDR canvas only.

Architecture: A new per-profile static ALPHA_GAMMA (SDR 1.0 = identity, HDR 2.2) is pushed as the global shader uniform hdr_alpha_gamma by the existing ShaderGlobals.push, which already follows the same decision as the root use_hdr_2d hold. A shared include hdr_alpha.gdshaderinc applies it as the last write of COLOR.a. fx/additive_mat.tres (~50 users) becomes a saved ShaderMaterial carrying the include; the shaders behind the measured worst layers get it directly. No runtime material swapping.

Tech Stack: Godot 4.7 typed GDScript, canvas_item shaders, GUT, Node node --test (console tools).

Spec: docs/superpowers/specs/2026-10-10-hdr-alpha-remap-design.md

  • Work in worktree .claude/worktrees/hdr-colour-space, branch hdr-colour-space. Implementer subagents get their OWN worktree off this branch’s tip, never the main checkout.
  • SDR look must be byte-identical: ColorProfileSdr.ALPHA_GAMMA = 1.0, pow(a, 1.0) == a.
  • ColorProfileHdr.ALPHA_GAMMA seed 2.2. Registry range min 1.0, max 3.0 on both profiles.
  • Global name hdr_alpha_gamma, type float, declared in [shader_globals] of BOTH project.godot and platform/tvos/project.godot at 1.0, ; comments only (a # line swallows the next key).
  • Saved materials only: never ShaderMaterial.new() / CanvasItemMaterial.new() at runtime in shipped dirs (godot#124088; tests/test_baked_shader_materials.gd).
  • Out of scope: default-material draw_* / StyleBoxFlat (HUD bars), HeroLights, GPUParticles process materials, arena_galaxy.gdshader (writes alpha 1.0, remap is a no-op).
  • Gate: scripts/gate.sh (or scripts/check-test-count.sh; never pull a whole GUT run into context). After merges adding class_names run godot --headless --path . --import first, then git checkout -- project.godot audio/bus_layout.tres (keep YOUR intended project.godot edits: re-apply or commit them before the checkout).
  • The headless gate never compiles shaders: every shader edit gets a windowed compile check under --rendering-method mobile AND --rendering-method gl_compatibility.
  • Commit with git commit --file=<msgfile>, message ending with the session attribution lines.

Task 1: ALPHA_GAMMA profile value, hdr_alpha_gamma global, shared include

Section titled “Task 1: ALPHA_GAMMA profile value, hdr_alpha_gamma global, shared include”

Files:

  • Modify: render/color_profile_sdr.gd (next to BORDER_HALO, line ~48)
  • Modify: render/color_profile_hdr.gd (next to BORDER_HALO, line ~35)
  • Modify: render/shader_globals.gd:18-19 (GLOBALS)
  • Modify: project.godot and platform/tvos/project.godot ([shader_globals], after cs_linearize)
  • Modify: net/tunables_registry.gd (after each profile’s BORDER_HALO row, lines ~1023 and ~1070)
  • Modify: tools/tunable_docs/docs.d/color_profiles.json (after each BORDER_HALO entry), then regenerate control/src/tunable_docs.js with the repo’s generator (find it: git grep -l "docs.d" -- tools scripts; a hand edit of the generated file fails the gate)
  • Create: render/shaders/hdr_alpha.gdshaderinc
  • Test: tests/test_color_profiles.gd

Interfaces:

  • Produces: ColorProfileSdr.ALPHA_GAMMA: float = 1.0, ColorProfileHdr.ALPHA_GAMMA: float = 2.2, global uniform hdr_alpha_gamma, include res://render/shaders/hdr_alpha.gdshaderinc exposing float hdr_alpha(float a).

  • Step 1: Write the failing tests (edit tests/test_color_profiles.gd)

Add "ALPHA_GAMMA": 1.0, to SDR_BUNDLED (after "BORDER_HALO": 2.2,) and "ALPHA_GAMMA": 2.2, to HDR_SEEDS. In test_push_sends_the_profiles_values, extend the SDR expected list to:

assert_eq(_pushed, [[&"border_halo", 2.2], [&"wfx_hot", 1.0], [&"wfx_accent", 1.0], [&"boss_hot", 1.0],
[&"dissolve_edge", 1.0], [&"glass_cap", 10000.0], [&"hdr_alpha_gamma", 1.0]], "SDR: today's look, byte for byte")

and after the HDR push assertions add assert_has(_pushed, [&"hdr_alpha_gamma", 2.2], "HDR: the alpha remap"). Append:

# HDR alpha remap (spec 2026-10-10): the HDR canvas blends alpha in linear light, so hdr_alpha()
# raises alpha to hdr_alpha_gamma there; SDR pushes 1.0 (identity).
func test_hdr_alpha_include_reads_the_global() -> void:
var src := FileAccess.get_file_as_string("res://render/shaders/hdr_alpha.gdshaderinc")
assert_true(src.contains("global uniform float hdr_alpha_gamma;"))
assert_true(src.contains("float hdr_alpha(float a)"))
assert_true(src.contains("pow(a, hdr_alpha_gamma)"))
  • Step 2: Run, verify FAIL

Run: GUT_LOG=$TMPDIR/bh-alpha-t1.log scripts/check-test-count.sh (or the single script via the GUT -gselect=test_color_profiles.gd invocation in docs/reference/running-and-testing.md). Expected: FAIL in test_sdr_bundled_values_are_todays_look (count), test_hdr_seeds, test_push_sends_the_profiles_values, test_hdr_alpha_include_reads_the_global.

  • Step 3: Implement

render/color_profile_sdr.gd, after BORDER_HALO:

# HDR alpha remap (spec 2026-10-10; shader global hdr_alpha_gamma): alpha exponent applied by
# hdr_alpha() on the HDR canvas. 1.0 here = identity, the 8-bit canvas already blends in gamma space.
static var ALPHA_GAMMA: float = 1.0

render/color_profile_hdr.gd, after BORDER_HALO:

# The HDR canvas blends alpha in LINEAR light, so a faint fill authored for SDR is ~10x brighter.
# a^γ matches SDR over black (γ ≈ the sRGB curve). 1.0 = no remap (the live A/B "off").
static var ALPHA_GAMMA: float = 2.2

render/shader_globals.gd:

const GLOBALS := {&"border_halo": "BORDER_HALO", &"wfx_hot": "WFX_HOT", &"wfx_accent": "WFX_ACCENT",
&"boss_hot": "BOSS_HOT", &"dissolve_edge": "DISSOLVE_EDGE", &"glass_cap": "GLASS_BACKDROP_CAP",
&"hdr_alpha_gamma": "ALPHA_GAMMA"}

Both project files, after the cs_linearize={...} block:

; HDR alpha remap (render/shaders/hdr_alpha.gdshaderinc): SDR value 1.0 = identity.
hdr_alpha_gamma={
"type": "float",
"value": 1.0
}

net/tunables_registry.gd:

{"key": "ColorProfileSdr.ALPHA_GAMMA", "script": COLOR_SDR, "name": "ALPHA_GAMMA", "min": 1.0, "max": 3.0},
{"key": "ColorProfileHdr.ALPHA_GAMMA", "script": COLOR_HDR, "name": "ALPHA_GAMMA", "min": 1.0, "max": 3.0},

docs.d/color_profiles.json:

"ColorProfileSdr.ALPHA_GAMMA": {
"label": "SDR alpha remap exponent",
"desc": "SDR look (no HDR output): Exponent applied to translucent alpha (shader global hdr_alpha_gamma). 1 = no remap, the right value on the gamma-space SDR canvas.",
"src": "code",
"group": "Glow & colour grade"
},
"ColorProfileHdr.ALPHA_GAMMA": {
"label": "HDR alpha remap exponent",
"desc": "HDR look (HDR output on): The HDR canvas blends in linear light, so faint fills look about 10x brighter than on SDR. Alpha is raised to this power to match. 2.2 = matches SDR over black, 1 = off (the washed-out look).",
"src": "code",
"group": "Glow & colour grade"
},

render/shaders/hdr_alpha.gdshaderinc:

// HDR alpha remap (spec docs/superpowers/specs/2026-10-10-hdr-alpha-remap-design.md). The 8-bit SDR
// canvas blends alpha on sRGB-encoded values; the HDR (use_hdr_2d) canvas blends in linear light, so a
// faint fill is ~10x brighter there. hdr_alpha_gamma is the active colour profile's ALPHA_GAMMA
// (ShaderGlobals.push): 1.0 on SDR (identity), ~2.2 on HDR. DECLARED in [shader_globals] of both project
// files (the export baker fails on runtime-only globals). Call it as the LAST write of COLOR.a in fragment().
#ifndef HDR_ALPHA_INC
#define HDR_ALPHA_INC
global uniform float hdr_alpha_gamma;
float hdr_alpha(float a) {
return a <= 0.0 ? 0.0 : pow(a, hdr_alpha_gamma);
}
#endif
  • Step 4: Run, verify PASS; also run node --test in tools/tunable_docs if it has tests, and the docs.d gate test (it runs in scripts/gate.sh).
  • Step 5: Commit — feat(hdr): ALPHA_GAMMA profile value + hdr_alpha_gamma global + hdr_alpha include

Task 2: fx/additive_mat.tres becomes a saved ShaderMaterial with the remap; CS_ADD / CS_MIX get it

Section titled “Task 2: fx/additive_mat.tres becomes a saved ShaderMaterial with the remap; CS_ADD / CS_MIX get it”

Files:

  • Create: render/shaders/additive.gdshader
  • Modify: fx/additive_mat.tres (same path, new type)
  • Modify: render/shaders/cs_add.gdshader, render/shaders/cs_mix.gdshader (the shaders behind cs_add_mat.tres / cs_mix_mat.tres; confirm names with grep shader render/shaders/cs_*_mat.tres)
  • Modify: the 50 typed preload sites (recipe below)
  • Modify: tests/test_fx_manager.gd:334-339
  • Create: tests/test_hdr_alpha.gd

Interfaces:

  • Consumes: res://render/shaders/hdr_alpha.gdshaderinc, hdr_alpha(float) (Task 1).

  • Produces: preload("res://fx/additive_mat.tres") is a ShaderMaterial; typed holders are Material. ColorSpace.ADDITIVE, FxManager.ADDITIVE_MAT, PrewarmPass.ADDITIVE_MAT are typed Material.

  • Step 1: Write the failing test tests/test_hdr_alpha.gd

extends GutTest
# HDR alpha remap (spec docs/superpowers/specs/2026-10-10-hdr-alpha-remap-design.md): every material
# behind the measured worst HDR-lift layers applies hdr_alpha() as the last write of COLOR.a.
const INCLUDE := "#include \"res://render/shaders/hdr_alpha.gdshaderinc\""
const SHADERS := [
"res://render/shaders/additive.gdshader",
"res://render/shaders/cs_add.gdshader",
"res://render/shaders/cs_mix.gdshader",
]
func _fragment_body(src: String) -> String:
var i := src.find("void fragment()")
return src.substr(i) if i >= 0 else ""
func test_targets_include_and_apply_the_remap_last() -> void:
for p: String in SHADERS:
var src := FileAccess.get_file_as_string(p)
assert_true(src.contains(INCLUDE), "%s includes hdr_alpha" % p)
var frag := _fragment_body(src)
assert_ne(frag, "", "%s has a fragment()" % p)
var at := frag.rfind("COLOR.a = hdr_alpha(COLOR.a);")
assert_gt(at, -1, "%s remaps alpha" % p)
var tail := frag.substr(at + 1)
assert_false(tail.contains("COLOR.a") or tail.contains("COLOR ="), "%s: nothing writes alpha after the remap" % p)
func test_additive_mat_is_a_saved_additive_shader_material() -> void:
var m: Material = preload("res://fx/additive_mat.tres")
assert_true(m is ShaderMaterial, "additive_mat carries the remap shader")
var sh := (m as ShaderMaterial).shader
assert_eq(sh.resource_path, "res://render/shaders/additive.gdshader")
assert_true(sh.code.contains("blend_add"), "still additive")
assert_ne(m.resource_path, "", "saved, so the export baker compiles it")
func test_no_canvas_item_typed_additive_holders_left() -> void:
for dir: String in ["res://fx", "res://render", "res://ui", "res://tools"]:
_scan(dir)
var main_src := FileAccess.get_file_as_string("res://main.gd")
assert_false(main_src.contains("CanvasItemMaterial = preload(\"res://fx/additive_mat.tres\")"), "main.gd")
func _scan(dir: String) -> void:
for f in DirAccess.get_files_at(dir):
if f.ends_with(".gd"):
var p := dir.path_join(f)
assert_false(FileAccess.get_file_as_string(p).contains("CanvasItemMaterial = preload(\"res://fx/additive_mat.tres\")"), p)
for d in DirAccess.get_directories_at(dir):
_scan(dir.path_join(d))
  • Step 2: Run, verify FAIL (additive.gdshader missing, additive_mat still CanvasItemMaterial, 50 typed sites).

  • Step 3: Implement

render/shaders/additive.gdshader:

shader_type canvas_item;
render_mode blend_add;
// The shared additive material (fx/additive_mat.tres, ~50 users). Was a CanvasItemMaterial
// (blend_mode ADD); a saved ShaderMaterial now so it can carry the HDR alpha remap
// (render/shaders/hdr_alpha.gdshaderinc). Identical on SDR (hdr_alpha_gamma 1.0).
#include "res://render/shaders/hdr_alpha.gdshaderinc"
void fragment() {
COLOR.a = hdr_alpha(COLOR.a);
}

fx/additive_mat.tres (write via the Godot editor/headless save or by hand; keep uid lines if the old file had one; it does not):

[gd_resource type="ShaderMaterial" load_steps=2 format=3]
[ext_resource type="Shader" path="res://render/shaders/additive.gdshader" id="1"]
[resource]
shader = ExtResource("1")

Then run godot --headless --path . --import so additive.gdshader.uid is generated; commit the .uid.

CS_ADD / CS_MIX shaders: add the include under the existing color_space include and a fragment:

#include "res://render/shaders/hdr_alpha.gdshaderinc"
...
void fragment() {
COLOR.a = hdr_alpha(COLOR.a);
}

Retype recipe (deterministic; 50 sites verified by git grep -c):

Terminal window
git grep -l 'CanvasItemMaterial = preload("res://fx/additive_mat.tres")' -- '*.gd' \
| xargs sed -i '' 's/: CanvasItemMaterial = preload("res:\/\/fx\/additive_mat.tres")/: Material = preload("res:\/\/fx\/additive_mat.tres")/'
git grep -n 'CanvasItemMaterial = preload("res://fx/additive_mat.tres")' -- '*.gd' # expect no output

Then fix any remaining use that needs the narrower type: git grep -n -E 'ADDITIVE(_MAT)?\)?\.(blend_mode|light_mode|particles)' (verified none in fx/render/ui/main.gd on 2026-10-10). Comments that say “CanvasItemMaterial” about the shared material (render/color_space.gd:92, fx/fx_manager.gd:11) get updated to “the shared additive material”.

tests/test_fx_manager.gd test_pooled_fx_share_one_additive_material, replace the two type asserts with:

assert_true(shared is ShaderMaterial, "the shared additive material (carries the HDR alpha remap)")
assert_true((shared as ShaderMaterial).shader.code.contains("blend_add"), "same additive look")
  • Step 4: Run godot --headless --path . --import, git checkout -- audio/bus_layout.tres (and project.godot only if the import changed anything beyond Task 1’s committed block: git diff project.godot), then the gate. Expected: PASS, test count +3.
  • Step 5: Windowed shader compile check under both renderers (boot the game ~10 s into a run; any shader error prints SHADER ERROR):
Terminal window
for r in mobile gl_compatibility; do perl -e 'alarm 40; exec @ARGV' godot --path . --rendering-method $r 2>&1 | grep -i -E 'shader error|error:' | head; done
git checkout -- project.godot audio/bus_layout.tres platform/tvos/project.godot

Expected: no shader errors.

  • Step 6: Commit — feat(hdr): shared additive material carries the HDR alpha remap

Task 3: Remap in the shaders behind the measured layers

Section titled “Task 3: Remap in the shaders behind the measured layers”

Files (verified 2026-10-10: each has one fragment(); last alpha write shown):

Shader Last alpha write today
render/shaders/arena_grid_breathe.gdshader COLOR.a *= (1.0 - breathe_depth) + ... (l.11)
render/shaders/arena_aurora.gdshader COLOR.a *= v_alpha; (l.25)
render/star_field.gdshader COLOR.a *= v_alpha; (l.21)
render/web_field.gdshader COLOR = vec4(web_col, ...); (l.45)
render/web_field_lite.gdshader read it: the final COLOR write
render/web_look_a.gdshader, web_look_b.gdshader, web_look_c.gdshader read each: the final COLOR write
render/shaders/enemy_smear.gdshader COLOR.a *= tail; (l.17)
  • Modify: tests/test_hdr_alpha.gd (SHADERS)

Recipe per shader: add #include "res://render/shaders/hdr_alpha.gdshaderinc" after render_mode (or after shader_type when there is none), and append COLOR.a = hdr_alpha(COLOR.a); as the LAST statement of fragment(), after every existing COLOR/COLOR.a write and outside any early return/discard branch that would skip it (if a fragment returns early, restructure so the remap runs on every path that writes a visible alpha).

  • Step 1: Failing test — append the nine paths above to SHADERS in tests/test_hdr_alpha.gd. Run: FAIL (nine “includes hdr_alpha”).
  • Step 2: Implement the recipe in all nine.
  • Step 3: Gate PASS, then the windowed compile check from Task 2 Step 5 under both renderers (web looks: switch through them with the existing web-look console command or tests/test_web_look_switch.gd’s mechanism, so a/b/c compile too).
  • Step 4: Commit — feat(hdr): alpha remap in the arena, web, star and smear shaders

Files:

  • Modify: tools/console_mcp/lib/hdr_ab.mjs, tools/console_mcp/hdr_ab.mjs, tools/console_mcp/test/hdr_ab.test.mjs
  • Modify: docs/architecture/rendering-and-performance.md (§ “The HDR canvas blends alpha in LINEAR light”)

Interfaces:

  • Produces: phaseCommand(toggle, on, { gamma }) in lib/hdr_ab.mjs returning the console command for one phase.

  • Step 1: Failing node test in test/hdr_ab.test.mjs:

import { phaseCommand } from '../lib/hdr_ab.mjs';
test('alpha toggle sets the HDR alpha exponent instead of a graphics effect', () => {
assert.deepEqual(phaseCommand('alpha', true, { gamma: 2.4 }),
{ kind: 'set_tunables', tunables: { 'ColorProfileHdr.ALPHA_GAMMA': 2.4 } });
assert.deepEqual(phaseCommand('alpha', false, { gamma: 2.4 }),
{ kind: 'set_tunables', tunables: { 'ColorProfileHdr.ALPHA_GAMMA': 1.0 } });
assert.deepEqual(phaseCommand('hdr_output', true), { kind: 'graphics', effect: 'hdr_output', on: true });
});

(match the file’s existing import test from 'node:test' / assert style). Run cd tools/console_mcp && npm test: FAIL.

  • Step 2: Implement in lib/hdr_ab.mjs:
// One phase's console command. 'alpha' A/Bs the HDR alpha remap (ColorProfileHdr.ALPHA_GAMMA:
// 1.0 = off, the washed-out look) through set_tunables; everything else is a graphics effect.
export function phaseCommand(toggle, on, { gamma = 2.2 } = {}) {
if (toggle === 'alpha') return { kind: 'set_tunables', tunables: { 'ColorProfileHdr.ALPHA_GAMMA': on ? gamma : 1.0 } };
return { kind: 'graphics', effect: toggle, on };
}

In hdr_ab.mjs: const gamma = Number(opt('gamma', 2.2));; the phase loop and restore() send phaseCommand(toggle, ph.on, { gamma }) / phaseCommand(toggle, true, { gamma }) (alpha restore = the remap ON at gamma; it is live-only, a relaunch resets to the code seed); for toggle === 'alpha' skip the flagOf status confirmation and print (alpha: trust the on-device "Console: ..." note); preflight skips the gfx: flag check for alpha but keeps the run/pause checks and adds if (toggle === 'alpha' && !status.hdr?.enabled) p.push('HDR output is not engaged: the alpha remap only acts on the HDR canvas'). Default grade for alpha = 'seed' (no grade change). Update the usage comment. Run npm test: PASS.

  • Step 3: Measure (controller may run this; Mac windowed):
Terminal window
O=<scratch>/ablate-after; mkdir -p $O
CS_OUT=$O CS_PROFILE=ablate perl -e 'alarm 600; exec @ARGV' godot --path . --rendering-method mobile res://tools/cs_capture/cs_capture.tscn > $O/log.txt 2>&1
git checkout -- project.godot audio/bus_layout.tres platform/tvos/project.godot
grep -E 'BASE|arena_background|zone_renderer|archetype_renderer|enemy_aura_look|hud.gd' $O/log.txt

Baseline (before, 2026-10-10): HDR BASE p75 0.01984 vs SDR 0.00091; p75 HDR/SDR arena_background 0.01810/0.00091, zone_renderer 0.01572/0.00091, archetype_renderer 0.00347/0.00025, enemy_aura_look 0.00056/0.00014, hud 0.00340/0.00025. Acceptance: each of the four targeted layers’ HDR p75 ≤ 1.5x its SDR p75. If one misses, ablate within it (which child/shader still lifts) and report before adding scope; do NOT tune γ above 3.0 to force it.

  • Step 4: Docs — replace the last sentence of the rendering doc § (“the fix direction is … (plan pending)”) with the shipped mechanism: ALPHA_GAMMA per profile → hdr_alpha_gamma → hdr_alpha.gdshaderinc as the last COLOR.a write; additive_mat.tres is a ShaderMaterial; the covered shader list; the before/after ablate numbers; out-of-scope paths (HUD StyleBoxes, plain draw_* on the default material, HeroLights) and the rule: a new translucent shader on the canvas includes hdr_alpha and applies it last (pinned by tests/test_hdr_alpha.gd’s list).
  • Step 5: Gate PASS; commit — feat(hdr): alpha A/B preset in hdr_ab, ablate after-numbers, rendering doc

Task 5 (controller + Chris, not a subagent): device verification

Section titled “Task 5 (controller + Chris, not a subagent): device verification”
  • Review: bh-reviewer on the branch diff vs the pre-plan tip 50c0b4c3 (MERGE / DO NOT MERGE).
  • Bump + Dev install on the ATV from the worktree (bh-worktree-device-install); ListAgents first (the ATV is shared).
  • A/B with Chris in a real run: node tools/console_mcp/hdr_ab.mjs atv --toggle alpha --gamma 2.2 --hold 20 (OFF = 1.0 vs ON = 2.2). If Chris wants it stronger or softer, repeat with --gamma 1.8 / 2.4. Record his verdict and γ.
  • Perf ABBA on the ATV with the remap ON vs OFF (skill bh-console-live-ab): flag > 0.5 ms render or ≥ 2 fps.
  • Fresh-install stall check (bh-fresh-install-stall-check): a shared material changed type.
  • Persist the chosen γ as the ColorProfileHdr.ALPHA_GAMMA seed (update HDR_SEEDS in tests/test_color_profiles.gd and the docs.d desc in the same commit); remote-config patch only with Chris’s OK.
  • Re-measure the HUD: if it is still the top lift, propose the follow-up (StyleBox/draw path) to Chris; do not build it in this plan.
  • Decisions (Chris, 2026-10-10): coverage = “Measured worst first” (not everything, not shaders-only); approach A (global + shared include, additive_mat becomes a ShaderMaterial, no runtime swaps) — rejected B (runtime material swap: 53-user registry, the swap pattern caused two step-2 bugs) and post-blend correction (impossible). After presenting the spec, Chris said “Go ahead” (= approved spec + plan writing). The A/B is the ColorProfileHdr.ALPHA_GAMMA tunable 1.0↔2.2 via console, NOT a new Debug Settings row (stated to Chris; he did not object).
  • Accepted edge: the console color_profile hdr dev command can force the HDR profile on an SDR canvas; γ 2.2 then darkens faint layers there. Dev-only path, accepted; do not special-case it.
  • Authorized: code on hdr-colour-space, pushes of that branch. Needs Chris’s same-day OK: device installs/bumps (check ListAgents first; ATV shared), any remote-config patch, merge to main.
  • Done outside the plan: spec committed 50c0b4c3. Baseline ablate numbers are in Task 4 Step 3 (Mac, 2026-10-10, headroom 4.93).
  • Gotchas hit while planning: cs_capture rewrites project.godot, audio/bus_layout.tres, platform/tvos/project.godot; git checkout -- them after every run (but keep Task 1’s intended [shader_globals] edits — commit them first). In a zsh one-liner, cd into the worktree can reset back to the main checkout; use absolute paths.
  • Open for Chris after Task 5: γ verdict; whether the HUD (StyleBox, 14x) gets a follow-up; then the queued P3 wide-gamut work, the fresh-install stall check and the merge of hdr-colour-space (memory bullet-heaven-hdr-output).
  • Next action: execute Task 1 subagent-driven (bh-implementer, model opus, own worktree off hdr-colour-space tip), per bh-sdd-concurrent + sdd-worktree-leak-guard.