Skip to content

cockpit: /ice real Iceland DEM terrain + geo "terrain" layer chrome#89

Merged
AdaWorldAPI merged 2 commits into
mainfrom
claude/ice-iceland-dem
Jul 6, 2026
Merged

cockpit: /ice real Iceland DEM terrain + geo "terrain" layer chrome#89
AdaWorldAPI merged 2 commits into
mainfrom
claude/ice-iceland-dem

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Follow-on to the merged #88 (/ice palette + sky + aerial camera + Kurvenlineal breathing): replaces the sparse point-cloud bake with a real Iceland DEM heightfield, and fixes the anatomy-layer chrome so a map doesn't read as skeleton/body-parts.

Real DEM terrain (44a474ff)

  • Source: AWS Terrarium terrain-RGB tiles — public, keyless (SRTM stops at 60°N and OpenTopography needs a key; both fail Iceland's 63–67°N). Zoom 9, 252 tiles, decoded elev = R·256 + G + B/256 − 32768, stitched to 4608×3584 and downsampled to a 1152×896 vertex grid.
  • Mesh: 1,032,192 verts / 2,060,290 tris. Shared-vertex heightfield, per-vertex normals from the terrain gradient, equirectangular projection (matching the OSM bake), true-scale elevation (span 0..0.0067; the shader applies uExag + Kurvenlineal, so no pre-exaggeration). Sea level → y=0 → painted ocean.
  • Encoded via a new additive bso2::encode_mesh_bso2 (mirrors the exact BSO2 ver-6 Signed360 layout the viewer decodes; the OSM encode_bso2 path is untouched, all 12 geo tests pass). New baker geo/src/bin/iceland_dem.rs; DEM fetched by scripts/fetch_iceland_dem.py (keeps the geo crate HTTP-dep-free).
  • iceland_latest repointed to the new iceland_dem.helix.soa.gz (9.6 MB, ships same-origin like the OSM bake); the sparse iceland.helix.soa.gz is preserved on disk, unreferenced — nothing overwritten.
  • Screenshot-verified: solid, recognizable Iceland (Westfjords + glacier caps) rising out of the blue ocean — a real winding-flip gotcha (down-facing normals → empty scene) was caught and fixed before shipping.

Geo "terrain" chrome (79f8dce3)

BodyHelix is shared by /helix (anatomy) and the geo scenes, and the layer sidebar/buttons rendered the hardcoded anatomy LAYERS (skin/muscle/…/skeleton) regardless of scene — so the terrain showed up categorized under skeleton. Geo scenes now derive activeLayers from the layers the bake actually stamps, relabelled "terrain" (empty anatomy layers dropped); the layer id is preserved so show/hide still filters the real geometry. Anatomy scenes keep LAYERS byte-identical.

Verify

cd cockpit && npm run build clean. The DEM scene is screenshot-confirmed (solid terrain); the chrome commit is a type-checked label swap over that same confirmed render (the 1M-vert breathing scene is too heavy for the headless swiftshader GPU to re-snapshot, so the panel label is build+code-verified — noted honestly). BodyHelix.tsx history is clean (no shared-tree race: the DEM agent was frozen out of the TSX; the chrome fix is my own commit).

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for an Iceland terrain DEM workflow, including downloading, stitching, and exporting elevation data for scene generation.
    • Introduced a new terrain mesh encoding path and a new build target to generate helix-compatible assets from DEM data.
  • Bug Fixes

    • Terrain layer controls now automatically show only the layers available in geo scenes.
    • Geo scenes use a dedicated terrain label and color for a clearer, more consistent display.
  • Chores

    • Updated the Iceland manifest to point to the new DEM-based asset.

claude added 2 commits July 6, 2026 16:18
Replace the SPARSE Iceland scatter with a REAL DEM heightfield so /ice
renders solid terrain under the already-shipped height-profile palette +
Kurvenlineal breathing.

DEM source: AWS Terrarium terrain-RGB tiles (public, keyless — SRTM stops
at 60°N and OpenTopography needs a key, both fail Iceland at 63-67°N).
zoom 9 (252 tiles, x220..237 / y126..139), decoded via
elev_m = R*256 + G + B/256 - 32768, stitched (4608x3584 px) and 4x
block-mean downsampled to a 1152x896 vertex grid (fetched by
scripts/fetch_iceland_dem.py).

Mesh: 1,032,192 verts · 2,060,290 tris, shared-vertex heightfield (two
tris/cell, per-vertex normals from the terrain gradient). Equirectangular
projection about the grid centre (matches the OSM bake); normalized to
[-1,1] by horizontal extent, elevation TRUE-SCALE (span 0..0.0067, the
shader applies uExag=10 + Kurvenlineal — no pre-exaggeration). Sea level
(elev <= 0, ~62% of verts) -> y=0, painted as ocean by the shader.
Concepts = grid rows (896, contiguous ranges) so the per-concept
max-diameter clamp stays a thin full-width strip and drops 0 triangles.
Reuses the geo V3 classid (0x0F01_1000) + HHTL tiling the OSM path uses.

Format: baked through bso2::encode_mesh_bso2 — a new additive generic-mesh
encoder mirroring encode_bso2's exact BSO2 ver-6 layout (F16 pos +
Signed360 normals + HXFL trailer). The OSM encode_bso2 path is untouched
(all 12 geo tests still pass, incl. the Signed360 round-trip). New baker
binary geo/src/bin/iceland_dem.rs (required-features = ["helix"]).

The sparse bake cockpit/public/iceland.helix.soa.gz is PRESERVED on disk
(unreferenced); only the manifest key iceland_latest is repointed to the
new cockpit/public/iceland_dem.helix.soa.gz (9.6 MB gzip). BodyHelix.tsx
and main.tsx are untouched.

Verified end-to-end: npm run build clean; a Playwright CDP frame-grab of
/ice (preview server) shows a SOLID Iceland landmass — recognizable island
outline, green coasts -> brown highlands -> white glacier caps, rising out
of the flat blue ocean under the sky dome. Header reads "1,032,192 verts ·
896 structures". Decode was independently replicated (BodyHelix's decode +
clamp) confirming X∈[-1,1], Z∈[-0.78,0.78], unit up-facing normals, and
FrontSide winding.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jEwwaT5JZ5x8qWvcnaMYC
Fixes the reported bug that the Iceland map is categorized as skeleton /
body-parts. BodyHelix is shared by /helix (anatomy) and the geo scenes
(/geo, /ice), and the layer sidebar + toggle buttons rendered the hardcoded
anatomy LAYERS (skin/muscle/organ/skeleton/vessel/nervous/connective/other)
regardless of scene — so the terrain concepts (stamped one layer) showed up
under "skeleton" with the full anatomy button row.

Geo scenes now derive `activeLayers` from the layers the bake actually
stamps, relabelled "terrain" (empty anatomy layers dropped). The layer *id*
is preserved, so the show/hide toggle still filters the real geometry — only
the label + the empty rows change. Anatomy scenes keep `LAYERS` verbatim
(byte-identical). Title/subtitle were already scene-gated; this finishes the
job for the sidebar + buttons.

Verified: `npm run build` (tsc + vite) clean; a pure label swap over the
already-render-confirmed DEM scene (geometry/shader untouched). A fresh
swiftshader frame of the panel wasn't obtainable — the 1M-vert breathing
scene is too heavy for the headless GPU to snapshot — so the label is
verified by build + code, not a new screenshot.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012jEwwaT5JZ5x8qWvcnaMYC
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR replaces the sparse Iceland OSM scatter with a DEM-based terrain mesh. It adds a Python tile-fetch script producing a .demgrid binary, a generalized BSO2 mesh encoder (MeshConcept/encode_mesh_bso2), a new iceland_dem Rust binary that builds and encodes the terrain mesh, and cockpit manifest/UI updates to render the new terrain scene.

Changes

Iceland DEM Terrain Pipeline

Layer / File(s) Summary
DEM tile fetch script
scripts/fetch_iceland_dem.py
Downloads Terrarium elevation tiles concurrently, stitches and block-mean downsamples them, computes latitude bounds, and writes a DEMG binary heightfield.
Generalized BSO2 mesh encoder
geo/src/bso2.rs
Adds MeshConcept and encode_mesh_bso2 to serialize arbitrary triangle meshes into BSO2 ver-6 /helix format, including .blocks sidecar centroid/radius computation.
iceland_dem CLI binary
geo/src/bin/iceland_dem.rs, geo/Cargo.toml
New binary reads .demgrid, projects/normalizes elevation into viewer space, computes normals and a watertight mesh, builds per-row MeshConcepts with HHTL keys, and writes .soa/.blocks via encode_mesh_bso2; Cargo target gated behind the helix feature.
Cockpit manifest and UI wiring
cockpit/public/body.manifest.json, cockpit/src/BodyHelix.tsx
iceland_latest now points to iceland_dem.helix.soa.gz with a note on the retained-but-unused prior asset; BodyHelix derives activeLayers from decoded conceptList in geo scenes, renaming the group to "terrain" with a fixed color and using it for the sidebar and toggle buttons.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant FetchScript as fetch_iceland_dem.py
  participant TerrariumAPI as AWS Terrarium Tiles
  participant IcelandDemBin as iceland_dem binary
  participant Bso2Encoder as encode_mesh_bso2
  participant Cockpit as BodyHelix / manifest

  FetchScript->>TerrariumAPI: fetch elevation tiles
  TerrariumAPI-->>FetchScript: PNG RGB tiles
  FetchScript->>FetchScript: stitch, downsample, write .demgrid
  IcelandDemBin->>FetchScript: read .demgrid
  IcelandDemBin->>IcelandDemBin: project, normalize, compute mesh + normals + concepts
  IcelandDemBin->>Bso2Encoder: encode_mesh_bso2(...)
  Bso2Encoder-->>IcelandDemBin: soa + blocks bytes
  IcelandDemBin->>Cockpit: write iceland_dem.helix.soa.gz asset
  Cockpit->>Cockpit: filter LAYERS by conceptList, render terrain UI
Loading

Possibly related PRs

  • AdaWorldAPI/q2#66: Both PRs modify cockpit/src/BodyHelix.tsx to drive layer/group rendering from decoded conceptList metadata and adjust layer toggle/sidebar behavior.
  • AdaWorldAPI/q2#80: Both PRs change the iceland_latest manifest target used by the scene/manifest asset resolution flow.

Poem

A rabbit dug through pixels deep,
Terrarium tiles for terrain steep,
DEM grids stitched, meshes spun tight,
Iceland now rises in helix light,
Hop, hop, hooray — the mountains take flight! 🐰⛰️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the two main changes: the new Iceland DEM terrain bake and the geo terrain layer UI update.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
geo/src/bso2.rs (1)

429-448: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

No bounds validation on MeshConcept.v_start/v_count — can panic on malformed input.

pos[c.v_start as usize..end.min(nv)] (Line 435) clamps the slice end to nv, but not the start. If a caller ever passes c.v_start > nv (or v_start > v_start + v_count), this slice panics with a "start > end" range error instead of a controlled error. The current iceland_dem caller happens to always produce in-bounds ranges, but this is a generalized public API (doc comment explicitly targets "arbitrary" meshes), so it's worth guarding against misuse by future callers.

🛡️ Proposed guard
     assert_eq!(nrm.len(), nv, "nrm len must match pos");
     assert_eq!(rows.len(), nv, "rows len must match pos");
+    for c in concepts {
+        assert!(
+            (c.v_start as usize) <= nv && (c.v_start + c.v_count) as usize <= nv,
+            "concept vertex range out of bounds"
+        );
+    }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@geo/src/bso2.rs` around lines 429 - 448, The block that computes the
`.blocks` sidecar in `bso2.rs` assumes `MeshConcept.v_start` and `v_count`
always define a valid slice, but `pos[c.v_start as usize..end.min(nv)]` can
still panic when the start is out of bounds or past the clamped end. Update the
loop in this mesh export path to validate or clamp both bounds before slicing,
using the existing `concepts`/`pos` data and the `MeshConcept` fields, so
malformed or future arbitrary inputs fail safely instead of triggering a range
panic.
scripts/fetch_iceland_dem.py (1)

85-89: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant int() casts around math.floor().

math.floor() already returns an int in Python 3; wrapping it in int(...) is a no-op (flagged by Ruff RUF046).

♻️ Proposed cleanup
-    x0 = int(math.floor(lon_to_tilex(LON_W, zoom)))
-    x1 = int(math.floor(lon_to_tilex(LON_E, zoom)))
+    x0 = math.floor(lon_to_tilex(LON_W, zoom))
+    x1 = math.floor(lon_to_tilex(LON_E, zoom))
     # tile-y grows south, so LAT_N (north) -> smaller y.
-    y0 = int(math.floor(lat_to_tiley(LAT_N, zoom)))
-    y1 = int(math.floor(lat_to_tiley(LAT_S, zoom)))
+    y0 = math.floor(lat_to_tiley(LAT_N, zoom))
+    y1 = math.floor(lat_to_tiley(LAT_S, zoom))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/fetch_iceland_dem.py` around lines 85 - 89, The tile index
calculations in fetch_iceland_dem.py use redundant int() wrappers around
math.floor(), which is a no-op in Python 3. Update the x0, x1, y0, and y1
assignments in the tile-bounds setup to use math.floor() directly, keeping the
existing lon_to_tilex() and lat_to_tiley() calls intact and preserving the
current southward y-axis comment.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@geo/src/bin/iceland_dem.rs`:
- Around line 40-51: The header validation in read_demgrid is too short and
allows truncated files to reach the f64_at(24) read path. Update the initial
length check in read_demgrid so it պահանջs enough bytes for the full fixed
header before any u32_at/f64_at access, ensuring files shorter than the needed
header size return the existing error instead of panicking.

In `@scripts/fetch_iceland_dem.py`:
- Around line 96-113: The DEM stitching logic in the tile fetch loop is leaving
failed tiles as zero-valued elevation in `stitched`, which makes missing data
look like valid sea-level terrain. Update the `ThreadPoolExecutor`/`fetch_tile`
processing to track a missing-tile mask or sentinel for each tile, and avoid
writing implicit zeros into `stitched` for absent tiles. Then either fail the
run when gaps remain, or explicitly fill them via interpolation/neighbor-based
recovery before emitting the raster, so downstream `iceland_dem` does not treat
synthetic flat patches as real data.

---

Nitpick comments:
In `@geo/src/bso2.rs`:
- Around line 429-448: The block that computes the `.blocks` sidecar in
`bso2.rs` assumes `MeshConcept.v_start` and `v_count` always define a valid
slice, but `pos[c.v_start as usize..end.min(nv)]` can still panic when the start
is out of bounds or past the clamped end. Update the loop in this mesh export
path to validate or clamp both bounds before slicing, using the existing
`concepts`/`pos` data and the `MeshConcept` fields, so malformed or future
arbitrary inputs fail safely instead of triggering a range panic.

In `@scripts/fetch_iceland_dem.py`:
- Around line 85-89: The tile index calculations in fetch_iceland_dem.py use
redundant int() wrappers around math.floor(), which is a no-op in Python 3.
Update the x0, x1, y0, and y1 assignments in the tile-bounds setup to use
math.floor() directly, keeping the existing lon_to_tilex() and lat_to_tiley()
calls intact and preserving the current southward y-axis comment.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 12a8910c-6675-4e07-8557-6cb6899a0ab0

📥 Commits

Reviewing files that changed from the base of the PR and between f58df77 and 79f8dce.

⛔ Files ignored due to path filters (1)
  • cockpit/public/iceland_dem.helix.soa.gz is excluded by !**/*.gz
📒 Files selected for processing (6)
  • cockpit/public/body.manifest.json
  • cockpit/src/BodyHelix.tsx
  • geo/Cargo.toml
  • geo/src/bin/iceland_dem.rs
  • geo/src/bso2.rs
  • scripts/fetch_iceland_dem.py

Comment on lines +40 to +51
fn read_demgrid(path: &str) -> Result<Dem, Box<dyn std::error::Error>> {
let b = std::fs::read(path)?;
if b.len() < 24 || &b[0..4] != b"DEMG" {
return Err("not a DEMG file".into());
}
let u32_at = |o: usize| u32::from_le_bytes(b[o..o + 4].try_into().unwrap());
let f64_at = |o: usize| f64::from_le_bytes(b[o..o + 8].try_into().unwrap());
let ver = u32_at(4);
if ver != 1 {
return Err(format!("unsupported DEMG version {ver}").into());
}
let w = u32_at(8) as usize;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Header length check is insufficient — reads past the validated bound.

b.len() < 24 only guarantees 24 bytes, but the header actually needs 32 bytes before east is read at Line 54 (f64_at(24) reads b[24..32]). A file truncated to between 24 and 32 bytes will panic on an out-of-range slice instead of hitting the intended "not a DEMG file" error path.

🐛 Proposed fix
-    if b.len() < 24 || &b[0..4] != b"DEMG" {
+    if b.len() < 32 || &b[0..4] != b"DEMG" {
         return Err("not a DEMG file".into());
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
fn read_demgrid(path: &str) -> Result<Dem, Box<dyn std::error::Error>> {
let b = std::fs::read(path)?;
if b.len() < 24 || &b[0..4] != b"DEMG" {
return Err("not a DEMG file".into());
}
let u32_at = |o: usize| u32::from_le_bytes(b[o..o + 4].try_into().unwrap());
let f64_at = |o: usize| f64::from_le_bytes(b[o..o + 8].try_into().unwrap());
let ver = u32_at(4);
if ver != 1 {
return Err(format!("unsupported DEMG version {ver}").into());
}
let w = u32_at(8) as usize;
fn read_demgrid(path: &str) -> Result<Dem, Box<dyn std::error::Error>> {
let b = std::fs::read(path)?;
if b.len() < 32 || &b[0..4] != b"DEMG" {
return Err("not a DEMG file".into());
}
let u32_at = |o: usize| u32::from_le_bytes(b[o..o + 4].try_into().unwrap());
let f64_at = |o: usize| f64::from_le_bytes(b[o..o + 8].try_into().unwrap());
let ver = u32_at(4);
if ver != 1 {
return Err(format!("unsupported DEMG version {ver}").into());
}
let w = u32_at(8) as usize;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@geo/src/bin/iceland_dem.rs` around lines 40 - 51, The header validation in
read_demgrid is too short and allows truncated files to reach the f64_at(24)
read path. Update the initial length check in read_demgrid so it պահանջs enough
bytes for the full fixed header before any u32_at/f64_at access, ensuring files
shorter than the needed header size return the existing error instead of
panicking.

Comment on lines +96 to +113
stitched = np.zeros((Htiles * TILE, Wtiles * TILE), dtype=np.float32)

jobs = [(zoom, x, y) for y in ys for x in xs]
got, missing = 0, 0
with ThreadPoolExecutor(max_workers=16) as ex:
for x, y, rgb in ex.map(lambda t: fetch_tile(*t), jobs):
gx = x - x0
gy = y - y0
if rgb is None:
missing += 1
continue
elev = rgb[:, :, 0] * 256.0 + rgb[:, :, 1] + rgb[:, :, 2] / 256.0 - 32768.0
stitched[gy * TILE:(gy + 1) * TILE, gx * TILE:(gx + 1) * TILE] = elev
got += 1
print(f"fetched {got} tiles, {missing} missing", file=sys.stderr)
if missing > len(jobs) // 10:
print("too many missing tiles — aborting", file=sys.stderr)
sys.exit(1)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Missing tiles silently become flat sea-level, not flagged in output.

stitched is zero-initialized (Line 96), and any tile that fails all retries is simply skipped (Line 104-106), leaving that region at elevation 0. Up to 10% of tiles are tolerated as missing (Line 111-113) with no interpolation, masking, or record of which cells are synthetic. This can silently inject visible flat/sea patches into the baked terrain that the downstream iceland_dem Rust baker and viewer will render as if they were real data — undermining the goal of this PR (replacing a sparse scatter with a "real" DEM).

Consider tracking a missing-tile mask and either failing the run, retrying more aggressively, or interpolating from neighboring valid tiles instead of defaulting to 0.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/fetch_iceland_dem.py` around lines 96 - 113, The DEM stitching logic
in the tile fetch loop is leaving failed tiles as zero-valued elevation in
`stitched`, which makes missing data look like valid sea-level terrain. Update
the `ThreadPoolExecutor`/`fetch_tile` processing to track a missing-tile mask or
sentinel for each tile, and avoid writing implicit zeros into `stitched` for
absent tiles. Then either fail the run when gaps remain, or explicitly fill them
via interpolation/neighbor-based recovery before emitting the raster, so
downstream `iceland_dem` does not treat synthetic flat patches as real data.

@AdaWorldAPI AdaWorldAPI merged commit 12d0742 into main Jul 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants