Expand failed regional building contexts
GeoIntel release gates / Compile, test, contracts and builds (push) Canceled after 0s
GeoIntel release gates / Python and npm vulnerability policy (push) Canceled after 0s
GeoIntel release gates / GIS image, SBOM and container scan (push) Canceled after 0s

This commit is contained in:
Jens
2026-07-29 17:14:17 +02:00
parent 2fd9da9e16
commit 08d406ce7d
4 changed files with 62 additions and 0 deletions
@@ -32,3 +32,19 @@ def test_portfolio_bbox_is_metric_sized() -> None:
bounds = to_metric.transform_bounds(bbox["min_x"], bbox["min_y"], bbox["max_x"], bbox["max_y"]) bounds = to_metric.transform_bounds(bbox["min_x"], bbox["min_y"], bbox["max_x"], bbox["max_y"])
assert 255 <= bounds[2] - bounds[0] <= 258 assert 255 <= bounds[2] - bounds[0] <= 258
assert 255 <= bounds[3] - bounds[1] <= 258 assert 255 <= bounds[3] - bounds[1] <= 258
def test_failure_driven_expansion_is_train_only_and_context_complete() -> None:
additions = [aoi for aoi in module.AOIS if aoi.slug.endswith("-v31") or "-v31-bg" in aoi.slug]
assert len(additions) == 18
assert {aoi.split for aoi in additions} == {"train"}
assert {aoi.region for aoi in additions} == {"flanders", "wallonia"}
contexts = {(aoi.region, aoi.context) for aoi in additions}
assert {
("flanders", "industrial"),
("flanders", "ribbon-development"),
("flanders", "coastal-urban"),
("wallonia", "dense-urban"),
("wallonia", "rural-town"),
("wallonia", "regional-architecture"),
} <= contexts
+9
View File
@@ -67,6 +67,15 @@ contexts. Its remaining known gaps are:
The active production model remains unchanged while any gate fails. The active production model remains unchanged while any gate fails.
The v31 expansion adds eighteen independent train-only AOIs after the v30
rotated-holdout calibration isolated the remaining domain gaps. Nine Flemish
AOIs cover industrial roofs, ribbon development and coastal urban fabric. Nine
Walloon AOIs add dense urban, rural-town, regional-architecture and difficult
industrial/rail/quarry negatives. Existing validation, calibration, test and
background-test AOIs remain frozen. The provisioner can load a short-lived
operator session from a mode-0600 token file, allowing governed acquisition on
an authenticated runtime without exposing credentials in process arguments.
## Reproducible evidence ## Reproducible evidence
- corpus assembler: `scripts/assemble_belgium_building_corpus.py`; - corpus assembler: `scripts/assemble_belgium_building_corpus.py`;
+5
View File
@@ -6,6 +6,11 @@
per-AOI calibration evidence. Protected calibration, test, background-test per-AOI calibration evidence. Protected calibration, test, background-test
and validation tiles remain excluded; manifests now record targeted contexts and validation tiles remain excluded; manifests now record targeted contexts
and their stronger repeat factors for reproducible follow-up iterations. and their stronger repeat factors for reproducible follow-up iterations.
- Prepared the next immutable corpus expansion with eighteen spatially
independent train-only AOIs: nine Flemish industrial/ribbon/coastal samples
and nine Walloon dense/rural/architecture or difficult-negative samples.
Added mode-0600 session-token-file support to the official provisioner so
authenticated Tower acquisition does not expose session material in argv.
## 2026-07-27 - Guest demo and product professionalization ## 2026-07-27 - Guest demo and product professionalization
@@ -81,6 +81,17 @@ AOIS = (
Aoi("brasschaat-heath-train-v12-bg", "flanders", "heath-hard-negative", "train", 4.525, 51.350, "background_candidate"), Aoi("brasschaat-heath-train-v12-bg", "flanders", "heath-hard-negative", "train", 4.525, 51.350, "background_candidate"),
Aoi("limburg-pine-train-v12-bg", "flanders", "forest-hard-negative", "train", 5.680, 51.020, "background_candidate"), Aoi("limburg-pine-train-v12-bg", "flanders", "forest-hard-negative", "train", 5.680, 51.020, "background_candidate"),
Aoi("westhoek-field-train-v12-bg", "flanders", "farmland-hard-negative", "train", 2.720, 50.990, "background_candidate"), Aoi("westhoek-field-train-v12-bg", "flanders", "farmland-hard-negative", "train", 2.720, 50.990, "background_candidate"),
# v31 failure-driven corpus expansion: independent examples matching the
# protected Genk/Lokeren/Ostend calibration failure contexts.
Aoi("tessenderlo-industry-train-v31", "flanders", "industrial", "train", 5.087, 51.065),
Aoi("maasmechelen-industry-train-v31", "flanders", "industrial", "train", 5.691, 50.963),
Aoi("izegem-industry-train-v31", "flanders", "industrial", "train", 3.209, 50.920),
Aoi("zele-ribbon-train-v31", "flanders", "ribbon-development", "train", 4.040, 51.066),
Aoi("putte-ribbon-train-v31", "flanders", "ribbon-development", "train", 4.632, 51.053),
Aoi("overpelt-ribbon-train-v31", "flanders", "ribbon-development", "train", 5.424, 51.211),
Aoi("nieuwpoort-coastal-train-v31", "flanders", "coastal-urban", "train", 2.749, 51.130),
Aoi("knokke-coastal-train-v31", "flanders", "coastal-urban", "train", 3.289, 51.340),
Aoi("bredene-coastal-train-v31", "flanders", "coastal-urban", "train", 2.976, 51.235),
Aoi("bruges-val", "flanders", "historic-urban", "val", 3.224, 51.209), Aoi("bruges-val", "flanders", "historic-urban", "val", 3.224, 51.209),
Aoi("turnhout-val", "flanders", "suburban", "val", 4.944, 51.322), Aoi("turnhout-val", "flanders", "suburban", "val", 4.944, 51.322),
Aoi("hasselt-cal", "flanders", "suburban", "calibration", 5.340, 50.930), Aoi("hasselt-cal", "flanders", "suburban", "calibration", 5.340, 50.930),
@@ -119,6 +130,17 @@ AOIS = (
Aoi("peruwelz-train-v12", "wallonia", "mixed-urban", "train", 3.591, 50.509), Aoi("peruwelz-train-v12", "wallonia", "mixed-urban", "train", 3.591, 50.509),
Aoi("ardenne-clearing-train-v12-bg", "wallonia", "forest-hard-negative", "train", 5.460, 50.080, "background_candidate"), Aoi("ardenne-clearing-train-v12-bg", "wallonia", "forest-hard-negative", "train", 5.460, 50.080, "background_candidate"),
Aoi("condroz-open-train-v12-bg", "wallonia", "farmland-hard-negative", "train", 5.020, 50.390, "background_candidate"), Aoi("condroz-open-train-v12-bg", "wallonia", "farmland-hard-negative", "train", 5.020, 50.390, "background_candidate"),
# v31 precision correction: independent positives plus difficult negatives
# for the weak Walloon dense/rural/regional-architecture contexts.
Aoi("herstal-dense-train-v31", "wallonia", "dense-urban", "train", 5.630, 50.665),
Aoi("dison-dense-train-v31", "wallonia", "dense-urban", "train", 5.854, 50.612),
Aoi("gembloux-rural-train-v31", "wallonia", "rural-town", "train", 4.692, 50.561),
Aoi("soignies-rural-train-v31", "wallonia", "rural-town", "train", 4.071, 50.579),
Aoi("stavelot-architecture-train-v31", "wallonia", "regional-architecture", "train", 5.931, 50.395),
Aoi("aubel-architecture-train-v31", "wallonia", "regional-architecture", "train", 5.859, 50.704),
Aoi("liege-brownfield-train-v31-bg", "wallonia", "industrial-hard-negative", "train", 5.607, 50.624, "background_candidate"),
Aoi("charleroi-rail-train-v31-bg", "wallonia", "rail-hard-negative", "train", 4.467, 50.421, "background_candidate"),
Aoi("condroz-quarry-train-v31-bg", "wallonia", "quarry-hard-negative", "train", 5.190, 50.365, "background_candidate"),
Aoi("tournai-val", "wallonia", "historic-urban", "val", 3.389, 50.606), Aoi("tournai-val", "wallonia", "historic-urban", "val", 3.389, 50.606),
Aoi("arlon-val", "wallonia", "small-city", "val", 5.817, 49.683), Aoi("arlon-val", "wallonia", "small-city", "val", 5.817, 49.683),
Aoi("verviers-cal", "wallonia", "suburban", "calibration", 5.860, 50.590), Aoi("verviers-cal", "wallonia", "suburban", "calibration", 5.860, 50.590),
@@ -212,8 +234,18 @@ def main() -> int:
parser.add_argument("--side-m", type=float, default=256.0) parser.add_argument("--side-m", type=float, default=256.0)
parser.add_argument("--resolution-m", type=float, default=0.25) parser.add_argument("--resolution-m", type=float, default=0.25)
parser.add_argument("--force-refresh", action="store_true") parser.add_argument("--force-refresh", action="store_true")
parser.add_argument(
"--session-token-file",
type=Path,
help="Read an operator session token from a local mode-0600 file instead of exposing it on the command line.",
)
args = parser.parse_args() args = parser.parse_args()
session = requests.Session() session = requests.Session()
if args.session_token_file:
token = args.session_token_file.read_text(encoding="utf-8").strip()
if not token:
raise SystemExit("--session-token-file is empty")
session.cookies.set("geointel_session", token)
samples: list[dict[str, Any]] = [] samples: list[dict[str, Any]] = []
if args.output_spec.is_file(): if args.output_spec.is_file():
existing = json.loads(args.output_spec.read_text(encoding="utf-8-sig")) existing = json.loads(args.output_spec.read_text(encoding="utf-8-sig"))