The scope-normalization sweep only fixed the read paths
(list_providers/get_provider/registry_generation) in most registries;
the write paths (register/snapshot/restore) still stored under the raw
scope string while reads resolved through hermes_home_key — so a
scoped registration was written under one key and read under another
(agent/terminal_env_registry.py test_scoped_registration_isolated
failed on both Linux and Windows CI).
- add hermes_constants.normalize_scope(scope): hermes_home_key for
non-None, None preserved for the process-global layer — one named
function instead of the expression repeated at ~20 call sites
- apply it on both sides of all nine scoped registries
(browser, terminal_env, image_gen, transcription, tts, video_gen,
web_search, secret_sources, dashboard_auth, tools.registry)
- agent/deadline: MAX_SAFE_TIMEOUT_S on win32 leaves 60s headroom under
the DWORD-ms ceiling so margin-adding consumers (human-wait +60s)
stay platform-safe; tools/approval fail-closed fallback mirrors it
- tools/approval: strip shell escapes everywhere except inside
drive-anchored paths (the Windows shell is bash, so r\m still spells
rm; only C:\... backslashes must survive deobfuscation)
- consolidate the duplicated _rmtree_force into hermes_cli/fs_utils
and repoint both callers
- hermes_cli/kanban + disk-cleanup: shlex.split(posix=False) keeps
wrapping quotes in tokens; strip them before dispatch/matching
- test gating: SIGKILL durability conformance cells are linux_only
(TerminateProcess is not SIGKILL), macOS TCC anchor symlink-tree
classes are linux_only, Linux chromium profile tests resolve the
fixture home via expanduser patch + posix-joined expecteds so they
run identically on every host