From 3d22031a12daef9dfa8391ee6f806e1ff032a6ee Mon Sep 17 00:00:00 2001 From: rob Date: Fri, 10 Jul 2026 15:17:35 +0000 Subject: [PATCH] dshackle overrides: tab guard - dshackle silently skips hot-reloading YAML containing tabs (operator gotcha); refuse to write tabbed output + audit all configs Co-Authored-By: Claude Fable 5 --- apply-dshackle-overrides.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/apply-dshackle-overrides.py b/apply-dshackle-overrides.py index 47a4111f..94fada67 100755 --- a/apply-dshackle-overrides.py +++ b/apply-dshackle-overrides.py @@ -117,12 +117,26 @@ def main(): if ov and apply(up, ov): changed = True if changed: + text = yaml.safe_dump(doc, default_flow_style=False, sort_keys=False) + # dshackle silently refuses to hot-reload configs containing TABS + # (operator gotcha 2026-07-10) - fail loudly, never write a tabbed file. + if '\t' in text: + print(f'dshackle-overrides: REFUSING to write {path} - tab in output') + continue with open(path, 'w') as f: - yaml.safe_dump(doc, f, default_flow_style=False, sort_keys=False) + f.write(text) total += 1 print(f'dshackle-overrides: rewove {path}') + # tab audit on ALL configs (even unchanged): a tabbed file silently fails + # dshackle's hot-reload, so disk and running state diverge invisibly. + for path in glob.glob(os.path.join(CONFIG_DIR, '*.yaml')): + try: + if '\t' in open(path, errors='replace').read(): + print(f'dshackle-overrides: WARNING {path} contains TABS - dshackle will SILENTLY skip reloading it') + except OSError: + pass if total: - print(f'dshackle-overrides: {total} file(s) updated (restart dshackle to activate method changes)') + print(f'dshackle-overrides: {total} file(s) rewoven (dshackle hot-reloads on the HUP that follows)') if __name__ == '__main__':