Skip to content

An unwalked, tapped wall still gets a spot (here inside the house) with wall backing and cable route passing #76

Open

Description

@AidenJohnston

Run 3's wall was never walked: the line came from the meter tap, both walks were refused, both ends are unexplored and nothing was marked. The server still returned a spot 4 ft 7 in left of the meter, about 1.9 m behind the real house wall, which is inside the house. "Flush against one straight wall", "Clear of the meter's working space" and "Cable route along the wall" all passed, and the app offered "See it on your wall".

Seen in the build 4.1 field test on 2026-09-26: TestFlight 4.1, beta at 45017ba, iPhone 14 (no LiDAR), iOS 26.6.2.

  • Run 3 (a real house): the result at 1:46–1:48 in the screen recording.
  • Re-running the solver at 45017ba on the exported scene.json with the public demo rules reproduces it exactly: manual_review, spot −5.90 → −3.32 ft, 3 ft 4 in of cable, 453 candidates (0 pass, 393 unsure, 60 fail).

Report: A41-2055-02.

What happens.

  • The result reads "An installer will take a look / 4 ft 7 in left of your meter, 3 ft of cable". The 3D preview shows the battery beside the meter, with the "See it on your wall" button under it.
  • Pass:
    • "Flush against one straight wall: The whole footprint backs onto one straight, observed wall segment."
    • Clear of the meter's working space (2 ft 1 in, ± about 2 ft).
    • No box or vent above.
    • Open space in front.
    • Cable route along the wall.
    • Cable run length (3 ft 4 in ± 2 ft 0 in).
  • Unsure: ground, gas, AC, driveway, pool, doors and windows, headroom.
  • The wall line came from a bad meter tap (Meter tap on an estimated plane put the wall 1.1 m behind the real wall and 46° off, and nothing corrects it #69). In world terms the spot's centre is 1.8–1.9 m behind the house wall planes ARKit detected. Every "pass" above follows from the imaginary line.
  • The scene alone was enough to tell this scan can't support a spot:
    • walls[0].source is tap;
    • ends.left.kind and ends.right.kind are both unexplored;
    • there are no ground entries and no objects;
    • capture lasted 98 s;
    • the 14.9 ft "wall" (13 ft 2 in left to 1 ft 9 in right) exists only because 7 rapid "Can't get there" taps (1:34–1:36.5) set its ends and skipped its tasks.

Cause.

  • check_backing passes whenever scene.missing("wall", …) is empty, that is, whenever the app reports the wall as observed. It doesn't look at how the wall line was found or whether it was walked (solver.py#L320-L345). The cable route check works the same way (solver.py#L775-L800).
  • source: tap only picks a default error for the wall (scene.py#L608-L614). Nothing treats an unconfirmed tapped wall as a reason not to place.
  • solve returns the best unsure candidate as the spot whenever there is one; unexplored ends only add a reason (solver.py#L1341-L1440).
  • The app shows "See it on your wall" whenever result.spot is set (ResultScreen.swift#L37-L47).

Fix direction.

  • Server: when the wall line is tap-sourced and no walk confirms it (both ends unexplored with next to nothing walked along it), don't return a spot. Return an incomplete result with a reason such as "not enough scan: walk the wall". At the very least, wall backing and the cable route should be unsure, not pass.
  • App: when both walks were refused, don't offer the AR view or a 3D spot. Say "We couldn't measure the wall. Try again in daylight" instead.
  • App: send the meter tap's disagreement with the detected planes (Meter tap on an estimated plane put the wall 1.1 m behind the real wall and 46° off, and nothing corrects it #69) so the server can act on it.

Related.

Screen recordings are in the comment below.

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    size:M30-99 effective changed lines.
    on Sep 27, 2026
  2. AidenJohnston commented on Sep 27, 2026

    @AidenJohnston
    CollaboratorAuthor

    Screen recordings from the build 4.1 field test (TestFlight 4.1, iPhone 14 without LiDAR). Click a link to play.

    Times are in each run's recording. Full analyses: PR #60.

  3. AidenJohnston commented on Sep 27, 2026

    @AidenJohnston
    CollaboratorAuthor

    Proposal: what the scan tells the server when the wall was never walked (#76)

    Question. When neither side of the wall was walked (both walks refused), the wall line comes only from the meter tap. If that tap was wrong, the solver still reports wall backing and the cable route as passing and returns a spot. How should the scan tell the server, and what should the homeowner see?

    Still reproduces on current code. A synthetic scene shaped like run 3 (one tap-sourced wall, both ends unexplored, the wall band observed over the tapped line, no ground, objects, facing or overheads) run through solve on t3/server (6c7ca23) with the public rules returns manual_review with a spot and a route. wall_backing, meter_working_space, wall_equipment_above, route_path and route_length pass; the rest are unsure (unobserved). check_backing only asks whether the wall band was observed, and solve returns the best unsure candidate whatever the ends say.

    Why today's data can't tell. "Can't get there" during a walk or mark-end step (cannotAccessArea → endWalkCannotGoOn on t3/ios-mvf) writes a plain unexplored end, the same as an end that turns a corner. A tap-sourced wall is normal for every meter tapped on an estimated plane. So neither the end kinds nor the wall's source mark this scan as unconfirmed. On the app side, "See it on your wall" shows whenever result.spot is set (ResultScreen).

    Options

    • (a) App only. Record per side whether the walk was refused. When both were, show "We couldn't measure your wall. Try again in daylight" with no spot and no "See it on your wall". No contract change, but the server is unchanged, so any other client still gets a spot.
    • (b) Contract. Add an optional coverage.ends.<side>.walked boolean to scene.schema.json (and the vendored copy in HouseScanKit's tests; $defs/end has additionalProperties: false, so both need the change). When the meter's wall has no walked end, the server returns spot: null with a new reason code (for example wall_not_walked, added to result.schema.json), or at least marks wall backing and the cable path UNSURE as unobserved. Needs agreement on the field and the reason.
    • (c) Both. Ship (a) first because it is app-only, then (b).

    Recommendation: (c). Pair it with the meter-tap sanity check for #69, which removes the usual trigger; this issue is the defence in depth.

    What unblocks it: agreement on the scene.json field (name, and whether it means "walked" or "refused" per end), the new reason code and its homeowner copy, and whether an unconfirmed wall should withhold the spot or only make the two checks unsure.

    🤖 Generated with Claude Code

  4. AidenJohnston commented on Sep 27, 2026

    @AidenJohnston
    CollaboratorAuthor

    Team decision: option (a) now, (b) after the deadline, in PR #135

  5. AidenJohnston commented on Sep 27, 2026

    @AidenJohnston
    CollaboratorAuthor

    Scope of the app guard in #135 (option (a)): it hides the spot only when "Can't get there" ended both walks near the meter, with every kept view and both ends within 2 ft 7 in (0.79 m) of it. It does not catch run 3. Run 3's kept views reached about 6 ft on each side, so both sides count as walked and the spot still shows. Run 3's spot inside the house came from the bad meter tap (#69), which #108's tap sanity check now guards. The server-side part, option (b), stays deferred until after the deadline.

    🤖 Generated with Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.size:M30-99 effective changed lines.

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions