diff --git a/crates/algo/src/segment/sky.rs b/crates/algo/src/segment/sky.rs
--- a/crates/algo/src/segment/sky.rs
+++ b/crates/algo/src/segment/sky.rs
@@ -3,8 +3,9 @@
 //! 1. At a reduced working resolution every pixel gets a *sky likelihood*: a colour prior
 //!    (blue and bright, or bright and unsaturated for overcast / cloud, or a bright warm glow
 //!    for sunsets) times a smoothness term (sky has little gradient energy).
-//! 2. Seeds are likely-sky pixels in the top rows; the sky region grows from them through
-//!    4-connected neighbours that stay likely-sky and change colour gradually.
+//! 2. Seeds are likely-sky pixels in the top rows, falling back to substantial high-confidence
+//!    components in the upper half when the top is obstructed. The sky region grows from them
+//!    through 4-connected neighbours that stay likely-sky and change colour gradually.
 //! 3. Sky seen through gaps (between branches) is not connected to the top: likely-sky pixels
 //!    that fit a colour model (GMM) of the grown sky are added too. Small holes are filled.
 //! 4. The binary working-resolution mask is upsampled and refined at full resolution with a
@@ -30,22 +31,31 @@ pub struct SkyParams {
 }
 
 impl Default for SkyParams {
+    /// Default parameters (threshold 50, softness 50).
     fn default() -> Self {
         Self { threshold: 50.0, softness: 50.0 }
     }
 }
 
+/// Hermite interpolation between `e0` and `e1` with cubic smoothing.
 #[inline]
 fn smooth(e0: f32, e1: f32, x: f32) -> f32 {
     let t = ((x - e0) / (e1 - e0)).clamp(0.0, 1.0);
     t * t * (3.0 - 2.0 * t)
 }
 
+/// Rec. 601 perceptual luminance of an RGB triple.
 #[inline]
 fn luma(p: [f32; 3]) -> f32 {
     0.299 * p[0] + 0.587 * p[1] + 0.114 * p[2]
 }
 
+/// Euclidean distance between two RGB colours.
+#[inline]
+fn rgb_dist(a: [f32; 3], b: [f32; 3]) -> f32 {
+    ((a[0] - b[0]).powi(2) + (a[1] - b[1]).powi(2) + (a[2] - b[2]).powi(2)).sqrt()
+}
+
 /// Colour prior: how sky-like a colour is on its own (0–1).
 pub fn colour_prior(p: [f32; 3]) -> f32 {
     let [r, g, b] = p;
@@ -79,7 +89,7 @@ pub fn likelihood(img: &RgbImage) -> Vec<f32> {
     img.px.iter().zip(&tex).map(|(p, t)| colour_prior(*p) * (1.0 - smooth(0.015, 0.07, *t))).collect()
 }
 
-/// Binary sky mask at working resolution (`None` when no sky touches the top of the image).
+/// Binary sky mask at working resolution (`None` when no plausible sky region is found).
 pub fn sky_mask_low(img: &RgbImage, threshold: f32) -> Option<Vec<bool>> {
     let (w, h) = (img.w, img.h);
     if w < 2 || h < 2 {
@@ -97,11 +107,22 @@ pub fn sky_mask_low(img: &RgbImage, threshold: f32) -> Option<Vec<bool>> {
             stack.push(i);
         }
     }
+    let max_step = 0.12f32;
     if stack.len() * 20 < top * w {
-        return None; // less than 5 % of the top edge looks like sky
+        // An overhang can hide the entire top band. Discard the sparse top seeds before
+        // looking for more certain, connected sky patches below it.
+        mask.fill(false);
+        stack = obstructed_sky_seeds(img, &like, t + 0.1, max_step);
+        if stack.is_empty() {
+            return None;
+        }
+        for &i in &stack {
+            if let Some(m) = mask.get_mut(i) {
+                *m = true;
+            }
+        }
     }
     // Region growing with a gradual-change constraint.
-    let max_step = 0.12f32;
     while let Some(i) = stack.pop() {
         let (x, y) = (i % w, i / w);
         let n = [(x > 0).then(|| i - 1), (x + 1 < w).then(|| i + 1), (y > 0).then(|| i - w), (y + 1 < h).then(|| i + w)];
@@ -110,8 +131,7 @@ pub fn sky_mask_low(img: &RgbImage, threshold: f32) -> Option<Vec<bool>> {
                 continue;
             }
             let (a, b) = (img.px[i], img.px[j]);
-            let d = ((a[0] - b[0]).powi(2) + (a[1] - b[1]).powi(2) + (a[2] - b[2]).powi(2)).sqrt();
-            if d < max_step {
+            if rgb_dist(a, b) < max_step {
                 mask[j] = true;
                 stack.push(j);
             }
@@ -138,6 +158,56 @@ pub fn sky_mask_low(img: &RgbImage, threshold: f32) -> Option<Vec<bool>> {
     mask.iter().any(|v| *v).then_some(mask)
 }
 
+/// Without border evidence, require a connected patch of at least 0.5% of the image (and
+/// 16 pixels). Searching only the upper half avoids using water or blue ground as seeds;
+/// counting each component separately keeps scattered bright specks from passing the gate.
+/// Adjacent pixels must satisfy the same gradual colour constraint (`max_step`) as region growing.
+fn obstructed_sky_seeds(img: &RgbImage, like: &[f32], threshold: f32, max_step: f32) -> Vec<usize> {
+    let (w, h) = (img.w, img.h);
+    let Some(area) = w.checked_mul(h) else { return Vec::new() };
+    let Some(upper) = w.checked_mul(h.div_ceil(2)) else { return Vec::new() };
+    if img.px.len() < upper {
+        return Vec::new();
+    }
+    let Some(like) = like.get(..upper) else { return Vec::new() };
+    let minimum = area.div_ceil(200).max(16);
+    let mut seen = vec![false; upper];
+    let mut seeds = Vec::new();
+    let mut component = Vec::new();
+    for (start, &score) in like.iter().enumerate() {
+        if score <= threshold || seen.get(start).copied().unwrap_or(true) {
+            continue;
+        }
+        component.clear();
+        component.push(start);
+        if let Some(s) = seen.get_mut(start) {
+            *s = true;
+        }
+        let mut cursor = 0;
+        while let Some(&i) = component.get(cursor) {
+            cursor += 1;
+            let x = i % w;
+            let neighbours = [(x > 0).then(|| i - 1), (x + 1 < w).then(|| i + 1), i.checked_sub(w), i.checked_add(w).filter(|j| *j < upper)];
+            for j in neighbours.into_iter().flatten() {
+                if like.get(j).is_some_and(|v| *v > threshold)
+                    && let Some(s) = seen.get_mut(j)
+                    && !*s
+                {
+                    let (a, b) = (img.px[i], img.px[j]);
+                    if rgb_dist(a, b) < max_step {
+                        *s = true;
+                        component.push(j);
+                    }
+                }
+            }
+        }
+        if component.len() >= minimum {
+            seeds.extend_from_slice(&component);
+        }
+    }
+    seeds
+}
+
 /// A neutral region that also covers most of the bottom rows is a studio or product backdrop,
 /// not an overcast sky (which never reaches the bottom of a photo); blue sky is never one.
 fn is_backdrop(img: &RgbImage, mask: &[bool], rows: usize) -> bool {
@@ -291,6 +361,89 @@ mod tests {
         assert!(r.at(30, 10) > 0.9 && r.at(30, 50) < 0.1);
     }
 
+    #[test]
+    fn finds_obstructed_blue_and_overcast_sky_in_disconnected_openings() {
+        for sky in [[0.35, 0.6, 0.95], [0.85, 0.86, 0.88]] {
+            // A dark arch with two openings: neither sky component touches an image edge.
+            let img =
+                RgbImage::from_fn(
+                    160,
+                    100,
+                    |x, y| {
+                        if (15..65).contains(&y) && ((15..65).contains(&x) || (95..145).contains(&x)) { sky } else { [0.12, 0.2, 0.1] }
+                    },
+                );
+            for threshold in [0.0, 50.0, 100.0] {
+                let p = SkyParams { threshold, ..SkyParams::default() };
+                let r = select_sky(&ImageSampler { img: &img, origin: (0, 0) }, Rect::new(0, 0, 160, 100), p).expect("sky beneath arch");
+                assert!(r.at(40, 30) > 0.9 && r.at(120, 30) > 0.9, "both disconnected openings: {sky:?}, {threshold}");
+                assert!(r.at(40, 55) > 0.9, "growth beyond the upper-half seed search");
+                assert!(r.at(40, 5) < 0.1, "overhead obstruction");
+                assert!(r.at(80, 30) < 0.1, "arch pillar");
+                assert!(r.at(40, 85) < 0.1, "ground");
+            }
+        }
+    }
+
+    #[test]
+    fn obstructed_fallback_rejects_small_patches_and_lower_half_objects() {
+        for colour in [[0.35, 0.6, 0.95], [0.9, 0.9, 0.92]] {
+            let img = RgbImage::from_fn(160, 100, |x, y| {
+                if ((20..26).contains(&x) && (20..26).contains(&y)) || ((20..140).contains(&x) && (65..95).contains(&y)) { colour } else { [0.12, 0.2, 0.1] }
+            });
+            assert!(sky_mask_low(&img, 50.0).is_none(), "small upper patch and large lower object: {colour:?}");
+        }
+    }
+
+    #[test]
+    fn obstructed_neutral_backdrop_is_still_rejected() {
+        let img = RgbImage::from_fn(160, 100, |_, y| if y < 12 { [0.12, 0.2, 0.1] } else { [0.95, 0.95, 0.94] });
+        assert!(sky_mask_low(&img, 50.0).is_none());
+    }
+
+    #[test]
+    fn fallback_requires_individually_large_four_connected_components() {
+        let (w, h) = (80, 80);
+        let img = RgbImage { w, h, px: vec![[0.35, 0.6, 0.95]; w * h] };
+        // Enough total likely pixels to pass the area gate, but no large component.
+        let mut like: Vec<f32> = (0..w * h).map(|i| if i % w % 4 == 0 && i / w % 4 == 0 { 1.0 } else { 0.0 }).collect();
+        assert!(obstructed_sky_seeds(&img, &like, 0.5, 0.12).is_empty());
+        // Adjacent row ends must not join across the horizontal image boundary.
+        like.fill(0.0);
+        for y in 10..20 {
+            for x in 0..2 {
+                like[y * w + x] = 1.0;
+                like[(y - 1) * w + w - 1 - x] = 1.0;
+            }
+        }
+        assert!(obstructed_sky_seeds(&img, &like, 0.5, 0.12).is_empty());
+    }
+
+    #[test]
+    fn obstructed_fallback_excludes_attached_differently_coloured_patch() {
+        let (w, h) = (160, 100);
+        // Minimum qualifying component size: area.div_ceil(200).max(16) = 16000 / 200 = 80.
+        // Sky component is 40x40 = 1600 pixels in rows 15..55, cols 20..60 (qualifies).
+        // Attached differently coloured patch is 2x5 = 10 pixels in rows 20..25, cols 60..62 (< 80 min).
+        // Both patches have high likelihood, but their colour distance exceeds max_step (0.12).
+        let img = RgbImage::from_fn(w, h, |x, y| {
+            if (15..55).contains(&y) && (20..60).contains(&x) {
+                [0.35, 0.6, 0.95]
+            } else if (20..25).contains(&y) && (60..62).contains(&x) {
+                [0.85, 0.86, 0.88]
+            } else {
+                [0.12, 0.2, 0.1]
+            }
+        });
+        let mask = sky_mask_low(&img, 50.0).expect("sky mask");
+        assert!(mask[30 * w + 40], "qualifying blue sky must be in mask");
+        for y in 20..25 {
+            for x in 60..62 {
+                assert!(!mask[y * w + x], "attached patch at ({x}, {y}) must be excluded from mask");
+            }
+        }
+    }
+
     /// #4634: a near-white studio backdrop around a product is not an overcast sky, but blue sky
     /// reaching the bottom (a photo taken upward) still is.
     #[test]
diff --git a/docs/gaps.md b/docs/gaps.md
--- a/docs/gaps.md
+++ b/docs/gaps.md
@@ -1,6 +1,6 @@
 # Where PhotoCraft falls short of Photoshop
 
-> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-26 · **Change:** minor (cropped selection morphology and command mask conversion performance evidence added; G9: 12 of 178 preferences do nothing, as the scorecard prefs audit counts them; G6: Art History Brush landed as partial, TOOL-213-20, #1610, so no toolbar tool is missing; G4: five hard-round built-in presets use 5% spacing to remove stacked-tip outlines and reduce pressure-opacity bands, #8842; G9: Crop tool canvas menu, #6561; G2: Content-Aware Scale seam carving 1.65–3.6× faster with unchanged output, P28 row 3.3 → 1.6 s on a 4-core VM, #5236; G9: UI scale presets done, 105–120% steps, #3222; G14: lossy DNG, raw sidecars, Camera Raw Defaults live, Calibration and Auto, CR3 assessed as not clean-room feasible; G8: PSD type on a path opens on its path and saves back into the file's `Txt2`, #7962; G11: a recorded Save As imports with its format and file (`file.saveAs`, `file.saveACopy` for As a Copy) instead of as a plain Save that wrote over the played file, #7102; folder destinations stop playback until #5430; adjustment clipping stays visible in compact Properties, #5231; G9: Color panel modes, ramp and copy commands, the same in every theme, UI-217-17, #6000; G17: Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; G10: `.asl` style libraries landed, #1051; G8: area type (TYPE-218-10); G1: smart objects keep Photoshop's Cylinder warp, #4112; G8: paragraph direction buttons in the Paragraph panel and options bar, TYPE-218-2 partial; G1: 32-bit Hue/Saturation and Colorize as Photoshop does them, Photoshop-oracle floor 190/258, #5781; G11: compound layer properties export as separate Photoshop Set events, rename last, #8304; G11: Batch and droplets take the result at the action's Save step, so actions ending in Save As and Close work; G11: `.atn` steps that switch to another open document import, play and save back, #7103; G14: the Nikon D4 white level follows the sample depth, so 12-bit D4 NEFs no longer open 2.6 stops dark, #5978; G14: a Nikon NEF's Adobe RGB preview is read as Adobe RGB (maker-note ColorSpace 0x001E), #5987; Apply Layer Comp action mapping, #7101; G10: JPEG Options dialog landed, FILE-215-19 partial (no Matte, progressive Scans or size preview); G10: Cineon write; G10: DPX read and write, #1049, Cineon and Amiga IFF read; Classical Object Finder improvement; learned segmentation remains open; G4: named, stateful section locks and visible keyboard focus in Brush Settings; G4: independent Brush Pose tilt-axis overrides, #3825 partial; G4: Transfer Mixer-only controls, #3825 partial; G9: Preferences › File Handling › Save in Background takes effect, #6207, 24 of 169 preferences do nothing; G7: Content-Aware Move previews every selection the command takes, coarse then exact, TOOL-213-4 done, #6680; G4: Pattern Stamp and Background Eraser draw live, TOOL-213-7; G9: Animated Zoom pref read: holding the Zoom tool zooms continuously, #6210, prefs that do nothing 25 of 166; G2: a cancelled 24 MP Gaussian Blur job stops in at most 44 ms, P25 under its 200 ms budget in local runs, baseline not re-run, #6205; G1: generated large-file fixtures, a 4.38 GB PSB opens on Windows through io, FILE-216-2 done, #5107; G9: fill and adjustment layers copy and paste whole, #2344; G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bins it, psd-tools oracle floor 241/309; G1: Gradient Map driven by the W3C luminosity, Photoshop-oracle floor 147/258; G7: Field Blur's on-canvas pins, #3373; G4: Hue Jitter amount track, #3825 partial; G4: minimum field interaction, #3825 partial; G1: CMYK Invert, Posterize and Threshold on the inks, 16-bit Lab Invert; Photoshop-oracle floor 145/258; G11: `.atn` import maps 112 events: Select and Mask, Filter Gallery Spatter, Ripple, Crystallize, Pattern Fill layers, mask targeting, Step Backward, nudges in points, Bitmap mode; G5: Free Transform H/V skew fields; G9: toolbar tool shortcut editing; refreshed against main: G2, G5, G7, G9, G10, G13, G14, G17 items that landed; G10: DPX read and write, #1049; G4: checkbox-only Brush Settings rows; G11: Load/Save Actions `.atn` landed, AUTO-219-2 partial; G5: hold-a-key spring-loaded tools landed, #2672; G1: #2465 fixed; stale missing-tool rows corrected: Color Replacement, Red Eye and Add/Delete Anchor Point are live tools, so only Art History Brush is missing; no estimate changed; G10: Amiga IFF write; G10: PSD spot channels in Photoshop's polarity, earlier PhotoCraft PSDs keep their ink, #7415 split; G10: TIFF alpha and spot channels written and read as extra samples, FILE-215-7 done, FILE-215-17's TIFF part, #7415) · **Target:** Adobe Photoshop 2026
+> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-26 · **Change:** minor (G15: classical Select › Sky can seed substantial high-confidence components beneath an obstructed top band; learned segmentation remains open; cropped selection morphology and command mask conversion performance evidence added; G9: 12 of 178 preferences do nothing, as the scorecard prefs audit counts them; G6: Art History Brush landed as partial, TOOL-213-20, #1610, so no toolbar tool is missing; G4: five hard-round built-in presets use 5% spacing to remove stacked-tip outlines and reduce pressure-opacity bands, #8842; G9: Crop tool canvas menu, #6561; G2: Content-Aware Scale seam carving 1.65–3.6× faster with unchanged output, P28 row 3.3 → 1.6 s on a 4-core VM, #5236; G9: UI scale presets done, 105–120% steps, #3222; G14: lossy DNG, raw sidecars, Camera Raw Defaults live, Calibration and Auto, CR3 assessed as not clean-room feasible; G8: PSD type on a path opens on its path and saves back into the file's `Txt2`, #7962; G11: a recorded Save As imports with its format and file (`file.saveAs`, `file.saveACopy` for As a Copy) instead of as a plain Save that wrote over the played file, #7102; folder destinations stop playback until #5430; adjustment clipping stays visible in compact Properties, #5231; G9: Color panel modes, ramp and copy commands, the same in every theme, UI-217-17, #6000; G17: Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; G10: `.asl` style libraries landed, #1051; G8: area type (TYPE-218-10); G1: smart objects keep Photoshop's Cylinder warp, #4112; G8: paragraph direction buttons in the Paragraph panel and options bar, TYPE-218-2 partial; G1: 32-bit Hue/Saturation and Colorize as Photoshop does them, Photoshop-oracle floor 190/258, #5781; G11: compound layer properties export as separate Photoshop Set events, rename last, #8304; G11: Batch and droplets take the result at the action's Save step, so actions ending in Save As and Close work; G11: `.atn` steps that switch to another open document import, play and save back, #7103; G14: the Nikon D4 white level follows the sample depth, so 12-bit D4 NEFs no longer open 2.6 stops dark, #5978; G14: a Nikon NEF's Adobe RGB preview is read as Adobe RGB (maker-note ColorSpace 0x001E), #5987; Apply Layer Comp action mapping, #7101; G10: JPEG Options dialog landed, FILE-215-19 partial (no Matte, progressive Scans or size preview); G10: Cineon write; G10: DPX read and write, #1049, Cineon and Amiga IFF read; Classical Object Finder improvement; learned segmentation remains open; G4: named, stateful section locks and visible keyboard focus in Brush Settings; G4: independent Brush Pose tilt-axis overrides, #3825 partial; G4: Transfer Mixer-only controls, #3825 partial; G9: Preferences › File Handling › Save in Background takes effect, #6207, 24 of 169 preferences do nothing; G7: Content-Aware Move previews every selection the command takes, coarse then exact, TOOL-213-4 done, #6680; G4: Pattern Stamp and Background Eraser draw live, TOOL-213-7; G9: Animated Zoom pref read: holding the Zoom tool zooms continuously, #6210, prefs that do nothing 25 of 166; G2: a cancelled 24 MP Gaussian Blur job stops in at most 44 ms, P25 under its 200 ms budget in local runs, baseline not re-run, #6205; G1: generated large-file fixtures, a 4.38 GB PSB opens on Windows through io, FILE-216-2 done, #5107; G9: fill and adjustment layers copy and paste whole, #2344; G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bins it, psd-tools oracle floor 241/309; G1: Gradient Map driven by the W3C luminosity, Photoshop-oracle floor 147/258; G7: Field Blur's on-canvas pins, #3373; G4: Hue Jitter amount track, #3825 partial; G4: minimum field interaction, #3825 partial; G1: CMYK Invert, Posterize and Threshold on the inks, 16-bit Lab Invert; Photoshop-oracle floor 145/258; G11: `.atn` import maps 112 events: Select and Mask, Filter Gallery Spatter, Ripple, Crystallize, Pattern Fill layers, mask targeting, Step Backward, nudges in points, Bitmap mode; G5: Free Transform H/V skew fields; G9: toolbar tool shortcut editing; refreshed against main: G2, G5, G7, G9, G10, G13, G14, G17 items that landed; G10: DPX read and write, #1049; G4: checkbox-only Brush Settings rows; G11: Load/Save Actions `.atn` landed, AUTO-219-2 partial; G5: hold-a-key spring-loaded tools landed, #2672; G1: #2465 fixed; stale missing-tool rows corrected: Color Replacement, Red Eye and Add/Delete Anchor Point are live tools, so only Art History Brush is missing; no estimate changed; G10: Amiga IFF write; G10: PSD spot channels in Photoshop's polarity, earlier PhotoCraft PSDs keep their ink, #7415 split; G10: TIFF alpha and spot channels written and read as extra samples, FILE-215-7 done, FILE-215-17's TIFF part, #7415) · **Target:** Adobe Photoshop 2026
 
 Every known shortfall against Photoshop 2026 (27.11.0), one entry each, ranked by user impact
 on the way to beta. This is the work list agents pick from: take the highest-ranked entry that
@@ -198,6 +198,7 @@ what an agent can't finish alone.
 - **Evidence:** Photoshop's `Required/UXP` ships the Neural Filters gallery and its `.kys` has
   a Neural Filters taskspace; users ask for local models (#2313, #1996, #2682).
 - **Progress (2026-10-17):** classical Object Finder no longer rejects a foreground solely for covering over 60% of the canvas (#6548); canvas-boundary coverage distinguishes it from the surrounding backdrop. This does not add semantic recognition or close #2788.
+- **Progress (2026-10-26):** classical Select › Sky falls back to connected high-confidence components in the upper half when its top seed band is obstructed. Synthetic blue and overcast skies beneath an arch are covered, including disconnected openings; small patches, lower-half objects and neutral backdrops are rejected. This remains a colour/smoothness heuristic, not semantic recognition; #2788 stays open.
 - **Estimate:** 300–600 h. **Human:** owner decision #41 (model licences, local vs remote).
 
 ### G16. Plug-in compatibility
@@ -395,6 +396,7 @@ what an agent can't finish alone.
 
 | Date | Change | Summary |
 |---|---|---|
+| 2026-10-26 | minor | G15: classical Select › Sky can seed substantial high-confidence components beneath an obstructed top band; learned segmentation remains open; percentages and estimates unchanged |
 | 2026-10-26 | minor | Expand/Contract/Border distance work, mask reads and replacement cropped to nonzero bounds; bounded distances for radii ≤5; 36 MP exact-output comparisons improve 1.54–37.82× across eight cases; percentages, estimates and scorecard budgets unchanged |
 | 2026-10-25 | minor | G9: the count of preferences that do nothing is the scorecard's again, 12 of 178 (it still said 24 of 171, from 2026-10-15); no estimate changed |
 | 2026-10-25 | minor | G6: Art History Brush landed as partial (TOOL-213-20, #1610), so no toolbar tool is missing; no percentage or estimate changed |
diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md
--- a/docs/target-app-parity.md
+++ b/docs/target-app-parity.md
@@ -1,6 +1,6 @@
 # PhotoCraft vs Adobe Photoshop: target-app parity
 
-> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-26 · **Change:** minor (cropped selection morphology and command mask conversion performance evidence added; 12 of 178 preferences do nothing, from the scorecard; the Camera Raw row names per-camera colour for non-DNG cameras as missing, not the Calibration panel, which landed 2026-10-13; Content-Aware Scale measurements added, #5236; Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; area type, TYPE-218-10 partial, Type scorecard 5 / 5 / 0; compound layer properties export as separate Photoshop Set events, #8304; JPEG Options dialog landed, FILE-215-19 partial; Print › Functions › Bleed through `file.print`; Content-Aware Move live preview for every selection size, TOOL-213-4 done, #6680; retouching evidence: Pattern Stamp and Background Eraser draw live, only the Mixer Brush is left of TOOL-213-7; fill and adjustment layers copy and paste whole, UI-217-23 partial, #2344; shape layers take Density and Feather, TOOL-214-12 done, #5846; on-canvas corner radius widgets, TOOL-214-12; `.atn` import maps 112 events; Free Transform H/V skew fields; stale rows corrected against `main` and the scorecard, estimates unchanged; Photoshop Actions `.atn` load and save; 2026-10-10: Tilt-Shift measurements added; earlier the same day: major, full re-measure against Photoshop 2026 27.11.0; merged `parity-estimate.md` and the roadmap's honest assessment; stale missing-tool rows corrected: Color Replacement and Red Eye are live toolbar tools, Frame landed; percentages unchanged; PSD spot plates in Photoshop's polarity, #7415 split; TIFF spot plates, FILE-215-17's TIFF part, #7415) · **Target:** Adobe Photoshop 2026
+> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-26 · **Change:** minor (classical Select › Sky can seed substantial high-confidence components beneath an obstructed top band; learned segmentation remains open; cropped selection morphology and command mask conversion performance evidence added; 12 of 178 preferences do nothing, from the scorecard; the Camera Raw row names per-camera colour for non-DNG cameras as missing, not the Calibration panel, which landed 2026-10-13; Content-Aware Scale measurements added, #5236; Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; area type, TYPE-218-10 partial, Type scorecard 5 / 5 / 0; compound layer properties export as separate Photoshop Set events, #8304; JPEG Options dialog landed, FILE-215-19 partial; Print › Functions › Bleed through `file.print`; Content-Aware Move live preview for every selection size, TOOL-213-4 done, #6680; retouching evidence: Pattern Stamp and Background Eraser draw live, only the Mixer Brush is left of TOOL-213-7; fill and adjustment layers copy and paste whole, UI-217-23 partial, #2344; shape layers take Density and Feather, TOOL-214-12 done, #5846; on-canvas corner radius widgets, TOOL-214-12; `.atn` import maps 112 events; Free Transform H/V skew fields; stale rows corrected against `main` and the scorecard, estimates unchanged; Photoshop Actions `.atn` load and save; 2026-10-10: Tilt-Shift measurements added; earlier the same day: major, full re-measure against Photoshop 2026 27.11.0; merged `parity-estimate.md` and the roadmap's honest assessment; stale missing-tool rows corrected: Color Replacement and Red Eye are live toolbar tools, Frame landed; percentages unchanged; PSD spot plates in Photoshop's polarity, #7415 split; TIFF spot plates, FILE-215-17's TIFF part, #7415) · **Target:** Adobe Photoshop 2026
 
 The authoritative answer to "how close is PhotoCraft to Photoshop, and how much work is left". The
 one-page summary is [`ROADMAP.md`](../ROADMAP.md); the ranked work list is [`gaps.md`](gaps.md);
@@ -168,7 +168,7 @@ parity for the area and are already contained in the dimension rows above.
 | Area | % | Hours | Notes |
 |---|---:|---:|---|
 | Layers, groups, masks, blend modes, smart objects, layer styles | 65% | 150–250 | Broad and GPU-accelerated. Open: a single pixel layer copies its pixels without its mask and styles (UI-217-23: smart object, type, shape, group, fill and adjustment layers and multi-layer selections copy and paste whole), smart-object perspective (FILE-215-6), a user contour library (FILE-215-15). Multi-layer Smart Object conversion (#2052, #2651), Stamp Visible (UI-217-22) and mask targeting by command (#2458) are done |
-| Selections, Select and Mask, channels | 55% | 120–200 | All selection tools, single row/column marquee included (#2837). Select and Mask is a dialog with Photoshop's view modes, a Refine Edge Brush and six outputs, not a workspace (TOOL-214-1), no Refine Hair (#2671); Select Subject/Sky classical, 559 ms p50 on 24 MP vs a 100 ms budget |
+| Selections, Select and Mask, channels | 55% | 120–200 | All selection tools, single row/column marquee included (#2837). Select and Mask is a dialog with Photoshop's view modes, a Refine Edge Brush and six outputs, not a workspace (TOOL-214-1), no Refine Hair (#2671); Select Subject/Sky classical; Sky has an upper-half component fallback for obstructed top bands (2026-10-26), still without semantic recognition. Select Subject: 559 ms p50 on 24 MP vs a 100 ms budget |
 | Painting and brush engine | 55% | 150–250 | Every Brush Settings section exists; feel is the gap: lag on big brushes, pressure jumps, smoothing and edge quality reports ([brush-parity.md](brush-parity.md)) |
 | Retouching (healing, clone, patch, remove, content-aware) | 50% | 100–180 | Remove tool non-generative; Content-Aware Fill has no workspace (TOOL-214-15); no live stroke preview for the Mixer Brush yet (TOOL-213-7) |
 | Transform, warp, puppet, perspective, liquify | 55% | 100–180 | Free Transform modifiers right, with a right-click transform menu (TOOL-214-5) and H/V skew fields; Puppet Warp mesh follows the object outline (TOOL-214-6); Liquify called "useless" by a user (#2606) |
@@ -580,6 +580,7 @@ See [method, raw measurements and reproduction](five-algorithm-performance.md).
 
 | Date | Change | Summary |
 |---|---|---|
+| 2026-10-26 | minor | Selections: classical Select › Sky can seed substantial high-confidence components beneath an obstructed top band; learned segmentation remains open; percentages and estimates unchanged |
 | 2026-10-26 | minor | Expand/Contract/Border distance work, mask reads and replacement cropped to nonzero bounds; bounded distances for radii ≤5; 36 MP exact-output comparisons improve 1.54–37.82× across eight cases; percentages, estimates and scorecard budgets unchanged |
 | 2026-10-25 | minor | UI / UX and Workspace rows: 12 of 178 preferences do nothing, the scorecard's count. Camera Raw row: the Calibration panel landed on 2026-10-13 (#5128); what is missing is per-camera colour for non-DNG cameras ([gaps.md](gaps.md) G14). Percentages and estimates unchanged |
 | 2026-10-23 | minor | Colour management and modes: PSD spot plates are stored as Photoshop stores them (ink 0 = solid), and PSDs from earlier PhotoCraft versions keep their ink (#7415 split, part 4); estimates unchanged |
