0943e77136
Two credential-isolation gaps found in review of the previous head. 1. strip_launch_profile_env() only knows dotenv- and terminal-config-owned names, but external secret sources (vault, 1Password, ...) also write their names into the shared os.environ and are tracked in secret_source_names(). A name the LAUNCH profile's source supplied therefore still reached a routed no_agent child. Drop every non-global source-owned name from the base; the routed scope overlay that follows puts back exactly the ones that profile's OWN sources supply, since build_profile_secret_scope folds get_secret_source_values(home) in. 2. refresh_installed_secret_scope() merged the rebuild with dict.update(), so a name a source had stopped supplying -- rotated, revoked, source removed -- kept its old value for the rest of the fire. Replace the mapping contents instead: the rebuild is the profile's current truth. Regressions: a routed child sees <unset> for a launch-source name while its own source value comes through, and a refresh whose rebuild omits a name drops it. Both fail if the corresponding change is reverted. (cherry picked from commit ecd51517c4828a75acb5f458ed99aea0bc3e5e9f)